Repository navigation
Generate writes cases the way school debaters prepare them - #244
Conversation
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Warning Review limit reachedEnable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. Next included review available in 9 minutes. View limit details
|
| Layer / File(s) | Summary |
|---|---|
Case schema and normalization packages/core/src/ai/schemas/generate.ts, packages/core/src/ai/case-view.ts, src/test/helpers/cases.ts, src/test/lib/case-view.test.ts |
The generation schema adds fields and types for openings, reinforcement, counters, and sources. readCase maps current and legacy output into a normalized view, and source helpers format and merge sources. |
Role-specific generation and validation supabase/functions/_shared/prompts/*, supabase/functions/_shared/control-enforcement.ts, supabase/functions/ai/features/generate.ts, src/lib/ai/features/generate.ts, e2e/full-stack/fake-openrouter.mjs, e2e/fixtures/ai-responses.ts, supabase/functions/ai/*test.ts, supabase/functions/_shared/*test.ts, .claude/skills/verify-debatelab/recipes/case-generation.spec.ts |
Prompts and controls define role-specific output. R2 uses reinforcement and counters, while the Conclusor uses reasons to win. Source validation filters URLs against known sources. Response transformation and tests cover the role-specific shapes. |
Case display and regeneration src/components/features/generate/GenerateResults.tsx, src/components/features/tools/*, src/pages/GeneratePage.tsx, packages/core/src/crossfire/prefill.ts, src/components/features/sparring/SparringRound.tsx, src/locales/*, .claude/skills/verify-debatelab/*, agentic/case-generation.e2e.ts, e2e/sparring.spec.ts |
Case display and live-draft sections use the normalized case fields. Regeneration maps selections to the updated sections and merges sources. Crossfire, discussion, sparring guidance, translations, and UI checks reflect the revised content and labels. |
Exports and case flowcharts src/lib/export-utils.ts, src/lib/pdf-export-utils.ts, supabase/functions/export-gdoc/index.ts, src/lib/flowchart.ts, src/test/lib/case-exports.test.ts, supabase/functions/export-gdoc/generate_test.ts, src/test/lib/flowchart.test.ts |
DOCX, PDF, and Google Docs exports render available case sections and sources, including legacy content where present. Flowcharts use arguments, reinforcement, or win reasons and map opponent claims to responses. |
Estimated code review effort: 4 (Complex) | ~45 minutes
Sequence Diagram(s)
sequenceDiagram
participant User
participant PromptBuilder as buildGenerateUserPrompt
participant Model as Generation model
participant Generate as handleGenerate
participant Controls as enforceGenerateControls
participant Sources as enforceGenerateSources
participant Results as GenerateResults
User->>PromptBuilder: request role-specific case
PromptBuilder->>Model: generation prompt
Model->>Generate: generated case output
Generate->>Controls: enforce role-specific sections
Controls->>Sources: validate sources against known URLs
Sources->>Results: normalized generation result
- Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts
Note
🎁 Summarized by CodeRabbit Free
-
Your organization is on the Free plan. CodeRabbit will generate a high-level summary and a walkthrough for each pull request. For a comprehensive line-by-line review, please upgrade your subscription to CodeRabbit Essentials by visiting https://app.coderabbit.ai/settings/billing.
Comment @coderabbitai help to get the list of available commands.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
R2 now follows Adam's own R2 speech (Debate print 1, 2025-03-26): who is speaking, about 2 minutes backing up the team's earlier arguments (reinforce), then the bulk in "If they say…" answers, and a closing line. Length sets R2's answer count (5/6/8) instead of an argument count. The prompt, case labels and exports no longer use framework, burden of proof, weighing, warrant, impact, thesis or counterpoint. Old saved cases keep those sections under plain names. Sparring's school-role guidance and the agentic test context describe the same structure. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… three languages Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The other side usually runs only 2-3 arguments, so R2's "If they say…" holds one full answer per likely argument (about 90-120 words at standard length), built the way Adam writes his own refutations in Debate print 1: a direct reply, a fact with its source, what it means, a tie back to our argument, and a closing question or firm line. He underlines the ones the other side used and builds on them in the round. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Adam asked for more "If they say…" blocks, each with more content, like his own debates. R2 now writes 6 blocks at standard length (5 brief): their main arguments, the points they use to back them up, and their answers to our case. Each answer pushes back at once, gives at least two specific facts with source and year, says what they mean, asks a question that turns their point around, and ties back to our argument by name. Numbers must come from the attached research and every cited source must be in the sources list. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude Haiku reasoned for 6,000-10,000 tokens on an R2 case at low effort, past the 3,000 that a 15,000 max_tokens left it. One reply was cut off and its retry finished at 128 s of the 130 s budget. Generate now keeps at least 10,000 tokens for reasoning (max_tokens 22,000 at low) while its reply cap stays at 12,000, so every cap still fits its retry. Also keep R2's backing-up paragraphs short beside the longer answers. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Describe the new case format on the public guides The guides still described the old case: thesis, framework, burden of proof, contentions with warrants and impacts, and a predicted opponent case. Generate now writes an opening, arguments (point, explanation, evidence, why it matters), "If they say… we answer…" replies, a closing line and sources (#244). The copy changes in seo_guides.py, seo_answers.py and the PAGES meta in generate_seo_content.py, and the pages and llms.txt are regenerated from them. The LD, PF, Policy and weighing format guides are unchanged. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> * Match the case guide to the shipped R2: no new arguments, five or six If they say blocks --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Restructures the cases Generate writes to match how Adam prepares his own school cases. It follows sections (d) and (e) of the 2026-10-24 case-structure research, Adam's 2026-10-27 decisions, and the 2026-10-28 R2 spec where they differ. No new features and no database migration: cases are JSON, and old saved cases still load and render.
What a case looks like now
The role shapes the speech:
R2, matched to Adam's own R2 documents
I matched R2 against "Debate print 1" (
Debate print 1_merged_removed.pdf). It holds the R2 speech Adam gave for the side arguing schools are not safe, which he emailed to his teacher on 2025-03-26 under the subject "Printing For Adam". The PDF also holds his refutation prep, his argument paragraph, the sources list and his flashcards. It is the only R2 material among his documents: the scratch folder holds the research notes, not other speeches.What the document contains:
How R2 now works:
contentionsis always empty for R2, and R2 has no argument count anywhere.reinforce): unchanged from the previous round. Short blocks return to the Introductor's and R1's arguments by name ("Our second argument was about…"), each with a fact and its source; the prompt asks for 100-120 words each.Measured on live Claude Haiku 5.5 runs, standard length, same motion as the earlier sample ("This House would make public transport free at the point of use"):
~/.t3/scratch/case-v2-shots/r2-case.json):Token budget for the longer R2
max_tokensleft it.aifunction's 130 s budget.REASONING_FLOOR_TOKENSin_shared/output-caps.ts):max_tokensis 22,000 at low effort and 34,000 on a cut-off retry. Its reply cap stays at 12,000, so the existing rule that every cap fits its retry still holds; a 20,000 cap would break it at high effort.callAI. Other features are unchanged.export-gdocsize cap.No jargon in the prompt, labels or exports
whyItMatters, and the server files it under the existingimpactkey, so stored cases keep their shape.export-gdoc, PDF, DOCX) have no Thesis, Framework, Burden of Proof, Predicted Opponent Case or Counterpoint labels, and no "No framework provided." or "No burden of proof provided." placeholders. The unused translation keys are removed in EN, HU and ES.predictedOpponentCase.Schema (
packages/core/src/ai/schemas/generate.ts)The storage keys stay as they were. The labels change on screen and in exports.
null:opening { hook, definition }contentions[].titlecounters[].sourcereinforce[] { argument, text }(R2)whyWeWin[](Conclusor)closingLinesources[] { org, year, claim, url }caseStructure.framework,keyDefinitionsandburdenOfProofpredictedOpponentCaseand its three listscounters[].rebuttalcaseStructure.thesisis the opening's "we will show…" line (for R2, "I'm the R2 of my team…").packages/core/src/ai/case-view.ts(readCase) reads old and new cases into the same sections, and every reader uses it:export-gdockeeps a small mirror, because it runs in Deno.Server rules
enforceGenerateControlsis role-aware:reinforceblock or with fewer than 4 answers. It keeps at most 3 reinforce blocks, cuts the answers at 5 (brief) or 6, and emptiescontentions.whyWeWinitems.opening.definition.enforceGenerateSourceskeeps a source's link only when the research or the student's Library supplied that URL.readCasealso links only http(s) URLs.Also in this PR
SparringRound.tsx,prompts/sparring.tsand thesparring.roleGuidancestrings in EN, HU and ES) describes the same four jobs. The Introductor no longer "sets the framework", and R2 brings no new arguments.e2e.config.tsdescribes the new case shape. This changes the agentic agent's context, so the next agentic run re-records its replay cache; I didn't run it.origin/mainwith a normal merge (no rebase, no force-push). The conflicts were the sentence-case relabels inen.jsonand the verify-skill docs and recipes. I kept the new section names, main's sentence case and main's "Daily AI uses used up" wording. Main didn't change GenerateResults.tsx, live-sections.ts or the other case readers, so the restyle, tab bar, motion and DebateOwl rename merged cleanly. The case cards keep main'smotion-list-itemand owl UI.Staging deploy for the Google Docs export (approved by Adam: staging only)
export-gdocalone to staging (brifeyypjauyusmkptkx) from commit a0c16ae, after its local tests passed (10 of 10). Staging went from version 20 (sha8852d4e1) to version 21 (sha6302cb22). No other function was deployed, and production was not touched.export-gdochasn't changed since a0c16ae, so v21 is the final export code.invalid_grant, and Adam asked us not to use his browser session, so we skipped it for now. The content builder is covered bysupabase/functions/export-gdoc/generate_test.ts(new, old and R2 cases; no removed labels).Deploy order (when this merges)
aiandexport-gdocEdge Functions to production. In the other order, the current client sends new-shape output down its old repair path, which makes up a "General framework" and drops the new sections.Verification
GitHub Actions is billing-blocked, so all of these are local runs. A local pass is not a CI pass.
npm run verifyat 08db62f passed, exit 0:@smokePlaywright: 47 of 47verify:fullwas not run.verify-debatelab, fake provider, desktop-chromium and mobile-chromium:recipes/case-generation: 20 of 20 at 7cdc2e8, includinggen-roleswith 6 R2 blocks. The later commit changed only the prompt wording and the token room, neither of which the fake provider reads.recipes/live-generation: 6 of 6 andrecipes/current-debate: 6 of 6 at 747729f.e2e/sparring.spec.ts: 6 of 6.verify-debatelab --live(Claude Haiku 5.5 and real Exa), desktop:gen-rolespassed at 08db62f. Every generate call usedmax_tokens22,000 and finished on the first try, with R2 in 36 s.aifunction, and onlyexport-gdocwas approved for a staging deploy.~/.t3/scratch/case-v2-shots/r2-390.png,r2-1440.pngandr2-case.json(English)r2-hu-390.png(Hungarian)introductor-andconclusor-390/1440.png, from 2026-10-28 09:45; their prompt sections haven't changed since.e2e.config.tscontext change means its replay cache re-records on the next run)🤖 Generated with Claude Code