docs: add .agents workspace and the Astro refactor plan
Adds the agent-facing workspace and a 20-task plan for migrating the site to Astro. Nothing here implements the refactor; these are briefs, rules and templates that the task agents read. - .agents/ holds context, rules, checklists, skills, specialist agents, component/page/config templates and gate scripts. It is vendor-neutral so MiniMax, Gemini and Codex can all read it; CLAUDE.md just points at AGENTS.md. - .husky/ plus .lintstagedrc.json wire the three gate tiers. gate.sh locks on the shared git-common-dir so parallel worktrees serialise, and guards the assertion count in scripts/verify.mjs against a coverage drop. - plans/astro-refactor/ carries the phase graph, per-task briefs and the model-routing recommendation. These files must be tracked before fanning out: a worktree only checks out tracked files, so an untracked plan is invisible to every agent working in one. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
# Which model runs which task
|
||||
|
||||
You have **MiniMax-M3** (primary), **Gemini**, and **Codex**. They are not
|
||||
interchangeable here, and the split is not about which is "smartest" — it is
|
||||
about which failure mode each task punishes.
|
||||
|
||||
**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
|
||||
known strengths. Validate it cheaply on **task 07** (small, self-contained,
|
||||
easy to judge) before fanning out across ten worktrees.
|
||||
|
||||
## Short answer
|
||||
|
||||
**Run the refactor on MiniMax-M3.** It is your primary, the work is mostly
|
||||
bounded mechanical migration with a hard verification gate, and that is exactly
|
||||
the shape M3 handles well at low cost. Reach for the other two at three specific
|
||||
points where M3 is the wrong tool.
|
||||
|
||||
## Routing table
|
||||
|
||||
| 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. |
|
||||
| 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. |
|
||||
| 04 content schema | **MiniMax-M3** | Small, well-specified, one file. |
|
||||
| 05–06 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. |
|
||||
| 08–11 component blocks | **MiniMax-M3 ×4 parallel** | Four bounded tasks, one template each, checklist-gated. Cost per task matters because there are many. |
|
||||
| 12–14, 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. |
|
||||
| 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
|
||||
|
||||
- **MiniMax-M3** — cheapest per task and strong at bounded, tool-driven edits.
|
||||
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
|
||||
template and a mechanical oracle.
|
||||
- **Codex** — best at "keep iterating until the check passes" over a
|
||||
complicated existing codebase. Use it where the loop is long and the answer is
|
||||
not obvious: scaffold, the two hard pages, verification.
|
||||
- **Gemini** — biggest context and genuinely useful multimodal comparison. Use
|
||||
it where the input is *everything at once* or where the judgement is
|
||||
**visual**: token consolidation, motion, screenshot diffing, and code review.
|
||||
|
||||
## Cross-checking rule
|
||||
|
||||
Whatever writes a task must not review it. Pair them: M3 writes → Gemini
|
||||
reviews; Codex writes → Gemini reviews; Gemini writes → Codex reviews. The
|
||||
`reviewer` agent definition is model-agnostic on purpose.
|
||||
|
||||
## Swap the routing if you see this
|
||||
|
||||
| Symptom | Move the task to |
|
||||
| --- | --- |
|
||||
| M3 spends more than ~3 iterations failing the same gate | Codex |
|
||||
| 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 |
|
||||
| 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 |
|
||||
|
||||
## Cost shape
|
||||
|
||||
Tasks 05–14 are ~two-thirds of the work and are all M3-eligible. Running those
|
||||
on Codex would work and cost several times more for no measurable quality gain,
|
||||
because the checklist and `gate.sh` — not the model — are what guarantee those
|
||||
outputs. Spend the expensive models where there is no mechanical oracle: 15, 16,
|
||||
and the visual judgement calls.
|
||||
@@ -0,0 +1,94 @@
|
||||
# Astro refactor — plan
|
||||
|
||||
**Status: not started. These are briefs, not work.** Nothing in this plan has
|
||||
been implemented.
|
||||
|
||||
Goal: move `ai-for-dummies` from ten hand-written HTML pages to Astro, so that
|
||||
adding a chapter is a component and a content entry rather than a copy-pasted
|
||||
file — **without changing how the site looks, what it says, or what it costs a
|
||||
visitor to load.**
|
||||
|
||||
## Read before starting anything
|
||||
|
||||
| File | Why |
|
||||
| --- | --- |
|
||||
| [`../../AGENTS.md`](../../AGENTS.md) | entry point |
|
||||
| [`../../.agents/context/design-system.md`](../../.agents/context/design-system.md) | three drifting palettes, a font that has never rendered |
|
||||
| [`../../.agents/context/verification.md`](../../.agents/context/verification.md) | 42 assertions that will all break, and must not be deleted |
|
||||
| [`../../.agents/context/publishing.md`](../../.agents/context/publishing.md) | Gitea Pages serves a branch and cannot build |
|
||||
|
||||
## The three things most likely to go wrong
|
||||
|
||||
1. **Content loss that nobody notices.** 50 KB of bilingual copy moves between
|
||||
files. Snapshot every route *before* migrating it — task 03 exists to make
|
||||
that possible and blocks all page work.
|
||||
2. **Assertions deleted to make a red suite green.** That converts a content-loss
|
||||
bug into a passing build. `gate.sh` refuses a coverage drop.
|
||||
3. **Base-path bugs.** The site lives at `/ai-for-dummies/`. It will work
|
||||
perfectly in `npm run preview` and 404 in production. Verify on the real host.
|
||||
|
||||
## Phases
|
||||
|
||||
```
|
||||
Phase 0 foundation 01 → (02 ∥ 03 ∥ 04)
|
||||
Phase 1 content 05 ∥ 06 after 04
|
||||
Phase 2 components 07 → (08 ∥ 09 ∥ 10 ∥ 11) after 02
|
||||
Phase 3 pages 12 ∥ 13 ∥ 14 ∥ 17, then 15 ∥ 16
|
||||
Phase 4 polish 18 ∥ 19, then 20
|
||||
```
|
||||
|
||||
| # | Task | Agent | Depends on | Parallel with |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 01 | [scaffold + gates](task-01-scaffold.md) | astro-architect | — | — |
|
||||
| 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 |
|
||||
| 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 |
|
||||
| 06 | [review-desk content](task-06-content-review.md) | content-i18n-migrator | 04 | 05 |
|
||||
| 07 | [primitives](task-07-primitives.md) | component-builder | 02 | — |
|
||||
| 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 |
|
||||
| 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 |
|
||||
| 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 |
|
||||
| 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 |
|
||||
| 16 | [review desk](task-16-page-review-desk.md) | page-migrator | 06, 11, 13 | 15 |
|
||||
| 17 | [hands-on passthrough](task-17-hands-on.md) | astro-architect | 01 | 12, 13, 14 |
|
||||
| 18 | [motion pass](task-18-motion.md) | motion-designer | 15, 16 | 19 |
|
||||
| 19 | [contract re-point](task-19-verify-repoint.md) | verification-engineer | 15, 16 | 18 |
|
||||
| 20 | [cutover + cleanup](task-20-cutover.md) | astro-architect | all | — |
|
||||
|
||||
Widest parallelism: **four agents** (tasks 08–11, then 12/13/14/17). More than
|
||||
that and they start contending on review capacity, not on files.
|
||||
|
||||
## Running a task
|
||||
|
||||
```bash
|
||||
.agents/scripts/worktree.sh start 08 route-cards
|
||||
cd ../af-task-08
|
||||
# agent reads: plans/astro-refactor/task-08-route-cards.md
|
||||
# .agents/agents/component-builder.md (+ the skills it names)
|
||||
```
|
||||
|
||||
The script runs `npm ci` and `verify-hooks.sh` for you. That matters: `.husky/_`
|
||||
is generated, not committed, so a hand-made worktree has hooks configured but
|
||||
**silently not running**.
|
||||
|
||||
Finishing:
|
||||
|
||||
```bash
|
||||
npm run gate # tier 2, same as pre-push
|
||||
# reviewer agent reads the diff against .agents/checklists/before-merge.md
|
||||
.agents/scripts/worktree.sh finish 08 route-cards
|
||||
```
|
||||
|
||||
## Which model to run each task
|
||||
|
||||
See [`MODEL-ROUTING.md`](MODEL-ROUTING.md).
|
||||
|
||||
## These files must be committed
|
||||
|
||||
Worktrees check out tracked files. If this plan stays untracked, every worktree
|
||||
you create will be missing it. Commit `plans/` and `.agents/` before fanning out.
|
||||
@@ -0,0 +1,59 @@
|
||||
# Task 01 — Astro scaffold, gates, and the publishing decision
|
||||
|
||||
**Agent**: `astro-architect` · **Model**: Codex · **Depends on**: nothing
|
||||
**Blocks**: everything · **Worktree**: `.agents/scripts/worktree.sh start 01 scaffold`
|
||||
|
||||
## Goal
|
||||
|
||||
A working Astro project that builds, serves one page correctly from the real
|
||||
host under `/ai-for-dummies/`, and has all three gate tiers live.
|
||||
|
||||
## Scope
|
||||
|
||||
`astro.config.mjs`, `package.json`, `tsconfig.json`, `src/layouts/BaseLayout.astro`,
|
||||
`.husky/`, `.lintstagedrc.json`, lint configs, `.gitea/workflows/verify.yml`,
|
||||
`docs/operations-guide.md`.
|
||||
|
||||
Copy the configs from `.agents/templates/config/` — they are written for this
|
||||
project (correct ignores for `hands-on/`, `submitted-skills/`, `vote-service/`).
|
||||
|
||||
## Steps
|
||||
|
||||
1. `npm create astro@latest` into the worktree — minimal template, TypeScript
|
||||
strict, **no UI framework, no CSS framework**.
|
||||
2. Set `base: '/ai-for-dummies'`. Every internal link goes through
|
||||
`import.meta.env.BASE_URL` from here on.
|
||||
3. `src/layouts/BaseLayout.astro`: `<html lang>`, viewport meta, title,
|
||||
description, global styles slot. Nothing clever.
|
||||
4. Merge `.agents/templates/config/package.scripts.json` into `package.json`.
|
||||
**`"prepare": "husky"` is what makes hooks exist** — without it every hook is
|
||||
inert.
|
||||
5. `npm install husky lint-staged prettier eslint stylelint …`, then `npx husky init`.
|
||||
6. Copy the three hooks and the lint configs into place. Verify with
|
||||
`.agents/scripts/verify-hooks.sh`.
|
||||
7. Migrate **one** page (`summary/` — smallest, zero JS) as a smoke test.
|
||||
8. Copy `hands-on/` into `public/` (task 17 does this properly; a stub is fine here).
|
||||
9. **Make the publishing decision** per `.agents/context/publishing.md`. Recommended:
|
||||
Gitea Actions builds `dist/` and pushes `pages`. Copy
|
||||
`.agents/templates/config/gitea-ci.yaml` to `.gitea/workflows/verify.yml`.
|
||||
10. Rewrite the publishing section of `docs/operations-guide.md` to match.
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] `npm run build` succeeds; `npm run gate` passes
|
||||
- [ ] `.agents/scripts/verify-hooks.sh` reports hooks live
|
||||
- [ ] A bad commit message is rejected; a raw hex in a `.astro` file is rejected
|
||||
- [ ] `/ai-for-dummies/summary/` serves correctly **from the real host**, not just preview
|
||||
- [ ] `docs/operations-guide.md` describes the actual publishing path
|
||||
|
||||
## Do not
|
||||
|
||||
- Do not migrate more than one page. That is tasks 12–16.
|
||||
- Do not add a UI framework, CSS framework, or any runtime dependency.
|
||||
- Do not touch `hands-on/` contents, `submitted-skills/`, or `vote-service/`.
|
||||
|
||||
## Watch for
|
||||
|
||||
The base path is the #1 production-only failure in this migration. `npm run
|
||||
preview` will lie to you. Deploy the smoke-test page and curl it with a
|
||||
`?v=<sha>` cache-buster.
|
||||
@@ -0,0 +1,56 @@
|
||||
# Task 02 — Design token layer
|
||||
|
||||
**Agent**: `design-system-keeper` · **Model**: Gemini (long context + visual judgement)
|
||||
**Depends on**: 01 · **Parallel with**: 03, 04 · **Blocks**: 07
|
||||
**Worktree**: `.agents/scripts/worktree.sh start 02 tokens`
|
||||
|
||||
## Goal
|
||||
|
||||
One value per token, a named type scale, five breakpoints — and photographic
|
||||
proof the site looks the same.
|
||||
|
||||
## Read first
|
||||
|
||||
`.agents/context/design-system.md`. It documents two traps you will otherwise
|
||||
walk into.
|
||||
|
||||
## Scope
|
||||
|
||||
`src/styles/tokens.css`, `src/styles/base.css`,
|
||||
`.agents/scripts/check-tokens.mjs`. You are the only writer of these.
|
||||
|
||||
## The two decisions to surface
|
||||
|
||||
1. **Three palettes → one.** `--ink` is `#172f42` / `#122534` / `#173044`;
|
||||
`--paper`, `--muted`, `--line`, `--gold` likewise. Most deltas are
|
||||
sub-perceptual — canonicalize. **`--blue` (`#527f9f` vs `#215675`) is visibly
|
||||
different**: screenshot both, get a human decision, record it here.
|
||||
2. **The fonts have never rendered.** `styles.css:1` has a malformed
|
||||
`@font-face` whose `src:` points at a Google Fonts *stylesheet*. Manrope and
|
||||
DM Mono have always fallen back to Arial and generic monospace. Default:
|
||||
delete the dead rule, declare what actually renders. Self-hosting the real
|
||||
fonts is a **redesign** and needs sign-off.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Run the extraction script in `.agents/skills/design-tokens/SKILL.md`.
|
||||
2. Capture baseline screenshots: 10 routes × {560, 800, 1100, 1600} **plus the
|
||||
eight breakpoint widths you are removing** (520, 530, 600, 620, 720, 850,
|
||||
880, 900).
|
||||
3. Write `tokens.css`: one value per semantic name, `--step-*` type scale
|
||||
replacing the 14 ad-hoc `clamp()` triples, five `--bp-*` widths.
|
||||
4. Re-capture. Compare. Explain every visible difference.
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] Extraction prints exactly one value per token
|
||||
- [ ] `node .agents/scripts/check-tokens.mjs` passes on `src/`
|
||||
- [ ] Before/after screenshots attached at all twelve widths
|
||||
- [ ] The `--blue` decision and the font decision are written down here
|
||||
|
||||
## Do not
|
||||
|
||||
- Do not add a webfont.
|
||||
- Do not rename tokens to numeric scales (`--color-neutral-900`).
|
||||
- Do not convert the `gap:1px` over a coloured parent trick into `border` — it
|
||||
is deliberate house style and appears everywhere.
|
||||
@@ -0,0 +1,49 @@
|
||||
# Task 03 — Verification net
|
||||
|
||||
**Agent**: `verification-engineer` · **Model**: Codex
|
||||
**Depends on**: 01 · **Parallel with**: 02, 04 · **Blocks**: 12–16
|
||||
**Worktree**: `.agents/scripts/worktree.sh start 03 verification-net`
|
||||
|
||||
## Goal
|
||||
|
||||
Rendered-text baselines for all ten routes, captured from the **vanilla site**,
|
||||
before any page is migrated. Without this the page migrators have nothing to
|
||||
diff against and "no content was lost" becomes an opinion.
|
||||
|
||||
This task is on the critical path. Do it early.
|
||||
|
||||
## Scope
|
||||
|
||||
`.agents/snapshots/`, `scripts/audit-ui.mjs`, `.agents/scripts/visual-regression.mjs`.
|
||||
|
||||
## Steps
|
||||
|
||||
1. `npm run serve` against the **current, unmigrated** site.
|
||||
2. Snapshot all ten routes:
|
||||
```bash
|
||||
for r in "" full-guide summary models agents skills rules skills-review \
|
||||
hands-on/starter hands-on/rules; do
|
||||
node .agents/scripts/snapshot-route.mjs "http://localhost:4173/$r/" \
|
||||
> ".agents/snapshots/${r:-index}.txt"
|
||||
done
|
||||
```
|
||||
Commit them. They are the regression net.
|
||||
3. Write `.agents/scripts/visual-regression.mjs` (Playwright). Extend the
|
||||
existing `scripts/inspect.py` pattern rather than inventing one. Baselines to
|
||||
`.agents/snapshots/before/`.
|
||||
4. **Fix the audit gap**: `audit-ui.mjs` rejects external `<script>`/`<link>`
|
||||
but misses external URLs in CSS — which is exactly how the broken Google
|
||||
Fonts `@font-face` got into this "dependency-free" site. Add `@import`,
|
||||
`src: url(https:…)`, `url(https:…)`.
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] Ten committed snapshots, each non-empty and containing that page's real prose
|
||||
- [ ] `visual-regression.mjs` captures 10 routes × 4 widths
|
||||
- [ ] Extended `audit-ui.mjs` **fails** on today's `styles.css` (prove it catches the real bug), then the dead rule is removed by task 02
|
||||
- [ ] `npm run gate` green
|
||||
|
||||
## Do not
|
||||
|
||||
Do not change any assertion in `verify.mjs` yet. That is task 19, after the
|
||||
pages exist.
|
||||
@@ -0,0 +1,37 @@
|
||||
# Task 04 — Content collection schema
|
||||
|
||||
**Agent**: `content-i18n-migrator` · **Model**: MiniMax-M3
|
||||
**Depends on**: 01 · **Parallel with**: 02, 03 · **Blocks**: 05, 06
|
||||
**Worktree**: `.agents/scripts/worktree.sh start 04 content-schema`
|
||||
|
||||
## Goal
|
||||
|
||||
Typed collections that make a missing translation a build error.
|
||||
|
||||
## Scope
|
||||
|
||||
`src/content/config.ts` only. You own it.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Define `const localized = z.object({ en: z.string(), pt: z.string() })`.
|
||||
**Both required.** A missing `pt` must fail the build — silent English
|
||||
fallback is how bilingual sites quietly become monolingual.
|
||||
2. Collections:
|
||||
- `guide` — `phases`, `modelGuide`, `skillSources`, `handsOnPrompts`, `skillInstallPrompts` from `app.js`
|
||||
- `chapters` — copy for `/models/`, `/agents/`, `/skills/`, `/summary/`
|
||||
- `reviews` — the 24 entries: `id`, `author`, `title`, `status`, `focus`, `wins[]`, `improve[]`, `extras`, `improved`
|
||||
3. **Make the language-switching decision** and record it here:
|
||||
- *client-side swap* — matches today, no URL change, both languages in the payload. **Recommended.**
|
||||
- *route-based `/en/` `/pt/`* — better SEO, changes every existing URL, needs redirects.
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] `astro check` passes
|
||||
- [ ] A deliberately missing `pt` field fails the build (prove it, then revert)
|
||||
- [ ] The language decision is written down here with its reason
|
||||
|
||||
## Do not
|
||||
|
||||
Do not move any content yet. Schema only — tasks 05 and 06 fill it, and they
|
||||
run in parallel against the shape you define.
|
||||
@@ -0,0 +1,38 @@
|
||||
# Task 05 — Guide content out of app.js
|
||||
|
||||
**Agent**: `content-i18n-migrator` · **Model**: MiniMax-M3
|
||||
**Depends on**: 04 · **Parallel with**: 06 · **Blocks**: 15
|
||||
**Worktree**: `.agents/scripts/worktree.sh start 05 content-guide`
|
||||
|
||||
## Goal
|
||||
|
||||
Every `{ en, pt }` string in `app.js` lives in `src/content/guide/`, byte-identical.
|
||||
|
||||
## Scope
|
||||
|
||||
`src/content/guide/**`. Do **not** delete anything from `app.js` yet — task 15
|
||||
removes it once the page consumes the collection.
|
||||
|
||||
## Steps
|
||||
|
||||
1. `node .agents/scripts/extract-strings.mjs app.js > /tmp/before.json`
|
||||
(~50 pairs across `phases`, `handsOnPrompts`, `modelGuide`, `skillSources`,
|
||||
`skillInstallPrompts`).
|
||||
2. Move them into the collection. **Copy mechanically — never retype.** These
|
||||
are hand-written translations with deliberate tone (`'Transforme ambiguidade
|
||||
em trabalho'`); retyping introduces drift nobody catches until a Portuguese
|
||||
speaker reads it.
|
||||
3. `node .agents/scripts/extract-strings.mjs src/content/guide/ > /tmp/after.json`
|
||||
4. `diff /tmp/before.json /tmp/after.json` → **must be empty**.
|
||||
|
||||
## Watch for
|
||||
|
||||
`handsOnPrompts` values are multi-line prompt strings built with `.join('\n')`.
|
||||
Preserve the exact line breaks and leading `-` bullets: they are copy-pasted by
|
||||
workshop attendees into an agent, and a mangled prompt breaks the exercise.
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] String diff empty
|
||||
- [ ] `astro check` passes; both locales present on every entry
|
||||
- [ ] `app.js` still untouched and the site still works
|
||||
@@ -0,0 +1,43 @@
|
||||
# Task 06 — Review-desk content out of catalog.js
|
||||
|
||||
**Agent**: `content-i18n-migrator` · **Model**: MiniMax-M3
|
||||
**Depends on**: 04 · **Parallel with**: 05 · **Blocks**: 16
|
||||
**Worktree**: `.agents/scripts/worktree.sh start 06 content-review`
|
||||
|
||||
## Goal
|
||||
|
||||
24 review entries become a typed collection, with the `improved` markdown as
|
||||
real `.md` files.
|
||||
|
||||
## Scope
|
||||
|
||||
`src/content/reviews/**`, `scripts/build-skill-review.mjs`.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Move all 24 entries from `skills-review/catalog.js` (27 KB) and
|
||||
`submitted-catalog.js` (18 KB) into the collection.
|
||||
2. `improved` becomes a real Markdown file per entry, rendered at build time.
|
||||
That deletes the hand-rolled client-side renderer.
|
||||
3. **Re-point `scripts/build-skill-review.mjs`** at the collection.
|
||||
|
||||
## The two traps
|
||||
|
||||
1. **The generator writes committed files.**
|
||||
`skill-reviews/improved/**/SKILL.md` is generated from the `improved` fields
|
||||
and the output is in git. Move `catalog.js` and the generator keeps running
|
||||
against nothing — **silently, exit code 0**. Prove it still produces
|
||||
byte-identical output:
|
||||
```bash
|
||||
node scripts/build-skill-review.mjs && git diff --exit-code skill-reviews/
|
||||
```
|
||||
2. **The diff view needs raw source.** The review desk compares original and
|
||||
improved as *text*. If `improved` only exists as rendered HTML, the change
|
||||
lens breaks. Keep the raw string reachable.
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] 24 entries in the collection; `verify.mjs`'s `id:'` count assertion still passes
|
||||
- [ ] `git diff --exit-code skill-reviews/` clean after regenerating
|
||||
- [ ] `astro check` passes
|
||||
- [ ] Every reference to the generator still accurate (`package.json`, `README.md`, `docs/operations-guide.md`, the review desk footer)
|
||||
@@ -0,0 +1,45 @@
|
||||
# Task 07 — Primitives
|
||||
|
||||
**Agent**: `component-builder` · **Model**: MiniMax-M3 — **use this task to
|
||||
calibrate the model routing before fanning out**
|
||||
**Depends on**: 02 · **Blocks**: 08–11
|
||||
**Worktree**: `.agents/scripts/worktree.sh start 07 primitives`
|
||||
|
||||
## Goal
|
||||
|
||||
The four smallest reusable pieces, so the four parallel block tasks compose
|
||||
rather than reinvent.
|
||||
|
||||
## Scope
|
||||
|
||||
`src/components/primitives/` — `Eyebrow.astro`, `Rule.astro`, `Callout.astro`,
|
||||
`CodeBlock.astro`. Nothing else.
|
||||
|
||||
## Why these four
|
||||
|
||||
Each appears 10+ times across the current stylesheets:
|
||||
|
||||
- **Eyebrow** — `10–11px` monospace, `letter-spacing:.08–.1em`, uppercase. The
|
||||
single most repeated treatment on the site and a signature of the design.
|
||||
- **Rule** — the `border-top: 4px solid var(--gold)` section divider.
|
||||
- **Callout** — gold-background emphasis block (`.callout`, `.thesis`).
|
||||
- **CodeBlock** — `<pre>` on `--ink` with gold text.
|
||||
|
||||
## Steps
|
||||
|
||||
Copy `.agents/templates/components/static-block.astro` for each. Typed props,
|
||||
tokens only, zero JS. Then grep the current CSS for every place each treatment
|
||||
appears and confirm the component covers them all — if it needs five variants,
|
||||
you have found two components, not one.
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] `.agents/checklists/before-component.md` complete for all four
|
||||
- [ ] Rendered output visually identical to the CSS classes they replace
|
||||
- [ ] `npm run gate` green
|
||||
- [ ] **Routing note written**: how many iterations, what the model got wrong.
|
||||
This decides whether 08–11 run on M3 or move to Codex.
|
||||
|
||||
## Do not
|
||||
|
||||
Do not build blocks or touch pages. Do not edit `tokens.css`.
|
||||
@@ -0,0 +1,37 @@
|
||||
# Task 08 — Route cards and grid group
|
||||
|
||||
**Agent**: `component-builder` · **Model**: MiniMax-M3
|
||||
**Depends on**: 07 · **Parallel with**: 09, 10, 11 · **Blocks**: 12
|
||||
**Worktree**: `.agents/scripts/worktree.sh start 08 route-cards`
|
||||
|
||||
## Goal
|
||||
|
||||
The landing page's six chapter cards become one component over data.
|
||||
|
||||
## Scope
|
||||
|
||||
`src/components/blocks/RouteCard.astro`, `src/components/blocks/GridGroup.astro`.
|
||||
|
||||
## Source
|
||||
|
||||
`index.html` — six `<article class="card">` blocks differing only in number,
|
||||
title, summary, and href. Textbook extraction. Styles in `landing.css` +
|
||||
`chapters.css`.
|
||||
|
||||
## Steps
|
||||
|
||||
1. `GridGroup` from `.agents/templates/components/grid-group.astro`. Preserve
|
||||
the `gap:1px` over a coloured parent separator technique — it is deliberate.
|
||||
2. `RouteCard` from `static-block.astro`: `number`, `title`, `summary`, `href`.
|
||||
3. Card content moves to the `chapters` collection, both locales.
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] Six cards render identically to `index.html` today
|
||||
- [ ] Screenshots at 560/800/1100/1600 match
|
||||
- [ ] Zero JS
|
||||
- [ ] `.agents/checklists/before-component.md` complete; `npm run gate` green
|
||||
|
||||
## Do not
|
||||
|
||||
Do not migrate `index.html` itself — that is task 12.
|
||||
@@ -0,0 +1,38 @@
|
||||
# Task 09 — Chapter blocks
|
||||
|
||||
**Agent**: `component-builder` · **Model**: MiniMax-M3
|
||||
**Depends on**: 07 · **Parallel with**: 08, 10, 11 · **Blocks**: 13, 14
|
||||
**Worktree**: `.agents/scripts/worktree.sh start 09 chapter-blocks`
|
||||
|
||||
## Goal
|
||||
|
||||
The shared furniture of `/models/`, `/agents/`, `/skills/`, `/summary/`,
|
||||
`/rules/` — five pages that today duplicate the same markup five times.
|
||||
|
||||
## Scope
|
||||
|
||||
`src/components/blocks/` — `ChapterHero.astro`, `SectionGrid.astro`,
|
||||
`ComparisonTable.astro`, `TopBar.astro`, `SiteFooter.astro`.
|
||||
`src/layouts/ChapterLayout.astro`.
|
||||
|
||||
## Source
|
||||
|
||||
`chapters.css` is already the shared layer; the duplication is in the five HTML
|
||||
files. Diff them against each other first — what differs is props, what matches
|
||||
is the component.
|
||||
|
||||
## Watch for
|
||||
|
||||
- `TopBar` carries `aria-current="page"`. Preserve it; it is the only
|
||||
indication of location for assistive tech.
|
||||
- The tables in `/models/` and `/rules/` scroll horizontally on narrow screens
|
||||
(`overflow-x:auto`, `min-width` on the inner element). Keep that — dropping it
|
||||
makes the tables unreadable on a phone, and `audit-ui.mjs` asserts related
|
||||
responsive tokens.
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] All five pages' markup expressible with these components
|
||||
- [ ] Rendered text identical to current pages
|
||||
- [ ] Zero JS
|
||||
- [ ] Checklist complete; `npm run gate` green
|
||||
@@ -0,0 +1,44 @@
|
||||
# Task 10 — Full-guide blocks
|
||||
|
||||
**Agent**: `component-builder` · **Model**: MiniMax-M3
|
||||
**Depends on**: 07 · **Parallel with**: 08, 09, 11 · **Blocks**: 15
|
||||
**Worktree**: `.agents/scripts/worktree.sh start 10 guide-blocks`
|
||||
|
||||
## Goal
|
||||
|
||||
The full guide's distinctive sections as components — **static shells only**.
|
||||
Task 15 wires the interactivity.
|
||||
|
||||
## Scope
|
||||
|
||||
`src/components/blocks/` — `PhasePanel.astro`, `FleetDiagram.astro`,
|
||||
`HandoffTable.astro`, `WorktreeMap.astro`, `RouteTable.astro`,
|
||||
`SkillPackage.astro`.
|
||||
|
||||
## Source
|
||||
|
||||
`full-guide/index.html` (22 KB) + `styles.css` + `responsive.css`.
|
||||
|
||||
## Critical: the `data-*` hooks are asserted by name
|
||||
|
||||
`verify.mjs` requires these survive: `data-phase="plan|build|review"`,
|
||||
`data-tree="main|ui"`, `data-worker="ui"`, `data-route="plan"`,
|
||||
`data-model-provider="openai|claude|gemini"`, `data-effort="low|medium|high"`,
|
||||
`data-skill-file="skill"`, `data-skill-step="observe|validate"`,
|
||||
`data-common-skill="ponytail|caveman|unlazy"`, `role="tablist"`, `id="hands-on"`.
|
||||
|
||||
Each is a real feature hook, not decoration. Losing one is losing a feature.
|
||||
|
||||
## Watch for
|
||||
|
||||
`responsive.css` is 30 KB of append-only overrides on top of `styles.css`. **Do
|
||||
not port it wholesale.** Take what each component needs, then prove the rest is
|
||||
dead. Expect to delete most of it — that is a win, not a risk, provided the
|
||||
screenshots agree.
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] Every `data-*` hook above present in rendered output
|
||||
- [ ] Components take props and render static markup; **no `client:*` yet**
|
||||
- [ ] Screenshots match the current guide at four widths
|
||||
- [ ] Checklist complete; `npm run gate` green
|
||||
@@ -0,0 +1,49 @@
|
||||
# Task 11 — Review-desk blocks
|
||||
|
||||
**Agent**: `component-builder` · **Model**: MiniMax-M3
|
||||
**Depends on**: 07 · **Parallel with**: 08, 09, 10 · **Blocks**: 16
|
||||
**Worktree**: `.agents/scripts/worktree.sh start 11 review-blocks`
|
||||
|
||||
## Goal
|
||||
|
||||
Review-desk furniture as static components. Interactivity is task 16.
|
||||
|
||||
## Scope
|
||||
|
||||
`src/components/blocks/` — `SkillList.astro`, `ReviewDetail.astro`,
|
||||
`FileTabs.astro`, `PreviewPane.astro`, `ChangeLens.astro`, `VoteWidget.astro`
|
||||
(markup only).
|
||||
|
||||
## Source
|
||||
|
||||
`skills-review/index.html`, `app.js` (20 KB), `styles.css`, `change-lens.css`,
|
||||
`vote.js`.
|
||||
|
||||
## One component, 24 entries
|
||||
|
||||
The 24 reviews are **data**, not 24 components. One `SkillReviewCard` iterating
|
||||
the collection. If you are writing the second near-identical component, stop.
|
||||
|
||||
## CSS tokens asserted by verify.mjs
|
||||
|
||||
`.change-lens`, `.change-rows`, `.skill-diff`, `.diff-lines`,
|
||||
`.markdown-preview`, `max-height:540px`, `.markdown-table-wrap`,
|
||||
`.markdown-frontmatter`, `.markdown-toc`, `.preview-title`, `.preview-markdown`,
|
||||
`grid-template-columns:minmax(0,1fr)`, `height:120px`, `-webkit-line-clamp:2`,
|
||||
`.vote-widget`, `.vote-buttons`, `[aria-pressed="true"]`.
|
||||
|
||||
Class names may move into scoped `<style>` blocks, but each must still exist and
|
||||
task 19 must be able to assert it. Coordinate names with the verification
|
||||
engineer rather than renaming freely.
|
||||
|
||||
## Watch for
|
||||
|
||||
`aria-pressed` on the vote buttons and preview switcher is how state reaches
|
||||
assistive tech. Colour alone is not enough. It is also asserted.
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] All listed CSS hooks present
|
||||
- [ ] `aria-pressed`, `role="group"`, `aria-label` preserved
|
||||
- [ ] Static render matches current desk at four widths
|
||||
- [ ] Checklist complete; `npm run gate` green
|
||||
@@ -0,0 +1,30 @@
|
||||
# Task 12 — Landing page
|
||||
|
||||
**Agent**: `page-migrator` · **Model**: MiniMax-M3
|
||||
**Depends on**: 03, 08 · **Parallel with**: 13, 14, 17
|
||||
**Worktree**: `.agents/scripts/worktree.sh start 12 page-landing`
|
||||
|
||||
## Goal
|
||||
|
||||
`index.html` → `src/pages/index.astro`. Smallest page migration; sets the
|
||||
pattern the other page tasks follow.
|
||||
|
||||
## Steps
|
||||
|
||||
Snapshot first (task 03 baseline exists — diff against it). Then compose from
|
||||
`RouteCard` + `GridGroup`, move copy to the `chapters` collection, port
|
||||
`landing.css` into component styles.
|
||||
|
||||
## Hard constraints
|
||||
|
||||
- URL stays `/ai-for-dummies/` exactly
|
||||
- **Zero JS** — this page has none today
|
||||
- `<title>`, `<meta name="description">`, viewport preserved
|
||||
- Internal links via `import.meta.env.BASE_URL`, never hand-written absolute
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] `diff .agents/snapshots/index.txt <(snapshot of dist)` empty
|
||||
- [ ] Screenshots match at four widths
|
||||
- [ ] Built page ships **0 bytes** of JS
|
||||
- [ ] `.agents/checklists/before-page.md` complete; `npm run gate` green
|
||||
@@ -0,0 +1,33 @@
|
||||
# Task 13 — Chapter pages ×4
|
||||
|
||||
**Agent**: `page-migrator` · **Model**: MiniMax-M3
|
||||
**Depends on**: 03, 09 · **Parallel with**: 12, 14, 17 · **Blocks**: 15, 16
|
||||
**Worktree**: `.agents/scripts/worktree.sh start 13 page-chapters`
|
||||
|
||||
## Goal
|
||||
|
||||
`/models/`, `/agents/`, `/skills/`, `/summary/` as Astro routes. One task
|
||||
because they share a layout — four near-identical migrations, and doing them
|
||||
together is what proves `ChapterLayout` is right.
|
||||
|
||||
Blocks 15 and 16 because those pages link here and share the layout.
|
||||
|
||||
## Hard constraints
|
||||
|
||||
- Four URLs unchanged, **trailing slashes included**
|
||||
- `/skills/` has an interactive package explorer (`skills/app.js`,
|
||||
`data-skill-file`, `data-skill-step`) — that becomes an **island**, and it is
|
||||
the only JS across these four pages. The other three ship zero.
|
||||
- All `data-*` hooks preserved; `verify.mjs` asserts several
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] Four snapshot diffs empty
|
||||
- [ ] Three pages ship 0 bytes JS; `/skills/` ships only its island
|
||||
- [ ] Screenshots match at four widths
|
||||
- [ ] Checklist complete for each page; `npm run gate` green
|
||||
|
||||
## Do not
|
||||
|
||||
Do not generalise `ChapterLayout` beyond these four. `/rules/` is task 14 and
|
||||
has its own interaction model.
|
||||
@@ -0,0 +1,33 @@
|
||||
# Task 14 — Rules page
|
||||
|
||||
**Agent**: `page-migrator` · **Model**: MiniMax-M3
|
||||
**Depends on**: 03, 09 · **Parallel with**: 12, 13, 17
|
||||
**Worktree**: `.agents/scripts/worktree.sh start 14 page-rules`
|
||||
|
||||
## Goal
|
||||
|
||||
`/rules/` → Astro. Separate from task 13: it is a standalone bilingual case
|
||||
study with its own stylesheet (`rules/styles.css`, 9.8 KB), its own script
|
||||
(`rules/app.js`, 16 KB), and its own responsive contract.
|
||||
|
||||
## Asserted by verify.mjs
|
||||
|
||||
- `rulesHtml` must have **no external `<script>`/`<link>`** — it is explicitly
|
||||
checked as a standalone page
|
||||
- `rulesCss` must contain `@media(min-width:2200px)`, `@media(max-width:900px)`,
|
||||
`@media(max-width:600px)`, `prefers-reduced-motion`
|
||||
|
||||
Task 02 collapses those breakpoints to named tokens. **Coordinate with the
|
||||
verification engineer** — the assertion must be re-pointed at the token, not
|
||||
deleted. Screenshot at the old widths (900, 600, 2200) to prove equivalence.
|
||||
|
||||
## Watch for
|
||||
|
||||
`rules/styles.css` shares `--accent` and `--deep` with `styles.css` — it is on
|
||||
the *first* palette. Confirm task 02 canonicalized it the same way.
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] Snapshot diff empty; bilingual toggle works, `<html lang>` follows
|
||||
- [ ] Responsive behaviour identical at 600/900/2200
|
||||
- [ ] No external dependency; checklist complete; `npm run gate` green
|
||||
@@ -0,0 +1,62 @@
|
||||
# Task 15 — Full guide
|
||||
|
||||
**Agent**: `page-migrator` · **Model**: **Codex** — hardest task in the plan
|
||||
**Depends on**: 05, 10, 13 · **Parallel with**: 16
|
||||
**Worktree**: `.agents/scripts/worktree.sh start 15 page-full-guide`
|
||||
|
||||
## Goal
|
||||
|
||||
`/full-guide/` → Astro. 22 KB of HTML, a 50 KB script, 30 KB of CSS, twelve
|
||||
render functions, bilingual throughout.
|
||||
|
||||
## What `app.js` actually is
|
||||
|
||||
Not application code — a **bilingual content database** (task 05 already moved
|
||||
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; `npm run gate` green
|
||||
@@ -0,0 +1,63 @@
|
||||
# Task 16 — Review desk
|
||||
|
||||
**Agent**: `page-migrator` · **Model**: **Codex** — highest defect risk
|
||||
**Depends on**: 06, 11, 13 · **Parallel with**: 15
|
||||
**Worktree**: `.agents/scripts/worktree.sh start 16 page-review-desk`
|
||||
|
||||
## Goal
|
||||
|
||||
`/skills-review/` → Astro. The most interactive page: search, filtering,
|
||||
lazy file fetching, markdown rendering, a client-side diff view, six URL params,
|
||||
and a live API call to `vote-service/`.
|
||||
|
||||
## The six query params are a public contract
|
||||
|
||||
`?author=`, `?skill=`, `?view=`, `?file=`, `?compare=`, `?render=` — documented
|
||||
in the page footer and shared externally. All six must round-trip, and browser
|
||||
back/forward must restore state (`syncUrl` / `selectFromUrl` today).
|
||||
|
||||
**Test every one manually.** A snapshot diff cannot catch a broken deep link.
|
||||
|
||||
## Islands
|
||||
|
||||
The catalog + detail pane is genuinely interactive: `client:load` is justified
|
||||
here. The vote widget is `client:visible`. Everything else server-renders.
|
||||
|
||||
## vote-service integration
|
||||
|
||||
`window.SKILLS_REVIEW_VOTE_API = 'https://ai-for-dummies-vote.marcospaulo.dev.br'`
|
||||
is set inline in `index.html` today. Either keep the global or move it to
|
||||
`PUBLIC_VOTE_API` — **if you move it, update `vote-service/README.md` in the
|
||||
same change**, since it documents the coupling.
|
||||
|
||||
`ALLOWED_ORIGIN` on the deployed service is
|
||||
`https://netcracker.pages.marcospaulo.dev.br`. If the site's origin changes, the
|
||||
vote API breaks with a CORS error. It does not change in this plan — but verify
|
||||
after cutover.
|
||||
|
||||
## Asserted by verify.mjs
|
||||
|
||||
Interaction tokens: `from './catalog.js'`, `from './files.js'`, `renderList`,
|
||||
`renderDetail`, `selectSkill`, `packageSummary`, `markdownHeadings`,
|
||||
`markdownToc`, `loadSelectedFile`, `schedulePackageSearch`, `fetchSource`,
|
||||
`packageSearchText`, `diffMarkup`, `diffRows`, `searchParams.set('compare')`,
|
||||
`markdownMarkup`, `syncUrl`, `selectFromUrl`, `URLSearchParams`,
|
||||
`navigator.clipboard`, `document.execCommand`.
|
||||
|
||||
Plus the catalog count: `id:'` occurrences across both catalogs **must equal 24**.
|
||||
|
||||
Same rule as task 15 — re-point with task 19, never delete.
|
||||
|
||||
## Watch for
|
||||
|
||||
The markdown renderer is hand-rolled (`markdownMarkup`, `markdownHeadings`,
|
||||
`markdownToc`). Task 06 moves rendering to build time — but the **diff view
|
||||
needs raw source text**, not rendered HTML. Keep both available.
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] All six query params round-trip; back/forward restores state
|
||||
- [ ] Search, filter, file tabs, preview, change lens, download, copy all work
|
||||
- [ ] Vote widget reaches the live API; CORS preflight succeeds
|
||||
- [ ] Snapshot diff empty; screenshots match; checklist complete
|
||||
- [ ] `npm run gate` green
|
||||
@@ -0,0 +1,38 @@
|
||||
# Task 17 — hands-on passthrough
|
||||
|
||||
**Agent**: `astro-architect` · **Model**: MiniMax-M3
|
||||
**Depends on**: 01 · **Parallel with**: 12, 13, 14
|
||||
**Worktree**: `.agents/scripts/worktree.sh start 17 hands-on`
|
||||
|
||||
## Goal
|
||||
|
||||
`hands-on/starter/` and `hands-on/rules/` ship **byte-identical** from
|
||||
`public/`, unprocessed.
|
||||
|
||||
## Why this is a task and not a footnote
|
||||
|
||||
These are **lab fixtures**. The workshop exercise is that an attendee points an
|
||||
agent at dependency-free HTML/CSS/JS and watches it work. Componentizing them,
|
||||
minifying them, or letting a bundler touch them destroys the lesson — and the
|
||||
prompts in `app.js` reference these files by path and content.
|
||||
|
||||
The risk is an agent "helpfully" improving them. This task exists to say
|
||||
explicitly: do not.
|
||||
|
||||
## Steps
|
||||
|
||||
1. Move both directories to `public/hands-on/`.
|
||||
2. Confirm Astro copies `public/` verbatim with no processing.
|
||||
3. Confirm URLs `/ai-for-dummies/hands-on/starter/` and `.../rules/` resolve.
|
||||
4. Confirm every lint/format config **ignores** them (the templates already do).
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] `diff -r` between the original directories and `dist/hands-on/` is empty
|
||||
- [ ] Both URLs serve; both labs work standalone
|
||||
- [ ] The `hands-on/starter/` reference in the full guide still resolves
|
||||
- [ ] `verify.mjs`'s `starterHtml` / `starterJs` assertions still pass
|
||||
|
||||
## Do not
|
||||
|
||||
Do not reformat, lint, componentize, or "modernise" a single line.
|
||||
@@ -0,0 +1,47 @@
|
||||
# Task 18 — Motion pass
|
||||
|
||||
**Agent**: `motion-designer` · **Model**: Gemini (perceptual judgement)
|
||||
**Depends on**: 15, 16 · **Parallel with**: 19
|
||||
**Worktree**: `.agents/scripts/worktree.sh start 18 motion`
|
||||
|
||||
## Goal
|
||||
|
||||
Audit the motion that exists, add only motion that earns its place, and make
|
||||
`prefers-reduced-motion` correct everywhere.
|
||||
|
||||
## Order of work — audit first
|
||||
|
||||
The audit is worth more than the additions.
|
||||
|
||||
1. Inventory every `transition`, `animation`, `@keyframes`, `transform` in `src/`.
|
||||
2. Flag anything animating a layout property (`width`, `height`, `top`, `left`,
|
||||
`margin`). Those force reflow every frame and fail the 200ms INP budget. The
|
||||
Stylelint config already blocks new ones; find the ported ones.
|
||||
3. Confirm every animated element has a reduced-motion path, then **test it**
|
||||
under DevTools emulation. Reduced means reduced, not broken — end states must
|
||||
still be correct.
|
||||
|
||||
## Then, sparingly
|
||||
|
||||
Candidates, each needing a written purpose:
|
||||
|
||||
- tab panel change in the guide (state change — justified)
|
||||
- review-desk detail swap on selection (state change — justified)
|
||||
- vote widget tally update (feedback — justified)
|
||||
|
||||
`transform` and `opacity` only. 150–250ms. `cubic-bezier(.2,0,0,1)`. One thing
|
||||
moves at a time — no staggered card cascades; this design has a point of view
|
||||
and staggering reads as a template.
|
||||
|
||||
## View transitions — optional, decide explicitly
|
||||
|
||||
Astro's `<ClientRouter />` is the only sanctioned motion dependency. If adopted,
|
||||
verify: JS-disabled navigation, browser back/forward, the review desk's six
|
||||
query params, and reduced motion. If any fails, do not ship it.
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] Zero animations on layout properties
|
||||
- [ ] Every animation has a one-line written purpose
|
||||
- [ ] Reduced-motion tested under emulation; end states correct
|
||||
- [ ] Before/after captures attached; `npm run gate` green
|
||||
@@ -0,0 +1,44 @@
|
||||
# Task 19 — Re-point the verification contract
|
||||
|
||||
**Agent**: `verification-engineer` · **Model**: Codex
|
||||
**Depends on**: 15, 16 · **Parallel with**: 18
|
||||
**Worktree**: `.agents/scripts/worktree.sh start 19 verify-repoint`
|
||||
|
||||
## Goal
|
||||
|
||||
All 42 assertions pin the same user-visible facts against the new architecture.
|
||||
Coverage does not fall.
|
||||
|
||||
You are the only role permitted to remove an assertion, and every removal needs
|
||||
a written reason.
|
||||
|
||||
## The three kinds
|
||||
|
||||
| Kind | Example | What to do |
|
||||
| --- | --- | --- |
|
||||
| Content presence | `data-phase="plan"` | re-point at `dist/full-guide/index.html`; the token should survive rendering. If it does not, a component dropped content — **stop and report** |
|
||||
| Implementation detail | `const phases`, `renderTree`, `from './catalog.js'` | obsolete as written, but each pins a **feature**. Replace with an output-level assertion of that feature. Never drop |
|
||||
| Asset version | `app.js?v=20260904-vote-widget` | Astro hashes assets — assert the built HTML references a hashed asset |
|
||||
|
||||
## Steps
|
||||
|
||||
1. `npm run build`, then re-point `read()` calls at `dist/`.
|
||||
2. Work through all 42 in order. For each: does the fact it pins still exist?
|
||||
Yes → re-point. No → content was lost; escalate.
|
||||
3. Add rendered-text snapshot assertions for all ten routes so this class of
|
||||
regression is caught structurally, not by string luck.
|
||||
4. Confirm `check-tokens.mjs` and the extended `audit-ui.mjs` are in
|
||||
`npm run verify`.
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] `grep -c 'throw new Error' scripts/verify.mjs` ≥ the `origin/main` baseline
|
||||
- [ ] Every removal has a one-line reason in this file
|
||||
- [ ] Snapshot assertions cover all ten routes
|
||||
- [ ] `npm run gate` green, and it **fails** when you deliberately delete a
|
||||
paragraph from a component (prove the net works, then revert)
|
||||
|
||||
## Do not
|
||||
|
||||
Do not weaken an assertion to make it pass. If it cannot pass, something is
|
||||
broken — that is the assertion doing its job.
|
||||
@@ -0,0 +1,58 @@
|
||||
# Task 20 — Cutover and cleanup
|
||||
|
||||
**Agent**: `astro-architect`, **with a human watching** · **Model**: MiniMax-M3 assisting
|
||||
**Depends on**: all · **Worktree**: `.agents/scripts/worktree.sh start 20 cutover`
|
||||
|
||||
This task touches production publishing. Do not run it unattended.
|
||||
|
||||
## Goal
|
||||
|
||||
The Astro build is what the world sees, the old files are gone, and the docs
|
||||
describe reality.
|
||||
|
||||
## Steps
|
||||
|
||||
1. **Full verification** on the built site: all 10 routes, all 6 query params,
|
||||
both languages, vote widget against the live API, screenshots at four widths.
|
||||
2. **Delete the superseded files** — only after their replacements are proven:
|
||||
`app.js`, `styles.css`, `responsive.css`, `chapters.css`, `landing.css`,
|
||||
`rules/app.js`, `rules/styles.css`, `skills/app.js`, `skills/styles.css`,
|
||||
`skills-review/*.js`, `skills-review/*.css`, and the ten old `index.html`
|
||||
files. `git rm`, one commit, reviewable.
|
||||
**Keep**: `hands-on/**` (now under `public/`), `submitted-skills/**`,
|
||||
`skill-reviews/**`, `docs/**`, `vote-service/**`.
|
||||
3. **Publish** via the mechanism chosen in task 01.
|
||||
4. **Verify on the real host** with a cache-buster:
|
||||
```bash
|
||||
for r in "" full-guide summary models agents skills rules skills-review \
|
||||
hands-on/starter hands-on/rules; do
|
||||
curl -sS -o /dev/null -w "%{http_code} $r\n" \
|
||||
"https://netcracker.pages.marcospaulo.dev.br/ai-for-dummies/$r/?v=$(git rev-parse --short HEAD)"
|
||||
done
|
||||
```
|
||||
All ten must be 200. A stale cached 200 looks identical to success — the
|
||||
`?v=` is what distinguishes them.
|
||||
5. **Update the docs**: `README.md`, `docs/operations-guide.md` (build + publish
|
||||
path, and it must stop claiming `pages` is "the exact published source" if
|
||||
that is no longer true), `GATES.md`, and `AGENTS.md` (stack is no longer
|
||||
"migration in progress").
|
||||
6. **Fast-forward `pages`** per the procedure in `docs/operations-guide.md`.
|
||||
|
||||
## Rollback
|
||||
|
||||
`pages` still holds the working vanilla site until you overwrite it. If cutover
|
||||
fails, reset `pages` to its previous commit — the old site returns immediately.
|
||||
Note the SHA before you start:
|
||||
|
||||
```bash
|
||||
git rev-parse origin/pages # write it down
|
||||
```
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] Ten routes 200 on the real host with a fresh cache-buster
|
||||
- [ ] Vote widget works end-to-end from the published origin (CORS is
|
||||
origin-sensitive — `ALLOWED_ORIGIN` must still match)
|
||||
- [ ] Old files deleted; `npm run gate` green
|
||||
- [ ] Docs match reality
|
||||
- [ ] Previous `pages` SHA recorded for rollback
|
||||
Reference in New Issue
Block a user