@erclx/canon 5.32.0 → 5.34.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 (250) hide show
  1. package/claude/.claude-plugin/plugin.json +1 -1
  2. package/claude/skills/api-design/REQUIREMENT.md +1 -2
  3. package/claude/skills/api-design/SKILL.md +2 -3
  4. package/claude/skills/api-design/references/adopted.md +1 -1
  5. package/claude/skills/auto-ship/SKILL.md +1 -1
  6. package/claude/skills/auto-ship/references/worktree-name.md +1 -1
  7. package/claude/skills/backlog-triage/REQUIREMENT.md +2 -2
  8. package/claude/skills/backlog-triage/SKILL.md +1 -1
  9. package/claude/skills/canon-cli/REQUIREMENT.md +16 -13
  10. package/claude/skills/canon-cli/SKILL.md +75 -32
  11. package/claude/skills/canon-feedback/REQUIREMENT.md +1 -0
  12. package/claude/skills/canon-feedback/SKILL.md +11 -29
  13. package/claude/skills/canon-feedback/references/template.md +53 -0
  14. package/claude/skills/{canvas → canvas-board}/REQUIREMENT.md +2 -2
  15. package/claude/skills/{canvas → canvas-board}/SKILL.md +6 -3
  16. package/claude/skills/{canvas → canvas-board}/references/canvas.md +26 -3
  17. package/{standards → claude/skills/canvas-board/references}/design.md +11 -2
  18. package/claude/skills/code-craft/REQUIREMENT.md +1 -1
  19. package/claude/skills/code-craft/SKILL.md +0 -1
  20. package/claude/skills/context-fold/REQUIREMENT.md +25 -33
  21. package/claude/skills/context-fold/SKILL.md +25 -70
  22. package/claude/skills/context-fold/references/classify.md +3 -3
  23. package/claude/skills/context-fold/references/completion-report.md +4 -4
  24. package/claude/skills/context-fold/references/context-refresh.md +5 -5
  25. package/{standards → claude/skills/context-fold/references}/context.md +16 -5
  26. package/claude/skills/context-fold/references/unusable-baseline.md +3 -5
  27. package/claude/skills/create-rule/SKILL.md +3 -3
  28. package/{standards → claude/skills/create-rule/references}/rule.md +15 -6
  29. package/claude/skills/create-skill/SKILL.md +2 -2
  30. package/{standards → claude/skills/create-skill/references}/skill.md +18 -15
  31. package/claude/skills/design-taste/REQUIREMENT.md +3 -3
  32. package/claude/skills/design-taste/SKILL.md +1 -1
  33. package/claude/skills/docs-sync/REQUIREMENT.md +1 -1
  34. package/claude/skills/docs-sync/SKILL.md +3 -3
  35. package/{standards → claude/skills/docs-sync/references}/docs.md +11 -0
  36. package/{standards → claude/skills/docs-sync/references}/readme.md +9 -2
  37. package/claude/skills/draft-and-pick/SKILL.md +5 -5
  38. package/claude/skills/draft-doc/SKILL.md +6 -6
  39. package/claude/skills/draft-figure/REQUIREMENT.md +2 -2
  40. package/claude/skills/draft-figure/SKILL.md +2 -2
  41. package/claude/skills/draft-figure/references/hand-drawn.md +1 -1
  42. package/claude/skills/draft-figure/references/mermaid-path.md +1 -1
  43. package/claude/skills/draft-identity/REQUIREMENT.md +2 -2
  44. package/claude/skills/draft-identity/SKILL.md +2 -2
  45. package/claude/skills/draft-ready/SKILL.md +1 -1
  46. package/claude/skills/git-branch/SKILL.md +1 -1
  47. package/{standards → claude/skills/git-branch/references}/branch.md +1 -1
  48. package/claude/skills/git-commit/SKILL.md +2 -2
  49. package/claude/skills/git-followup/REQUIREMENT.md +1 -1
  50. package/claude/skills/git-followup/SKILL.md +1 -1
  51. package/claude/skills/git-issue/SKILL.md +1 -1
  52. package/claude/skills/git-issue/references/issue.md +4 -1
  53. package/claude/skills/git-pr/SKILL.md +13 -13
  54. package/claude/skills/git-pr/references/evidence.md +2 -2
  55. package/claude/skills/git-pr/references/final-command.md +38 -14
  56. package/claude/skills/git-pr/references/labels.md +5 -1
  57. package/{standards → claude/skills/git-pr/references}/pr.md +19 -9
  58. package/{standards → claude/skills/git-pr/references}/publish.md +4 -2
  59. package/claude/skills/git-pr/references/task-number.md +1 -1
  60. package/claude/skills/git-ship/SKILL.md +15 -14
  61. package/claude/skills/git-split/SKILL.md +3 -3
  62. package/claude/skills/git-stage/SKILL.md +1 -1
  63. package/claude/skills/plan-feature/REQUIREMENT.md +1 -1
  64. package/claude/skills/review-address/SKILL.md +1 -1
  65. package/claude/skills/review-address/references/post-review-findings.md +1 -1
  66. package/claude/skills/review-craft/references/ui.md +1 -1
  67. package/claude/skills/review-pr/REQUIREMENT.md +1 -1
  68. package/claude/skills/review-pr/SKILL.md +3 -3
  69. package/claude/skills/review-pr/references/body-variants.md +2 -2
  70. package/claude/skills/review-pr/references/key-changes.md +3 -3
  71. package/claude/skills/review-pr/references/post.md +4 -2
  72. package/claude/skills/review-ui/REQUIREMENT.md +1 -1
  73. package/claude/skills/review-ui/SKILL.md +8 -6
  74. package/claude/skills/review-ui/references/driving.md +8 -8
  75. package/claude/skills/review-ui/references/post.md +53 -17
  76. package/claude/skills/role-orchestrator/REQUIREMENT.md +3 -0
  77. package/claude/skills/role-orchestrator/SKILL.md +2 -2
  78. package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +2 -2
  79. package/claude/skills/role-orchestrator/references/orchestrator-handoff.md +8 -5
  80. package/claude/skills/role-orchestrator/references/orchestrator-launch.md +32 -1
  81. package/claude/skills/role-orchestrator/references/orchestrator-refill.md +2 -2
  82. package/claude/skills/role-orchestrator/references/orchestrator-resume.md +3 -0
  83. package/claude/skills/role-planner/REQUIREMENT.md +2 -1
  84. package/claude/skills/role-planner/SKILL.md +13 -2
  85. package/claude/skills/role-reviewer/SKILL.md +1 -1
  86. package/claude/skills/role-worker/REQUIREMENT.md +1 -0
  87. package/claude/skills/role-worker/SKILL.md +9 -1
  88. package/claude/skills/session-map/SKILL.md +1 -1
  89. package/claude/skills/session-resume/REQUIREMENT.md +2 -2
  90. package/claude/skills/session-worktree/SKILL.md +5 -5
  91. package/claude/skills/target-setup/SKILL.md +10 -4
  92. package/claude/skills/target-setup/references/detect.md +20 -3
  93. package/claude/skills/task-board/REQUIREMENT.md +7 -12
  94. package/claude/skills/task-board/SKILL.md +5 -17
  95. package/claude/skills/task-board/references/tasks.md +2 -2
  96. package/claude/skills/task-complete/REQUIREMENT.md +47 -0
  97. package/claude/skills/task-complete/SKILL.md +86 -0
  98. package/claude/skills/{task-board → task-complete}/references/archive.md +4 -4
  99. package/claude/skills/{context-fold → task-complete}/references/receipt-sweep.md +5 -5
  100. package/claude/skills/task-complete/references/unusable-baseline.md +19 -0
  101. package/claude/skills/teach-workspace/REQUIREMENT.md +6 -2
  102. package/claude/skills/teach-workspace/SKILL.md +8 -4
  103. package/claude/skills/teach-workspace/references/lesson-craft.md +1 -1
  104. package/claude/skills/{context-fold/references/promoted-pages.md → teach-workspace/references/promotion-fold.md} +3 -3
  105. package/claude/skills/teach-workspace/references/promotion.md +3 -3
  106. package/claude/skills/test-craft/REQUIREMENT.md +2 -3
  107. package/claude/skills/test-craft/SKILL.md +15 -3
  108. package/claude/skills/ui-checklist/SKILL.md +1 -1
  109. package/claude/skills/ux-audit/SKILL.md +1 -1
  110. package/claude/skills/ux-measure/SKILL.md +1 -1
  111. package/docs/agents/canvas.md +6 -2
  112. package/docs/agents/commands.md +4 -3
  113. package/docs/agents/context-audit-checks.md +4 -4
  114. package/docs/agents/gov-detect.md +47 -0
  115. package/docs/agents/index.md +7 -4
  116. package/docs/agents/indexes.md +1 -1
  117. package/docs/agents/install-and-sync.md +10 -11
  118. package/docs/agents/key-changes.md +5 -5
  119. package/docs/agents/label-coverage.md +11 -0
  120. package/docs/agents/migrate.md +1 -1
  121. package/docs/agents/pr-evidence-layout.md +70 -0
  122. package/docs/agents/pr-evidence.md +8 -9
  123. package/docs/agents/pr-frames.md +7 -2
  124. package/docs/agents/pr-lift.md +132 -0
  125. package/docs/agents/records-push.md +2 -2
  126. package/docs/agents/records-stale.md +12 -47
  127. package/docs/agents/records-validate.md +3 -7
  128. package/docs/agents/records.md +5 -27
  129. package/docs/agents/rule-citations.md +1 -1
  130. package/docs/agents/sandbox.md +4 -4
  131. package/docs/agents/scripting.md +2 -1
  132. package/docs/agents/skills-audit.md +1 -1
  133. package/docs/agents/tasks-plans.md +2 -2
  134. package/docs/agents/tasks.md +2 -2
  135. package/docs/target/migrations.md +10 -2
  136. package/docs/target/projects.md +4 -4
  137. package/docs/target/sync.md +1 -1
  138. package/docs/workflow/operating-model.md +2 -2
  139. package/docs/workflow/parallel-features.md +7 -7
  140. package/docs/workflow/skill-map-on-request.md +9 -9
  141. package/docs/workflow/skill-map.md +12 -11
  142. package/docs/workflow/visual-design-workflow.md +2 -2
  143. package/governance/detect.toml +201 -0
  144. package/governance/renames.toml +0 -11
  145. package/governance/rules/canon/context.md +13 -0
  146. package/governance/rules/claude/skill.md +17 -0
  147. package/governance/rules/code/000-code.md +1 -13
  148. package/governance/rules/code/010-testing.md +2 -30
  149. package/governance/rules/ui/400-ui.md +1 -1
  150. package/governance/rules/ui/480-canvas.md +13 -0
  151. package/governance/stacks/base.toml +2 -4
  152. package/package.json +4 -4
  153. package/scripts/core/install-check.sh +3 -3
  154. package/scripts/core/regen-hero.ts +0 -6
  155. package/scripts/lib/ui.sh +0 -168
  156. package/src/audits/catalog.ts +0 -1
  157. package/src/canvas/arrange.ts +66 -0
  158. package/src/canvas/capture.ts +20 -6
  159. package/src/canvas/content.ts +39 -0
  160. package/src/canvas/fit.ts +238 -0
  161. package/src/canvas/tokens.ts +28 -10
  162. package/src/capture/frame-values.ts +2 -32
  163. package/src/claude/cases/misc.ts +1 -1
  164. package/src/claude/cases/setup.ts +4 -0
  165. package/src/claude/cases/workflow.ts +6 -1
  166. package/src/claude/seeds.ts +1 -1
  167. package/src/claude/skills-audit.ts +2 -2
  168. package/src/cli/help.ts +3 -1
  169. package/src/cli/ui.ts +2 -3
  170. package/src/commands/canvas.ts +179 -1
  171. package/src/commands/claude.ts +1 -1
  172. package/src/commands/gov.ts +146 -16
  173. package/src/commands/labels.ts +326 -7
  174. package/src/commands/migrate.ts +6 -1
  175. package/src/commands/pr.ts +377 -2
  176. package/src/commands/records.ts +13 -399
  177. package/src/commands/sandbox.ts +3 -6
  178. package/src/commands/tasks.ts +3 -3
  179. package/src/context/audit.ts +5 -5
  180. package/src/context/folders.ts +1 -1
  181. package/src/design/budget.ts +1 -1
  182. package/src/design/components.ts +1 -1
  183. package/src/design/document.ts +1 -1
  184. package/src/design/regen.ts +1 -1
  185. package/src/design/render.ts +1 -1
  186. package/src/feedback/body.ts +26 -5
  187. package/src/gate/measures.ts +59 -45
  188. package/src/gate/sequencer.ts +56 -1
  189. package/src/gate/stages.ts +4 -11
  190. package/src/gov/detect.ts +301 -0
  191. package/src/gov/install.ts +2 -3
  192. package/src/gov/list.ts +23 -2
  193. package/src/gov/stacks.ts +10 -1
  194. package/src/hooks/post-merge.ts +1 -1
  195. package/src/labels/apply.ts +39 -0
  196. package/src/labels/format.ts +3 -3
  197. package/src/labels/phase.ts +3 -3
  198. package/src/labels/sections.ts +43 -0
  199. package/src/migrate/skill-names.ts +20 -1
  200. package/src/pr/evidence.ts +218 -45
  201. package/src/pr/frames.ts +23 -3
  202. package/src/pr/lift.ts +418 -0
  203. package/src/pr/paths.ts +4 -4
  204. package/src/pr/rest.ts +3 -0
  205. package/src/pr/review-scope.ts +76 -0
  206. package/src/records/backup.ts +16 -6
  207. package/src/records/stale-canonical.ts +31 -1
  208. package/src/records/validate.ts +2 -188
  209. package/src/sandbox/census.ts +1 -1
  210. package/src/sandbox/coverage.ts +2 -6
  211. package/src/sandbox/equivalence.ts +19 -51
  212. package/src/sandbox/expect.ts +4 -4
  213. package/src/sandbox/provision.ts +13 -36
  214. package/src/sandbox/scenario.ts +26 -48
  215. package/src/sandbox/tree.ts +2 -6
  216. package/src/standards/read.ts +14 -1
  217. package/src/sync/git.ts +1 -1
  218. package/src/tasks/archive.ts +5 -5
  219. package/src/tasks/branch.ts +3 -3
  220. package/src/tasks/label.ts +1 -1
  221. package/src/tasks/record.ts +2 -2
  222. package/src/tasks/validate.ts +1 -1
  223. package/standards/index.md +0 -13
  224. package/standards/standard.md +1 -7
  225. package/tooling/base/reference.md +1 -1
  226. package/tooling/base/seeds/.github/pull_request_template.md +2 -2
  227. package/tooling/claude/reference.md +1 -1
  228. package/tooling/claude/seeds/.claude/hooks/pr-create-log.sh +9 -1
  229. package/tooling/claude/seeds/.claude/hooks/review-post-scan.sh +171 -0
  230. package/tooling/claude/seeds/.claude/settings.json +9 -0
  231. package/governance/rules/standards/context.md +0 -14
  232. package/governance/rules/standards/design.md +0 -12
  233. package/governance/rules/standards/readme.md +0 -12
  234. package/governance/rules/standards/rule.md +0 -13
  235. package/governance/rules/standards/skill.md +0 -21
  236. package/governance/rules/standards/standard.md +0 -13
  237. package/scripts/config.sh +0 -11
  238. package/scripts/lib/gov.sh +0 -14
  239. package/scripts/lib/sandbox-fixtures.sh +0 -191
  240. package/scripts/lib/sandbox-git.sh +0 -125
  241. package/scripts/lib/sandbox-path.sh +0 -50
  242. package/scripts/sandbox-hook.sh +0 -99
  243. package/src/gov/standard-rules.ts +0 -179
  244. package/src/records/migrate.ts +0 -78
  245. package/src/records/stale.ts +0 -243
  246. package/src/sandbox/hooks.ts +0 -128
  247. /package/{standards → claude/skills/draft-figure/references}/figures.md +0 -0
  248. /package/{standards → claude/skills/git-branch/references}/slug.md +0 -0
  249. /package/{standards → claude/skills/git-commit/references}/commit.md +0 -0
  250. /package/{standards → claude/skills/git-commit/references}/versioning.md +0 -0
@@ -5,11 +5,10 @@ description: Validating the session records and the standards corpus, the per-ki
5
5
 
6
6
  # Records validate
7
7
 
8
- `canon records validate <kind>` reports where a file and the standard governing it disagree. Five kinds are gitignored folders under the record root, resolved at `.canon/` first: `plans`, `groundwork`, `intake`, `memory`, and `teach`. The sixth is `standards`, the authoring corpus, which is tracked and installed rather than scratch.
8
+ `canon records validate <kind>` reports where a file and the standard governing it disagree. Four kinds are gitignored folders under the record root, resolved at `.canon/` first: `plans`, `groundwork`, `intake`, and `teach`. The fifth is `standards`, the authoring corpus, which is tracked and installed rather than scratch.
9
9
 
10
10
  ```bash
11
11
  canon records validate plans
12
- canon records validate memory
13
12
  canon records validate standards
14
13
  canon records validate intake --json
15
14
  ```
@@ -23,7 +22,7 @@ It reads and never writes, and the reason splits by kind. A session record is pe
23
22
 
24
23
  `standards` reads the authoring root at `standards/` where it exists and a copy at `.claude/standards/` otherwise. The authoring root wins because it is the only tree anyone authors in and the only one the resolver answers from, so a finding fixed anywhere else is fixed where nothing reads it. No repository generates the second candidate any more, which leaves it as a floor under a target holding a copy an older toolkit installed. The walk stays flat, matching the catalog.
25
24
 
26
- Nothing fires it automatically. The five record folders are gitignored, so the standards-audit hook exits early on them and any check reading changed files from git never lists one. The corpus is tracked and still unreached, since the markdown audit reads content across the files git lists and rules on no filename. The verb runs at the moment a session claims the record is finished, which is the same placement `canon tasks validate` takes over the board.
25
+ Nothing fires it automatically. The four record folders are gitignored, so the standards-audit hook exits early on them and any check reading changed files from git never lists one. The corpus is tracked and still unreached, since the markdown audit reads content across the files git lists and rules on no filename. The verb runs at the moment a session claims the record is finished, which is the same placement `canon tasks validate` takes over the board.
27
26
 
28
27
  The two record roots every kind resolves at are in `records.md`.
29
28
 
@@ -34,15 +33,12 @@ The two record roots every kind resolves at are in `records.md`.
34
33
  | `plans` | A filename that is not `feature-<slug>.md`, a missing `# Feature:` heading, a missing required section, a files-to-touch entry naming no file or saying nothing about one, a question carrying no suggestion or no answer slot, and a batch still staged with a `**Batch N**` sub-heading inside the one file rather than split into its own plan |
35
34
  | `groundwork` | A track with no `README.md` or no `01-current-state.md`, a file missing `title` or `description`, a `README.md` with no `date` as `YYYY-MM-DD`, an unnumbered file, and a track holding a decision without its handoff or the reverse |
36
35
  | `intake` | A dump with no `00-overview.md`, the same frontmatter and numbering checks, an item missing any of `Problem`, `Fix`, `Worth it`, or `You`, and an item carrying `Open` with no `Suggested` |
37
- | `memory` | A filename whose prefix names none of the four types, an entry missing `title`, `description`, or `category`, a `category` disagreeing with that prefix, a title repeating the filename, and a rule-bearing body missing a part |
38
36
  | `standards` | A standard missing `title` or `description`, an absent `## Scope` section, a scope section carrying no `Does not govern:` list, a statement anchoring nothing, and a filename naming no part of the path the statement governs |
39
37
  | `teach` | A workspace folder carrying no two-digit ordinal, an absent `MISSION.md`, `RESOURCES.md`, or `GLOSSARY.md`, a file missing `title` or `description`, a mission with no `date` as `YYYY-MM-DD` or no `## Success looks like` section, an unnumbered learning record, and a reference page opening with an ordinal |
40
38
 
41
39
  The half-closed track is the groundwork check a reader cannot run by eye. A folder holding `06` without `07` reads as closed to anyone scanning filenames while the file a returning session actually opens is absent.
42
40
 
43
- The item check skips `00-overview.md` and `99-next-session.md`, since neither holds items and running it over the handoff would report every heading it carries. The memory walk skips `index.md` for the same reason, since the catalog is generated from its siblings rather than authored as an entry.
44
-
45
- A memory `category` is compared against the sentence-case form of the filename prefix rather than checked field by field, so one finding covers a prefix outside the four types, a field disagreeing with the prefix, and a casing drift that would open a second group in the catalog. The body check runs on `feedback` and `project` entries alone, because a `user` or `reference` entry is a single sentence by design and has no rule to apply.
41
+ The item check skips `00-overview.md` and `99-next-session.md`, since neither holds items and running it over the handoff would report every heading it carries.
46
42
 
47
43
  The standards filename check derives a word from the governed path rather than counting words in the name. Every member of the corpus is named for the artifact its scope statement governs, and one word is what that produces rather than the rule itself, so a check keyed on word count would pass a conforming single word naming the wrong artifact. Each path segment offers its own word, a dotted container segment offers none, a hyphenated segment offers its parts, and the singular and the plural both match.
48
44
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Records
3
- description: The two roots a record folder resolves at, migrating a record a frontmatter change orphaned, claiming the ordinal intake and groundwork share, reading each folder's size and growth, pruning stale scratch, and where validation, the memory review queue, and the private-remote backup are described
3
+ description: The two roots a record folder resolves at, claiming the ordinal intake and groundwork share, reading each folder's size and growth, pruning stale scratch, and where validation, the canonical review count, and the private-remote backup are described
4
4
  ---
5
5
 
6
6
  # Records
@@ -19,28 +19,6 @@ A refusal names every root it looked at, so a message reading `no-folder` says w
19
19
 
20
20
  `canon records validate <kind>` reports where a record folder or the standards corpus disagrees with the standard governing it. Its flags, the per-kind checks, and the refusals are in `records-validate.md`.
21
21
 
22
- ## Migrate
23
-
24
- `canon records migrate <kind>` rewrites the records a `validate` finding names a transform for. A standard that redefines its own required frontmatter breaks every record already written to the old shape, and this is the repair `validate` could only report until now.
25
-
26
- ```bash
27
- canon records migrate memory
28
- canon records migrate memory --write
29
- canon records migrate memory --json
30
- ```
31
-
32
- | Option | Behavior |
33
- | --------------- | ------------------------------------------------------------------- |
34
- | `--json` | Add a machine-readable record on stdout |
35
- | `--write` | Rewrite every record a transform can repair |
36
- | `--root <path>` | Project root, defaulting to the main worktree except on `standards` |
37
-
38
- It writes nothing until `--write` is passed, matching the write-flag contract `canon tooling sync` carries: a session record has no history to undo a wrong repair from, so naming a kind is not consent to rewrite every record inside it. A dry run reports which records it would touch and exits non-zero either way, headless or not, since there is nothing to prompt for.
39
-
40
- A transform runs only where the missing value is recoverable from the file itself. The one shipped today repairs a memory record missing `category` alone, deriving it from the same filename prefix `checkMemory` already reads it from. `title` and `description` are prose nobody wrote down, so a finding naming either carries no transform and stays for a session to fix by hand, and `validate` keeps reporting it. The transform re-reads the file rather than trusting a value captured at validate time, so a check and its repair cannot disagree about the same record.
41
-
42
- Exit codes: `0` nothing carried a known transform, or `--write` repaired everything it found. `1` refused for a reason `validate` shares, every candidate it found failed to repair, or `--write` repaired only some of them. `2` a record carries a known transform and `--write` was not passed.
43
-
44
22
  ## Ordinal
45
23
 
46
24
  `canon records ordinal <kind> <slug>` reports the next ordinal `intake` and `groundwork` share, or claims it with `--claim`. The two kinds share one sequence, per `claude/skills/plan-intake/references/intake.md` and `claude/skills/plan-groundwork/references/groundwork.md`, so this reads both `.canon/intake/` and `.canon/groundwork/` regardless of which kind was asked for.
@@ -81,9 +59,9 @@ Ordering by weight is what makes the reading worth taking. A folder listed alpha
81
59
 
82
60
  The reading carries two windows rather than one, at 7 and 30 days. A single window cannot separate a folder growing steadily from one that took a single batch: a folder whose 7-day count is most of its 30-day count moved in one pass, and one where the two are proportional is growing at a rate.
83
61
 
84
- Nothing fails on a number here. A record folder has no correct size, so the reading is a number to notice rather than a threshold to gate, and the point of the verb is that the next reading is taken by a command instead of by someone remembering to count the folder. The memory pen went from 44 entries to 236 between two readings taken by hand two weeks apart, which is the measurement this replaces.
62
+ Nothing fails on a number here. A record folder has no correct size, so the reading is a number to notice rather than a threshold to gate, and the point of the verb is that the next reading is taken by a command instead of by someone remembering to count the folder. A pen went from 44 entries to 236 between two readings taken by hand two weeks apart, which is the measurement this replaces.
85
63
 
86
- The scratch folder is read here and skipped by a backup, because deletable without loss is not the same as empty. The routing handoffs and the memory archive both sit there and both accumulate. `.canon/.records.git` stays out because it is the backup history rather than a record, and `.claude/worktrees/` stays out because each entry is a checkout of the project with its own removal verb, and one of them outweighs every record folder combined.
64
+ The scratch folder is read here and skipped by a backup, because deletable without loss is not the same as empty. The routing handoffs and a retired entry archive both sit there and both accumulate. `.canon/.records.git` stays out because it is the backup history rather than a record, and `.claude/worktrees/` stays out because each entry is a checkout of the project with its own removal verb, and one of them outweighs every record folder combined.
87
65
 
88
66
  The window counts read `mtime`, so what they report is a file written inside the window rather than one created there. An entry edited long after it landed reads as recent, which overstates growth and never understates it, and these folders are append-mostly so the two readings agree on nearly every file. The one reading that is wrong rather than early is a machine restored by `canon records pull`, which resets the work tree hard and re-dates every file it writes, so a window taken there counts the restore. Nothing on the filesystem separates the two, since a restored file is new by every stamp it carries.
89
67
 
@@ -112,13 +90,13 @@ A candidate is a unit whose newest file is older than the threshold: a `tmp/<slu
112
90
 
113
91
  A scratch-root name `canon migrate record-layout` or `canon migrate scratch-evidence` moves out of scratch for good, such as `memory-archive`, is skipped the same way on a project that has not yet run that migration, naming the verb to run. The retired-entry archive `memory-archive` holds is never deleted, per the memory standard, so it stays skipped rather than aging into an offer.
114
92
 
115
- It writes nothing until `--write` is passed, matching `canon records migrate`: a session record has no history to undo a wrong delete from. It reads `mtime` the way `canon records size` does, so a machine restored by `canon records pull` reads its whole tree as new and fails safe by offering nothing.
93
+ It writes nothing until `--write` is passed, since a session record has no history to undo a wrong delete from. It reads `mtime` the way `canon records size` does, so a machine restored by `canon records pull` reads its whole tree as new and fails safe by offering nothing.
116
94
 
117
95
  Exit codes: `0` nothing to prune, or `--write` deleted every candidate. `1` refused, sharing `no-folder` with `size`, or a delete failed. `2` candidates exist and `--write` was not passed.
118
96
 
119
97
  ## Stale
120
98
 
121
- `canon records stale memory` reports which memory entries are due for review and which cite a path the tree no longer holds, ordered so a review takes the first N as a batch. `canon records stale canonical` reports when the requirements record was last reviewed and how many releases have shipped since. What makes an entry due, how a cited path resolves, how the release count is taken, and the refusals are in `records-stale.md`.
99
+ `canon records stale canonical` reports when the requirements record was last reviewed and how many releases have shipped since. How the release count is taken and the refusals are in `records-stale.md`.
122
100
 
123
101
  ## Push and pull
124
102
 
@@ -49,7 +49,7 @@ A `path` is anchored on the whole backticked span rather than on a trailing patt
49
49
  A rule body is full of backticked spans carrying a slash, and almost none of them names a file in this tree. The stage declines four shapes outright.
50
50
 
51
51
  - A placeholder or glob segment describes a shape rather than naming a file: `canon/context/<domain>.md`, `standards/<name>.md`, `app/**/route.ts`, `${CLAUDE_SKILL_DIR}/../../standards/<name>.md`.
52
- - A bare filename names a convention: `route.ts`, `manifest.toml`, `components.json`, `playwright.config.ts`. A bare name is read as a citation only when it matches a rule filename, which is how one authored rule would point at a sibling such as `605-worktrees.md`. A generated rule under `governance/rules/standards/` carries no number, so a bare name citing one is not read as a citation, and those rules name each other in prose instead.
52
+ - A bare filename names a convention: `route.ts`, `manifest.toml`, `components.json`, `playwright.config.ts`. A bare name is read as a citation only when it matches a rule filename, which is how one authored rule would point at a sibling such as `605-worktrees.md`.
53
53
  - A span carrying no file extension is a folder or a module specifier: `src/pages/`, `next/font`, `try/except`, `react-hooks/set-state-in-effect`, `oven-sh/setup-bun@v2`, `@/lib/utils`.
54
54
  - A fenced block displays a path rather than pointing at one.
55
55
 
@@ -9,7 +9,7 @@ description: Scenario routing, the expectation scoring surface, and the coverage
9
9
 
10
10
  ## Scenarios
11
11
 
12
- Scenarios live under `sandbox/`, one folder per category and one file per command, either a TypeScript module or a bash script, and provisioning refuses a command present in both forms. `sandbox/fixtures/` is the exception, holding file content that scenarios stage rather than scenarios of its own, so the picker and the coverage report both filter it out. That tree sits outside `files` in `package.json`, so an installed `canon` carries the command, reports it as toolkit-only on one line, and exits 1 rather than failing on the missing directory. Route non-interactively with `SANDBOX_SCENARIO`:
12
+ Scenarios live under `sandbox/`, one folder per category and one file per command, each a TypeScript module. `sandbox/fixtures/` is the exception, holding file content that scenarios stage rather than scenarios of its own, so the picker and the coverage report both filter it out. That tree sits outside `files` in `package.json`, so an installed `canon` carries the command, reports it as toolkit-only on one line, and exits 1 rather than failing on the missing directory. Route non-interactively with `SANDBOX_SCENARIO`:
13
13
 
14
14
  ```bash
15
15
  SANDBOX_SCENARIO=sync canon sandbox infra:tooling
@@ -47,7 +47,7 @@ Exit 0 means `pass` or `unchecked`. Exit 1 means `fail`, or a caller error: a ma
47
47
 
48
48
  ## Headless runs
49
49
 
50
- `canon sandbox run` provisions a scenario, drives one `claude -p` session over it, and scores the result with `canon sandbox check`. `sandbox/run.sh` is a wrapper that passes its arguments to the verb, so either spelling runs the same code.
50
+ `canon sandbox run` provisions a scenario, drives one `claude -p` session over it, and scores the result with `canon sandbox check`.
51
51
 
52
52
  ```bash
53
53
  canon sandbox run <category>:<command> "<prompt>" [arm]
@@ -93,7 +93,7 @@ The baseline is a detached worktree with full history, removed on exit including
93
93
 
94
94
  The record lists per arm `identical`, `differs` with the manifest keys that differ, `red-on-base` when both sides fail the same way, or `skipped-anchor`. It also carries `canonVersion`, `baseCommit`, `masksApplied`, `errors`, and `counts`. A declared arm adds a `check` entry from `canon sandbox check` on the head tree, whose `asserted` count shows its `expect.toml` resolved from `sandbox/fixtures/`.
95
95
 
96
- Exit 0 means every compared arm is identical or red the same way on both sides. Exit 1 means any `differs`, a base and head exit that disagree, an armed arm that `canon sandbox coverage` lists and enumeration lacks, a scenario present as both `.sh` and `.ts`, or a `.ts` scenario that fails to load.
96
+ Exit 0 means every compared arm is identical or red the same way on both sides. Exit 1 means any `differs`, a base and head exit that disagree, an armed arm that `canon sandbox coverage` lists and enumeration lacks, or a `.ts` scenario that fails to load.
97
97
 
98
98
  ## Scenario coverage
99
99
 
@@ -115,7 +115,7 @@ The record carries every scenario with the arms that declare, plus `totalScenari
115
115
 
116
116
  `--skills` answers what the scenario count cannot, which is whether anything can fail a given skill. It adds `skills`, `totalSkills`, `asserted`, `shouldBeAsserted`, `exempt`, `staleExemptions`, and `supersededExemptions` to the record, and keeps the scenario view rather than replacing it. The two denominators disagree on purpose: an armed scenario under `infra/` or `tooling/` exercises a CLI domain and pairs with no skill at all.
117
117
 
118
- A skill pairs to a scenario by filename, `<category>-<command>` first and bare `<command>` second, so `claude/target-setup.sh` reaches the `target-setup` skill. `should-be-asserted` is the default rather than a queue to drain, and which of those skills earns an arm is a project decision the census does not make.
118
+ A skill pairs to a scenario by filename, `<category>-<command>` first and bare `<command>` second, so `claude/target-setup.ts` reaches the `target-setup` skill. `should-be-asserted` is the default rather than a queue to drain, and which of those skills earns an arm is a project decision the census does not make.
119
119
 
120
120
  `exempt` means no arm should be written and holds only with a reason, declared in `sandbox/exempt.toml` and limited to a harness limit the checker cannot reach past or a skill that writes no artifact. An armed arm outranks an exemption. An exemption naming no shipped skill, or naming one an arm now asserts, exits 1 without `--strict`. Each armed arm reports as `<category>:<command>/<arm>`, so two same-named arms under different scenarios stay distinct.
121
121
 
@@ -15,7 +15,8 @@ Use these to discover what's available instead of hardcoding names.
15
15
  | --------------------------------- | ---------------------------------------------------------------- |
16
16
  | `canon tooling list --json` | Stacks, extends chain, dep and script counts |
17
17
  | `canon standards list --json` | Standards docs and the paths each governs |
18
- | `canon gov list --json` | Governance stacks, rule sets, and unreferenced rules |
18
+ | `canon gov list --json` | Governance stacks, rule sets, evidence, and unreferenced rules |
19
+ | `canon gov detect --json` | Opt-in rules a target's dependencies and paths propose |
19
20
  | `canon claude seeds list --json` | Seed doc sources with content |
20
21
  | `canon claude skills list --json` | Plugin skills, descriptions, requirement flag, family vocabulary |
21
22
  | `canon docs list --json` | Consumer docs plus per-domain context |
@@ -5,7 +5,7 @@ description: Measuring both skill corpora against the skill standards, the check
5
5
 
6
6
  # Skill audit
7
7
 
8
- `canon claude skills audit [path]` reports both skill corpora against the rules `standards/skill.md`, `claude/skills/create-skill/references/skill-requirement.md`, and `claude/skills/create-skill/references/skill-practice.md` state mechanically. It reads and reports. Fixing what it finds is separate work.
8
+ `canon claude skills audit [path]` reports both skill corpora against the rules `claude/skills/create-skill/references/skill.md`, `claude/skills/create-skill/references/skill-requirement.md`, and `claude/skills/create-skill/references/skill-practice.md` state mechanically. It reads and reports. Fixing what it finds is separate work.
9
9
 
10
10
  ```bash
11
11
  canon claude skills audit
@@ -83,7 +83,7 @@ The record carries `type`, `slug`, `branch`, `words`, and `conforms`. Exit codes
83
83
 
84
84
  `slug` is the plan filename with its `feature-` prefix and its extension taken off, and `type` is the constant `feat`. Reading a type off the plan's prose was the alternative, and it is the half of the derivation that has already disagreed with itself: one dispatch checked `fix/path-form-hook` against a worker that took `feat/path-form-hook`, both sides reading one plan. What makes the constant safe is that a branch type is cosmetic. `git-stage` reads a commit's type off the staged diff and `git-pr` reads a title off the diff, so the semantics a release reads never pass through the branch name. What it costs is a worktree listing where every plan-derived branch reads `feat/`, and nothing renames it later.
85
85
 
86
- `conforms` reads both caps `standards/branch.md` states, being 4 words on the description and 50 characters on the whole branch. A false reading is a row for a person rather than a name to shorten here, since a rename parts the branch slug from the plan slug that `session-worktree` tier 1 and `git-pr`'s plan lookup both read back.
86
+ `conforms` reads both caps `claude/skills/git-branch/references/branch.md` states, being 4 words on the description and 50 characters on the whole branch. A false reading is a row for a person rather than a name to shorten here, since a rename parts the branch slug from the plan slug that `session-worktree` tier 1 and `git-pr`'s plan lookup both read back.
87
87
 
88
88
  Both sides of a dispatch call it. The orchestrator's collision check derives its candidate here, and `auto-ship` Step 0 derives the worktree it enters from the same plan, so the branch a gate clears and the branch a session takes are one string by construction. They were two readings of one paragraph until 2026-09-06, when four dispatches on one plan produced three different strings.
89
89
 
@@ -118,7 +118,7 @@ It reads only what is written down, so it inherits the dispatch runbook's blindn
118
118
 
119
119
  A claim is only as current as the folder it was read from, and the live folder holds a plan whose work already shipped until something archives it. `canon tasks archive` moves a plan on merge, so a plan stranded by a run that never reached the archive keeps claiming its files against every branch afterwards. Check whether the holder is actually in flight before treating a claim as a collision: the first run of this verb on its own branch reported five paths held by a plan whose verb had already merged, and the whole reading came of a file nobody archived. `canon tasks validate` is what reports the stranded plan itself.
120
120
 
121
- `canon:git-ship` runs it at step 4, after `git add -A` and before the commit grouping. That is the first point the branch is whole and the last before a pull request exists to carry the answer.
121
+ `canon:git-ship` runs it at step 5, after `git add -A` and before the commit grouping. That is the first point the branch is whole and the last before a pull request exists to carry the answer.
122
122
 
123
123
  ```bash
124
124
  canon tasks plan-reach dispatch-answer-gate --json | jq -r '.claimed[] | "\(.path) held by \([.holders[].name] | join(", "))"'
@@ -27,7 +27,7 @@ Exit codes: `0` derived, `1` refused with `no-board`, `2` refused with `label-co
27
27
 
28
28
  The minor digit rolls from 9 to 0 on the next major rather than growing a second digit, which is the single-digit-minor shape every phase label already takes. `canon tasks archive` moves a task's file from the live folder into the archive without renumbering it, so the same label counts toward the maximum wherever it currently sits, and a label claimed by two different files folds into the same scan without a dedicated check.
29
29
 
30
- A claim is an exclusive `mkdir` at `.canon/ordinal-locks/<label>`, and the scan counts every reservation beside the task files, since the file lands after the verb returns. Reservations never expire, so a claim that died leaves a gap, which `standards/versioning.md` permits. A bare read still reports without reserving, and it does not count reservations either, so it can return a label a claim already holds until that claim's task file lands. Two bare reads in the same second can also take the same answer.
30
+ A claim is an exclusive `mkdir` at `.canon/ordinal-locks/<label>`, and the scan counts every reservation beside the task files, since the file lands after the verb returns. Reservations never expire, so a claim that died leaves a gap, which `claude/skills/git-commit/references/versioning.md` permits. A bare read still reports without reserving, and it does not count reservations either, so it can return a label a claim already holds until that claim's task file lands. Two bare reads in the same second can also take the same answer.
31
31
 
32
32
  ```bash
33
33
  canon tasks next-label --json | jq -r '.label'
@@ -60,7 +60,7 @@ canon tasks pull-request 673 --plan worktree-scratch-routing --json
60
60
 
61
61
  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.
62
62
 
63
- Run from a branch other than `main` or `master`, the verb also drops that branch from the task's `Pending branch:` line, along with every name its reflog says it was renamed from, and removes the line once it is empty. The renamed names matter because `git-ship` renames a nonconforming branch after `context-fold` wrote the marker. It does so on an `unchanged` run too, so a rerun repairs a marker left behind. The `pending` field lists the branches still on the line after the write.
63
+ Run from a branch other than `main` or `master`, the verb also drops that branch from the task's `Pending branch:` line, along with every name its reflog says it was renamed from, and removes the line once it is empty. The renamed names matter because `git-ship` renames a nonconforming branch after `task-complete` wrote the marker. It does so on an `unchanged` run too, so a rerun repairs a marker left behind. The `pending` field lists the branches still on the line after the write.
64
64
 
65
65
  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.
66
66
 
@@ -64,9 +64,11 @@ Twenty-five plugin skills dropped their `claude-` prefix for two-word names, so
64
64
 
65
65
  The same sweep carries the merge of the five per-kind document drafters into `draft-doc`, so a citation of any one of them lands on `canon:draft-doc`.
66
66
 
67
- Fourteen skills, one verb, and one rule were retired without a rename, so the sweep has nothing to map them to and leaves a citation of one as it stands. `design-extract` and `sketch-design` are replaced by `canon:canvas`, which carries a picked direction into `canon/DESIGN.md`. `review-branch`, `seed-sync`, `restate-plainly`, `bash-cli-script`, `canon-operator`, `canon-rollout`, `create-standard`, `markdown-propose`, `memory-review`, `project-commands`, `repo-metadata`, and `ux-walkthrough` have no successor. `canon repo metadata` went with `repo-metadata`, and `canon autoship` went with `review-branch`, whose review step it served. The `120-bash` rule left the `base` stack, so `canon gov sync` removes its installed copy. Replace each citation by hand, or delete the sentence naming a skill that has no successor. <!-- canon-keep-retired -->
67
+ The one skill that took a two-word name from a single word is `canvas`, now `canvas-board`. A bare `canvas` is ordinary prose and the name of a verb, so the sweep rewrites only the forms the skill alone spells, `canon:canvas` and `skills/canvas`. A prose mention of the skill by its bare name stays, so replace it by hand. <!-- canon-keep-retired -->
68
68
 
69
- The memory system retired the same way. `memory-capture`, the `603-memory` rule, and the `memory` standard have no successor, and a citation of any one is replaced by hand or deleted. Ship chains no longer capture a session's lessons, so a lesson goes to the context entry that owns the fact, or to a task's findings. The `canon records` memory kind stays, so a project can still validate, back up, and migrate a folder it holds. <!-- canon-keep-retired -->
69
+ Fourteen skills, one verb, and one rule were retired without a rename, so the sweep has nothing to map them to and leaves a citation of one as it stands. `design-extract` and `sketch-design` are replaced by `canon:canvas-board`, which carries a picked direction into `canon/DESIGN.md`. `review-branch`, `seed-sync`, `restate-plainly`, `bash-cli-script`, `canon-operator`, `canon-rollout`, `create-standard`, `markdown-propose`, `memory-review`, `project-commands`, `repo-metadata`, and `ux-walkthrough` have no successor. `canon repo metadata` went with `repo-metadata`, and `canon autoship` went with `review-branch`, whose review step it served. The `120-bash` rule left the `base` stack, so `canon gov sync` removes its installed copy. Replace each citation by hand, or delete the sentence naming a skill that has no successor. <!-- canon-keep-retired -->
70
+
71
+ The memory system retired the same way. `memory-capture`, the `603-memory` rule, and the `memory` standard have no successor, and a citation of any one is replaced by hand or deleted. Ship chains no longer capture a session's lessons, so a lesson goes to the context entry that owns the fact, or to a task's findings. The `memory` record kind left `canon records` with it, and so did `canon records migrate`, whose one transform repaired a memory record. `canon records validate memory` and `canon records stale memory` now refuse as an unknown kind, and `canon records migrate` is an unknown command. A target that upgrades the CLI while a pre-retirement plugin still runs `memory-review` gets that refusal, which is the intended outcome. A `.canon/memory/` folder a target holds is still backed up by `canon records push`. <!-- canon-keep-retired -->
70
72
 
71
73
  An installed target keeps its `.canon/memory/` folder and the memory arms of its seeded `records-index.sh` and `standards-audit.sh` hooks, since `canon claude sync` writes only a seed a target lacks. Both are inert: nothing writes the folder, and the hooks match no file. `canon gov sync` removes the installed `603-memory` rule and the generated `memory` standard rule.
72
74
 
@@ -85,6 +87,12 @@ Run the second line once per stack the project holds, since the two hooks above
85
87
 
86
88
  The order carries the reason. A sync replaces each toolkit-owned copy with one already carrying the new names, and the sweep afterwards reaches the prose the project wrote itself. Sweeping first rewrites those installed files in place, which moves them off the hash the install recorded, so the next sync reads them as edited by the project and leaves them alone.
87
89
 
90
+ ## Rename the pull request template headings, once
91
+
92
+ The pull request section headings moved to sentence case, so the template seeds `## Key changes` and `## Technical context`. `canon labels scan` now fails a body whose level-two heading is outside the closed list, and it compares case exactly, so a body written under the old `## Key Changes` heading fails the pull request gate.
93
+
94
+ A project scaffolded earlier holds the old template at `.github/pull_request_template.md`, and a sync writes only a seed a target lacks. Rename the two headings in that file by hand, or delete it and run `canon tooling sync base . --write` to take the new seed. Do it ahead of the first pull request after `canon upgrade`. `canon pr key-changes` reads either casing, so a body already open keeps parsing, and only the scan needs the rename on its next edit.
95
+
88
96
  ## Move the surfaces off `.claude/`, once
89
97
 
90
98
  Tracked surfaces moved out of `.claude/` and into a root of their own. `context/`, `wireframes/`, the three loose documents (`ARCHITECTURE.md`, `REQUIREMENTS.md`, `DESIGN.md`), and the install stamp folder, respelled `canon/config/`, now live under `canon/`, and `rules/`, `skills/`, `hooks/`, and `settings.json` stay put since Claude Code reads those by path.
@@ -51,7 +51,7 @@ claude --plugin-dir <toolkit>/claude
51
51
  Two steps, in order:
52
52
 
53
53
  1. Run the framework's own scaffold if the project needs one, such as `bun init`, `npm create vite`, or `npm create astro`. The toolkit does not wrap framework scaffolding.
54
- 2. Invoke `canon:target-setup` in Claude Code. The skill detects the stack, resolves flags, previews the full chain, and runs it end-to-end.
54
+ 2. Invoke `canon:target-setup` in Claude Code. The skill detects the stack, asks `canon gov detect` which opt-in rules the project's evidence proposes, previews the full chain with those proposals for you to confirm, and runs it end-to-end.
55
55
 
56
56
  The chain is:
57
57
 
@@ -72,7 +72,7 @@ Keep the `## Scripts` table in `canon/context/development.md` current as scripts
72
72
  Scaffold installs tooling and seeds. It does not fill the planning docs or the design system. Complete those before the first feature session:
73
73
 
74
74
  1. Fill `canon/REQUIREMENTS.md`. The seed asks for the problem in one line, then goals and non-goals, and the scope is yours to write. The seed states its own cap of 600 words, and `canon context audit` gates on it. Edit the number in the record to loosen it. A decision about how the project is built goes in the `canon/context/` entry of the domain it constrains.
75
- 2. For a UI project, write `canon/DESIGN.md` from the seed template, or work the direction out with `canon:canvas` and carry the pick in. Skip for non-UI projects.
75
+ 2. For a UI project, write `canon/DESIGN.md` from the seed template, or work the direction out with `canon:canvas-board` and carry the pick in. Skip for non-UI projects.
76
76
  3. Optionally invoke `canon:draft-figure` naming an architecture view, such as system context or components, and the document it belongs in. It draws the view from the context index, the folder layout, and the requirements and renders it to verify the layout, which downloads the Mermaid CLI on first use and takes about 15 seconds.
77
77
  4. Start the feature loop. See [AI workflow](../workflow/ai-workflow.md) for the per-feature sequence.
78
78
 
@@ -88,7 +88,7 @@ Escalate only for real web apps. The `target-setup` skill reads `package.json` a
88
88
 
89
89
  In a monorepo the skill reads each folder holding a `package.json`, `pyproject.toml`, `go.mod`, `composer.json`, or `Cargo.toml` to depth two, skipping what git ignores. Each of those folders gets its own tooling stack and a `canon tooling sync <stack> <folder> --skip base` in the preview. Governance still installs once at the root, since a rule's `paths:` globs reach every subfolder, so a subfolder's language rules join the root install through `--add`.
90
90
 
91
- `node-server` is named rather than detected. It carries the server-side security and persistence rules for a project writing request handlers or a persistence layer in TypeScript, and the detect step matches a runtime or a framework against stack names, so nothing there marks a project as a backend. Pass it deliberately with `canon init --stack node-server` or `canon gov install node-server <target>`.
91
+ `node-server` is named rather than detected. It carries the server-side security and persistence rules for a project writing request handlers or a persistence layer in TypeScript, and the detect step matches a runtime or a framework against stack names, so the stack never resolves on its own. `canon gov detect` proposes its two rules from a server framework or database client in the manifest, which you confirm in the preview. Pass the stack deliberately with `canon init --stack node-server` or `canon gov install node-server <target>`.
92
92
 
93
93
  Markdown-heavy projects, CLI tools, docs sites, research notebooks, and scripting repos stay on `base`. Escalation is a ceiling move, not a default.
94
94
 
@@ -113,7 +113,7 @@ The plugin corpus carries runtime behavior rather than reference prose alone, be
113
113
 
114
114
  When a new need appears after scaffold, install the one domain without re-running `canon init`.
115
115
 
116
- - Governance rule for a newly adopted library: invoke `canon:target-setup gov`, or run `canon gov install <stack> --add <rule> <path>`
116
+ - Governance rule for a newly adopted library: run `canon gov detect <path> --json` to see what the project's evidence proposes, then `canon gov install --add <rule> <path>`, which installs the rule with no stack
117
117
  - 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.
118
118
  - Index.md system for a markdown-heavy folder that emerged: invoke `canon:target-setup indexes`
119
119
 
@@ -78,7 +78,7 @@ Standards take no part in that run. Nothing installed them, so there is no copy
78
78
 
79
79
  - Claude seed docs such as `CLAUDE.md` and `canon/REQUIREMENTS.md`: merge by hand against the toolkit copy, section by section, keeping the project's customizations. A `stale` seed is safe to take whole.
80
80
  - Governance rules already installed: `canon gov sync <path>` diffs and applies, and never adds new rules. A rule your recorded stack lists reports as `missing` instead.
81
- - Tooling configs and seeds: `canon tooling <stack> <path>` overwrites golden configs and merges seeds
81
+ - Tooling configs and seeds: `canon tooling <stack> <path>` overwrites golden configs and merges dictionary seeds, and drops every other seed once
82
82
  - Reference docs for a stack: `canon tooling reference <stack>` reads and never writes, so there is nothing to sync
83
83
  - Index regeneration after markdown edits: `canon indexes regen`
84
84
 
@@ -97,10 +97,10 @@ The human read at merge is the final gate. No layer repeats another.
97
97
  The orchestrator's pass also reads the pull request body against itself, which is
98
98
  a vantage the worker never has. This repository squash-merges, so the body
99
99
  becomes the commit message and the record on the trunk once the branch is gone.
100
- `canon pr key-changes` compares the paths the body's Key Changes claims against
100
+ `canon pr key-changes` compares the paths the body's Key changes claims against
101
101
  its own changed-file list, and a claim the diff does not carry is a finding on
102
102
  the body rather than on a file. See
103
- [Key Changes bijection](../agents/key-changes.md).
103
+ [Key changes bijection](../agents/key-changes.md).
104
104
 
105
105
  ## The review channel
106
106
 
@@ -38,23 +38,23 @@ The plan's shape is fixed by `claude/skills/plan-feature/references/plan.md`: th
38
38
 
39
39
  An execution that picks other than the suggestion rewrites the `- Suggested:` line as `overridden at execution to <pick>,` followed by the measurement that moved it, and leaves the slot blank. That fixed phrase is how a reader of the archived plan tells an override from a suggestion the execution accepted, since an authored suggestion often carries a number of its own. The same deviation takes one line in the open task's `## Findings`, which is the register that survives the plan being archived. A deviation from a question somebody already answered goes back to whoever answered it instead, since a filled slot is a decision already made.
40
40
 
41
- `canon records validate plans` reports where a plan and that standard disagree: a filename that is not `feature-<slug>.md`, a missing required section, a files-to-touch entry naming no file, and a question carrying a suggestion with no answer slot. The same verb takes `groundwork`, `intake`, `memory`, and `teach`, which are governed the same way and were unreachable for the same reason. Nothing fires it automatically, because all five folders are gitignored and every check the repository runs reads changed files from git. It reports and never writes, since the folders are per-machine scratch with no history to recover a wrong repair from.
41
+ `canon records validate plans` reports where a plan and that standard disagree: a filename that is not `feature-<slug>.md`, a missing required section, a files-to-touch entry naming no file, and a question carrying a suggestion with no answer slot. The same verb takes `groundwork`, `intake`, and `teach`, which are governed the same way and were unreachable for the same reason. Nothing fires it automatically, because all four folders are gitignored and every check the repository runs reads changed files from git. It reports and never writes, since the folders are per-machine scratch with no history to recover a wrong repair from.
42
42
 
43
43
  `canon records push` carries these folders off the disk they live on, and `canon records pull` brings them back. Every top-level entry under `.canon/` is backed except `tmp`, `ordinal-locks`, and `.records.git`, so a folder added later enters the payload on its own rather than waiting on a name written into a list. Push names each folder it carries the first time it sees it, which is what keeps a stray folder visible instead of silently entering the payload. It refuses the whole push, naming each path, when a new or changed file is over 25 MB or carries a credential `canon secrets scan` would report. The history lives in a second git directory at `.canon/.records.git` with `.canon/` as its work tree, so every path a task file cites stays where it is.
44
44
 
45
45
  A person points it at a private repository once and both verbs refuse until they have, and `push` refuses when that origin is also a remote of the project, since the payload is the task board and the groundwork trails. `.husky/post-merge` runs the push after its archive loop, on every merge rather than only on one that closed a task. See [records push](../agents/records-push.md) for the refusal table.
46
46
 
47
- `canon records size` reports what each of these folders holds, heaviest first, along with `.canon/tmp`. Each row carries the file count, the bytes, how many files were written in the last 7 and 30 days, and the dates of the least and most recently written one. Nothing fails on a number, because a record folder has no correct size. What the verb replaces is a reading somebody had to remember to take: the memory pen went from 44 entries to 236 between two counts made by hand a fortnight apart, and nothing reported the rate in between.
47
+ `canon records size` reports what each of these folders holds, heaviest first, along with `.canon/tmp`. Each row carries the file count, the bytes, how many files were written in the last 7 and 30 days, and the dates of the least and most recently written one. Nothing fails on a number, because a record folder has no correct size. What the verb replaces is a reading somebody had to remember to take: a pen went from 44 entries to 236 between two counts made by hand a fortnight apart, and nothing reported the rate in between.
48
48
 
49
49
  `canon records prune-tmp` reports scratch under `.canon/tmp` nobody has touched inside an age window, and deletes it only with `--write`. A `tmp/handoff/` folder and the live `tmp/pr/poll/` baseline are never offered, since a reader deletes a handoff once it is read and a poll baseline is state a session still needs. See [records](../agents/records.md) for the candidate shapes and the exit codes.
50
50
 
51
- `canon records stale memory` reads the memory pen as a review queue. It names each entry due for review, meaning one carrying no `reviewed` date or one older than 30 days, and every backticked path an entry cites that the tree no longer holds. Due entries come first, with the ones citing a missing path ahead of the rest, so a review takes the first batch rather than the whole pen. It writes nothing. See [records stale](../agents/records-stale.md) for how a path is read and the refusals.
51
+ `canon records stale canonical` reports when the requirements record was last reviewed and how many releases have shipped since, so a review of it starts from a count rather than from the tag list. It writes nothing. See [records stale](../agents/records-stale.md) for how the count is taken and the refusals.
52
52
 
53
53
  A plan that ships is archived, never deleted. `canon tasks archive` moves it to `.canon/plans/archive/` alongside the task it belonged to and retargets that task's `Plan:` line at the new location, so a completed task still leads to the reasoning behind it. An archive sits inside the record folder it archives rather than beside it, so one ignore entry and one backed-folder entry cover a record and everything it has retired. The folder is gitignored, which is why a deleted plan had no recovery path. A plan cited by more than one task stays put until the last of them closes, since moving it early would strand every other pointer.
54
54
 
55
- An older branch review report takes the other route and is swept rather than archived. It sits flat in `.canon/review/` as `branch-<slug>.md`, the session addressing it read it once, and the durable record of what a review found is the comment `review-pr` posts on the pull request, so `context-fold` deletes any report whose branch is gone. The body that writes a report owns how long it lives, which leaves the shipping branch's own report on disk through the run that cites it and collects it a branch later. What that loses is a local-only review on a branch that never opened a pull request, which is why the report says so where a reader meets it.
55
+ An older branch review report takes the other route and is swept rather than archived. It sits flat in `.canon/review/` as `branch-<slug>.md`, the session addressing it read it once, and the durable record of what a review found is the comment `review-pr` posts on the pull request, so `canon:task-complete` deletes any report whose branch is gone. The body that writes a report owns how long it lives, which leaves the shipping branch's own report on disk through the run that cites it and collects it a branch later. What that loses is a local-only review on a branch that never opened a pull request, which is why the report says so where a reader meets it.
56
56
 
57
- `canon:context-fold` decides which task closed by reading the diff rather than the conversation. It resolves a merge base against `origin/main`, unions the committed diff with the working tree and untracked files, then matches unchecked outcomes on the board against what shipped. A task that shipped without ever being discussed still gets marked. Decisions and design stay session-sourced, because a diff cannot carry a judgment. The requirements record is never folded. A direction change gets one report line naming `canon:document-health`, which reviews that record only when asked.
57
+ `canon:task-complete` decides which task closed by reading the diff rather than the conversation, as the ship-chain step after `canon:context-fold`. It resolves a merge base against `origin/main`, unions the committed diff with the working tree and untracked files, then matches unchecked outcomes on the board against what shipped. A task that shipped without ever being discussed still gets marked. Decisions stay session-sourced, because a diff cannot carry a judgment, and `canon:context-fold` folds them into the context entries. The requirements record is never folded. A direction change gets one report line naming `canon:document-health`, which reviews that record only when asked.
58
58
 
59
59
  ## Shipping a fan-out
60
60
 
@@ -87,12 +87,12 @@ A hand-maintained `priority.md` sits beside the index carrying execution order a
87
87
 
88
88
  Past that shape, it checks what a surviving row claims against what the tree holds: every plan pointer resolves, every task file is named by a board row or a backlog line and never by both, no task sits in two groups, and every row marked ready names its files. One check across both surfaces is what lets a task move between the board and the backlog without the move reading as a dropped file. Paths two ready rows share go to a `shared` array moving no exit code, the candidate list the orchestrator's conflict check reads. Blockers re-takes what a parked row waits on, reporting one whose cited task reached the trunk and one whose cited file nothing running still holds. A cited task settles the row by being archived, or by closing every outcome and naming a pull request the trunk carries, since the checkbox alone is marked while the branch is still in review. Both halves read a citation out of the blocker cell, so a row citing neither is reported as untested rather than counted clean, and so is a cited task the trunk could not answer for. It reports and never writes, because a row is the orchestrator's claim and a validator repairing one would assert the claim it exists to test. Nothing fires it automatically, since the board is gitignored per-machine scratch with no shared moment to hang a hook on, so the orchestrator's sweep calls it at the point the readiness claim is made and follows it with the parked re-test.
89
89
 
90
- `canon:task-board` owns the two operations that bracket a task's life. It creates the file, holding the filename convention and the frontmatter contract so a malformed write cannot break the index for every sibling, and it moves a shipped task to `.canon/tasks/archive/`. Creation is where the origin invariant is enforced: every task names a plan, a groundwork folder, an intake folder, or an issue, since a task with no origin is either lost context or work nobody decided to do.
90
+ `canon:task-board` creates the file, holding the filename convention and the frontmatter contract so a malformed write cannot break the index for every sibling, and declines a task decided against. `canon:task-complete` marks a shipped task's outcomes and moves one the merge hook left to `.canon/tasks/archive/`. Creation is where the origin invariant is enforced: every task names a plan, a groundwork folder, an intake folder, or an issue, since a task with no origin is either lost context or work nobody decided to do.
91
91
 
92
92
  Archiving a task carries its plan with it, in the same act. The merge is what settles a plan, and the hook below reaches the archive with nobody watching, so a second call after it would be a second failure point leaving the task archived and the plan live. A task whose plan a sibling still cites archives on its own and leaves the plan live, since moving it on the first task to close strands every other pointer at a path that has gone.
93
93
 
94
94
  Nothing chained that archive until the `post-merge` git hook landed. Every earlier step fires from `canon:auto-ship` or `canon:git-ship`, both of which finish while the pull request is still open, so a task archived there would close for work that may be abandoned. The board is gitignored, which rules out reading it from anywhere but the machine that pulled. The hook archives the task a merged pull request closed, through the same verb the base stack ships to every target, and does nothing on a project with no board.
95
95
 
96
- The archive gates on a pull request number the merge carried and a closed task, because outcomes are marked on the branch and a task can read all `[x]` while its pull request is still open, so `canon:task-board` still confirms the work reached `main` when a person archives by hand. A companion `post-rewrite` hook carries the same steps for anyone pulling with rebase, which fires that event instead of `post-merge`.
96
+ The archive gates on a pull request number the merge carried and a closed task, because outcomes are marked on the branch and a task can read all `[x]` while its pull request is still open, so `canon:task-complete` still confirms the work reached `main` when a person archives by hand. A companion `post-rewrite` hook carries the same steps for anyone pulling with rebase, which fires that event instead of `post-merge`.
97
97
 
98
98
  The hook archives through `canon tasks archive`, which carries the refusals above, so a task whose pull request has not merged stays where it is. Both hooks ship with the `base` tooling stack, so a target project running this workflow gets the same trigger, and `CANON_SKIP_RECLAIM`, `CANON_SKIP_UPGRADE`, and `CANON_SKIP_PLUGIN_UPDATE` turn off the three steps that act on the machine.
@@ -25,15 +25,15 @@ These two groups hold the skills no single moment in a project's life calls for,
25
25
 
26
26
  ## Answer a question at any point
27
27
 
28
- | Skill | When to use |
29
- | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
30
- | `canon:canon-cli` | Before running an unfamiliar verb, a sync, or an install, to learn which command to run, which reference doc covers it, or what it overwrites, merges, or leaves alone |
31
- | `canon:youtube-transcripts` | When a video transcript is wanted in the repo as context |
32
- | `canon:read-frames` | To read a recorded demo back frame by frame and report what each one shows, with no verdict on whether the recording looks right |
33
- | `canon:teach-workspace` | To learn a subject across sessions, in a workspace that holds the progress |
34
- | `canon:markdown-craft` | Before a substantial markdown edit, for the format and structure rules and the audit that follows |
35
- | `canon:write-human` | Before drafting or revising prose, for voice, rhythm, and density |
28
+ | Skill | When to use |
29
+ | --------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
30
+ | `canon:canon-cli` | To pick the `canon` verb that does a job, or before a sync or migrate, to learn which verbs can lose the project's edits |
31
+ | `canon:youtube-transcripts` | When a video transcript is wanted in the repo as context |
32
+ | `canon:read-frames` | To read a recorded demo back frame by frame and report what each one shows, with no verdict on whether the recording looks right |
33
+ | `canon:teach-workspace` | To learn a subject across sessions, in a workspace that holds the progress |
34
+ | `canon:markdown-craft` | Before a substantial markdown edit, for the format and structure rules and the audit that follows |
35
+ | `canon:write-human` | Before drafting or revising prose, for voice, rhythm, and density |
36
36
 
37
37
  Every row answers a question rather than marking a point in a project's life, so filing one under a phase on the [skill map](skill-map.md) would send a reader to the wrong group.
38
38
 
39
- A learning workspace produces two halves and only one of them leaves. A lesson is worked through once and stays in the workspace, and a reference page or a glossary carries no learner, so it belongs wherever the project already keeps prose on that subject. Asking `canon:teach-workspace` to promote sorts each durable page by who owns its subject, sending an Anthropic-owned subject to the wiki, an internal one to the matching context entry, and everything else, subject-neutral material included, to the public docs. It proposes and waits, because a promoted page is public prose that needs a line naming who owns the subject, and it writes nothing to a destination: each page the operator confirms goes to a handoff file that `canon:context-fold` folds in from a branch. A project with no wiki folder gets a refusal naming `canon wiki init` rather than a folder it never asked for.
39
+ A learning workspace produces two halves and only one of them leaves. A lesson is worked through once and stays in the workspace, and a reference page or a glossary carries no learner, so it belongs wherever the project already keeps prose on that subject. Asking `canon:teach-workspace` to promote sorts each durable page by who owns its subject, sending an Anthropic-owned subject to the wiki, an internal one to the matching context entry, and everything else, subject-neutral material included, to the public docs. It proposes and waits, because a promoted page is public prose that needs a line naming who owns the subject, and it writes nothing to a destination: each page the operator confirms goes to a handoff file that `canon:teach-workspace` folds in from a branch in its fold mode. A project with no wiki folder gets a refusal naming `canon wiki init` rather than a folder it never asked for.
@@ -29,8 +29,8 @@ Each row sits under the group its skill's `metadata.family` names. The landing p
29
29
  | `canon:plan-groundwork` | When the state is unmeasured and more than one approach is live |
30
30
  | `canon:decision-escalate` | When open decisions turn on your preference and want batching into one set |
31
31
  | `canon:draft-and-pick` | When the call is taste and wants several candidates rendered side by side |
32
- | `canon:canvas` | When a direction should be drawn as frames the operator can see, select, and edit |
33
- | `canon:task-board` | When a decided item needs a file on the board, or a shipped one needs archiving |
32
+ | `canon:canvas-board` | When a direction should be drawn as frames the operator can see, select, and edit |
33
+ | `canon:task-board` | When a decided item needs a file on the board, or one is decided against |
34
34
  | `canon:plan-feature` | When the approach is settled and the next step is a plan |
35
35
  | `canon:codebase-layout` | When a plan or change adds a file and you need to decide which folder holds it |
36
36
 
@@ -63,15 +63,16 @@ Each row sits under the group its skill's `metadata.family` names. The landing p
63
63
 
64
64
  ## Ship it
65
65
 
66
- | Skill | When to use |
67
- | -------------------- | ---------------------------------------------------------------------------------- |
68
- | `canon:git-ship` | To run the whole post-feature chain from the verify gate through open PR |
69
- | `canon:context-fold` | When decisions diverged from the plan, or a shipped task needs its outcomes marked |
70
- | `canon:docs-sync` | When a change since main left `README.md` or `docs/` stale |
71
- | `canon:git-stage` | When the staged set spans several concerns and wants one commit each |
72
- | `canon:git-commit` | When the staged set is one concern, or was staged hunk by hand |
73
- | `canon:git-branch` | When a branch name needs generating or renaming to conventional form |
74
- | `canon:git-pr` | When a pull request needs a title and body written from the diff |
66
+ | Skill | When to use |
67
+ | --------------------- | ----------------------------------------------------------------------------------------------- |
68
+ | `canon:git-ship` | To run the whole post-feature chain from the verify gate through open PR |
69
+ | `canon:context-fold` | When decisions diverged from the plan, or the diff left a context entry stale |
70
+ | `canon:task-complete` | After the fold, to mark the outcomes the diff shipped, or to archive a task the merge hook left |
71
+ | `canon:docs-sync` | When a change since main left `README.md` or `docs/` stale |
72
+ | `canon:git-stage` | When the staged set spans several concerns and wants one commit each |
73
+ | `canon:git-commit` | When the staged set is one concern, or was staged hunk by hand |
74
+ | `canon:git-branch` | When a branch name needs generating or renaming to conventional form |
75
+ | `canon:git-pr` | When a pull request needs a title and body written from the diff |
75
76
 
76
77
  ## After the pull request opens
77
78
 
@@ -20,7 +20,7 @@ Claude Code reads it and writes the implementation. Works for CLI tools, interna
20
20
 
21
21
  ### Seed shape
22
22
 
23
- The toolkit seed in `tooling/claude/seeds/canon/DESIGN.md` ships a token-table template with a starting set of roles, and `standards/design.md` carries the same tables under `## Template` with placeholder rows. The column headers are what the renderer parses, so they stay verbatim in either, while the rows and values are the project's own.
23
+ The toolkit seed in `tooling/claude/seeds/canon/DESIGN.md` ships a token-table template with a starting set of roles, and `claude/skills/canvas-board/references/design.md` carries the same tables under `## Template` with placeholder rows. The column headers are what the renderer parses, so they stay verbatim in either, while the rows and values are the project's own.
24
24
 
25
25
  `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/index.md`.
26
26
 
@@ -39,7 +39,7 @@ A cell no source anchors ends in `? verify`, and the preview shows that marker b
39
39
  - `canon:ux-audit` for UX gap detection on existing surfaces
40
40
  - `canon:ux-measure` for what a running surface costs to paint, read against published thresholds
41
41
  - `canon:draft-and-pick` for a call settled by looking, drafting several candidates as frames on the canvas and taking your pick
42
- - `canon:canvas` for a direction worked out over several turns, drawn as HTML frames you drag, select, and restyle in the browser while the session reads your changes back. Only the pick moves into `canon/DESIGN.md`, since the canvas folder is gitignored
42
+ - `canon:canvas-board` for a direction worked out over several turns, drawn as HTML frames you drag, select, and restyle in the browser while the session reads your changes back. Only the pick moves into `canon/DESIGN.md`, since the canvas folder is gitignored
43
43
  - `canon:draft-identity` to draft a project's logo mark and compose it into an icon sequence and a social card, through `draft-and-pick`'s own render-and-pick loop. On an Astro project holding the card route scaffold, the card lands as a route the project keeps and is captured through a running server, so it reads the project's real stylesheet rather than typed copies of every color. Everywhere else it ships as a PNG and the run says so.
44
44
  - Anthropic's `frontend-design` plugin optional for light visual steering
45
45