@erclx/canon 4.81.0 → 4.83.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/docs-fold/REQUIREMENT.md +13 -0
- package/claude/skills/docs-fold/SKILL.md +20 -0
- package/claude/skills/docs-fold/references/classify.md +78 -0
- package/claude/skills/draft-slides/SKILL.md +1 -1
- package/claude/skills/draft-wireframes/REQUIREMENT.md +1 -1
- package/claude/skills/draft-wireframes/SKILL.md +7 -4
- package/docs/agents/commands.md +8 -4
- package/docs/agents/context-audit-checks.md +22 -2
- package/docs/agents/context-audit.md +13 -3
- package/docs/agents/context-classify.md +99 -0
- package/docs/agents/index.md +1 -0
- package/docs/target-projects.md +15 -0
- package/docs/workflow/ai-workflow.md +4 -3
- package/docs/workflow/visual-design-workflow.md +1 -1
- package/governance/rules/claude/520-wireframes.md +1 -1
- package/governance/rules/claude/545-decisions.md +12 -0
- package/package.json +1 -1
- package/src/claude/seeds.ts +1 -0
- package/src/commands/claude.ts +26 -5
- package/src/commands/context.ts +496 -2
- package/src/context/architecture.ts +73 -0
- package/src/context/audit.ts +18 -2
- package/src/context/classify/extract.ts +450 -0
- package/src/context/classify/ollama.ts +172 -0
- package/src/context/classify/patterns.ts +114 -0
- package/src/context/classify/prompts.ts +73 -0
- package/src/context/classify/run.ts +348 -0
- package/src/context/classify/settings.ts +196 -0
- package/src/context/folders.ts +1 -0
- package/src/context/gate.ts +44 -6
- package/src/context/wireframe-states.ts +238 -0
- package/src/surface-root.ts +1 -0
- package/standards/architecture.md +11 -1
- package/standards/context.md +4 -1
- package/standards/decisions.md +100 -0
- package/standards/design.md +6 -0
- package/standards/index.md +1 -0
- package/standards/requirements.md +2 -1
- package/standards/wireframes.md +45 -29
- package/tooling/claude/reference.md +2 -1
- package/tooling/claude/seeds/CLAUDE.md +2 -1
- package/tooling/claude/seeds/canon/decisions/index.md +8 -0
- package/tooling/claude/seeds/canon/wireframes/index.md +2 -2
|
@@ -17,6 +17,8 @@ The receipt half of that sweep was missing entirely. A review receipt was delete
|
|
|
17
17
|
|
|
18
18
|
The trigger side carries a gap of its own. "Sync the docs" names either corpus to the person saying it, so a description leaving its corpus to the opening clause alone competes with its public-facing sibling on nothing the routing field states, and the planning surface the request was about goes untouched.
|
|
19
19
|
|
|
20
|
+
This skill writes canonical docs at the end of a long build and never reviews what it wrote. An appended figure or a branch-narrated re-measurement lands unchecked the same way a session's own edits do, so what the fold produces carries the exact defect the standards it cites already ban.
|
|
21
|
+
|
|
20
22
|
## Must
|
|
21
23
|
|
|
22
24
|
- Name the `.claude/` corpus in a trigger phrase rather than in the opening clause alone, so a bare request to sync the docs separates this skill from `docs-sync` on something both descriptions state
|
|
@@ -34,6 +36,10 @@ The trigger side carries a gap of its own. "Sync the docs" names either corpus t
|
|
|
34
36
|
- Leave the current branch's review receipt alone, since the chain that wrote it cites it in its own closing line and this skill cannot read whether that citation is still live
|
|
35
37
|
- Land each block of a promotion handoff at the destination its heading names, then delete the file so a later run does not fold it twice
|
|
36
38
|
- Take a promotion destination as already decided, since the operator confirmed it where the page was produced
|
|
39
|
+
- Classify the fold's whole diff baseline through `canon context classify diff`, calling the verb rather than reimplementing its pattern or its prompt in the skill body, since an earlier commit on the branch carries a doc edit the fold is equally responsible for
|
|
40
|
+
- Apply a `REPLACE` or `HISTORY` finding, and a regex-decided `MOVE` finding, against the quote it names, report a model-decided `MOVE` finding naming the surface it belongs on rather than cutting it, or keep a finding with a one-line reason, rather than leaving a finding unanswered
|
|
41
|
+
- Rewrite a restated or superseded statement in place rather than appending the replacement beside it, on every canonical doc type this skill writes
|
|
42
|
+
- Report a refusal or a missing `context classify` subcommand as one line and continue the fold either way, since a check that cannot run is not a reason to leave the fold's own output unshipped
|
|
37
43
|
|
|
38
44
|
## Must not
|
|
39
45
|
|
|
@@ -45,6 +51,13 @@ The trigger side carries a gap of its own. "Sync the docs" names either corpus t
|
|
|
45
51
|
- Overwrite a file a promotion block routes to. A destination that already holds a page is a merge for a person, and folding over it discards work this skill never read.
|
|
46
52
|
- Write an anchor onto a decision the run did not amend, or refresh one without re-reading the number. A date from a pass that measured nothing is the false confidence the marker exists to prevent.
|
|
47
53
|
- Anchor an entry written before the rule, which dates it by blame rather than by a read
|
|
54
|
+
- Pick or configure a classifier backend. The project setting decides it, and this skill reports the resolved `modelLayer` as returned.
|
|
55
|
+
- Stop the fold on a classify finding, a refusal, or a missing subcommand. All three report and continue.
|
|
56
|
+
- Apply a finding against a quote found more than once or not found at all. Report that it could not be located instead of guessing.
|
|
57
|
+
- Re-run the classifier after applying a finding, which loops it over its own edit
|
|
58
|
+
- Cut a model-decided `MOVE` finding. The model's own prompt defines `MOVE` more broadly than the regex layer does, for correct content sitting on the wrong surface rather than a deletion candidate, so cutting one can discard content that belongs elsewhere rather than removing detail that never belonged at all.
|
|
59
|
+
- Paste a regex-decided `MOVE` finding's content into another canonical doc after cutting it. It never belonged on the wireframe surface at all, so cutting is the whole fix, not a relocation.
|
|
60
|
+
- Scope Step 10 to the files Steps 3 and 7 wrote this run. An earlier commit on the branch carries a doc edit the fold is equally responsible for, and the verb's own extraction already answers whether anything in range qualifies.
|
|
48
61
|
|
|
49
62
|
## Guards
|
|
50
63
|
|
|
@@ -108,6 +108,7 @@ Read `ok` and `reason` out of that record rather than the exit. An operator's sh
|
|
|
108
108
|
|
|
109
109
|
- Update only the sections affected by session decisions.
|
|
110
110
|
- Do not rewrite sections unrelated to what changed.
|
|
111
|
+
- Rewrite a restated or superseded statement in place rather than appending the replacement beside it. State the fact that stands and keep the earlier reasoning only where it is the alternative that lost, per `${CLAUDE_SKILL_DIR}/../../standards/context.md` and `${CLAUDE_SKILL_DIR}/../../standards/architecture.md`.
|
|
111
112
|
- Follow `${CLAUDE_SKILL_DIR}/../../standards/markdown.md` and the `write-human` skill for all edits.
|
|
112
113
|
- Close a decision entry in `canon/ARCHITECTURE.md` with its verification anchor whenever this run writes that entry or amends its reasoning and that reasoning cites a measured number. Re-read the number against the tree first, since the marker records the read rather than the edit. `${CLAUDE_SKILL_DIR}/../../standards/architecture.md` fixes the sentence.
|
|
113
114
|
- Leave every decision entry this run did not write alone, anchored or not. The rule is scoped forward, so an entry written before it is dated by blame rather than by a read. Step 5 reports a stale anchor and no step writes one on an entry it did not amend.
|
|
@@ -160,6 +161,7 @@ Reuse the diff from the baseline above, names and content both. For each domain
|
|
|
160
161
|
|
|
161
162
|
- Map the entry's section headings, whether they sit in one flat file or spread across a nested domain's sibling files, to the changed files. An entry is relevant when its prose references files, modules, or decisions touched by the diff.
|
|
162
163
|
- For each relevant entry, rewrite only the sections affected by the diff. Same pattern as `docs-sync`. Do not touch unrelated sections. Never rewrite a split domain's own `index.md` directly, since a regen overwrites it the same way it overwrites the top-level catalog. Rewrite the sibling file the affected section actually lives in instead.
|
|
164
|
+
- Rewrite a restated or superseded statement in place rather than appending beside it, the same rule Step 3 applies to the other four canonical doc types.
|
|
163
165
|
- Write a reference to another entry as the path that entry sits at, rather than as its bare filename. `${CLAUDE_SKILL_DIR}/../../standards/context.md` states the form, and a bare name strands the reference once a domain splits into subfolders.
|
|
164
166
|
|
|
165
167
|
### When the diff removes a capability
|
|
@@ -245,12 +247,30 @@ Output one line per file swept:
|
|
|
245
247
|
|
|
246
248
|
If nothing qualifies, skip this step silently.
|
|
247
249
|
|
|
250
|
+
## Step 10: classify the fold's diff baseline
|
|
251
|
+
|
|
252
|
+
Skip this step silently only when the Diff baseline section could not resolve a base ref at all, reporting `⚠ No diff to scope against. Skipped the classify check.` The verb needs a resolvable ref to run against, which is the one condition it cannot answer for itself.
|
|
253
|
+
|
|
254
|
+
Otherwise resolve `<base>` the way the Diff baseline section already does for Steps 2, 4, 5, and 7, and reuse it rather than resolving a second time. Run the check over the fold's whole baseline rather than scoping it to what Steps 3 and 7 wrote this run: earlier commits on the branch carry doc edits the fold is equally responsible for, and the verb's own extraction already scopes to canonical doc types and reports nothing when the range carries none.
|
|
255
|
+
|
|
256
|
+
The invocation is:
|
|
257
|
+
|
|
258
|
+
```bash
|
|
259
|
+
canon context classify diff --base <base> --json
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
Never substitute a different verb for it, such as `canon autoship classify` (a different check, over a different scope) or `canon docs <name>` (a documentation lookup, not a classification). Read `${CLAUDE_SKILL_DIR}/references/classify.md` for the record fields, applying a finding, the one-line keep reason, the unreachable and missing-subcommand lines, and the report shape. `${CLAUDE_SKILL_DIR}` names this skill's own directory, resolved once when the skill loaded, several steps before this one. If Step 10's memory of that path is uncertain, read the reference by that resolved path rather than guessing a `.claude/skills/docs-fold/references/classify.md` path from the toolkit's install-time layout, which is a different root than the one this skill's own files live under. The invocation above runs either way, whether or not that reference resolves.
|
|
263
|
+
|
|
264
|
+
Findings never stop the fold. A refusal or a missing subcommand on an older installed binary reports one line, per that reference, and the fold continues either way.
|
|
265
|
+
|
|
248
266
|
## After completion
|
|
249
267
|
|
|
250
268
|
Output one line per file updated:
|
|
251
269
|
|
|
252
270
|
`✅ Updated: .claude/<filename>`
|
|
253
271
|
|
|
272
|
+
Step 10 adds its own lines when it applied or reported a finding, in the exact shape `${CLAUDE_SKILL_DIR}/references/classify.md` gives them under its own Report section. Do not shorten or paraphrase those lines here or in the reply, since the quote and the reason are what a reader checks the finding against.
|
|
273
|
+
|
|
254
274
|
If no files were updated and nothing was swept, output:
|
|
255
275
|
|
|
256
276
|
`✅ No changes needed.`
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Classify the fold's diff baseline
|
|
3
|
+
description: The classify diff invocation, the record fields to read, applying a finding, the one-line keep reason, the unreachable and missing-subcommand lines, and the report shape
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Classify the fold's diff baseline
|
|
7
|
+
|
|
8
|
+
Mechanics for Step 10 of `docs-fold`. The body owns the skip condition and the shared baseline, and this file owns the invocation, what the record carries, and what applying a finding does.
|
|
9
|
+
|
|
10
|
+
## Invocation
|
|
11
|
+
|
|
12
|
+
Call the verb rather than reimplementing its pattern or prompt in this skill:
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
canon context classify diff --base <base> --json
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
Reuse the base the Diff baseline section already resolved. Never pick or configure a backend here. The project setting decides it, and this step reports `modelLayer` as the record returns it.
|
|
19
|
+
|
|
20
|
+
## Reading the record
|
|
21
|
+
|
|
22
|
+
Branch on the record's `decision` field, never on the exit code, which a shell function wrapping `canon` can flatten to zero.
|
|
23
|
+
|
|
24
|
+
- `decision: 'refused'`: a bad range or a file the verb could not read. Report the record's `message` and continue. See "When the verb is absent or refused" below.
|
|
25
|
+
- `decision: 'ok'`: the record carries `modelLayer` (`'off'`, `'ran'`, `'skipped-no-model'`, or `'skipped-unreachable'`) and `findings`.
|
|
26
|
+
|
|
27
|
+
Each finding carries `file`, a `verdict` of `KEEP`, `REPLACE`, `HISTORY`, or `MOVE`, and `decidedBy` (`'regex'` or `'model'`) naming which layer's reading won. Take the `quote` and `reason` from whichever of the finding's `regex` or `model` fields `decidedBy` names. Skip every `KEEP` finding: nothing decided against that text.
|
|
28
|
+
|
|
29
|
+
## Scope
|
|
30
|
+
|
|
31
|
+
Answer every non-`KEEP` finding the verb returns, not only the files Step 3 or Step 7 wrote this run. A branch carrying earlier commits from a prior session has doc edits the fold is equally responsible for, and the verb's own extraction already scopes to canonical doc types and reports nothing when the range carries none, so there is no narrower check to add here.
|
|
32
|
+
|
|
33
|
+
## Applying a finding
|
|
34
|
+
|
|
35
|
+
Locate the finding by its `quote` in the file's current content. The quote is often a narrow fragment rather than the whole clause it sits in, since the regex layer's own match is a short pattern hit, so the edit below targets the sentence or bullet the quote sits in rather than the literal substring alone.
|
|
36
|
+
|
|
37
|
+
- **Found exactly once.** Apply the verdict:
|
|
38
|
+
- `REPLACE`: rewrite the sentence or bullet carrying the quote in place with the fact that now stands, per Step 3 and Step 7's rewrite-in-place rule. State what is current and drop what the quote restated, in the one edit.
|
|
39
|
+
- `HISTORY`: rewrite the sentence or bullet carrying the quote to drop the narration and keep any current fact the same clause states. The quote narrates how the fact arrived rather than stating the fact, which a canonical doc excludes regardless of what wrote it, and a literal cut of the fragment alone would leave the rest of the clause grammatically stranded.
|
|
40
|
+
- `MOVE`, regex-decided (`decidedBy: 'regex'`): cut the sentence or bullet carrying the quote and stop there. Do not also paste it into another canonical doc, however close a match the current diff makes one look. The regex layer only ever returns `MOVE` inside `canon/wireframes/`, on prose naming a source-file path, which is implementation detail a wireframe surface does not carry, so a regex-decided `MOVE` is always safe to remove outright, and removing it is the whole fix.
|
|
41
|
+
- `MOVE`, model-decided (`decidedBy: 'model'`): do not cut. The model's own prompt defines `MOVE` more broadly, for correct content sitting on the wrong surface, such as domain mechanism written into `canon/ARCHITECTURE.md` that belongs in a context entry. Cutting would delete content a fold with no model configured would never have flagged at all. Report the finding instead, naming the surface the `reason` names as where the content belongs, and leave the file unedited.
|
|
42
|
+
- **Found more than once, or not found at all.** Report that the finding could not be located rather than guessing which occurrence or rewriting nothing silently. A model verdict paraphrasing the quote it read is the ordinary way this happens.
|
|
43
|
+
|
|
44
|
+
Run the classifier once per fold. Do not re-run it after applying a finding to check the edit, since a second pass over what this step wrote is the loop the verb's own reference already warns against.
|
|
45
|
+
|
|
46
|
+
## Keeping a finding
|
|
47
|
+
|
|
48
|
+
Keep a non-`KEEP` finding without applying it only when the quote is itself the alternative a nearby decision states and lost, or the file already carries the current fact elsewhere. State the reason in one line in the report. A keep costs one line, where an incorrect apply costs a rewrite of prose nobody asked to change.
|
|
49
|
+
|
|
50
|
+
## When the verb is absent or refused
|
|
51
|
+
|
|
52
|
+
The verb ships with the CLI and this skill ships with the plugin, so a target holding an older installed binary carries no `context classify` subcommand. Report:
|
|
53
|
+
|
|
54
|
+
`⚠ Classify: canon context classify not available on the installed binary. Skipped.`
|
|
55
|
+
|
|
56
|
+
and continue. Never read a missing subcommand as a clean pass, which would report a run that never checked anything as one that found nothing.
|
|
57
|
+
|
|
58
|
+
A refused range reports the same way, naming the verb's own message:
|
|
59
|
+
|
|
60
|
+
`⚠ Classify: <message>`
|
|
61
|
+
|
|
62
|
+
Neither case stops the fold. This step checks what the fold wrote, and a check that cannot run is not a reason to leave the fold's own output unshipped.
|
|
63
|
+
|
|
64
|
+
## Report
|
|
65
|
+
|
|
66
|
+
One line naming what ran:
|
|
67
|
+
|
|
68
|
+
`✅ Classify: <n> findings, regex ran, model <modelLayer>`
|
|
69
|
+
|
|
70
|
+
Then one line per non-`KEEP` finding:
|
|
71
|
+
|
|
72
|
+
- `✏ Rewrote: <file>, "<quote>" (<reason>)`
|
|
73
|
+
- `✂ Cut: <file>, "<quote>" (<reason>)`
|
|
74
|
+
- `➡ Move needed: <file>, "<quote>" (<reason>)`, for a model-decided `MOVE` this step reported rather than cut
|
|
75
|
+
- `⏭ Kept: <file>, "<quote>", <reason for keeping>`
|
|
76
|
+
- `⚠ Not located: <file>, "<quote>" not found or found more than once`
|
|
77
|
+
|
|
78
|
+
When every finding reads `KEEP`, output `✅ Classify: <n> findings, all KEEP` and nothing further.
|
|
@@ -50,7 +50,7 @@ Pass `--variant light` or `--variant dark` to override the source variant for a
|
|
|
50
50
|
Run this once after the first render, then stop.
|
|
51
51
|
|
|
52
52
|
1. Convert the deck to images: `soffice --headless --convert-to pdf <deck>.pptx` then `pdftoppm -r 90 -png <deck>.pdf slide`. If `soffice` or `pdftoppm` is missing, skip the image pass and say so. Do not fail the render.
|
|
53
|
-
2.
|
|
53
|
+
2. Open and inspect every rendered image in this session, checking each slide for overlap, overflow, low contrast, and empty regions.
|
|
54
54
|
3. Fix the reported issues in `SLIDES.md` once, re-render, and stop. Do not loop indefinitely on aesthetics.
|
|
55
55
|
|
|
56
56
|
## Response
|
|
@@ -11,7 +11,7 @@ Without this skill, a session drafting a wireframe for a surface with no file ye
|
|
|
11
11
|
|
|
12
12
|
## Must
|
|
13
13
|
|
|
14
|
-
- Read `standards/wireframes.md` before drafting, since the frontmatter contract, the
|
|
14
|
+
- Read `standards/wireframes.md` before drafting, since the frontmatter contract, the regions list, the states table, the exclusions section, and the Transcription-wireframes branch are what make the file arguable against a sibling
|
|
15
15
|
- Walk the whole `canon/wireframes/` tree, including a grouped surface's own subfolder, before drafting, since a top-level-only check misses a nested match
|
|
16
16
|
- Detect an existing higher tier from `canon/DESIGN.md` and the wireframes tree and report it, never build a companion render for it, since no shipped mechanism produces one
|
|
17
17
|
- Draft in transcription mode, citing the real source, when the surface names an already-built component. Draft in role-intent mode otherwise.
|
|
@@ -11,7 +11,7 @@ A project the surface move has not reached keeps its wireframes folder under `.c
|
|
|
11
11
|
|
|
12
12
|
Read these files in parallel:
|
|
13
13
|
|
|
14
|
-
- `${CLAUDE_SKILL_DIR}/../../standards/wireframes.md`: the
|
|
14
|
+
- `${CLAUDE_SKILL_DIR}/../../standards/wireframes.md`: the four questions a wireframe must answer, its frontmatter, the regions list and states table, the exclusions section, the Transcription-wireframes branch, and what moves to a context entry instead
|
|
15
15
|
- `${CLAUDE_SKILL_DIR}/../../standards/markdown.md`: banned words, punctuation, and formatting for the prose around the fences
|
|
16
16
|
- The `write-human` skill: voice, rhythm, and sentence construction for the prose around the fences
|
|
17
17
|
|
|
@@ -25,15 +25,18 @@ This skill stays fully independent of `docs-fold`'s wireframe coverage sweep, wh
|
|
|
25
25
|
## Tier detection
|
|
26
26
|
|
|
27
27
|
- Read `canon/DESIGN.md` and every existing `canon/wireframes/` file for a tier signal: a Stitch, Excalidraw, or Figma reference, or a marker naming one of them.
|
|
28
|
-
- State the detected tier at the confirm step. Always draft the
|
|
28
|
+
- State the detected tier at the confirm step. Always draft the regions-and-states shape regardless of what is detected, since that is the only shape this skill or any other shipped mechanism produces, adding the ASCII sketch fence only when the layout is not built yet. Report a higher tier rather than attempting a companion render for it.
|
|
29
29
|
- Default silently to tier 0 when nothing is detected.
|
|
30
30
|
|
|
31
31
|
## Draft
|
|
32
32
|
|
|
33
33
|
- Decide the mode before drafting. When the surface names an already-built component or file, open that source and draft in transcription mode, citing the render function, the stylesheet rule, or the built file each region and label traces to, per the standard's Transcription-wireframes section.
|
|
34
34
|
- Draft in role-intent mode otherwise: label each region by its role, never by a class name or a token value.
|
|
35
|
-
- Draft `title` and `description` frontmatter, then
|
|
36
|
-
-
|
|
35
|
+
- Draft `title` and `description` frontmatter, then a lead paragraph naming what the surface is for and what it covers, then `## Regions` as a bullet list naming every region and where it sits relative to the others.
|
|
36
|
+
- Draw an ASCII `plaintext` fence with `←` role annotations only when the layout is not built yet. Skip the fence in transcription mode, which already cites the built source instead.
|
|
37
|
+
- Draft `## States` as a table listing every state a visitor can reach, what reaches it, what it shows in words, and its evidence folder, reading `not captured` in the evidence cell until a capture lands.
|
|
38
|
+
- Follow with `## Copy`, `## Behavior`, and `## Not on this surface`, against `${CLAUDE_SKILL_DIR}/../../standards/wireframes.md`'s template.
|
|
39
|
+
- Give a layout that changes across a breakpoint or state its own entry in the regions list, named by what triggers it, never for a spacing difference alone.
|
|
37
40
|
- Leave out algorithms, event-handler code, framework prop or class names outside transcription mode, and anything else the standard sends to a context entry instead.
|
|
38
41
|
|
|
39
42
|
## Confirm
|
package/docs/agents/commands.md
CHANGED
|
@@ -58,7 +58,7 @@ Full help: `canon <command> --help`. Behavior notes for the install and sync ver
|
|
|
58
58
|
| `canon migrate rename` | Rewrite every unprotected `aitk` token to `canon` and move the paths that carry the name, reporting the plan without `--write` (`--scope`, `--json`) |
|
|
59
59
|
| `canon migrate skill-names` | Move the prefixed skill folders onto their two-word names and rewrite every citation, reporting the plan without `--write` (`--root`, `--json`) |
|
|
60
60
|
| `canon migrate records` | Move the gitignored session records to `.canon/` and repoint every tracked citation, reporting the plan without `--write` (`--root`, `--json`) |
|
|
61
|
-
| `canon migrate surface-roots` | Move the tracked surfaces (`context/`, `wireframes/`, the three loose documents, and the install stamp folder) from `.claude/` to `canon/` with `git mv` and repoint every tracked citation, reporting the plan without `--write` (`--root`, `--json`)
|
|
61
|
+
| `canon migrate surface-roots` | Move the tracked surfaces (`context/`, `decisions/`, `wireframes/`, the three loose documents, and the install stamp folder) from `.claude/` to `canon/` with `git mv` and repoint every tracked citation, reporting the plan without `--write` (`--root`, `--json`) |
|
|
62
62
|
| `canon migrate record-tree` | Repoint the old-root citations inside the records themselves, scoped to the live folders and reporting every line without `--write` (`--root`, `--json`) |
|
|
63
63
|
| `canon migrate rule-layout` | Move a target's installed rules from the flat `.claude/rules/<subdir>/` layout to `.claude/rules/canon/<subdir>/`, reporting the plan without `--write` (`--root`, `--json`) |
|
|
64
64
|
| `canon migrate scratch-evidence` | Move a folder under `.tmp/` that a durable record cites as evidence to `.canon/review/evidence/`, repointing every citation live or archived, reporting the plan without `--write` (`--root`, `--json`) |
|
|
@@ -66,7 +66,11 @@ Full help: `canon <command> --help`. Behavior notes for the install and sync ver
|
|
|
66
66
|
| `canon worktrees list` | Report which worktrees are reclaimable, keyed on the pull request having merged, with every refusal and the removal route named (`--json`) |
|
|
67
67
|
| `canon worktrees reclaim` | Remove every reclaimable worktree and the branch behind it, reporting without acting under `--dry-run` (`--json`) |
|
|
68
68
|
| `canon comments scan` | Measure comment density by language and comment kind, with a trend recomputed from git |
|
|
69
|
-
| `canon context audit` | Report required sections, length, cited paths, reference form, catalog tables, provenance, superseded-decision narration, and
|
|
69
|
+
| `canon context audit` | Report required sections, length, cited paths, reference form, catalog tables, provenance, superseded-decision narration, index drift, the architecture record's word weight, and wireframe states against their evidence folders |
|
|
70
|
+
| `canon context classify diff` | Classify the chunks a git range changed, each with its enclosing section, as keep, replace, history, or move (`--base`, `--doc-types`, `--json`) |
|
|
71
|
+
| `canon context classify sweep` | Classify every section of the five canonical doc types, split at H3, as keep, rewrite, or move (`--doc-types`, `--json`) |
|
|
72
|
+
| `canon context classifier show` | Report the resolved classifier backend and model and which source decided them (`--json`) |
|
|
73
|
+
| `canon context classifier set` | Write the project classifier setting to `canon/config/classifier.toml` (`--backend`, `--model`, `--json`) |
|
|
70
74
|
| `canon markdown audit` | Fail any markdown path on a banned character, word, or spelling, or a dead relative link, and report the structural checkpoints |
|
|
71
75
|
| `canon claude skills audit` | Report both skill corpora against the mechanical rules in `standards/skill.md` |
|
|
72
76
|
| `canon standards audit` | Report the corpus against the success-criterion gate `standards/standard.md` states, failing only on a standard new to the branch (`--json`, `--arrivals-only`) |
|
|
@@ -143,7 +147,7 @@ Each domain exposes a consistent shape where applicable: `list`, `install`, `syn
|
|
|
143
147
|
| `intake` | `list`, `answer` |
|
|
144
148
|
| `teach` | `list`, `open`, `resource`, `glossary`, `lesson`, `stylesheet`, `nav`, `render` |
|
|
145
149
|
| `comments` | `scan` |
|
|
146
|
-
| `context` | `audit`
|
|
150
|
+
| `context` | `audit`, `classify diff`, `classify sweep`, `classifier show`, `classifier set` |
|
|
147
151
|
| `markdown` | `audit` |
|
|
148
152
|
| `secrets` | `scan` |
|
|
149
153
|
| `deps` | `audit` |
|
|
@@ -169,7 +173,7 @@ Common patterns:
|
|
|
169
173
|
|
|
170
174
|
A record folder already present at the destination is a refusal rather than a merge, and a line carrying `canon-keep-record-root`, or the nearest non-blank line below it, keeps the old spelling for prose that dates a decision. The records themselves are never swept: everything under `.canon/` and every `.claude/` record folder is passed over and reported as a count on its own line, which is what keeps the run that follows the ignore collapse touching the same files as one before it. Running it twice rewrites nothing, which is the check that the exclusions, the markers, and that skip all fired.
|
|
171
175
|
|
|
172
|
-
`migrate surface-roots` moves the tracked surfaces from `.claude/` to `canon/`: `context/`, `wireframes/`, `ARCHITECTURE.md`, `REQUIREMENTS.md`, `DESIGN.md`, and the install stamp folder, respelled `canon/config/` since a project under `canon/` reserves the bare `canon` name for the CLI's own install. Every path is tracked, so each file moves with `git mv` and its history follows it, and every tracked citation of one is rewritten in the same run. `rules/`, `skills/`, `hooks/`, and `settings.json` stay where Claude Code reads them. It reports until `--write` is passed, and a destination already present under `canon/` refuses the whole plan rather than splitting a surface across both roots.
|
|
176
|
+
`migrate surface-roots` moves the tracked surfaces from `.claude/` to `canon/`: `context/`, `decisions/`, `wireframes/`, `ARCHITECTURE.md`, `REQUIREMENTS.md`, `DESIGN.md`, and the install stamp folder, respelled `canon/config/` since a project under `canon/` reserves the bare `canon` name for the CLI's own install. Every path is tracked, so each file moves with `git mv` and its history follows it, and every tracked citation of one is rewritten in the same run. `rules/`, `skills/`, `hooks/`, and `settings.json` stay where Claude Code reads them. It reports until `--write` is passed, and a destination already present under `canon/` refuses the whole plan rather than splitting a surface across both roots.
|
|
173
177
|
|
|
174
178
|
A line carrying `canon-keep-surface-root`, or the nearest non-blank line above it, keeps the old spelling. A rule's frontmatter `paths:` glob, a citation shaped like a path into another repository, and one inside a dated paragraph are reported by file and line and left alone. Running it twice rewrites nothing, which is the idempotence check. A project that never runs it keeps resolving each surface under `.claude/`, since every reader takes whichever root holds the entry.
|
|
175
179
|
|
|
@@ -55,6 +55,8 @@ The table check reports a catalog that grows a row per shipped thing, not a tabl
|
|
|
55
55
|
|
|
56
56
|
The provenance check reports the markers narrating how a domain reached its shape rather than describing what it is: a date, a change number, or a release label. The standard admits a rejected alternative and the reasoning that killed it while refusing the provenance attached to it, so a marker names a line to read rather than a line to delete. Findings group by entry and sort left to right within a line, since what a reader acts on is which file to open.
|
|
57
57
|
|
|
58
|
+
A change number matches at any digit count, so `PR #7` and `#49` report alongside a four-digit number. Displayed spans are masked before the match runs, which is what keeps a heading's own auto-derived link destination, `(#7-open-questions)`, and a hex color in a code span, `` `#000` ``, from reading as a change reference: both are text an entry shows rather than a claim it makes. <!-- canon-allow-reference: illustrates the input shape the rule reads -->
|
|
59
|
+
|
|
58
60
|
A date stamping a measurement is excluded, because the standard cuts a date attached to a change and permits one dating a figure. The check reads the clause in front of the date, back to the nearest sentence boundary, for one of five verbs: measured, verified, driven, passed, and fired. The noun `run` counts only where it sits against the date, so `A run on 2026-08-14` is excluded and `Runs on erclx/canon#632 and erclx/canon#634 landed 2026-08-02` reports. The set is closed, and a date it cannot place reports as a change marker rather than as a state of its own, which names one date too many rather than clearing one the rule cuts. <!-- canon-allow-reference: illustrates the input shape the rule reads -->
|
|
59
61
|
|
|
60
62
|
A release label reports with or without its leading `v` at three segments, since the rule cuts the label rather than a spelling of it. Two segments still need the `v`, which keeps a dollar cost and a duration out. Another tool's version reports too, and the check cannot tell one from a release, so treat a version beside a tool name as a line to read rather than one to cut.
|
|
@@ -89,7 +91,7 @@ The JSON record carries the findings per entry as `entries[].narration` and the
|
|
|
89
91
|
|
|
90
92
|
## The architecture record
|
|
91
93
|
|
|
92
|
-
|
|
94
|
+
Three findings read `canon/ARCHITECTURE.md` rather than a folder, and only the first is a fact.
|
|
93
95
|
|
|
94
96
|
The length check compares the record against the ceiling it derives for itself, and only a record that states its own allowances has one. No standard sets a length rule for this document, so the numbers belong to whichever record declares them. The check reads a frame allowance and an allowance per decision out of the record's own prose and puts the ceiling at the frame plus the allowance times the decision count. The JSON record carries what it read as `architecture.allowances` and the reading as `architecture.lines` against `architecture.ceiling`.
|
|
95
97
|
|
|
@@ -103,9 +105,27 @@ Three limits are stated on every run rather than hidden. The countable signal re
|
|
|
103
105
|
|
|
104
106
|
The report gates nothing. Deciding whether a sentence states a claim is a judgment no parser settles, so the output names candidates for a reader. This answers a different question from the verification anchors `standards/architecture.md` describes, which record that one cited number was re-read. That mechanism says whether a marked figure held, and this one says how much of the record could be checked at all.
|
|
105
107
|
|
|
108
|
+
The third finding is a word count, measured in words rather than lines: one figure for the whole record and one per decision. `standards/architecture.md` asks a session to judge the file's weight by reading it rather than by counting it, and reads the word figure alongside that judgment when one is available. A paragraph written one source line to a paragraph passes the rendered-line measure other checks use while still reading heavy, which is the gap a word count closes without turning into a second cap.
|
|
109
|
+
|
|
110
|
+
The `## Risks / open questions` section is weighed the same way, reported apart from the whole-record figure since the standard singles it out for holding only what is still open. This finding gates nothing under any mode. The JSON record carries the whole-record figure as `architecture.words`, the section figure as `architecture.risksWords` where the record carries the heading, and the per-decision figure as `architecture.decisions[].words`.
|
|
111
|
+
|
|
112
|
+
## Wireframe states
|
|
113
|
+
|
|
114
|
+
Every entry under `canon/wireframes/` carrying a `## States` table is checked against its evidence folders on disk. `State` and `Evidence` are matched by header text rather than column position, since the standard's own template could still move a column during its own review. An entry with no such table is out of scope and reports nothing.
|
|
115
|
+
|
|
116
|
+
An evidence cell's path is read as written and resolved against the project root, since the standard puts the path in the cell rather than a state name a convention would have to guess at. A state whose cited path resolves to no directory is a missing folder, measured in states: one finding per row. A directory sitting under a root at least one row already cites, but named in no row itself, is an unlisted folder, measured in folders: one finding per directory.
|
|
117
|
+
|
|
118
|
+
Both are counted rather than only listed, since a count is what a reader compares run to run. A `not captured` cell is the one value the standard exempts from having a folder, and it drops out of both counts.
|
|
119
|
+
|
|
120
|
+
The third finding reads the whole entry rather than one row: whether it carries a `plaintext`-fenced sketch while a state's evidence already exists on disk. The standard asks the fence to come out the moment a layout has a capture to show instead, so a sketch surviving past that point is a boolean per entry rather than a count.
|
|
121
|
+
|
|
122
|
+
The unit here is the entry rather than the layout the standard's own rule is stated against. A table names states, not the layouts a wireframe's `## Regions` section can split into at a breakpoint, so this finding has no narrower unit to match a sketch against the evidence for its own layout alone. An entry with a captured default layout and a sketch for a breakpoint layout that is not built yet is conforming, and this finding still reports it, which is why it stays advisory under every mode rather than joining the states-mismatch gate below.
|
|
123
|
+
|
|
124
|
+
All three wireframe findings are printed under a bare run. The states-mismatch finding, missing and unlisted folders together, gates at `2` under `--gate`, alongside a missing required section and index drift. The sketch finding stays advisory under both modes, for the reason above. The JSON record carries them per entry under `wireframes[]`, as `rows`, `missingFolders`, `unlistedFolders`, and `sketchWithEvidence` alongside `sketchLine`.
|
|
125
|
+
|
|
106
126
|
## Which folders each check reaches
|
|
107
127
|
|
|
108
|
-
The provenance, required-section, and narration checks cover `canon/context/` alone, the reference-form check covers the split folders inside it,
|
|
128
|
+
The provenance, required-section, and narration checks cover `canon/context/` alone, the reference-form check covers the split folders inside it, length and the table finding reach every audited folder, and the wireframe states check covers `canon/wireframes/` alone.
|
|
109
129
|
|
|
110
130
|
What narrows the three is stated in `standards/context.md`, which opens its scope by handing diagrams and wireframes to `diagrams.md` and `wireframes.md`, and the sibling standards do not restate it. A marker reported in a diagram entry would cite a rule that entry's own standard routes elsewhere, and a diagram entry carries a heading per kind rather than a run of bullets deciding anything. The split is between kinds of rule rather than kinds of folder, and what decides it is which tier states the rule rather than what the check measures.
|
|
111
131
|
|
|
@@ -29,7 +29,7 @@ canon context audit tooling/base/seeds --gate
|
|
|
29
29
|
|
|
30
30
|
## Folder scope
|
|
31
31
|
|
|
32
|
-
Scope defaults to `context`, `diagrams`, and `wireframes`, and a folder the project does not carry is skipped rather than reported. A domain that outgrew one file and split into `<domain>/` is audited as its own folder, so a split entry measures at the same grain as a flat one.
|
|
32
|
+
Scope defaults to `context`, `decisions`, `diagrams`, and `wireframes`, and a folder the project does not carry is skipped rather than reported. A domain that outgrew one file and split into `<domain>/` is audited as its own folder, so a split entry measures at the same grain as a flat one.
|
|
33
33
|
|
|
34
34
|
A name passed to `--folder` resolves under the record roots first, `.canon/` ahead of `.claude/`, and at the project root last, which is what puts `docs/` and any later corpus in reach of the same engine. The root base is reached only by a name the caller passes, so the default list still resolves under a record root alone and a project holding a root `wireframes/` is not audited against a standard it never adopted. `diagrams` is the one default name that is a session record and moves with them, which is why both record roots are in the list rather than one, and `docs/agents/records.md` states the read order every verb shares. The scope line prints the resolved path, so a project carrying both spellings reads which one was taken. The JSON record carries the base per folder as `folders[].base`.
|
|
35
35
|
|
|
@@ -37,9 +37,11 @@ A run where no requested name resolves refuses, whichever list it read. Naming t
|
|
|
37
37
|
|
|
38
38
|
## Exit codes
|
|
39
39
|
|
|
40
|
-
Exit codes are `0` for a clean run, `1` for a refusal, and `2` for a gating finding. An unresolved citation gates under every mode. An architecture record that states its own line allowances gates when it is past the ceiling those derive, on any run that measures it, which is every mode except `--citations-only`, and a record stating none is reported and never gated.
|
|
40
|
+
Exit codes are `0` for a clean run, `1` for a refusal, and `2` for a gating finding. An unresolved citation gates under every mode. An architecture record that states its own line allowances gates when it is past the ceiling those derive, on any run that measures it, which is every mode except `--citations-only`, and a record stating none is reported and never gated.
|
|
41
41
|
|
|
42
|
-
|
|
42
|
+
Entry length, reference form, table, provenance, narration, the record's claim classification, and every word figure print and return `0` under every mode, because each is a judgment or a weight read alongside one, and failing a push on either would make the check something to route around. Narration is the weakest of the printed measures, since whether two bullets share a subject is a call the measure approximates from structure alone, and one of the shapes it matches is the rejected alternative the standard asks an entry to keep.
|
|
43
|
+
|
|
44
|
+
Required-section, index, and wireframe-states findings sit between the two. All three are answerable from the file rather than weighed, so `--gate` promotes them to failing codes while a bare run leaves them advisory. Sketch-with-evidence sits with the printed measures instead, for the reason `context-audit-checks.md` states: it reads a whole entry against whether any of its states has evidence, not one layout against its own evidence, so a conforming file can still trip it. The toolkit runs the bare form against itself and the widened form against the seed tree, described below.
|
|
43
45
|
|
|
44
46
|
## The seed gate
|
|
45
47
|
|
|
@@ -81,3 +83,11 @@ Append `<!-- audit-ignore-citations: <path> -->` to the source line in either ca
|
|
|
81
83
|
The marker itself stays out of anything that installs. A seed, a plugin skill body, and a stack reference all reach a target, so a marker there lands as toolkit bookkeeping in someone else's tree. Reword those lines to drop the path instead, and where a stop message has to spell it, move that message into a fenced block, which this check already skips.
|
|
82
84
|
|
|
83
85
|
The pattern spells both record-root prefixes, so a citation into a folder that has moved still resolves and a folder resolved at the project root is measured by every other check while contributing nothing here. A pattern fixed at one root matches nothing after a move and reports nothing, which is a stale reference passing the check written to find it. Widening it to a bare `docs/x.md` would match prose that references nothing, which is a separate decision from where entries come from. A run whose folders all resolved at the root says the check is out of scope rather than reporting that zero paths resolved, and the same run under `--citations-only` refuses, because a gate exiting clean on a scope it could not build is the failure the gate exists to catch.
|
|
86
|
+
|
|
87
|
+
## The wireframe states gate
|
|
88
|
+
|
|
89
|
+
Every entry under `canon/wireframes/` carrying a `## States` table is checked one-to-one against its evidence folders, matching the table's `State` and `Evidence` columns by header text rather than position, so a project reordering the template's own columns still resolves. An entry with no such table reports nothing, which is what leaves a project on an older wireframe shape silent until it adopts one.
|
|
90
|
+
|
|
91
|
+
An evidence cell resolves as the literal path it names, taken from the project root. A state whose cited folder does not exist is a states mismatch, and so is a folder sitting under a cited evidence root that no row names. A `not captured` cell is the one exception the standard admits, and it excuses that row from both readings. A `plaintext` sketch still carried once a state's evidence exists on disk is a third finding this check adds, reading the entry as a whole rather than one row.
|
|
92
|
+
|
|
93
|
+
The states mismatch is printed under a bare run and gates at `2` under `--gate`, alongside a missing required section and index drift. The sketch finding is printed and stays advisory under both modes: it has no way to pair a sketched layout with that layout's own evidence, only the entry with any evidence at all, so a conforming file, a captured default layout beside a sketch of a breakpoint layout nobody has built, can still trip it.
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Doc classifier
|
|
3
|
+
description: Classifying canonical-doc content as keep, replace/rewrite, history, or move in diff and sweep mode, the classifier setting pair, the record shape, and the exit codes
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Doc classifier
|
|
7
|
+
|
|
8
|
+
`canon context classify` reads content from the five canonical doc types (`context/<domain>.md`, `ARCHITECTURE.md`, `wireframes/<surface>.md`, `DESIGN.md`, `REQUIREMENTS.md`) and reports whether each piece states the project as it stands or should be rewritten, narrated elsewhere, or moved to another surface. It reports and never gates: a finding is a judgment for a writer to act on, not a fact a push fails over. The `docs-fold` skill calls this verb in diff mode over its own diff baseline. Wiring it into the merge gate or `canon context audit` is separate work this verb does not do.
|
|
9
|
+
|
|
10
|
+
Two modes read different units. Diff mode reads the chunks a git range changed, each with the section it landed in, which is what a session checks right after an edit. Sweep mode reads every section of the five doc types, split at H3, which is what a cleanup pass or a periodic re-scan runs over a whole corpus.
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
canon context classify diff
|
|
14
|
+
canon context classify diff --base origin/main --json
|
|
15
|
+
canon context classify diff --doc-types context,wireframes
|
|
16
|
+
canon context classify sweep
|
|
17
|
+
canon context classify sweep --doc-types design,requirements --json
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
| Option | Behavior |
|
|
21
|
+
| -------------------- | -------------------------------------------------------------- |
|
|
22
|
+
| `--base <ref>` | Diff mode only. Far side of the range, defaulting to the trunk |
|
|
23
|
+
| `--doc-types <list>` | Comma-separated canonical doc types (default: all five) |
|
|
24
|
+
| `--backend <name>` | Override the resolved model backend for this run |
|
|
25
|
+
| `--model <name>` | Override the resolved model name for this run |
|
|
26
|
+
| `--json` | Add a machine-readable record on stdout |
|
|
27
|
+
|
|
28
|
+
## Two layers
|
|
29
|
+
|
|
30
|
+
The regex layer always runs. It is free, needs nothing installed, and catches narration (a branch name, "closed on", "did not survive") and a source file path named inside a wireframe. It never answers REPLACE in diff mode, since telling a restated figure from a genuinely new one needs the section a hunk landed in, which the model layer reads and the regex layer does not.
|
|
31
|
+
|
|
32
|
+
The local Ollama layer runs only when configured, through `canon context classifier`. When it runs, its call is one chunk or section per request, never batched: the groundwork measurement behind this verb found that batching 16 hunks into one call returned KEEP for every one of them. Thinking is always off, since it was measured to catch nothing thinking-off missed while running roughly five times slower and, in sweep mode, losing three real flags by reasoning past them.
|
|
33
|
+
|
|
34
|
+
A finding carries both layers' readings when the model ran. The `verdict` field takes the model's reading when it ran and parsed, and falls back to the regex reading otherwise, since the model catches shapes the regex layer cannot reach structurally. `decidedBy` names which one won.
|
|
35
|
+
|
|
36
|
+
A configured-but-unreachable backend warns on stderr and falls back to the regex layer alone. The run still exits clean: the record's `modelLayer` field names why the model layer did not run (`off`, `skipped-no-model`, `skipped-unreachable`, or `ran`), so a clean regex-only report never reads as a clean model pass.
|
|
37
|
+
|
|
38
|
+
## The classifier setting
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
canon context classifier show
|
|
42
|
+
canon context classifier show --json
|
|
43
|
+
canon context classifier set --backend ollama --model qwen3.8:27b
|
|
44
|
+
canon context classifier set --backend off
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
The backend and model resolve independently through the same four-tier precedence: a flag on the verb, then `CANON_CLASSIFIER_BACKEND` / `CANON_CLASSIFIER_MODEL`, then `canon/config/classifier.toml`, then off. `classifier show` reports the resolved backend and model and which tier decided them, without running a classification. There is no default model name: a model that resolves on one machine means nothing on another, so a backend configured with no model reports `no-model` from `show` and runs the regex layer alone from `classify`.
|
|
48
|
+
|
|
49
|
+
`classifier set` writes `canon/config/classifier.toml`, creating `canon/config/` when a project does not carry it yet:
|
|
50
|
+
|
|
51
|
+
```toml
|
|
52
|
+
[classifier]
|
|
53
|
+
backend = "ollama"
|
|
54
|
+
model = "qwen3.8:27b"
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
`--backend off` writes a file with no `model` line, which reads back as `off` at the same tier a missing file would default to, but with a source line saying the file decided it rather than the default.
|
|
58
|
+
|
|
59
|
+
## The record
|
|
60
|
+
|
|
61
|
+
```json
|
|
62
|
+
{
|
|
63
|
+
"decision": "ok",
|
|
64
|
+
"mode": "diff",
|
|
65
|
+
"backend": "ollama",
|
|
66
|
+
"model": "qwen3.8:27b",
|
|
67
|
+
"modelLayer": "ran",
|
|
68
|
+
"settingsSource": "file",
|
|
69
|
+
"findings": [
|
|
70
|
+
{
|
|
71
|
+
"file": "canon/context/retrieval.md",
|
|
72
|
+
"docType": "context",
|
|
73
|
+
"regex": {
|
|
74
|
+
"verdict": "KEEP",
|
|
75
|
+
"quote": "",
|
|
76
|
+
"reason": "no narration or wrong-surface pattern"
|
|
77
|
+
},
|
|
78
|
+
"model": {
|
|
79
|
+
"verdict": "REPLACE",
|
|
80
|
+
"quote": "the count moved",
|
|
81
|
+
"reason": "restates a figure the section already carries"
|
|
82
|
+
},
|
|
83
|
+
"verdict": "REPLACE",
|
|
84
|
+
"decidedBy": "model"
|
|
85
|
+
}
|
|
86
|
+
]
|
|
87
|
+
}
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Sweep mode's findings carry a `heading` field alongside `file` and use the sweep vocabulary (KEEP, REWRITE, MOVE) rather than diff mode's four (KEEP, REPLACE, HISTORY, MOVE). REWRITE stands in for both REPLACE and HISTORY, matching the sweep prompt's own three-verdict vocabulary: a whole section already shows its own history in view, so there is no diff-mode split left to make.
|
|
91
|
+
|
|
92
|
+
## Exit codes
|
|
93
|
+
|
|
94
|
+
| Code | Meaning |
|
|
95
|
+
| ---- | ------------------------------------------------------------- |
|
|
96
|
+
| `0` | the run completed, whatever the findings say |
|
|
97
|
+
| `1` | refused: a bad range, an unreadable file, or a malformed flag |
|
|
98
|
+
|
|
99
|
+
Findings never set a failing exit code, in either mode. Diff mode refuses on a git range it cannot resolve. Both modes refuse on a file the run could not read.
|
package/docs/agents/index.md
CHANGED
|
@@ -15,6 +15,7 @@ CLI catalog and invocation rules for agents, split by command domain. Start with
|
|
|
15
15
|
- [Comments](comments.md): Comment density by language and kind, the two structural exclusions, and how the degradation sweep finds its vocabulary
|
|
16
16
|
- [Context audit checks](context-audit-checks.md): What each non-gating check reports, the unit each checkpoint is measured in, the architecture record's length gate and claim coverage, which folders each check reaches, and what moved to the attribute tier
|
|
17
17
|
- [Context audit](context-audit.md): Running the audit, its flags and folder scope, the exit codes, the citation gate, and the widened gate the seed stage runs
|
|
18
|
+
- [Doc classifier](context-classify.md): Classifying canonical-doc content as keep, replace/rewrite, history, or move in diff and sweep mode, the classifier setting pair, the record shape, and the exit codes
|
|
18
19
|
- [Self-stated counts](counts.md): Reading a sentence that asserts a closed catalog's size, how a match is decided, the plausibility filter that keeps a generic word from matching a subset, and why the sweep reports rather than gates
|
|
19
20
|
- [Demo](demo.md): Compiling a screencast draft into a runnable plan, driving a served application to a recording and a still, reading numbered frames back out of a recording, the pointer the recording paints, and what each refusal reports
|
|
20
21
|
- [Design board](design-board.md): Generating a static index over a project's design surfaces, what each panel reads, and which two stay toolkit-checkout-only
|
package/docs/target-projects.md
CHANGED
|
@@ -196,6 +196,21 @@ Run the second line once per stack the project holds, since the two hooks above
|
|
|
196
196
|
|
|
197
197
|
The order carries the reason. A sync replaces each toolkit-owned copy with one already carrying the new names, and the sweep afterwards reaches the prose the project wrote itself. Sweeping first rewrites those installed files in place, which moves them off the hash the install recorded, so the next sync reads them as edited by the project and leaves them alone.
|
|
198
198
|
|
|
199
|
+
### Move the surfaces off `.claude/`, once
|
|
200
|
+
|
|
201
|
+
Tracked surfaces moved out of `.claude/` and into a root of their own. `context/`, `decisions/`, `wireframes/`, the three loose documents (`ARCHITECTURE.md`, `REQUIREMENTS.md`, `DESIGN.md`), and the install stamp folder, respelled `canon/config/`, now live under `canon/`, and `rules/`, `skills/`, `hooks/`, and `settings.json` stay put since Claude Code reads those by path.
|
|
202
|
+
|
|
203
|
+
Run `canon upgrade` first if you have not, then run this from inside the project:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
canon migrate surface-roots --json
|
|
207
|
+
canon migrate surface-roots --write --json
|
|
208
|
+
```
|
|
209
|
+
|
|
210
|
+
The first line reports the plan and the second applies it, moving each surface with `git mv` so its history follows and repointing every tracked citation of one in the same run. See `canon docs agents` for the full file list rather than reading it here.
|
|
211
|
+
|
|
212
|
+
Neither `canon sync --check` nor any other command notices a surface still sitting at `.claude/`, so running this is on you rather than on a prompt from the toolkit.
|
|
213
|
+
|
|
199
214
|
### Check first
|
|
200
215
|
|
|
201
216
|
`canon sync --check <path>` reports what has drifted without writing anything. It splits each difference by cause, which is the question that decides what to do next.
|
|
@@ -19,8 +19,9 @@ canon/
|
|
|
19
19
|
├── REQUIREMENTS.md ← goals, non-goals, MVP scope
|
|
20
20
|
├── ARCHITECTURE.md ← technical design decisions
|
|
21
21
|
├── DESIGN.md ← visual intent and token decisions (UI projects)
|
|
22
|
-
├── wireframes/ ←
|
|
23
|
-
|
|
22
|
+
├── wireframes/ ← regions, states, UI copy, and interaction rules (UI projects)
|
|
23
|
+
├── context/ ← per-domain narrative loaded on demand via index.md
|
|
24
|
+
└── decisions/ ← decision history a canonical doc points at, never loaded eagerly
|
|
24
25
|
|
|
25
26
|
.claude/
|
|
26
27
|
└── rules/ ← path-scoped governance rules, written by canon gov install
|
|
@@ -33,7 +34,7 @@ canon/
|
|
|
33
34
|
└── tmp/ ← deletable scratch, safe to remove without loss
|
|
34
35
|
```
|
|
35
36
|
|
|
36
|
-
A project scaffolded before the move keeps its records under `.claude/`, and every command reads either root. `canon migrate records` moves one project across and repoints what cites it, and `canon migrate record-tree` follows it to reach the citations inside the records themselves, which the first verb passes over because it enumerates through git. A project scaffolded before the surface move keeps its context, wireframes, and loose documents under `.claude/` the same way, and `canon migrate surface-roots` moves those to `canon/` with the history following each file.
|
|
37
|
+
A project scaffolded before the move keeps its records under `.claude/`, and every command reads either root. `canon migrate records` moves one project across and repoints what cites it, and `canon migrate record-tree` follows it to reach the citations inside the records themselves, which the first verb passes over because it enumerates through git. A project scaffolded before the surface move keeps its context, decisions, wireframes, and loose documents under `.claude/` the same way, and `canon migrate surface-roots` moves those to `canon/` with the history following each file.
|
|
37
38
|
|
|
38
39
|
Three tiers of context load with different cost: always-loaded (root `CLAUDE.md`, `canon/REQUIREMENTS.md`, `canon/ARCHITECTURE.md`), path-scoped lazy (`.claude/rules/<scope>.md` with `paths:` glob), and on-demand lookup (`canon/context/<domain>.md`, or `canon/context/<domain>/` once a domain outgrows one file, discovered via `canon/context/index.md`). See [the context model](../../canon/context/context-model.md) for the full picture.
|
|
39
40
|
|
|
@@ -14,7 +14,7 @@ Two tools anchor tier 1 and tier 2. Stitch is the agent-addressable default thro
|
|
|
14
14
|
|
|
15
15
|
## Tier 0: prose only
|
|
16
16
|
|
|
17
|
-
The default. `canon/DESIGN.md` holds visual intent as prose plus token tables for color, typography, spacing, borders, motion, and iconography. `.claude/WIREFRAMES.md` holds
|
|
17
|
+
The default. `canon/DESIGN.md` holds visual intent as prose plus token tables for color, typography, spacing, borders, motion, and iconography. `.claude/WIREFRAMES.md` holds each surface's regions and states.
|
|
18
18
|
|
|
19
19
|
Claude Code reads both and writes the implementation. Works for CLI tools, internal dashboards, admin panels, and backend-focused projects.
|
|
20
20
|
|
|
@@ -9,5 +9,5 @@ paths:
|
|
|
9
9
|
|
|
10
10
|
## Authority
|
|
11
11
|
|
|
12
|
-
- Follow the wireframes standard for layout and interaction intent:
|
|
12
|
+
- Follow the wireframes standard for layout and interaction intent: regions, the states table and its evidence links, copy, behavior, exclusions, and what moves to `canon/context/`. It is the single source. Read it with `canon standards wireframes`.
|
|
13
13
|
- Read it before adding or revising a surface.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: Route canon/decisions/ edits to the decisions standard for record shape and lifecycle
|
|
3
|
+
paths:
|
|
4
|
+
- 'canon/decisions/**'
|
|
5
|
+
- '.claude/decisions/**'
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
# Decisions standards
|
|
9
|
+
|
|
10
|
+
## Authority
|
|
11
|
+
|
|
12
|
+
- Follow the decisions standard for folder layout, the ordinal filename, frontmatter, record sections, and the append-only lifecycle. It is the single source. Read it with `canon standards decisions`.
|
package/package.json
CHANGED