5.0 KiB
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 forhands-on/rules/.renderHandsOntakes 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.csshere. 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 gategreen — the full gate, notverify+audit-uialone- 42 assertions intact
What 15a, 15b and 15c actually shipped
Read .agents/context/content-i18n.md first — it is the language contract and
it is binding on this task.
src/components/islands/GuideSelector.astro— one island, all nine groups. Render it as<GuideSelector rootSelector="#full-guide" data={...} />.dataneedsphases,workers,trees,routes,providers,efforts,skillFiles,skillWorkflow,commonSkillsand a bilinguallabelsobject; theGuideSelectorDatainterface at the top of the file is the exact shape. You server-render each group's shell and its initial detail panel, keeping today'sdata-*hooks and.activestate. Mark each grouprole="tablist"and its controlsrole="tab"or the keyboard handler will not bind.src/components/islands/LanguageToggle.astro— render each localized fragment twice, withdata-language-content="en"or"pt"on the outer element. The toggle flipshiddenon those, sets<html lang>, and firesai-for-dummies:languagechangeonwindow. It is a plain.astroisland that defers its own setup withrequestIdleCallback; do not putclient:idleon it — that directive is framework-components only.src/components/islands/CopyPrompt.astro— one per button. Passtarget="prompt-install-skills" | "prompt-basic" | "prompt-skills". Render<p id="copy-status" role="status" aria-live="polite">exactly once on the page; the island writes into it. Fill the<pre><code id="prompt-…">bodies from thehandsOnPromptsandskillInstallPromptscollections — 15b verified those are byte-identical to the legacyapp.jsconstants, and the clipboard copies whatever you render, so do not reformat them.src/components/islands/ReadingProgress.astro— replaces the legacy<div class="reading-progress">at the top of the page.
Nothing else is missing. If you are about to write an island, you are doing another task's work — report the gap instead.
Two things to expect
- The snapshot will not match by construction. Dual-locale rendering emits
both languages into the HTML where today's page emits English plus a
Portuguese map inside
app.js. Compare rendered, language-filtered output against today's page, and if.agents/snapshots/needs regenerating, say so explicitly in your report with what changed and why — do not quietly rewrite a snapshot to make a diff go away. renderHandsOntakes no argument and is not part of GuideSelector's nine-group pattern. It is yours. Its name is asserted byverify.mjs.