@erclx/canon 4.117.0 → 4.118.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-operator/SKILL.md +1 -1
- package/claude/skills/draft-ready/references/assembly.md +8 -0
- package/claude/skills/plan-feature/REQUIREMENT.md +1 -0
- package/claude/skills/plan-feature/SKILL.md +7 -0
- package/claude/skills/review-pr/REQUIREMENT.md +1 -0
- package/claude/skills/review-pr/SKILL.md +3 -1
- package/claude/skills/target-check/references/domains.md +1 -1
- package/docs/agents/commands.md +1 -1
- package/docs/agents/context-audit-checks.md +2 -28
- package/docs/agents/context-audit.md +1 -1
- package/docs/agents/install-and-sync.md +23 -17
- package/docs/target-projects.md +2 -2
- package/docs/workflow/operating-model.md +1 -1
- package/docs/workflow/visual-design-workflow.md +1 -1
- package/governance/rules/claude/510-context.md +0 -12
- package/governance/rules/core/005-behavior.md +1 -2
- package/governance/rules/core/015-output.md +1 -3
- package/governance/rules/core/035-tasks.md +1 -3
- package/governance/rules/core/045-memory.md +0 -1
- package/governance/rules/core/055-scratch.md +2 -4
- package/governance/rules/core/070-planning.md +1 -4
- package/governance/rules/core/087-git.md +2 -2
- package/governance/rules/core/090-code-comments.md +1 -1
- package/governance/rules/ui/460-design-taste.md +0 -15
- package/package.json +1 -1
- package/src/commands/context.ts +11 -111
- package/src/commands/sync.ts +2 -2
- package/src/context/audit.ts +3 -145
- package/src/gate/measures.ts +37 -0
- package/src/gate/stages.ts +9 -0
- package/src/gov/adapter.ts +8 -6
- package/src/records/validate.ts +5 -1
- package/src/sync/check.ts +7 -1
- package/src/sync/engine.ts +90 -10
- package/src/sync/stamp.ts +44 -0
- package/standards/plan.md +24 -1
- package/src/context/narration.ts +0 -99
|
@@ -27,7 +27,7 @@ Read seven fields off the report and carry each to `## Route`:
|
|
|
27
27
|
- `unmigrated`: a domain sitting at the root layout with nothing under `.claude/`. The most urgent finding, because that domain reports no drift of its own while being entirely behind
|
|
28
28
|
- `superseded`: a file a newer seed folder replaced. No command moves it, since the content is the project's own, so this routes to `canon:target-check` for the full per-domain reading rather than ending at the report
|
|
29
29
|
- `seeds`: entries are `matching`, `stale`, `drifted`, or `missing`. Anything but `matching` needs the seed handoff
|
|
30
|
-
- `domains[].entries`: per-file `stale`, `customized`, `stranded`, and `orphaned` as before
|
|
30
|
+
- `domains[].entries`: per-file `stale`, `customized`, `stranded`, and `orphaned` as before, plus `retired` for a rule the toolkit no longer ships, which the next sync deletes
|
|
31
31
|
- `reverse`: what the target holds that no live catalog claims. `unclaimed` lists folders at roots the toolkit stopped shipping, each with an `attribution` of `dropped`, `unattributed`, or `project`. Act on the first two and leave `project` alone, which history proved the project owns
|
|
32
32
|
- `historyUnavailable` on a domain, on `seeds`, or on `reverse`: nothing could be dated, so treat every difference as unverified and say so rather than reporting a file as untouched. It is set on `reverse` when the toolkit itself ships without history, which is the registry-install case, so the walk found nothing rather than finding a clean target
|
|
33
33
|
- `tooling`: read `measured` first. Every count under it is zero when it is false, which is an absence of measurement rather than a measured zero. Past that, `chain` names the stacks the install resolved, nearest first, and `counts.gitignore` counts the managed ignore entries the target is missing.
|
|
@@ -47,10 +47,18 @@ destinations:
|
|
|
47
47
|
|
|
48
48
|
- `<path/to/file>`: copy from the ready folder, <one clause on what it changes>
|
|
49
49
|
|
|
50
|
+
**Verification:**
|
|
51
|
+
|
|
52
|
+
- <the command that proves the copy landed, or "None identified.">
|
|
53
|
+
|
|
50
54
|
**Risks:**
|
|
51
55
|
|
|
52
56
|
- <what could go wrong, or "None identified.">
|
|
53
57
|
|
|
58
|
+
**Review focus:**
|
|
59
|
+
|
|
60
|
+
- <an input the copied files must handle, or "None identified.">
|
|
61
|
+
|
|
54
62
|
**Questions:**
|
|
55
63
|
|
|
56
64
|
None identified.
|
|
@@ -14,6 +14,7 @@ Without this skill, implementation starts before anyone knows what it touches. A
|
|
|
14
14
|
- Read the project's own Claude setup before scanning source, so the plan inherits decisions already made instead of reopening them
|
|
15
15
|
- Name every file the work touches with the reason it is touched
|
|
16
16
|
- Place each new path against the layout guidance with a one-clause reason, loading that guidance only when the plan creates a file or folder, since the planner decides placement and the worker copies whatever path it is given
|
|
17
|
+
- Name how each outcome is proven and which input or state would break the change, so the executing session has a check to run and the reviewer has a place to look
|
|
17
18
|
- Surface each unresolved ambiguity as a numbered question carrying a suggested answer and an empty answer slot, so the plan is decision-ready in one pass
|
|
18
19
|
- State which act a constraint forbids when it names a surface to leave alone, since conforming that surface and retargeting a pointer into it are different acts and only one is out of scope
|
|
19
20
|
- Scale the output to the work. A two-file change with nothing to decide should not produce a plan file.
|
|
@@ -46,6 +46,7 @@ What this skill adds on top of the standard:
|
|
|
46
46
|
- Apply senior judgment to every `- Suggested:` line. Pick the best option and state it in one line with its reason or main tradeoff. No padding, no alternatives unless they change the pick.
|
|
47
47
|
- Suggest a real default when best practice, the codebase, or prior context points to one.
|
|
48
48
|
- Load the `canon:codebase-layout` skill before writing the `**Files to touch:**` entries when any of them names a file or folder that does not exist yet, and give each new path its placement reason in its entry. Skip the load when every entry edits an existing file. Report it rather than proceeding silently when the skill does not resolve.
|
|
49
|
+
- Write `**Verification:**` as one bullet per outcome naming the test or command that proves it, and `**Review focus:**` as the inputs or states that would break the change. You understood the risk before any diff existed, and these two sections carry it to the executing session and to the reviewer.
|
|
49
50
|
- Prefer `None identified.` over low-signal fillers. A small feature should produce a short plan, not a padded one.
|
|
50
51
|
- When three or more questions remain, keep chat output to the file pointer plus a short summary. Inline chat is fine when two or fewer remain.
|
|
51
52
|
|
|
@@ -76,8 +77,14 @@ Output the plan to chat. Do not write a plan file. The markers match the standar
|
|
|
76
77
|
**Files to touch:**
|
|
77
78
|
|
|
78
79
|
- `path/to/file`: reason
|
|
80
|
+
|
|
81
|
+
**Verification:**
|
|
82
|
+
|
|
83
|
+
- <outcome>: `<test or command that proves it>`
|
|
79
84
|
```
|
|
80
85
|
|
|
86
|
+
Small mode carries no `**Review focus:**`, since it already requires Risks to come out `None identified.` and a change with no risk leaves the reviewer no breaking input to name.
|
|
87
|
+
|
|
81
88
|
If real questions exist, include a numbered `**Questions:**` section below, each with a `- Suggested:` line and an `- Answer:` slot:
|
|
82
89
|
|
|
83
90
|
```markdown
|
|
@@ -28,6 +28,7 @@ Scoping a later pass off GitHub's review stamp skipped real work. On 2026-09-07
|
|
|
28
28
|
- Key the body file on the pull request number and the head commit, and on the response it answers once the head repeats, so no two passes overwrite each other
|
|
29
29
|
- Scan the comment for banned characters and internal phase labels before posting, since a finding phrased against a phase label reaches a reader with no task board
|
|
30
30
|
- Answer a `## For the reviewer` bullet in the body, bounded to the section itself rather than the Summary or the Technical Context around it, so the independent vantage stays clear of the author's framing
|
|
31
|
+
- Confirm each `**Review focus:**` item the plan names on a first pass, and turn one the pass cannot confirm into a finding, since the planning session named the breaking inputs before the diff existed and no other reader holds that list
|
|
31
32
|
|
|
32
33
|
## Must not
|
|
33
34
|
|
|
@@ -47,7 +47,7 @@ Read these in parallel from the project root, skipping any that do not exist:
|
|
|
47
47
|
- `canon/REQUIREMENTS.md`: feature scope and non-goals
|
|
48
48
|
- `canon/ARCHITECTURE.md`: technical design decisions
|
|
49
49
|
- `.canon/tasks/priority.md`: where this feature sits on the board and what each neighboring row waits on. Resolve this one at the main worktree root the way `session-worktree` does, since the board is gitignored and a linked worktree holds no copy of it
|
|
50
|
-
- `.canon/plans/feature-<slug>.md` for the branch, when present: the intent the PR should satisfy
|
|
50
|
+
- `.canon/plans/feature-<slug>.md` for the branch, when present: the intent the PR should satisfy, and its `**Review focus:**` section as the inputs this pass must confirm the diff handles
|
|
51
51
|
|
|
52
52
|
Coding standards from `.claude/rules/` are auto-loaded by Claude Code.
|
|
53
53
|
|
|
@@ -157,6 +157,8 @@ Read `## For the reviewer` the same way, bounded to the bullets under that headi
|
|
|
157
157
|
|
|
158
158
|
Answer each bullet in the body, on the same terms as a Testing question: no severity, no count. A request nobody can answer stays owed under the heading and dispatch Step 4 states, keeping the thread open exactly as an unanswered Testing box does. One the pass does answer carries no further weight, since the answer is discharged in the same comment that carries it.
|
|
159
159
|
|
|
160
|
+
On a first pass, confirm each `**Review focus:**` item the plan names against the diff, since the planning session named the inputs that would break the change before any code existed and no other reader holds that list. Report the items in a `**Review focus**` block after the `**For the reviewer**` block, one bullet per item naming what confirmed it, such as a test, a guard, or a branch in the code. The block carries no severity and enters no count. An item the pass cannot confirm becomes a `should-fix` finding under the file that should have handled it, so a reader can tell an item checked from one skipped. A plan whose section reads `None identified.`, or a branch with no plan, takes no block. The section binds the first pass only: a later pass checks whether the finding an unconfirmed item became has landed, like any other prior finding, and never re-raises a confirmed item against a delta that did not touch it.
|
|
161
|
+
|
|
160
162
|
Apply the high-signal filter: flag only what will cause incorrect behavior, break a documented rule, or mislead a downstream feature. If uncertain, do not flag.
|
|
161
163
|
|
|
162
164
|
A later pass applies the same axes to the delta, and adds one check the first pass cannot make: did each prior finding land, and did the fix regress anything it touched. Findings of its own are normal findings, stated at the same severity and counted the same way. That count is one of the two things Step 4 reads to pick the heading, so a pass raising a finding of its own is not a close-out at any severity.
|
|
@@ -39,7 +39,7 @@ Routes by finding. `unmigrated` routes to a relocation the user runs, since no c
|
|
|
39
39
|
|
|
40
40
|
Read `domains` off the report and take every entry it carries rather than naming governance here. Each entry carries `stamped`, per-state `counts`, and `entries` with a `state` and a `rel` path.
|
|
41
41
|
|
|
42
|
-
The states are `matching`, `stale`, `customized`, `drifted`, `orphaned`, `stranded`, and `missing`.
|
|
42
|
+
The states are `matching`, `stale`, `customized`, `drifted`, `orphaned`, `retired`, `stranded`, and `missing`. A `retired` rule is one the toolkit no longer ships, and the next sync deletes it.
|
|
43
43
|
|
|
44
44
|
- Current: every count but `matching` reads zero.
|
|
45
45
|
- Behind: any other count is non-zero. Report the counts and name the paths behind `stale` and `missing`, which a sync repairs, separately from `customized` and `drifted`, which the project wrote and a sync would overwrite.
|
package/docs/agents/commands.md
CHANGED
|
@@ -70,7 +70,7 @@ Full help: `canon <command> --help`. Bare `canon --help` lists every top-level c
|
|
|
70
70
|
| `canon worktrees list` | Report which worktrees are reclaimable, keyed on the pull request having merged, with every refusal and the removal route named (`--json`) |
|
|
71
71
|
| `canon worktrees reclaim` | Remove every reclaimable worktree and the branch behind it, reporting without acting under `--dry-run` (`--json`) |
|
|
72
72
|
| `canon comments scan` | Measure comment density by language and comment kind, with a trend recomputed from git |
|
|
73
|
-
| `canon context audit` | Report required sections, length, cited paths, reference form, catalog tables, provenance,
|
|
73
|
+
| `canon context audit` | Report required sections, length, cited paths, reference form, catalog tables, provenance, index drift, the architecture record against its own ceiling and entry cap and its word weight, and wireframe states against their evidence folders |
|
|
74
74
|
| `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`) |
|
|
75
75
|
| `canon context classify sweep` | Classify every section of the five canonical doc types, split at H3, as keep, rewrite, or move (`--doc-types`, `--json`) |
|
|
76
76
|
| `canon context classifier show` | Report the resolved classifier backend and model and which source decided them (`--json`) |
|
|
@@ -63,32 +63,6 @@ A release label reports with or without its leading `v` at three segments, since
|
|
|
63
63
|
|
|
64
64
|
Fenced blocks are excluded, which keeps a pinned version in an install command from reading as a claim the entry makes. Frontmatter is excluded with them, since the content checks read the body alone, and that is what keeps a diagram entry's dated `verified` stamp a record of its last check rather than a marker to settle. Length is the exception, counting the whole file, so a reader applying the 150-rendered-line checkpoint against the body alone lands a few lines under what the tool reports.
|
|
65
65
|
|
|
66
|
-
## Narration
|
|
67
|
-
|
|
68
|
-
The narration check reports a bullet that states the design a sibling bullet replaced instead of rewriting it. `standards/context.md` asks for the rewrite because the subject is still live and two bullets on one subject leave a reader to work out which of them is current, and no other measure sees that shape.
|
|
69
|
-
|
|
70
|
-
It reads structure rather than words, which the corpus decided. Measured across the 39 entries this toolkit held the day it shipped, the terms carrying clean signal for a supersession are too rare to catch anything: `superseded` appears twice, `previously` three times, and `formerly`, `originally`, and `at first` never. The one term that would have caught the case a review caught by hand is `now`, which appears 57 times across 24 entries in correct present-tense prose. A list including it reports 57 lines to catch one, and a list excluding it reports nothing.
|
|
71
|
-
|
|
72
|
-
What it matches instead is a bullet doing three things at once: opening with a pronoun whose antecedent is the bullet above it, carrying a past-tense verb, and following another top-level bullet. All three are required. Eight bullets in the corpus open with a back-reference, and the verb set narrows those to one.
|
|
73
|
-
|
|
74
|
-
The pronoun is matched cased and anchored to the opening, since a mid-sentence `this` is a determiner rather than a reference back. The verb is matched uncased anywhere in the bullet, and rejected when a copula sits in front of it, since `is used to resolve the folder` is the passive of `use` rather than the past habitual the set means.
|
|
75
|
-
|
|
76
|
-
Both sets are published under `## Narration pronouns` and `## Narration verbs` in a governance rule and read at run time, so widening either costs a rule edit rather than a TypeScript change. The copula list stays in code, because it is English grammar rather than corpus vocabulary and a rule publishing two of three headings would be another absent state to carry. Discovery keys on the headings rather than the filename, because rules are numbered and a renumber would empty the sets while the check kept reporting clean. A run finding no rule that publishes both says it scanned nothing rather than reporting clean.
|
|
77
|
-
|
|
78
|
-
A blank line does not end the run. Markdown reads the bullets around one as a single loose list, so a walker that broke there would leave the shape reachable by anyone who spaced their bullets out. What ends a run is content that is neither a bullet nor indented under one, which is what keeps the first bullet under a heading from reading as a reply to the last bullet above it.
|
|
79
|
-
|
|
80
|
-
A fence answers that test for itself, because every scan here skips a fenced line before reaching it. An unindented fence ends the run, since CommonMark reads one at column zero as interrupting the list and the bullets around it are then two lists with no antecedent crossing between them. A fence indented under its bullet stays inside the item and leaves the run intact.
|
|
81
|
-
|
|
82
|
-
The opening delimiter decides that for the whole block rather than each line deciding for itself. A blank line inside an indented fence carries no indentation to read, and a content line may sit at column zero inside one because CommonMark strips the fence's own indent and nothing further. Reading either as unindented ends a run that should have continued, which costs findings rather than inventing them, so no corpus count moves when it is wrong.
|
|
83
|
-
|
|
84
|
-
Two fenced blocks with nothing between them are one contiguous run of fenced lines, so the mark alone cannot say where the first ends. The line walker reports which block each line sits in, and the boundary re-reads indentation whenever that number changes, so an unindented block written directly behind an indented one ends the run rather than inheriting the answer above it. No markdown file this repository tracks holds that shape, because a formatter inserts a blank line between two fences on contact, and a target running these commands over an unformatted tree still can.
|
|
85
|
-
|
|
86
|
-
Precision is the whole value, so recall is the accepted exposure, and two shapes are knowingly out of reach. A narration written as one bullet carrying its own before and after slips through, and nothing else sees it either. So does the perfect passive, since `has been superseded` narrates a supersession and the copula guard rejects it with the passives it exists for.
|
|
87
|
-
|
|
88
|
-
A rejected alternative is a back-reference in the past tense by construction, and the standard keeps what was tried and why it lost, so a legitimate hit exists and no measure separates it from a violation. The report states that on every run, which is why the finding names a line to read rather than a line to delete.
|
|
89
|
-
|
|
90
|
-
The JSON record carries the findings per entry as `entries[].narration` and the sets as `checkpoints.narration`, which is absent under `--citations-only` where the run never loads them and null where no rule publishes both.
|
|
91
|
-
|
|
92
66
|
## The architecture record
|
|
93
67
|
|
|
94
68
|
Four findings read `canon/ARCHITECTURE.md` rather than a folder, and only the first two are facts.
|
|
@@ -127,9 +101,9 @@ All three wireframe findings are printed under a bare run. The states-mismatch f
|
|
|
127
101
|
|
|
128
102
|
## Which folders each check reaches
|
|
129
103
|
|
|
130
|
-
The provenance
|
|
104
|
+
The provenance check covers `canon/context/` alone, the reference-form check covers the split folders inside it, the required-section check covers `canon/context/` and `canon/wireframes/`, length and the table finding reach every audited folder, and the wireframe states check covers `canon/wireframes/` alone.
|
|
131
105
|
|
|
132
|
-
What narrows the
|
|
106
|
+
What narrows the provenance check 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. 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.
|
|
133
107
|
|
|
134
108
|
Length and the table finding generalize as judgments about how far a reader travels, so both reach wherever the audit is pointed. Required sections narrow for a plainer reason: each list is one standard's own, so it reaches the folder that standard governs. The context and wireframe standards each state a set, and the diagram standard states none.
|
|
135
109
|
|
|
@@ -41,7 +41,7 @@ Exit codes are `0` for a clean run, `1` for a refusal, and `2` for a gating find
|
|
|
41
41
|
|
|
42
42
|
`bun run check` in the toolkit repository reads both limits through its own Architecture record stage rather than through this verb, since the verb's only gating stage there runs `--citations-only` and never opens the record.
|
|
43
43
|
|
|
44
|
-
Entry length, reference form, table, provenance,
|
|
44
|
+
Entry length, reference form, table, provenance, 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.
|
|
45
45
|
|
|
46
46
|
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.
|
|
47
47
|
|
|
@@ -17,22 +17,26 @@ matched, or reported on, which is how project-authored rules survive. It also
|
|
|
17
17
|
removes a stale `.claude/GOV.md` from the retired build. Use
|
|
18
18
|
`canon gov install` to add rules.
|
|
19
19
|
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
a
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
20
|
+
Everything under `.claude/rules/canon/` belongs to the toolkit, so a rule
|
|
21
|
+
there that the toolkit no longer ships is deleted on sync, edited or not. That
|
|
22
|
+
is how a retired or renamed rule stops loading in a target. The sync lists each
|
|
23
|
+
deletion by path before it applies, and the target's git diff is the record
|
|
24
|
+
afterwards. `canon sync --check` lists the same file as `retired` before any
|
|
25
|
+
sync runs. A project's own rules belong under `.claude/rules/project/`, where
|
|
26
|
+
`canon standards rule` reserves `900-999` for them, and a rule placed under
|
|
27
|
+
`canon/` instead is lost on the next sync.
|
|
28
|
+
|
|
29
|
+
A sync never deletes a rule that a newer canon release installed. The stamp
|
|
30
|
+
records the newest release that synced governance, and an older binary holds
|
|
31
|
+
every rule it finds no source for, naming both releases and asking for an
|
|
32
|
+
upgrade, rather than deleting what it cannot recognize.
|
|
33
|
+
|
|
34
|
+
A renamed rule loses its old file and gains nothing under the new name unless
|
|
35
|
+
the target's stamp records the stack it installed, in which case the new name
|
|
36
|
+
shows as `missing` and `canon gov install <stack>` adds it.
|
|
37
|
+
|
|
38
|
+
Design's own orphans are the target's overrides and are meant to stay where
|
|
39
|
+
they are, so `canon design sync` deletes nothing it finds no source for.
|
|
36
40
|
|
|
37
41
|
`canon design install` copies one toolkit-owned file to
|
|
38
42
|
`.claude/design/base.css` and creates no override. A project overrides a value
|
|
@@ -160,7 +164,9 @@ matches what the toolkit installed, `customized` when the project edited it,
|
|
|
160
164
|
`stranded` when it sits at a path the toolkit no longer installs to, `orphaned`
|
|
161
165
|
when the project authored it, or `drifted` when no stamp covers it. Governance
|
|
162
166
|
also reports `missing`, for a rule the target's recorded stack lists that its
|
|
163
|
-
tree does not hold at all
|
|
167
|
+
tree does not hold at all, and `retired`, for a rule under
|
|
168
|
+
`.claude/rules/canon/` the toolkit no longer ships, which the next sync
|
|
169
|
+
deletes. A `retired` file counts toward `--exit-code`, since one sync clears it.
|
|
164
170
|
|
|
165
171
|
Use `--json` for the machine-readable report and `--exit-code` to fail a CI job. Orphaned
|
|
166
172
|
and missing files are both excluded from that exit code: a project-authored
|
package/docs/target-projects.md
CHANGED
|
@@ -118,7 +118,7 @@ The plugin corpus carries runtime behavior rather than reference prose alone, be
|
|
|
118
118
|
When a new need appears after scaffold, install the one domain without re-running `canon init`.
|
|
119
119
|
|
|
120
120
|
- Governance rule for a newly adopted library: invoke `canon:target-setup gov`, or run `canon gov install <stack> --add <rule> <path>`
|
|
121
|
-
- 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.
|
|
121
|
+
- Project-specific rule the toolkit does not ship: invoke `canon:create-rule`. It scaffolds a rule into `.claude/rules/project/` with a non-colliding number, and `canon gov sync` leaves it untouched. A rule placed under `.claude/rules/canon/` instead is deleted on the next sync, since that folder belongs to the toolkit.
|
|
122
122
|
- Index.md system for a markdown-heavy folder that emerged: invoke `canon:target-setup indexes`
|
|
123
123
|
|
|
124
124
|
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.
|
|
@@ -225,7 +225,7 @@ The report opens by naming the binary running it. The installed version reads ag
|
|
|
225
225
|
|
|
226
226
|
#### Then the causes
|
|
227
227
|
|
|
228
|
-
A `stale` file still matches what the toolkit installed, so the update is mechanical. A `customized` file carries local edits, so taking the upstream version is a decision and `canon:seed-sync` is the tool for it. A `stranded` file sits where an older toolkit installed it and the toolkit has since moved, which is a relocation the report names but no command runs.
|
|
228
|
+
A `stale` file still matches what the toolkit installed, so the update is mechanical. A `customized` file carries local edits, so taking the upstream version is a decision and `canon:seed-sync` is the tool for it. A `stranded` file sits where an older toolkit installed it and the toolkit has since moved, which is a relocation the report names but no command runs. A `retired` rule is one under `.claude/rules/canon/` the toolkit no longer ships, and the next `canon gov sync` deletes it.
|
|
229
229
|
|
|
230
230
|
That attribution comes from `canon/config/config.json`, which every install and sync now writes, falling back to `.claude/canon/config.json` for a target stamped before that move. A target stamped before that path shipped is read from the retired `.claude/canon.json` instead, reported rather than migrated. Governance records a hash per installed file, plus the stack `canon gov install` was given, and tooling records the stack chain it resolved instead of any file hash, since its install runs no per-file walk to attribute.
|
|
231
231
|
|
|
@@ -263,4 +263,4 @@ port-collision detail.
|
|
|
263
263
|
|
|
264
264
|
- [Claude Code and git worktrees](../../wiki/claude/claude-worktrees.md) for the isolation and fan-out mechanics
|
|
265
265
|
- [Claude Code subagents](../../wiki/claude/claude-subagents.md) for in-session parallelism without worktrees
|
|
266
|
-
- `canon/context/claude-plugin/skill-strategy.md` for how the skills in the loop are categorized
|
|
266
|
+
- `canon/context/claude-plugin/skill-strategy/overview.md` for how the skills in the loop are categorized
|
|
@@ -150,7 +150,7 @@ Resist over-tiering early. Moving up is cheap because tiers stack. Moving down m
|
|
|
150
150
|
## References
|
|
151
151
|
|
|
152
152
|
- [Claude Design](../../wiki/claude/claude-design.md): first-party hosted design product and handoff bundle
|
|
153
|
-
- `canon/context/claude-plugin/skill-strategy.md`: how to decide between workflow and domain-knowledge skills
|
|
153
|
+
- `canon/context/claude-plugin/skill-strategy/overview.md`: how to decide between workflow and domain-knowledge skills
|
|
154
154
|
- [`microsoft/playwright-mcp`](https://github.com/microsoft/playwright-mcp): browser automation MCP used in tier 1 and tier 2
|
|
155
155
|
- [`ChromeDevTools/chrome-devtools-mcp`](https://github.com/ChromeDevTools/chrome-devtools-mcp): live frontend debugging MCP used in tier 1 and tier 2
|
|
156
156
|
- [`yctimlin/mcp_excalidraw`](https://github.com/yctimlin/mcp_excalidraw): community MCP server behind the tier 1 wireframe companion
|
|
@@ -12,18 +12,6 @@ paths:
|
|
|
12
12
|
- Before non-trivial work in a domain, read its `canon/context/<domain>.md` entry. Use `canon/context/index.md` to find it.
|
|
13
13
|
- Leave the entry conforming when work in its domain changes what it describes.
|
|
14
14
|
|
|
15
|
-
## Narration pronouns
|
|
16
|
-
|
|
17
|
-
Do not open a bullet with one of these where the antecedent is the bullet above it.
|
|
18
|
-
|
|
19
|
-
- `It`, `That`, `This`, `These`, `Those`, `They`
|
|
20
|
-
|
|
21
|
-
## Narration verbs
|
|
22
|
-
|
|
23
|
-
Do not put a sibling bullet's design in the past with one of these.
|
|
24
|
-
|
|
25
|
-
- `was`, `were`, `became`, `replaced`, `superseded`, `used to`
|
|
26
|
-
|
|
27
15
|
## Authority
|
|
28
16
|
|
|
29
17
|
- Follow the context standard for entry shape: frontmatter, sections, length, and what goes in. It is the single source. Read it with `canon standards context`.
|
|
@@ -13,8 +13,7 @@ description: Handle judgment calls, scope discipline, and file-editing mechanics
|
|
|
13
13
|
- When facing a judgment call with 2-3 reasonable options mid-flow, pick one and state the tradeoff in one sentence. Enumerate options only when the user's preference is the deciding factor.
|
|
14
14
|
- Put a call the user's preference decides through the structured question surface, such as `AskUserQuestion` in Claude Code, and fall back to a numbered list in one message where none exists. Rank the recommendation first and mark it, order the rest behind it, and give each option its cost, since an option with no stated cost is picked blind.
|
|
15
15
|
- Author the real choices only. A structured surface appends its own trailing escapes for a free-text answer and for reopening the question as conversation, so never write either as an option. On the numbered-list fallback, say that answering outside the list is fine.
|
|
16
|
-
- Answer from the artifact when one already put the question in writing with a suggestion, rather than re-asking it.
|
|
17
|
-
- Rewrite the `- Suggested:` line rather than the blank `- Answer:` slot when execution decides against an unanswered plan question's suggestion, per the plan standard, which your toolkit resolves by name.
|
|
16
|
+
- Answer from the artifact when one already put the question in writing with a suggestion, rather than re-asking it.
|
|
18
17
|
|
|
19
18
|
## Scope discipline
|
|
20
19
|
|
|
@@ -11,9 +11,7 @@ description: Report file paths correctly for the reading surface and group them
|
|
|
11
11
|
- When it reads `claude-desktop`, emit each path as a markdown link carrying the path as its text and an absolute `file://` URI as its target, resolving a relative path against the main project root to build that target. The desktop file tree hides dotted folders, so a bare path into one names a file the reader cannot reach.
|
|
12
12
|
- On every other value, including unset, emit the path bare. A terminal emulator makes it clickable through its own path detection, and link markup defeats that.
|
|
13
13
|
- Both forms govern a path emitted in a response. A path written into a markdown file follows the markdown standard instead, which your toolkit resolves by name, and which backticks a file reference and never repeats it as a link label.
|
|
14
|
-
-
|
|
15
|
-
- In the main worktree: relative from `pwd` works because `pwd` equals the editor root.
|
|
16
|
-
- In a linked worktree (under `.claude/worktrees/<name>/`): use absolute paths. Relative paths from worktree `pwd` would not resolve against the editor's project root. A `PostToolUse` hook computes this form after each write and hands it back as additional context where it is installed. Prefer that form when it arrives, and fall back to computing the absolute path yourself when it does not.
|
|
14
|
+
- In a linked worktree (under `.claude/worktrees/<name>/`), emit the absolute path, since the editor is rooted at the main project root and a path relative to the worktree resolves nowhere there. Prefer the form a `PostToolUse` hook hands back after a write where one is installed.
|
|
17
15
|
|
|
18
16
|
## Grouping multiple files
|
|
19
17
|
|
|
@@ -6,8 +6,6 @@ description: Scope, size, and link a task file correctly
|
|
|
6
6
|
|
|
7
7
|
## Task files
|
|
8
8
|
|
|
9
|
-
- `.canon/tasks/` is gitignored local session scratch, one file per task. Edit freely. No staging or revert before commits.
|
|
10
9
|
- Only create a task for work that spans multiple sessions or has real dependencies. Handle small edits immediately without a task entry.
|
|
11
10
|
- Do not add tasks retroactively for work already completed. Completed work is visible in git.
|
|
12
|
-
- When a task needs execution detail beyond its own file,
|
|
13
|
-
- Write the plan in the same session as the task file. The session that executes the plan later inherits reasoning context it would otherwise have to re-derive.
|
|
11
|
+
- When a task needs execution detail beyond its own file, write a plan in `.canon/plans/` in the same session as the task and link to it from the task's intro paragraph. The session that executes the plan later inherits reasoning context it would otherwise have to re-derive.
|
|
@@ -9,4 +9,3 @@ description: Keep memory writes scoped to .canon/memory/ and out of context-owne
|
|
|
9
9
|
- Write all memory files to `.canon/memory/`, not `~/.claude/projects/`
|
|
10
10
|
- A fact about a domain goes to that domain's `canon/context/` entry, not to memory. `canon:memory-capture` routes it there and `canon:docs-fold` folds it in. Memory keeps only what no context entry owns. Report it rather than proceeding silently when either skill does not resolve. Both ship with the plugin and this rule ships with the CLI, so a project that installed governance alone does not have them.
|
|
11
11
|
- Never delete a memory entry. Retire one by moving it to `.canon/memory/archive/`, which `canon records push` backs. A bulk retire runs through the shell, where no file edit fires a path-scoped rule.
|
|
12
|
-
- Follow the memory standard for the filename and type prefix, the frontmatter, the body shape each type carries, and the lifecycle. Read it with `canon standards memory`. Check every entry in the pen against that standard and fix what breaks it, since nothing keeps the folder conforming on its own.
|
|
@@ -6,7 +6,5 @@ description: Write temporary files to the scratch folder structure
|
|
|
6
6
|
|
|
7
7
|
## Temporary files
|
|
8
8
|
|
|
9
|
-
- Write temporary files to `.canon/tmp/<slug>/<file>.md`
|
|
10
|
-
- Write to `.claude/.tmp/<slug>/` instead in a project that carries no `.canon/` root,
|
|
11
|
-
- "The project root" above means the current worktree by default. `085-worktrees.md` states the same mixed default for `.canon/tmp/` and defers to each skill's own body for which write resolves at the main root instead.
|
|
12
|
-
- `runs/`, `hooks/`, `handoff/`, `pr/`, and `render/` are reserved under `tmp/` for build and command output that can be regenerated, hook state, skill-to-skill handoff, pull request scratch, and render output. A session slug must not take one of these five names.
|
|
9
|
+
- Write temporary files to `.canon/tmp/<slug>/<file>.md` at the current worktree's root, a nested folder with a kebab-slug tied to the topic rather than a flat `<slug>-<file>.md`. The slug must not take one of the five reserved names `runs`, `hooks`, `handoff`, `pr`, and `render`. A skill that resolves a write at the main root instead states so in its own body.
|
|
10
|
+
- Write to `.claude/.tmp/<slug>/` instead in a project that carries no `.canon/` root, and `canon migrate records` moves it to the first spelling. <!-- canon-keep-record-root -->
|
|
@@ -6,14 +6,11 @@ description: Enforce planning standards before implementation
|
|
|
6
6
|
|
|
7
7
|
## Planning
|
|
8
8
|
|
|
9
|
-
-
|
|
9
|
+
- Confirm a numbered implementation plan before a change whose diff cannot be described in one sentence.
|
|
10
10
|
- Challenge ambiguous or over-engineered requests before implementation.
|
|
11
11
|
- Search the project, its dependencies, and the standard library for an existing implementation before writing new code.
|
|
12
12
|
- State where the search ran and why each candidate was rejected. Do not assert a search without naming its results.
|
|
13
13
|
- Propose the simplest solution that satisfies the requirement before implementing complex patterns.
|
|
14
14
|
- Write or update tests as part of every implementation plan.
|
|
15
15
|
- Write the test for a behavior before the code that implements it. Confirm visual output after implementing it, not before.
|
|
16
|
-
- Load the `canon:test-first` skill before writing the implementation for a behavior whose test does not exist yet, and report it rather than proceeding silently when the skill does not resolve.
|
|
17
16
|
- Run `canon gov test-order` before shipping a branch. Fix what it names as reaching history ahead of its test.
|
|
18
|
-
- Load the `canon:systematic-debugging` skill before proposing a fix for a failing test, a surfaced bug, or behavior nobody has explained yet, and report it rather than proceeding silently when the skill does not resolve.
|
|
19
|
-
- Do not modify code without a confirmed plan.
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: Route every git operation through the canon git skills,
|
|
2
|
+
description: Route every git operation through the canon git skills, which choose the surface and never authorize the operation
|
|
3
3
|
---
|
|
4
4
|
|
|
5
5
|
# Git standards
|
|
@@ -12,4 +12,4 @@ description: Route every git operation through the canon git skills, and run one
|
|
|
12
12
|
|
|
13
13
|
## Whether to act
|
|
14
14
|
|
|
15
|
-
-
|
|
15
|
+
- The bullets above decide which surface performs an operation already decided, never whether to take one.
|
|
@@ -11,19 +11,4 @@ paths:
|
|
|
11
11
|
## Authority
|
|
12
12
|
|
|
13
13
|
- Load the `canon:design-taste` skill for which design decision settles first, what must stay constant across a surface, and the defaults to reach past. It is the single source for all three.
|
|
14
|
-
- Load it before drafting, not after revising. A revision recovers a color and never recovers the composition a draft already settled.
|
|
15
14
|
- Report it rather than proceeding silently when the skill does not resolve. It ships with the plugin and this rule ships with the CLI, so a project that installed governance alone does not have it.
|
|
16
|
-
- Do not work the layer ordering or the coherence locks from memory.
|
|
17
|
-
|
|
18
|
-
## When this fires and when it does not
|
|
19
|
-
|
|
20
|
-
- This rule scopes to the files where an undecided visual choice lands, which is the stylesheet and the design document. Building a surface somebody already decided is implementation rather than design, and the rules below carry what implementation owes.
|
|
21
|
-
- Load the skill by name when a component edit makes a visual choice nobody has taken yet, such as a new section's shape, a spacing relationship, or a radius. The glob cannot see that intent and no glob can.
|
|
22
|
-
- Do not load it to ship a decided design. A worker wiring a picked composition pays the read and gets nothing back.
|
|
23
|
-
|
|
24
|
-
## Boundaries
|
|
25
|
-
|
|
26
|
-
- Accessibility, keyboard interaction and ARIA are a separate topic. `410-a11y` routes them, on every rendered path.
|
|
27
|
-
- States, empty and loading coverage, and destructive confirmation are a separate topic. `430-ux-completeness` routes them.
|
|
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
|
-
- The floor those three carry is not restated in the skill, and it is not traded against a preference where the two collide.
|