build: migrate from npm to pnpm
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>
This commit is contained in:
@@ -6,30 +6,30 @@ merged into anything.
|
||||
|
||||
## Where the work is
|
||||
|
||||
| Branch | Head | Worktree | Gate |
|
||||
| --- | --- | --- | --- |
|
||||
| `main` | `a45aa84` | `~/Projects/ai-for-dummies` | n/a |
|
||||
| `refactor/task-01-scaffold` | `71021e6` | `~/Projects/af-task-01` | passed |
|
||||
| `refactor/task-02-tokens` | `c9ec9e3` | `~/Projects/af-task-02` | passed |
|
||||
| `refactor/task-03-verification-net` | `2e79aac` | `~/Projects/af-task-03` | passed |
|
||||
| `refactor/task-04-content-schema` | `b554f87` | `~/Projects/af-task-04` | **not run** |
|
||||
| Branch | Head | Worktree | Gate |
|
||||
| ----------------------------------- | --------- | --------------------------- | ----------- |
|
||||
| `main` | `a45aa84` | `~/Projects/ai-for-dummies` | n/a |
|
||||
| `refactor/task-01-scaffold` | `71021e6` | `~/Projects/af-task-01` | passed |
|
||||
| `refactor/task-02-tokens` | `c9ec9e3` | `~/Projects/af-task-02` | passed |
|
||||
| `refactor/task-03-verification-net` | `2e79aac` | `~/Projects/af-task-03` | passed |
|
||||
| `refactor/task-04-content-schema` | `b554f87` | `~/Projects/af-task-04` | **not run** |
|
||||
|
||||
02, 03 and 04 all branch from `refactor/task-01-scaffold`, not from `main`.
|
||||
Task 01 must merge to `main` first, then the other three.
|
||||
02, 03 and 04 all branch from `refactor/task-01-scaffold`, not from `main`. Task
|
||||
01 must merge to `main` first, then the other three.
|
||||
|
||||
## What each task actually produced
|
||||
|
||||
**01 — scaffold (Codex).** Astro 5.5 with `base: '/ai-for-dummies'`, strict TS,
|
||||
`BaseLayout.astro`, `summary.astro` as the single smoke page, lint/format/husky
|
||||
configs, `.gitea/workflows/`, rewritten publishing section in
|
||||
`docs/operations-guide.md`, `hands-on/` copied verbatim into `public/`.
|
||||
Build passes, gate passes, hooks verified live, 42/42 assertions intact.
|
||||
`docs/operations-guide.md`, `hands-on/` copied verbatim into `public/`. Build
|
||||
passes, gate passes, hooks verified live, 42/42 assertions intact.
|
||||
|
||||
**02 — tokens (Gemini).** `src/styles/tokens.css` and `src/styles/base.css`
|
||||
only — 43 lines. It did **not** touch the legacy CSS, deliberately: rewriting
|
||||
**02 — tokens (Gemini).** `src/styles/tokens.css` and `src/styles/base.css` only
|
||||
— 43 lines. It did **not** touch the legacy CSS, deliberately: rewriting
|
||||
`styles.css` would break `verify.mjs`'s exact-string assertions. So the three
|
||||
drifting palettes are now resolved *in the new token layer*, while the live
|
||||
site still runs on the old values. That is the correct scope, but it means the
|
||||
drifting palettes are now resolved _in the new token layer_, while the live site
|
||||
still runs on the old values. That is the correct scope, but it means the
|
||||
consolidation is not proven visually yet.
|
||||
|
||||
**03 — verification net (Codex).** `.agents/scripts/visual-regression.mjs`,
|
||||
@@ -38,15 +38,15 @@ rendered-text snapshots for all 10 routes, and PNG baselines at 4 widths in
|
||||
purpose — they are the regression baseline).
|
||||
|
||||
**04 — content schema (MiniMax).** `src/content/config.ts` with eight empty
|
||||
collections and a strict `localized({en, pt})` helper. No content moved; that
|
||||
is tasks 05 and 06.
|
||||
collections and a strict `localized({en, pt})` helper. No content moved; that is
|
||||
tasks 05 and 06.
|
||||
|
||||
## Things I fixed that the plan got wrong
|
||||
|
||||
- `AGENTS.md` listed `package-lock.json` under **Never touch**, meaning never
|
||||
hand-edit. Task 01 read it as never create and shipped with
|
||||
`--package-lock=false`. `npm ci` — which is how every worktree spins up —
|
||||
cannot work without it. Wording corrected; lockfile committed.
|
||||
`--package-lock=false`. `npm ci` — which is how every worktree spun up at the
|
||||
time — cannot work without it. Wording corrected; lockfile committed.
|
||||
- The first lockfile was reconstructed from a `node_modules` installed without
|
||||
one, so its entries had no `resolved`/`integrity` and `npm ci` failed with
|
||||
`ETARGET tinyglobby@0.2.17`. Regenerated from a clean install.
|
||||
@@ -62,17 +62,17 @@ is tasks 05 and 06.
|
||||
- **Task 03 went outside its brief.** It rewrote `scripts/audit-ui.mjs` to ban
|
||||
external CSS dependencies — a sound check that the pre-existing malformed
|
||||
`@font-face` in `styles.css` violates, so it left the gate red for every
|
||||
downstream task. Reverted in `2e79aac`; the snapshot net was kept. **The
|
||||
check should come back once the font decision is made.**
|
||||
- **Task 03 rebased instead of branching**, flattening task 01's merge into
|
||||
four duplicate commits with new SHAs — the same divergent-history trap that
|
||||
broke the `pages` branch. Replayed onto the proper base; task 01 is an
|
||||
ancestor again. Worth adding to `.agents/rules/git-worktrees.md`: **never
|
||||
rebase a task branch onto anything.**
|
||||
downstream task. Reverted in `2e79aac`; the snapshot net was kept. **The check
|
||||
should come back once the font decision is made.**
|
||||
- **Task 03 rebased instead of branching**, flattening task 01's merge into four
|
||||
duplicate commits with new SHAs — the same divergent-history trap that broke
|
||||
the `pages` branch. Replayed onto the proper base; task 01 is an ancestor
|
||||
again. Worth adding to `.agents/rules/git-worktrees.md`: **never rebase a task
|
||||
branch onto anything.**
|
||||
- **Task 02 left 29 MB of screenshots in `~/Projects/af-task-02/before/`** —
|
||||
untracked, and in the wrong place (`.agents/snapshots/` is the right one).
|
||||
Its report claims the screenshot box is unticked while the files exist.
|
||||
Delete them or move them; do not commit them where they are.
|
||||
untracked, and in the wrong place (`.agents/snapshots/` is the right one). Its
|
||||
report claims the screenshot box is unticked while the files exist. Delete
|
||||
them or move them; do not commit them where they are.
|
||||
|
||||
## Still open from task 01's own report
|
||||
|
||||
@@ -84,15 +84,16 @@ is tasks 05 and 06.
|
||||
## The decision that is still yours
|
||||
|
||||
`styles.css:1` has an `@font-face` whose `src:` points at a Google Fonts
|
||||
*stylesheet*, not a font file. Manrope and DM Mono have therefore never
|
||||
_stylesheet_, not a font file. Manrope and DM Mono have therefore never
|
||||
rendered; the site has always been Arial and generic monospace. Self-hosting
|
||||
them during the migration would silently redesign the site. Task 02 defaulted
|
||||
to matching what renders today. Decide explicitly, then task 19 can restore the
|
||||
them during the migration would silently redesign the site. Task 02 defaulted to
|
||||
matching what renders today. Decide explicitly, then task 19 can restore the
|
||||
external-CSS assertion. See `.agents/context/design-system.md`.
|
||||
|
||||
## Next steps, in order
|
||||
|
||||
1. Verify task 04: `cd ~/Projects/af-task-04 && npm ci --prefer-offline && npm run gate`
|
||||
1. Verify task 04:
|
||||
`cd ~/Projects/af-task-04 && pnpm install --frozen-lockfile && pnpm run gate`
|
||||
2. Review the four diffs against `.agents/checklists/before-merge.md`. Use a
|
||||
different model than the one that wrote each — `MODEL-ROUTING.md` says never
|
||||
review with the author.
|
||||
@@ -112,9 +113,9 @@ external-CSS assertion. See `.agents/context/design-system.md`.
|
||||
`.agents/scripts/launch.sh <nn> <slug> [--base ref] [--cli codex|agy|mm] [--fg]`
|
||||
|
||||
Routing is automatic: Codex for 01/03/15/16/19, `agy` (Gemini 3.1 Pro) for
|
||||
02/18, `mm` (Claude Code against MiniMax-M3) for the rest. All three launch
|
||||
with permission prompts disabled, because a blocked edit in an unattended run
|
||||
just hangs. Logs land in `.agents/logs/` (gitignored).
|
||||
02/18, `mm` (Claude Code against MiniMax-M3) for the rest. All three launch with
|
||||
permission prompts disabled, because a blocked edit in an unattended run just
|
||||
hangs. Logs land in `.agents/logs/` (gitignored).
|
||||
|
||||
**Task 07 is the routing calibration point.** It is small and easy to judge.
|
||||
Check it before committing to MiniMax for the other twelve.
|
||||
|
||||
Reference in New Issue
Block a user