From 48c31dc1b3ddd1813264dc704501e476597ef0fc Mon Sep 17 00:00:00 2001 From: Marcos Paulo Date: Sat, 5 Sep 2026 04:29:42 +0000 Subject: [PATCH] build: migrate from npm to pnpm MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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 --- .agents/ORCHESTRATOR.md | 34 +- .agents/agents/astro-architect.md | 24 +- .agents/agents/component-builder.md | 7 +- .agents/agents/content-i18n-migrator.md | 29 +- .agents/agents/design-system-keeper.md | 13 +- .agents/agents/page-migrator.md | 12 +- .agents/agents/verification-engineer.md | 11 +- .agents/checklists/before-component.md | 11 +- .agents/checklists/before-merge.md | 8 +- .agents/checklists/before-page.md | 20 +- .agents/context/publishing.md | 15 +- .agents/context/verification.md | 16 +- .agents/rules/gates.md | 26 +- .agents/rules/git-worktrees.md | 26 +- .agents/rules/theming.md | 31 +- .agents/scripts/check-tokens.mjs | 38 +- .agents/scripts/gate.sh | 17 +- .agents/scripts/launch.sh | 6 +- .agents/scripts/verify-hooks.sh | 4 +- .agents/scripts/visual-regression.mjs | 2 +- .agents/scripts/worktree.sh | 2 +- .agents/skills/astro-component/SKILL.md | 23 +- .agents/skills/astro-page/SKILL.md | 14 +- .agents/skills/design-tokens/SKILL.md | 12 +- .agents/skills/visual-regression/SKILL.md | 18 +- .gitea/workflows/verify.yml | 45 +- .gitignore | 7 + .husky/pre-commit | 4 +- .prettierignore | 1 + AGENTS.md | 66 +- README.md | 76 +- docs/operations-guide.md | 14 +- package-lock.json | 9205 ----------------- package.json | 8 +- plans/astro-refactor/HANDOVER.md | 73 +- plans/astro-refactor/README.md | 80 +- plans/astro-refactor/task-01-scaffold.md | 32 +- .../task-03-verification-net.md | 19 +- plans/astro-refactor/task-07-primitives.md | 8 +- plans/astro-refactor/task-08-route-cards.md | 11 +- .../astro-refactor/task-09-chapter-blocks.md | 12 +- plans/astro-refactor/task-10-guide-blocks.md | 11 +- plans/astro-refactor/task-11-review-blocks.md | 8 +- plans/astro-refactor/task-12-page-landing.md | 8 +- plans/astro-refactor/task-13-page-chapters.md | 8 +- plans/astro-refactor/task-14-page-rules.md | 10 +- .../astro-refactor/task-15-page-full-guide.md | 30 +- .../task-16-page-review-desk.md | 15 +- plans/astro-refactor/task-18-motion.md | 9 +- .../astro-refactor/task-19-verify-repoint.md | 25 +- plans/astro-refactor/task-20-cutover.md | 13 +- pnpm-lock.yaml | 5366 ++++++++++ pnpm-workspace.yaml | 17 + 53 files changed, 5958 insertions(+), 9642 deletions(-) delete mode 100644 package-lock.json create mode 100644 pnpm-lock.yaml create mode 100644 pnpm-workspace.yaml diff --git a/.agents/ORCHESTRATOR.md b/.agents/ORCHESTRATOR.md index 5bf9f62..a358041 100644 --- a/.agents/ORCHESTRATOR.md +++ b/.agents/ORCHESTRATOR.md @@ -21,28 +21,30 @@ reality won — update the rule and say so. ## Specialists -Each agent has one responsibility, one set of rules, and its own worktree. -Full definitions in [`agents/`](agents/). +Each agent has one responsibility, one set of rules, and its own worktree. Full +definitions in [`agents/`](agents/). -| Agent | Owns | Loads skills | -| --- | --- | --- | -| [`astro-architect`](agents/astro-architect.md) | project scaffold, config, routing, layouts | `astro-page` | -| [`design-system-keeper`](agents/design-system-keeper.md) | tokens, the single palette, type scale | `design-tokens` | -| [`component-builder`](agents/component-builder.md) | one component per task, from templates | `astro-component`, `design-tokens` | -| [`page-migrator`](agents/page-migrator.md) | one page per task, HTML → `.astro` | `astro-page`, `content-migration` | -| [`motion-designer`](agents/motion-designer.md) | transitions, islands with animation | `motion` | -| [`content-i18n-migrator`](agents/content-i18n-migrator.md) | strings out of `app.js` into content collections | `content-migration` | +| Agent | Owns | Loads skills | +| ---------------------------------------------------------- | --------------------------------------------------- | -------------------------------------- | +| [`astro-architect`](agents/astro-architect.md) | project scaffold, config, routing, layouts | `astro-page` | +| [`design-system-keeper`](agents/design-system-keeper.md) | tokens, the single palette, type scale | `design-tokens` | +| [`component-builder`](agents/component-builder.md) | one component per task, from templates | `astro-component`, `design-tokens` | +| [`page-migrator`](agents/page-migrator.md) | one page per task, HTML → `.astro` | `astro-page`, `content-migration` | +| [`motion-designer`](agents/motion-designer.md) | transitions, islands with animation | `motion` | +| [`content-i18n-migrator`](agents/content-i18n-migrator.md) | strings out of `app.js` into content collections | `content-migration` | | [`verification-engineer`](agents/verification-engineer.md) | keeping `verify.mjs` meaningful across the refactor | `verify-contract`, `visual-regression` | -| [`reviewer`](agents/reviewer.md) | merge gate; reads diffs, never writes features | all | +| [`reviewer`](agents/reviewer.md) | merge gate; reads diffs, never writes features | all | ## Working agreement -1. **One task, one worktree, one agent.** See [`rules/git-worktrees.md`](rules/git-worktrees.md). -2. **Read `context/` first.** Especially `design-system.md` and `verification.md`. - Most wrong answers here come from assuming the CSS is already coherent. +1. **One task, one worktree, one agent.** See + [`rules/git-worktrees.md`](rules/git-worktrees.md). +2. **Read `context/` first.** Especially `design-system.md` and + `verification.md`. Most wrong answers here come from assuming the CSS is + already coherent. 3. **Templates over invention.** `templates/components/` and `templates/pages/` exist so ten parallel agents produce one house style, not ten. -4. **The gate is `npm run verify` plus the relevant checklist.** Green tests +4. **The gate is `pnpm run verify` plus the relevant checklist.** Green tests with deleted assertions is a failed task. 5. **Report what you did not do.** Partial work with an honest boundary is useful; silent narrowing is not. @@ -58,7 +60,7 @@ agent loads .agents/agents/.md + its skills ↓ checklists/before-*.md ← self-gate ↓ -npm run verify ← hard gate +pnpm run verify ← hard gate ↓ reviewer agent on the diff ← merge gate ``` diff --git a/.agents/agents/astro-architect.md b/.agents/agents/astro-architect.md index d6a2c08..f88c4c1 100644 --- a/.agents/agents/astro-architect.md +++ b/.agents/agents/astro-architect.md @@ -1,14 +1,18 @@ --- name: astro-architect -description: Owns the Astro scaffold — config, routing, layouts, build pipeline, and the publishing decision. Use for task 01 and any later change to astro.config.mjs, package.json, or the deploy path. Do not use for component or page work. +description: + Owns the Astro scaffold — config, routing, layouts, build pipeline, and the + publishing decision. Use for task 01 and any later change to astro.config.mjs, + package.json, or the deploy path. Do not use for component or page work. tools: Read, Write, Edit, Bash, Grep, Glob --- -You own the foundation. Everything other agents build sits on your decisions, -so wrong choices here are expensive and late-discovered. +You own the foundation. Everything other agents build sits on your decisions, so +wrong choices here are expensive and late-discovered. -**Read first**: `.agents/context/architecture.md`, `.agents/context/publishing.md`, -`.agents/rules/astro.md`. **Load skill**: `astro-page`. +**Read first**: `.agents/context/architecture.md`, +`.agents/context/publishing.md`, `.agents/rules/astro.md`. **Load skill**: +`astro-page`. ## You own @@ -19,11 +23,13 @@ writer of these. Other agents report problems with them; they do not edit. ## Non-negotiable outcomes - `base: '/ai-for-dummies'` set and **verified against the real host**, not just - `npm run preview`. Base-path bugs are the most likely production-only failure. + `pnpm run preview`. Base-path bugs are the most likely production-only + failure. - Every existing URL resolves identically, trailing slash included. - Zero JS by default. Astro ships none unless a component asks. - `hands-on/starter/` and `hands-on/rules/` copied to `public/` **verbatim, - unprocessed**. They are lab fixtures; the exercise is that they are plain files. + unprocessed**. They are lab fixtures; the exercise is that they are plain + files. - No UI framework, no CSS framework, no runtime dependencies. ## The publishing decision is yours to make and document @@ -39,6 +45,6 @@ pod restart silently kills CI. Put that in the runbook. ## Done when -`npm run build` succeeds, one migrated page serves correctly from the real host -under `/ai-for-dummies/`, `npm run verify` and `node scripts/audit-ui.mjs` are +`pnpm run build` succeeds, one migrated page serves correctly from the real host +under `/ai-for-dummies/`, `pnpm run verify` and `node scripts/audit-ui.mjs` are green, and the operations guide matches reality. diff --git a/.agents/agents/component-builder.md b/.agents/agents/component-builder.md index 6bdc1ee..c8151e7 100644 --- a/.agents/agents/component-builder.md +++ b/.agents/agents/component-builder.md @@ -1,6 +1,9 @@ --- name: component-builder -description: Builds one Astro component per task from the project templates. Use for the component-extraction tasks (05-09). Do not use for page migration, token changes, or verify.mjs. +description: + Builds one Astro component per task from the project templates. Use for the + component-extraction tasks (05-09). Do not use for page migration, token + changes, or verify.mjs. tools: Read, Write, Edit, Bash, Grep, Glob --- @@ -34,4 +37,4 @@ You may not edit `tokens.css`, `verify.mjs`, `astro.config.mjs`, or `.agents/checklists/before-component.md` is fully checked, rendered text diffs clean against the markup you replaced, screenshots at four widths look -unchanged, and `npm run verify` is green **with no assertion deleted**. +unchanged, and `pnpm run verify` is green **with no assertion deleted**. diff --git a/.agents/agents/content-i18n-migrator.md b/.agents/agents/content-i18n-migrator.md index 6084d02..067e040 100644 --- a/.agents/agents/content-i18n-migrator.md +++ b/.agents/agents/content-i18n-migrator.md @@ -1,19 +1,23 @@ --- name: content-i18n-migrator -description: Moves bilingual copy out of app.js and catalog.js into typed Astro content collections without altering a string. Use for tasks 03-04 and any later content relocation. Do not use for markup or styling. +description: + Moves bilingual copy out of app.js and catalog.js into typed Astro content + collections without altering a string. Use for tasks 03-04 and any later + content relocation. Do not use for markup or styling. tools: Read, Write, Edit, Bash, Grep, Glob --- You own `src/content/` and `src/content/config.ts`, and you are their only writer. Your job is a lossless move, not an edit. -**Read first**: `.agents/rules/content-i18n.md`. **Load skill**: `content-migration`. +**Read first**: `.agents/rules/content-i18n.md`. **Load skill**: +`content-migration`. ## What you are moving ~50 `{ en, pt }` keys from `app.js` (`phases`, `handsOnPrompts`, `modelGuide`, -`skillSources`, `skillInstallPrompts`), plus 24 review entries from -`catalog.js` and `submitted-catalog.js`. +`skillSources`, `skillInstallPrompts`), plus 24 review entries from `catalog.js` +and `submitted-catalog.js`. These are hand-written translations with deliberate tone. **Copy them mechanically. Never retype.** Retyping introduces drift nobody notices until a @@ -21,9 +25,9 @@ Portuguese speaker does. ## Procedure -Extract → write into collection → diff extracted-before against -extracted-after → only then delete the source. If the diff is not empty, you -changed content. Fix it before continuing. +Extract → write into collection → diff extracted-before against extracted-after +→ only then delete the source. If the diff is not empty, you changed content. +Fix it before continuing. Both locales required in the schema. A missing `pt` must be a **build error**, never a silent English fallback — that is how bilingual sites quietly become @@ -35,11 +39,12 @@ monolingual. `scripts/build-skill-review.mjs` and the output is **committed**. Move `catalog.js` and the generator keeps running against nothing — silently. Either re-point it or replace it, and update `package.json`, `README.md`, -`docs/operations-guide.md`, and the review desk footer, all of which reference it. +`docs/operations-guide.md`, and the review desk footer, all of which reference +it. -Also: the review desk's diff view compares original and improved **source text**. -If you convert `improved` to rendered Markdown, keep the raw string available or -the diff view breaks. +Also: the review desk's diff view compares original and improved **source +text**. If you convert `improved` to rendered Markdown, keep the raw string +available or the diff view breaks. ## The language-switching decision @@ -50,4 +55,4 @@ a decision, record it. Either way `` tracks the active language. ## Done when The string diff is empty, both locales validate, the generator still produces -identical output, and `npm run verify` is green. +identical output, and `pnpm run verify` is green. diff --git a/.agents/agents/design-system-keeper.md b/.agents/agents/design-system-keeper.md index 6b734f3..959beaa 100644 --- a/.agents/agents/design-system-keeper.md +++ b/.agents/agents/design-system-keeper.md @@ -1,6 +1,9 @@ --- name: design-system-keeper -description: Owns src/styles/tokens.css — the palette, type scale, and breakpoints. Use for task 02 and any later token change or check-tokens failure. Do not use for building components. +description: + Owns src/styles/tokens.css — the palette, type scale, and breakpoints. Use for + task 02 and any later token change or check-tokens failure. Do not use for + building components. tools: Read, Write, Edit, Bash, Grep, Glob --- @@ -18,7 +21,7 @@ palettes and a broken `@font-face`. **Load skills**: `design-tokens`, sub-perceptual and can be canonicalized. `--blue` (`#527f9f` vs `#215675`) is visibly different — screenshot both and get a human decision. 2. **The fonts have never rendered.** The `@font-face` in `styles.css:1` points - `src:` at a Google Fonts *stylesheet*, so Manrope and DM Mono have always + `src:` at a Google Fonts _stylesheet_, so Manrope and DM Mono have always fallen back to Arial and generic monospace. Self-hosting them is a redesign, not a refactor. Default: delete the dead rule, declare the stacks that actually render. Escalate if someone wants the real fonts. @@ -28,9 +31,9 @@ palettes and a broken `@font-face`. **Load skills**: `design-tokens`, `src/styles/tokens.css`, `src/styles/base.css`, and `.agents/scripts/check-tokens.mjs`. -Deliver: one value per token, a named type scale (`--step-*`) replacing 14 ad-hoc -`clamp()` triples, five named breakpoints replacing sixteen, and an enforcement -script wired into `npm run verify`. +Deliver: one value per token, a named type scale (`--step-*`) replacing 14 +ad-hoc `clamp()` triples, five named breakpoints replacing sixteen, and an +enforcement script wired into `pnpm run verify`. ## Preserve the house style diff --git a/.agents/agents/page-migrator.md b/.agents/agents/page-migrator.md index 0c11d4d..a23c5bf 100644 --- a/.agents/agents/page-migrator.md +++ b/.agents/agents/page-migrator.md @@ -1,13 +1,17 @@ --- name: page-migrator -description: Migrates one hand-written HTML page to an Astro route with identical URL, content, and JS budget. Use for the page-migration tasks (10-16). Do not use for component extraction or config changes. +description: + Migrates one hand-written HTML page to an Astro route with identical URL, + content, and JS budget. Use for the page-migration tasks (10-16). Do not use + for component extraction or config changes. tools: Read, Write, Edit, Bash, Grep, Glob --- You migrate **one page per task**. The bar is that a visitor cannot tell. -**Read first**: `.agents/context/architecture.md`, `.agents/context/verification.md`. -**Load skills**: `astro-page`, `content-migration`, `visual-regression`. +**Read first**: `.agents/context/architecture.md`, +`.agents/context/verification.md`. **Load skills**: `astro-page`, +`content-migration`, `visual-regression`. ## Snapshot before you touch anything @@ -38,5 +42,5 @@ them, it is wrong — stop and report. ## Done when `.agents/checklists/before-page.md` complete, snapshot diff empty (or every line -justified), `node scripts/audit-ui.mjs` and `npm run verify` green, screenshots +justified), `node scripts/audit-ui.mjs` and `pnpm run verify` green, screenshots compared, and your task report lists what you deliberately left alone. diff --git a/.agents/agents/verification-engineer.md b/.agents/agents/verification-engineer.md index 4209122..a36e58c 100644 --- a/.agents/agents/verification-engineer.md +++ b/.agents/agents/verification-engineer.md @@ -1,6 +1,9 @@ --- name: verification-engineer -description: Keeps scripts/verify.mjs meaningful across the migration and builds the snapshot/visual-regression net. Use for tasks 18-19 and whenever a verify assertion needs re-pointing. The only role permitted to reduce coverage. +description: + Keeps scripts/verify.mjs meaningful across the migration and builds the + snapshot/visual-regression net. Use for tasks 18-19 and whenever a verify + assertion needs re-pointing. The only role permitted to reduce coverage. tools: Read, Write, Edit, Bash, Grep, Glob --- @@ -45,6 +48,6 @@ this "dependency-free" site. Add `@import`, `src: url(https:…)`, and ## Done when -Coverage has not fallen, every removal has a reason, snapshots exist for all -ten routes, `check-tokens.mjs` and the extended audit are wired into -`npm run verify`, and the suite runs green on the migrated site. +Coverage has not fallen, every removal has a reason, snapshots exist for all ten +routes, `check-tokens.mjs` and the extended audit are wired into +`pnpm run verify`, and the suite runs green on the migrated site. diff --git a/.agents/checklists/before-component.md b/.agents/checklists/before-component.md index 207f373..8f96bc5 100644 --- a/.agents/checklists/before-component.md +++ b/.agents/checklists/before-component.md @@ -1,6 +1,7 @@ # Checklist: before you call a component done -- [ ] It appears (or will appear) in **three** places, or has a name a person says out loud +- [ ] It appears (or will appear) in **three** places, or has a name a person + says out loud - [ ] Lives in the right folder: `primitives/`, `blocks/`, or `islands/` - [ ] Typed `interface Props`; every field intentional; no `any` - [ ] **No raw hex, px font sizes, or ad-hoc breakpoints** — tokens only @@ -8,8 +9,10 @@ - [ ] Markup under ~120 lines - [ ] Native elements: `