@erclx/canon 4.102.0 → 4.104.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (74) hide show
  1. package/claude/.claude-plugin/plugin.json +1 -1
  2. package/claude/skills/canon-cli/SKILL.md +3 -74
  3. package/claude/skills/canon-operator/REQUIREMENT.md +2 -2
  4. package/claude/skills/canon-operator/SKILL.md +5 -5
  5. package/claude/skills/canon-rollout/SKILL.md +7 -6
  6. package/claude/skills/design-taste/references/craft.md +1 -1
  7. package/claude/skills/design-taste/references/preflight.md +2 -2
  8. package/claude/skills/design-taste/references/tells.md +1 -1
  9. package/claude/skills/draft-readme/REQUIREMENT.md +2 -0
  10. package/claude/skills/draft-readme/SKILL.md +9 -1
  11. package/claude/skills/git-followup/SKILL.md +1 -1
  12. package/claude/skills/git-issue/SKILL.md +2 -2
  13. package/{standards → claude/skills/git-issue/references}/issue.md +3 -8
  14. package/claude/skills/git-pr/SKILL.md +2 -2
  15. package/claude/skills/index-lookup/REQUIREMENT.md +2 -2
  16. package/claude/skills/project-commands/REQUIREMENT.md +1 -1
  17. package/claude/skills/seed-sync/REQUIREMENT.md +1 -1
  18. package/claude/skills/target-check/REQUIREMENT.md +42 -0
  19. package/claude/skills/target-check/SKILL.md +91 -0
  20. package/claude/skills/target-check/references/domains.md +88 -0
  21. package/claude/skills/target-setup/REQUIREMENT.md +56 -0
  22. package/claude/skills/target-setup/SKILL.md +163 -0
  23. package/claude/skills/target-setup/references/detect.md +80 -0
  24. package/claude/skills/{setup-indexes/SKILL.md → target-setup/references/indexes.md} +59 -23
  25. package/claude/skills/target-setup/references/verify.md +95 -0
  26. package/claude/skills/ui-checklist/SKILL.md +17 -0
  27. package/docs/agents/commands.md +1 -1
  28. package/docs/agents/sandbox.md +1 -1
  29. package/docs/agents/scripting.md +3 -2
  30. package/docs/target-projects.md +13 -11
  31. package/docs/workflow/ai-workflow.md +19 -23
  32. package/governance/rules/ci/700-ci-workflow.md +11 -0
  33. package/governance/rules/ui/400-ui.md +0 -5
  34. package/governance/rules/ui/460-design-taste.md +1 -1
  35. package/governance/rules/ui/465-interface-casing.md +31 -0
  36. package/governance/stacks/astro.toml +1 -1
  37. package/governance/stacks/react.toml +1 -1
  38. package/package.json +1 -1
  39. package/scripts/core/regen-hero.sh +1 -1
  40. package/scripts/core/regen-web-previews.ts +1 -0
  41. package/src/claude/cases/setup.ts +20 -11
  42. package/src/commands/design.ts +8 -2
  43. package/src/commands/sync.ts +1 -1
  44. package/src/design/css.ts +5 -2
  45. package/src/design/render.ts +46 -6
  46. package/src/gate/measures.ts +57 -0
  47. package/src/gate/stages.ts +10 -14
  48. package/src/gov/list.ts +1 -1
  49. package/src/sandbox/census.ts +3 -3
  50. package/src/shipped/references.ts +1 -1
  51. package/standards/index.md +0 -1
  52. package/standards/readme.md +22 -3
  53. package/tooling/astro/manifest.toml +1 -0
  54. package/tooling/nextjs/manifest.toml +1 -0
  55. package/tooling/web/configs/.github/workflows/readme-screenshot.yml +110 -0
  56. package/tooling/web/configs/e2e/screenshot.ts +69 -15
  57. package/tooling/web/configs/scripts/lib/preview-server.sh +31 -0
  58. package/tooling/web/configs/scripts/readme-screenshot.sh +26 -0
  59. package/tooling/web/configs/scripts/screenshot.sh +1 -24
  60. package/tooling/web/manifest.toml +1 -0
  61. package/tooling/web/reference.md +6 -1
  62. package/claude/skills/setup-gov/REQUIREMENT.md +0 -37
  63. package/claude/skills/setup-gov/SKILL.md +0 -77
  64. package/claude/skills/setup-indexes/REQUIREMENT.md +0 -48
  65. package/claude/skills/setup-init/REQUIREMENT.md +0 -46
  66. package/claude/skills/setup-init/SKILL.md +0 -133
  67. package/claude/skills/setup-plugins/REQUIREMENT.md +0 -42
  68. package/claude/skills/setup-plugins/SKILL.md +0 -81
  69. package/claude/skills/setup-plugins/references/plugin-catalog.md +0 -53
  70. package/claude/skills/setup-smoke/REQUIREMENT.md +0 -38
  71. package/claude/skills/setup-smoke/SKILL.md +0 -53
  72. package/claude/skills/setup-verify/REQUIREMENT.md +0 -39
  73. package/claude/skills/setup-verify/SKILL.md +0 -51
  74. package/scripts/core/regen-tooling-paths.sh +0 -61
@@ -0,0 +1,56 @@
1
+ ---
2
+ name: target-setup
3
+ description: Why getting a project onto the toolkit is one skill with phases rather than a family a session has to pick among
4
+ ---
5
+
6
+ # Setup requirement
7
+
8
+ ## Gap
9
+
10
+ Without this skill, a session facing a project that does not carry the toolkit
11
+ resolves the stack by hand, picks per-domain install commands from the CLI
12
+ surface, and runs them in an order nothing states. The install logic lives in
13
+ `canon init`, so what is missing is not the writing but the reading: which stack
14
+ matches this project, which extras it needs beyond the stack, and what the
15
+ commands will do before they run.
16
+
17
+ The naive shape is one skill per phase, and it failed on discrimination rather
18
+ than on content. Six descriptions covering one job made the model pick among
19
+ them on wording, and the two that split on how heavy their checks are gave a
20
+ session no way to tell from the catalog which one a scaffold wanted. A phase
21
+ argument answers the same question by naming the depth rather than by choosing
22
+ between two bodies that differ in a table.
23
+
24
+ Merging also closes a class of drift the family carried. Detection was stated
25
+ twice, once for the full chain and once for the governance-only route, and the
26
+ two copies could disagree with nothing comparing them.
27
+
28
+ ## Must
29
+
30
+ - Read the toolkit catalogs before resolving, and hardcode no stack, rule, or snippet name
31
+ - Preview the resolved arguments and the exact commands before the first write
32
+ - Mark a fallback resolution as a fallback in the preview, where it can still be declined
33
+ - Run every phase without a TTY, and carry an argument for each prompt a phase would otherwise open
34
+ - Reach each phase alone, so a caller wanting one layer does not run the chain to get it
35
+ - Name a destination for each state the chain declines rather than ending on the refusal
36
+
37
+ ## Must not
38
+
39
+ - Guard against clobbering an existing project's configs, which routes to `canon-operator` instead
40
+ - Author a rule or a stack in the target project on the fly
41
+ - Generate a config the tooling stack ships as a golden file
42
+ - Install Claude Code plugins, which provision a machine rather than a project
43
+ - Fail an unattended scaffold on a server start, which is flaky enough to be a depth the operator asks for
44
+ - Survive as a skill nothing invokes but a person typing its name. `canon-operator` hands first-time scaffold here and the target-projects page names it as the scaffold step, so a later read finding no caller but the author has found a body that should have stayed a verb
45
+
46
+ ## Guards
47
+
48
+ - No `package.json` at the project root stops the verify phase, since there are no declared scripts to read
49
+ - A missing dependency folder installs first rather than letting every script fail on the same cause
50
+ - A detected technology with no matching rule surfaces rather than resolving to a guess
51
+
52
+ ## Out of scope
53
+
54
+ - An existing project's per-domain drift, which `canon-operator` diagnoses and `target-check` reports
55
+ - Reaching a remote or the project's history, which `repo-metadata` and `git-commit` own
56
+ - Provisioning Claude Code plugins on a machine, which the `claude plugin` CLI does directly
@@ -0,0 +1,163 @@
1
+ ---
2
+ name: target-setup
3
+ description: Gets a project onto the toolkit. Detects the stack, resolves per-domain arguments, previews the chain, runs `canon init`, then verifies at a stated depth and bootstraps the `index.md` system. Use when asked to "set up this project", "init this project", "bootstrap the toolkit", "install governance", "install gov rules", "set up indexes", "verify the scaffold", "run the smoke tests", or "one-shot install". Assumes the `canon` CLI is on PATH. Do NOT use on a project that already carries the toolkit, which is `canon-operator`, or to report per-domain drift without repairing it, which is `target-check`.
4
+ ---
5
+
6
+ # Setup
7
+
8
+ Gets a project onto the toolkit. Detects project type, resolves per-domain
9
+ arguments, previews the chain, runs `canon init`, then verifies what landed and
10
+ bootstraps the `index.md` system over the project's own documentation folders.
11
+
12
+ The CLI holds the install logic. This skill resolves, previews, and routes. It
13
+ reimplements no verb and hardcodes no stack, rule, or snippet name.
14
+
15
+ ## Phases
16
+
17
+ Five phases run in order on a bare invocation. Each is also reachable alone, so
18
+ a caller wanting one layer does not run the chain to get it.
19
+
20
+ | Phase | What it does | Reached alone by |
21
+ | --------- | ----------------------------------------------------------- | --------------------- |
22
+ | `detect` | Reads the project and resolves stack arguments | `setup detect` |
23
+ | `install` | Runs `canon init` and the tooling sync | `setup install` |
24
+ | `gov` | Installs governance rules and nothing else | `setup gov` |
25
+ | `verify` | Runs the installed scripts at a stated depth | `setup verify [deep]` |
26
+ | `indexes` | Bootstraps the `index.md` system over documentation folders | `setup indexes` |
27
+
28
+ An argument naming a phase runs that phase and stops. A bare invocation runs
29
+ `detect`, `install`, `verify`, then `indexes`. `gov` is a narrowing of `install`
30
+ rather than a step within it, so the full chain never runs it separately.
31
+
32
+ ## Non-interactive path
33
+
34
+ Every phase runs under `CANON_NON_INTERACTIVE=1` with no TTY. Two phases
35
+ otherwise pause, and each takes an argument that answers its prompt ahead of
36
+ time:
37
+
38
+ - `indexes` confirms its folder list with the operator. `setup indexes --all`
39
+ takes every candidate the scan found, and `--folders <a>,<b>` takes a named
40
+ set. With neither, and with no TTY, the phase reports its candidates and stops
41
+ rather than choosing for the operator.
42
+ - `gov` stops on a detected technology with no matching rule. `--skip-gaps`
43
+ proceeds with the matched layer and lists the gap in the report.
44
+
45
+ Claude Code's tool permission dialog is the confirmation gate for everything
46
+ else. Do not pause for a separate confirmation.
47
+
48
+ ## Scope
49
+
50
+ - This skill and `canon init` run once on a fresh scaffold, never on an existing project. They do not guard against clobbering existing configs. When tempted to add guards, mode switches, or an existing-project branch, stop. Extend the per-domain `canon <domain> install` or `canon sync` paths instead.
51
+ - The chain stops at the project edge. `repo-metadata` and `git-commit` also ship, reaching a remote and the project's history respectively, and neither runs here.
52
+ - Claude Code plugins are a machine concern rather than a project one, so no phase here installs them. Install them with `claude plugin install <name> --scope user`, which applies in every project on the machine and is copied into none.
53
+
54
+ ## Declined states
55
+
56
+ Three states reach this skill that the chain does not serve. Name the destination for each, so the refusal routes rather than ends. The first two stop the chain outright and the third runs it on a default the person may not want.
57
+
58
+ - **An existing project.** Stop and hand off to `canon-operator`. It reads what the target already carries before it names a command, which this chain never does, so any per-domain install picked here is a guess against configs nobody read. The Scope bullet above names the same commands as the authoring alternative, and this is the destination a person takes.
59
+ - **An install wanting the `.claude/` folder alone.** Stop. Run `canon claude init` for the seed docs, then run the `indexes` phase over the project's own documentation folders. Neither needs the tooling sync the `install` phase runs.
60
+ - **A language the toolkit carries no stack for.** The chain still runs, on `base`, with the fallback marked in the preview. A project that wants none of what `base` carries declines there and takes the `gov` phase, which is language-neutral and installs rules without the `base` development dependencies the tooling layer would drop on it. Say so at the preview rather than resolving it here, since the fallback is a working default and only the person can say whether it fits.
61
+
62
+ Do not add a stack, a mode switch, or an existing-project branch to satisfy one of these. Each destination already exists and routing to it costs a line.
63
+
64
+ ## Phase: detect
65
+
66
+ Read `${CLAUDE_SKILL_DIR}/references/detect.md`. It holds the catalog reads, the
67
+ evidence list, the argument resolution, the gap handling, and the preview, which
68
+ the `install` and `gov` phases share rather than each stating.
69
+
70
+ ## Phase: install
71
+
72
+ Run the chain in order, starting immediately after the preview. Run from the
73
+ target project's current directory. Do not cd into the toolkit source tree. The
74
+ `canon` CLI is global.
75
+
76
+ Step 1: `canon init` installs base tooling, claude seeds, governance rules, and wiki.
77
+
78
+ ```bash
79
+ CANON_NON_INTERACTIVE=1 canon init \
80
+ --stack <stack> \
81
+ --add <rules> \
82
+ <target>
83
+ ```
84
+
85
+ Omit any flag whose resolved value is empty.
86
+
87
+ Step 2: `canon tooling sync <tooling-stack> --write` installs stack deps, scripts, gitignore entries, seeds, golden configs, and drops the reference doc. The extends chain is walked, so syncing `vite-react` also pulls `web` and `base` configs. Skip if the tooling stack is `base` (already synced by `canon init`).
88
+
89
+ `--write` is required. A headless run without it reports what it would replace and exits 1, since golden configs overwrite whatever the target holds at those paths. Scaffolding into a fresh target has nothing to lose, so pass it directly rather than reading a report first.
90
+
91
+ ```bash
92
+ CANON_NON_INTERACTIVE=1 canon tooling sync <tooling-stack> <target> --write
93
+ ```
94
+
95
+ Monorepo with multiple language roots: run `canon init` once at the repo root so `base` (husky, prettier, cspell, commitlint, CI) lands single, then sync each subtree with `--skip base` so the shared layer is not re-dropped.
96
+
97
+ ```bash
98
+ CANON_NON_INTERACTIVE=1 canon tooling sync vite-react ./frontend --skip base --write
99
+ CANON_NON_INTERACTIVE=1 canon tooling sync python ./backend --skip base --write
100
+ ```
101
+
102
+ Without `--skip base`, each subtree re-drops husky, and git honors only one `core.hooksPath`, so the extra hook dirs silently break. Each subtree keeps its own framework configs, and its own stack reference reads through `canon tooling reference <stack>`.
103
+
104
+ Step 3: post-sync fixups. Golden configs arrive from sync, so no config generation is required. But a few items may need a one-time touch:
105
+
106
+ - **ESLint version pin.** If `bun create vite` installed `eslint@^10` and the manifest pins `eslint@^9`, sync does not override a present dep. Run `bun add -d eslint@^9` if `bun run lint:fix` fails with `Class extends value undefined`.
107
+ - **File naming.** `bun create vite`'s `App.tsx` violates the `KEBAB_CASE` rule. Rename to `app.tsx` and update the import in `main.tsx`.
108
+ - **Docs.** Run `canon tooling reference <tooling-stack>` and `canon tooling reference web` for any stack-specific follow-ups (Chrome extension overrides, setup script details).
109
+
110
+ Do not generate ESLint, Vitest, or Playwright configs. They ship as golden files. Generating from prose duplicates what sync already installed.
111
+
112
+ ## Phase: gov
113
+
114
+ Governance rules and nothing else, for a project declining the tooling layer.
115
+ Resolve exactly as the detect reference states, then run:
116
+
117
+ ```bash
118
+ CANON_NON_INTERACTIVE=1 canon gov install <stack> --add <extras> <target>
119
+ ```
120
+
121
+ Report the rule count installed, the target path, and any rules that failed to
122
+ resolve, which the CLI warns on.
123
+
124
+ ## Phase: verify
125
+
126
+ Read `${CLAUDE_SKILL_DIR}/references/verify.md`. It holds both depths and the
127
+ script chain each runs. The default depth runs the leaf scripts and reports pass
128
+ or fail per script. `deep` adds the dev and preview server smoke, the end-to-end
129
+ suite, and the screenshot harness.
130
+
131
+ The chain runs the default depth. `deep` is the operator's call rather than the
132
+ chain's, since a slow server start reads as a failure and an unattended run
133
+ should not fail a scaffold on that.
134
+
135
+ ## Phase: indexes
136
+
137
+ Read `${CLAUDE_SKILL_DIR}/references/indexes.md`. It holds the scan, the
138
+ frontmatter drafting, the scaffold, the validate step, and the convention seed
139
+ offer.
140
+
141
+ This phase confirms candidate folders with the operator rather than running
142
+ unattended, which is the one phase in the chain that pauses for a conversation
143
+ unless `--all` or `--folders` answered it ahead of time. A fresh scaffold usually
144
+ has no markdown-heavy folder yet, so this phase frequently finds nothing to
145
+ present, which its reference defines as its own outcome rather than a failure of
146
+ the chain.
147
+
148
+ ## Report
149
+
150
+ After the chain, report:
151
+
152
+ - Domains installed, with a check per domain
153
+ - Tooling stack synced, or skipped. Name the layers pulled via the extends chain.
154
+ - Any post-sync fixups applied (ESLint pin, filename renames)
155
+ - `verify` outcome, naming the depth it ran at
156
+ - `indexes` outcome (folders bootstrapped, or none found)
157
+ - Any domains or scripts that failed
158
+ - Any detection gaps surfaced during resolve
159
+ - Claude Code plugins as an onboarding step this chain does not cover, so a clean result does not read as onboarding complete
160
+
161
+ A resolved name and a fallback read alike once written, so the preview marks the
162
+ fallback rather than this report. The preview is the last point before the first
163
+ write, and the report runs after the files have landed.
@@ -0,0 +1,80 @@
1
+ ---
2
+ title: Detect and resolve
3
+ description: The catalog reads, evidence list, argument resolution, gap handling, and preview the install and gov phases share
4
+ ---
5
+
6
+ # Detect and resolve
7
+
8
+ What the `install` and `gov` phases both do before they write anything. Stated
9
+ once here rather than twice in the body, since the two phases differ in what
10
+ they install rather than in how they read the project.
11
+
12
+ ## Read the catalogs
13
+
14
+ Run in parallel. Never hardcode stack, rule, snippet, or standards names. The
15
+ catalog is the source of truth.
16
+
17
+ Run from the target project's current directory. Do not cd into the toolkit
18
+ source tree. The `canon` CLI is global.
19
+
20
+ ```bash
21
+ canon gov list --json 2>/dev/null
22
+ canon tooling list --json 2>/dev/null
23
+ ```
24
+
25
+ The `gov` phase needs only the first. Run both anyway on a bare invocation,
26
+ since the chain reaches the tooling resolution a moment later.
27
+
28
+ ## Detect
29
+
30
+ Read these from the project root in parallel, skipping any that do not exist:
31
+
32
+ - `package.json`: `dependencies` and `devDependencies`
33
+ - Root configs: `astro.config.*`, `next.config.*`, `vite.config.*`, `tailwind.config.*`, `tsconfig.json`, `pyproject.toml`, `go.mod`, `Cargo.toml`
34
+ - `canon/REQUIREMENTS.md` and `canon/ARCHITECTURE.md` if present
35
+ - Directory structure via `ls -1` of the project root and `src/` if present
36
+
37
+ ## Resolve arguments
38
+
39
+ - **Stack:** pick the closest governance stack by matching detected runtime or framework against stack names in the catalog. If nothing matches, fall back to `base` and carry the fallback into the preview.
40
+ - **Tooling stack:** pick the closest tooling stack from `canon tooling list --json` (e.g. `vite-react`, `astro`, `nextjs`). Distinct from the governance stack. Fall back to `base` if no framework match, and carry that fallback into the preview too.
41
+ - **Next.js:** map `next` in `package.json` dependencies, or a root `next.config.ts`/`.js`/`.mjs` file, to the `nextjs` tooling stack. The dependency name does not match the stack name by itself.
42
+ - **Extras:** identify technologies not already covered by the picked stack. For each, find a rule whose `description` or `paths` points at that technology and pass it via `--add`. Dedupe against the stack's own rules. Do not add a rule the stack already pulls in.
43
+ - **Skip (`--skip`):** `wiki` installs by default. Add `--skip wiki` only when the user explicitly wants it left out.
44
+
45
+ ## Gap handling
46
+
47
+ If a detected technology has no matching rule or stack, do not guess. Surface
48
+ the gap.
49
+
50
+ On the full chain, either defer and author a rule in the toolkit before
51
+ re-running, or proceed with the matched layer and list the gap in the final
52
+ report. Rules and stacks are authored in the toolkit repository, never in the
53
+ target project on the fly.
54
+
55
+ On the `gov` phase, stop and present four options rather than picking:
56
+
57
+ 1. Author a new rule in the toolkit at `governance/rules/<domain>/<num>-<name>.md` following `${CLAUDE_SKILL_DIR}/../../standards/rule.md`, commit, then re-run install. Take this route when the toolkit should ship the rule to every project.
58
+ 2. Invoke `create-rule`, which scaffolds the file into the target project at a non-colliding number. Take this route when the rule is specific to this project and no sync should ever overwrite it.
59
+ 3. Install the matching non-`<tech>` rules and skip the tech-specific layer.
60
+ 4. Abort.
61
+
62
+ `--skip-gaps` takes option 3 ahead of the prompt, which is what keeps the phase
63
+ non-interactive. This skill authors no rule itself. Option 1 writes in the
64
+ toolkit repository, and option 2 hands the project-local file to `create-rule`.
65
+
66
+ ## Preview
67
+
68
+ Before executing, output:
69
+
70
+ - **Detected:** each technology with its evidence file
71
+ - **Stack:** picked governance stack and resolved rule count. Mark it `fallback` when no detected runtime or framework matched a catalog name.
72
+ - **Tooling stack:** picked tooling stack. Mark it `fallback` on the same test, and name what `base` lands: configs, seeds, and gitignore entries in every case, plus the JavaScript development dependencies, scripts, and hook activation wherever a `package.json` exists to carry them. A project outside that ecosystem runs none of the second group and keeps the first. Omit this line entirely on the `gov` phase, which syncs no tooling.
73
+ - **Extras:** each `--add` rule with a one-line reason
74
+ - **Skip:** any `--skip` entries with reason
75
+ - **Target:** resolved target path
76
+ - **Commands:** the full chain that will run
77
+
78
+ A resolved name and a fallback read alike once written, so mark the fallback
79
+ here rather than in the report. The preview is the last point before the first
80
+ write, and the report runs after the files have landed.
@@ -1,25 +1,32 @@
1
1
  ---
2
- name: setup-indexes
3
- description: Bootstraps the toolkit's `index.md` system in a target project. Scans for markdown-heavy folders, drafts `title` and `description` frontmatter, scaffolds `index.md` per chosen folder, and runs `canon indexes regen` to validate. Use when asked to "set up indexes", "bootstrap indexes", "add index.md to this project", or "install indexes". Assumes the `canon` CLI is on PATH.
2
+ title: Indexes bootstrap
3
+ description: The scan, frontmatter drafting, scaffold, validate, and convention seed phases that add the index.md system to a project
4
4
  ---
5
5
 
6
- # Indexes install
6
+ # Indexes bootstrap
7
7
 
8
- Adds the index.md system to a project that does not have it. Operates in the active Claude session: Claude reads files, drafts frontmatter, confirms with the user, and writes. The CLI handles validation and regeneration only.
8
+ Adds the `index.md` system to a project that does not have it. Operates in the
9
+ active Claude session: Claude reads files, drafts frontmatter, confirms with the
10
+ user, and writes. The CLI handles validation and regeneration only.
9
11
 
10
- Read `canon docs indexes` from the toolkit if context on the system is needed before scanning.
12
+ Read `canon docs indexes` from the toolkit if context on the system is needed
13
+ before scanning.
11
14
 
12
15
  ## Scope
13
16
 
14
17
  - Bootstrap un-indexed folders only. Skip folders that already contain an `index.md`.
15
18
  - All-or-nothing per chosen folder. Every `*.md` sibling in a chosen folder gets `title` and `description` injected, or none does. Partial migration creates folders that hard-error on regen.
16
- - This is where `setup-init` sends an install that wants the Claude layer without the tooling chain, once `canon claude init` has seeded the docs. The work is the same either way, since the scan below prunes `.claude` and reads the project's own documentation folders whichever route reached it.
19
+ - This phase is where an install wanting the Claude layer without the tooling chain arrives, once `canon claude init` has seeded the docs. The work is the same either way, since the scan below prunes `.claude` and reads the project's own documentation folders whichever route reached it.
17
20
 
18
21
  ## Scan
19
22
 
20
- Walk the project root for folders containing three or more sibling `*.md` files. Prune `.git`, `node_modules`, `.claude`, `snippets`, anything matched by `.gitignore`, and any folder that already contains an `index.md`.
23
+ Walk the project root for folders containing three or more sibling `*.md` files.
24
+ Prune `.git`, `node_modules`, `.claude`, `snippets`, anything matched by
25
+ `.gitignore`, and any folder that already contains an `index.md`.
21
26
 
22
- Skip `.claude/snippets/`. Snippets are invoked by reference (`@snippet-name`) rather than browsed, so they need neither `index.md` nor per-file frontmatter. Adding them creates noise that targets keep reporting.
27
+ Skip `.claude/snippets/`. Snippets are invoked by reference (`@snippet-name`)
28
+ rather than browsed, so they need neither `index.md` nor per-file frontmatter.
29
+ Adding them creates noise that targets keep reporting.
23
30
 
24
31
  For each candidate, capture:
25
32
 
@@ -35,7 +42,9 @@ If the scan found no candidate, report the flat result and skip ahead:
35
42
  No folder has three or more markdown siblings without an index.md already. Nothing to bootstrap.
36
43
  ```
37
44
 
38
- Skip past the ask below and every step between it and the seed offer, straight to `## Offer the convention seed`. There is no candidate to ask about, so this stops rather than opening a prompt with nothing in it.
45
+ Skip past the ask below and every step between it and the seed offer, straight
46
+ to `## Offer the convention seed`. There is no candidate to ask about, so this
47
+ stops rather than opening a prompt with nothing in it.
39
48
 
40
49
  Output one line per candidate:
41
50
 
@@ -45,7 +54,12 @@ Output one line per candidate:
45
54
  - references/ (3 files, 0/3 with frontmatter)
46
55
  ```
47
56
 
48
- Ask the user which to bootstrap. Accept folder paths, `all`, or `none`. The user can also force a folder with fewer than three siblings by naming it explicitly.
57
+ Ask the user which to bootstrap. Accept folder paths, `all`, or `none`. The user
58
+ can also force a folder with fewer than three siblings by naming it explicitly.
59
+
60
+ `--all` and `--folders <a>,<b>` answer this ask ahead of time, which is what
61
+ keeps the phase non-interactive. With neither, and with no TTY, report the
62
+ candidate list and stop rather than choosing on the operator's behalf.
49
63
 
50
64
  ## Draft frontmatter
51
65
 
@@ -62,9 +76,13 @@ docs/architecture.md
62
76
  description: System boundaries, data flow, and module responsibilities
63
77
  ```
64
78
 
65
- The user accepts, edits, or rejects per file. Offer "accept all remaining" once the user confirms two in a row to keep the loop short.
79
+ The user accepts, edits, or rejects per file. Offer "accept all remaining" once
80
+ the user confirms two in a row to keep the loop short.
66
81
 
67
- Never write drafts before the user confirms. Drafted text is a proposal, not a commit.
82
+ Never write drafts before the user confirms. Drafted text is a proposal, not a
83
+ commit. A run that took `--all` or `--folders` confirmed the folder set rather
84
+ than each draft, so surface the drafts as a batch and write them without a
85
+ second ask.
68
86
 
69
87
  ## Scaffold the folder index
70
88
 
@@ -81,9 +99,12 @@ Surface the proposed `title` and `subtitle` and let the user edit before writing
81
99
 
82
100
  ## Inject
83
101
 
84
- After all confirmations, write frontmatter into each sibling and `index.md` into each folder. Use a single batched write per file.
102
+ After all confirmations, write frontmatter into each sibling and `index.md` into
103
+ each folder. Use a single batched write per file.
85
104
 
86
- Preserve existing content below the frontmatter block. If a sibling already has frontmatter without `title` or `description`, merge in the missing fields. Do not touch files the user rejected.
105
+ Preserve existing content below the frontmatter block. If a sibling already has
106
+ frontmatter without `title` or `description`, merge in the missing fields. Do not
107
+ touch files the user rejected.
87
108
 
88
109
  ## Validate
89
110
 
@@ -93,22 +114,28 @@ Run from the project root:
93
114
  canon indexes regen --dry-run --json
94
115
  ```
95
116
 
96
- Parse the JSON. On any `error` action, surface the file and reason and stop. On `would-write` for the bootstrapped folders, the dry-run is healthy. Run for real:
117
+ Parse the JSON. On any `error` action, surface the file and reason and stop. On
118
+ `would-write` for the bootstrapped folders, the dry-run is healthy. Run for real:
97
119
 
98
120
  ```bash
99
121
  canon indexes regen --json
100
122
  ```
101
123
 
102
- Count the `written` actions in that record and report the number. Read the real run the same way the dry run is read, since the exit carries nothing reliable back to a session. An operator's shell profile may wrap `canon` in a function that runs the binary and then a second command and takes the second status, so a regen that errored on a sibling missing `title` arrives here as a clean pass.
124
+ Count the `written` actions in that record and report the number. Read the real
125
+ run the same way the dry run is read, since the exit carries nothing reliable
126
+ back to a session. An operator's shell profile may wrap `canon` in a function
127
+ that runs the binary and then a second command and takes the second status, so a
128
+ regen that errored on a sibling missing `title` arrives here as a clean pass.
103
129
 
104
130
  ## Offer the convention seed
105
131
 
106
- First check whether `CLAUDE.md` exists in the project root. If absent, do not scaffold one. Skip the seed install with this exact message:
132
+ First check whether `CLAUDE.md` exists in the project root. If absent, do not
133
+ scaffold one. Skip the seed install with this exact message:
107
134
 
108
135
  ```plaintext
109
136
  No CLAUDE.md in the project. Skipping convention seed.
110
137
  To add the convention later, run `canon tooling sync` or `canon init`,
111
- then re-invoke this skill.
138
+ then re-invoke this phase.
112
139
  ```
113
140
 
114
141
  If `CLAUDE.md` exists, check it for an existing `## Indexes` section:
@@ -119,7 +146,10 @@ grep -l '^## Indexes' CLAUDE.md 2>/dev/null
119
146
 
120
147
  If the section is present, skip the seed silently.
121
148
 
122
- If `CLAUDE.md` exists but has no `## Indexes` section, offer to install the canonical convention block. The text below is the source of truth and is mirrored in the toolkit's `tooling/claude/seeds/CLAUDE.md`. Paste it verbatim. Do not rewrite, paraphrase, condense, or add punctuation.
149
+ If `CLAUDE.md` exists but has no `## Indexes` section, offer to install the
150
+ canonical convention block. The text below is the source of truth and is
151
+ mirrored in the toolkit's seed `CLAUDE.md`. Paste it verbatim. Do not rewrite,
152
+ paraphrase, condense, or add punctuation.
123
153
 
124
154
  ```markdown
125
155
  - When a folder has an `index.md`, check it before reading individual files in that folder.
@@ -127,11 +157,16 @@ If `CLAUDE.md` exists but has no `## Indexes` section, offer to install the cano
127
157
  - Every `index.md` carries its own frontmatter (`title`, `subtitle`) that the walker preserves. To keep a folder's `index.md` hand-edited, add `auto: false` to its frontmatter.
128
158
  ```
129
159
 
130
- Append a new `## Indexes` section at the end of the file containing the three lines. Do not touch any other section.
160
+ Append a new `## Indexes` section at the end of the file containing the three
161
+ lines. Do not touch any other section.
131
162
 
132
163
  ## Closeout
133
164
 
134
- Always emit this block as the final message of the skill run. Do not skip it regardless of how the seed step concluded (installed, already present, declined, or skipped because no `CLAUDE.md` exists). Output exactly one closeout, even if the seed step paused for user input. Resume the flow after the user responds and emit the closeout next.
165
+ Always emit this block as the final message of the phase. Do not skip it
166
+ regardless of how the seed step concluded (installed, already present, declined,
167
+ or skipped because no `CLAUDE.md` exists). Output exactly one closeout, even if
168
+ the seed step paused for user input. Resume the flow after the user responds and
169
+ emit the closeout next.
135
170
 
136
171
  Format:
137
172
 
@@ -144,14 +179,15 @@ Folders bootstrapped:
144
179
  Drafts: <n> accepted, <n> edited, <n> rejected
145
180
  Convention seed: <installed | already present | declined | skipped (no CLAUDE.md)>
146
181
 
147
- Optional maintenance (opt in, the skill does not configure these):
182
+ Optional maintenance (opt in, the phase does not configure these):
148
183
  - lint-staged entry in .lintstagedrc.json:
149
184
  "**/*.md": "canon indexes regen"
150
185
  - Claude Code PostToolUse hook on Edit and Write matching **/*.md running:
151
186
  canon indexes regen
152
187
  ```
153
188
 
154
- Replace bracketed values with the values from this run. Drop the "Folders bootstrapped" line if zero folders were chosen.
189
+ Replace bracketed values with the values from this run. Drop the "Folders
190
+ bootstrapped" line if zero folders were chosen.
155
191
 
156
192
  ## Reference
157
193
 
@@ -0,0 +1,95 @@
1
+ ---
2
+ title: Verify depths
3
+ description: The two verification depths and the script chain each runs against a freshly scaffolded project
4
+ ---
5
+
6
+ # Verify depths
7
+
8
+ Runs the local verification chain against a freshly scaffolded project. Catches
9
+ config typos, missing deps, and wiring mistakes before the user ever sees them.
10
+
11
+ Two depths over one contract. Both read the `scripts` block from the project's
12
+ own `package.json` and run what is declared there, so neither hardcodes a script
13
+ name and a stack exposing a different set is covered without an edit here.
14
+
15
+ ## Guards
16
+
17
+ - If `package.json` does not exist at the project root, stop: `❌ No package.json found. Cannot verify.`
18
+ - If `node_modules/` does not exist, run `bun install` first, then proceed.
19
+
20
+ ## Step 1: read scripts
21
+
22
+ Read `package.json` from the project root and extract the `scripts` block. Do
23
+ not hardcode script names. Different stacks expose different scripts.
24
+
25
+ ## Step 2: run the chain
26
+
27
+ Run the scripts for the requested depth in order. Stop on the first failure and
28
+ surface the error. Skip any script not present in `package.json`. Do not invent
29
+ a fallback command. Run each as `bun run <script>` from the project root.
30
+
31
+ ### Default depth
32
+
33
+ Every script is a leaf command, so failures point at the exact break and the
34
+ exit code is the whole verdict.
35
+
36
+ | Order | Script | Skip if |
37
+ | ----- | ----------- | --------------------------- |
38
+ | 1 | `lint:fix` | absent |
39
+ | 2 | `typecheck` | absent |
40
+ | 3 | `check` | absent |
41
+ | 4 | `test:run` | absent, fall back to `test` |
42
+ | 5 | `build` | absent |
43
+
44
+ Do not run composite scripts like `check:full`. Do not run `dev`, `preview`,
45
+ `test:e2e`, `test:ui`, or `screenshot` at this depth. They belong to `deep`
46
+ below.
47
+
48
+ ### Deep depth
49
+
50
+ The checks a scaffold's leaf scripts cannot cover: whether the dev and preview
51
+ servers actually start, whether the end-to-end suite passes against a real
52
+ server, and whether the screenshot harness produces output.
53
+
54
+ | Order | Script | Skip if | How judged |
55
+ | ----- | ------------ | ------- | ----------------------- |
56
+ | 1 | `dev` | absent | server smoke, see below |
57
+ | 2 | `preview` | absent | server smoke, see below |
58
+ | 3 | `test:e2e` | absent | leaf script: exit code |
59
+ | 4 | `screenshot` | absent | leaf script: exit code |
60
+
61
+ `deep` runs the four above and not the five leaf scripts, which the default
62
+ depth already covers. The two sets are disjoint, so running both depths runs
63
+ every declared script exactly once.
64
+
65
+ Take `deep` on request rather than by default. A dev server that starts slowly
66
+ reads as a failure here, which is too flaky to fail an unattended scaffold check
67
+ on, and the end-to-end stage needs a browser install the chain does not make.
68
+
69
+ ### Server smoke
70
+
71
+ `dev` and `preview` run until stopped, so there is no exit code to read. Start
72
+ the script backgrounded, wait 5 seconds, then check two things: the process is
73
+ still running, and its captured output carries no string matching `error`,
74
+ `Error`, or `fatal`. Kill the process either way once judged. Report a failure
75
+ on either check failing.
76
+
77
+ This is weaker than a real readiness probe. No manifest key exposes a generic
78
+ port to poll across stacks, so port-probing is out of reach here.
79
+
80
+ ## Step 3: report
81
+
82
+ For each script run, report one of:
83
+
84
+ - `✅ <script>`
85
+ - `❌ <script>` followed by the failing output (last 40 lines) or, for a server script, the reason judged (process died, or a fatal string in its output)
86
+
87
+ End with a summary line naming the depth that ran:
88
+
89
+ - On pass: `✅ Scaffold verified at <depth> (<n> scripts passed).`
90
+ - On fail: `❌ Scaffold failed at <script>. Fix the error and re-run the verify phase.`
91
+
92
+ ## Out of scope
93
+
94
+ - Generating the configs these scripts drive, which the tooling stack reference owns.
95
+ - CI workflow validation. It runs in GitHub Actions on a pull request rather than locally. The `deep` depth runs the same end-to-end and screenshot stages locally, as the closest proxy.
@@ -31,6 +31,23 @@ Group visual items by feature area. Use `- [ ]` checkbox syntax, and write each
31
31
  - [ ] <action> → <expected visual result>
32
32
  ```
33
33
 
34
+ ## The widths block
35
+
36
+ A screenshot shows one width, so a reviewer cannot tell from the picture alone whether any other width was looked at. When a change touches layout, spacing, or anything responsive, put this block above the visual items, since it frames what the screenshots beside it can support:
37
+
38
+ ```markdown
39
+ **Widths:**
40
+
41
+ Seen at: <the widths the reviewer looked at>
42
+ Not seen at: <the widths nobody looked at, or "none">
43
+ ```
44
+
45
+ Leave both lines for the reviewer to complete. This session cannot verify a width, so the block asks what was seen and never asserts coverage. Fix no width list in the block, since which widths matter belongs to the project.
46
+
47
+ Keep the `Not seen at:` line even when the answer is "none", so an omission reads as a claim rather than a gap.
48
+
49
+ Omit the block when the change cannot differ by width, such as copy, color, or a state that renders the same everywhere, the way the missing-test heading is omitted below.
50
+
34
51
  ## The missing-test list
35
52
 
36
53
  Name every automatable change this branch ships with no test, one per line, with the layer `test-craft` would place it at. Do not write the test and do not read the project's test config to write one against.
@@ -22,7 +22,7 @@ Full help: `canon <command> --help`. Behavior notes for the install and sync ver
22
22
  | `canon indexes regen` | Regenerate `index.md` files from sibling frontmatter |
23
23
  | `canon indexes list [path]` | Flatten every folder index under a path into one `{path, title, description}` catalog (`--json`) |
24
24
  | `canon docs [topic]` | Emit toolkit reference docs (`list`, or a topic by name) |
25
- | `canon design render` | Render `canon/DESIGN.md` tokens to HTML and CSS |
25
+ | `canon design render` | Render `canon/DESIGN.md` tokens to HTML and CSS, declaring each vendored face the typography table names with `--embed-fonts` |
26
26
  | `canon design regen` | Rewrite this repository's `canon/DESIGN.md` and `src/design/base.css` from `src/design/tokens.ts` |
27
27
  | `canon design board` | Generate a static page set indexing tokens, surfaces, wireframes, past candidates, components, and references against a caller-resolved `--root` (`--out`), defaulting to the main worktree |
28
28
  | `canon design css` | Emit the design tokens and components as CSS on stdout (`--no-components` for properties alone) |
@@ -65,7 +65,7 @@ The record carries every scenario with the arms that declare, plus `totalScenari
65
65
 
66
66
  `--skills` answers what the scenario count cannot, which is whether anything can fail a given skill. It adds `skills`, `totalSkills`, `asserted`, `shouldBeAsserted`, `exempt`, `staleExemptions`, and `supersededExemptions` to the record, and keeps the scenario view rather than replacing it. The two denominators disagree on purpose: an armed scenario under `infra/` or `tooling/` exercises a CLI domain and pairs with no skill at all.
67
67
 
68
- A skill pairs to a scenario by filename, `<category>-<command>` first and bare `<command>` second, so `claude/setup-init.sh` reaches the `setup-init` skill. `should-be-asserted` is the default rather than a queue to drain, and which of those skills earns an arm is a project decision the census does not make.
68
+ A skill pairs to a scenario by filename, `<category>-<command>` first and bare `<command>` second, so `claude/target-setup.sh` reaches the `target-setup` skill. `should-be-asserted` is the default rather than a queue to drain, and which of those skills earns an arm is a project decision the census does not make.
69
69
 
70
70
  `exempt` means no arm should be written and holds only with a reason, declared in `scripts/sandbox/exempt.toml` and limited to a harness limit the checker cannot reach past or a skill that writes no artifact. An armed arm outranks an exemption. An exemption naming no shipped skill, or naming one an arm now asserts, exits 1 without `--strict`. Each armed arm reports as `<category>:<command>/<arm>`, so two same-named arms under different scenarios stay distinct.
71
71
 
@@ -145,5 +145,6 @@ overwrites every golden config a stack ships, which reaches the CI workflow, the
145
145
  git hooks, the end-to-end harness, and the shell scripts under `scripts/`, so a
146
146
  headless run carrying neither `--check` nor `--write` reports what it would
147
147
  replace and exits 1 rather than applying it. Run `--check` first to read the
148
- list, then `--write` to apply it. `canon tooling sync --help` names both, and the
149
- full per-stack path list sits in the `canon-cli` skill.
148
+ list, then `--write` to apply it. `canon tooling sync --help` names both, and
149
+ `canon tooling diff <stack> <target>` reports the per-stack path list resolved
150
+ against a real target.