docs: split task 15 into 15a-15e after two failed attempts
verify-and-publish / gate (push) Successful in 6m57s
verify-and-publish / publish (push) Has been skipped

This commit is contained in:
Marcos Paulo
2026-09-05 17:35:58 +00:00
parent 47c50d43dd
commit aa2653340a
8 changed files with 384 additions and 113 deletions
+35 -30
View File
@@ -5,9 +5,9 @@ interchangeable here, and the split is not about which is "smartest" — it is
about which failure mode each task punishes. about which failure mode each task punishes.
**Honest caveat up front:** I have not benchmarked these three on this **Honest caveat up front:** I have not benchmarked these three on this
repository. The routing below is reasoned from task shape and each model's repository. The routing below is reasoned from task shape and each model's known
known strengths. Validate it cheaply on **task 07** (small, self-contained, strengths. Validate it cheaply on **task 07** (small, self-contained, easy to
easy to judge) before fanning out across ten worktrees. judge) before fanning out across ten worktrees.
## Short answer ## Short answer
@@ -18,22 +18,27 @@ points where M3 is the wrong tool.
## Routing table ## Routing table
| Task | Model | Why this one | | Task | Model | Why this one |
| --- | --- | --- | | ------------------------- | -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 01 scaffold + gates | **Codex** | Config-heavy, many interacting tools (Astro + husky + lint-staged + CI), and success is binary — it builds and hooks fire, or not. Codex's long autonomous run-until-green loop suits it, and getting the foundation wrong is expensive later. | | 01 scaffold + gates | **Codex** | Config-heavy, many interacting tools (Astro + husky + lint-staged + CI), and success is binary — it builds and hooks fire, or not. Codex's long autonomous run-until-green loop suits it, and getting the foundation wrong is expensive later. |
| 02 design tokens | **Gemini** | Needs the whole CSS corpus in one context (8 stylesheets, ~90 KB) plus **visual judgement on screenshots**. Gemini's long context and multimodal comparison are the differentiator; the others would work file-by-file and miss cross-file drift. | | 02 design tokens | **Gemini** | Needs the whole CSS corpus in one context (8 stylesheets, ~90 KB) plus **visual judgement on screenshots**. Gemini's long context and multimodal comparison are the differentiator; the others would work file-by-file and miss cross-file drift. |
| 03 verification net | **Codex** | Writing test tooling with a tight feedback loop. Precision about what an assertion pins matters more than speed. | | 03 verification net | **Codex** | Writing test tooling with a tight feedback loop. Precision about what an assertion pins matters more than speed. |
| 04 content schema | **MiniMax-M3** | Small, well-specified, one file. | | 04 content schema | **MiniMax-M3** | Small, well-specified, one file. |
| 0506 content migration | **MiniMax-M3** | High-volume mechanical string moves with a `diff` as the oracle. Cheap, parallel, verifiable. Exactly M3's sweet spot. | | 0506 content migration | **MiniMax-M3** | High-volume mechanical string moves with a `diff` as the oracle. Cheap, parallel, verifiable. Exactly M3's sweet spot. |
| 07 primitives | **MiniMax-M3** | Small components from templates. Use this task to calibrate the whole routing decision. | | 07 primitives | **MiniMax-M3** | Small components from templates. Use this task to calibrate the whole routing decision. |
| 0811 component blocks | **MiniMax-M3 ×4 parallel** | Four bounded tasks, one template each, checklist-gated. Cost per task matters because there are many. | | 0811 component blocks | **MiniMax-M3 ×4 parallel** | Four bounded tasks, one template each, checklist-gated. Cost per task matters because there are many. |
| 1214, 17 pages | **MiniMax-M3** | Bounded, snapshot-diff verified. | | 1214, 17 pages | **MiniMax-M3** | Bounded, snapshot-diff verified. |
| 15 full guide | **Codex** | The hard one: 50 KB `app.js`, 12 render functions, tab state, bilingual swap. Long sustained reasoning over interacting pieces; the task most likely to need many iterations against a failing check. | | 15 full guide | **split** | Ran twice on Codex, zero usable commits both times. This table's own swap rule applied: too big, so it became 15a15e. |
| 16 review desk | **Codex** | Same shape and worse — search, filtering, file fetching, six query params, markdown rendering, client-side diff. Highest defect risk in the plan. | | 15a guide selector | **Codex** | Collapsing nine near-identical render functions into one island is the reasoning-heavy part that remains. |
| 18 motion | **Gemini** | Judging whether motion looks right is perceptual. Feed it before/after captures. | | 15b copy prompt | MiniMax-M3 | Small, mechanical, and has an exact oracle: the clipboard payload must be byte-identical. |
| 19 contract re-point | **Codex** | 42 assertions to translate without losing coverage. Meticulous, mechanical, verifiable. | | 15c language toggle | **Codex** | Needs a design decision written down, not a port — the selector-map approach cannot survive. |
| 20 cutover | **you, with M3 assisting** | Touches production publishing. A human should be watching. | | 15d assemble full guide | **Codex** | Assembly, but wide: 22 KB of bilingual markup against three islands and task 10's blocks. |
| review of every task | **Gemini** | Fresh eyes, whole-diff-in-context, and it did not write the code. Never review with the model that wrote it. | | 15e retire responsive.css | `agy` | Screenshot-diff driven — needs vision. |
| 16 review desk | **Codex** | Same shape and worse — search, filtering, file fetching, six query params, markdown rendering, client-side diff. Highest defect risk in the plan. |
| 18 motion | **Gemini** | Judging whether motion looks right is perceptual. Feed it before/after captures. |
| 19 contract re-point | **Codex** | 42 assertions to translate without losing coverage. Meticulous, mechanical, verifiable. |
| 20 cutover | **you, with M3 assisting** | Touches production publishing. A human should be watching. |
| review of every task | **Gemini** | Fresh eyes, whole-diff-in-context, and it did not write the code. Never review with the model that wrote it. |
## The reasoning in one line each ## The reasoning in one line each
@@ -41,11 +46,11 @@ points where M3 is the wrong tool.
Use it for volume: 13 of the 20 tasks. Its weakness is long multi-file Use it for volume: 13 of the 20 tasks. Its weakness is long multi-file
reasoning where the spec is vague; every task above that it owns has a reasoning where the spec is vague; every task above that it owns has a
template and a mechanical oracle. template and a mechanical oracle.
- **Codex** — best at "keep iterating until the check passes" over a - **Codex** — best at "keep iterating until the check passes" over a complicated
complicated existing codebase. Use it where the loop is long and the answer is existing codebase. Use it where the loop is long and the answer is not
not obvious: scaffold, the two hard pages, verification. obvious: scaffold, the two hard pages, verification.
- **Gemini** — biggest context and genuinely useful multimodal comparison. Use - **Gemini** — biggest context and genuinely useful multimodal comparison. Use
it where the input is *everything at once* or where the judgement is it where the input is _everything at once_ or where the judgement is
**visual**: token consolidation, motion, screenshot diffing, and code review. **visual**: token consolidation, motion, screenshot diffing, and code review.
## Cross-checking rule ## Cross-checking rule
@@ -56,13 +61,13 @@ reviews; Codex writes → Gemini reviews; Gemini writes → Codex reviews. The
## Swap the routing if you see this ## Swap the routing if you see this
| Symptom | Move the task to | | Symptom | Move the task to |
| --- | --- | | ------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| M3 spends more than ~3 iterations failing the same gate | Codex | | M3 spends more than ~3 iterations failing the same gate | Codex |
| M3 edits files outside its task scope | Codex, and tighten the brief | | M3 edits files outside its task scope | Codex, and tighten the brief |
| Codex "fixes" a red suite by deleting assertions | anything — but re-read `context/verification.md` to it first; `gate.sh` blocks the merge either way | | Codex "fixes" a red suite by deleting assertions | anything — but re-read `context/verification.md` to it first; `gate.sh` blocks the merge either way |
| Gemini gives confident visual sign-off with no screenshots attached | require the artifacts; do not accept prose | | Gemini gives confident visual sign-off with no screenshots attached | require the artifacts; do not accept prose |
| A task needs more than two models' worth of hand-holding | the task is too big — split it | | A task needs more than two models' worth of hand-holding | the task is too big — split it |
## Cost shape ## Cost shape
+28 -23
View File
@@ -37,32 +37,37 @@ on four branches; nothing is merged or pushed.
Phase 0 foundation 01 → (02 ∥ 03 ∥ 04) Phase 0 foundation 01 → (02 ∥ 03 ∥ 04)
Phase 1 content 05 ∥ 06 after 04 Phase 1 content 05 ∥ 06 after 04
Phase 2 components 07 → (08 ∥ 09 ∥ 10 ∥ 11) after 02 Phase 2 components 07 → (08 ∥ 09 ∥ 10 ∥ 11) after 02
Phase 3 pages 12 ∥ 13 ∥ 14 ∥ 17, then 15 ∥ 16 Phase 3 pages 12 ∥ 13 ∥ 14 ∥ 17, then 15a ∥ 15b ∥ 15c ∥ 16, then 15d, 15e
Phase 4 polish 18 ∥ 19, then 20 Phase 4 polish 18 ∥ 19, then 20
``` ```
| # | Task | Agent | Depends on | Parallel with | | # | Task | Agent | Depends on | Parallel with |
| --- | ------------------------------------------------ | --------------------- | ---------- | ------------- | | --- | ----------------------------------------------------------------- | --------------------- | ------------- | ------------- |
| 01 | [scaffold + gates](task-01-scaffold.md) | astro-architect | — | — | | 01 | [scaffold + gates](task-01-scaffold.md) | astro-architect | — | — |
| 02 | [design tokens](task-02-tokens.md) | design-system-keeper | 01 | 03, 04 | | 02 | [design tokens](task-02-tokens.md) | design-system-keeper | 01 | 03, 04 |
| 03 | [verification net](task-03-verification-net.md) | verification-engineer | 01 | 02, 04 | | 03 | [verification net](task-03-verification-net.md) | verification-engineer | 01 | 02, 04 |
| 04 | [content schema](task-04-content-schema.md) | content-i18n-migrator | 01 | 02, 03 | | 04 | [content schema](task-04-content-schema.md) | content-i18n-migrator | 01 | 02, 03 |
| 05 | [guide content](task-05-content-guide.md) | content-i18n-migrator | 04 | 06 | | 05 | [guide content](task-05-content-guide.md) | content-i18n-migrator | 04 | 06 |
| 06 | [review-desk content](task-06-content-review.md) | content-i18n-migrator | 04 | 05 | | 06 | [review-desk content](task-06-content-review.md) | content-i18n-migrator | 04 | 05 |
| 07 | [primitives](task-07-primitives.md) | component-builder | 02 | — | | 07 | [primitives](task-07-primitives.md) | component-builder | 02 | — |
| 08 | [route cards](task-08-route-cards.md) | component-builder | 07 | 09, 10, 11 | | 08 | [route cards](task-08-route-cards.md) | component-builder | 07 | 09, 10, 11 |
| 09 | [chapter blocks](task-09-chapter-blocks.md) | component-builder | 07 | 08, 10, 11 | | 09 | [chapter blocks](task-09-chapter-blocks.md) | component-builder | 07 | 08, 10, 11 |
| 10 | [guide blocks](task-10-guide-blocks.md) | component-builder | 07 | 08, 09, 11 | | 10 | [guide blocks](task-10-guide-blocks.md) | component-builder | 07 | 08, 09, 11 |
| 11 | [review-desk blocks](task-11-review-blocks.md) | component-builder | 07 | 08, 09, 10 | | 11 | [review-desk blocks](task-11-review-blocks.md) | component-builder | 07 | 08, 09, 10 |
| 12 | [landing page](task-12-page-landing.md) | page-migrator | 03, 08 | 13, 14, 17 | | 12 | [landing page](task-12-page-landing.md) | page-migrator | 03, 08 | 13, 14, 17 |
| 13 | [chapter pages ×4](task-13-page-chapters.md) | page-migrator | 03, 09 | 12, 14, 17 | | 13 | [chapter pages ×4](task-13-page-chapters.md) | page-migrator | 03, 09 | 12, 14, 17 |
| 14 | [rules page](task-14-page-rules.md) | page-migrator | 03, 09 | 12, 13, 17 | | 14 | [rules page](task-14-page-rules.md) | page-migrator | 03, 09 | 12, 13, 17 |
| 15 | [full guide](task-15-page-full-guide.md) | page-migrator | 05, 10, 13 | 16 | | 15 | [full guide](task-15-page-full-guide.md) **split into 15a15e** | — | — | |
| 16 | [review desk](task-16-page-review-desk.md) | page-migrator | 06, 11, 13 | 15 | | 15a | [guide selector](task-15a-guide-selector.md) | component-builder | 05, 10 | 15b, 15c |
| 17 | [hands-on passthrough](task-17-hands-on.md) | astro-architect | 01 | 12, 13, 14 | | 15b | [copy prompt](task-15b-copy-prompt.md) | component-builder | 05 | 15a, 15c |
| 18 | [motion pass](task-18-motion.md) | motion-designer | 15, 16 | 19 | | 15c | [language toggle](task-15c-language-toggle.md) | content-i18n-migrator | 05 | 15a, 15b |
| 19 | [contract re-point](task-19-verify-repoint.md) | verification-engineer | 15, 16 | 18 | | 15d | [assemble full guide](task-15d-page-full-guide.md) | page-migrator | 10, 13, 15ac | 16 |
| 20 | [cutover + cleanup](task-20-cutover.md) | astro-architect | all | — | | 15e | [retire responsive.css](task-15e-responsive-css.md) | design-system-keeper | 15d, 16 | — |
| 16 | [review desk](task-16-page-review-desk.md) | page-migrator | 06, 11, 13 | 15d |
| 17 | [hands-on passthrough](task-17-hands-on.md) | astro-architect | 01 | 12, 13, 14 |
| 18 | [motion pass](task-18-motion.md) | motion-designer | 15d, 16 | 19 |
| 19 | [contract re-point](task-19-verify-repoint.md) | verification-engineer | 15d, 16 | 18 |
| 20 | [cutover + cleanup](task-20-cutover.md) | astro-architect | all | — |
Widest parallelism: **four agents** (tasks 0811, then 12/13/14/17). More than Widest parallelism: **four agents** (tasks 0811, then 12/13/14/17). More than
that and they start contending on review capacity, not on files. that and they start contending on review capacity, not on files.
+18 -60
View File
@@ -1,64 +1,22 @@
# Task 15 — Full guide # Task 15 — Full guide — **SUPERSEDED, split into 15a15e**
**Agent**: `page-migrator` · **Model**: **Codex** — hardest task in the plan Do not work this brief. It is kept because other documents link to it.
**Depends on**: 05, 10, 13 · **Parallel with**: 16 **Worktree**:
`.agents/scripts/worktree.sh start 15 page-full-guide`
## Goal Task 15 was attempted twice on Codex and produced no usable commit either time.
The second report's own words: _"this is an incomplete scaffold, not the real
migration requested."_ `MODEL-ROUTING.md` says a task needing more than two
models' worth of hand-holding is too big — split it. So it is split, along the
seams that made it hard: the nine-fold selector duplication, the clipboard
fallback, and the selector-map language toggle that cannot survive the port.
`/full-guide/` → Astro. 22 KB of HTML, a 50 KB script, 30 KB of CSS, twelve | Brief | What | Depends on |
render functions, bilingual throughout. | ---------------------------------- | ------------------------------------------- | --------------------- |
| [15a](task-15a-guide-selector.md) | one generic selector island for nine groups | 05, 10 |
| [15b](task-15b-copy-prompt.md) | copy-prompt buttons, reading progress | 05 |
| [15c](task-15c-language-toggle.md) | language toggle — needs a decision first | 05 |
| [15d](task-15d-page-full-guide.md) | assemble `/full-guide/` | 10, 13, 15a, 15b, 15c |
| [15e](task-15e-responsive-css.md) | prove `responsive.css` dead, delete it | 15d, 16 |
## What `app.js` actually is 15a, 15b and 15c run in parallel. 15d is assembly and must not invent islands.
Downstream tasks that said "depends on 15" now depend on **15d** (18, 19) or
Not application code — a **bilingual content database** (task 05 already moved **15e** (20).
it) plus ~12 `render*` functions that swap `innerHTML` on tab clicks. Once
content is a collection, the remaining JS is small: tab state and a language
toggle.
## Islands
Only these hydrate. Everything else is server-rendered.
| Island | Directive | Why |
| -------------------------------------------------------- | ---------------- | -------------------------------------------------- |
| Phase tabs | `client:visible` | click-driven panel swap |
| Tree / worker / route / model / effort / skill selectors | `client:visible` | same pattern; consider one generic selector island |
| Language toggle | `client:idle` | page-wide, not urgent |
| Copy-prompt buttons | `client:visible` | clipboard |
If you end up with 12 separate islands you have missed the pattern — they are
one selector component with different data.
## Asserted by verify.mjs — all must survive
`const phases`, `const handsOnPrompts`, `const modelGuide`,
`const skillSources`, `const skillInstallPrompts`, `render('plan')`,
`renderTree`, `renderWorker`, `renderRoute`, `renderModelProvider`,
`renderEffort`, `renderSkillFile`, `renderSkillWorkflow`, `renderCommonSkill`,
`renderHandsOn`, `copyPrompt`.
These are **implementation-detail assertions** — they look deletable and are
not. Each pins a feature. Coordinate with task 19 to replace each with an
output-level assertion of the same behaviour. **Never delete one yourself.**
Also: `data-copy-target="prompt-install-skills|prompt-basic|prompt-skills"`,
`hands-on/starter/`, `additional-reading.md`, `role="tablist"`, `<table>`.
## Watch for
- `copyPrompt` uses `navigator.clipboard` with a `document.execCommand`
fallback. Keep both — the fallback exists for non-secure contexts.
- The hands-on prompt strings are copy-pasted by attendees into an agent. Exact
whitespace and line breaks matter.
- `responsive.css` (30 KB) mostly serves this page. Port what is needed, prove
the rest dead, delete it. Screenshots are the proof.
## Done when
- [ ] Snapshot diff empty
- [ ] Every interaction works: all tabs, both languages, all copy buttons
- [ ] Keyboard: arrow keys move between tabs; focus visible throughout
- [ ] JS payload **smaller** than today's 50 KB (content is now static)
- [ ] Screenshots match at four widths; checklist complete; `pnpm run gate`
green
@@ -0,0 +1,86 @@
# Task 15a — The one guide selector island
**Agent**: `component-builder` · **Model**: **Codex** **Depends on**: 05, 10 ·
**Parallel with**: 15b · **Blocks**: 15d **Worktree**:
`.agents/scripts/worktree.sh start 15a guide-selector`
## Why this task exists
Task 15 was attempted twice on Codex and produced no usable commit either time.
Its own second report said "this is an incomplete scaffold, not the real
migration requested". `MODEL-ROUTING.md` says a task that needs more than two
models' worth of hand-holding is too big — so it is split. This is the first
piece: **the interactive machinery, with no page migration in it.**
## Scope
One new island under `src/components/islands/`. You import nothing into a page
and you migrate no page — tasks 07 through 11 shipped components ahead of their
pages the same way, and the gate is happy with an unimported component.
## What you are replacing
`app.js` has nine functions that are the same function nine times:
| Function | Trigger attribute | Detail panel target |
| --------------------- | --------------------- | ---------------------- |
| `render` | `data-phase` | `#phase-panel` |
| `renderWorker` | `data-worker` | `#worker-detail` |
| `renderTree` | `data-tree` | `#tree-detail` |
| `renderRoute` | `data-route` | `#route-detail` |
| `renderModelProvider` | `data-model-provider` | `#provider-detail` |
| `renderEffort` | `data-effort` | `#effort-detail` |
| `renderSkillFile` | `data-skill-file` | `#skill-detail` |
| `renderSkillWorkflow` | `data-skill-step` | `#builder-detail` |
| `renderCommonSkill` | `data-common-skill` | `#common-skill-detail` |
Each: click a button in a group, mark it active, swap the panel's `innerHTML`
from a content object. **Build one island, not nine.** If your diff has nine
components you have missed the point of the task.
The panels' inner markup differs per group (`#route-detail` draws a `--score`
meter, `#tree-detail` draws owner/checkout/note/command). Take the shape from
the slot or from a per-group layout, not from nine islands.
## The one coupling that is not uniform
`data-model-provider` clicks also re-run `renderEffort` with the currently
active effort. Preserve that. Everything else is independent.
## Asserted by verify.mjs — all nine names must survive
`render('plan')`, `renderTree`, `renderWorker`, `renderRoute`,
`renderModelProvider`, `renderEffort`, `renderSkillFile`, `renderSkillWorkflow`,
`renderCommonSkill`. Also `role="tablist"`.
These are implementation-detail assertions. They look deletable and are not —
each pins a feature. **Never delete one.** If a name genuinely cannot survive
the new shape, stop and report it; task 19 re-points assertions, you do not.
## Also deliver
- Keyboard: Arrow keys, Home and End move between buttons in a group; focus
visible throughout. `role="tablist"` groups follow the ARIA tabs pattern.
- Server-render the initially active panel. The panel must not be empty before
hydration.
- `client:visible`.
## Do not
- Migrate `/full-guide/` or create `src/pages/full-guide.astro`. That is 15d.
- Touch the language toggle or the copy buttons. Those are 15c and 15b.
- Touch `src/content/config.ts`, `verify.mjs`, `tokens.css`, `responsive.css`.
- Reformat `app.js`. It is in `.prettierignore`; keep it that way.
- Substitute a near-miss design token for a legacy value. Mark it:
`/* token-gap: <reason>; owner design-system-keeper */`. See
`.agents/rules/gates.md`.
## Done when
- [ ] One island, driven by the collections task 05 filled
- [ ] All nine behaviours reachable through it, including the provider/effort
coupling
- [ ] Keyboard and focus complete
- [ ] `pnpm run gate` green — the **full** gate, not just `verify` + `audit-ui`
- [ ] 42 assertions intact
- [ ] Report names the island's props so 15d can wire it without guessing
@@ -0,0 +1,55 @@
# Task 15b — Copy-prompt buttons and reading progress
**Agent**: `component-builder` · **Model**: MiniMax-M3 **Depends on**: 05 ·
**Parallel with**: 15a, 15c · **Blocks**: 15d **Worktree**:
`.agents/scripts/worktree.sh start 15b copy-prompt`
## Scope
Two small pieces of `app.js`, as islands. No page migration.
### 1. `copyPrompt`
Reads `#${button.dataset.copyTarget}`'s `textContent` and copies it.
- Keeps `navigator.clipboard.writeText` **and** the `document.execCommand`
textarea fallback. The fallback exists because the site is served over plain
HTTP in workshop settings, where `navigator.clipboard` is undefined. Deleting
it silently breaks the lab for attendees. Keep both paths.
- Writes a bilingual result string into `#copy-status`.
- On success, swaps the button's `<span>` to COPIED / COPIADO and back after
1800 ms.
Targets asserted by `verify.mjs`:
`data-copy-target="prompt-install-skills|prompt-basic|prompt-skills"`.
The prompt bodies are copy-pasted by attendees straight into an agent. **Exact
whitespace and line breaks matter** — verify what lands on the clipboard is
byte-identical to today's, not merely visually similar.
### 2. Reading progress
The `scroll` listener that sets `.reading-progress span`'s width. It is
`{ passive: true }` today; keep it passive.
## Language
Both pieces read `currentLanguage`. Task 15c owns how language is held. Do not
invent a second mechanism — take the language as a prop or read the document's
`lang`, and say in your report which you chose so 15c and 15d can align.
## Do not
- Create `src/pages/full-guide.astro`. That is 15d.
- Touch `verify.mjs`, `tokens.css`, `src/content/config.ts`.
- Reformat `app.js`.
- Substitute a near-miss token; mark gaps with
`/* token-gap: <reason>; owner design-system-keeper */`.
## Done when
- [ ] Both clipboard paths present and the fallback actually exercised
- [ ] `#copy-status` bilingual, and announced (it is a live region)
- [ ] Clipboard payload byte-identical to today's for all three targets
- [ ] `pnpm run gate` green — the full gate
- [ ] 42 assertions intact
@@ -0,0 +1,62 @@
# Task 15c — The language toggle
**Agent**: `content-i18n-migrator` · **Model**: **Codex** **Depends on**: 05 ·
**Parallel with**: 15a, 15b · **Blocks**: 15d **Worktree**:
`.agents/scripts/worktree.sh start 15c language-toggle`
## Why this is its own task
This is the part of the full guide that does not survive a mechanical port, and
it is the most likely reason task 15 failed twice.
Today `applyLanguage` walks a `translations.pt` map of **CSS selector →
Portuguese HTML** and overwrites `innerHTML` at each selector. It keeps an
`originals` Map to restore English. That design cannot survive the migration:
the selectors are page-structure coupling, and once the content is a collection
the Portuguese string already lives beside the English one.
## Deliver a decision, then an implementation
Write the approach down in `.agents/context/content-i18n.md` (or the rule file
it points at) **before** you build, because tasks 15d, 16, and 20 all depend on
it and there is currently no stated answer.
The realistic options:
1. **Server-render both locales, toggle visibility.** Simple, no hydration cost
for text, doubles the HTML.
2. **Server-render the saved locale, islands re-render on toggle.** Smaller
HTML; every island then needs both strings client-side anyway.
3. **Separate routes per locale.** Cleanest, but changes URLs, which touches
publishing and every internal link — out of scope unless you argue for it and
the report flags it as a plan change.
Pick one, say why, and note what it costs.
## Behaviour that must not regress
- `localStorage` key `ai-for-dummies-language`, wrapped in try/catch — previews
disable storage and an unguarded read throws.
- `document.documentElement.lang` becomes `pt-BR` or `en`.
- `[data-lang]` buttons get `.active` and `aria-pressed`.
- Toggling language re-renders the active phase panel and every selector panel.
Coordinate with 15a: the island must expose a way to do this.
- `client:idle` — page-wide, not urgent.
## Do not
- Create `src/pages/full-guide.astro`. That is 15d.
- Edit `src/content/config.ts` schemas belonging to other collections beyond
what the toggle genuinely needs; if a schema is wrong, report it.
- Touch `verify.mjs`.
- Translate, rewrite, or "improve" any string. Both locales already exist in the
collections. This is plumbing, not copywriting.
## Done when
- [ ] Approach written down where 15d, 16 and 20 will find it
- [ ] Toggle island built, `client:idle`, storage guarded
- [ ] Both locales verified on a real rendered page, not just in theory
- [ ] `pnpm run gate` green — the full gate
- [ ] 42 assertions intact
- [ ] Report states the contract 15d must satisfy
@@ -0,0 +1,58 @@
# Task 15d — Assemble /full-guide/
**Agent**: `page-migrator` · **Model**: **Codex** **Depends on**: 10, 13, 15a,
15b, 15c · **Parallel with**: 16 · **Blocks**: 15e, 18, 19 **Worktree**:
`.agents/scripts/worktree.sh start 15d page-full-guide`
## Goal
`src/pages/full-guide.astro`. 22 KB of HTML, bilingual throughout, everything
interactive already built by 15a/15b/15c and every block already built by
task 10. **This task is assembly.** If you find yourself writing a new island,
stop — it belongs to one of the earlier briefs and you should report the gap
instead.
Read the reports from 15a, 15b and 15c first. They state their props and the
language contract.
## Islands and nothing else
| Island | Directive | From |
| ------------------------------- | ---------------- | ---- |
| Guide selector (one, ×9 groups) | `client:visible` | 15a |
| Copy-prompt buttons + progress | `client:visible` | 15b |
| Language toggle | `client:idle` | 15c |
Everything else is server-rendered.
## Asserted by verify.mjs — all must survive
`const phases`, `const handsOnPrompts`, `const modelGuide`,
`const skillSources`, `const skillInstallPrompts`, `render('plan')`,
`renderTree`, `renderWorker`, `renderRoute`, `renderModelProvider`,
`renderEffort`, `renderSkillFile`, `renderSkillWorkflow`, `renderCommonSkill`,
`renderHandsOn`, `copyPrompt`, plus
`data-copy-target="prompt-install-skills|prompt-basic|prompt-skills"`,
`hands-on/starter/`, `additional-reading.md`, `role="tablist"`, `<table>`.
Implementation-detail assertions, deliberately. **Never delete one.** Task 19
re-points them to output-level checks; you do not.
## Watch for
- `hands-on/starter/` is a **lab fixture**. Link to it, ship it as a static
asset, do not componentize it. Same for `hands-on/rules/`.
- `renderHandsOn` takes no argument — it is not part of 15a's selector pattern.
Check whether 15a covered it; if not, it is yours, and say so in the report.
- Do not delete `responsive.css` here. That is 15e, and it needs screenshots.
## Done when
- [ ] Snapshot diff against `.agents/snapshots/` empty
- [ ] Every interaction works: all nine selector groups, both languages, all
three copy buttons
- [ ] Keyboard: arrows move between tabs; focus visible throughout
- [ ] JS payload **smaller** than today's 50 KB — content is static now
- [ ] Screenshots match at 560 / 800 / 1100 / 1600 px
- [ ] `pnpm run gate` green — the full gate, not `verify` + `audit-ui` alone
- [ ] 42 assertions intact
@@ -0,0 +1,42 @@
# Task 15e — Retire responsive.css
**Agent**: `design-system-keeper` · **Model**: `agy` (Gemini 3.1 Pro — vision)
**Depends on**: 15d, 16 · **Blocks**: 20 **Worktree**:
`.agents/scripts/worktree.sh start 15e responsive-css`
## Goal
`responsive.css` is 30 KB and mostly served `/full-guide/`. Once 15d and 16 have
landed, port what the Astro pages still need into component styles or
`tokens.css`, prove the remainder dead, and delete it.
**Proof is screenshots, not reading.** A rule that looks unused because no
selector matches at 1600 px may be the only thing holding the 560 px layout
together.
## Method
1. Build. Screenshot every migrated route at 560 / 800 / 1100 / 1600 px.
2. Remove `responsive.css` from the build entirely.
3. Screenshot again. Every diff is a rule you must port.
4. Port it into the owning component's `<style>`, or — if it is a real token —
into `tokens.css`, which **you own**. No other agent may add tokens.
5. Repeat until the diffs are empty.
## Constraints
- Allowed breakpoints are 560 / 800 / 1100 / 1600 / 2200 px.
`.agents/scripts/check-tokens.mjs` rejects others.
- Do not delete the file while any legacy page still loads it. Check which
routes have actually been migrated at the time you run; 20 is the cutover.
- No raw hex, no `font-size: Npx` outside `tokens.css`.
- You are also the owner of the ~190 accumulated `/* token-gap: ... */` markers.
Resolving them is **not** in this brief — do not start. Report the count so it
can be scheduled.
## Done when
- [ ] Screenshot diffs empty at all four widths without `responsive.css`
- [ ] Ported rules live with the component that needs them, or in `tokens.css`
- [ ] `responsive.css` deleted, and nothing references it
- [ ] `pnpm run gate` green; 42 assertions intact