Merge branch 'refactor/task-21-batch1-corrections'
verify-and-publish / gate (push) Waiting to run
verify-and-publish / publish (push) Blocked by required conditions

Conflicts kept main's current 89/84-floor wording, took task-21's
var(--red) focus ring and visual-regression capture docs. Also resolves
conflict markers committed in .agents/context/architecture.md by the
task-49 merge, and adds the /films/ and /lab/ routes there.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-06 14:08:18 -03:00
7 changed files with 65 additions and 106 deletions
+3 -37
View File
@@ -2,42 +2,7 @@
## Current (Astro, static output)
<<<<<<< HEAD
Thirteen routes, one `src/pages/` entry each, built to `dist/`:
| Route | Source | Islands |
| ----------------------- | ------------------------------------------------ | ----------------------------------------------- |
| `/` | `src/pages/index.astro` | — |
| `/full-guide/` | `src/pages/full-guide.astro` | `GuideSelector`, `LanguageToggle`, `CopyPrompt` |
| `/summary/` | `src/pages/summary.astro` | — |
| `/models/` | `src/pages/models.astro` | — |
| `/agents/` | `src/pages/agents.astro` | — |
| `/skills/` | `src/pages/skills.astro` | `SkillPackageExplorer` |
| `/rules/` | `src/pages/rules.astro` | `RulesInteractive` |
| `/rag/` | `src/pages/rag.astro` | `RagWorkbench` |
| `/docs/references/rag/` | `src/pages/docs/references/rag.astro` | — |
| `/skills-review/` | `src/pages/skills-review.astro` | `legacy/skills-review/app.js` |
| `/hands-on/starter/` | `public/` lab fixture | own |
| `/hands-on/rules/` | `public/` lab fixture | own |
| `/404/` | `src/pages/404.astro` (built to `dist/404.html`) | — |
Twelve routes, one `src/pages/` entry each, built to `dist/`:
| Route | Page | Islands |
| ----------------------- | ------------------------------------- | ----------------------------------------------- |
| `/` | `src/pages/index.astro` | — |
| `/full-guide/` | `src/pages/full-guide.astro` | `GuideSelector`, `LanguageToggle`, `CopyPrompt` |
| `/summary/` | `src/pages/summary.astro` | — |
| `/models/` | `src/pages/models.astro` | — |
| `/agents/` | `src/pages/agents.astro` | — |
| `/skills/` | `src/pages/skills.astro` | `SkillPackageExplorer` |
| `/rules/` | `src/pages/rules.astro` | `RulesInteractive` |
| `/skills-review/` | `src/pages/skills-review.astro` | `legacy/skills-review/app.js` |
| `/rag/` | `src/pages/rag.astro` | `RagWorkbench` |
| `/docs/references/rag/` | `src/pages/docs/references/rag.astro` | — |
| `/hands-on/starter/` | `public/` lab fixture | own |
| `/hands-on/rules/` | `public/` lab fixture | own |
=======
Eleven source routes under `src/pages/`, two lab fixtures copied verbatim from
Thirteen source routes under `src/pages/`, two lab fixtures copied verbatim from
`public/`, and a not-found fallback. Built to `dist/` by `pnpm run build`:
| Route | Page | Islands / runtime |
@@ -52,6 +17,8 @@ Eleven source routes under `src/pages/`, two lab fixtures copied verbatim from
| `/skills-review/` | `src/pages/skills-review.astro` | `legacy/skills-review/app.js` (lazy-loaded since T36) |
| `/rag/` | `src/pages/rag.astro` | `RagWorkbench` island |
| `/docs/references/rag/` | `src/pages/docs/references/rag.astro` | — (sources listing) |
| `/films/` | `src/pages/films.astro` | `FilmPlayer` (clips in `public/videos/`) |
| `/lab/` | `src/pages/lab.astro` | `ModelLab` island + `ModelLab.worker.ts`, `FilmPlayer` |
| `/404/` | `src/pages/404.astro` | — |
| `/hands-on/starter/` | `public/hands-on/starter/` lab fixture | own (vanilla HTML/CSS/JS — shipped untouched) |
| `/hands-on/rules/` | `public/hands-on/rules/` lab fixture | own |
@@ -76,7 +43,6 @@ skills) all appear in `dist/sitemap-0.xml` — see
path. `verify.mjs` does not assert its content — it is purely a visitor-facing
fallback, and the page uses `BaseLayout` rather than `ChapterLayout` on purpose
(no slot machinery, no chapter chrome).
>>>>>>> refactor/task-49-context-update
## What is still unmigrated
-1
View File
@@ -32,7 +32,6 @@ The real gate:
```
astro check types
astro build it compiles
verify.mjs 89 content assertions — count must not fall
verify.mjs 89 content assertions (84 floor enforced by gate.sh) — count must not fall
audit-ui.mjs no external runtime dependencies
check-tokens.mjs full sweep
+1 -1
View File
@@ -74,7 +74,7 @@ Rules that bite most often here:
## Prove it
1. Render it at 560 / 800 / 1100 / 1600 px.
2. Tab to it. Focus ring visible (`outline: 3px solid #a7483f`).
2. Tab to it. Focus ring visible (`outline: 3px solid var(--red)`).
3. Diff its rendered text against the markup it replaced (use
`node .agents/scripts/snapshot-route.mjs`).
4. Run
@@ -1,20 +1,28 @@
# Interview source map
# Interview source map (ai-for-dummies)
This map records the implementation inspected for the rules case study.
Reconfirm paths when the source repository changes.
Paths confirmed against this repository on 2026-09-06. The map below is the
worked example; if the project layout shifts, reconcile this file in the same
commit that shifts the layout.
| Concern | Source | Role |
| ------------------------ | ----------------------------------- | ------------------------------------------------------------------------------ |
| Shared context | `AGENTS.md` | Stack, commands, product shape, conventions, and verification expectations. |
| Reusable procedures | `.agents/skills/` | Focused workflows such as gates, frontend, Go API, repo DB, and skill writing. |
| Machine-readable routing | `.agents/db/commands.json` | Canonical checks and code-generation commands. |
| UI enforcement | `scripts/check-ui-contract.mjs` | Ratchet for buttons, catches, headings, colors, and duplicate components. |
| Ratchet state | `scripts/ui-contract-baseline.json` | Baseline counts that new violations cannot exceed. |
| Commit boundary | `.husky/pre-commit` | Runs lint-staged and the UI contract check. |
| Commit message boundary | `.husky/commit-msg` | Runs commitlint. |
| Staged-file tools | `.lintstagedrc.cjs` | Biome, ESLint, Prettier, and Buf formatting by file type. |
| Independent review | `.pr-review.json` | Review focus, exclusions, security constraints, and test expectations. |
| Agent roles | `.claude/agents/` | Prior-art scout, scoped implementer, and verifier responsibilities. |
| Concern | Source | Role |
| ----------------------- | ---------------------------------------------------- | ---------------------------------------------------------------------------------- |
| Shared context | `AGENTS.md` | Stack, commands, product shape, conventions, and verification expectations. |
| Reusable procedures | `.agents/skills/` | On-demand workflows (gates, page migration, motion, design tokens, translation). |
| Specialist agents | `.agents/agents/` | One role per file; `reviewer` is the merge gate. |
| Authoritative rule book | `.agents/rules/` + `.agents/context/` | Binding constraints and the facts they assume. Context wins when they disagree. |
| Quality gate script | `.agents/scripts/gate.sh` | Canonical checks; run by `pre-push`. Reads the assertion ledger. |
| Token enforcement | `.agents/scripts/check-tokens.mjs` | Raw-hex / raw-px ratchet across `src/**`. Lists every `token-gap:` waiver. |
| Translation enforcement | `.agents/scripts/audit-translations.mjs` | Flags identical `en`/`pt` pairs and missing mirrors. Wired into `pnpm run verify`. |
| UI / no-external-deps | `scripts/audit-ui.mjs` | Every page has a viewport meta; no external `<script>`/`<link>`. |
| Assertion ledger | `.agents/context/assertion-removals.md` | A removal is only allowed by adding an entry here. The gate counts `## ` headings. |
| Tier 1 boundary | `.husky/pre-commit` | Runs `lint-staged` (Prettier, ESLint, Stylelint, `check-tokens.mjs`). |
| Tier 1 config | `.lintstagedrc.json` | File-glob → command mapping for staged files. |
| Tier 2 boundary | `.husky/pre-push` | Runs `gate.sh`; queues behind `.git/af-gate.lock` for parallel agents. |
| Commit message boundary | `.husky/commit-msg` | Conventional Commits regex (`feat | fix | docs | refactor | ...`); subject ≤ 72 chars. |
| Tier 3 boundary | `.gitea/workflows/verify.yml` | CI re-runs tier 2 against a clean install. |
| Rendered-text baselines | `.agents/snapshots/*.txt` + `snapshot-route.mjs` | DOM-text regression net for page migrations. |
| Published site | `pages` branch (build output of `main`) | Force-pushed by `.agents/scripts/publish-pages.sh` after a clean `gate.sh` run. |
| Publishing contract | `docs/operations-guide.md` + `context/publishing.md` | How a push becomes a live URL; bypass with `AF_NO_PUBLISH=1`. |
The source of truth is the repository. This table is a teaching map, not a
replacement for reading the files.
The source of truth is the repository. This table is a teaching map for the case
study, not a substitute for reading the files it points at.
+2 -2
View File
@@ -14,8 +14,8 @@ Read [`../../context/verification.md`](../../context/verification.md) first.
`verify.mjs` carries **89 assertions** with an **84-floor** that `gate.sh`
enforces (`.agents/scripts/gate.sh:75`). They are the only thing preventing
silent content loss during a refactor, and they break as paths and
architectures move.
silent content loss during a refactor, and they break as paths and architectures
move.
## The rule
+33 -48
View File
@@ -11,53 +11,32 @@ description:
## Capture
The repo lists `playwright` as a devDependency in `package.json`; write the
screenshot script as a small Playwright runner checked into the project (or
extend `.agents/scripts/visual-regression.mjs` if the change is broad enough).
Do not promote `scripts/inspect.py` — it is untracked local scratch per
`.agents/rules/git-worktrees.md` and must not be discovered and committed
through a visual-regression sweep.
The repo already has a capture script (`.agents/scripts/visual-regression.mjs`).
It uses Playwright under Node (not Python) and writes PNGs to
`.agents/snapshots/before/`. Extend it rather than inventing a new capture path.
```js
// .agents/scripts/visual-regression.mjs style — keep the route list in sync
// with src/pages/** and the widths in .agents/rules/theming.md.
import { chromium } from 'playwright';
```bash
# default: capture every route at 560 / 800 / 1100 / 1600 px
node .agents/scripts/visual-regression.mjs
const ROUTES = [
'/',
'/full-guide/',
'/summary/',
'/models/',
'/agents/',
'/skills/',
'/rules/',
'/skills-review/',
'/hands-on/starter/',
'/hands-on/rules/',
];
const WIDTHS = [560, 800, 1100, 1600];
# capture against a preview server (the script's default base is :4173)
pnpm run preview & # serves the Astro build
VISUAL_BASE_URL=http://localhost:4321 node .agents/scripts/visual-regression.mjs
const browser = await chromium.launch();
for (const route of ROUTES) {
for (const w of WIDTHS) {
const ctx = await browser.newContext({
viewport: { width: w, height: 900 },
});
const page = await ctx.newPage();
await page.goto(`${BASE}${route}`, { waitUntil: 'networkidle' });
await page.screenshot({
path: `${OUT}/${route.replace(/^\/|\/$/g, '').replace(/\//g, '_') || 'index'}-${w}.png`,
fullPage: true,
});
await ctx.close();
}
}
await browser.close();
# add a reduced-motion pass — animations must land in their end state
node .agents/scripts/visual-regression.mjs --reduced-motion
```
Run once against `pnpm run preview`. To compare against the hand-written
pre-cutover site, serve a worktree of `pages-backup-2026-09-06` on :4173 first —
those files are no longer on `main`. Keep both sets.
`playwright` is in `devDependencies` but its browser binaries are not installed
by default. First run only:
```bash
pnpm exec playwright install chromium
```
To compare against a legacy site that no longer ships on `main`, serve it from a
pre-cutover worktree on a second port (e.g. :4174) and point the script at it
with `VISUAL_BASE_URL`. Keep both sets — before and after — for the task report.
## Compare
@@ -71,16 +50,22 @@ done
Pixel-exact is not the bar — antialiasing differs. Judge by eye where the metric
is non-trivial, and attach the pair to the task report.
## The three widths that catch the most
## The widths that catch the most
- **560px** — where the 16 ad-hoc breakpoints collapse to `--bp-sm`. Highest
risk in the whole migration.
- **800px** — the most common existing breakpoint; layout flips here.
The capture script writes at **560 / 800 / 1100 / 1600** px. The token-layer
gate (`check-tokens.mjs`) recognises **560 / 800 / 1100 / 1600 / 2200** px as
the consolidated breakpoint set — 2200 has no baseline screenshot yet. Pay
closest attention to:
- **560px** — smallest tier; the place layout grids are most likely to break.
- **800px** — the most common breakpoint in legacy CSS; layout flips here.
- **1600px** — `min-width` rules that only fire on large screens are the ones
nobody notices are broken.
Also screenshot at the **old** breakpoint values you removed (520, 530, 600,
620, 720, 850, 880, 900), not just the new ones. Regressions hide exactly there.
Also screenshot at any **legacy** breakpoint values you removed (520, 530, 600,
620, 720, 850, 880, 900, etc.), not just the new ones. Regressions hide exactly
there. To do this without editing the script, run Playwright directly with an
extra `viewport.width` of your own and reuse the same naming.
## What a real difference looks like
+1
View File
@@ -0,0 +1 @@
../.agents/agents