Three strands of work on the chapter surface, all reading from the same
constraint: this site ships no runtime dependencies, so every effect below
is native CSS or an .astro component.
Motion (src/styles/motion.css, DrawRule.astro). A scroll-driven layer of
reveals, hero parallax, section depth, and a hairline that paints itself
along its path, scrubbed by `animation-timeline: view()` — 0KB against
lottie-web's ~60KB gzipped on the main thread. Every scrubbed rule sits
inside `prefers-reduced-motion: no-preference` and `@supports`, so a
Firefox reader or an opted-out one gets the complete static page rather
than one with holes in it. Ranges key to `cover 40%`-`cover 75%` where the
motion is meant to be watched: `view()` ranges key to first visibility,
which on a 2600px page is long before anyone is reading the section.
`.agents/skills/motion/references/scroll-driven.md` records the technique
and the two ways `pathLength` normalisation was broken while building it.
Diagrams (StepFlow.astro, WorktreeMap.astro). The `.steps` stack on
/skills/, /models/, and /agents/ becomes a numbered flow with connectors,
and /agents/ grows the worktree map it was describing in prose — reusing
the `trees` collection rather than a second set of strings. The map's
static variant is gated one class deeper than full-guide's page styles, so
the interactive copy renders byte-identical. Connectors are pseudo-elements,
not SVG: a stretched path desynchronises its own dash pattern, and a
straight line does not need one. Mermaid was considered and rejected at
~1MB of runtime.
Retrieval practice (/rules/, /skills/). A "check yourself" section of
native `<details>` question/answer pairs plus a citation row, both bilingual
through the existing `data-copy` toggle, and both JavaScript-free.
Two audit blind spots surfaced and are closed rather than worked around:
`build.inlineStylesheets: 'never'`, because Astro inlined sheets under ~4kB
and audit-ui.mjs reads its colour and size baseline from dist/_astro/*.css;
and `--columns` declared in the grid components, because an element-level
custom property is not a declaration the audit can resolve.
legacy/styles/skills.css is renamed and imported for its side effect. Inside
a *page*, `?url` resolves to that page's own CSS chunk whatever file it
names, so the link pointed at the wrong asset and the sheet was emitted but
never loaded — the package preview had been rendering unstyled and
overflowing since the Astro cutover.
verify.mjs gains 5 assertions for the recall sections and their Portuguese
copy: 89 now, against the 84 baseline.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The repository had two skill directories. `skills/` held the four written
for this project; `.agents/skills/` held the ones the agent context refers
to. Nothing said which an agent should read, and `.agents/ORCHESTRATOR.md`
only ever pointed at the second.
Move the first four into `.agents/skills/` so there is one location, and
add the vendored packages this chapter work used: `animation-vocabulary`
and `improve-animations` (emilkowalski/skills), `teach` (mattpocock/skills),
plus a local `translation` skill and `audit-translations.mjs` for the EN/PT
pairs.
`skills-lock.json` pins the vendored three by source and content hash, so a
later re-vendor is a diff rather than a guess. `.claude/skills/` is
symlinks into `.agents/skills/`, which is what makes them loadable here
without a second copy on disk.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Deletes the pre-Astro pages, scripts, and stylesheets that the migration
replaced, and moves the ones it did not replace out of the way.
Deleted (32 files): app.js, responsive.css, landing.css, rules/app.js,
rules/styles.css, skills/app.js, the ten route index.html files, and the
root hands-on/ copy, which is byte-identical to public/hands-on/ -- the
one the build actually ships.
Moved to legacy/ (12 files): styles.css, full-guide/audit.css,
chapters.css, skills/styles.css, skills-review/styles.css,
skills-review/change-lens.css, and the skills-review/app.js module graph.
These are not dead. The Astro pages import them and the build fails
without them, which the plan had not accounted for. They go to legacy/
rather than src/ because check-tokens.mjs sweeps src, and these files are
full of raw hex and unnamed breakpoints: moving one into src/ should mean
migrating it to tokens in the same change, not adding a scan exclusion.
The prettier, stylelint, and eslint ignore lists that already named these
files at their old paths now name legacy/ instead.
verify.mjs no longer reads app.js. The 102 Portuguese strings were
extracted from its translations.pt object before deletion into
.agents/snapshots/full-guide-pt.json -- a legacy capture, not a snapshot
of the Astro build, so the assertion still compares against an
independent source. The brace-matching helper's assertion is replaced by
one that rejects an empty snapshot entry, without which trimming the
snapshot would make the presence check pass vacuously. Count stays at 84.
audit-ui.mjs reads the ten pages from dist/ and resolves Astro's
base-absolute hrefs against it.
Before deleting anything, rendered-text-diff was run across all ten
routes plus both Portuguese pages: every one at parity, 0 missing and 0
extra. That comparison is not repeatable once the legacy files are gone.
computed-style-diff on /full-guide/ stays at 32 differences, so the moves
are style-neutral.
Docs updated to match: README, AGENTS.md, GATES.md, the architecture
context, the operations guide's lab instructions, and the three skills
that told you to serve the vanilla site.
Publishing is not part of this commit.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Ten git worktrees each carried their own 225 MB node_modules (1.1 GB across
five) and paid 11s per `npm ci`. pnpm hardlinks from a shared store: the same
five worktrees cost ~250 MB total, and a fresh install is 4s.
What changed beyond the mechanical rename:
- `overrides` moved to `pnpm-workspace.yaml`. pnpm 11 does not read the `pnpm`
field in package.json *or* npm's top-level `overrides`, and it fails silently
— the vite/defu/language-server pins would have quietly stopped applying.
- Build scripts are blocked by default in pnpm; esbuild and sharp are allowed
explicitly via `allowBuilds` (renamed from `onlyBuiltDependencies` in 11).
- `packageManager` + `engines` pin the toolchain.
- gate.sh rejects a package-lock.json/yarn.lock/bun.lock outright, so an agent
running `npm install` out of habit fails loudly instead of building a second,
divergent dependency tree.
- CI bootstraps pnpm with `npm install --global pnpm@11.25.0` rather than
corepack (unbundled as of Node 25) or pnpm/action-setup (this self-hosted
act-runner has never run a job; fetching a third-party action is not
something to discover on the first one).
Two pre-existing CI bugs fixed while in the file:
- the gate installed with `npm install --package-lock=false`, which discarded
the lockfile the previous session had just fixed.
- the visual-regression step imported `playwright`, which is not a dependency,
and `visual-regression.mjs` has no compare mode anyway — in CI it overwrote
its own baselines and passed unconditionally. Removed with a comment; it
comes back when it can diff.
The `publish` job is now manual (`workflow_dispatch`). During the migration
dist/ holds three HTML files against the live pages branch's ten, so publishing
on every push to main would take the site down to a stub. Restore at task 20.
HANDOVER.md's incident log still says npm where it describes what happened at
the time; that is history, not a missed rename.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
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>