From d4ebd637fb6c0880d2230fbf83475c8e1caba38a Mon Sep 17 00:00:00 2001 From: PatrikBak Date: Sat, 16 May 2026 03:56:10 +0200 Subject: [PATCH] Split handout-editor skill; add fan-out to typos pass Split the single handout-editor skill into four focused skills: editor (single-file edits), figure (.asy work), propagate (sync edits across language variants), and translate (full end-to-end CS/SK/EN translation). Editor's prose section now covers author-voice mirroring and \Image placement explicitly. Typos skill gains diff-mode scoping, per-section fan-out for multi-problem handouts, and an interactive AskUserQuestion pass for items it flagged as Uncertain. --- .claude/skills/handout-editor/SKILL.md | 21 ++------- .claude/skills/handout-figure/SKILL.md | 53 +++++++++++++++++++++++ .claude/skills/handout-propagate/SKILL.md | 22 ++++++++++ .claude/skills/handout-translate/SKILL.md | 26 +++++++++++ .claude/skills/handout-typos/SKILL.md | 31 ++++++------- 5 files changed, 119 insertions(+), 34 deletions(-) create mode 100644 .claude/skills/handout-figure/SKILL.md create mode 100644 .claude/skills/handout-propagate/SKILL.md create mode 100644 .claude/skills/handout-translate/SKILL.md diff --git a/.claude/skills/handout-editor/SKILL.md b/.claude/skills/handout-editor/SKILL.md index b3047a03..8d44dfb0 100644 --- a/.claude/skills/handout-editor/SKILL.md +++ b/.claude/skills/handout-editor/SKILL.md @@ -1,6 +1,6 @@ --- name: handout-editor -description: Use this skill when working on olympiad math handouts — filling solutions, translating (CS/SK/EN), reformatting, or adding problems. Operates on the PlainTeX+AMS-TeX+OPmac stack used by this project. +description: Use this skill when editing one olympiad math handout file — filling solutions, reformatting/transcribing, adding problems, or polishing prose. Operates on the PlainTeX+AMS-TeX+OPmac stack used by this project. Do NOT use for full-handout translation between CS/SK/EN (use `handout-translate`) or for applying a change across multiple language variants (use `handout-propagate`). --- # Handout Editor @@ -13,7 +13,7 @@ You are a professional olympiad math writer, editor, and translator. Help curate ## Workflow -1. If the user hasn't specified what to do, ask. Common modes: fill solutions, translate, reformat/transcribe, add new problems. +1. If the user hasn't specified what to do, ask. Common modes: fill solutions, reformat/transcribe, add new problems. 2. Read the relevant `.tex` file(s) with the Read tool if working on an existing file. If the user pastes content inline, work from that directly. 3. Make the requested changes. 4. After every edit, compile and verify. If compilation fails with exit code ≠ 0, fix the error and recompile. @@ -41,8 +41,6 @@ Exit code 0 = success. Ignore all warnings — do not investigate, fix, or menti **`\Problem` stars argument** must be a non-negative integer (`0`, `1`, `2`, …). Never leave it empty (`{}`). Use `{0}` when the difficulty is unspecified. -**Modify only the target argument** (solution / proof / translation). Leave all other arguments exactly as they are unless the user explicitly asks to change them. Never rewrite, rephrase, or "improve" the user's existing prose — statements, intro text, footnotes, comments — unless explicitly asked. - When the user asks to **reformat or transcribe** (e.g. "convert this old format", "add these problems"), copy content faithfully — do not invent, improve, or fill in solutions. Leave solution arguments as `{}` if no solution is provided. ### Canonical `\Problem` example @@ -80,25 +78,14 @@ A problem with no hint and no solution looks like `\Problem{0}{}{Statement.}{}`. ## Prose style +- **Mirror the author's style strictly.** Before writing, read existing solutions/exercises in the same file. Match the author's voice — sentence length, level of formality, how explicitly steps are spelled out, idiomatic word choices and short phrases. Your additions should be indistinguishable from the existing content. Do not inflate with synonyms or impose your own voice. - **Self-contained.** Solutions must stand alone — do not rely on hints. Pull in any essential fact briefly. - **Elegant and elementary.** Prefer the prettiest elementary route that aligns with the provided hints. Never contradict or bypass them. - **Calibrate to a strong school student starting olympiads.** Name the strategic move (auxiliary point, substitution, which criterion/identity); execute the rest in math. Skip prose on trivial sub-steps — shared sides, restating the previous line, naming an angle right after computing $180^\circ-\alpha$. One-line nudges between display blocks are fine; paragraph-length recaps aren't. -- **Copy phrasing habits.** Mirror the short idioms already in the file. Do not inflate with synonyms. +- **`\Image` placement.** In multi-paragraph solutions/proofs, place `\Image{...}` between paragraphs — not as the opening line and not as the closing line. Drop it right after the paragraph that constructs/names what the figure shows. Single-paragraph solutions are exempt. ## Language-specific phrasing - **American English** (when `\setlanguage{EN}`). Use American spellings throughout: -ize not -ise, -or not -our, -er not -re (center/incenter/excenter/orthocenter/circumcenter, not centre/incentre/…), practice (verb and noun). - **EN angle notation:** Write `$\angle XYZ$`, never `$|\angle XYZ|$`. The absolute-value bars around angles are CS/SK convention only. - **EN length notation:** Write `$AB$`, never `$|AB|$`. The absolute-value bars around segment lengths are CS/SK convention only. When removing `|...|` from a length that follows a TeX control sequence (e.g. `\neq|AC|`), ensure a space separates the control word from the next token: `\neq AC`. -- **Match the file's `\setlanguage{CS|SK|EN}` declaration.** Mirror labels (Cvičení/Cvičenie/Exercise, Řešení/Riešenie/Solution, etc.) exactly as in existing files. -- **Symmetry / analogy idioms:** CS "Analogicky", SK "Zo symetrie", EN "By symmetry" — use directly where applicable. - ---- - -## Translation rules - -When translating CS ↔ SK ↔ EN: -- Translate **all prose** (statements, solutions, section headings, footnotes, intro text). -- Keep all math, macro names, and structure identical. -- Set the correct `\setlanguage{...}` and `\MathcompsLink{...}` slug. -- Match the target language's label conventions already used in existing handouts. diff --git a/.claude/skills/handout-figure/SKILL.md b/.claude/skills/handout-figure/SKILL.md new file mode 100644 index 00000000..5e290033 --- /dev/null +++ b/.claude/skills/handout-figure/SKILL.md @@ -0,0 +1,53 @@ +--- +name: handout-figure +description: Use this skill when editing or adding handout figures — Asymptote `.asy` files in `data/handouts/Images/`. Adding/modifying geometry, angle marks, fills, colors, labels, then re-rendering to PDF + SVG. Trigger phrases: "add a 60° angle to that figure", "change the color in the figure", "redraw", "fix the figure", "make X visible", anything touching a `.asy` under handouts. Do NOT use for editing the `.tex` that embeds the figure — that's `handout-editor`. +--- + +# Handout Figure Editor + +You edit Asymptote figures in `data/handouts/Images/`. Source is `.asy`; both `.pdf` (handout PDF) and `.svg` (website) are committed and must stay in sync with the source. + +## Scope + +- Edit `.asy` files in `data/handouts/Images/`. +- Re-render every modified figure via `_Export-Asy.ps1` — never raw `asy.exe`. +- Do not touch the `.tex` that embeds the figure — that's `handout-editor`. + +## Workflow + +1. **Identify the figure.** The user may name the slug (e.g. `angles-pentagon`) or paste a `\Image{...}` line. The file is `data/handouts/Images/.asy`. +2. **Read `_common.asy`** if you don't recall its primitives — `Draw`, `Circle`, `AngleMark`, `RightAngleMark`, `LabeledDot`, `EdgeLabel`, `ParallelMark`, `EquilateralTriangle`, `Midpoint`, `Foot`, `ReflectAcross`, `Polar`, `ExtendPast`. +3. **Check for a shared module.** If `-shared.asy` exists, the figure is part of a statement/solution pair: geometry and base layers live in shared; individual files call `BaseFills() / BaseEdges() / BaseDots()` and add only their own marks. +4. **Edit.** Strict draw order: **fills (incl. AngleMark sectors) → edges → dots → standalone labels.** +5. **Re-render** from `data/handouts/Images/`: + ``` + pwsh -NoProfile -File ./_Export-Asy.ps1 .asy + ``` + Produces deterministic-metadata PDF and Inkscape-converted SVG. Both get committed. +6. **Report** one sentence — what changed in the figure. + +## Palette and styling + +- **6 hue families × 3 shades** in `_common.asy`: `LightBlue/Blue/DarkBlue`, `LightRed/Red/DarkRed`, `LightGreen/Green/DarkGreen`, `LightPurple/Purple/DarkPurple`, `LightPink/Pink/DarkPink`, `LightYellow/Yellow/DarkYellow`. Always pick a named pen — never inline `rgb(...)`. +- **`AngleMark` / `RightAngleMark` take a `Light*` pen** — they fill a sector with no edge stroke, so a saturated pen reads heavy. For `labelPen` use a Normal/Dark pen or a `Font*` tier (e.g. `labelPen = Red`, `labelPen = Font2`). +- **Line widths**: three tiers only — `ThinWidth = 0.5`, `NormalWidth = 1.0`, `ThickWidth = 1.5`. `Draw`/`Circle`/`vertexPen` apply these automatically. +- **Font tiers**: `Font1..Font5` (8 / 10 / 13 / 16 / 20 pt). `Font3` is the default. Pass via `labelPen` for narrow sectors or dense figures. +- **Opacity is forbidden** except for genuinely overlapping translucent fills (two filled regions where the overlap should read deeper). For non-overlapping fills, pick a different `Light*` shade instead. + +## Comments in figure files + +- **Minimal.** Only math/geometry-derivation comments. No file headers, no section dividers, no inline narration of `Draw` / `LabeledDot` calls. `_common.asy` itself is exempt — its helpers carry full doc blocks. +- **For new helpers** (in `_common.asy` or `-shared.asy`): each parameter on its own line, framed `//` docstring above the function, verb-first prose, matching the style already in the file. + +## Gotchas + +- **Asymptote strings**: only `\"` is escaped. Write `"\alpha"` (one backslash) for LaTeX — `"\\alpha"` renders a newline followed by `alpha`. +- **`include "-shared.asy";`** must be quoted — hyphens are illegal in bare identifiers. `import _common;` works because `_common` is a valid identifier. +- **Don't name point variables `N`, `S`, `E`, `W`, `NE`, …** — those shadow asy's compass constants, breaking `LabeledDot(P, "P", N)`. If you need a point at those positions, give it a different name and pass `(0,1)` etc. as alignment. +- **Figure pairs** that share geometry → extract to `-shared.asy` (no `_` prefix — that's reserved for handout-wide modules like `_common`; `-shared` suffix sorts next to its siblings). Split into `BaseFills()`, `BaseEdges()`, `BaseDots()` so each figure layers its own marks in the right order. + +## Rules + +- **Never call `asy.exe` directly for committed changes** — `_Export-Asy.ps1` is the canonical pipeline (deterministic PDF metadata + Inkscape SVG matching the rest of the project). +- **Never inline `rgb(...)`, `fontsize(...)`, ad-hoc widths, or stray `opacity(...)`** — extend the palette in `_common.asy` if a missing shade is genuinely needed (the user OK'd `LightYellow` etc. this way), but don't sprinkle one-offs. +- **Never edit `-shared.asy` to change a single figure's marks** — only geometry and `Base*` layers belong there. diff --git a/.claude/skills/handout-propagate/SKILL.md b/.claude/skills/handout-propagate/SKILL.md new file mode 100644 index 00000000..6efed6c4 --- /dev/null +++ b/.claude/skills/handout-propagate/SKILL.md @@ -0,0 +1,22 @@ +--- +name: handout-propagate +description: Use this skill when applying a localized change made in one handout language variant to its other-language variants — keeping CS/SK/EN versions in sync after an edit. Trigger phrases: "apply these changes to other languages", "propagate this to SK", "sync the EN version", "update the other languages". Do NOT use for full-handout end-to-end translation when no target file exists — that's `handout-translate`. Do NOT use for editing one file with no propagation — that's `handout-editor`. +--- + +# Handout Propagator + +You apply a localized change made in one language variant of a handout (CS ↔ SK ↔ EN) to its other-language variants so all stay in sync. All **Macro reference**, **TeX / format rules**, **Prose style**, and **Language-specific phrasing** rules from the `handout-editor` skill apply. + +## Scope + +- The source variant and at least one target variant already exist as `..tex` siblings in `data/handouts/`. +- The change is a *delta*: a fix, rewrite, re-phrasing, new `\Problem` block, or section reorder — anything short of a from-scratch translation. +- Translate only the changed prose; leave untouched passages alone. Match each target file's existing voice. + +## Workflow + +1. **Identify the change.** Pin down what changed on the source side via `git diff`, the user's pointer ("the solution to problem 3"), or recent in-session edits. List each changed passage as a discrete item. +2. **Identify the targets.** List the other-language variants that exist (`..tex` siblings of the source). +3. **For each target file, for each changed item:** locate the parallel passage (by problem number, exercise number, or section heading), translate the delta applying that language's conventions (CS/SK `|\angle XYZ|` / `|AB|` vs EN bare `\angle XYZ` / `AB`, American spellings for EN, etc.), apply with `Edit`. For substantial additions (a whole new `\Problem` block, a multi-paragraph proof rewrite), follow the `handout-translate` glossary-aware pattern. +4. **Compile each modified target.** From `data/handouts/`: `pdfcsplain -interaction=nonstopmode -halt-on-error ""`. Fix and recompile on error. +5. **Report** one sentence per target file (e.g. "Propagated 2 fixes to .sk and .en."). diff --git a/.claude/skills/handout-translate/SKILL.md b/.claude/skills/handout-translate/SKILL.md new file mode 100644 index 00000000..d33b2d17 --- /dev/null +++ b/.claude/skills/handout-translate/SKILL.md @@ -0,0 +1,26 @@ +--- +name: handout-translate +description: Use this skill when translating an olympiad math handout end-to-end between CS / SK / EN — producing a NEW target-language file from a finished source. Trigger phrases: "translate this handout to SK", "preložte do češtiny", "translate the EN version". Operates on the PlainTeX+AMS-TeX+OPmac stack. Do NOT use for editing one file (use `handout-editor`) or for syncing a small change across already-existing language variants (use `handout-propagate`). +--- + +# Handout Translator + +You translate a finished olympiad math handout from one language to another (CS ↔ SK ↔ EN). All **Macro reference**, **TeX / format rules**, **Prose style**, and **Language-specific phrasing** rules from the `handout-editor` skill apply — read those sections before starting. This skill adds only the translation-specific workflow. + +## Scope + +- One source `.tex` file → one target `.tex` file in `data/handouts/`. Keep the source filename stem; change only the language suffix (e.g., `factorization.en.tex` → `factorization.sk.tex`). +- Translate **all prose**: statements, solutions, section headings, footnotes, intro text. +- Keep all math, macro names, and structure identical. +- Set the correct `\setlanguage{...}` and `\MathcompsLink{...}` slug. +- Match the target language's label conventions used in existing handouts. + +## Workflow + +1. **Identify source, target, and `\MathcompsLink` slug.** Confirm source file and target language with the user if not specified. Then find the handout entry in `web/src/content/handouts.json` (whose `slug.` matches the source's slug) and check `slug.`: if populated, that's the `\MathcompsLink{...}` value to use; if missing, translate the title into the target language, propose a kebab-case slug, and confirm with the user before proceeding. Note that slugs are translated, not transliterated (e.g. `factorization` ↔ `rozklady-na-soucin` ↔ `rozklady-na-sucin`). +2. **Lock terminology inline.** Read the full source. Build a small glossary: recurring technical terms, named-object conventions, signature phrases — and pick the target-language rendering for each now. Note CS/SK `|\angle XYZ|` and `|AB|` conventions vs EN bare `\angle XYZ` / `AB` and American spellings. +3. **Fan out the translation.** Dispatch 3–5 parallel subagents over contiguous, non-overlapping slices of problems/sections. Each agent receives: the glossary, its source slice, and the target-language conventions. Trust your judgment to skip fan-out on trivially small inputs. +4. **Assemble** the merged target file with `\setlanguage{...}` and the right `\MathcompsLink{...}` slug. +5. **Consistency sweep.** Read the merged file top-to-bottom once. Verify each glossary term renders identically across slices, smooth obvious voice/register inconsistencies at slice boundaries, catch any untranslated fragments (forgotten source-language tokens, mismatched conventions). Apply fixes via Edit. +6. **Compile and verify.** From `data/handouts/`: `pdfcsplain -interaction=nonstopmode -halt-on-error ""`. Fix any error and recompile. +7. **Report** in one sentence. diff --git a/.claude/skills/handout-typos/SKILL.md b/.claude/skills/handout-typos/SKILL.md index 1c1018da..cc1f066b 100644 --- a/.claude/skills/handout-typos/SKILL.md +++ b/.claude/skills/handout-typos/SKILL.md @@ -18,6 +18,7 @@ You proofread one olympiad math handout `.tex` file (PlainTeX + AMS-TeX + OPmac) - **Operate on one `.tex` file at a time** in `data/handouts/`. If the user names several, process them one by one. - **Edit prose only.** Math, macro names, commands, labels, URLs, and verbatim content are off-limits. - **Language** is set by `\setlanguage{CS|SK|EN}` in the file (and mirrored in the filename suffix `.cs.tex` / `.sk.tex` / `.en.tex`). Apply CS/SK/EN rules accordingly. +- **Two input shapes.** Default is one whole file. If the user asks to check only recent changes (a diff), identify the changed passages via `git diff` or recent in-session edits — and operate on those passages **plus their surrounding sentence or paragraph**, since agreement, case, and punctuation errors need context to detect. Passes 1–2 run over that scope, not the whole file. --- @@ -26,20 +27,25 @@ You proofread one olympiad math handout `.tex` file (PlainTeX + AMS-TeX + OPmac) 1. **Identify the target file.** If the user hasn't named one, ask. 2. **Read** the file and note the language. 3. **Pass 1 — collect candidates** across prose only. Include only *serious*, *objective* errors: - - Misspellings and missing/wrong diacritics. - - Broken agreement (gender/number/case), clearly wrong verb forms, a missing or doubled word that breaks the sentence. - - Unequivocal punctuation mistakes that change parsing or are clearly wrong (not stylistic comma choices). - - Casing errors: sentence-initial uppercase; proper names capitalized. Don't over-capitalize — in CS/SK, days, months, and language names stay lowercase unless sentence-initial. - - Repeated words (case-insensitive): immediate duplicates separated only by whitespace, `~`, or trivial punctuation (`token token → token`). + - **Misspellings** and missing/wrong diacritics. + - **Broken agreement** (gender/number/case), clearly wrong verb forms, a missing or doubled word that breaks the sentence. + - **Unequivocal punctuation mistakes** that change parsing or are clearly wrong (not stylistic comma choices). + - **Casing errors:** sentence-initial uppercase; proper names capitalized. Don't over-capitalize — in CS/SK, days, months, and language names stay lowercase unless sentence-initial. + - **Repeated words** (case-insensitive): immediate duplicates separated only by whitespace, `~`, or trivial punctuation (`token token → token`). - **Genuinely ungrammatical sentences** — word salad, missing essential particle, mangled construction that no native speaker would produce. Merely awkward, stiff, clunky, or non-idiomatic phrasing does **not** qualify. If a native speaker could read the sentence and say "that's an unusual way to put it, but it's fine," it stays. 4. **Pass 2 — classify each candidate** into one of three buckets: - **Fix directly**: objective mistake (typo, diacritic, agreement error, obvious duplicate word, sentence-initial case) where the correction is unambiguous and cosmetic. - **Uncertain**: proper noun you can't verify, a clearly ungrammatical sentence where the minimal fix is non-obvious, or a spelling/case-ending choice that hinges on meaning you can't infer. Be stingy with this list — if you're about to flag something because it "could be smoother," drop it. - **Leave alone**: author's voice / idiom / rhythm / clunkiness — not a mistake, just not how you'd write it. This is the default; when in doubt, here. 5. **Apply the "fix directly" items with Edit.** One fix per Edit call; include 2–3 words of surrounding context so `old_string` is unique. Use `replace_all` only when the replacement is safe in every occurrence. Batch independent Edit calls in a single message. -6. **Report.** One short sentence summarizing what was fixed (e.g. "Fixed 3 diacritics, 1 repeated word, 1 agreement."), then — only if any exist — a plain bulleted list of **Uncertain** items. For each entry, quote the problematic clause with a short context snippet, then **propose a minimal concrete fix** that repairs the grammar without rewriting the sentence. Keep suggestions minimal — change only what's broken, preserve the author's voice, and explain in a few words *why* it's wrong (e.g. "missing verb", "wrong case ending", "doubled preposition"). If you truly have no idea what the author meant, say so and ask rather than guessing. If nothing is uncertain, say so in a few words. The diff shows the fixes — don't re-list them. +6. **Report and resolve Uncertain.** Start with a one-sentence summary of directly-applied fixes (e.g. "Fixed 3 diacritics, 1 repeated word, 1 agreement."). If nothing is Uncertain, say so in a few words and stop. -Do not compile. Typo fixes in prose cannot break TeX. If the user wants a compile check afterwards, they will ask (or use the `handout` skill). + Otherwise, for each Uncertain item print a short paragraph with: a line-number anchor (e.g. `L296`), the problematic clause with surrounding context, a minimal proposed fix, and a few-word reason (e.g. "missing verb", "wrong case ending", "doubled preposition"). Deduplicate — each distinct item once. + + Then call `AskUserQuestion` (batched up to 4 per call) with options per item: **Apply suggested fix** / **Leave alone**. Apply approved fixes via Edit and emit a final one-liner with what was applied. If you genuinely have no idea what the author meant for an item, leave it out of `AskUserQuestion` and ask in plain text instead. +7. **Fan out by section** for multi-problem handouts. Dispatch 3–5 parallel subagents to run **passes 1–2** (steps 3–4) over contiguous, non-overlapping slices. Each subagent returns its **Fix directly** and **Uncertain** lists as text — it does not call Edit. The main session then applies all fixes (step 5) and produces the merged report (step 6). Trust your judgment to skip fan-out on trivially small inputs. + +Do not compile. Typo fixes in prose cannot break TeX. If the user wants a compile check afterwards, they will ask. --- @@ -89,13 +95,4 @@ When in doubt: leave unchanged, and do **not** list under Uncertain. - Non-idiomatic but grammatical word choices — e.g. a slightly unusual adjective, a translated-feeling turn of phrase that still parses. - Stiffness, stuffiness, repetition, or a sentence that could be "smoother." -If in doubt whether something is a mistake or a voice choice, it's voice. Leave it. The bar for flagging anything at all is: *a native speaker would read this and say it's wrong*, not *a native speaker could improve it*. - ---- - -## Rules - -- Never change math, macros, labels, URLs, or structure. -- Never "improve" style, tone, or word choice. -- Never touch `\Problem` stars, source argument, or any structural argument — only prose inside statements / solutions / proofs. -- Deduplicate the Uncertain list: each distinct item once. +If in doubt whether something is a mistake or a voice choice, it's voice. Leave it. The bar for flagging anything at all is: *a native speaker would read this and say it's wrong*, not *a native speaker could improve it*. \ No newline at end of file