@erclx/canon 4.117.0 → 4.119.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/claude/.claude-plugin/plugin.json +1 -1
  2. package/claude/skills/canon-operator/SKILL.md +1 -1
  3. package/claude/skills/canon-rollout/SKILL.md +2 -2
  4. package/claude/skills/design-extract/SKILL.md +1 -1
  5. package/claude/skills/docs-fold/SKILL.md +2 -2
  6. package/claude/skills/draft-ready/REQUIREMENT.md +1 -1
  7. package/claude/skills/draft-ready/SKILL.md +1 -1
  8. package/claude/skills/draft-ready/references/assembly.md +8 -0
  9. package/claude/skills/draft-screencast/SKILL.md +1 -1
  10. package/claude/skills/git-pr/SKILL.md +5 -3
  11. package/claude/skills/memory-capture/SKILL.md +3 -3
  12. package/claude/skills/memory-review/SKILL.md +3 -3
  13. package/claude/skills/plan-feature/REQUIREMENT.md +1 -0
  14. package/claude/skills/plan-feature/SKILL.md +8 -1
  15. package/claude/skills/review-branch/SKILL.md +1 -1
  16. package/claude/skills/review-pr/REQUIREMENT.md +1 -0
  17. package/claude/skills/review-pr/SKILL.md +4 -2
  18. package/claude/skills/role-planner/SKILL.md +1 -1
  19. package/claude/skills/role-worker/REQUIREMENT.md +1 -1
  20. package/claude/skills/role-worker/SKILL.md +10 -41
  21. package/claude/skills/seed-sync/SKILL.md +1 -1
  22. package/claude/skills/session-compact/SKILL.md +1 -1
  23. package/claude/skills/session-map/SKILL.md +1 -1
  24. package/claude/skills/session-relay/REQUIREMENT.md +7 -1
  25. package/claude/skills/session-relay/SKILL.md +4 -7
  26. package/claude/skills/session-worktree/REQUIREMENT.md +5 -1
  27. package/claude/skills/session-worktree/SKILL.md +7 -1
  28. package/claude/skills/session-worktree/references/main-root-writes.md +24 -0
  29. package/claude/skills/target-check/references/domains.md +1 -1
  30. package/claude/skills/task-board/SKILL.md +4 -3
  31. package/claude/skills/teach-workspace/SKILL.md +4 -4
  32. package/claude/skills/ui-checklist/SKILL.md +1 -1
  33. package/claude/skills/ux-audit/SKILL.md +1 -1
  34. package/claude/skills/ux-measure/SKILL.md +1 -1
  35. package/claude/skills/ux-walkthrough/references/relay.md +1 -1
  36. package/docs/agents/commands.md +3 -3
  37. package/docs/agents/context-audit-checks.md +2 -28
  38. package/docs/agents/context-audit.md +1 -1
  39. package/docs/agents/install-and-sync.md +28 -17
  40. package/docs/agents/tasks.md +4 -4
  41. package/docs/target-projects.md +2 -2
  42. package/docs/workflow/ai-workflow.md +9 -9
  43. package/docs/workflow/operating-model.md +1 -1
  44. package/docs/workflow/visual-design-workflow.md +2 -2
  45. package/governance/renames.toml +13 -0
  46. package/governance/rules/claude/510-context.md +0 -12
  47. package/governance/rules/core/005-behavior.md +1 -2
  48. package/governance/rules/core/015-output.md +1 -3
  49. package/governance/rules/core/035-tasks.md +1 -3
  50. package/governance/rules/core/045-memory.md +0 -1
  51. package/governance/rules/core/055-scratch.md +2 -4
  52. package/governance/rules/core/070-planning.md +1 -4
  53. package/governance/rules/core/085-worktrees.md +2 -8
  54. package/governance/rules/core/087-git.md +2 -2
  55. package/governance/rules/core/090-code-comments.md +1 -1
  56. package/governance/rules/ui/460-design-taste.md +0 -15
  57. package/package.json +1 -1
  58. package/src/claude/cases/workflow.ts +10 -0
  59. package/src/commands/context.ts +11 -111
  60. package/src/commands/sync.ts +11 -3
  61. package/src/commands/tasks.ts +9 -8
  62. package/src/context/audit.ts +3 -145
  63. package/src/design/base.css +19 -19
  64. package/src/design/board.ts +18 -7
  65. package/src/design/neutral.ts +127 -0
  66. package/src/design/regen.ts +6 -4
  67. package/src/design/tokens.ts +5 -2
  68. package/src/gate/measures.ts +37 -0
  69. package/src/gate/stages.ts +13 -4
  70. package/src/gov/adapter.ts +59 -7
  71. package/src/gov/install.ts +13 -3
  72. package/src/gov/renames.ts +76 -0
  73. package/src/gov/stacks.ts +5 -1
  74. package/src/records/validate.ts +5 -1
  75. package/src/sync/check.ts +25 -4
  76. package/src/sync/engine.ts +154 -10
  77. package/src/sync/stamp.ts +44 -0
  78. package/src/tasks/archive.ts +28 -7
  79. package/src/tasks/record.ts +16 -9
  80. package/src/tasks/validate.ts +3 -1
  81. package/standards/plan.md +24 -1
  82. package/standards/tasks.md +5 -3
  83. package/governance/rules/core/091-channel.md +0 -13
  84. package/src/context/narration.ts +0 -99
@@ -12,7 +12,7 @@ Read `${CLAUDE_SKILL_DIR}/../../standards/tasks.md` before writing any file. It
12
12
  ## Guards
13
13
 
14
14
  - Resolve the board at the main worktree root, not `pwd`. Run `git worktree list --porcelain | grep -m 1 '^worktree ' | cut -d' ' -f2-`, falling back to `pwd` outside a git repo. Every read and write below resolves against that root. The board is gitignored scratch shared across worktrees, so a linked worktree writing to its own `pwd` creates a second board nothing else reads.
15
- - From a linked worktree the file-editing tools refuse that root, so a new task file goes out through `Bash` as a plain single command carrying a heredoc. Archiving already runs through `canon tasks archive`, which resolves the root in-process. Marking an outcome shipped is `docs-fold` and runs through `canon tasks outcome`. Resolve that root the way `session-worktree` does.
15
+ - A new task file is a main-root write, so it goes out as a heredoc. Archiving already runs through `canon tasks archive`, which resolves the root in-process. Marking an outcome shipped is `docs-fold` and runs through `canon tasks outcome`. Resolve that root and route the write the way `session-worktree` states.
16
16
  - If `.canon/tasks/` does not exist at that root, stop: `❌ No .canon/tasks/ board. Run canon claude init to set it up.`
17
17
  - Route on the request rather than on a flag. Creating names work that does not exist yet, archiving names a task file already shipped, and declining names one decided against. If the request fits none of the three, stop: `❌ Ambiguous. Say whether to create a task, archive one, or decline one.`
18
18
  - Never hand-edit `.canon/tasks/index.md`. A hook regenerates it from sibling frontmatter after a write. Do not run the regen command directly, except after a shell write from a linked worktree: the hook matches `Write|Edit|MultiEdit` and nothing fires on `Bash`, so that one case regenerates explicitly with `canon indexes regen --no-stage --root <main-root> <main-root>/.canon/tasks/index.md`.
@@ -53,7 +53,7 @@ Check the roster for a live orchestrator before writing either file. Read `canon
53
53
 
54
54
  - **Found.** Do not write `priority.md` or `backlog.md`. Report the surface the row would take and the reason worked out above, then hand off by messaging that session with the same information so it places the row itself rather than two sessions writing the board at once.
55
55
  - **Not found, and this session's own name (already read above) starts with `worker-` or `planner-`.** Do not write either file. Those two role bodies ban a board write with no exception, and an orchestrator absent from the roster is not consent to break it. Report the row and the surface it would take, so the operator or a later orchestrator places it.
56
- - **Not found otherwise, or the roster read fails.** Write the row directly, as today. A failed read is indistinguishable from a solo project holding no orchestrator, and stopping would strand the row on the one path this section otherwise keeps unconditional. From a linked worktree the file-editing tools refuse the main root, so the row lands through the same `Bash` route the file itself took.
56
+ - **Not found otherwise, or the roster read fails.** Write the row directly, as today. A failed read is indistinguishable from a solo project holding no orchestrator, and stopping would strand the row on the one path this section otherwise keeps unconditional. The row is a main-root write too, so it lands through the same heredoc route the file itself took.
57
57
 
58
58
  Say which branch fired and why in the report. The call is a judgment restated on every sweep rather than a property of the task, and a placement with no stated reason is one the next sweep re-derives from nothing.
59
59
 
@@ -98,7 +98,7 @@ git fetch origin main --quiet && git log origin/main --oneline -20
98
98
 
99
99
  Match the shipped outcomes against that log, widening to `gh pr list --state merged --limit 20` when a remote is configured and the log does not settle it. When the work is not on `main`, name the task and stop: `❌ Work not on main. Archiving now loses the task if the pull request is abandoned.`
100
100
 
101
- The board is gitignored, so an archived task has no history behind it and nothing restores one archived early. Skip this check when the task carries a `Pull request:` line and that pull request is merged, since the number already proves what the log is being read for.
101
+ The board is gitignored, so an archived task has no history behind it and nothing restores one archived early. Skip this check when the task carries a `Pull request:` line and the last number it lists is merged, since the number already proves what the log is being read for.
102
102
 
103
103
  ### Step 2: run the archive
104
104
 
@@ -118,6 +118,7 @@ Each reason has one resolution and none of them is to archive around it:
118
118
 
119
119
  - `open-outcomes`: the named outcomes are unmarked or genuinely open. Run `docs-fold` when the work shipped and nothing marked it. Leave the task on the board when the outcome is real. When the work is being abandoned, cut it by striking the body, `- ~~<outcome>~~ <why>`, whatever the checkbox holds, so the board records what was dropped rather than meeting this refusal a second time.
120
120
  - `ambiguous`: two tasks name one pull request, which is the misfile `${CLAUDE_SKILL_DIR}/../../standards/tasks.md` rules out. Resolve the citation by hand, since no sweep repairs it.
121
+ - `earlier-slice`: the number is listed on the task but is not the last, so a later slice is still to merge. Leave the task on the board. Its last slice's merge archives it.
121
122
  - `no-match`: the stem or number names nothing on the board. Check the name against the listed stems.
122
123
  - `bad-input`: the command line was wrong rather than the board. Read the message, fix the arguments, and run it again. Nothing on the board needs repair, which is what separates this from the two above.
123
124
 
@@ -32,10 +32,10 @@ canon teach list --json
32
32
 
33
33
  It reports every workspace with its path, its counts, and the ordinal a new one would take. A `no-teach` refusal means the project has opened none yet, which is the new-workspace path in Step 1 rather than a reason to stop. The open verb creates the folder.
34
34
 
35
- From a linked worktree the file-editing tools refuse every path under the main root and offer a worktree copy instead, which is a second file no later session reads. Never take that redirect. The route splits by what the write does to the file:
35
+ Every path under the main root is a main-root write, routed the way `session-worktree` states. The route splits by what the write does to the file:
36
36
 
37
- - Creating a whole file that does not exist yet, which is a lesson, a reference page, and a learning record, goes out as one plain shell command carrying a heredoc
38
- - Changing a line inside a file that already exists goes through the verb that owns it, since the stream editors are banned and no other shell route reaches it
37
+ - Creating a whole file that does not exist yet, which is a lesson, a reference page, and a learning record, goes out as a heredoc
38
+ - Changing a line inside a file that already exists goes through the verb that owns it
39
39
 
40
40
  ## Step 1: open or resume
41
41
 
@@ -239,7 +239,7 @@ Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. Fall back to
239
239
 
240
240
  The handoff is its own file rather than a shared one. The routed-facts file another skill writes is deleted by whichever pass folds it, so a second producer's unread work goes with it, and a sibling path costs the folding skill one more read and removes the interaction.
241
241
 
242
- An append is a whole-file operation, so send it as a plain single `Bash` command carrying a heredoc, per Step 0. Then tell the operator that `/docs-fold` folds the file in from a branch. The proposal costs nothing tracked and runs anywhere, while the page it describes is a tracked file, so the fold is a worktree operation and the workspace it came from is not.
242
+ An append is a whole-file operation, so send it as a heredoc, per Step 0. Then tell the operator that `/docs-fold` folds the file in from a branch. The proposal costs nothing tracked and runs anywhere, while the page it describes is a tracked file, so the fold is a worktree operation and the workspace it came from is not.
243
243
 
244
244
  ## Output
245
245
 
@@ -72,7 +72,7 @@ When a checklist is produced, write it directly to `.canon/tmp/handoff/ui-checkl
72
72
 
73
73
  The path names the artifact rather than this skill, so it does not move when the skill is renamed. A checklist written by an older binary still lands where the consumer looks.
74
74
 
75
- From a linked worktree the file-editing tools refuse that path, so the checklist goes out through `Bash`. Send the `mkdir -p` and the heredoc as two plain commands rather than joining them with `&&`, which is refused as compound.
75
+ The checklist is a main-root write, so it goes out as a heredoc, routed the way `session-worktree` states.
76
76
 
77
77
  Skip the file write when there is nothing to verify visually and nothing shipping untested.
78
78
 
@@ -64,7 +64,7 @@ Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. Fall back to
64
64
 
65
65
  Write the full report directly to `.canon/review/ux-audit-<slug>.md` at the main worktree root, not the current worktree. Resolve that root the way `session-worktree` does. Create the directory if it does not exist. Always overwrite.
66
66
 
67
- From a linked worktree the file-editing tools refuse that path, so the report goes out through `Bash`. Send the `mkdir -p` and the heredoc as two plain commands rather than joining them with `&&`, which is refused as compound.
67
+ The report is a main-root write, so it goes out as a heredoc, routed the way `session-worktree` states.
68
68
 
69
69
  If there are no observations, write `✅ No observations.` to the file with a timestamp.
70
70
 
@@ -108,7 +108,7 @@ Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. Fall back to
108
108
 
109
109
  Write the full reading directly to `.canon/review/ux-measure-<slug>.md` at the main worktree root, not the current worktree. Resolve that root the way `session-worktree` does. Create the directory if it does not exist. Always overwrite.
110
110
 
111
- From a linked worktree the file-editing tools refuse that path, so the reading goes out through `Bash`. Send the `mkdir -p` and the heredoc as two plain commands rather than joining them with `&&`, which is refused as compound.
111
+ The reading is a main-root write, so it goes out as a heredoc, routed the way `session-worktree` states.
112
112
 
113
113
  The `.canon/review/` directory is gitignored. Do not stage or commit the file.
114
114
 
@@ -4,7 +4,7 @@ Read when the operator calls a batch, and at the start of the walkthrough when a
4
4
 
5
5
  ## Where the batch goes
6
6
 
7
- - Send it to the controller where the session was dispatched by one, resolved per the Channel rule, matched by name through `canon gov list --rules --json` rather than a path a target may not have installed.
7
+ - Send it to the controller where the session was dispatched by one, through `canon:session-relay`, which resolves the address and carries the send.
8
8
  - Give it to the operator as one list in the conversation where no controller exists. The walkthrough file is the handoff either way.
9
9
 
10
10
  ## When
@@ -23,10 +23,10 @@ Full help: `canon <command> --help`. Bare `canon --help` lists every top-level c
23
23
  | `canon indexes list [path]` | Flatten every folder index under a path into one `{path, title, description}` catalog (`--json`) |
24
24
  | `canon docs [topic]` | Emit toolkit reference docs (`list`, or a topic by name) |
25
25
  | `canon design render` | Render `canon/DESIGN.md` tokens to HTML and CSS, declaring each vendored face the typography table names with `--embed-fonts` |
26
- | `canon design regen` | Rewrite this repository's `canon/DESIGN.md` and `src/design/base.css` from `src/design/tokens.ts` |
26
+ | `canon design regen` | Rewrite this repository's `canon/DESIGN.md` from `src/design/tokens.ts` and `src/design/base.css` from `src/design/neutral.ts` |
27
27
  | `canon design board` | Generate a static page set indexing tokens, surfaces, wireframes, past candidates, components, and references against a caller-resolved `--root` (`--out`), defaulting to the main worktree |
28
28
  | `canon design css` | Emit the design tokens and components as CSS on stdout (`--no-components` for properties alone) |
29
- | `canon design install` | Install the base stylesheet into a project at `.claude/design/base.css` |
29
+ | `canon design install` | Install the neutral base stylesheet into a project at `.claude/design/base.css` |
30
30
  | `canon design sync` | Update a base stylesheet already installed under `.claude/design/` |
31
31
  | `canon slides render` | Render a `.claude/SLIDES.md` source into a PowerPoint deck, reporting any unrecognized layout name on stderr |
32
32
  | `canon slides list` | List the available slide layouts (`--json` for the catalog) |
@@ -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, superseded-decision narration, index drift, the architecture record against its own ceiling and entry cap and its word weight, and wireframe states against their evidence folders |
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 and narration checks cover `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.
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 first two 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.
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, 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.
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,29 @@ 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
- A rule under `.claude/rules/canon/` that the toolkit finds no source for is
21
- reported orphaned with no destination offered. The toolkit cannot tell a rule
22
- a project dropped there from one it shipped and later renamed, and a
23
- destination nested inside `canon/` would be wrong for the first case
24
- regardless, since that folder is replaced wholesale on sync.
25
-
26
- Nothing is moved either way, because a rule's installed path is one the
27
- project's own rules, skills, and docs may cite. `canon standards rule` carries
28
- the reserved number bands behind the three-way split, where `900-999` under
29
- `.claude/rules/project/` is what a project-authored rule takes and everything
30
- under `.claude/rules/canon/` belongs to the toolkit.
31
-
32
- `canon sync --check` does not report an orphaned entry. It skips every one, so
33
- the destination reaches `canon gov sync` alone among the two per-file domain
34
- syncs, since design's own orphans are the target's overrides and are meant to
35
- stay where they are.
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 rule stops loading in a target. A renamed or renumbered rule
23
+ the toolkit declares in `governance/renames.toml` moves instead: the sync
24
+ installs the rule under its new name and deletes the old file, whether or not
25
+ the target's stamp records a stack. Local edits to the old file are not
26
+ carried, and the sync says so. The sync lists each change by path before it
27
+ applies, and the target's git diff is the record afterwards. `canon sync
28
+ --check` lists the same file as `retired` or `renamed` before any sync runs. A project's own rules belong under `.claude/rules/project/`, where
29
+ `canon standards rule` reserves `900-999` for them, and a rule placed under
30
+ `canon/` instead is lost on the next sync.
31
+
32
+ A sync never deletes a rule that a newer canon release installed. The stamp
33
+ records the newest release that synced governance, and an older binary holds
34
+ every rule it finds no source for, naming both releases and asking for an
35
+ upgrade, rather than deleting what it cannot recognize.
36
+
37
+ A renamed rule loses its old file and gains nothing under the new name unless
38
+ the target's stamp records the stack it installed, in which case the new name
39
+ shows as `missing` and `canon gov install <stack>` adds it.
40
+
41
+ Design's own orphans are the target's overrides and are meant to stay where
42
+ they are, so `canon design sync` deletes nothing it finds no source for.
36
43
 
37
44
  `canon design install` copies one toolkit-owned file to
38
45
  `.claude/design/base.css` and creates no override. A project overrides a value
@@ -160,7 +167,11 @@ matches what the toolkit installed, `customized` when the project edited it,
160
167
  `stranded` when it sits at a path the toolkit no longer installs to, `orphaned`
161
168
  when the project authored it, or `drifted` when no stamp covers it. Governance
162
169
  also reports `missing`, for a rule the target's recorded stack lists that its
163
- tree does not hold at all.
170
+ tree does not hold at all, `retired`, for a rule under
171
+ `.claude/rules/canon/` the toolkit no longer ships, which the next sync
172
+ deletes, and `renamed`, for one the toolkit ships under a new name, which the
173
+ next sync moves. A `retired` or `renamed` file counts toward `--exit-code`,
174
+ since one sync clears it.
164
175
 
165
176
  Use `--json` for the machine-readable report and `--exit-code` to fail a CI job. Orphaned
166
177
  and missing files are both excluded from that exit code: a project-authored
@@ -50,7 +50,7 @@ canon tasks archive --pull-request 673 --json
50
50
  | `--json` | Emit a machine-readable record on stdout |
51
51
  | `--root <path>` | Board root, defaulting to the main worktree |
52
52
 
53
- Exit codes: `0` archived, `1` refused. Every gate is a refusal rather than a warning, because `.husky/post-merge` calls this with nobody watching. The `reason` field carries which gate fired: `no-board`, `no-match`, `ambiguous`, `no-outcomes`, `open-outcomes`, or `bad-input`.
53
+ Exit codes: `0` archived, `1` refused. Every gate is a refusal rather than a warning, because `.husky/post-merge` calls this with nobody watching. The `reason` field carries which gate fired: `no-board`, `no-match`, `ambiguous`, `no-outcomes`, `open-outcomes`, `earlier-slice`, or `bad-input`. `earlier-slice` fires when `--pull-request` names a number that is not the last on the task's `Pull request:` line, since outcomes are ticked at ship time and only the last slice's merge closes the task.
54
54
 
55
55
  An outcome whose body is struck reads as cut rather than open or closed, whatever its checkbox holds: `- ~~<outcome>~~ <why>`. A task carrying only cut outcomes archives, since the gate refuses `no-outcomes` only when both the closed and the cut counts are zero. The success record carries `closed` and `cut` as counts, so a reader tells a shipped task from an abandoned one without opening the file.
56
56
 
@@ -245,13 +245,13 @@ canon tasks plan-link v28.1-trigger-escalation .canon/plans/feature-dispatch-ans
245
245
 
246
246
  The plan resolves the same way `canon tasks plan-answers` resolves one, against the project root first and `.canon/tasks/` second, so a bare slug and a board-relative path both work. A reference resolving to no file refuses as `no-plan`, naming every base it looked under.
247
247
 
248
- The write mirrors `canon tasks pull-request`'s add/correct/unchanged shape, anchored on the H1 rather than on the last origin line, since `Plan:` is the first origin line a task carries rather than the last. The `action` field reports `added`, `corrected`, or `unchanged`, which makes a rerun against the same plan safe.
248
+ The write adds the line when it is absent and corrects the target in place when it exists, anchored on the H1 rather than on the last origin line, since `Plan:` is the first origin line a task carries rather than the last. The `action` field reports `added`, `corrected`, or `unchanged`, which makes a rerun against the same plan safe.
249
249
 
250
250
  Exit codes: `0` recorded, `1` refused. The `reason` field carries `no-board`, `no-match`, `no-plan`, or `bad-input`.
251
251
 
252
252
  ## Pull request
253
253
 
254
- `canon tasks pull-request` records the number a branch's pull request carries onto the task that branch closes. It adds `Pull request: #NNN` under the `Plan:`, `Groundwork:`, `Intake:`, or `Issue:` lines the task already holds, and corrects the number in place when the line exists.
254
+ `canon tasks pull-request` records the number a branch's pull request carries onto the task that branch closes. It adds `Pull request: #NNN` under the `Plan:`, `Groundwork:`, `Intake:`, or `Issue:` lines the task already holds. When the line exists it appends `, #NNN` rather than replacing it, so a task shipped in slices lists every pull request oldest first, and a number already listed leaves the line alone. A line that does not read as a comma-separated list of `#NNN` entries is replaced whole.
255
255
 
256
256
  Name the task by its filename stem, or by the plan its `Plan:` line points at:
257
257
 
@@ -266,7 +266,7 @@ canon tasks pull-request 673 --plan worktree-scratch-routing --json
266
266
  | `--json` | Emit a machine-readable record on stdout |
267
267
  | `--root <path>` | Board root, defaulting to the main worktree |
268
268
 
269
- A plan is matched on the token both spellings share, so `worktree-scratch-routing`, `feature-worktree-scratch-routing`, and `.canon/plans/feature-worktree-scratch-routing.md` all select the same task. The `action` field reports `added`, `corrected`, or `unchanged`, which makes a rerun against the same number safe.
269
+ A plan is matched on the token both spellings share, so `worktree-scratch-routing`, `feature-worktree-scratch-routing`, and `.canon/plans/feature-worktree-scratch-routing.md` all select the same task. The `action` field reports `added`, `appended`, `corrected`, or `unchanged`, which makes a rerun against the same number safe.
270
270
 
271
271
  Exit codes: `0` recorded, `1` refused. The `reason` field carries `no-board`, `no-match`, or `ambiguous`. `git-pr` skips silently on those three, because each is a case where a guessed write would archive the wrong task once the branch merges.
272
272
 
@@ -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. A `renamed` rule is one the toolkit now ships under a new name, and the next sync installs the new name and deletes the old file.
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
 
@@ -224,15 +224,15 @@ This section is the corpus the coverage claim is measured against: every name `c
224
224
 
225
225
  ### Build the feature
226
226
 
227
- | Skill | When to use |
228
- | ---------------------------- | ------------------------------------------------------------------------------- |
229
- | `canon:session-worktree` | At the plan-to-execute boundary, to get an isolated tree and branch |
230
- | `canon:auto-ship` | After plan approval, to chain implement, verify, review, draft PR |
231
- | `canon:project-commands` | When the project's own command needs running |
232
- | `canon:test-first` | Before implementing a planned change, to run its test red, green, then refactor |
233
- | `canon:test-craft` | When writing or changing any test, to pick its layer and filter what it asserts |
234
- | `canon:systematic-debugging` | When a test fails or a bug surfaces, to force root cause first |
235
- | `canon:ui-checklist` | After a UI change, to write what to look at and name what ships untested |
227
+ | Skill | When to use |
228
+ | ---------------------------- | ---------------------------------------------------------------------------------------------------------- |
229
+ | `canon:session-worktree` | At the plan-to-execute boundary, to get an isolated tree and branch, or to route a refused main-root write |
230
+ | `canon:auto-ship` | After plan approval, to chain implement, verify, review, draft PR |
231
+ | `canon:project-commands` | When the project's own command needs running |
232
+ | `canon:test-first` | Before implementing a planned change, to run its test red, green, then refactor |
233
+ | `canon:test-craft` | When writing or changing any test, to pick its layer and filter what it asserts |
234
+ | `canon:systematic-debugging` | When a test fails or a bug surfaces, to force root cause first |
235
+ | `canon:ui-checklist` | After a UI change, to write what to look at and name what ships untested |
236
236
 
237
237
  ### Check the work before it leaves the branch
238
238
 
@@ -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
@@ -24,7 +24,7 @@ The toolkit seed in `tooling/claude/seeds/canon/DESIGN.md` ships a token-table t
24
24
 
25
25
  The `canon:design-extract` skill drafts the file, sourcing tokens from a project's existing prose and CLI UI surfaces, or proposing them from `canon/REQUIREMENTS.md` and a `## Personality` paragraph when no UI code exists yet. `canon design render` writes an HTML plus CSS preview to `.canon/tmp/render/design/` for eyeballing the current system without leaving Claude Code. See `canon/context/design.md`.
26
26
 
27
- A project wanting the toolkit's own values rather than its own runs `canon design install`, which copies one stylesheet to `.claude/design/base.css` carrying the token set as custom properties and two components built on them. That file is toolkit-owned and `canon design sync` refreshes it, so a project overrides a value in `.claude/design/project/` instead, which sync never touches. Nothing arrives without that install, and the two channels are independent: a record drafted by the extract skill is the project's own, and the installed stylesheet is the toolkit's.
27
+ A project wanting a neutral starting point to override runs `canon design install`, which copies one stylesheet to `.claude/design/base.css` carrying an achromatic token set as custom properties and two components built on them. Greys run from near-black to near-white and the accent is monochrome, so the only palette the project renders is one it writes itself. That file is toolkit-owned and `canon design sync` refreshes it, so a project overrides a value in `.claude/design/project/` instead, which sync never touches. Nothing arrives without that install, and the two channels are independent: a record drafted by the extract skill is the project's own, and the installed stylesheet is the toolkit's.
28
28
 
29
29
  A cell no source anchors ends in `? verify`, and the preview shows that marker beside the value rather than folding it in, so a swatch and a font sample stay built from the value alone. A confidence line above the sections names how many cells are anchored against how many are tagged, which is what tells a reader whether they are looking at a record of the code or a proposal about it. It reads the columns a source could anchor and leaves out the row names, so the ratio is not diluted by cells no tag could ever reach. The proposal path tags nearly all of them, so that count reads low on day one by design.
30
30
 
@@ -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
@@ -0,0 +1,13 @@
1
+ # Rule renames a sync carries a target across. Each key under [renamed] is an
2
+ # old rule basename and its value the basename the same rule ships under now,
3
+ # so `canon gov sync` replaces a held old file with the rule under its new name
4
+ # rather than only deleting it.
5
+ #
6
+ # An entry declares one-to-one identity and nothing else. A fold of several
7
+ # rules into one, or a split of one into several, is a retirement plus an
8
+ # addition and takes no entry here. Add the entry in the same change as the
9
+ # rename or renumber, and never prune one: a target can sit any number of
10
+ # releases behind, and a chain A to B to C resolves A only while both links
11
+ # stay. A key must name no live rule and every chain must end on one, which
12
+ # `src/gov/renames.test.ts` checks against this file.
13
+ [renamed]
@@ -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. A blank `- Answer:` slot in a plan accepts the `- Suggested:` line above it, per the plan standard, which your toolkit resolves by name.
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
- - Use the path the user's editor can resolve. The editor is rooted at the main project root.
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, create a plan in `.canon/plans/` and link to it from the task's intro paragraph. When that task ships, move its plan file to `.canon/plans/archive/`. Never delete it.
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` in the project root, a nested `<slug>/` folder with a kebab-slug tied to the topic, not a flat `<slug>-<file>.md`. The scratch-guard hook enforces the location.
10
- - Write to `.claude/.tmp/<slug>/` instead in a project that carries no `.canon/` root, which is one the record move has not reached. The hook accepts either, but the ignore file is the source: `.gitignore` and its manifest counterpart are what keep the fallback spelling out of `git status`, and the hook and this rule both defer to it. `canon migrate records` is what moves a project from this second spelling to the first. <!-- canon-keep-record-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
- - Analyze requests and output a numbered implementation plan before execution.
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 tracked-file writes and shared session scratch correctly from a linked worktree
2
+ description: Enter a linked worktree for implementation, resolve shared session scratch at the main root, and route a refused main-root write through session-worktree
3
3
  ---
4
4
 
5
5
  # Worktrees standards
@@ -11,10 +11,4 @@ description: Route tracked-file writes and shared session scratch correctly from
11
11
  ## Shared session scratch
12
12
 
13
13
  - Shared session scratch (`.canon/plans/`, `.canon/review/`, `.canon/memory/`, `.canon/tasks/`) lives at the main worktree root, not inside a linked worktree. From a linked worktree, resolve these paths against the main root via `git worktree list --porcelain | grep -m 1 '^worktree ' | cut -d' ' -f2-`. Fall back to `pwd` if not a git repo.
14
- - `.canon/tmp/` is mixed rather than main-root by default: it stays worktree-local per `055-scratch.md`, and a skill that resolves a write there at the main root instead states so in its own body.
15
- - From a linked worktree, every `Edit` or `Write` to a tracked file (source, docs) must use a path starting with `pwd`.
16
- - From a linked worktree, `Edit` and `Write` are refused for every main-root path, session scratch included. The refusal names session isolation and points at the worktree copy, which is a second gitignored file no later session reads, so never take that redirect.
17
- - `Read` resolves against the main root normally from a linked worktree. A main-root write reaches it only through `Bash`, as one plain command rather than a compound one, which is refused for complexity.
18
- - Route a main-root write by what it does to the file. Creating a whole file goes out as one plain `Bash` command carrying a heredoc. Changing a line inside a file that already exists goes through a command that resolves the main root in-process, because the shell route for that case is the stream editor this file bans.
19
- - A background session that entered no worktree at all meets the identical refusal writing to the main root, since the guard gates on isolation rather than on sitting inside a linked worktree. A planner writing its plan file from no worktree takes the same heredoc route for that reason.
20
- - The heredoc route costs nothing on `.canon/plans/` and `.canon/review/`, which no `PostToolUse` hook watches, and costs the index on `.canon/tasks/` and `.canon/memory/`, since a hook matching `Write|Edit|MultiEdit` never fires on `Bash`. Regenerate positionally: in-process where a verb such as `canon tasks archive` already calls it, elsewhere by an explicit `canon indexes regen` call.
14
+ - From a linked worktree, or from a background session that entered none, `Edit` and `Write` refuse a main-root path and redirect to a worktree copy no later session reads. Never take that redirect. Route the write the way the `session-worktree` skill states, and report it rather than proceeding silently when that 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.
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: Route every git operation through the canon git skills, and run one only when something actually calls for it
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
- - A git operation runs only when the user asked for it, a task states it, or it executes as a step of a chain the user invoked. The bullets above decide which surface performs an operation already decided, never whether to take one.
15
+ - The bullets above decide which surface performs an operation already decided, never whether to take one.
@@ -36,4 +36,4 @@ paths:
36
36
 
37
37
  Do not write a comment carrying any of these terms.
38
38
 
39
- - `FIXED`, `BUGFIX`, `HACK`, `XXX`, `NOTE:`, `TODO`, `FIXME`, `don't remove`, `previously`, `used to`, `workaround`
39
+ - `TODO`, `FIXME`, `HACK`, `XXX`
@@ -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.
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@erclx/canon",
3
3
  "type": "module",
4
- "version": "4.117.0",
4
+ "version": "4.119.0",
5
5
  "description": "Infrastructure and quality tooling for developer workflows",
6
6
  "license": "MIT",
7
7
  "bin": {