@erclx/canon 4.103.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.
- package/claude/.claude-plugin/plugin.json +1 -1
- package/claude/skills/canon-cli/SKILL.md +3 -77
- package/claude/skills/canon-operator/REQUIREMENT.md +2 -2
- package/claude/skills/canon-operator/SKILL.md +5 -5
- package/claude/skills/design-taste/references/craft.md +1 -1
- package/claude/skills/design-taste/references/preflight.md +2 -2
- package/claude/skills/design-taste/references/tells.md +1 -1
- package/claude/skills/git-followup/SKILL.md +1 -1
- package/claude/skills/git-issue/SKILL.md +2 -2
- package/{standards → claude/skills/git-issue/references}/issue.md +3 -8
- package/claude/skills/git-pr/SKILL.md +2 -2
- package/claude/skills/index-lookup/REQUIREMENT.md +2 -2
- package/claude/skills/project-commands/REQUIREMENT.md +1 -1
- package/claude/skills/seed-sync/REQUIREMENT.md +1 -1
- package/claude/skills/target-check/REQUIREMENT.md +1 -1
- package/claude/skills/target-setup/REQUIREMENT.md +56 -0
- package/claude/skills/target-setup/SKILL.md +163 -0
- package/claude/skills/target-setup/references/detect.md +80 -0
- package/claude/skills/{setup-indexes/SKILL.md → target-setup/references/indexes.md} +59 -23
- package/claude/skills/target-setup/references/verify.md +95 -0
- package/docs/agents/sandbox.md +1 -1
- package/docs/agents/scripting.md +3 -2
- package/docs/target-projects.md +11 -11
- package/docs/workflow/ai-workflow.md +8 -13
- package/governance/rules/ui/400-ui.md +0 -5
- package/governance/rules/ui/460-design-taste.md +1 -1
- package/governance/rules/ui/465-interface-casing.md +31 -0
- package/governance/stacks/astro.toml +1 -1
- package/governance/stacks/react.toml +1 -1
- package/package.json +1 -1
- package/scripts/core/regen-hero.sh +1 -1
- package/src/claude/cases/setup.ts +12 -11
- package/src/commands/sync.ts +1 -1
- package/src/gate/measures.ts +57 -0
- package/src/gate/stages.ts +10 -14
- package/src/gov/list.ts +1 -1
- package/src/sandbox/census.ts +3 -3
- package/src/shipped/references.ts +1 -1
- package/standards/index.md +0 -1
- package/claude/skills/setup-gov/REQUIREMENT.md +0 -37
- package/claude/skills/setup-gov/SKILL.md +0 -77
- package/claude/skills/setup-indexes/REQUIREMENT.md +0 -48
- package/claude/skills/setup-init/REQUIREMENT.md +0 -46
- package/claude/skills/setup-init/SKILL.md +0 -133
- package/claude/skills/setup-plugins/REQUIREMENT.md +0 -42
- package/claude/skills/setup-plugins/SKILL.md +0 -81
- package/claude/skills/setup-plugins/references/plugin-catalog.md +0 -53
- package/claude/skills/setup-smoke/REQUIREMENT.md +0 -38
- package/claude/skills/setup-smoke/SKILL.md +0 -53
- package/claude/skills/setup-verify/REQUIREMENT.md +0 -39
- package/claude/skills/setup-verify/SKILL.md +0 -51
- package/scripts/core/regen-tooling-paths.sh +0 -61
|
@@ -1,25 +1,32 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
description:
|
|
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
|
|
6
|
+
# Indexes bootstrap
|
|
7
7
|
|
|
8
|
-
Adds the index.md system to a project that does not have it. Operates in the
|
|
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
|
|
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
|
|
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.
|
|
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`)
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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.
|
package/docs/agents/sandbox.md
CHANGED
|
@@ -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
|
|
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
|
|
package/docs/agents/scripting.md
CHANGED
|
@@ -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
|
|
149
|
-
|
|
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.
|
package/docs/target-projects.md
CHANGED
|
@@ -51,19 +51,19 @@ claude --plugin-dir <toolkit>/claude
|
|
|
51
51
|
Two steps, in order:
|
|
52
52
|
|
|
53
53
|
1. Run the framework's own scaffold if the project needs one, such as `bun init`, `npm create vite`, or `npm create astro`. The toolkit does not wrap framework scaffolding.
|
|
54
|
-
2. Invoke `canon:setup
|
|
54
|
+
2. Invoke `canon:target-setup` in Claude Code. The skill detects the stack, resolves flags, previews the full chain, and runs it end-to-end.
|
|
55
55
|
|
|
56
56
|
The chain is:
|
|
57
57
|
|
|
58
58
|
- `canon init` installs base tooling, Claude seeds, and governance rules into `.claude/rules/` in the same pass
|
|
59
59
|
- `canon tooling sync <stack> --write` adds stack-specific deps, scripts, and gitignore entries
|
|
60
60
|
- The agent reads `canon tooling reference <stack>` (plus parents) as its audit context, follows it to generate eslint, vitest, playwright configs and the stack's setup script, and extends `canon/context/ci.md` and `canon/context/development.md` per the reference's extend sections <!-- audit-ignore-citations: canon/context/development.md -->
|
|
61
|
-
- `
|
|
62
|
-
- `
|
|
61
|
+
- The `verify` phase runs the installed `package.json` scripts (lint, typecheck, check, test, build) and reports pass or fail
|
|
62
|
+
- The `indexes` phase bootstraps the `index.md` system over the project's own documentation folders, confirming candidate folders with the operator rather than running unattended
|
|
63
63
|
|
|
64
|
-
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 as part of it. The chain serves a fresh scaffold and names a destination for the three states it does not. An existing project goes to `canon:canon-operator`, which reads what the project already carries before naming a per-domain command. An install wanting the Claude layer without the tooling chain runs `canon claude init` for the seed docs and then `canon:setup
|
|
64
|
+
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 as part of it. The chain serves a fresh scaffold and names a destination for the three states it does not. An existing project goes to `canon:canon-operator`, which reads what the project already carries before naming a per-domain command. An install wanting the Claude layer without the tooling chain runs `canon claude init` for the seed docs and then `canon:target-setup indexes` for the index system. A language the toolkit ships no stack for is the one of the three the chain still runs for, on `base`, with the fallback marked in the preview so it can be declined there.
|
|
65
65
|
|
|
66
|
-
Run `canon:setup
|
|
66
|
+
Run `canon:target-setup verify deep` by hand once the default depth passes, for the heavier server smoke, end-to-end, and screenshot pass, since the same flakiness reasons that keep those stages out of the default depth keep them out of this unattended chain too.
|
|
67
67
|
|
|
68
68
|
Keep the `## Scripts` table in `canon/context/development.md` current as scripts are added. Base tooling seeds that entry with the commands it installs, and each stack reference extends the table. `project-commands` reads it to start the app or run a check on request, so a command missing from the table cannot be run that way. A project whose entry outgrew one file and split into `canon/context/development/` keeps the table in `overview.md`, which is where the skill looks next. <!-- audit-ignore-citations: canon/context/development.md -->
|
|
69
69
|
|
|
@@ -86,13 +86,13 @@ Each diagram entry records the commit and date it was last verified against, and
|
|
|
86
86
|
|
|
87
87
|
The default path is `base`. `canon init` on `base` installs base tooling configs, Claude seeds, and governance core rules, and scaffolds an empty `.claude/wiki/`. Most projects need nothing more.
|
|
88
88
|
|
|
89
|
-
Escalate only for real web apps. The `setup
|
|
89
|
+
Escalate only for real web apps. The `target-setup` skill reads `package.json` and root configs, then picks the matching tooling stack (`canon tooling list --json` names the current set) and the matching governance stack (`react`, `astro`, `node`).
|
|
90
90
|
|
|
91
91
|
`node-server` is named rather than detected. It carries the server-side security and persistence rules for a project writing request handlers or a persistence layer in TypeScript, and the detect step matches a runtime or a framework against stack names, so nothing there marks a project as a backend. Pass it deliberately with `canon init --stack node-server` or `canon gov install node-server <target>`.
|
|
92
92
|
|
|
93
93
|
Markdown-heavy projects, CLI tools, docs sites, research notebooks, and scripting repos stay on `base`. Escalation is a ceiling move, not a default.
|
|
94
94
|
|
|
95
|
-
A project the toolkit ships no stack for lands on `base` the same way, and the skill marks that resolution as a fallback in its preview rather than reporting it as a match. Configs, seeds, and gitignore entries land either way, and the JavaScript development dependencies, scripts, and hook activation land only where a `package.json` exists to carry them. A project outside that ecosystem declines at the preview and takes `canon:setup
|
|
95
|
+
A project the toolkit ships no stack for lands on `base` the same way, and the skill marks that resolution as a fallback in its preview rather than reporting it as a match. Configs, seeds, and gitignore entries land either way, and the JavaScript development dependencies, scripts, and hook activation land only where a `package.json` exists to carry them. A project outside that ecosystem declines at the preview and takes `canon:target-setup gov` for the governance layer alone, which is language-neutral.
|
|
96
96
|
|
|
97
97
|
Run `canon tooling list --json` and `canon gov list --json` to see the current catalogs. Never hardcode stack names.
|
|
98
98
|
|
|
@@ -115,9 +115,9 @@ The plugin corpus carries runtime behavior rather than reference prose alone, be
|
|
|
115
115
|
|
|
116
116
|
When a new need appears after scaffold, install the one domain without re-running `canon init`.
|
|
117
117
|
|
|
118
|
-
- Governance rule for a newly adopted library: invoke `canon:setup
|
|
118
|
+
- Governance rule for a newly adopted library: invoke `canon:target-setup gov`, or run `canon gov install <stack> --add <rule> <path>`
|
|
119
119
|
- Project-specific rule the toolkit does not ship: invoke `canon:create-rule`. It scaffolds a rule into `.claude/rules/` with a non-colliding number, and `canon gov sync` leaves it untouched.
|
|
120
|
-
- Index.md system for a markdown-heavy folder that emerged: invoke `canon:setup
|
|
120
|
+
- Index.md system for a markdown-heavy folder that emerged: invoke `canon:target-setup indexes`
|
|
121
121
|
|
|
122
122
|
Standards and snippets are not on that list, and there is nothing to add for either. Neither installs into a project, by default or by flag, so a session reads a standard with `canon standards <name>` and a snippet through its `@` reference off the live plugin symlink, both resolving against the toolkit rather than a project copy. A project holding a `.claude/standards/` or `.claude/snippets/` folder from an older toolkit is carrying a stale artifact nothing reads, and deleting it is safe.
|
|
123
123
|
|
|
@@ -300,7 +300,7 @@ cd <your-project>
|
|
|
300
300
|
claude
|
|
301
301
|
```
|
|
302
302
|
|
|
303
|
-
In the session, invoke `canon:setup
|
|
303
|
+
In the session, invoke `canon:target-setup`. The skill detects no framework and resolves tooling to `base` and governance to `base`. The preview marks both stacks as fallbacks, since neither came from a match, then the chain runs `canon init`.
|
|
304
304
|
|
|
305
305
|
Ongoing: run `canon sync --check .` to see what has drifted, then invoke `canon:seed-sync` for seed drift or `canon sync .` for a catch-all refresh.
|
|
306
306
|
|
|
@@ -311,7 +311,7 @@ bun create vite my-app && cd my-app
|
|
|
311
311
|
claude
|
|
312
312
|
```
|
|
313
313
|
|
|
314
|
-
Invoke `canon:setup
|
|
314
|
+
Invoke `canon:target-setup`. The skill reads `package.json` and the Vite config, resolves tooling to `vite-react` and governance to `react`, and runs `canon init` with the resolved flags.
|
|
315
315
|
|
|
316
316
|
Ongoing maintenance:
|
|
317
317
|
|
|
@@ -200,19 +200,14 @@ This section is the corpus the coverage claim is measured against: every name `c
|
|
|
200
200
|
|
|
201
201
|
### Set up a project
|
|
202
202
|
|
|
203
|
-
| Skill | When to use
|
|
204
|
-
| ---------------------- |
|
|
205
|
-
| `canon:setup
|
|
206
|
-
| `canon:canon-operator` | On a project that already exists, to read what it carries before an install is picked
|
|
207
|
-
| `canon:
|
|
208
|
-
| `canon:
|
|
209
|
-
| `canon:
|
|
210
|
-
| `canon:
|
|
211
|
-
| `canon:setup-smoke` | After `setup-verify` passes, to check the dev and preview servers, end-to-end tests, and the screenshot harness |
|
|
212
|
-
| `canon:sketch-design` | Before `design-extract`'s greenfield path, to trace a design direction from reference images or URLs |
|
|
213
|
-
| `canon:design-extract` | Before the first UI feature, to draft `canon/DESIGN.md` |
|
|
214
|
-
| `canon:draft-diagram` | Once the architecture is written, to draft per-kind entries under `.canon/diagrams/` |
|
|
215
|
-
| `canon:repo-metadata` | When the GitHub About text, homepage, or topics may have drifted, to reconcile them against the README |
|
|
203
|
+
| Skill | When to use |
|
|
204
|
+
| ---------------------- | ------------------------------------------------------------------------------------------------------ |
|
|
205
|
+
| `canon:target-setup` | On a fresh scaffold, to detect the stack and run the install chain, or to reach one phase of it alone |
|
|
206
|
+
| `canon:canon-operator` | On a project that already exists, to read what it carries before an install is picked |
|
|
207
|
+
| `canon:sketch-design` | Before `design-extract`'s greenfield path, to trace a design direction from reference images or URLs |
|
|
208
|
+
| `canon:design-extract` | Before the first UI feature, to draft `canon/DESIGN.md` |
|
|
209
|
+
| `canon:draft-diagram` | Once the architecture is written, to draft per-kind entries under `.canon/diagrams/` |
|
|
210
|
+
| `canon:repo-metadata` | When the GitHub About text, homepage, or topics may have drifted, to reconcile them against the README |
|
|
216
211
|
|
|
217
212
|
### Decide what to build
|
|
218
213
|
|
|
@@ -9,11 +9,6 @@ paths:
|
|
|
9
9
|
|
|
10
10
|
# UI copy standards
|
|
11
11
|
|
|
12
|
-
## Casing
|
|
13
|
-
|
|
14
|
-
- Use sentence case for all rendered UI text: headings, labels, nav items, tab titles, and dialog titles.
|
|
15
|
-
- Retain original casing for proper nouns and product names: `GitHub`, `macOS`, `TypeScript`.
|
|
16
|
-
|
|
17
12
|
## Punctuation
|
|
18
13
|
|
|
19
14
|
- Do not use em dashes (`—`). Use a comma or period, or restructure the sentence.
|
|
@@ -25,5 +25,5 @@ paths:
|
|
|
25
25
|
|
|
26
26
|
- Accessibility, keyboard interaction and ARIA are a separate topic. `410-a11y` routes them, on every rendered path.
|
|
27
27
|
- States, empty and loading coverage, and destructive confirmation are a separate topic. `430-ux-completeness` routes them.
|
|
28
|
-
- Rendered copy casing
|
|
28
|
+
- Rendered copy casing is a separate topic. `465-interface-casing` routes it. Button labels and error wording are separate too, and `400-ui` routes them.
|
|
29
29
|
- The floor those three carry is not restated in the skill, and it is not traded against a preference where the two collide.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Enforce casing for interface text in markup, MDX, and content modules, where copy lives in a content folder
|
|
3
|
+
paths:
|
|
4
|
+
- '**/*.tsx'
|
|
5
|
+
- '**/*.jsx'
|
|
6
|
+
- '**/*.astro'
|
|
7
|
+
- '**/*.html'
|
|
8
|
+
- '**/*.mdx'
|
|
9
|
+
- '**/content/**/*.ts'
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
# Interface casing standards
|
|
13
|
+
|
|
14
|
+
## Sentence case
|
|
15
|
+
|
|
16
|
+
- Use sentence case for all rendered interface text: headings, labels, nav items, tab titles, and dialog titles.
|
|
17
|
+
- Retain original casing for proper nouns and product names: `GitHub`, `macOS`, `TypeScript`.
|
|
18
|
+
- Treat title case on every heading as a template tell, since it reads as a default rather than a choice.
|
|
19
|
+
|
|
20
|
+
## Uppercase labels
|
|
21
|
+
|
|
22
|
+
- Keep small uppercase labels above headings to one per three sections, with the first screen counting as one. More than `ceil(sections / 3)` is too many, and the fix is usually to delete the label, since a section's position already says what it is.
|
|
23
|
+
- Treat the count as a judgment, since a glob cannot check it.
|
|
24
|
+
|
|
25
|
+
## Where it applies
|
|
26
|
+
|
|
27
|
+
- The rule covers markup, MDX, and content modules under a `content/` folder. Copy kept elsewhere, such as a locale file, is not reached, so apply the same casing there without the rule firing.
|
|
28
|
+
|
|
29
|
+
## Overriding
|
|
30
|
+
|
|
31
|
+
- Depart from sentence case where the case needs it, such as an acronym, a brand mark, or a set-in-caps identity the design chose on purpose.
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
extends = "node"
|
|
2
|
-
rules = ["210-astro", "300-testing-ts", "305-e2e-reliability", "306-test-scope", "350-security-web", "400-ui", "410-a11y", "420-forms", "430-ux-completeness", "440-surface-capture", "450-link-behavior", "460-design-taste", "470-motion"]
|
|
2
|
+
rules = ["210-astro", "300-testing-ts", "305-e2e-reliability", "306-test-scope", "350-security-web", "400-ui", "410-a11y", "420-forms", "430-ux-completeness", "440-surface-capture", "450-link-behavior", "460-design-taste", "465-interface-casing","470-motion"]
|
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
extends = "node"
|
|
2
|
-
rules = ["200-react", "230-nextjs", "250-tailwind", "300-testing-ts", "305-e2e-reliability", "306-test-scope", "310-zod", "350-security-web", "400-ui", "410-a11y", "420-forms", "430-ux-completeness", "440-surface-capture", "450-link-behavior", "460-design-taste", "470-motion"]
|
|
2
|
+
rules = ["200-react", "230-nextjs", "250-tailwind", "300-testing-ts", "305-e2e-reliability", "306-test-scope", "310-zod", "350-security-web", "400-ui", "410-a11y", "420-forms", "430-ux-completeness", "440-surface-capture", "450-link-behavior", "460-design-taste", "465-interface-casing","470-motion"]
|
package/package.json
CHANGED
|
@@ -1,39 +1,40 @@
|
|
|
1
1
|
import type { SkillCase } from '@/claude/skills-rank'
|
|
2
2
|
|
|
3
3
|
/**
|
|
4
|
-
* `setup
|
|
4
|
+
* `target-setup`, `migration-*`, `canon-*`, and `create-rule`: scaffolding,
|
|
5
5
|
* proposal-only migrations, and the toolkit's own reference and feedback
|
|
6
6
|
* surfaces.
|
|
7
|
+
*
|
|
8
|
+
* The five `target-setup` cases are one skill read through five entry phrasings
|
|
9
|
+
* rather than five rows that collapsed to a duplicate. Each names a different
|
|
10
|
+
* phase, and the merged description has to carry every one of them, which is
|
|
11
|
+
* the discrimination the six-skill family failed at from the other direction.
|
|
7
12
|
*/
|
|
8
13
|
export const SETUP_CASES: readonly SkillCase[] = [
|
|
9
14
|
{
|
|
10
15
|
prompt:
|
|
11
16
|
'This project has no rules installed yet, get the right governance in place.',
|
|
12
|
-
expect: 'setup
|
|
17
|
+
expect: 'target-setup',
|
|
13
18
|
},
|
|
14
19
|
{
|
|
15
20
|
prompt:
|
|
16
21
|
"Get the index.md system bootstrapped across this project's folders.",
|
|
17
|
-
expect: 'setup
|
|
22
|
+
expect: 'target-setup',
|
|
18
23
|
},
|
|
19
24
|
{
|
|
20
25
|
prompt:
|
|
21
26
|
'This is a brand-new project, get the toolkit bootstrapped in one shot.',
|
|
22
|
-
expect: 'setup
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
prompt: 'Get the usual Claude Code plugins provisioned on this machine.',
|
|
26
|
-
expect: 'setup-plugins',
|
|
27
|
+
expect: 'target-setup',
|
|
27
28
|
},
|
|
28
29
|
{
|
|
29
30
|
prompt:
|
|
30
31
|
"Run through the generated scaffold's scripts and confirm each one passes.",
|
|
31
|
-
expect: 'setup
|
|
32
|
+
expect: 'target-setup',
|
|
32
33
|
},
|
|
33
34
|
{
|
|
34
35
|
prompt:
|
|
35
36
|
'Check that the dev server actually starts and the end-to-end suite passes against the scaffold.',
|
|
36
|
-
expect: 'setup
|
|
37
|
+
expect: 'target-setup',
|
|
37
38
|
},
|
|
38
39
|
{
|
|
39
40
|
prompt:
|
|
@@ -76,7 +77,7 @@ export const SETUP_CASES: readonly SkillCase[] = [
|
|
|
76
77
|
{
|
|
77
78
|
prompt:
|
|
78
79
|
"Whatever the right toolkit command is, get this project's rules installed.",
|
|
79
|
-
expect: 'setup
|
|
80
|
+
expect: 'target-setup',
|
|
80
81
|
},
|
|
81
82
|
{
|
|
82
83
|
prompt:
|
package/src/commands/sync.ts
CHANGED
|
@@ -109,7 +109,7 @@ function renderCheck(report: CheckReport): void {
|
|
|
109
109
|
logStep('Not a toolkit project')
|
|
110
110
|
logWarn('No .claude/ directory and no CLAUDE.md at the target.')
|
|
111
111
|
logInfo(
|
|
112
|
-
'Run `canon init` to install, or /canon:setup
|
|
112
|
+
'Run `canon init` to install, or /canon:target-setup to resolve a stack.',
|
|
113
113
|
)
|
|
114
114
|
outro()
|
|
115
115
|
return
|
package/src/gate/measures.ts
CHANGED
|
@@ -629,6 +629,63 @@ export const shippedReferences: Measure = async (ctx) => {
|
|
|
629
629
|
}
|
|
630
630
|
}
|
|
631
631
|
|
|
632
|
+
const RAW_FIELD_FILE_REFERENCE = /(?:^|\s)(?:-f|--raw-field)[ =]\S+=@/
|
|
633
|
+
|
|
634
|
+
/**
|
|
635
|
+
* A `gh api` raw-string flag carrying a file reference, over the seven shipped
|
|
636
|
+
* corpora.
|
|
637
|
+
*
|
|
638
|
+
* `-f body=@<path>` sends the literal path as the field value, so a comment
|
|
639
|
+
* edited that way is overwritten with the path itself and loses the marker a
|
|
640
|
+
* later read resolves it by. `-F` is the flag that reads the file. The pattern
|
|
641
|
+
* requires `=@`, so `-F`, `--field`, and a raw string such as `-f body="text"`
|
|
642
|
+
* all pass.
|
|
643
|
+
*
|
|
644
|
+
* It scans prose rather than parsing a command, so a body quoting the wrong
|
|
645
|
+
* spelling to explain it fails too. Reword it rather than exempting it, since an
|
|
646
|
+
* exemption is what lets a real occurrence hide.
|
|
647
|
+
*/
|
|
648
|
+
export const rawFieldFileReference: Measure = async (ctx) => {
|
|
649
|
+
const files = shippedCorpusFiles(ctx.root)
|
|
650
|
+
|
|
651
|
+
if (files.length === 0) {
|
|
652
|
+
return {
|
|
653
|
+
emissions: [],
|
|
654
|
+
unmeasured: `No corpus under ${SHIPPED_CORPORA.join(', ')} is present, so no shipped file was read.`,
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
const found = files.flatMap((file) =>
|
|
659
|
+
readFileSync(join(ctx.root, file), 'utf8')
|
|
660
|
+
.split('\n')
|
|
661
|
+
.flatMap((text, index) =>
|
|
662
|
+
RAW_FIELD_FILE_REFERENCE.test(text) ? [`${file}:${index + 1}`] : [],
|
|
663
|
+
),
|
|
664
|
+
)
|
|
665
|
+
|
|
666
|
+
if (found.length === 0) {
|
|
667
|
+
return {
|
|
668
|
+
emissions: [
|
|
669
|
+
info(
|
|
670
|
+
`No raw-field file reference across ${files.length} files in ${SHIPPED_CORPORA.length} shipped corpora`,
|
|
671
|
+
),
|
|
672
|
+
],
|
|
673
|
+
}
|
|
674
|
+
}
|
|
675
|
+
|
|
676
|
+
return {
|
|
677
|
+
emissions: found.map((location) =>
|
|
678
|
+
warn(
|
|
679
|
+
`${location} passes a file reference through a raw-string flag, which posts the path as the field value. Use -F instead`,
|
|
680
|
+
),
|
|
681
|
+
),
|
|
682
|
+
failure:
|
|
683
|
+
found.length === 1
|
|
684
|
+
? 'One raw-field file reference in the shipped corpora. Change -f or --raw-field to -F or --field where the value reads a file with @, or reword a prose line quoting the wrong spelling.'
|
|
685
|
+
: `${found.length} raw-field file references in the shipped corpora. Change -f or --raw-field to -F or --field where the value reads a file with @, or reword a prose line quoting the wrong spelling.`,
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
|
|
632
689
|
/**
|
|
633
690
|
* Every git-tracked file quoting a listed client command with the wrong
|
|
634
691
|
* argument, over the whole tree rather than one corpus, since a wrong
|