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:
+10
-8
@@ -21,11 +21,11 @@ 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` |
|
||||
@@ -37,12 +37,14 @@ Full definitions in [`agents/`](agents/).
|
||||
|
||||
## 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/<role>.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
|
||||
```
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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**.
|
||||
|
||||
@@ -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 `<html lang>` 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.
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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: `<button>` for actions, `<a>` for navigation
|
||||
- [ ] Keyboard: tab to it, operate with Enter/Space, focus ring visible
|
||||
- [ ] Interactive state exposed via ARIA (`aria-pressed`, `aria-current`), not just colour
|
||||
- [ ] Any motion respects `prefers-reduced-motion` and animates only `transform`/`opacity`
|
||||
- [ ] Interactive state exposed via ARIA (`aria-pressed`, `aria-current`), not
|
||||
just colour
|
||||
- [ ] Any motion respects `prefers-reduced-motion` and animates only
|
||||
`transform`/`opacity`
|
||||
- [ ] Renders correctly at 560 / 800 / 1100 / 1600 px
|
||||
- [ ] Both `en` and `pt` strings present; no hard-coded copy
|
||||
- [ ] `npm run verify` green with no assertion deleted
|
||||
- [ ] `pnpm run verify` green with no assertion deleted
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
# Checklist: before you merge a task branch
|
||||
|
||||
- [ ] Rebased on current `origin/main`, conflicts resolved in the worktree
|
||||
- [ ] `npm run verify` and `node scripts/audit-ui.mjs` both green
|
||||
- [ ] **Assertion count in `verify.mjs` did not fall** (`grep -c 'throw new Error' scripts/verify.mjs`)
|
||||
- [ ] Only files in your task's scope changed — `git diff --stat origin/main` matches the brief
|
||||
- [ ] `pnpm run verify` and `node scripts/audit-ui.mjs` both green
|
||||
- [ ] **Assertion count in `verify.mjs` did not fall**
|
||||
(`grep -c 'throw new Error' scripts/verify.mjs`)
|
||||
- [ ] Only files in your task's scope changed — `git diff --stat origin/main`
|
||||
matches the brief
|
||||
- [ ] No contended file edited unless you own it (see `rules/git-worktrees.md`)
|
||||
- [ ] No `.serena/`, `__pycache__/`, `dist/`, or scratch files staged
|
||||
- [ ] Commit message: what, why, and what you deliberately did not do
|
||||
|
||||
@@ -1,14 +1,20 @@
|
||||
# Checklist: before you call a page migrated
|
||||
|
||||
- [ ] URL identical to the old one, **trailing slash included**
|
||||
- [ ] Any query params the old page honoured still work (`?author=`, `?skill=`, `?view=`, `?file=`, `?compare=`, `?render=`)
|
||||
- [ ] Rendered text content diffs clean against the pre-migration snapshot — or every difference is listed and justified
|
||||
- [ ] Same number of JS bytes or fewer; a previously-zero-JS page still ships zero
|
||||
- [ ] `<title>`, `<meta name="description">`, and `<meta name="viewport">` preserved
|
||||
- [ ] Any query params the old page honoured still work (`?author=`, `?skill=`,
|
||||
`?view=`, `?file=`, `?compare=`, `?render=`)
|
||||
- [ ] Rendered text content diffs clean against the pre-migration snapshot — or
|
||||
every difference is listed and justified
|
||||
- [ ] Same number of JS bytes or fewer; a previously-zero-JS page still ships
|
||||
zero
|
||||
- [ ] `<title>`, `<meta name="description">`, and `<meta name="viewport">`
|
||||
preserved
|
||||
- [ ] One `<h1>`; heading levels do not skip
|
||||
- [ ] Every ARIA attribute from the original survived (`verify.mjs` asserts several)
|
||||
- [ ] No external `<script>`, `<link>`, `@import`, or `url()` — `node scripts/audit-ui.mjs` green
|
||||
- [ ] Every ARIA attribute from the original survived (`verify.mjs` asserts
|
||||
several)
|
||||
- [ ] No external `<script>`, `<link>`, `@import`, or `url()` —
|
||||
`node scripts/audit-ui.mjs` green
|
||||
- [ ] Internal links go through `BASE_URL`, not hand-written absolute paths
|
||||
- [ ] Screenshots at 560 / 800 / 1100 / 1600 px compared against the old page
|
||||
- [ ] `<html lang>` correct and still switching with the language toggle
|
||||
- [ ] `npm run verify` green with no assertion deleted
|
||||
- [ ] `pnpm run verify` green with no assertion deleted
|
||||
|
||||
@@ -9,7 +9,8 @@ because the Pages Server publishes a branch, not a directory.
|
||||
Live at `https://netcracker.pages.marcospaulo.dev.br/ai-for-dummies/`.
|
||||
|
||||
Full procedure, including the fact that `merge --ff-only main` fails (the
|
||||
histories diverged), is in [`../../docs/operations-guide.md`](../../docs/operations-guide.md).
|
||||
histories diverged), is in
|
||||
[`../../docs/operations-guide.md`](../../docs/operations-guide.md).
|
||||
|
||||
## What Astro changes
|
||||
|
||||
@@ -17,9 +18,9 @@ Astro emits `dist/`. The Pages Server cannot run a build, so **something has to
|
||||
put built output on `pages`**. Pick one, deliberately, in task 01:
|
||||
|
||||
| Option | How | Cost |
|
||||
| --- | --- | --- |
|
||||
| **A. Build locally, commit `dist/` to `pages`** | `npm run build`, copy `dist/*` into the `pages` worktree, commit | `pages` stops being "the exact source". Diffs become unreadable. Publishing depends on one workstation. Simple, no new infra. |
|
||||
| **B. Gitea Actions builds and pushes `pages`** | workflow on `main` → `npm ci && npm run build` → force-push `dist/` to `pages` | `pages` becomes a machine-owned branch (force-push is fine *because* nothing else writes it). Needs the act-runner to be healthy. **Recommended.** |
|
||||
| ----------------------------------------------- | ------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- |
|
||||
| **A. Build locally, commit `dist/` to `pages`** | `pnpm run build`, copy `dist/*` into the `pages` worktree, commit | `pages` stops being "the exact source". Diffs become unreadable. Publishing depends on one workstation. Simple, no new infra. |
|
||||
| **B. Gitea Actions builds and pushes `pages`** | workflow on `main` → `pnpm install --frozen-lockfile && pnpm run build` → force-push `dist/` to `pages` | `pages` becomes a machine-owned branch (force-push is fine _because_ nothing else writes it). Needs the act-runner to be healthy. **Recommended.** |
|
||||
| **C. Serve from a container instead** | drop Pages Server for an nginx pod behind the existing ingress | most control, most infra, changes the URL story |
|
||||
|
||||
**Recommended: B**, with A as the documented manual fallback for when the runner
|
||||
@@ -39,7 +40,7 @@ through `import.meta.env.BASE_URL` or Astro's `<a href={...}>` helpers rather
|
||||
than a hand-written absolute `/models/`.
|
||||
|
||||
This is the single most likely source of "works locally, 404s in production" in
|
||||
this migration. Verify it on the real host, not just `npm run preview`.
|
||||
this migration. Verify it on the real host, not just `pnpm run preview`.
|
||||
|
||||
## Verification before you call it published
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# Context: the verification contract
|
||||
|
||||
`scripts/verify.mjs` is 13 KB, 42 `throw new Error` sites, 16 checkpoints. It
|
||||
reads 26 source files and asserts that specific **string tokens** appear in
|
||||
them — `data-phase="plan"`, `renderTree`, `.change-lens`,
|
||||
reads 26 source files and asserts that specific **string tokens** appear in them
|
||||
— `data-phase="plan"`, `renderTree`, `.change-lens`,
|
||||
`styles.css?v=20260904-vote-widget`, and so on.
|
||||
|
||||
## Why this matters more than it looks
|
||||
@@ -11,7 +11,7 @@ These assertions are the only thing standing between this site and silent
|
||||
content loss during a large refactor. They are also **all going to break**,
|
||||
because they assert against files that will stop existing.
|
||||
|
||||
The failure mode to guard against: an agent runs `npm run verify`, sees red,
|
||||
The failure mode to guard against: an agent runs `pnpm run verify`, sees red,
|
||||
and "fixes" it by deleting the assertion. The suite goes green and the site
|
||||
loses a section. **Deleting an assertion is a change that requires review, the
|
||||
same as deleting a feature.**
|
||||
@@ -21,9 +21,9 @@ same as deleting a feature.**
|
||||
Three kinds of assertion, three different fates:
|
||||
|
||||
| Kind | Example | Fate |
|
||||
| --- | --- | --- |
|
||||
| ------------------------- | ------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------- |
|
||||
| **Content presence** | `'data-phase="plan"'` in `full-guide/index.html` | Re-point at built output (`dist/`) — the token should survive rendering. If it does not, the component dropped content. |
|
||||
| **Implementation detail** | `'const phases'`, `'renderTree'` in `app.js` | Obsolete. Replace with an assertion about *behaviour or output*, never delete outright. |
|
||||
| **Implementation detail** | `'const phases'`, `'renderTree'` in `app.js` | Obsolete. Replace with an assertion about _behaviour or output_, never delete outright. |
|
||||
| **Cache-busting version** | `'app.js?v=20260904-vote-widget'` | Obsolete — Astro hashes assets. Replace with "the built HTML references a hashed asset". |
|
||||
|
||||
**Rule: the assertion count must not fall.** Every removed token is replaced by
|
||||
|
||||
+10
-8
@@ -5,14 +5,14 @@ worktrees stay fast** — the whole point is that a gate you are tempted to skip
|
||||
is not a gate.
|
||||
|
||||
| Tier | Hook | Scope | Budget | Runs |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| ---- | ------------------ | ------------------------------------- | ------- | -------------------- |
|
||||
| 1 | `pre-commit` | **staged files only** (lint-staged) | < 3s | every commit |
|
||||
| 2 | `pre-push` | whole project: build + verify + audit | < 90s | every push |
|
||||
| 3 | CI (Gitea Actions) | tier 2 + visual regression | minutes | every push to `main` |
|
||||
|
||||
Tier 1 must stay under a few seconds. If it creeps, move the check to tier 2.
|
||||
An agent that waits 40s per commit will start passing `--no-verify`, and then
|
||||
you have no gate at all.
|
||||
Tier 1 must stay under a few seconds. If it creeps, move the check to tier 2. An
|
||||
agent that waits 40s per commit will start passing `--no-verify`, and then you
|
||||
have no gate at all.
|
||||
|
||||
## Tier 1 — pre-commit (lint-staged)
|
||||
|
||||
@@ -21,7 +21,8 @@ parallel worktrees do ten small jobs, not ten full-project sweeps.
|
||||
|
||||
- Prettier + ESLint on `*.{js,mjs,ts,astro}`
|
||||
- Prettier + Stylelint on `*.css`
|
||||
- `check-tokens.mjs` on changed `.astro`/`.css` — catches raw hex before it lands
|
||||
- `check-tokens.mjs` on changed `.astro`/`.css` — catches raw hex before it
|
||||
lands
|
||||
- Prettier on `*.{json,md}`
|
||||
|
||||
## Tier 2 — pre-push
|
||||
@@ -56,13 +57,14 @@ If a gate is wrong, fix the gate in its own commit. Do not route around it.
|
||||
- The heavy tier-2 gate takes a **lock** (`.git/af-gate.lock`, shared across
|
||||
worktrees) so ten agents pushing at once do not run ten concurrent builds and
|
||||
thrash the machine. Waiters queue; they do not fail.
|
||||
- `npm ci` in a fresh worktree should use `--prefer-offline` to avoid registry
|
||||
contention when several spin up at once.
|
||||
- `pnpm install --frozen-lockfile` in a fresh worktree is cheap: pnpm hardlinks
|
||||
from the shared content-addressable store, so a second worktree costs seconds
|
||||
and almost no disk instead of another 225 MB. No `--prefer-offline` needed.
|
||||
|
||||
## The silent-failure mode you must know about
|
||||
|
||||
Husky sets `core.hooksPath` to `.husky/_`, and **`.husky/_` is generated by
|
||||
`npm install`, not committed**. A fresh `git worktree add` therefore has hooks
|
||||
`pnpm install`, not committed**. A fresh `git worktree add` therefore has hooks
|
||||
configured but the directory missing — so **hooks silently do not run**. Every
|
||||
commit passes. Nothing is checked.
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ This project teaches worktrees. It should use them properly.
|
||||
# from the main checkout
|
||||
git worktree add ../af-task-07 -b refactor/task-07-route-cards
|
||||
cd ../af-task-07
|
||||
npm ci
|
||||
pnpm install --frozen-lockfile
|
||||
```
|
||||
|
||||
Naming: directory `../af-task-NN`, branch `refactor/task-NN-<slug>`. Both
|
||||
@@ -18,8 +18,8 @@ derived from the task file so the mapping is never ambiguous.
|
||||
|
||||
The migration runs many agents in parallel over the same small set of files
|
||||
(`tokens.css`, `verify.mjs`, `astro.config.mjs` are contended). Worktrees give
|
||||
each agent its own working directory over one object store — cheap, and no
|
||||
agent can see another's half-finished state.
|
||||
each agent its own working directory over one object store — cheap, and no agent
|
||||
can see another's half-finished state.
|
||||
|
||||
The failure mode without them: two agents both "fix" `verify.mjs`, and the
|
||||
second overwrites the first's assertions.
|
||||
@@ -30,7 +30,7 @@ These are touched by many tasks. Whoever owns them per the plan is the **only**
|
||||
writer; everyone else opens an issue in their task report instead of editing:
|
||||
|
||||
| File | Owner |
|
||||
| --- | --- |
|
||||
| ---------------------------------- | ----------------------- |
|
||||
| `src/styles/tokens.css` | `design-system-keeper` |
|
||||
| `scripts/verify.mjs` | `verification-engineer` |
|
||||
| `astro.config.mjs`, `package.json` | `astro-architect` |
|
||||
@@ -44,7 +44,7 @@ writer; everyone else opens an issue in their task report instead of editing:
|
||||
|
||||
## Before you finish
|
||||
|
||||
1. `npm run verify` green — without deleting assertions.
|
||||
1. `pnpm run verify` green — without deleting assertions.
|
||||
2. The relevant checklist in [`../checklists/`](../checklists/) complete.
|
||||
3. `git rebase origin/main` again, resolve conflicts in your worktree.
|
||||
4. Task report: what changed, what you verified, **what you did not do**.
|
||||
@@ -64,6 +64,8 @@ should be short.
|
||||
|
||||
- Never work directly on `main`.
|
||||
- Never force-push a shared branch. The `pages` branch is the sole exception,
|
||||
and only if CI owns it (see [`../context/publishing.md`](../context/publishing.md)).
|
||||
and only if CI owns it (see
|
||||
[`../context/publishing.md`](../context/publishing.md)).
|
||||
- Never `git add -A` from the repository root. This repo has untracked local
|
||||
scratch (`.serena/`, `scripts/inspect.py`) that must not be swept into a commit.
|
||||
scratch (`.serena/`, `scripts/inspect.py`) that must not be swept into a
|
||||
commit.
|
||||
|
||||
@@ -15,7 +15,7 @@ the token layer is missing something (add it there, not inline).
|
||||
```css
|
||||
/* forbidden */
|
||||
color: #172f42;
|
||||
color: rgba(23,47,66,.6);
|
||||
color: rgba(23, 47, 66, 0.6);
|
||||
|
||||
/* required */
|
||||
color: var(--ink);
|
||||
@@ -23,7 +23,7 @@ color: var(--muted);
|
||||
```
|
||||
|
||||
No raw hex outside `tokens.css`. `.agents/scripts/check-tokens.mjs` enforces it;
|
||||
wire it into `npm run verify`.
|
||||
wire it into `pnpm run verify`.
|
||||
|
||||
## Semantic names, not literal ones
|
||||
|
||||
@@ -31,8 +31,8 @@ wire it into `npm run verify`.
|
||||
`--deep` are the existing vocabulary. Keep it — it is already semantic and the
|
||||
team reads it fluently. Do not rename to `--color-neutral-900`.
|
||||
|
||||
If a genuine second surface is needed, extend semantically
|
||||
(`--surface-lab`, `--ink-inverse`), never numerically.
|
||||
If a genuine second surface is needed, extend semantically (`--surface-lab`,
|
||||
`--ink-inverse`), never numerically.
|
||||
|
||||
## Type scale
|
||||
|
||||
@@ -56,8 +56,11 @@ repetitions.
|
||||
Five named widths replace the current sixteen:
|
||||
|
||||
```css
|
||||
--bp-sm: 560px; --bp-md: 800px; --bp-lg: 1100px;
|
||||
--bp-xl: 1600px; --bp-2xl: 2200px;
|
||||
--bp-sm: 560px;
|
||||
--bp-md: 800px;
|
||||
--bp-lg: 1100px;
|
||||
--bp-xl: 1600px;
|
||||
--bp-2xl: 2200px;
|
||||
```
|
||||
|
||||
When collapsing a component's old breakpoint onto a named one, screenshot at the
|
||||
@@ -74,5 +77,5 @@ When collapsing a component's old breakpoint onto a named one, screenshot at the
|
||||
## Fonts
|
||||
|
||||
Do not add a webfont without an explicit decision recorded in the task. The
|
||||
intended Manrope/DM Mono has never rendered; introducing it is a visual redesign,
|
||||
not a refactor. Default: match what renders today.
|
||||
intended Manrope/DM Mono has never rendered; introducing it is a visual
|
||||
redesign, not a refactor. Default: match what renders today.
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
#!/usr/bin/env node
|
||||
// Fails when a raw colour, px font-size, or ad-hoc breakpoint appears outside
|
||||
// the token layer. A rule nobody checks is a suggestion — wire this into
|
||||
// `npm run verify`.
|
||||
// `pnpm run verify`.
|
||||
//
|
||||
// Usage: node .agents/scripts/check-tokens.mjs [srcDir]
|
||||
|
||||
@@ -29,7 +29,9 @@ for (const path of targets) {
|
||||
if (!['.astro', '.css'].includes(extname(path))) continue;
|
||||
if (TOKEN_FILES.some((allowed) => path.endsWith(allowed))) continue;
|
||||
|
||||
readFileSync(path, 'utf8').split('\n').forEach((line, index) => {
|
||||
readFileSync(path, 'utf8')
|
||||
.split('\n')
|
||||
.forEach((line, index) => {
|
||||
const at = `${path}:${index + 1}`;
|
||||
|
||||
// Raw hex — the drifted-palette failure mode this whole layer exists to stop.
|
||||
@@ -47,7 +49,9 @@ for (const path of targets) {
|
||||
// Ad-hoc breakpoints are how sixteen of them accumulated last time.
|
||||
const media = line.match(/@media[^{]*?\(\s*(?:max|min)-width:\s*(\d+px)/);
|
||||
if (media && !ALLOWED_BREAKPOINTS.includes(media[1]))
|
||||
findings.push(`${at}: breakpoint ${media[1]} is not a named one (${ALLOWED_BREAKPOINTS.join(', ')})`);
|
||||
findings.push(
|
||||
`${at}: breakpoint ${media[1]} is not a named one (${ALLOWED_BREAKPOINTS.join(', ')})`,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
+13
-4
@@ -26,18 +26,27 @@ step() { printf '\n\033[1m▸ %s\033[0m\n' "$1"; }
|
||||
|
||||
# Fail loudly rather than passing vacuously when the toolchain is not installed.
|
||||
if [ ! -d node_modules ]; then
|
||||
echo "gate: node_modules missing — run 'npm ci --prefer-offline' first" >&2
|
||||
echo "gate: node_modules missing — run 'pnpm install --frozen-lockfile' first" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# This project is pnpm-only. An agent that runs `npm install` out of habit gets
|
||||
# a second, divergent dependency tree and a lockfile nobody reads — the same
|
||||
# class of failure that cost two sessions during phase 0. Catch it here.
|
||||
if [ -f package-lock.json ] || [ -f yarn.lock ] || [ -f bun.lock ] || [ -f bun.lockb ]; then
|
||||
echo "gate: a non-pnpm lockfile is present. This project uses pnpm only." >&2
|
||||
echo " Delete it, then run 'pnpm install --frozen-lockfile'." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
step "types"
|
||||
npx --no-install astro check
|
||||
pnpm exec astro check
|
||||
|
||||
step "build"
|
||||
npm run build
|
||||
pnpm run build
|
||||
|
||||
step "content contracts"
|
||||
npm run verify
|
||||
pnpm run verify
|
||||
|
||||
# The assertion count is the thing agents are most tempted to "fix" downward.
|
||||
# Compare against origin/main and refuse a silent reduction.
|
||||
|
||||
@@ -58,11 +58,11 @@ else
|
||||
git worktree add "$dir" -b "$branch" "$base"
|
||||
fi
|
||||
|
||||
# npm ci only once task 01 has produced a lockfile. The pre-existing root
|
||||
# pnpm install works only once task 01 has produced a lockfile. The pre-existing root
|
||||
# package.json carries two scripts and no dependencies, so before task 01 there
|
||||
# is no toolchain to install and no hooks to verify.
|
||||
if [ -f "$dir/package-lock.json" ]; then
|
||||
( cd "$dir" && npm ci --prefer-offline && .agents/scripts/verify-hooks.sh )
|
||||
if [ -f "$dir/pnpm-lock.yaml" ]; then
|
||||
( cd "$dir" && pnpm install --frozen-lockfile && .agents/scripts/verify-hooks.sh )
|
||||
fi
|
||||
|
||||
prompt=$(cat <<PROMPT
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
# Guards the silent-failure mode described in .agents/rules/gates.md.
|
||||
#
|
||||
# Husky points core.hooksPath at `.husky/_`, but that directory is GENERATED by
|
||||
# `npm install` and is NOT committed. A fresh `git worktree add` therefore has
|
||||
# `pnpm install` and is NOT committed. A fresh `git worktree add` therefore has
|
||||
# hooks configured and the directory missing — so every hook silently does
|
||||
# nothing and every commit passes unchecked.
|
||||
#
|
||||
@@ -43,7 +43,7 @@ fi
|
||||
|
||||
if [ "$fail" -ne 0 ]; then
|
||||
echo
|
||||
echo "Fix: npm ci --prefer-offline (its prepare script regenerates .husky/_)"
|
||||
echo "Fix: pnpm install --frozen-lockfile (its prepare script regenerates .husky/_)"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ try {
|
||||
({ chromium } = await import('playwright'));
|
||||
} catch {
|
||||
throw new Error(
|
||||
'visual regression requires Playwright; install its project dependency and run npx playwright install chromium',
|
||||
'visual regression requires Playwright; install its project dependency and run pnpm exec playwright install chromium',
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ case "$action" in
|
||||
# Not optional. `.husky/_` is generated by install and is NOT committed, so
|
||||
# a fresh worktree has hooks configured but absent — every commit would pass
|
||||
# unchecked. --prefer-offline keeps ten parallel spin-ups off the registry.
|
||||
( cd "$dir" && npm ci --prefer-offline && .agents/scripts/verify-hooks.sh )
|
||||
( cd "$dir" && pnpm install --frozen-lockfile && .agents/scripts/verify-hooks.sh )
|
||||
|
||||
echo
|
||||
echo "worktree : $dir"
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
---
|
||||
name: astro-component
|
||||
description: Build one Astro component for the ai-for-dummies site from the project templates. Use when creating a primitive, block, or island, or when splitting existing markup into a component.
|
||||
description:
|
||||
Build one Astro component for the ai-for-dummies site from the project
|
||||
templates. Use when creating a primitive, block, or island, or when splitting
|
||||
existing markup into a component.
|
||||
---
|
||||
|
||||
# Building an Astro component
|
||||
@@ -38,6 +41,7 @@ interface Props {
|
||||
}
|
||||
const { number, title, summary, href } = Astro.props;
|
||||
---
|
||||
|
||||
<article class="card">
|
||||
<b>{number}</b>
|
||||
<h2>{title}</h2>
|
||||
@@ -46,8 +50,16 @@ const { number, title, summary, href } = Astro.props;
|
||||
</article>
|
||||
|
||||
<style>
|
||||
.card { display: grid; gap: 10px; padding: 22px; background: var(--paper); }
|
||||
b { color: var(--accent); font: var(--font-eyebrow); }
|
||||
.card {
|
||||
display: grid;
|
||||
gap: 10px;
|
||||
padding: 22px;
|
||||
background: var(--paper);
|
||||
}
|
||||
b {
|
||||
color: var(--accent);
|
||||
font: var(--font-eyebrow);
|
||||
}
|
||||
</style>
|
||||
```
|
||||
|
||||
@@ -64,5 +76,6 @@ Rules that bite most often here:
|
||||
1. Render it at 560 / 800 / 1100 / 1600 px.
|
||||
2. Tab to it. Focus ring visible (`outline: 3px solid #a7483f`).
|
||||
3. Diff its rendered text against the markup it replaced.
|
||||
4. Run [`../../checklists/before-component.md`](../../checklists/before-component.md).
|
||||
5. `npm run verify` — green, with no assertion deleted.
|
||||
4. Run
|
||||
[`../../checklists/before-component.md`](../../checklists/before-component.md).
|
||||
5. `pnpm run verify` — green, with no assertion deleted.
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
---
|
||||
name: astro-page
|
||||
description: Migrate one hand-written HTML page of the ai-for-dummies site to an Astro route without changing its URL, content, or JS budget. Use for any page-level migration task.
|
||||
description:
|
||||
Migrate one hand-written HTML page of the ai-for-dummies site to an Astro
|
||||
route without changing its URL, content, or JS budget. Use for any page-level
|
||||
migration task.
|
||||
---
|
||||
|
||||
# Migrating a page to Astro
|
||||
@@ -10,7 +13,7 @@ description: Migrate one hand-written HTML page of the ai-for-dummies site to an
|
||||
The snapshot is the only objective evidence that no content was lost.
|
||||
|
||||
```bash
|
||||
npm run serve & # vanilla site on :4173
|
||||
pnpm run serve & # vanilla site on :4173
|
||||
node .agents/scripts/snapshot-route.mjs http://localhost:4173/models/ \
|
||||
> .agents/snapshots/models.txt
|
||||
```
|
||||
@@ -30,7 +33,8 @@ Then, in order:
|
||||
2. Move copy into `src/content/`. Both `en` and `pt`, copied literally — never
|
||||
retyped.
|
||||
3. Move page CSS into component `<style>` blocks. Do **not** port
|
||||
`responsive.css` wholesale; take what this page needs and prove the rest dead.
|
||||
`responsive.css` wholesale; take what this page needs and prove the rest
|
||||
dead.
|
||||
4. Keep every `data-*` hook. `verify.mjs` asserts many of them by name
|
||||
(`data-phase`, `data-tree`, `data-route`, `data-model-provider`, …).
|
||||
5. Keep every ARIA attribute and the `<title>` / `<meta name="description">`.
|
||||
@@ -49,11 +53,11 @@ documented in the page footer and shared externally.
|
||||
## Prove it
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
pnpm run build
|
||||
node .agents/scripts/snapshot-route.mjs dist/models/index.html > /tmp/after.txt
|
||||
diff .agents/snapshots/models.txt /tmp/after.txt # empty, or justify every line
|
||||
node scripts/audit-ui.mjs
|
||||
npm run verify
|
||||
pnpm run verify
|
||||
```
|
||||
|
||||
Then screenshots at the same four widths, and
|
||||
|
||||
@@ -1,6 +1,10 @@
|
||||
---
|
||||
name: design-tokens
|
||||
description: Extract, name, and enforce the design token layer for the ai-for-dummies site. Use when touching any colour, font size, spacing value, or breakpoint, when consolidating the three drifted palettes, or when a check-tokens failure needs resolving.
|
||||
description:
|
||||
Extract, name, and enforce the design token layer for the ai-for-dummies site.
|
||||
Use when touching any colour, font size, spacing value, or breakpoint, when
|
||||
consolidating the three drifted palettes, or when a check-tokens failure needs
|
||||
resolving.
|
||||
---
|
||||
|
||||
# Design tokens
|
||||
@@ -9,8 +13,8 @@ description: Extract, name, and enforce the design token layer for the ai-for-du
|
||||
|
||||
Read [`../../context/design-system.md`](../../context/design-system.md). This
|
||||
site has **three drifting palettes** and a **broken `@font-face`**. Both are
|
||||
traps. If you have not read that file, you will "preserve the styles" by
|
||||
copying a bug.
|
||||
traps. If you have not read that file, you will "preserve the styles" by copying
|
||||
a bug.
|
||||
|
||||
## Extracting
|
||||
|
||||
@@ -60,7 +64,7 @@ a breakpoint, **screenshot at the old value** — that is where the regression i
|
||||
node .agents/scripts/check-tokens.mjs # fails on raw hex outside tokens.css
|
||||
```
|
||||
|
||||
Wire it into `npm run verify`. A rule nobody checks is a suggestion.
|
||||
Wire it into `pnpm run verify`. A rule nobody checks is a suggestion.
|
||||
|
||||
## The font decision
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
---
|
||||
name: visual-regression
|
||||
description: Prove a refactor did not change how the site looks. Use before and after any page migration, token consolidation, or breakpoint change on ai-for-dummies.
|
||||
description:
|
||||
Prove a refactor did not change how the site looks. Use before and after any
|
||||
page migration, token consolidation, or breakpoint change on ai-for-dummies.
|
||||
---
|
||||
|
||||
# Visual regression
|
||||
@@ -31,8 +33,8 @@ with sync_playwright() as p:
|
||||
browser.close()
|
||||
```
|
||||
|
||||
Run once against the vanilla site (`npm run serve`), once against
|
||||
`npm run preview`. Keep both sets.
|
||||
Run once against the vanilla site (`pnpm run serve`), once against
|
||||
`pnpm run preview`. Keep both sets.
|
||||
|
||||
## Compare
|
||||
|
||||
@@ -43,8 +45,8 @@ for f in before/*.png; do
|
||||
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.
|
||||
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
|
||||
|
||||
@@ -61,9 +63,9 @@ Also screenshot at the **old** breakpoint values you removed (520, 530, 600,
|
||||
|
||||
Expect and accept: sub-pixel text shifts, antialiasing.
|
||||
|
||||
Investigate: anything that moves by more than ~2px, any colour change (that is
|
||||
a token bug), any element that appears or disappears (that is content loss —
|
||||
stop and check the snapshot diff).
|
||||
Investigate: anything that moves by more than ~2px, any colour change (that is a
|
||||
token bug), any element that appears or disappears (that is content loss — stop
|
||||
and check the snapshot diff).
|
||||
|
||||
## Reduced motion
|
||||
|
||||
|
||||
+29
-16
@@ -6,6 +6,14 @@ on:
|
||||
push:
|
||||
branches: [main]
|
||||
pull_request:
|
||||
# Publication is deliberately manual for the duration of the Astro migration.
|
||||
# See the `publish` job below for why.
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
publish:
|
||||
description: 'Force-push dist/ to the pages branch'
|
||||
type: boolean
|
||||
default: false
|
||||
|
||||
jobs:
|
||||
gate:
|
||||
@@ -17,22 +25,27 @@ jobs:
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
- run: npm install --package-lock=false --prefer-offline
|
||||
- run: npm run lint
|
||||
# Node 25 dropped the bundled corepack, and this self-hosted act-runner
|
||||
# is not a good place to discover whether it can fetch a third-party
|
||||
# action. Bootstrapping pnpm with npm needs neither. Keep the version in
|
||||
# step with package.json's `packageManager`.
|
||||
- run: npm install --global pnpm@11.25.0
|
||||
- run: pnpm install --frozen-lockfile
|
||||
- run: pnpm run lint
|
||||
- run: ./.agents/scripts/gate.sh
|
||||
- name: visual regression
|
||||
run: |
|
||||
npx playwright install --with-deps chromium
|
||||
node .agents/scripts/visual-regression.mjs
|
||||
- uses: actions/upload-artifact@v4
|
||||
if: failure()
|
||||
with:
|
||||
name: screenshots
|
||||
path: .agents/snapshots/diff/
|
||||
# The visual-regression step is intentionally absent. `visual-regression.mjs`
|
||||
# only *captures* baselines — it has no compare mode — so in CI it would
|
||||
# overwrite .agents/snapshots/before/ and pass unconditionally. It also
|
||||
# imports `playwright`, which is not a dependency of this project. Wire it
|
||||
# back in once it can actually diff. See task 03's report.
|
||||
|
||||
publish:
|
||||
if: github.ref == 'refs/heads/main'
|
||||
# Until the migration finishes, `dist/` holds only /summary/ and the two
|
||||
# hands-on fixtures, while the live `pages` branch serves ten pages.
|
||||
# Publishing on every push to main would take the site down to a stub, so
|
||||
# this job runs only when a human asks for it. Make it unconditional on
|
||||
# main again at task 20 (cutover), not before.
|
||||
if: github.event_name == 'workflow_dispatch' && inputs.publish
|
||||
needs: gate
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
@@ -40,9 +53,9 @@ jobs:
|
||||
- uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 22
|
||||
cache: npm
|
||||
- run: npm install --package-lock=false --prefer-offline
|
||||
- run: npm run build
|
||||
- run: npm install --global pnpm@11.25.0
|
||||
- run: pnpm install --frozen-lockfile
|
||||
- run: pnpm run build
|
||||
- name: Publish generated site to pages
|
||||
run: |
|
||||
git config user.name 'gitea-actions[bot]'
|
||||
|
||||
@@ -15,3 +15,10 @@ dist/
|
||||
|
||||
# agent run logs
|
||||
.agents/logs/
|
||||
|
||||
# pnpm-only project. A stray npm/yarn/bun run here is a bug the gate rejects;
|
||||
# ignoring the artefacts keeps one from being committed by accident.
|
||||
package-lock.json
|
||||
yarn.lock
|
||||
bun.lock
|
||||
bun.lockb
|
||||
|
||||
+2
-2
@@ -3,8 +3,8 @@
|
||||
# Husky v9+: no `husky.sh` sourcing (deprecated in v9, removed in v10).
|
||||
|
||||
# Guard the silent-failure mode: if hooks are configured but .husky/_ is
|
||||
# missing (fresh worktree that never ran `npm install`), this file would not
|
||||
# missing (fresh worktree that never ran `pnpm install`), this file would not
|
||||
# execute at all. Nothing we can do from inside it — so verify-hooks.sh exists
|
||||
# and worktree.sh runs it at creation time.
|
||||
|
||||
npx --no-install lint-staged
|
||||
pnpm exec lint-staged
|
||||
|
||||
@@ -5,3 +5,4 @@ submitted-skills
|
||||
skill-reviews
|
||||
vote-service
|
||||
.agents/snapshots
|
||||
pnpm-lock.yaml
|
||||
|
||||
@@ -12,54 +12,64 @@ rules, and verification.** It is published as a static site on a self-hosted
|
||||
Gitea Pages Server, and it doubles as its own teaching artifact: the hands-on
|
||||
labs are dependency-free HTML/CSS/JS that workshop attendees point an agent at.
|
||||
|
||||
- **Current stack**: hand-written HTML + CSS + ES modules, no build step, no dependencies
|
||||
- **Target stack**: Astro (see [`plans/astro-refactor/`](plans/astro-refactor/README.md)) — migration in progress
|
||||
- **Current stack**: hand-written HTML + CSS + ES modules, no build step, no
|
||||
dependencies
|
||||
- **Target stack**: Astro (see
|
||||
[`plans/astro-refactor/`](plans/astro-refactor/README.md)) — migration in
|
||||
progress
|
||||
- **Languages**: English and Brazilian Portuguese, toggled client-side
|
||||
- **Companion service**: `vote-service/` (Go + Kubernetes) — separate lifecycle, see its own README
|
||||
- **Companion service**: `vote-service/` (Go + Kubernetes) — separate lifecycle,
|
||||
see its own README
|
||||
|
||||
## Essential commands
|
||||
|
||||
```bash
|
||||
npm run verify # content + interaction contracts (scripts/verify.mjs) — the gate
|
||||
pnpm run verify # content + interaction contracts (scripts/verify.mjs) — the gate
|
||||
node scripts/audit-ui.mjs # responsive / no-external-dependency audit
|
||||
node scripts/build-skill-review.mjs # regenerate skill-reviews/improved/ from catalog.js
|
||||
npm run serve # python3 -m http.server 4173
|
||||
pnpm run serve # python3 -m http.server 4173
|
||||
```
|
||||
|
||||
`npm run verify` is not a formality. It is a set of ~42 string-token assertions
|
||||
that pin the site's real content and interactions. **A refactor that "passes"
|
||||
by deleting assertions has failed.** See
|
||||
`pnpm run verify` is not a formality. It is a set of ~42 string-token assertions
|
||||
that pin the site's real content and interactions. **A refactor that "passes" by
|
||||
deleting assertions has failed.** See
|
||||
[`.agents/context/verification.md`](.agents/context/verification.md).
|
||||
|
||||
## Publishing
|
||||
|
||||
`main` is the source of truth. The `pages` branch is what the Gitea Pages
|
||||
Server actually serves, and its tree must end up identical to `main`'s. The
|
||||
full procedure — including why `merge --ff-only` does *not* work here — is in
|
||||
`main` is the source of truth. The `pages` branch is what the Gitea Pages Server
|
||||
actually serves, and its tree must end up identical to `main`'s. The full
|
||||
procedure — including why `merge --ff-only` does _not_ work here — is in
|
||||
[`docs/operations-guide.md`](docs/operations-guide.md).
|
||||
|
||||
Adding a build step changes this contract. Read
|
||||
[`.agents/context/publishing.md`](.agents/context/publishing.md) before doing so.
|
||||
[`.agents/context/publishing.md`](.agents/context/publishing.md) before doing
|
||||
so.
|
||||
|
||||
## Never touch
|
||||
|
||||
- `hands-on/starter/` and `hands-on/rules/` — **lab fixtures.** The exercise *is*
|
||||
that they are dependency-free vanilla HTML/CSS/JS an attendee can hand to an
|
||||
agent. Componentizing them destroys the lesson. They ship as static assets.
|
||||
- `hands-on/starter/` and `hands-on/rules/` — **lab fixtures.** The exercise
|
||||
_is_ that they are dependency-free vanilla HTML/CSS/JS an attendee can hand to
|
||||
an agent. Componentizing them destroys the lesson. They ship as static assets.
|
||||
- `submitted-skills/` — other people's submitted work, reproduced verbatim
|
||||
- `skill-reviews/improved/` — generated; edit `skills-review/catalog.js` instead
|
||||
- `vote-service/` — separate deploy lifecycle; do not fold into the site build
|
||||
- `dist/`, `node_modules/` — build output, never committed
|
||||
- `package-lock.json` — **committed, but never hand-edited.** Change it only
|
||||
as a side effect of `npm install`. Every worktree spins up with `npm ci`,
|
||||
which fails outright without it.
|
||||
- `pnpm-lock.yaml` — **committed, but never hand-edited.** Change it only as a
|
||||
side effect of `pnpm install`. Every worktree spins up with
|
||||
`pnpm install --frozen-lockfile`, which fails outright without it.
|
||||
- This project is **pnpm-only** (`packageManager` in `package.json` pins the
|
||||
version). Never run `npm install` or `bun install` here — the gate rejects a
|
||||
`package-lock.json`, `yarn.lock`, or `bun.lock` outright. pnpm settings live
|
||||
in `pnpm-workspace.yaml`, **not** in a `pnpm` field in `package.json`; pnpm 11
|
||||
ignores that field silently.
|
||||
|
||||
## Rules
|
||||
|
||||
Binding. Read the one that covers what you are about to do.
|
||||
|
||||
| Rule | When |
|
||||
| --- | --- |
|
||||
| ---------------------------------------------------------- | ------------------------------------ |
|
||||
| [`astro.md`](.agents/rules/astro.md) | any `.astro` file |
|
||||
| [`theming.md`](.agents/rules/theming.md) | any colour, font, or spacing value |
|
||||
| [`componentization.md`](.agents/rules/componentization.md) | creating or splitting a component |
|
||||
|
||||
@@ -3,16 +3,15 @@
|
||||
A lightweight, presentation-style field guide to AI-assisted engineering.
|
||||
|
||||
It explains how to combine a strong planning/review model with faster workers,
|
||||
reusable skills, subagent handoffs, Git worktrees, and explicit verification.
|
||||
An interactive field kit compares common behavior skills such as
|
||||
`ponytail-lite`, `caveman`, `unlazy`, research, debugging, and review.
|
||||
The skill-forge workflow covers discovery, triggers, package anatomy,
|
||||
progressive instructions, structural validation, and behavioral iteration.
|
||||
The hands-on lab provides a tiny starter project and copy-ready baseline and
|
||||
skill-enabled prompts for a short side-by-side exercise.
|
||||
An interactive model gearbox separates capability tier from reasoning effort
|
||||
across OpenAI, Claude, and Gemini, and every featured skill links to a pinned
|
||||
source with an approval-first installation prompt.
|
||||
reusable skills, subagent handoffs, Git worktrees, and explicit verification. An
|
||||
interactive field kit compares common behavior skills such as `ponytail-lite`,
|
||||
`caveman`, `unlazy`, research, debugging, and review. The skill-forge workflow
|
||||
covers discovery, triggers, package anatomy, progressive instructions,
|
||||
structural validation, and behavioral iteration. The hands-on lab provides a
|
||||
tiny starter project and copy-ready baseline and skill-enabled prompts for a
|
||||
short side-by-side exercise. An interactive model gearbox separates capability
|
||||
tier from reasoning effort across OpenAI, Claude, and Gemini, and every featured
|
||||
skill links to a pinned source with an approval-first installation prompt.
|
||||
|
||||
## Run locally
|
||||
|
||||
@@ -27,23 +26,30 @@ Then open <http://localhost:4173>.
|
||||
Verify the content and interaction contracts with:
|
||||
|
||||
```bash
|
||||
npm run verify
|
||||
pnpm run verify
|
||||
```
|
||||
|
||||
## Project structure
|
||||
|
||||
- `index.html` — default route map and focused chapter navigation
|
||||
- `full-guide/` — the complete bilingual presentation, with responsive audit overrides
|
||||
- `styles.css` / `app.js` — editorial visual system and bilingual field-guide interactions
|
||||
- `full-guide/` — the complete bilingual presentation, with responsive audit
|
||||
overrides
|
||||
- `styles.css` / `app.js` — editorial visual system and bilingual field-guide
|
||||
interactions
|
||||
- `responsive.css` — interactive diagrams and Full HD-to-4K adaptations
|
||||
- `docs/references/` — bundled research sources and notes
|
||||
- `docs/operations-guide.md` — canonical SilverBullet operations and skills guide
|
||||
- `docs/operations-guide.md` — canonical SilverBullet operations and skills
|
||||
guide
|
||||
- `hands-on/starter/` — dependency-free Tiny Tasks exercise
|
||||
- `hands-on/rules/` — dependency-free Guardrails lab; toggles rule sources into the prompt
|
||||
- `hands-on/rules/` — dependency-free Guardrails lab; toggles rule sources into
|
||||
the prompt
|
||||
- `rules/` — bilingual case study of skills, CLI ratchets, Husky, and PR review
|
||||
- `skills/` — reusable design and rules-case-study skills, plus an interactive package anatomy explorer
|
||||
- `skills-review/` — static review desk for submitted skills; its reader vote widget calls the separate `vote-service`
|
||||
- `vote-service/` — small Go API + Kubernetes manifests backing the skills-review vote widget (see `vote-service/README.md`)
|
||||
- `skills/` — reusable design and rules-case-study skills, plus an interactive
|
||||
package anatomy explorer
|
||||
- `skills-review/` — static review desk for submitted skills; its reader vote
|
||||
widget calls the separate `vote-service`
|
||||
- `vote-service/` — small Go API + Kubernetes manifests backing the
|
||||
skills-review vote widget (see `vote-service/README.md`)
|
||||
- `GATES.md` — acceptance ledger for the project
|
||||
|
||||
## Publishing
|
||||
@@ -54,9 +60,9 @@ The Gitea instance has a Pages Server configured to publish a repository’s
|
||||
<https://netcracker.pages.marcospaulo.dev.br/ai-for-dummies/>
|
||||
|
||||
If the URL is not available yet, verify that the `pages` branch exists and that
|
||||
the repository’s `pages` branch exists. Gitea itself does not
|
||||
provide a built-in Pages server; this setup uses the instance’s separate Pages
|
||||
Server and Actions deployment path.
|
||||
the repository’s `pages` branch exists. Gitea itself does not provide a built-in
|
||||
Pages server; this setup uses the instance’s separate Pages Server and Actions
|
||||
deployment path.
|
||||
|
||||
For the complete authoring, verification, publication, rollback, worktree, and
|
||||
skill workflow, see [docs/operations-guide.md](docs/operations-guide.md).
|
||||
@@ -64,9 +70,9 @@ skill workflow, see [docs/operations-guide.md](docs/operations-guide.md).
|
||||
## Reader voting on the skills-review desk
|
||||
|
||||
`skills-review/` is static, so its "which draft would you ship?" vote widget
|
||||
calls a separate stateful service — `vote-service/`, a small Go API on its
|
||||
own pod, one vote per visitor enforced server-side by IP (a MAC address is
|
||||
never visible to a server across the internet, so it cannot be used). See
|
||||
calls a separate stateful service — `vote-service/`, a small Go API on its own
|
||||
pod, one vote per visitor enforced server-side by IP (a MAC address is never
|
||||
visible to a server across the internet, so it cannot be used). See
|
||||
[vote-service/README.md](vote-service/README.md) for the API, the anti-abuse
|
||||
design, and the build/push/deploy steps; `skills-review/index.html` sets
|
||||
`window.SKILLS_REVIEW_VOTE_API` to point at it once deployed.
|
||||
@@ -74,19 +80,21 @@ design, and the build/push/deploy steps; `skills-review/index.html` sets
|
||||
## Research
|
||||
|
||||
See [docs/references/README.md](docs/references/README.md) for official Claude,
|
||||
Codex, and Git documentation. The [additional reading path](docs/references/additional-reading.md)
|
||||
bundles 12 verified articles and guides, including Medium and practitioner sources.
|
||||
See [model routing](docs/references/model-routing.md) for current provider controls
|
||||
and [verified skill sources](docs/references/skill-sources.md) for commit-pinned provenance.
|
||||
Codex, and Git documentation. The
|
||||
[additional reading path](docs/references/additional-reading.md) bundles 12
|
||||
verified articles and guides, including Medium and practitioner sources. See
|
||||
[model routing](docs/references/model-routing.md) for current provider controls
|
||||
and [verified skill sources](docs/references/skill-sources.md) for commit-pinned
|
||||
provenance.
|
||||
|
||||
## Rules and enforcement case study
|
||||
|
||||
Open `/rules/` for a concise walkthrough grounded in the
|
||||
`netcracker/interview` repository. It shows how `AGENTS.md`, project-local
|
||||
skills, machine-readable repo ledgers, a UI contract ratchet, lint-staged,
|
||||
Husky, commitlint, specialist verifier agents, and PR review reinforce one
|
||||
another. Every example links to its source file in Gitea, and the page includes
|
||||
a copy-ready prompt for mapping the same layers in another repository.
|
||||
Open `/rules/` for a concise walkthrough grounded in the `netcracker/interview`
|
||||
repository. It shows how `AGENTS.md`, project-local skills, machine-readable
|
||||
repo ledgers, a UI contract ratchet, lint-staged, Husky, commitlint, specialist
|
||||
verifier agents, and PR review reinforce one another. Every example links to its
|
||||
source file in Gitea, and the page includes a copy-ready prompt for mapping the
|
||||
same layers in another repository.
|
||||
|
||||
The implementation patterns are also packaged as project-local skills in
|
||||
[skills/](skills/README.md). Use `editorial-playbook` when adding chapters or
|
||||
|
||||
@@ -25,7 +25,7 @@ worktree practices taught by the presentation fit together.
|
||||
| Local checkout | `/home/marcos/Projects/ai-for-dummies` |
|
||||
| Source branch | `main` |
|
||||
| Published branch | `pages` |
|
||||
| Local verification | `npm run verify` |
|
||||
| Local verification | `pnpm run verify` |
|
||||
| SilverBullet page | `Guides/AI For Dummies Presentation` |
|
||||
| Skills-review vote API | `vote-service/` — separate pod, see `vote-service/README.md` |
|
||||
|
||||
@@ -51,7 +51,7 @@ migration task.
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
E[Edit main] --> V[npm run gate]
|
||||
E[Edit main] --> V[pnpm run gate]
|
||||
V --> C[Commit]
|
||||
C --> P[Push main]
|
||||
P --> G[Gitea Actions: gate + build]
|
||||
@@ -76,7 +76,7 @@ part of the published site.
|
||||
### 2. Preview locally
|
||||
|
||||
```bash
|
||||
npm run dev
|
||||
pnpm run dev
|
||||
```
|
||||
|
||||
Open
|
||||
@@ -88,7 +88,7 @@ least one desktop and one mobile viewport. The production site is under the
|
||||
### 3. Verify before committing
|
||||
|
||||
```bash
|
||||
npm run gate
|
||||
pnpm run gate
|
||||
```
|
||||
|
||||
The gate runs Astro types and build checks, content contracts, the runtime
|
||||
@@ -120,8 +120,8 @@ If the runner is unavailable, use the following manual fallback from a clean
|
||||
`main` checkout. It deliberately replaces the generated branch tree only:
|
||||
|
||||
```bash
|
||||
npm install --package-lock=false --prefer-offline
|
||||
npm run build
|
||||
pnpm install --frozen-lockfile
|
||||
pnpm run build
|
||||
git worktree add /tmp/ai-for-dummies-pages --detach pages
|
||||
git -C /tmp/ai-for-dummies-pages rm -rf .
|
||||
cp -a dist/. /tmp/ai-for-dummies-pages/
|
||||
@@ -523,7 +523,7 @@ ordinary content recovery.
|
||||
- [ ] Portuguese static and dynamic copy is complete.
|
||||
- [ ] Mouse and keyboard interactions work.
|
||||
- [ ] Full HD, 4K, and mobile layouts remain readable.
|
||||
- [ ] `npm run verify`, `node --check app.js`, and `git diff --check` pass.
|
||||
- [ ] `pnpm run verify`, `node --check app.js`, and `git diff --check` pass.
|
||||
- [ ] `main` is pushed.
|
||||
- [ ] `pages` fast-forwards to the same commit.
|
||||
- [ ] Live endpoint returns HTTP 200 and contains the new section.
|
||||
|
||||
Generated
-9205
File diff suppressed because it is too large
Load Diff
+4
-4
@@ -30,9 +30,9 @@
|
||||
"stylelint-config-standard": "^39",
|
||||
"typescript": "^5.8.3"
|
||||
},
|
||||
"overrides": {
|
||||
"@astrojs/language-server": "2.15.0",
|
||||
"defu": "6.1.7",
|
||||
"vite": "6.2.1"
|
||||
"packageManager": "pnpm@11.25.0",
|
||||
"engines": {
|
||||
"node": ">=22.13",
|
||||
"pnpm": ">=11"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,29 +7,29 @@ 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** |
|
||||
|
||||
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.
|
||||
|
||||
@@ -8,13 +8,13 @@ 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.**
|
||||
|
||||
**Session state: see [`HANDOVER.md`](HANDOVER.md).** Phase 0 is done and
|
||||
green on four branches; nothing is merged or pushed.
|
||||
**Session state: see [`HANDOVER.md`](HANDOVER.md).** Phase 0 is done and green
|
||||
on four branches; nothing is merged or pushed.
|
||||
|
||||
## 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 |
|
||||
@@ -23,12 +23,13 @@ green on four branches; nothing is merged or pushed.
|
||||
## 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
|
||||
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.
|
||||
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.
|
||||
perfectly in `pnpm run preview` and 404 in production. Verify on the real
|
||||
host.
|
||||
|
||||
## Phases
|
||||
|
||||
@@ -41,7 +42,7 @@ 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 |
|
||||
@@ -75,14 +76,14 @@ cd ../af-task-08
|
||||
# .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**.
|
||||
The script runs `pnpm install --frozen-lockfile` 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
|
||||
pnpm 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
|
||||
```
|
||||
@@ -94,4 +95,5 @@ 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.
|
||||
you create will be missing it. Commit `plans/` and `.agents/` before fanning
|
||||
out.
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
# 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`
|
||||
**Blocks**: everything · **Worktree**:
|
||||
`.agents/scripts/worktree.sh start 01 scaffold`
|
||||
|
||||
## Goal
|
||||
|
||||
@@ -10,16 +11,16 @@ 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`.
|
||||
`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
|
||||
1. `pnpm 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.
|
||||
@@ -28,22 +29,25 @@ project (correct ignores for `hands-on/`, `submitted-skills/`, `vote-service/`).
|
||||
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`.
|
||||
5. `pnpm install husky lint-staged prettier eslint stylelint …`, then
|
||||
`pnpm exec 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
|
||||
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
|
||||
- [ ] `pnpm run build` succeeds; `pnpm 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
|
||||
- [ ] `/ai-for-dummies/summary/` serves correctly **from the real host**, not
|
||||
just preview
|
||||
- [ ] `docs/operations-guide.md` describes the actual publishing path
|
||||
|
||||
## Do not
|
||||
@@ -54,6 +58,6 @@ project (correct ignores for `hands-on/`, `submitted-skills/`, `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.
|
||||
The base path is the #1 production-only failure in this migration.
|
||||
`pnpm run preview` will lie to you. Deploy the smoke-test page and curl it with
|
||||
a `?v=<sha>` cache-buster.
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# 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`
|
||||
**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
|
||||
|
||||
@@ -14,11 +14,12 @@ This task is on the critical path. Do it early.
|
||||
|
||||
## Scope
|
||||
|
||||
`.agents/snapshots/`, `scripts/audit-ui.mjs`, `.agents/scripts/visual-regression.mjs`.
|
||||
`.agents/snapshots/`, `scripts/audit-ui.mjs`,
|
||||
`.agents/scripts/visual-regression.mjs`.
|
||||
|
||||
## Steps
|
||||
|
||||
1. `npm run serve` against the **current, unmigrated** site.
|
||||
1. `pnpm 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 \
|
||||
@@ -38,10 +39,12 @@ This task is on the critical path. Do it early.
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] Ten committed snapshots, each non-empty and containing that page's real prose
|
||||
- [ ] 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
|
||||
- [ ] 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
|
||||
- [ ] `pnpm run gate` green
|
||||
|
||||
## Do not
|
||||
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
# 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`
|
||||
calibrate the model routing before fanning out** **Depends on**: 02 ·
|
||||
**Blocks**: 08–11 **Worktree**:
|
||||
`.agents/scripts/worktree.sh start 07 primitives`
|
||||
|
||||
## Goal
|
||||
|
||||
@@ -36,7 +36,7 @@ you have found two components, not one.
|
||||
|
||||
- [ ] `.agents/checklists/before-component.md` complete for all four
|
||||
- [ ] Rendered output visually identical to the CSS classes they replace
|
||||
- [ ] `npm run gate` green
|
||||
- [ ] `pnpm 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.
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# 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`
|
||||
**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
|
||||
|
||||
@@ -10,7 +10,8 @@ The landing page's six chapter cards become one component over data.
|
||||
|
||||
## Scope
|
||||
|
||||
`src/components/blocks/RouteCard.astro`, `src/components/blocks/GridGroup.astro`.
|
||||
`src/components/blocks/RouteCard.astro`,
|
||||
`src/components/blocks/GridGroup.astro`.
|
||||
|
||||
## Source
|
||||
|
||||
@@ -30,7 +31,7 @@ title, summary, and href. Textbook extraction. Styles in `landing.css` +
|
||||
- [ ] 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
|
||||
- [ ] `.agents/checklists/before-component.md` complete; `pnpm run gate` green
|
||||
|
||||
## Do not
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# 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`
|
||||
**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
|
||||
|
||||
@@ -23,8 +23,8 @@ is the component.
|
||||
|
||||
## Watch for
|
||||
|
||||
- `TopBar` carries `aria-current="page"`. Preserve it; it is the only
|
||||
indication of location for assistive tech.
|
||||
- `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
|
||||
@@ -35,4 +35,4 @@ is the component.
|
||||
- [ ] All five pages' markup expressible with these components
|
||||
- [ ] Rendered text identical to current pages
|
||||
- [ ] Zero JS
|
||||
- [ ] Checklist complete; `npm run gate` green
|
||||
- [ ] Checklist complete; `pnpm run gate` green
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# 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`
|
||||
**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
|
||||
|
||||
@@ -25,7 +25,8 @@ Task 15 wires the interactivity.
|
||||
`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"`.
|
||||
`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.
|
||||
|
||||
@@ -41,4 +42,4 @@ screenshots agree.
|
||||
- [ ] 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
|
||||
- [ ] Checklist complete; `pnpm run gate` green
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# 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`
|
||||
**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
|
||||
|
||||
@@ -46,4 +46,4 @@ assistive tech. Colour alone is not enough. It is also asserted.
|
||||
- [ ] 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
|
||||
- [ ] Checklist complete; `pnpm run gate` green
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# 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`
|
||||
**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
|
||||
|
||||
@@ -27,4 +27,4 @@ Snapshot first (task 03 baseline exists — diff against it). Then compose from
|
||||
- [ ] `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
|
||||
- [ ] `.agents/checklists/before-page.md` complete; `pnpm run gate` green
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# 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`
|
||||
**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
|
||||
|
||||
@@ -25,7 +25,7 @@ Blocks 15 and 16 because those pages link here and share the layout.
|
||||
- [ ] 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
|
||||
- [ ] Checklist complete for each page; `pnpm run gate` green
|
||||
|
||||
## Do not
|
||||
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# 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`
|
||||
**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
|
||||
|
||||
@@ -24,10 +24,10 @@ 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.
|
||||
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
|
||||
- [ ] No external dependency; checklist complete; `pnpm run gate` green
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# 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`
|
||||
**Depends on**: 05, 10, 13 · **Parallel with**: 16 **Worktree**:
|
||||
`.agents/scripts/worktree.sh start 15 page-full-guide`
|
||||
|
||||
## Goal
|
||||
|
||||
@@ -21,7 +21,7 @@ toggle.
|
||||
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 |
|
||||
@@ -32,10 +32,11 @@ 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`.
|
||||
`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
|
||||
@@ -48,8 +49,8 @@ Also: `data-copy-target="prompt-install-skills|prompt-basic|prompt-skills"`,
|
||||
|
||||
- `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.
|
||||
- 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.
|
||||
|
||||
@@ -59,4 +60,5 @@ Also: `data-copy-target="prompt-install-skills|prompt-basic|prompt-skills"`,
|
||||
- [ ] 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
|
||||
- [ ] Screenshots match at four widths; checklist complete; `pnpm run gate`
|
||||
green
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
# 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`
|
||||
**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/`.
|
||||
`/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
|
||||
|
||||
@@ -44,7 +44,8 @@ Interaction tokens: `from './catalog.js'`, `from './files.js'`, `renderList`,
|
||||
`markdownMarkup`, `syncUrl`, `selectFromUrl`, `URLSearchParams`,
|
||||
`navigator.clipboard`, `document.execCommand`.
|
||||
|
||||
Plus the catalog count: `id:'` occurrences across both catalogs **must equal 24**.
|
||||
Plus the catalog count: `id:'` occurrences across both catalogs **must equal
|
||||
24**.
|
||||
|
||||
Same rule as task 15 — re-point with task 19, never delete.
|
||||
|
||||
@@ -60,4 +61,4 @@ needs raw source text**, not rendered HTML. Keep both available.
|
||||
- [ ] 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
|
||||
- [ ] `pnpm run gate` green
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# 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`
|
||||
**Depends on**: 15, 16 · **Parallel with**: 19 **Worktree**:
|
||||
`.agents/scripts/worktree.sh start 18 motion`
|
||||
|
||||
## Goal
|
||||
|
||||
@@ -13,7 +13,8 @@ Audit the motion that exists, add only motion that earns its place, and make
|
||||
|
||||
The audit is worth more than the additions.
|
||||
|
||||
1. Inventory every `transition`, `animation`, `@keyframes`, `transform` in `src/`.
|
||||
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.
|
||||
@@ -44,4 +45,4 @@ query params, and reduced motion. If any fails, do not ship it.
|
||||
- [ ] 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
|
||||
- [ ] Before/after captures attached; `pnpm run gate` green
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
# 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`
|
||||
**Agent**: `verification-engineer` · **Model**: Codex **Depends on**: 15, 16 ·
|
||||
**Parallel with**: 18 **Worktree**:
|
||||
`.agents/scripts/worktree.sh start 19 verify-repoint`
|
||||
|
||||
## Goal
|
||||
|
||||
@@ -15,27 +15,28 @@ 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/`.
|
||||
1. `pnpm 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`.
|
||||
`pnpm run verify`.
|
||||
|
||||
## Done when
|
||||
|
||||
- [ ] `grep -c 'throw new Error' scripts/verify.mjs` ≥ the `origin/main` baseline
|
||||
- [ ] `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
|
||||
- [ ] `pnpm run gate` green, and it **fails** when you deliberately delete a
|
||||
paragraph from a component (prove the net works, then revert)
|
||||
|
||||
## Do not
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
# 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`
|
||||
**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.
|
||||
|
||||
@@ -18,9 +19,9 @@ describe reality.
|
||||
`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/**`.
|
||||
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
|
||||
@@ -53,6 +54,6 @@ git rev-parse origin/pages # write it down
|
||||
- [ ] 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
|
||||
- [ ] Old files deleted; `pnpm run gate` green
|
||||
- [ ] Docs match reality
|
||||
- [ ] Previous `pages` SHA recorded for rollback
|
||||
|
||||
Generated
+5366
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,17 @@
|
||||
# pnpm 11 no longer reads the "pnpm" field in package.json; every setting that
|
||||
# used to live there (and npm's top-level "overrides") belongs here instead.
|
||||
# See https://pnpm.io/settings
|
||||
|
||||
# Was npm's top-level "overrides". These pins are load-bearing: dropping them
|
||||
# silently changes the resolved vite/language-server versions.
|
||||
overrides:
|
||||
'@astrojs/language-server': 2.15.0
|
||||
defu: 6.1.7
|
||||
vite: 6.2.1
|
||||
|
||||
# pnpm blocks dependency postinstall scripts by default. Astro's build needs
|
||||
# both of these: esbuild verifies its platform binary, sharp its libvips
|
||||
# prebuild. Anything not listed here stays blocked, which is the point.
|
||||
allowBuilds:
|
||||
esbuild: true
|
||||
sharp: true
|
||||
Reference in New Issue
Block a user