@erclx/canon 5.41.0 → 5.43.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 (220) hide show
  1. package/claude/.claude-plugin/plugin.json +1 -1
  2. package/claude/skills/api-design/references/adopted.md +34 -14
  3. package/claude/skills/auto-ship/REQUIREMENT.md +1 -0
  4. package/claude/skills/auto-ship/SKILL.md +24 -4
  5. package/claude/skills/auto-ship/references/draft-mark.md +32 -6
  6. package/claude/skills/auto-ship/references/failure-recovery.md +15 -13
  7. package/claude/skills/auto-ship/references/tier-failures.md +31 -10
  8. package/claude/skills/auto-ship/references/ui-checklist.md +9 -4
  9. package/claude/skills/auto-ship/references/worktree-name.md +9 -3
  10. package/claude/skills/build-in-slices/references/adopted.md +35 -21
  11. package/claude/skills/canvas-board/references/canvas.md +17 -6
  12. package/claude/skills/canvas-board/references/design.md +26 -7
  13. package/claude/skills/ci-workflow/REQUIREMENT.md +2 -1
  14. package/claude/skills/ci-workflow/SKILL.md +12 -2
  15. package/claude/skills/ci-workflow/references/workflows.md +12 -9
  16. package/claude/skills/code-craft/references/adopted.md +58 -20
  17. package/claude/skills/codebase-layout/references/adopted.md +49 -16
  18. package/claude/skills/codebase-layout/references/frontend.md +11 -4
  19. package/claude/skills/codebase-layout/references/tests.md +4 -2
  20. package/claude/skills/context-fold/references/classify.md +10 -15
  21. package/claude/skills/context-fold/references/completion-report.md +11 -9
  22. package/claude/skills/context-fold/references/context-refresh.md +26 -9
  23. package/claude/skills/context-fold/references/unusable-baseline.md +5 -3
  24. package/claude/skills/create-rule/REQUIREMENT.md +5 -0
  25. package/claude/skills/create-rule/SKILL.md +10 -1
  26. package/claude/skills/create-rule/references/checklist.md +26 -0
  27. package/claude/skills/create-rule/references/rule.md +98 -20
  28. package/claude/skills/create-skill/SKILL.md +1 -0
  29. package/claude/skills/create-skill/references/skill-disclosure.md +10 -2
  30. package/claude/skills/create-skill/references/skill-frontmatter.md +43 -0
  31. package/claude/skills/create-skill/references/skill-paths.md +7 -4
  32. package/claude/skills/create-skill/references/skill-practice.md +6 -3
  33. package/claude/skills/create-skill/references/skill-requirement.md +4 -2
  34. package/claude/skills/create-skill/references/skill.md +67 -44
  35. package/claude/skills/decision-escalate/SKILL.md +1 -2
  36. package/claude/skills/deploy-app/references/vercel.md +2 -1
  37. package/claude/skills/deprecation-migration/references/adopted.md +44 -25
  38. package/claude/skills/design-taste/references/adopted.md +9 -1
  39. package/claude/skills/design-taste/references/craft.md +3 -1
  40. package/claude/skills/design-taste/references/kinds.md +8 -7
  41. package/claude/skills/design-taste/references/preflight.md +12 -0
  42. package/claude/skills/design-taste/references/systems.md +7 -6
  43. package/claude/skills/design-taste/references/tells.md +24 -25
  44. package/claude/skills/design-taste/references/vocabulary.md +7 -5
  45. package/claude/skills/document-health/references/axes.md +55 -30
  46. package/claude/skills/draft-and-pick/references/live-arms.md +2 -2
  47. package/claude/skills/draft-doc/references/context.md +4 -3
  48. package/claude/skills/draft-doc/references/docs.md +6 -3
  49. package/claude/skills/draft-doc/references/readme/agent-facing.md +6 -0
  50. package/claude/skills/draft-doc/references/readme/application.md +8 -2
  51. package/claude/skills/draft-doc/references/readme/cli.md +5 -1
  52. package/claude/skills/draft-doc/references/readme/library.md +4 -0
  53. package/claude/skills/draft-doc/references/readme/plugin.md +9 -1
  54. package/claude/skills/draft-doc/references/readme.md +30 -13
  55. package/claude/skills/draft-doc/references/requirements.md +17 -4
  56. package/claude/skills/draft-doc/references/wiki-kind.md +20 -10
  57. package/claude/skills/draft-doc/references/wiki.md +1 -1
  58. package/claude/skills/draft-figure/references/architecture-set.md +7 -3
  59. package/claude/skills/draft-figure/references/figures.md +8 -6
  60. package/claude/skills/draft-figure/references/hand-drawn.md +3 -1
  61. package/claude/skills/draft-figure/references/mermaid-path.md +19 -9
  62. package/claude/skills/draft-figure/references/mermaid.md +10 -5
  63. package/claude/skills/draft-ready/references/ready.md +22 -15
  64. package/claude/skills/git-branch/references/branch.md +11 -1
  65. package/claude/skills/git-branch/references/slug.md +17 -5
  66. package/claude/skills/git-commit/references/commit.md +9 -5
  67. package/claude/skills/git-commit/references/versioning.md +23 -17
  68. package/claude/skills/git-followup/REQUIREMENT.md +1 -1
  69. package/claude/skills/git-followup/SKILL.md +5 -6
  70. package/claude/skills/git-issue/references/issue.md +29 -16
  71. package/claude/skills/git-pr/REQUIREMENT.md +1 -5
  72. package/claude/skills/git-pr/SKILL.md +11 -22
  73. package/claude/skills/git-pr/references/final-command.md +21 -8
  74. package/claude/skills/git-pr/references/labels.md +45 -28
  75. package/claude/skills/git-pr/references/pr.md +29 -9
  76. package/claude/skills/git-pr/references/publish.md +42 -28
  77. package/claude/skills/git-pr/references/task-number.md +20 -8
  78. package/claude/skills/git-ship/SKILL.md +1 -1
  79. package/claude/skills/plan-feature/SKILL.md +1 -1
  80. package/claude/skills/plan-feature/references/plan-lifecycle.md +10 -3
  81. package/claude/skills/plan-feature/references/plan.md +58 -21
  82. package/claude/skills/plan-groundwork/references/groundwork-spikes.md +4 -1
  83. package/claude/skills/plan-groundwork/references/groundwork.md +14 -16
  84. package/claude/skills/plan-intake/references/intake.md +29 -24
  85. package/claude/skills/pr-evidence/REQUIREMENT.md +40 -0
  86. package/claude/skills/pr-evidence/SKILL.md +53 -0
  87. package/claude/skills/pr-evidence/references/evidence.md +150 -0
  88. package/claude/skills/review-address/references/post-review-findings.md +10 -3
  89. package/claude/skills/review-address/references/rebase-conflicts.md +15 -7
  90. package/claude/skills/review-address/references/rest-reads.md +3 -1
  91. package/claude/skills/review-craft/references/adopted.md +35 -18
  92. package/claude/skills/review-craft/references/security.md +42 -7
  93. package/claude/skills/review-craft/references/ui.md +23 -8
  94. package/claude/skills/review-pr/SKILL.md +6 -6
  95. package/claude/skills/review-pr/references/body-variants.md +29 -9
  96. package/claude/skills/review-pr/references/close-out.md +20 -5
  97. package/claude/skills/review-pr/references/key-changes.md +27 -3
  98. package/claude/skills/review-pr/references/post.md +83 -31
  99. package/claude/skills/review-pr/references/scope.md +54 -19
  100. package/claude/skills/review-ui/references/close-out.md +7 -5
  101. package/claude/skills/review-ui/references/driving.md +24 -4
  102. package/claude/skills/review-ui/references/post.md +43 -15
  103. package/claude/skills/role-orchestrator/SKILL.md +2 -0
  104. package/claude/skills/role-orchestrator/references/orchestrator-cloud-launch.md +67 -17
  105. package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +80 -40
  106. package/claude/skills/role-orchestrator/references/orchestrator-handback.md +52 -15
  107. package/claude/skills/role-orchestrator/references/orchestrator-handoff.md +48 -26
  108. package/claude/skills/role-orchestrator/references/orchestrator-inbound.md +12 -13
  109. package/claude/skills/role-orchestrator/references/orchestrator-launch.md +72 -36
  110. package/claude/skills/role-orchestrator/references/orchestrator-output.md +16 -4
  111. package/claude/skills/role-orchestrator/references/orchestrator-parked.md +64 -24
  112. package/claude/skills/role-orchestrator/references/orchestrator-poll.md +80 -26
  113. package/claude/skills/role-orchestrator/references/orchestrator-refill.md +41 -18
  114. package/claude/skills/role-orchestrator/references/orchestrator-resume.md +19 -7
  115. package/claude/skills/role-orchestrator/references/orchestrator-review-dispatch.md +22 -12
  116. package/claude/skills/role-orchestrator/references/orchestrator-reviewer-launch.md +15 -6
  117. package/claude/skills/role-orchestrator/references/orchestrator-sweep.md +25 -7
  118. package/claude/skills/role-orchestrator/references/orchestrator-watch.md +34 -8
  119. package/claude/skills/role-orchestrator/scripts/poll.ts +16 -24
  120. package/claude/skills/role-planner/REQUIREMENT.md +1 -1
  121. package/claude/skills/role-planner/SKILL.md +3 -3
  122. package/claude/skills/role-worker/REQUIREMENT.md +3 -0
  123. package/claude/skills/role-worker/SKILL.md +34 -2
  124. package/claude/skills/search-craft/REQUIREMENT.md +1 -1
  125. package/claude/skills/search-craft/SKILL.md +2 -2
  126. package/claude/skills/search-craft/references/adopted.md +18 -6
  127. package/claude/skills/session-map/references/session.md +26 -7
  128. package/claude/skills/session-worktree/references/main-root-writes.md +25 -8
  129. package/claude/skills/systematic-debugging/references/adopted.md +30 -16
  130. package/claude/skills/target-check/references/domains.md +39 -11
  131. package/claude/skills/target-setup/references/detect.md +80 -65
  132. package/claude/skills/target-setup/references/indexes.md +8 -6
  133. package/claude/skills/task-board/references/board.md +86 -30
  134. package/claude/skills/task-board/references/decline.md +29 -13
  135. package/claude/skills/task-board/references/tasks-decline.md +12 -5
  136. package/claude/skills/task-board/references/tasks.md +65 -33
  137. package/claude/skills/task-complete/references/archive.md +41 -17
  138. package/claude/skills/task-complete/references/receipt-sweep.md +23 -9
  139. package/claude/skills/task-complete/references/unusable-baseline.md +10 -3
  140. package/claude/skills/teach-workspace/references/glossary.md +6 -2
  141. package/claude/skills/teach-workspace/references/lesson-build.md +44 -16
  142. package/claude/skills/teach-workspace/references/lesson-craft.md +12 -7
  143. package/claude/skills/teach-workspace/references/pedagogy.md +6 -3
  144. package/claude/skills/teach-workspace/references/promotion-fold.md +17 -11
  145. package/claude/skills/teach-workspace/references/promotion.md +31 -8
  146. package/claude/skills/teach-workspace/references/revisit.md +8 -2
  147. package/claude/skills/teach-workspace/references/teach.md +17 -9
  148. package/claude/skills/test-craft/references/adopted.md +48 -14
  149. package/claude/skills/test-craft/references/component.md +7 -4
  150. package/claude/skills/test-craft/references/e2e.md +25 -7
  151. package/claude/skills/test-craft/references/unit.md +3 -1
  152. package/claude/skills/test-first/references/adopted.md +12 -4
  153. package/claude/skills/ui-checklist/REQUIREMENT.md +1 -1
  154. package/claude/skills/ui-checklist/SKILL.md +1 -1
  155. package/claude/skills/video-craft/references/adopted.md +62 -18
  156. package/claude/skills/write-human/references/adopted.md +21 -8
  157. package/docs/agents/audits.md +1 -0
  158. package/docs/agents/migrate.md +11 -8
  159. package/docs/target/migrations.md +11 -0
  160. package/docs/workflow/parallel-features.md +1 -1
  161. package/docs/workflow/skill-map.md +1 -0
  162. package/governance/detect.toml +4 -0
  163. package/governance/rules/canon/context.md +2 -1
  164. package/governance/rules/canon/plan.md +3 -5
  165. package/governance/rules/canon/scratch.md +3 -1
  166. package/governance/rules/canon/task-scope.md +2 -1
  167. package/governance/rules/canon/tasks.md +2 -1
  168. package/governance/rules/canon/worktrees.md +5 -2
  169. package/governance/rules/claude/output.md +7 -4
  170. package/governance/rules/claude/skill.md +6 -4
  171. package/governance/rules/tooling/ci-workflow.md +6 -39
  172. package/governance/rules/ui/design-reference.md +37 -0
  173. package/governance/rules/writing/markdown.md +2 -1
  174. package/package.json +6 -6
  175. package/src/audits/catalog.ts +42 -0
  176. package/src/claude/cases/workflow.ts +5 -0
  177. package/src/claude/settings.ts +8 -4
  178. package/src/commands/claude.ts +11 -1
  179. package/src/commands/gov.ts +198 -0
  180. package/src/commands/migrate.ts +121 -2
  181. package/src/commands/pr.ts +146 -105
  182. package/src/commands/tooling.ts +3 -3
  183. package/src/commands/worktrees.ts +49 -0
  184. package/src/gate/stages.ts +15 -0
  185. package/src/gov/audit.ts +440 -0
  186. package/src/listeners/belongs.ts +21 -0
  187. package/src/listeners/machine.ts +93 -0
  188. package/src/listeners/parse.ts +41 -0
  189. package/src/markdown/scope.ts +144 -0
  190. package/src/migrate/session-defaults.ts +138 -0
  191. package/src/pr/lift.ts +6 -3
  192. package/src/pr/local.ts +4 -69
  193. package/src/pr/review-state.ts +182 -0
  194. package/src/sync/check.ts +15 -0
  195. package/src/tooling/stamp.ts +56 -12
  196. package/src/worktrees/stop.ts +92 -0
  197. package/tooling/base/configs/.github/workflows/phase-label-gate.yml +6 -2
  198. package/tooling/base/configs/commitlint.config.js +0 -20
  199. package/tooling/base/reference.md +1 -1
  200. package/tooling/base/seeds/.github/workflows/verify.yml +4 -1
  201. package/tooling/claude/reference.md +13 -7
  202. package/tooling/claude/seeds/.claude/settings.json +4 -0
  203. package/tooling/claude/user/settings.template.json +0 -4
  204. package/tooling/cloudflare/configs/.github/workflows/deploy.yml +5 -5
  205. package/tooling/public/configs/.github/dependabot.yml +12 -0
  206. package/tooling/public/configs/.github/workflows/release-please.yml +30 -0
  207. package/tooling/public/manifest.toml +8 -0
  208. package/tooling/public/reference.md +53 -0
  209. package/tooling/public/seeds/.github/ISSUE_TEMPLATE/bug.yml +48 -0
  210. package/tooling/public/seeds/.github/ISSUE_TEMPLATE/config.yml +5 -0
  211. package/tooling/public/seeds/.github/ISSUE_TEMPLATE/feature.yml +16 -0
  212. package/tooling/public/seeds/.release-please-manifest.json +3 -0
  213. package/tooling/public/seeds/CONTRIBUTING.md +50 -0
  214. package/tooling/public/seeds/LICENSE +21 -0
  215. package/tooling/public/seeds/SECURITY.md +13 -0
  216. package/tooling/public/seeds/release-please-config.json +12 -0
  217. package/tooling/shell/configs/.github/workflows/shell.yml +4 -1
  218. package/tooling/web/configs/.github/workflows/readme-screenshot.yml +6 -3
  219. package/tooling/web/configs/.github/workflows/verify.yml +15 -12
  220. package/claude/skills/git-pr/references/evidence.md +0 -124
@@ -37,11 +37,11 @@ api = ["services/api/"]
37
37
  web = ["apps/web/", "packages/ui/"]
38
38
  ```
39
39
 
40
- A label takes more than one prefix when two folders read as one surface. Two labels may claim overlapping prefixes, and a path under both earns both.
41
-
42
- Matching is prefix-anchored, so a row written for an authoring root reaches nothing under the copy a project consumes. A surface living only under a dotted folder carries its own prefix on the row that owns its subject, and a folder holding several subjects rather than one splits across the rows that own them.
43
-
44
- The map is authored by hand, so a surface added after it was written labels nothing until someone adds a row. `canon labels audit` is what names that surface before the branch merges.
40
+ - A label takes more than one prefix when two folders read as one surface, and a path under two overlapping labels earns both
41
+ - Matching is prefix-anchored, so a row written for an authoring root reaches nothing under the copy a project consumes
42
+ - A surface living only under a dotted folder carries its own prefix on the row owning its subject
43
+ - A folder holding several subjects splits across the rows that own them
44
+ - The map is hand-authored, so a surface added later labels nothing until someone adds a row, and `canon labels audit` names it before the merge
45
45
 
46
46
  ## Paths a map declines to label
47
47
 
@@ -55,44 +55,54 @@ release-managed = ["CHANGELOG.md", "package.json"]
55
55
  generated = ["build/manifest.json"]
56
56
  ```
57
57
 
58
- A table rather than a comment because the check reads it. A path here is a decision already taken and a path under neither table is a gap nobody has gotten to, and a report that could not tell those apart would be useful about neither.
59
-
60
- A path claimed by a `[domains]` row and a `[declined]` row takes the label. It already has a subject, so reporting it as deliberately unlabelled would contradict the label the same run applies.
58
+ - It is a table rather than a comment because the check reads it, separating a decision already taken from a gap nobody has reached
59
+ - A path claimed by both a `[domains]` row and a `[declined]` row takes the label, since it already has a subject
61
60
 
62
61
  ## Reporting a surface no row reaches
63
62
 
63
+ The audit names every changed path no row reaches.
64
+
64
65
  ```bash
65
66
  canon labels audit --base <base> --json
66
67
  ```
67
68
 
68
- The record carries `labels`, `declined`, and `uncovered`. It exits 2 when `uncovered` has anything in it and 1 when it refuses, with `reason` naming the cause: `no-map` for a project that declared none, and a parse or range failure otherwise.
69
+ The record carries `labels`, `declined`, and `uncovered`. It exits 2 when `uncovered` has anything in it and 1 when it refuses, with `reason` naming the cause, `no-map` for a project that declared none and a parse or range failure otherwise.
69
70
 
70
- It reports and never gates. Whether an uncovered surface deserves a label is a judgment only the person who owns that surface can make, and a push failing on one teaches a contributor to route around the check while nothing about the surface has changed.
71
-
72
- What it leaves unmeasured is a prefix reaching no path, so a row left behind by a deleted folder stays in the map. That is the map going stale from the other side and a second measure rather than this one.
71
+ - It reports and never gates, since whether a surface deserves a label is a call only its owner makes
72
+ - A push failing on one teaches a contributor to route around the check while the surface stays unchanged
73
+ - A prefix reaching no path stays unmeasured, so a row left by a deleted folder stays in the map. That staleness needs a second measure.
73
74
 
74
75
  ## Matching
75
76
 
76
- - Take the changed set from `git diff --name-only <base>...HEAD`, resolved against the same base as the diff the body is written from. The three dots hold whether `<base>` arrives already resolved to a merge base or as a bare ref name, where the two-dot form is correct only in the first case and hands the branch somebody else's merged paths in the second
77
+ - Take the changed set from `git diff --name-only <base>...HEAD`, against the same base the body is written from
78
+ - The three dots hold whether `<base>` is already a merge base or a bare ref, where two dots would hand the branch somebody else's merged paths
77
79
  - A path earns a label when the path starts with one of that label's prefixes
78
80
  - Collect the distinct labels across the whole set, ordered as the map declares them, so two runs over one branch produce one string
79
81
  - Pass the result as a single comma-separated value. An empty result runs no labelling step.
80
82
 
81
83
  ## Applying
82
84
 
83
- Apply labels after the pull request resolves, never as a field on the create. A create carrying a label the remote lacks either fails whole or creates the label, depending on the surface, and neither is the map's call. One step against a pull request that already exists covers the create and the edit path alike. It runs over REST, so it works where GraphQL is blocked, and the REST endpoint creates any label it is handed that the remote lacks, so the step reads each name off the remote first and warns on a missing one rather than adding it.
85
+ Apply labels after the pull request resolves, never as a field on the create. A create carrying a label the remote lacks either fails whole or creates the label, depending on the surface, and neither is the map's call.
86
+
87
+ - One step against an existing pull request covers the create and the edit path alike, over REST, so it works where GraphQL is blocked
88
+ - The REST endpoint creates any label it is handed, so the step reads each name off the remote first and warns on a missing one
84
89
 
85
- `canon labels apply <number>` is that step. It resolves the earned set from the pull request's own files listing, or from the git range when `--base` is passed, binds to the pull request only when its head is the current branch and it is open, and adds each earned label the pull request lacks. `--check` reports what is owed and writes nothing. The record carries `number`, `earned`, `present`, `added`, `owed`, `missingOnRemote`, and `uncovered`.
90
+ ### The apply verb
86
91
 
87
- A pull request opened outside this skill, such as by `gh pr create`, takes the same command, since nothing else labels it.
92
+ `canon labels apply <number>` is that step. It resolves the earned set from the pull request's files listing, or from the git range when `--base` is passed, and adds each earned label the pull request lacks.
88
93
 
89
- Labelling runs whenever this skill runs and at no other time. Nothing else computes the set, so a push made any other way leaves the labels exactly as the last run left them. Any caller invoking this skill again reaches the step again, and it recomputes over the whole branch diff rather than over the new commits.
94
+ - It binds only when the pull request's head is the current branch and it is open
95
+ - `--check` reports what is owed and writes nothing
96
+ - The record carries `number`, `earned`, `present`, `added`, `owed`, `missingOnRemote`, and `uncovered`
97
+ - A pull request opened outside this skill, such as by `gh pr create`, takes the same command, since nothing else labels it
90
98
 
91
- An ordinary branch therefore labels once, when the pull request opens. The return leg that answers a review hands its push to `git-followup`, which refreshes the body without invoking this skill, so the commits that answer a review reach no labelling step.
99
+ ### When labelling runs
92
100
 
93
- A follow-up push reaching a surface the earlier ones did not merges under-labelled, with nothing to report the miss. Keeping the step in one skill is worth that cost, since a review fix lands in the files the review named and rarely opens a surface the branch had not already touched.
101
+ Labelling runs whenever this skill runs and at no other time, recomputing over the whole branch diff. A push made any other way leaves the labels as the last run left them, so an ordinary branch labels once, when the pull request opens.
94
102
 
95
- The add endpoint adds and never removes. A label a person applied by hand is not this skill's to strip, and a re-run over a branch that has since dropped a surface keeps the label that surface earned.
103
+ - The review return leg pushes through `git-followup`, which refreshes the body without this skill, so commits answering a review reach no labelling
104
+ - A follow-up reaching a new surface merges under-labelled, a cost worth paying since a review fix rarely opens a surface the branch had not touched
105
+ - The add endpoint never removes, so a hand-applied label stays and a surface the branch has since dropped keeps its label
96
106
 
97
107
  ## A label the remote does not carry
98
108
 
@@ -102,9 +112,9 @@ Warn and continue rather than creating it, naming the command in the warning:
102
112
  gh label create <name> --description "<text>"
103
113
  ```
104
114
 
105
- Creating a label writes to the repository settings from a run the user invoked to open a pull request, and a label created from a typo in the map is harder to notice than a warning is.
115
+ Creating a label writes to the repository settings from a run invoked to open a pull request, and a label created from a map typo is harder to notice than a warning.
106
116
 
107
- The refusal names the label it rejected and applies none of the set, so a warning that reaches nobody leaves the run reading exactly like one that labelled. Surface it beside the result line rather than letting the pull request URL stand alone.
117
+ The refusal names the label it rejected and applies none of the set, so an unseen warning leaves the run reading like one that labelled. Surface it beside the result line rather than letting the pull request URL stand alone.
108
118
 
109
119
  ## Release pull requests
110
120
 
@@ -118,14 +128,21 @@ The labels step of `git-pr` reads from here. Ask the CLI first:
118
128
  canon labels audit --base <base> --json
119
129
  ```
120
130
 
121
- The record carries `labels`, the set this branch earns, and `uncovered`, the changed paths no row of the map reaches. Join `labels` with commas into `pr_labels`, which the skill's final command takes. Report each `uncovered` path beside the result line, naming the map so the reader knows where a row would go, since a surface nobody covered merges bare and nothing else says so.
131
+ Join the record's `labels`, the set this branch earns, with commas into `pr_labels`, which the final command takes. Report each `uncovered` path beside the result line, naming the map so the reader knows where a row would go, since an uncovered surface merges bare and nothing else says so.
132
+
133
+ ### Reading the reason
122
134
 
123
- Branch on the record rather than on the exit. An operator's shell profile may wrap `canon` in a function whose status comes from a trailing command, and the binary exits 1 for an unknown subcommand and 1 for an ordinary refusal alike.
135
+ Branch on the record rather than on the exit. A shell profile may wrap `canon` in a function whose status comes from a trailing command, and the binary exits 1 for an unknown subcommand and an ordinary refusal alike.
124
136
 
125
- A `reason` of `no-map` is the answer that the project declared no map, which earns no labels and no warning: a label set this skill supplied would be a guess about that project's surfaces. Stop there and label nothing.
137
+ - `no-map` means the project declared no map, so label nothing and warn about nothing, since a set this skill supplied would be a guess
138
+ - `unreadable-map`, `no-domains`, `no-base`, `unreadable-changes`, and `bad-base` take the fallback below, with a warning naming the reason
139
+ - A map with a typo still has rows a prefix can reach, and reading its refusal as absence would open the pull request bare and silent
126
140
 
127
- Every other `reason` is a map or a range the verb could not read, which is `unreadable-map`, `no-domains`, `no-base`, and `unreadable-changes`, plus `bad-base` for a ref this skill resolved wrongly. Take the fallback below and warn beside the result line, naming the reason. A map with a typo in it still has rows a prefix match can reach, and reading the refusal as an absence would open the pull request with no labels and nothing said, which is the surface merging bare that the verb exists to name.
141
+ ### The fallback
128
142
 
129
- The fallback is reading `canon/config/pr-labels.toml`, or `.claude/canon/pr-labels.toml` when the project has not moved, and matching it against the name-only diff per `## Matching` above. It also covers no record coming back at all, which is an installed `canon` predating the verb, since a skill reaches a target the moment it merges while the CLI reaches one only when a release publishes. Naming both spellings matters exactly here: the binary old enough to need this fallback is the same binary that may predate the move, so the project's map can still sit at the older path. The fallback labels correctly. It reports an uncovered path only when `canon labels audit` answered, passing that record's `uncovered` on as `pr_uncovered`, and a binary too old for the audit has none to pass.
143
+ Read `canon/config/pr-labels.toml`, or `.claude/canon/pr-labels.toml` when the project has not moved, and match it against the name-only diff per `## Matching`. The fallback labels correctly.
130
144
 
131
- Leave `pr_labels` empty when no map resolves or no prefix matches, which skips the labelling command rather than running it against nothing.
145
+ - It also covers no record at all, an installed `canon` predating the verb, since a skill reaches a target on merge and the CLI only on release
146
+ - Both spellings matter here, since the binary old enough to need the fallback may predate the move too
147
+ - It reports an uncovered path only when `canon labels audit` answered, passing that record's `uncovered` as `pr_uncovered`
148
+ - Leave `pr_labels` empty when no map resolves or no prefix matches, which skips the labelling command
@@ -33,6 +33,7 @@ Does not govern:
33
33
  - Format: `<type>(<scope>): <subject>`, with `!` before the colon for a breaking change
34
34
  - Casing: lowercase for `<type>`, `<scope>`, and first word of `<subject>`
35
35
  - Length: 72 characters maximum
36
+ - Subject: follows the subject rules in `commit.md`, including the one for a sync or upgrade title
36
37
 
37
38
  ## Content
38
39
 
@@ -42,6 +43,8 @@ Does not govern:
42
43
 
43
44
  ### What to leave out
44
45
 
46
+ A body describes the new behavior and nothing the diff or the commits already say.
47
+
45
48
  - Do not describe historical behavior or unchanged code. Describe new behavior only.
46
49
  - Do not include future promises or speculative documentation
47
50
  - Do not explain obvious changes (formatting, renaming variables)
@@ -54,38 +57,49 @@ Does not govern:
54
57
 
55
58
  ### Context section
56
59
 
57
- - `## Technical context` (optional): 1-2 lines of architectural reasoning explaining why, not what
60
+ `## Technical context` is optional and carries 1-2 lines of architectural reasoning explaining why, not what.
61
+
58
62
  - Omit Technical context for docs, config, or trivial changes
59
63
  - Use bullet points for multiple reasons, one sentence for a single reason
60
64
 
61
65
  ### Testing section
62
66
 
63
- - `## Testing` (optional): specify exact commands or test cases run
67
+ `## Testing` is optional and names the exact commands or test cases run.
68
+
64
69
  - Omit Testing for docs, config, or trivial sync changes
65
70
  - Use checkboxes, never prose. See Testing discipline for which box gets ticked.
66
71
 
67
72
  ### Reviewer section and visuals
68
73
 
69
- - `## For the reviewer` (optional): what the reviewing session should confirm, one bullet per request
74
+ `## For the reviewer` is optional and lists what the reviewing session should confirm, one bullet per request.
75
+
70
76
  - Visuals: include only when they clarify architecture, UI, or complex logic flows
71
- - The list is closed. A body carries the sections above and nothing after the last of them, which covers a trailer a harness appends once the body is composed. `canon labels scan` holds the list: it fails a level-two heading outside the five above, and a body missing `## Summary` or `## Key changes`. A review body and a release-please body are exempt.
77
+ - The list is closed, so a body carries nothing after its last section, including a trailer a harness appends once the body is composed
78
+ - `canon labels scan` fails a level-two heading outside the five above, and a body missing `## Summary` or `## Key changes`
79
+ - A review body and a release-please body are exempt
72
80
 
73
81
  ## Testing discipline
74
82
 
75
83
  - Run the check before writing its line. A `- [ ]` reports a check that has not run rather than one that is planned.
76
84
  - Tick the box and state the observed result. `- [x] npm test passes, 42 tests` beats `- [ ] run npm test`.
77
85
  - Quote the count or output the run reported, never a figure carried from elsewhere.
78
- - A ticked box describes the tree as it stands, not as it stood when it was written. A later commit that removes or replaces what it names makes the box false, and the branch that made that commit corrects it in the same pass, the same as any other stale claim in the body.
86
+ - A ticked box describes the tree as it stands. A later commit removing or replacing what it names makes the box false.
87
+ - The branch that made that commit corrects the box in the same pass, as with any other stale claim in the body
79
88
 
80
89
  ### Human-only boxes
81
90
 
82
- - Leave a box unchecked only when a human is required, and name which human and why on the same line.
83
- - Human-only covers visual or aesthetic judgment, anything needing credentials or a live third-party service, anything needing a second machine or a fresh OS, and judgment about whether a boundary or an abstraction reads correctly. The agent runs everything else.
84
- - What makes a human required is a capability the agent lacks, never the cost of the run. Authorizing a spend is the operator's and performing the run is not, so an arm the repository ships a harness for gets driven once the operator has cleared the spend, and the box records what it returned.
85
- - A tool refusal that actually fired is a capability gap, and the line says which refusal rather than naming the cost behind it. A refusal predicted and never met is not one.
91
+ Leave a box unchecked only when a human is required, and name which human and why on the same line. The agent runs everything else.
92
+
93
+ - Human-only covers visual or aesthetic judgment, credentials or a live third-party service, and a second machine or a fresh OS
94
+ - It also covers judgment about whether a boundary or an abstraction reads correctly
95
+ - A human is required by a capability the agent lacks, never the cost of the run. Authorizing a spend is the operator's and performing the run is not.
96
+ - An arm the repository ships a harness for gets driven once the operator has cleared the spend, and the box records what it returned
97
+ - A tool refusal that actually fired is a capability gap, and the line names the refusal rather than the cost. A refusal predicted and never met is not one.
86
98
 
87
99
  ### Live sessions and reviewer requests
88
100
 
101
+ A live agent session is never the human a box waits on.
102
+
89
103
  - A live agent session is not a human. A box reading `needs a live session driving the skill` names the thing writing the description, so that run is owed rather than blocked.
90
104
  - Put a request for the reviewer under `## For the reviewer`. It is a request rather than unfinished testing, so it never appears as an unchecked Testing box.
91
105
 
@@ -97,6 +111,8 @@ Does not govern:
97
111
 
98
112
  ### Template
99
113
 
114
+ Every section a body may carry, in order.
115
+
100
116
  ```markdown
101
117
  ## Summary
102
118
 
@@ -124,6 +140,8 @@ Does not govern:
124
140
 
125
141
  ### Correct
126
142
 
143
+ Each line's comment names the rule it follows.
144
+
127
145
  ```markdown
128
146
  ## Summary
129
147
 
@@ -151,6 +169,8 @@ Update auth middleware to enforce jwt expiration checks. # imperative + direct o
151
169
 
152
170
  ### Incorrect
153
171
 
172
+ Each line's comment names the rule it breaks.
173
+
154
174
  ```markdown
155
175
  ## Summary
156
176
 
@@ -7,7 +7,7 @@ description: Scan an author runs against finished text, the cross-reference form
7
7
 
8
8
  ## Scope
9
9
 
10
- Governs the scan an author runs against finished text on its way out, the form a pull request or issue reference takes in every destination, and the responses available when a source it reaches for cannot be read. It is an attribute standard rather than a document-type one, so it applies wherever no automated check covers the text, whether that text is leaving through a channel or sitting in the repository, and it carries no template because a scan has no document to shape.
10
+ Governs the scan an author runs against finished text on its way out, the form a pull request or issue reference takes in every destination, and the response when a source the scan reaches for cannot be read. As an attribute standard it applies wherever no automated check covers the text, and carries no template.
11
11
 
12
12
  Does not govern:
13
13
 
@@ -18,68 +18,82 @@ Does not govern:
18
18
 
19
19
  ## When it runs
20
20
 
21
- Wherever text leaves through a channel no automated check covers, the author is the only gate and runs this scan. Text sent to another service, written to a path the project's checks exclude, and text inside a fenced block are the usual cases. The surface that publishes the text is what knows which gap applies, so it names its own rather than reading one here.
21
+ Wherever text leaves through a channel no automated check covers, the author is the only gate and runs this scan. Text sent to another service, text written to a path the checks exclude, and text inside a fenced block are the usual cases.
22
22
 
23
- Run the scan as an explicit step against the finished text. Having read the underlying rules before drafting does not cover it, because the check has to happen after the text exists.
23
+ - The surface publishing the text knows which gap applies, so it names its own rather than reading one here
24
+ - Run the scan as an explicit step against the finished text, since the check has to happen after the text exists
24
25
 
25
- Scope every check below by destination. Text published to a remote takes all of them. Text staying in the repository takes the character bans alone, since those hold wherever the text lands, and skips whichever check depends on the reader holding something only this checkout carries. The two checks below that depend on it say so under their own headings.
26
+ ### Scope by destination
27
+
28
+ Text published to a remote takes every check below. Text staying in the repository takes the character bans alone, since those hold wherever the text lands.
29
+
30
+ - Phase labels and board identifiers depend on the reader holding this checkout, so repository text skips both
31
+ - Session links depend on the reader holding the account, a narrower dependency stated under their own heading
26
32
 
27
33
  ## Banned characters
28
34
 
29
35
  `${CLAUDE_SKILL_DIR}/../markdown-craft/references/markdown.md` holds the character bans. Read it at scan time rather than working the sets from memory, then scan the drafted text and rewrite each occurrence.
30
36
 
31
- `canon labels scan` fails on these characters in a title or body, outside a code span or a link, so the scan is the check and the read above is the reason. It holds a pull request and a posted review alike.
32
-
33
- Restructure the sentence rather than substituting the character. A semicolon swapped for a period leaves both clauses in the order the semicolon chose, which is the shape the ban exists to remove.
37
+ - `canon labels scan` fails on these characters in a title or body outside a code span or a link, for a pull request and a posted review alike
38
+ - Restructure the sentence rather than substituting the character, since a semicolon swapped for a period keeps the shape the ban exists to remove
34
39
 
35
40
  ## Phase labels
36
41
 
37
42
  `${CLAUDE_SKILL_DIR}/../git-commit/references/versioning.md` holds the label rule and the table of surfaces. Read it at scan time rather than working the format from memory.
38
43
 
39
- This check is one of the two the destination rule above scopes. The reader inside the repository has the task board and the reader on a remote does not.
44
+ The reader inside the repository has the task board and the reader on a remote does not, so this check is scoped by destination.
40
45
 
41
46
  ## Board identifiers
42
47
 
43
- A phase label is one way text names the board, and a path under a record root is the other. Both resolve for a reader holding this checkout and neither resolves for anyone else, so this check is the second one the destination rule scopes.
48
+ A phase label is one way text names the board, and a path under a record root is the other. Both resolve for a reader holding this checkout and for nobody else, so this check is scoped by destination too.
44
49
 
45
- Two shapes get past a reader scanning for a bare label. A code span quoting a label is still the label, so read a span whose whole content is one as a hit and leave a longer token inside a span alone, which is a fixture name rather than a reference. The second shape is a path under a record root, gitignored and therefore absent from every clone, so `.canon/feedback/` names a folder the remote's reader cannot open.
50
+ - A code span whose whole content is a label is still the label and a hit. A longer token inside a span is a fixture name and stays.
51
+ - A path under a record root is gitignored and absent from every clone, so `.canon/feedback/` names a folder the remote's reader cannot open
52
+ - Tracked `canon/` and `.claude/` paths are no hit, since `canon/context/surfaces/governance.md` resolves everywhere
53
+ - Every path under `.canon/` is a hit whichever folder it names, since one ignore line covers the root whole
46
54
 
47
- Under the tracked `canon/` and `.claude/` folders there is no hit, since `canon/context/surfaces/governance.md` resolves everywhere. `.canon/` carries no such carve-out: one ignore line covers the root whole, so every path beneath it is a hit regardless of which folder names it.
55
+ ### Fixing a hit
48
56
 
49
- Rewrite a hit to name what the reader can reach rather than deleting it. A row's subject stated plainly replaces its label, and what a record folder holds, said in a sentence, replaces its path.
57
+ Rewrite a hit to name what the reader can reach rather than deleting it. State a row's subject plainly in place of its label, and say in a sentence what a record folder holds in place of its path.
50
58
 
51
- `canon labels scan` runs this check and the phase-label one over a pull request title and body, and over a posted review's own text once one is submitted. Any other channel, a plain issue comment among them, is still the author's own scan.
59
+ `canon labels scan` runs this check and the phase-label one over a pull request title and body, and over a posted review's text once submitted. Any other channel, a plain issue comment among them, is still the author's own scan.
52
60
 
53
61
  ## Session links
54
62
 
55
- A link to one Claude Code session names the session that wrote the text rather than the change the text describes. It enters because the harness tells the composing session to end its published text with one, so the author writes it deliberately and it reads as required rather than as a slip. That is what carries it past a scan the same author runs, and it is why a rule stating the ban does not reach the case: the session is following an instruction it was given, and reads its own compliance as correct.
56
-
57
- This check depends on the reader holding the account rather than the checkout, which is narrower than the dependency the destination rule above scopes. A reader inside this checkout opens a record path and still cannot open a session, since the session resolves for the one account that started it and for nobody else. The scoping still sits at the invocation site, because `canon labels scan` reads a pull request title and body and reaches no other text.
58
-
59
- Delete a hit rather than rewriting it. The other two checks replace a hit with what the reader can reach instead, and a session has no such form, so what stands in its place is the body already written above it.
63
+ A link to one Claude Code session names the session that wrote the text rather than the change it describes. The harness tells the composing session to end its published text with one, so the author writes it deliberately and reads that compliance as correct. That is how it passes a scan the same author runs.
60
64
 
61
- Removing the link before a merge does not substitute for never writing it. One branch removed it, read the live body back clean, and the squashed commit landed carrying it anyway off an earlier snapshot, which is permanent on the trunk.
65
+ - The session resolves only for the account that started it, so a reader inside this checkout still cannot open it
66
+ - The scoping sits at the invocation site, because `canon labels scan` reads a pull request title and body and no other text
67
+ - Delete a hit rather than rewriting it, since a session has no reachable form and the body above it already stands in its place
68
+ - Removing it before a merge is no substitute for never writing it, since a squash can land it from an earlier snapshot, permanently on the trunk
62
69
 
63
70
  ## Cross-reference form
64
71
 
65
- A number referring to a pull request or an issue takes the form its destination renders. Write it bare where the destination auto-links it, and in backticks where it does not. Both spellings are correct, each in one place, so a reference moved from one destination to the other is rewritten rather than copied.
72
+ A number referring to a pull request or an issue takes the form its destination renders. Write it bare where the destination auto-links it and in backticks where it does not, so a reference moved between destinations is rewritten rather than copied.
66
73
 
67
- Text published to a remote is the auto-linking half: a pull request body, an issue body, a comment on either, and a commit message. Write `#123` there, and `owner/repo#123` where the reference crosses repositories, which the same auto-linking reaches. A markdown file browsed from the repository tree is the other half, where neither spelling links and the backticked one marks the number as an identifier. <!-- canon-allow-reference: the two spellings this section defines, which a qualified form would destroy -->
74
+ | Destination | Form |
75
+ | --------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
76
+ | Pull request or issue body, a comment on either, a commit | `#123`, or `owner/repo#123` across repositories <!-- canon-allow-reference: the two spellings this section defines, which a qualified form would destroy --> |
77
+ | A markdown file browsed from the repository tree | the number in backticks, since neither spelling links there |
78
+ | Content installed into another repository | qualified against a different, resolvable repository, or no number |
68
79
 
69
- Content that installs into another repository is the third destination, and it splits on which repository the number names. A skill body loads from a plugin cache and a docs page is read through `canon docs`, so the reader holds their own repository rather than the one a bare number belongs to. Qualifying a number against a different, resolvable repository fixes that, since the reader can open that repository even without this one.
80
+ A commit message takes the bare form even though the log links nothing, since the remote is what the form is chosen for. Text quoted from another surface keeps the spelling it arrived with, since rewriting it reports the source as saying something it never said.
70
81
 
71
- Qualifying it against `erclx/canon` fixes nothing, because a reader holding only the plugin cache or the published package still cannot open this repository's own history. A same-repository citation takes no number here at all, bare or qualified. State the fact the citation was standing in for instead, and where the identifier is the only trace of a one-off incident rather than a reproducible count, carry it into the `canon/context/` entry that owns the surface.
82
+ ### Installed content
72
83
 
73
- Write `owner/repo#123` and `owner/repo@abc1234` for a citation of a different, resolvable repository, across every such surface. `canon gate run` fails a push on a bare reference there, and a line whose bare form is the point carries `canon-allow-reference: <reason>` on itself or on the line above.
84
+ A skill body loads from a plugin cache and a docs page is read through `canon docs`, so the reader holds their own repository rather than the one a bare number belongs to.
74
85
 
75
- Choose the number over the sha where the citation names a decided change, since a pull request number resolves to the diff and the review behind it. Take the sha only for a tree or measurement state, the `Measured at <sha>` shape a context entry already uses. The choice holds for both spellings this section fixes, the bare form a remote auto-links and the qualified form a cross-repository citation carries.
86
+ - Write `owner/repo#123` and `owner/repo@abc1234` for a different, resolvable repository, which the reader can open without this one
87
+ - Qualifying against `erclx/canon` fixes nothing, since a reader holding the cache or the package still cannot open this repository's history
88
+ - A same-repository citation takes no number, so state the fact it stood in for, and carry a one-off incident's identifier into the `canon/context/` entry owning the surface
89
+ - `canon gate run` fails a push on a bare reference there, and a line whose bare form is the point carries `canon-allow-reference: <reason>` on itself or the line above
76
90
 
77
- A commit message takes the bare form even though it is also read through the log, where nothing links. The remote is what the form is chosen for, since a reader in the log loses only a link that plain text never carried.
91
+ ### Number or sha
78
92
 
79
- Text quoted from another surface keeps the spelling it arrived with. A reference inside a quotation belongs to what is being quoted rather than to the text doing the quoting, so rewriting it reports the source as having said something it never said.
93
+ Choose the number where the citation names a decided change, since it resolves to the diff and the review behind it. Take the sha only for a tree or measurement state, the `Measured at <sha>` shape a context entry already uses. The choice holds for the bare and the qualified spelling alike.
80
94
 
81
95
  ## An unreadable source
82
96
 
83
97
  Stop and name the source when one this scan reaches for cannot be read. Do not scan what resolved and report the result.
84
98
 
85
- A run that covers half its sources and says nothing is worse than one that visibly did not happen, because the surfaces running this scan are the ones that describe themselves as the only gate. A clean result from a half-run scan is read as coverage.
99
+ A half-run scan that says nothing is worse than one that visibly did not happen, because the surfaces running this scan describe themselves as the only gate. Its clean result is read as coverage.
@@ -7,22 +7,34 @@ description: How git-pr writes the pull request number the final command printed
7
7
 
8
8
  The last step of `git-pr` before its report, reached on every run whose final command printed a number.
9
9
 
10
- Write the `number` the final command printed onto the task the branch is closing. Do not resolve it again. A final command that refused on a head mismatch printed no number, so this step writes nothing on that run. `${CLAUDE_SKILL_DIR}/REQUIREMENT.md` states why: a lookup that resolves by branch alone can return a closed pull request sharing that head, so the number is resolved once and reused rather than re-derived.
10
+ Write the `number` the final command printed onto the task the branch is closing, and never resolve it again. A lookup by branch alone can return a closed pull request sharing that head, per `${CLAUDE_SKILL_DIR}/REQUIREMENT.md`. A final command that refused on a head mismatch printed no number, so this step writes nothing on that run.
11
11
 
12
- The task is the one whose `Plan:` line names the plan this branch implemented. Name that plan by its file, which is `.canon/plans/feature-<slug>.md` at the main worktree root with `<slug>` derived per `${CLAUDE_SKILL_DIR}/../git-branch/references/slug.md`. `plan-feature` writes the plan under the branch slug, so the two correspond on any branch that came through the plan-to-execute path. When the session already knows which plan it implemented, because a caller read it earlier in the chain, use that filename instead of re-deriving.
12
+ ## Name the plan
13
+
14
+ The task is the one whose `Plan:` line names the plan this branch implemented. That plan is `.canon/plans/feature-<slug>.md` at the main worktree root, with `<slug>` derived per `${CLAUDE_SKILL_DIR}/../git-branch/references/slug.md`.
15
+
16
+ - `plan-feature` writes the plan under the branch slug, so the two correspond on any branch that came through the plan-to-execute path
17
+ - When a caller earlier in the chain already read the plan, use that filename instead of re-deriving
18
+ - The slug is a guess at the plan rather than a fact about the task, so the verb re-checks it against the board and refuses on a near miss
13
19
 
14
20
  ```bash
15
21
  canon tasks pull-request <number> --plan feature-<slug> --json
16
22
  ```
17
23
 
18
- The slug is a guess at which plan this branch carries rather than a fact about the task, which is why the verb re-checks it against the board and refuses instead of writing on a near miss. A branch whose slug names no plan file falls to the silent skip below, the same as one whose plan no task cites.
24
+ ## What the verb writes
25
+
26
+ The verb resolves the board at the main worktree root in-process, the root `session-worktree` resolves on entry. It is the route because the write edits an existing main-root file, which `session-worktree` routes through a verb.
27
+
28
+ - It adds `Pull request: #NNN` under the task's `Plan:`, `Groundwork:`, `Intake:`, or `Issue:` lines, and corrects the number in place when the line exists
29
+ - A line already reading as a list of `#NNN` entries takes the new number appended, reported as `appended`, so a task shipped in slices keeps every pull request
30
+ - The same write drops this branch from the `Pending branch:` line `canon tasks outcome` wrote, which lets the merge-time archive close the task
19
31
 
20
- The verb resolves the board at the main worktree root in-process, adds `Pull request: #NNN` under the `Plan:`, `Groundwork:`, `Intake:`, or `Issue:` lines the task already carries, and corrects the number in place when the line exists. This is the route because the write is an edit inside an existing main-root file, which `session-worktree` routes through a verb. That root is the one `session-worktree` resolves on entry.
32
+ ## Refusals
21
33
 
22
- The correction reaches only a line that does not read as a list of `#NNN` entries. A line that does takes the new number appended rather than replaced, reported as `appended`, so a task shipped in slices keeps every pull request.
34
+ Skip silently when the record is `ok: false` and `reason` is `no-board`, `no-match`, or `ambiguous`, meaning no board, no task naming the plan, or more than one. A guessed write would compound each, since a wrong match archives the wrong task unattended once the branch merges. Report any other refusal rather than swallowing it.
23
35
 
24
- The same write drops this branch from the task's `Pending branch:` line, which `canon tasks outcome` wrote when the branch ticked an outcome, so this step is what lets the merge-time archive close the task.
36
+ A branch whose slug names no plan file lands on `no-match`, the same as one whose plan no task cites.
25
37
 
26
- Skip this silently when the record is `ok: false` and `reason` is `no-board`, `no-match`, or `ambiguous`. Those are the three cases a guessed write would compound: no board, no task naming the plan, or more than one. One pull request names one task, and a wrong match archives the wrong task unattended once the branch merges. Report any other refusal rather than swallowing it.
38
+ ## Why the number
27
39
 
28
- The number is what lets the merge close the task. Every merge on `main` is a squash carrying it in the subject, so the number survives where a branch name does not, and `post-merge` reads it back to call `canon tasks archive`. Writing it here rather than at worktree time is what makes it a pull request number rather than a branch the squash discards.
40
+ Every merge on `main` is a squash carrying the number in its subject, so the number survives where a branch name does not. `post-merge` reads it back to call `canon tasks archive`, which is why this step runs at pull request time rather than at worktree time.
@@ -89,7 +89,7 @@ On a `passing` wake, run `canon pr evidence <number> --check --json` against the
89
89
  | Any other `reason`, such as `gh-failed` | Stop and report it, since an unread thread is not a settled one |
90
90
  | No record, or an unknown flag error | The binary predates `--check`, so report the thread unread and continue without claiming it was checked |
91
91
 
92
- On `owed`, run the named steps from `canon:git-pr`'s `references/evidence.md`, evidence first and then preview, and re-read with the same command. Continue only on `settled`, and stop on any other reading with the `reason` and the `owed` list, never looping back.
92
+ On `owed`, invoke `canon:pr-evidence` with the number, which runs the evidence step first and then the preview the thread owes, and re-read with the same command. Continue only on `settled`, and stop on any other reading with the `reason` and the `owed` list, never looping back.
93
93
 
94
94
  A refused preview step or a failed deploy leaves `preview` owed on the re-read, so that is the stop and not a retry. The read is a closing step, so the draft mark stays the only thing between steps 8 and 9, and a caller closing on its own block waits on the same wake.
95
95
 
@@ -49,7 +49,7 @@ Measure against the tree rather than recall, since a count carried from an earli
49
49
  When a decision rests on an outside practice or a third-party behavior, invoke `canon:search-craft` before searching, fetch each source, and record the passage relied on. Skip this for a plan that rests on nothing outside the project.
50
50
 
51
51
  - Confirm exact wording through `curl` where a decision turns on it, since `WebFetch` returns a model's answer rather than the page
52
- - Route a Claude Code subject to the `claude-code-guide` agent
52
+ - Fetch a Claude Code subject from Anthropic's docs directly, starting at the index `https://code.claude.com/docs/llms.txt` and reading the `.md` form of the page it names
53
53
  - Mark a source that could not be fetched as unverified rather than citing recall
54
54
  - Report it rather than proceeding silently when `canon:search-craft` does not resolve
55
55
 
@@ -30,7 +30,14 @@ A plan lost to deletion, or carrying two answers to one question, fails both.
30
30
  ## Lifecycle
31
31
 
32
32
  - Write the plan before implementation starts, and treat it as the scope of the run that executes it. A subject that has to be measured before anyone can plan against it takes a measurement track first.
33
- - Keep every plan at one root. A plan copied into each parallel working tree forks, and the copies answer the same question differently.
34
- - Amend the plan in place when a decision changes mid-flight. Do not append a second passage narrating the change, which leaves a reader to work out which of two answers is current. An execution-time deviation from a suggestion is one such amendment, and the suggested-and-answer contract in `plan.md` fixes which line takes it.
35
- - Move the plan to `.canon/plans/archive/` when the work it describes ships or is declined. Never delete it, because the plan is where the rejected alternative is written down. A flat `.claude/plans-archive/` sibling is the older layout.
36
33
  - Write the plan in the same session that opens the task it serves. The session executing it later inherits reasoning it would otherwise re-derive.
34
+ - Keep every plan at one root. A plan copied into each parallel working tree forks, and the copies answer the same question differently.
35
+
36
+ ### Amending and archiving
37
+
38
+ A plan changes in place and leaves only by a move.
39
+
40
+ - Amend the plan in place when a decision changes mid-flight, never appending a passage narrating the change, which leaves two answers to reconcile
41
+ - An execution-time deviation from a suggestion is one such amendment, and the suggested-and-answer contract in `plan.md` fixes which line takes it
42
+ - Move the plan to `.canon/plans/archive/` when its work ships or is declined, and never delete it, since it records the rejected alternative
43
+ - A flat `.claude/plans-archive/` sibling is the older layout.