@erclx/canon 5.32.0 → 5.33.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 (210) hide show
  1. package/claude/.claude-plugin/plugin.json +1 -1
  2. package/claude/skills/auto-ship/SKILL.md +1 -1
  3. package/claude/skills/auto-ship/references/worktree-name.md +1 -1
  4. package/claude/skills/backlog-triage/REQUIREMENT.md +2 -2
  5. package/claude/skills/backlog-triage/SKILL.md +1 -1
  6. package/claude/skills/canon-cli/REQUIREMENT.md +16 -13
  7. package/claude/skills/canon-cli/SKILL.md +75 -32
  8. package/claude/skills/canon-feedback/SKILL.md +1 -1
  9. package/claude/skills/{canvas → canvas-board}/REQUIREMENT.md +2 -2
  10. package/claude/skills/{canvas → canvas-board}/SKILL.md +2 -2
  11. package/{standards → claude/skills/canvas-board/references}/design.md +11 -2
  12. package/claude/skills/context-fold/REQUIREMENT.md +25 -33
  13. package/claude/skills/context-fold/SKILL.md +25 -70
  14. package/claude/skills/context-fold/references/classify.md +3 -3
  15. package/claude/skills/context-fold/references/completion-report.md +4 -4
  16. package/claude/skills/context-fold/references/context-refresh.md +5 -5
  17. package/{standards → claude/skills/context-fold/references}/context.md +16 -5
  18. package/claude/skills/context-fold/references/unusable-baseline.md +3 -5
  19. package/claude/skills/create-rule/SKILL.md +2 -2
  20. package/{standards → claude/skills/create-rule/references}/rule.md +12 -5
  21. package/claude/skills/create-skill/SKILL.md +2 -2
  22. package/{standards → claude/skills/create-skill/references}/skill.md +17 -14
  23. package/claude/skills/design-taste/REQUIREMENT.md +3 -3
  24. package/claude/skills/design-taste/SKILL.md +1 -1
  25. package/claude/skills/docs-sync/REQUIREMENT.md +1 -1
  26. package/claude/skills/docs-sync/SKILL.md +3 -3
  27. package/{standards → claude/skills/docs-sync/references}/docs.md +11 -0
  28. package/{standards → claude/skills/docs-sync/references}/readme.md +9 -2
  29. package/claude/skills/draft-and-pick/SKILL.md +5 -5
  30. package/claude/skills/draft-doc/SKILL.md +6 -6
  31. package/claude/skills/draft-figure/REQUIREMENT.md +2 -2
  32. package/claude/skills/draft-figure/SKILL.md +2 -2
  33. package/claude/skills/draft-figure/references/hand-drawn.md +1 -1
  34. package/claude/skills/draft-figure/references/mermaid-path.md +1 -1
  35. package/claude/skills/draft-identity/REQUIREMENT.md +2 -2
  36. package/claude/skills/draft-identity/SKILL.md +2 -2
  37. package/claude/skills/draft-ready/SKILL.md +1 -1
  38. package/claude/skills/git-branch/SKILL.md +1 -1
  39. package/{standards → claude/skills/git-branch/references}/branch.md +1 -1
  40. package/claude/skills/git-commit/SKILL.md +2 -2
  41. package/claude/skills/git-followup/REQUIREMENT.md +1 -1
  42. package/claude/skills/git-followup/SKILL.md +1 -1
  43. package/claude/skills/git-issue/SKILL.md +1 -1
  44. package/claude/skills/git-pr/SKILL.md +13 -13
  45. package/claude/skills/git-pr/references/evidence.md +2 -2
  46. package/claude/skills/git-pr/references/final-command.md +38 -14
  47. package/claude/skills/git-pr/references/labels.md +5 -1
  48. package/{standards → claude/skills/git-pr/references}/pr.md +19 -9
  49. package/{standards → claude/skills/git-pr/references}/publish.md +4 -2
  50. package/claude/skills/git-pr/references/task-number.md +1 -1
  51. package/claude/skills/git-ship/SKILL.md +15 -14
  52. package/claude/skills/git-split/SKILL.md +3 -3
  53. package/claude/skills/git-stage/SKILL.md +1 -1
  54. package/claude/skills/plan-feature/REQUIREMENT.md +1 -1
  55. package/claude/skills/review-address/SKILL.md +1 -1
  56. package/claude/skills/review-address/references/post-review-findings.md +1 -1
  57. package/claude/skills/review-pr/REQUIREMENT.md +1 -1
  58. package/claude/skills/review-pr/SKILL.md +3 -3
  59. package/claude/skills/review-pr/references/body-variants.md +2 -2
  60. package/claude/skills/review-pr/references/key-changes.md +3 -3
  61. package/claude/skills/review-pr/references/post.md +4 -2
  62. package/claude/skills/review-ui/REQUIREMENT.md +1 -1
  63. package/claude/skills/review-ui/SKILL.md +1 -1
  64. package/claude/skills/review-ui/references/post.md +1 -1
  65. package/claude/skills/role-orchestrator/REQUIREMENT.md +3 -0
  66. package/claude/skills/role-orchestrator/SKILL.md +2 -2
  67. package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +2 -2
  68. package/claude/skills/role-orchestrator/references/orchestrator-handoff.md +8 -5
  69. package/claude/skills/role-orchestrator/references/orchestrator-launch.md +23 -1
  70. package/claude/skills/role-orchestrator/references/orchestrator-refill.md +2 -2
  71. package/claude/skills/role-orchestrator/references/orchestrator-resume.md +3 -0
  72. package/claude/skills/role-planner/REQUIREMENT.md +2 -1
  73. package/claude/skills/role-planner/SKILL.md +13 -2
  74. package/claude/skills/role-reviewer/SKILL.md +1 -1
  75. package/claude/skills/role-worker/REQUIREMENT.md +1 -0
  76. package/claude/skills/role-worker/SKILL.md +9 -1
  77. package/claude/skills/session-map/SKILL.md +1 -1
  78. package/claude/skills/session-resume/REQUIREMENT.md +2 -2
  79. package/claude/skills/session-worktree/SKILL.md +5 -5
  80. package/claude/skills/target-setup/references/detect.md +1 -1
  81. package/claude/skills/task-board/REQUIREMENT.md +7 -12
  82. package/claude/skills/task-board/SKILL.md +5 -17
  83. package/claude/skills/task-board/references/tasks.md +2 -2
  84. package/claude/skills/task-complete/REQUIREMENT.md +47 -0
  85. package/claude/skills/task-complete/SKILL.md +86 -0
  86. package/claude/skills/{task-board → task-complete}/references/archive.md +4 -4
  87. package/claude/skills/{context-fold → task-complete}/references/receipt-sweep.md +5 -5
  88. package/claude/skills/task-complete/references/unusable-baseline.md +19 -0
  89. package/claude/skills/teach-workspace/REQUIREMENT.md +6 -2
  90. package/claude/skills/teach-workspace/SKILL.md +8 -4
  91. package/claude/skills/teach-workspace/references/lesson-craft.md +1 -1
  92. package/claude/skills/{context-fold/references/promoted-pages.md → teach-workspace/references/promotion-fold.md} +3 -3
  93. package/claude/skills/teach-workspace/references/promotion.md +3 -3
  94. package/claude/skills/ui-checklist/SKILL.md +1 -1
  95. package/claude/skills/ux-audit/SKILL.md +1 -1
  96. package/claude/skills/ux-measure/SKILL.md +1 -1
  97. package/docs/agents/canvas.md +1 -1
  98. package/docs/agents/commands.md +3 -2
  99. package/docs/agents/context-audit-checks.md +4 -4
  100. package/docs/agents/index.md +3 -3
  101. package/docs/agents/indexes.md +1 -1
  102. package/docs/agents/install-and-sync.md +6 -11
  103. package/docs/agents/key-changes.md +5 -5
  104. package/docs/agents/label-coverage.md +11 -0
  105. package/docs/agents/migrate.md +1 -1
  106. package/docs/agents/records-push.md +2 -2
  107. package/docs/agents/records-stale.md +12 -47
  108. package/docs/agents/records-validate.md +3 -7
  109. package/docs/agents/records.md +5 -27
  110. package/docs/agents/rule-citations.md +1 -1
  111. package/docs/agents/sandbox.md +4 -4
  112. package/docs/agents/skills-audit.md +1 -1
  113. package/docs/agents/tasks-plans.md +2 -2
  114. package/docs/agents/tasks.md +2 -2
  115. package/docs/target/migrations.md +10 -2
  116. package/docs/target/projects.md +1 -1
  117. package/docs/target/sync.md +1 -1
  118. package/docs/workflow/operating-model.md +2 -2
  119. package/docs/workflow/parallel-features.md +7 -7
  120. package/docs/workflow/skill-map-on-request.md +9 -9
  121. package/docs/workflow/skill-map.md +12 -11
  122. package/docs/workflow/visual-design-workflow.md +2 -2
  123. package/governance/renames.toml +0 -11
  124. package/governance/rules/canon/context.md +13 -0
  125. package/governance/rules/claude/skill.md +17 -0
  126. package/governance/stacks/base.toml +2 -4
  127. package/package.json +4 -4
  128. package/scripts/core/install-check.sh +3 -3
  129. package/scripts/lib/ui.sh +0 -159
  130. package/src/audits/catalog.ts +0 -1
  131. package/src/claude/cases/misc.ts +1 -1
  132. package/src/claude/cases/setup.ts +4 -0
  133. package/src/claude/cases/workflow.ts +6 -1
  134. package/src/claude/seeds.ts +1 -1
  135. package/src/claude/skills-audit.ts +2 -2
  136. package/src/cli/help.ts +3 -1
  137. package/src/cli/ui.ts +2 -3
  138. package/src/commands/claude.ts +1 -1
  139. package/src/commands/gov.ts +2 -15
  140. package/src/commands/labels.ts +326 -7
  141. package/src/commands/migrate.ts +6 -1
  142. package/src/commands/pr.ts +1 -1
  143. package/src/commands/records.ts +13 -399
  144. package/src/commands/sandbox.ts +3 -6
  145. package/src/commands/tasks.ts +3 -3
  146. package/src/context/audit.ts +5 -5
  147. package/src/context/folders.ts +1 -1
  148. package/src/design/budget.ts +1 -1
  149. package/src/design/components.ts +1 -1
  150. package/src/design/document.ts +1 -1
  151. package/src/design/regen.ts +1 -1
  152. package/src/design/render.ts +1 -1
  153. package/src/gate/measures.ts +1 -1
  154. package/src/gate/sequencer.ts +56 -1
  155. package/src/gate/stages.ts +1 -7
  156. package/src/gov/install.ts +2 -3
  157. package/src/gov/stacks.ts +1 -1
  158. package/src/hooks/post-merge.ts +1 -1
  159. package/src/labels/apply.ts +39 -0
  160. package/src/labels/format.ts +3 -3
  161. package/src/labels/phase.ts +3 -3
  162. package/src/labels/sections.ts +43 -0
  163. package/src/migrate/skill-names.ts +20 -1
  164. package/src/pr/paths.ts +4 -4
  165. package/src/records/backup.ts +16 -6
  166. package/src/records/stale-canonical.ts +31 -1
  167. package/src/records/validate.ts +2 -188
  168. package/src/sandbox/census.ts +1 -1
  169. package/src/sandbox/coverage.ts +2 -6
  170. package/src/sandbox/equivalence.ts +5 -44
  171. package/src/sandbox/expect.ts +4 -4
  172. package/src/sandbox/provision.ts +13 -36
  173. package/src/sandbox/scenario.ts +26 -48
  174. package/src/sandbox/tree.ts +2 -6
  175. package/src/standards/read.ts +14 -1
  176. package/src/sync/git.ts +1 -1
  177. package/src/tasks/archive.ts +5 -5
  178. package/src/tasks/branch.ts +3 -3
  179. package/src/tasks/label.ts +1 -1
  180. package/src/tasks/record.ts +2 -2
  181. package/src/tasks/validate.ts +1 -1
  182. package/standards/index.md +0 -13
  183. package/standards/standard.md +1 -7
  184. package/tooling/base/reference.md +1 -1
  185. package/tooling/base/seeds/.github/pull_request_template.md +2 -2
  186. package/tooling/claude/reference.md +1 -1
  187. package/tooling/claude/seeds/.claude/hooks/pr-create-log.sh +9 -1
  188. package/tooling/claude/seeds/.claude/hooks/review-post-scan.sh +171 -0
  189. package/tooling/claude/seeds/.claude/settings.json +9 -0
  190. package/governance/rules/standards/context.md +0 -14
  191. package/governance/rules/standards/design.md +0 -12
  192. package/governance/rules/standards/readme.md +0 -12
  193. package/governance/rules/standards/rule.md +0 -13
  194. package/governance/rules/standards/skill.md +0 -21
  195. package/governance/rules/standards/standard.md +0 -13
  196. package/scripts/config.sh +0 -11
  197. package/scripts/lib/gov.sh +0 -14
  198. package/scripts/lib/sandbox-fixtures.sh +0 -191
  199. package/scripts/lib/sandbox-git.sh +0 -125
  200. package/scripts/lib/sandbox-path.sh +0 -50
  201. package/scripts/sandbox-hook.sh +0 -99
  202. package/src/gov/standard-rules.ts +0 -179
  203. package/src/records/migrate.ts +0 -78
  204. package/src/records/stale.ts +0 -243
  205. package/src/sandbox/hooks.ts +0 -128
  206. /package/claude/skills/{canvas → canvas-board}/references/canvas.md +0 -0
  207. /package/{standards → claude/skills/draft-figure/references}/figures.md +0 -0
  208. /package/{standards → claude/skills/git-branch/references}/slug.md +0 -0
  209. /package/{standards → claude/skills/git-commit/references}/commit.md +0 -0
  210. /package/{standards → claude/skills/git-commit/references}/versioning.md +0 -0
@@ -9,8 +9,8 @@ metadata:
9
9
 
10
10
  Before proposing a split, read in parallel:
11
11
 
12
- - `${CLAUDE_SKILL_DIR}/../../standards/branch.md`: format, types, length limit, and constraints
13
- - `${CLAUDE_SKILL_DIR}/../../standards/pr.md`: PR title format, body sections, and content rules
12
+ - `${CLAUDE_SKILL_DIR}/../git-branch/references/branch.md`: format, types, length limit, and constraints
13
+ - `${CLAUDE_SKILL_DIR}/../git-pr/references/pr.md`: PR title format, body sections, and content rules
14
14
 
15
15
  Follow both exactly.
16
16
 
@@ -71,7 +71,7 @@ If Mode is Independent, append this line to the preview:
71
71
 
72
72
  After outputting the preview, execute the final commands immediately. Claude Code's tool permission dialog is the confirmation gate. Do not wait for user input.
73
73
 
74
- Before running them, run the scan in `${CLAUDE_SKILL_DIR}/../../standards/publish.md` against every title and body. Each body stages under `.canon/tmp/` and leaves through `gh`, so the hook sees neither and this scan is the only gate. Each resulting branch reaches the `pull_request` check the git-pr surface carries once its own pull request opens, but not before, so this scan is what catches a leak ahead of that.
74
+ Before running them, run the scan in `${CLAUDE_SKILL_DIR}/../git-pr/references/publish.md` against every title and body. Each body stages under `.canon/tmp/` and leaves through `gh`, so the hook sees neither and this scan is the only gate. Each resulting branch reaches the `pull_request` check the git-pr surface carries once its own pull request opens, but not before, so this scan is what catches a leak ahead of that.
75
75
 
76
76
  ### Final commands
77
77
 
@@ -9,7 +9,7 @@ metadata:
9
9
 
10
10
  Read these files in parallel:
11
11
 
12
- - `${CLAUDE_SKILL_DIR}/../../standards/commit.md`: format, types, scopes, and constraints
12
+ - `${CLAUDE_SKILL_DIR}/../git-commit/references/commit.md`: format, types, scopes, and constraints
13
13
  - `${CLAUDE_SKILL_DIR}/../markdown-craft/references/markdown.md`: punctuation and formatting for all generated text
14
14
  - The `write-human` skill: voice, rhythm, and sentence construction for all generated text
15
15
 
@@ -40,4 +40,4 @@ Without this skill, implementation starts before anyone knows what it touches. A
40
40
 
41
41
  - Executing the plan, which is the ship pipeline
42
42
  - Task-board state, which `task-board` owns. A plan links to its task and does not create one.
43
- - Reconciling the planning docs after the work lands, which `context-fold` owns
43
+ - Reconciling the context entries after the work lands, which `context-fold` owns, and marking the board, which `task-complete` owns
@@ -156,7 +156,7 @@ the regen rebuilt, and close the same way. The heading stays outside the
156
156
  `## Review` family so the close-out's equality test on the first line never
157
157
  matches it.
158
158
 
159
- Before posting, follow `${CLAUDE_SKILL_DIR}/../../standards/publish.md`
159
+ Before posting, follow `${CLAUDE_SKILL_DIR}/../git-pr/references/publish.md`
160
160
  and run its scan against the reply:
161
161
 
162
162
  ```bash
@@ -7,7 +7,7 @@ description: How review-address posts something worth reporting after Step 7 clo
7
7
 
8
8
  Outside the numbered flow of `review-address`. The session reads this file when it has something worth reaching the reviewing session after Step 7 already closed the review.
9
9
 
10
- Not everything worth reaching the reviewing session surfaces inside the numbered flow in `SKILL.md`. A worker that settled a risk, filed a follow-up, or found something else worth reporting after Step 7 already closed the review posts it directly rather than waiting on a review pass that has nothing left to trigger it. Write the body the way Step 6 writes a reply: load `write-human` for voice and word choice, follow `${CLAUDE_SKILL_DIR}/../markdown-craft/references/markdown.md` for punctuation, and run the `${CLAUDE_SKILL_DIR}/../../standards/publish.md` scan before posting with `canon labels scan --body-file .canon/tmp/pr/reply/reply-<number>.md`.
10
+ Not everything worth reaching the reviewing session surfaces inside the numbered flow in `SKILL.md`. A worker that settled a risk, filed a follow-up, or found something else worth reporting after Step 7 already closed the review posts it directly rather than waiting on a review pass that has nothing left to trigger it. Write the body the way Step 6 writes a reply: load `write-human` for voice and word choice, follow `${CLAUDE_SKILL_DIR}/../markdown-craft/references/markdown.md` for punctuation, and run the `${CLAUDE_SKILL_DIR}/../git-pr/references/publish.md` scan before posting with `canon labels scan --body-file .canon/tmp/pr/reply/reply-<number>.md`.
11
11
 
12
12
  Open with `## Post-review findings` rather than `## Review response`, since nothing on the thread is being answered. `review-pr` states the full heading set this belongs to and routes it the same as a response: `role-orchestrator`'s poll picks it up and sends the reviewing session back for a pass. Close the body with `🤖 Addressed by Claude Code` on its own line, matching the reply's footer.
13
13
 
@@ -29,7 +29,7 @@ Scoping a later pass off GitHub's review stamp skipped real work. On 2026-09-07
29
29
  - Key the body file on the pull request number and the head commit, and on the response it answers once the head repeats, so no two passes overwrite each other
30
30
  - Link a file-bound finding to its line at the reviewed head, since a bare file block leaves a reader hunting the diff for the spot
31
31
  - Scan the comment for banned characters and internal phase labels before posting, since a finding phrased against a phase label reaches a reader with no task board
32
- - Answer a `## For the reviewer` bullet in the body, bounded to the section itself rather than the Summary or the Technical Context around it, so the independent vantage stays clear of the author's framing
32
+ - Answer a `## For the reviewer` bullet in the body, bounded to the section itself rather than the Summary or the Technical context around it, so the independent vantage stays clear of the author's framing
33
33
  - Confirm each `**Review focus:**` item the plan names on a first pass, and turn one the pass cannot confirm into a finding, since the planning session named the breaking inputs before the diff existed and no other reader holds that list
34
34
 
35
35
  ## Must not
@@ -79,15 +79,15 @@ Read each test file the branch added or changed against the final filter in `can
79
79
 
80
80
  Then read the description's `## Testing` section, which is the one part of a pull request body this session is positioned to falsify. The branch author cannot see what a sibling branch drove the same day, and the arm list is what settles the claim rather than the diff.
81
81
 
82
- Test every unchecked box against the testing discipline in `${CLAUDE_SKILL_DIR}/../../standards/pr.md`, which reserves an unchecked box for a capability the agent lacks. Raise the box when it names no human at all, when the human it names is a live agent session, or when it names a person for a step the repository ships a harness for, such as `sandbox/run.sh`. Cost alone is not an answer, since authorizing a spend is the operator's and performing the run is not. A refusal the author actually met is an answer, and it names which one.
82
+ Test every unchecked box against the testing discipline in `${CLAUDE_SKILL_DIR}/../git-pr/references/pr.md`, which reserves an unchecked box for a capability the agent lacks. Raise the box when it names no human at all, when the human it names is a live agent session, or when it names a person for a step the repository ships a harness for, such as `canon sandbox run`. Cost alone is not an answer, since authorizing a spend is the operator's and performing the run is not. A refusal the author actually met is an answer, and it names which one.
83
83
 
84
84
  Test every ticked box too, bounded to one naming a file or a command. Confirm what it names still exists at `<headRefOid>`, `git show <headRefOid>:<path>` for a file or `git grep <command> <headRefOid>` for a command, rather than re-running what it claims. A box naming neither stays untested, since nothing here can confirm a claim carrying no artifact. A box ticked before a later commit removed or replaced what it names is a `should-fix` finding on the body itself, filed under a `**PR body**` block ahead of the file blocks, since what it corrupts is the merge record rather than a file in the diff.
85
85
 
86
- Then test what `## Key Changes` claims against the diff it describes. Read `${CLAUDE_SKILL_DIR}/references/key-changes.md` for the verb that compares them, which field of its record becomes a finding, and which ones raise nothing.
86
+ Then test what `## Key changes` claims against the diff it describes. Read `${CLAUDE_SKILL_DIR}/references/key-changes.md` for the verb that compares them, which field of its record becomes a finding, and which ones raise nothing.
87
87
 
88
88
  Ask rather than grade. Whether a human is genuinely required is a reading the branch author may hold a reason this session cannot see, so the question carries no severity and enters no count. What it does carry is the heading and the dispatch, on the rule the opening states, because a question the author never receives corrects nothing and the author is the only party who can answer it. Answering it closes it, and the answer may be that the requirement holds.
89
89
 
90
- Read `## For the reviewer` the same way, bounded to the bullets under that heading rather than the Summary or the Technical Context around it. Those two carry the author's argument for the change, and reading them while judging it is most of what an independent pass exists to avoid, so the read stops at the section itself.
90
+ Read `## For the reviewer` the same way, bounded to the bullets under that heading rather than the Summary or the Technical context around it. Those two carry the author's argument for the change, and reading them while judging it is most of what an independent pass exists to avoid, so the read stops at the section itself.
91
91
 
92
92
  Answer each bullet in the body, on the same terms as a Testing question: no severity, no count. A request nobody can answer stays owed under the heading and dispatch the opening states, keeping the thread open exactly as an unanswered Testing box does. One the pass does answer carries no further weight, since the answer is discharged in the same comment that carries it.
93
93
 
@@ -12,7 +12,7 @@ A Testing box the Step 3 check raised goes in a `**Testing**` block placed after
12
12
  ```markdown
13
13
  **Testing**
14
14
 
15
- - `- [ ] <the box as written>` names no capability the agent lacks. `sandbox/run.sh <arm>` drives it. Was there a reason to leave it?
15
+ - `- [ ] <the box as written>` names no capability the agent lacks. `canon sandbox run <arm>` drives it. Was there a reason to leave it?
16
16
  ```
17
17
 
18
18
  Keep it to the boxes the check raised. Restating a box whose stated requirement holds teaches the branch author to skip the block.
@@ -24,7 +24,7 @@ An unanswered bullet is owed the same way an unanswered Testing box is, so a pas
24
24
  ```markdown
25
25
  **For the reviewer**
26
26
 
27
- - Confirm the 401 and 403 split reads correctly for the public API. Confirmed — `AuthService.authenticate()` returns 401 for an expired token and 403 for a missing scope, and both paths are covered under `## Testing`.
27
+ - Confirm the 401 and 403 split reads correctly for the public API. Confirmed: `AuthService.authenticate()` returns 401 for an expired token and 403 for a missing scope, and both paths are covered under `## Testing`.
28
28
  ```
29
29
 
30
30
  A pass carrying nothing at all takes `## Review closed` and a short body, with the footer line included either way. On a first pass, post `✅ No findings. Reviewed against project docs and the board.` On a later pass, post `✅ Prior findings addressed. Re-reviewed <short-sha>, N commits since the prior pass.`
@@ -1,13 +1,13 @@
1
1
  ---
2
2
  title: Key changes check
3
- description: How review-pr Step 3 tests what the pull request body's Key Changes section claims against the diff, reading each field the canon pr key-changes record carries and which one becomes a finding
3
+ description: How review-pr Step 3 tests what the pull request body's Key changes section claims against the diff, reading each field the canon pr key-changes record carries and which one becomes a finding
4
4
  ---
5
5
 
6
- # Test the Key Changes claims
6
+ # Test the Key changes claims
7
7
 
8
8
  Part of Step 3 of `review-pr`. The session reads this file after the `## Testing` boxes and before the `## For the reviewer` bullets.
9
9
 
10
- Test what `## Key Changes` claims against the diff it describes, with `canon pr key-changes <number> --json`. This repository squash-merges, so that section becomes the commit message and the record on the trunk once the branch is gone, which is the same thing a stale ticked box corrupts. Branch on the record rather than on the exit code, which a shell function wrapping `canon` can flatten to zero.
10
+ Test what `## Key changes` claims against the diff it describes, with `canon pr key-changes <number> --json`. This repository squash-merges, so that section becomes the commit message and the record on the trunk once the branch is gone, which is the same thing a stale ticked box corrupts. Branch on the record rather than on the exit code, which a shell function wrapping `canon` can flatten to zero.
11
11
 
12
12
  Read `unmet` as a `should-fix` finding under the same `**PR body**` block the stale box takes, one entry per path, quoting the bullet the record carries on `preview` and naming the `head` the comparison ran at. Read the bullet before filing it, since one class survives the reader: a bullet citing where something is defined while claiming an edit elsewhere, which puts a real path in the claim region and points the change at a locative the path does not name. Report that as the class rather than as a stale claim. A body is edited between pushes, so the reading is true at that commit and can be false a minute later. Read `unnamed` for yourself and raise nothing off the count. The class still covers a real omission and equally a generated asset or a regenerated index that earns no bullet, and the entries the reader can name as owing none are already held apart under `incidental`. Open the section and confirm no bullet names the file before putting a single one to the author, because this instruction has sent the question to three pull requests in one day over bullets that had named the files all along, and one of those authors added bullets nobody needed. Report `unresolved` and `incidental` nowhere: the first was judged in neither direction and the second owes no bullet, so neither says anything about the body.
13
13
 
@@ -56,7 +56,7 @@ X critical, Y should-fix, Z minor. Reviewed against project docs and the board.
56
56
 
57
57
  A stale ticked box goes in a `**PR body**` block, in place of a `**`path/to/file.ext`**` block and ahead of every one of those, since it precedes the code the diff carries rather than sitting inside it.
58
58
 
59
- Run `canon labels scan --title "<title>" --body "<body>" --head <headRefName>` against the PR under review, since Step 1 already holds all three and this pass is the last human-shaped gate before merge. A hit lands in the same `**PR body**` block, `should-fix`, naming each finding the scan returns: a token quoted from the title or body for a phase label, a board identifier, a session link, or an unspelled word, and the broken rule's name, `structure`, a casing issue, or `length`, for a title-format hit. This reads the pull request being reviewed, distinct from the comment this pass is about to post, which the scan later in this step still covers.
59
+ Run `canon labels scan --title "<title>" --body "<body>" --head <headRefName>` against the PR under review, since Step 1 already holds all three and this pass is the last human-shaped gate before merge. A hit lands in the same `**PR body**` block, `should-fix`, naming each finding the scan returns: a token quoted from the title or body for a phase label, a board identifier, a session link, or an unspelled word, and the broken rule's name, `structure`, a casing issue, or `length`, for a title-format hit. A heading in `sections.outside`, a heading in `sections.missing`, or a character in `bannedCharacters` is a hit of the same weight, naming the heading or the character. This reads the pull request being reviewed, distinct from the comment this pass is about to post, which the scan later in this step still covers.
60
60
 
61
61
  A later pass carrying findings keeps that shape and changes only the summary line:
62
62
 
@@ -116,7 +116,9 @@ Write it as a comment rather than as prose so a reader of the thread never meets
116
116
 
117
117
  It is inert data, so the `publish.md` scan below and `canon labels scan` have nothing to fire on. Confirm that against the posted body rather than assuming it, since a phase label or a board identifier appearing inside a commit sha is not a shape either scan was written against.
118
118
 
119
- Before posting, run the scan in `${CLAUDE_SKILL_DIR}/../../standards/publish.md` against the body. The hook skips `.canon/tmp/`, so this scan is the only gate ahead of the post. A finding phrased against an internal phase label is what the label half of the scan catches here. This repository reads the same text again once posted, on `phase-label-gate.yml`'s `pull_request_review` trigger, which is what closes the gap this scan leaves open for a review a person writes and posts by hand with no scripted step in front of it. That workflow now reaches every target on the `base` stack, seeded at `tooling/base/configs/.github/workflows/phase-label-gate.yml` invoking the published CLI rather than this checkout's own source tree, so a target's coverage extends past this pre-post scan to the same post-trigger re-read this repository gets.
119
+ Before posting, run `canon labels scan --body-file .canon/tmp/pr/review/body-<number>-<short-sha>.md` against the body, which applies the rule in `${CLAUDE_SKILL_DIR}/../git-pr/references/publish.md`. Fix the body and scan again on a finding. A finding phrased against an internal phase label is what the label half of the scan catches here. The call carries no `--title`, so the scan reads the text as a review.
120
+
121
+ A `PreToolUse` hook on `Bash` runs the same scan against the `-F body=@<file>` of the post below and denies the call on a hit, so the check holds whether or not this step ran it. The hook reads the file before the command runs, so write the body in an earlier call than the post, and pass it as a file rather than inline. This repository reads the same text again once posted, on `phase-label-gate.yml`'s `pull_request_review` trigger, which is what closes the gap for a review a person writes and posts by hand with no hook in front of it. That workflow now reaches every target on the `base` stack, seeded at `tooling/base/configs/.github/workflows/phase-label-gate.yml` invoking the published CLI rather than this checkout's own source tree, so a target's coverage extends past the hook to the same post-trigger re-read this repository gets.
120
122
 
121
123
  Do not run the command below when `<prior-heading>` from Step 2 reads `## Review closed` and this pass carries nothing owed. That pass replaces the standing comment rather than adding one, so read `${CLAUDE_SKILL_DIR}/references/close-out.md` instead of posting. Posting first and reaching that section afterward leaves two close-outs both naming the new head, which is worse than the pair the guard exists against.
122
124
 
@@ -34,7 +34,7 @@ A verdict also goes stale without saying so. A push after the pass changes what
34
34
 
35
35
  ## Must not
36
36
 
37
- - Read the diff, the plan, the task, or the description's Summary and Technical Context. A pass that has heard the author's argument drives towards what it expects.
37
+ - Read the diff, the plan, the task, or the description's Summary and Technical context. A pass that has heard the author's argument drives towards what it expects.
38
38
  - Judge a box marked as taste
39
39
  - Check out, build, or serve the head, or download a browser mid-pass
40
40
  - Tick a taste box, a failed box, or a box at a head it did not drive, or tick any box other than through `canon pr tick`
@@ -46,7 +46,7 @@ gh api --paginate 'repos/{owner}/{repo}/issues/<number>/comments?per_page=100' -
46
46
 
47
47
  The first read prints the verdict's body and when it was posted as one JSON line, and the second prints when the newest reply was. `--paginate` runs the filter once per page, so `tail` outside it keeps the newest row in the thread rather than the newest on each page. The verdict goes out as JSON because its body spans many lines, and `tail` over the raw body would keep only its last one. An empty first read is a pull request carrying no verdict yet. Take the sha off the body's last-line `<!-- review-ui: head=<sha> -->` marker. A body carrying none covers no head this pass can trust, so drive.
48
48
 
49
- Read nothing else about the change. The diff, the plan, the task, and the description's Summary and Technical Context all carry the author's argument for it, and a pass that has heard it drives towards what it expects.
49
+ Read nothing else about the change. The diff, the plan, the task, and the description's Summary and Technical context all carry the author's argument for it, and a pass that has heard it drives towards what it expects.
50
50
 
51
51
  ## Step 2: read the evidence record
52
52
 
@@ -72,7 +72,7 @@ End every body on `<!-- review-ui: head=<head> -->`, carrying the full sha Step
72
72
 
73
73
  ## Posting
74
74
 
75
- Run `canon labels scan --body-file .canon/tmp/pr/review-ui/body-<number>-<short-sha>.md` against the body first, which applies the rule in `${CLAUDE_SKILL_DIR}/../../standards/publish.md`, since nothing gates a file under `.canon/tmp/` before the review-event run does. Fix the body and scan again on a finding. Then post it as a review rather than an issue comment, since the poll reads the UI family off reviews:
75
+ Run `canon labels scan --body-file .canon/tmp/pr/review-ui/body-<number>-<short-sha>.md` against the body first, which applies the rule in `${CLAUDE_SKILL_DIR}/../git-pr/references/publish.md`, since nothing gates a file under `.canon/tmp/` before the review-event run does. Fix the body and scan again on a finding. Then post it as a review rather than an issue comment, since the poll reads the UI family off reviews:
76
76
 
77
77
  Record the instant just before the post, in UTC, as `<posted-at>`. Step 9 keeps only review-event runs created after it, since the code review posts its own review on the same head and fires a run of the same gate.
78
78
 
@@ -80,6 +80,8 @@ Dispatch parts from what it checked in three ways. The gate and the worker each
80
80
  - Carry the dispatcher's `sessionId` in the launch prompt, since a worker owed two messages has no property on the roster that resolves a controller and a name goes stale inside the window it builds in
81
81
  - Report each self-dispatch and the row it fired against loudly enough to follow, since a person no longer watches the launch step happen
82
82
  - Stop dispatching once `## Run now` is empty or every row in it reads claimed, rather than waking again to fire on a board nobody is clearing
83
+ - Launch a planner or worker the operator will talk with from the talk shape, with the `-talk` suffix and the brief sentence that tells it so, since a cold launch retires the session the moment its delivery lands while the operator still wants the conversation
84
+ - Retire a talk session only on the operator's word and report it as held open until then, since its delivery says nothing about whether the conversation is over
83
85
  - Dispatch a pull request's review, first pass included, to `role-reviewer` on load or on executable content, a skill body included, and keep one cross-branch pass per wave here, since a warm pass holding a wave skims what a cold one reads
84
86
 
85
87
  ## Must not
@@ -105,6 +107,7 @@ Dispatch parts from what it checked in three ways. The gate and the worker each
105
107
  - Blocker only an operator can clear: record the row as untestable this pass and name the action owed, rather than re-measuring what no session can move
106
108
  - Branch check refuses, with no session registry or no repository resolved: treat the candidate as unverified and fall back to the human-launch line, rather than reading a check that could not run as a clear one
107
109
  - Candidate holds under the conflict check: leave the row ready and name the hold, rather than dispatching onto a contract still moving
110
+ - Talk session the client renamed after launch: find it by the `sessionId` recorded in the map, since the `-talk` suffix is display only and a rename can drop it
108
111
  - Operator states a cap for the session: honor it for that session alone, rather than treating it as a standing rule or writing the number into a file
109
112
 
110
113
  ## Out of scope
@@ -59,10 +59,10 @@ Report the state of play in the invocation block, and open every later sweep rep
59
59
 
60
60
  ## The loop
61
61
 
62
- 1. Plan the next feature. The cross-feature call stays in this warm session, being which rows conflict, what merges before what, and whether a row should run at all. Per-row planning runs either way: `plan-feature` here with that context, or a cold planner dispatched under `role-planner` through the planning shape in `${CLAUDE_SKILL_DIR}/references/orchestrator-launch.md`. Every plan written from here also carries a constraint per track in flight, which the paragraph below this list states.
62
+ 1. Plan the next feature. The cross-feature call stays in this warm session, being which rows conflict, what merges before what, and whether a row should run at all. Per-row planning runs either way: `plan-feature` here with that context, or a cold planner dispatched under `role-planner` through the planning shape in `${CLAUDE_SKILL_DIR}/references/orchestrator-launch.md`, or a talk planner from that file's talk shape when the operator wants to shape the row with the session. Every plan written from here also carries a constraint per track in flight, which the paragraph below this list states.
63
63
  2. Decide parallelism and merge order. Note which plans depend on another or change a contract another consumes, since those hold, and which merely share a file, since those build together and the second to merge rebases.
64
64
  3. Verify the plan against the tree. Reading it is not enough, since a plan goes stale from whatever merged after it was written. Grep for each construct it names and count the sites against the count it claims. Check that every phase label it cites is still open. Open each file it describes rather than trusting its account of the contents. Correct the plan before handing it over.
65
- 4. Hand off. Read `${CLAUDE_SKILL_DIR}/references/orchestrator-dispatch.md` and follow it: check the branch is unclaimed, run its conflict check against every track in flight, then dispatch a background worker with `claude --bg`. Fall back to the human-launch line it replaces when the branch check refuses or the conflict check holds the row behind something already out.
65
+ 4. Hand off. Read `${CLAUDE_SKILL_DIR}/references/orchestrator-dispatch.md` and follow it: check the branch is unclaimed, run its conflict check against every track in flight, then dispatch a background worker with `claude --bg`. Fall back to the human-launch line it replaces when the branch check refuses or the conflict check holds the row behind something already out. Where the operator wants to talk with the worker, launch the talk build from the talk shape in the launch runbook after the same checks clear.
66
66
  5. Review the PR. When a worker opens a PR, its first pass runs through `review-pr` in a reviewer dispatched under `role-reviewer` when `### The review dispatch` below fires, and in this session otherwise. Either is the deep, independent pass. The worker's chain carries no review step, so this is the first review the change gets.
67
67
  - Learning that a PR moved is the mechanical half, so read `${CLAUDE_SKILL_DIR}/references/orchestrator-poll.md` and run the poll under the condition it states rather than checking the board by hand. That runbook holds the routing and the trigger, and a summary of it here is a second source that drifts from it.
68
68
  6. Dispatch the handback. A pass posting anything owed, a finding at any severity or a testing question, tells the session holding that branch to run `review-address`, rather than waiting for a person to relay it. Re-review when the worker's own message says the address pass finished, per the channel `role-worker` states, rather than polling for an answer nothing else marks as landed, and send the re-review back to the dispatched reviewer when one took the first pass. Once a pass posts `## Review closed`, a UI close names the current head wherever the PR carries a checklist, the poll run as `--check <number>` prints `CLEAR`, and `--check` reports `settled`, lift the pull request's draft mark yourself, per Boundaries below. Then the human merges. Tell each trailing worker whose files the merged diff touches to run `review-address`, which rebases it when it no longer merges or when `main` changed a file it writes, after each merge rather than once per wave.
@@ -23,7 +23,7 @@ Run this at loop step 4, for a `## Run now` row whose plan is verified, in place
23
23
  Run `canon tasks plan-branch <plan> --json` against the row's plan file and read `branch`, `type`, `slug`, and `conforms` off the record.
24
24
 
25
25
  - `conforms: true`: take `branch` as the candidate, and take `type` and `slug` from the same record for the check below.
26
- - `conforms: false`: the plan's own filename breaks a cap in `${CLAUDE_SKILL_DIR}/../../standards/branch.md`. Report which, and hand the row to the human-launch line below rather than shortening the slug here. A rename parts the branch from the plan filename that `session-worktree` tier 1 and `git-pr`'s plan lookup both read back.
26
+ - `conforms: false`: the plan's own filename breaks a cap in `${CLAUDE_SKILL_DIR}/../git-branch/references/branch.md`. Report which, and hand the row to the human-launch line below rather than shortening the slug here. A rename parts the branch from the plan filename that `session-worktree` tier 1 and `git-pr`'s plan lookup both read back.
27
27
  - `reason: archived`, `no-plan`, or `bad-input`: the row does not cite a live plan. Repoint the row or fix the citation rather than dispatching, since `auto-ship` Step 1 refuses the same file and the worker would meet that refusal after the launch spent.
28
28
  - Anything else, including a record carrying no `branch` key and an installed binary carrying no `plan-branch` subcommand: treat the candidate as unverified rather than clear, name which reading could not be taken, and fall back to the human-launch line below. Re-deriving by prose here rebuilds the defect the verb closes, and does it quietly.
29
29
 
@@ -94,7 +94,7 @@ No practitioner source serializes on a shared file. Each builds in parallel and
94
94
 
95
95
  Read `canon sessions list --json` for the branches in flight as well as the board, since a track a person launched by hand carries no row, and read the plan of any branch no row names. `canon tasks validate` and `canon tasks plan-reach` report the paths two rows share, which is a candidate list for the five holds and the paths the dispatch names. A shared folder means a Touches cell claimed it bare, so narrow that cell rather than reading the folder as a sweep.
96
96
 
97
- A declared set predicts what a branch writes rather than bounding it, since `canon:context-fold`, `canon:docs-sync`, and the regenerated drift stages write past every plan. Such a crossing changes what the second branch rebases over rather than whether a row holds, and `canon tasks plan-reach` at `canon:git-ship` step 4 names it before the pull request opens. What binds past the five holds is review attention, which `## Parallelism` in the skill body states. The one number this skill carries is the review dispatch's count of three in `orchestrator-review-dispatch.md`, which moves a review rather than binding a track, and this runbook carries none.
97
+ A declared set predicts what a branch writes rather than bounding it, since `canon:context-fold`, `canon:docs-sync`, and the regenerated drift stages write past every plan. Such a crossing changes what the second branch rebases over rather than whether a row holds, and `canon tasks plan-reach` at `canon:git-ship` step 5 names it before the pull request opens. What binds past the five holds is review attention, which `## Parallelism` in the skill body states. The one number this skill carries is the review dispatch's count of three in `orchestrator-review-dispatch.md`, which moves a review rather than binding a track, and this runbook carries none.
98
98
 
99
99
  ## Pick the model
100
100
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Orchestrator handoff runbook
3
- description: Retirement act the wind-down owes the fleet it dispatched, the two sections an orchestrating session adds over the shared session map, where a lesson goes from a session that never commits, and the resume invocation the file carries out
3
+ description: Retirement act the wind-down owes the fleet it dispatched, the talk sessions it exempts, the three sections an orchestrating session adds over the shared session map, where a lesson goes from a session that never commits, and the resume invocation the file carries out
4
4
  ---
5
5
 
6
6
  ## Retire what the wave delivered
@@ -15,7 +15,9 @@ Name the planner as the case always in this set, and scope the act no narrower.
15
15
 
16
16
  ### Which sessions this session may retire unasked
17
17
 
18
- Retire what this session dispatched. Report a hand-launched session and leave the act to the operator, since the knowledge making the act safe is a delivery this session received and it received nothing from a session it never launched. The `worker-` and `planner-` name prefixes separate the two populations, per `orchestrator-dispatch.md`.
18
+ Retire what this session dispatched. Report a hand-launched session and leave the act to the operator, since the knowledge making the act safe is a delivery this session received and it received nothing from a session it never launched. The `worker-` and `planner-` name prefixes separate the two populations, per `orchestrator-launch.md`.
19
+
20
+ A talk session is the exception inside the dispatched population. Retire it only on the operator's word, given here or carried in the session's own close message, and never on its delivery, at wind-down or at any other point. Its plan landing or its pull request opening tells this session nothing about whether the conversation is over. Until the word arrives, report it as held open next to the hand-launched read. A talk session is found by the `sessionId` the prior map records or this session's own launch output carries, since the client can rename it and drop the `-talk` suffix `orchestrator-launch.md` gives it.
19
21
 
20
22
  A capability gap sits beside the knowledge gap, and it holds even where delivery is somehow known. A hand-launched session is as often interactive as background, and `claude rm <id>` has no id to take for an interactive one at all, so the command cannot reach it whatever this session learned about its delivery.
21
23
 
@@ -39,10 +41,11 @@ Report the retired sessions as a list, the hand-launched ones under it as a read
39
41
 
40
42
  Write the pre-compaction handoff as orchestrator. Invoke `canon:session-map` for the generic half, which is the filename, the three core sections, the write procedure, the drift step and the ref it reads, and the citation rule. Everything in this section is the extension this role adds over that core, and none of it belongs to a session holding no delegated authority.
41
43
 
42
- Settle both steps below before the door writes, so one write carries the core and the extension together. The door reports the map as written and knows nothing of this role, so its success line ends the generic half rather than this runbook, and a session that stops there ships a map missing both of the things this section adds to it.
44
+ Settle all three steps below before the door writes, so one write carries the core and the extension together. The door reports the map as written and knows nothing of this role, so its success line ends the generic half rather than this runbook, and a session that stops there ships a map missing everything this section adds to it.
43
45
 
44
46
  1. Add `## Decisions taken under delegated authority` directly after `## State`, holding each decision and why it went that way, so nobody re-proposes it. It sits there rather than after the core because a decision is read against the state it was taken in.
45
- 2. Close the file with the block below, resolving `${CLAUDE_SKILL_DIR}/references/orchestrator-resume.md` and `${CLAUDE_SKILL_DIR}/references/orchestrator-poll.md` to absolute paths as you write it and pasting each in place of `<RESUME_RUNBOOK>` and `<POLL_RUNBOOK>`:
47
+ 2. Add `## Talk sessions held open` directly after that section, with one line per open talk session giving its name, its `sessionId`, and its row, or `None.` when there are none. The next session reads it to know which sessions it must not retire on a delivery.
48
+ 3. Close the file with the block below, resolving `${CLAUDE_SKILL_DIR}/references/orchestrator-resume.md` and `${CLAUDE_SKILL_DIR}/references/orchestrator-poll.md` to absolute paths as you write it and pasting each in place of `<RESUME_RUNBOOK>` and `<POLL_RUNBOOK>`:
46
49
 
47
50
  ```markdown
48
51
  Resume by loading the orchestrator skill and asking it to resume after a compaction. This repository spells that `/canon:role-orchestrator` followed by the request. Following <RESUME_RUNBOOK> reaches the same place with no skill loaded at all.
@@ -52,7 +55,7 @@ That resume reads the board and stops. It restarts nothing, so the review poll i
52
55
 
53
56
  The delegated-authority section is the orchestrator's alone because a worker holds no delegation to have exercised, and a section a session cannot fill teaches its reader to skip the file. The closing block is the orchestrator's for the same reason from the other direction: it restarts a review poll no other role runs.
54
57
 
55
- The substitution belongs in step 2 because that step ends the write. A reader who treats the list as finished elsewhere ships the literal placeholders, and the variable expands while this runbook renders rather than in the turn that reads the handoff back, so a path left unresolved reaches a session holding no skill as a string matching nothing. `orchestrator-poll.md` resolves its script at the same point and for the same reason.
58
+ The substitution belongs in step 3 because that step ends the write. A reader who treats the list as finished elsewhere ships the literal placeholders, and the variable expands while this runbook renders rather than in the turn that reads the handoff back, so a path left unresolved reaches a session holding no skill as a string matching nothing. `orchestrator-poll.md` resolves its script at the same point and for the same reason.
56
59
 
57
60
  That block sits in this runbook and again in the file this runbook writes, which is the fix rather than a copy for a later pass to collapse. A session has to already be holding this runbook to read it, and a compaction that took the skill body took the routing to it too, so the session that most needs the resume is the one that can no longer find it. The map survives that, so it carries the invocation itself. Each of the two reaches a reader the other cannot.
58
61
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Orchestrator launch runbook
3
- description: The launch every dispatch kind shares, being the build, cloud build, review-address, and planning templates, the session name and controller id each carries, why the command sits at position zero, and what the brief may carry
3
+ description: The launch every dispatch kind shares, being the build, cloud build, review-address, planning, and talk templates, the session name and controller id each carries, why the command sits at position zero, and what the brief may carry
4
4
  ---
5
5
 
6
6
  Run this once `orchestrator-dispatch.md` has cleared a row, or from its planning or review-address shape below when that runbook's checks do not bind. The model each template names comes from `## Pick the model` in that runbook.
@@ -89,6 +89,28 @@ What a planning dispatch owes instead is the reverse reading, because the plan i
89
89
 
90
90
  One row per dispatch. A session reused across a batch pays the context load once and ages its picture of the tree while it works, which is what puts the in-flight read on the task rather than on the batch, and one that compacts mid-batch loses the reasoning behind its earlier plans with nothing reporting it. Cap a reused session where the saving is worth it and say what the cap was.
91
91
 
92
+ ## Dispatch a talk session
93
+
94
+ A planner or worker the operator will talk with takes the same launch as its cold shape above, with two changes. It carries a `-talk` suffix on its name, and its brief gains one sentence. A cold session works alone and reports back, and a talk session stays open after its plan or pull request lands so the operator can keep shaping the row with it.
95
+
96
+ Take the planning shape or the build shape and change those two things:
97
+
98
+ ```bash
99
+ claude --bg --model <model> -n "planner-<project>-<slug>-talk" "Run /canon:role-planner, then /canon:plan-feature <task>. This is a talk session: the operator will talk with you here, so run your role's talk clause, and message your controller when the operator ends the conversation. Your controller is the session whose sessionId is <dispatcher-id>. ..."
100
+ claude --bg --model <model> -n "worker-<project>-<slug>-talk" "/canon:auto-ship <plan>
101
+ This is a talk session: the operator will talk with you here, so run your role's talk clause, and message your controller when the operator ends the conversation. Your controller is the session whose sessionId is <dispatcher-id>. ..."
102
+ ```
103
+
104
+ The ellipsis stands for the rest of the cold template's message clauses, unchanged. The build variant keeps `/canon:auto-ship <plan>` at position zero with nothing before it, per the rule above.
105
+
106
+ Keep the role prefix and add the suffix rather than inventing a prefix. `orchestrator-handoff.md` separates dispatched sessions from hand-launched ones by `worker-` and `planner-`, so a new prefix would read as a hand launch and fall outside the retirement act.
107
+
108
+ Read the session's `sessionId` off the launch output and carry it in this session's own context, then write it into the map's `## Talk sessions held open` section at the next handoff. The map exists only once the handoff writes it, so the launches this session made, read from its own context with the prior map, are the source the first wind-down reads talk sessions from. The client can rename a session after launch and drop the suffix, so the id is the durable marker and the suffix is only for display.
109
+
110
+ A talk session is retired only on the operator's word, which `orchestrator-handoff.md` states under the retirement act. That runbook is the one place the rule lives, so do not restate it in a launch report.
111
+
112
+ Reviewers get no talk shape, since a reviewer's pass holds no operator dialogue.
113
+
92
114
  ## Dispatch a reviewer
93
115
 
94
116
  Read `${CLAUDE_SKILL_DIR}/references/orchestrator-reviewer-launch.md` when `orchestrator-review-dispatch.md` sends a pull request to a dispatched reviewer, for the code, cloud, and UI reviewer shapes.
@@ -14,7 +14,7 @@ It counts unclaimed plans against workers rather than reading the reserve in ste
14
14
  1. Run `gh pr list --state open` and `git log --oneline -8`. Report any pull request whose review has not been posted and stop for that one first.
15
15
  2. For each pull request merged since the last sweep, place every finding it produced. Route a finding that changes a rule to the standard or rule that states it, one that changes another task to that task's Findings, and one that overturns a groundwork lean to that folder marked answered. Never leave a finding in a pull request thread alone.
16
16
  3. Archive what closed.
17
- - A task whose outcomes are all `[x]` runs `context-fold` for the plan sweep, then `task-board` to archive
17
+ - A task whose outcomes are all `[x]` and whose pull request merged is archived by the `post-merge` hook through `canon tasks archive`, which carries its plans with it. Run `task-complete` to archive one the hook left in place
18
18
  - A task whose outcomes describe standing policy rather than a deliverable never closes on its own, so hand it to a worker to encode the policy where it is enforced, then cut the outcomes with the reason recorded and archive once that branch merges. Encoding it from this session would write a tracked file, which `## Boundaries` in the skill body forbids.
19
19
  4. Read `.canon/tasks/priority.md` and count entries under its `## Run now` heading that carry a written plan. Keep one in reserve beyond what is running.
20
20
  5. Promote from the top of `## Needs a plan`, which is where the last sweep recorded what to plan next. Depart from that order when something has changed under it and say what changed, since a position nobody honors is the ordering going stale on the surface built to hold it. What sets the order in the first place is whether a task establishes functionality rather than how old it is, so prefer a task that adds or proves a mechanism over one that trims, tidies, or audits an existing surface.
@@ -50,4 +50,4 @@ Promoting, demoting, and archiving a row all write `.canon/tasks/priority.md`, a
50
50
  - Re-resolve every Plan pointer after anything archives a plan
51
51
  - Read the file back after writing it, since the row that lands is the row a worker acts on
52
52
 
53
- A Plan pointer goes stale from a branch this board never sees. `context-fold` moves a plan to `.canon/plans/archive/` and rewrites the citation in the task file alone, so a row for a task still on the board keeps pointing into `.canon/plans/` at a file that has moved. Workers running the ship chain on their own branches archive plans this board still cites, and the board reads as correct until a pointer is followed.
53
+ A Plan pointer goes stale from a merge this board never sees. The `post-merge` hook moves a plan to `.canon/plans/archive/` through `canon tasks archive` and rewrites the citation in the archived task file alone, so a row for a task still on the board keeps pointing into `.canon/plans/` at a file that has moved. `task-complete` marks outcomes on each worker's branch and moves nothing, so the move lands at the merge, and the board reads as correct until a pointer is followed.
@@ -17,8 +17,11 @@ Read: <task files>, <groundwork folders>
17
17
  Shipped since: <commits or PRs>
18
18
  Stale in the groundwork: <lean or number the shipped work overturned>
19
19
  Next: <the one or two tasks ready to hand a worker>
20
+ Held open: <talk sessions from the map's `## Talk sessions held open`, or none>
20
21
  ```
21
22
 
23
+ Read `Held open:` off the newest session map's `## Talk sessions held open`, so a resumed session does not mistake a conversation for a finished delivery. `orchestrator-handoff.md` states what ends one.
24
+
22
25
  Treat a groundwork folder as three kinds of content with different shelf lives. Trust the reasoning and the method, which stay correct. Re-measure every count, size, and cost, because they were true when written. Check every `Leaning:` against what has shipped, because work spawned by a track routinely overturns the lean that spawned it and nothing writes back.
23
26
 
24
27
  A plan a live task cites goes stale the same way, and `role-orchestrator` states the check that catches it.
@@ -61,6 +61,7 @@ four carried at least one, caught only because the planner ran
61
61
  - Owe an announcement when the record lands, carrying the path and what the row got wrong, since the controller cannot watch the read happen
62
62
  - Owe a message before a block becomes an interactive prompt, since a session already waiting on input never reaches the tool round an inbound message drains at
63
63
  - Keep correcting the dispatcher a first-class move carrying its evidence, since a trial corrected a brief's premise, planned every row anyway, and carried the consequence into a plan question
64
+ - Carry a talk clause for a launch whose operator is in the session, putting each open question to them, recording a settled pick in place, and owing a close message when they end the conversation, since a cold planner's halting rules contradict a brief that asks it to talk
64
65
  - Point at each of the three skills for its record's shape and the steps that write it
65
66
  - Defer the addressee resolution to `session-relay` and keep only the last-rung inference, which discriminates differently here than it does for a worker because a session in this role holds no feature branch either
66
67
 
@@ -69,7 +70,7 @@ four carried at least one, caught only because the planner ran
69
70
  - Restate a record's sections, its suggested-and-answer contract, or the steps the running skill carries, since thinness is what keeps one body correct for a dispatched session reading it as its whole contract
70
71
  - Restate the write-scope exceptions each of the three skills states about its own folder
71
72
  - Restate a boundary `role-orchestrator` or `role-worker` states about itself
72
- - Tell a planner to halt on a plan question, which the suggested line already answers, rather than on what blocks writing the plan at all
73
+ - Tell a planner to halt on a plan question, which the suggested line already answers, rather than on what blocks writing the plan at all. A talk launch is the exception, since putting the question to the operator in the session is its job.
73
74
  - Tell a planner to report the path with no account of what the row got wrong. That instruction came from a trial condition holding a blind comparison intact, and it is not a durable obligation.
74
75
  - Report progress through the channel, which rebuilds on the sender's side the poll the announcement exists to retire
75
76
  - Write the priority board or the backlog, at any size, or the task file outside `plan-groundwork`'s close-time exception
@@ -94,14 +94,25 @@ controller. Report the candidates and stop where more than one does, rather than
94
94
  addressing the first. Send to the single row where exactly one comes back, and
95
95
  say the addressee was inferred.
96
96
 
97
+ ## Talk launch
98
+
99
+ A launch whose brief says it is a talk session puts the operator in this one. Everything above holds, and the clause below changes how questions are answered and when the role ends. A launch carrying no such sentence takes none of this.
100
+
101
+ - Put each open question to the operator through the structured question surface before writing the record, and record a settled pick in place per the plan standard's answer-in-place rule. Never fill an `- Answer:` slot the operator did not answer.
102
+ - Keep answering under `plan-feature`'s discussion rounds after the record lands, since the operator launched this session to keep talking.
103
+ - Owe the landing announcement as usual, plus a close message when the operator ends the conversation.
104
+ - Skip the before-prompt block message for a question put to the operator who is in the session. Keep it for a block the operator cannot answer, since a controller learns of a stall only from a message.
105
+
106
+ The operator being present is an assumption the launch carries. A talk planner whose operator has walked away waits silently on its first question, so say what the session is waiting on in the turn it stops.
107
+
97
108
  ## Refusing is part of the job
98
109
 
99
110
  - Refuse an instruction the tree contradicts, and carry the evidence with it. Name the commands read and what complying would produce, rather than reporting reluctance.
100
111
  - Correct a premise the brief carried when the tree disagrees with it. One trial was told two rows were free of a renamed token and found they carried it as command names rather than path segments, planned all three rows anyway, and put the consequence into a plan question. Correct, continue, and record what the correction changed.
101
- - Answer a plan question rather than halting on it. Every question carries a `- Suggested:` line the operator accepts or overrules, so a judgment written down is the deliverable. Halt only on what blocks writing the record at all, and send that out as a message before it becomes a prompt.
112
+ - Answer a plan question rather than halting on it. Every question carries a `- Suggested:` line the operator accepts or overrules, so a judgment written down is the deliverable. Halt only on what blocks writing the record at all, and send that out as a message before it becomes a prompt. A talk launch is the exception, per `## Talk launch` above, where a question goes to the operator in the session.
102
113
 
103
114
  ## Lifetime
104
115
 
105
- - The role runs from the launch to the record landing, and one record closes it. A session handed a second row works it under the same role and reads the tree again for that row.
116
+ - The role runs from the launch to the record landing. The record closes the role, and the operator closes a talk session. A session handed a second row works it under the same role and reads the tree again for that row.
106
117
  - A reused session pays the context load once and stales differently. Its picture of the tree ages while it works, which is why the in-flight read runs per row, and it accumulates toward a compaction that drops the reasoning behind its earlier records with nothing reporting it. Cap a reused session rather than letting it run the board.
107
118
  - Treat this body as possibly older than the branch under it. A plugin skill loads from the marketplace cache rather than from the working tree.
@@ -35,7 +35,7 @@ from here.
35
35
 
36
36
  - Read the diff, the plan the branch built under, the task's `## Outcomes`, the rules the diff's paths load, and `review-craft`. That is the artifact and the contract the change answers to.
37
37
  - Read the pull request's `## For the reviewer` bullets and its `## Testing` section, which `review-pr` already bounds its read to, and stop there.
38
- - Leave the author's Summary and Technical Context unread while judging, and never open the worker's session or its transcript. Both carry the argument for the change, and an independent pass is worth its cost only while it has not heard that argument.
38
+ - Leave the author's Summary and Technical context unread while judging, and never open the worker's session or its transcript. Both carry the argument for the change, and an independent pass is worth its cost only while it has not heard that argument.
39
39
  - Read none of the above as a UI reviewer. `review-ui` states its own reads, being the checklist and the address, and a UI pass that has read the diff drives towards what it expects the code to do.
40
40
  - Treat the cross-branch facts the launch carries as facts rather than findings. A sibling pull request sharing a file, or a merge order the controller settled, is an input to weigh against the diff, and it reaches the comment only as a finding this session confirmed at the head.
41
41
 
@@ -32,6 +32,7 @@ The draft mark fails from both ends. On 2026-08-31 four sessions re-drafted a pu
32
32
  - Defer the addressee resolution to `session-relay` and keep only the operator ask and the last-rung inference, which discriminates here because a worker holds a feature branch and a controller does not, and which falls back to the roster and says so, since an operator's own launch names nobody
33
33
  - Keep refusing a dispatcher a first-class move carrying its evidence, since the halts measured so far were correct and the cost of each fell where it belonged
34
34
  - State that a held body may be older than the branch under it, since a plugin skill loads from the marketplace cache rather than from the working tree
35
+ - Carry a talk clause for a launch whose operator is in the session, asking them at a judgment call and sending a close message when they end the conversation, since a cold worker's halt-toward-the-controller and merge-ends-the-role rules contradict a brief that asks it to talk
35
36
  - Point at `session-worktree`, `auto-ship`, and `review-address` for the steps each already owns
36
37
 
37
38
  ## Must not
@@ -79,6 +79,14 @@ correct it. This rung stays here rather than in the relay because it differs
79
79
  between roles, and it discriminates for a worker because a worker holds a
80
80
  feature branch and a controller does not.
81
81
 
82
+ ## Talk launch
83
+
84
+ A launch whose brief says it is a talk session puts the operator in this one. Everything above holds, and the clause below changes where a judgment call goes and when the role ends. A launch carrying no such sentence takes none of this.
85
+
86
+ - Ask the operator in the session through the structured question surface at a judgment call, rather than halting toward the controller. A plan question written as needing the operator's call is put to them directly.
87
+ - Send the controller a close message when the operator ends the conversation, beside the announcements the channel above owes.
88
+ - Keep the before-prompt block message for a block the operator cannot answer. A question put to the operator who is in the session needs none.
89
+
82
90
  ## Refusing is part of the job
83
91
 
84
92
  - Refuse an instruction the tree contradicts, and carry the evidence with it. Name the commands read and the consequences of complying, rather than reporting reluctance.
@@ -92,5 +100,5 @@ feature branch and a controller does not.
92
100
 
93
101
  ## Lifetime
94
102
 
95
- - The role runs from the worktree entry to the merge of the branch it built, and nothing carries across to a second row. A worker handed another row after that is a new build under a new plan.
103
+ - The role runs from the worktree entry to the merge of the branch it built, and nothing carries across to a second row. A talk session outlives the merge and ends when the operator says the conversation is over. A worker handed another row after that is a new build under a new plan.
96
104
  - Treat this body as possibly older than the branch under it. A plugin skill loads from the marketplace cache rather than the working tree, so a session building a change to its own skills may be holding the copy from before the last update.
@@ -22,7 +22,7 @@ Decline where the session holds no reasoning a reader could not get faster from
22
22
  ## Guards
23
23
 
24
24
  - If `git rev-parse --git-dir` does not resolve, stop: `❌ Not a git repository. A session map takes its filename from the branch.`
25
- - Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. An empty result falls back to `latest` rather than stopping, since a handoff is scratch and a stop loses the reasoning the file exists to save.
25
+ - Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../git-branch/references/slug.md`. An empty result falls back to `latest` rather than stopping, since a handoff is scratch and a stop loses the reasoning the file exists to save.
26
26
  - Resolve the containing folder at the main worktree root with `git worktree list --porcelain | grep -m 1 '^worktree ' | cut -d' ' -f2-`. The guard above already stopped where that read has no repository to answer from, so it takes no fallback.
27
27
 
28
28
  ## Step 1: recover the commit the drift step reads
@@ -42,6 +42,6 @@ A resume is a read, and a session that treats it as a cleanup pass offers to arc
42
42
 
43
43
  - Writing a handoff, which happens at the close of a session rather than at its start. This skill names the standard that governs one and follows it no further.
44
44
  - The sections a role adds over the core handoff, which belong to that role's own surface
45
- - Archiving a shipped task out of the folder: `task-board`
46
- - Archiving a plan and marking an outcome, which `context-fold` does when the work ships
45
+ - Archiving a shipped task out of the folder: `task-complete`
46
+ - Marking an outcome, which `task-complete` does when the work ships, and archiving a plan, which the merge does
47
47
  - Implementing the item it recommends, which is the next request rather than part of this one
@@ -41,8 +41,8 @@ The directory test separates the defect from a genuinely bare repository, which
41
41
 
42
42
  Try each source in order. Stop at the first match.
43
43
 
44
- 0. **Caller-supplied.** The invocation carried an argument. Take it as the name and infer nothing further. Accept `<name>` or `<type>/<name>`, where a leading segment matching a type in `${CLAUDE_SKILL_DIR}/../../standards/branch.md` sets `<type>` and the rest is `<name>`. A bare `<name>` falls to the default type below.
45
- 1. **Plan matched to current branch.** Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. An empty result falls through to the next source here rather than becoming `latest`, since the slug is one candidate among several. If `<main-root>/.canon/plans/feature-<slug>.md` exists, use `<slug>`.
44
+ 0. **Caller-supplied.** The invocation carried an argument. Take it as the name and infer nothing further. Accept `<name>` or `<type>/<name>`, where a leading segment matching a type in `${CLAUDE_SKILL_DIR}/../git-branch/references/branch.md` sets `<type>` and the rest is `<name>`. A bare `<name>` falls to the default type below.
45
+ 1. **Plan matched to current branch.** Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../git-branch/references/slug.md`. An empty result falls through to the next source here rather than becoming `latest`, since the slug is one candidate among several. If `<main-root>/.canon/plans/feature-<slug>.md` exists, use `<slug>`.
46
46
  2. **Single plan file.** List `<main-root>/.canon/plans/feature-*.md`. If exactly one match, derive `<slug>` from the filename.
47
47
  3. **Multiple plan files, no branch match.** Ask the user which plan. Show the candidate slugs as a numbered list. Do not pick.
48
48
  4. **Current branch.** When no plan exists, use the `<slug>` from step 1 if it is not `main` or `master`.
@@ -53,7 +53,7 @@ Tier 0 sits ahead of the inference because every tier below it answers from stat
53
53
 
54
54
  Validate the result: letters, digits, dots, underscores, dashes only, max 64 chars (`/` separators are also allowed). If the derived name violates the rule, sanitize by replacing invalid chars with `-` and truncating. Show the sanitized name in the preview before invoking.
55
55
 
56
- Resolve `<type>` here as well, since Step 3 previews it and Step 5 renames onto it, drawing the value from the type vocabulary in `${CLAUDE_SKILL_DIR}/../../standards/branch.md`. A type the caller spelled in tier 0 wins outright and no reading overrides it. A name that came from a plan, through tier 1 or tier 2, takes its type from `canon tasks plan-branch <plan> --json`, read off the record's `type` field. Every other case takes `feat`, which covers a name from a branch, a bare name from the user, and a plan the verb could not answer for.
56
+ Resolve `<type>` here as well, since Step 3 previews it and Step 5 renames onto it, drawing the value from the type vocabulary in `${CLAUDE_SKILL_DIR}/../git-branch/references/branch.md`. A type the caller spelled in tier 0 wins outright and no reading overrides it. A name that came from a plan, through tier 1 or tier 2, takes its type from `canon tasks plan-branch <plan> --json`, read off the record's `type` field. Every other case takes `feat`, which covers a name from a branch, a bare name from the user, and a plan the verb could not answer for.
57
57
 
58
58
  The verb is the reading rather than this body, because a type read off a plan's sections is a judgment that two sessions reading one plan can grade differently, and the verb answers the same for both. The caller's type still wins over the verb's, because tier 0 is the one source that knows something no file states.
59
59
 
@@ -68,7 +68,7 @@ Then test both names the entry is about to claim. Neither read needs a worktree,
68
68
 
69
69
  Leave both in place. Resolving either automatically risks the wrong one.
70
70
 
71
- The two tests catch different collisions. The branch test misses the one `${CLAUDE_SKILL_DIR}/../../standards/slug.md` records, where two branches differing only in type collapse onto one name: `feat/foo` and `fix/foo` are distinct refs and reach one directory. The directory test is the only read that sees it.
71
+ The two tests catch different collisions. The branch test misses the one `${CLAUDE_SKILL_DIR}/../git-branch/references/slug.md` records, where two branches differing only in type collapse onto one name: `feat/foo` and `fix/foo` are distinct refs and reach one directory. The directory test is the only read that sees it.
72
72
 
73
73
  The branch test fires on the tier 1 and tier 4 sources whenever the branch the session started on is already conventional, since a name derived from that branch resolves back onto it. Stopping is the answer there. The concern already has a branch, git refuses a second under the same name, and the bare-name rename this replaces only carried the collision forward to the `git-branch` step. It fires on tier 0 as well, where a caller handed a name something already holds.
74
74
 
@@ -98,7 +98,7 @@ Call `EnterWorktree` with `name: "<name>"`. Claude Code's tool permission dialog
98
98
  git branch -m worktree-<name> <type>/<name>
99
99
  ```
100
100
 
101
- The slug transform drops a leading type segment, so `<name>` is what every downstream derivation reads back out of the typed branch. See `${CLAUDE_SKILL_DIR}/../../standards/slug.md`.
101
+ The slug transform drops a leading type segment, so `<name>` is what every downstream derivation reads back out of the typed branch. See `${CLAUDE_SKILL_DIR}/../git-branch/references/slug.md`.
102
102
 
103
103
  Step 2 already cleared the target name, so the rename runs unguarded here. Do not repeat the test. A ref created between the two points is a second session racing this one, which a re-read narrows rather than closes.
104
104
 
@@ -96,7 +96,7 @@ target project on the fly.
96
96
 
97
97
  On the `gov` phase, stop and present four options rather than picking:
98
98
 
99
- 1. Author a new rule in the toolkit at `governance/rules/<domain>/<num>-<name>.md` following `${CLAUDE_SKILL_DIR}/../../standards/rule.md`, commit, then re-run install. Take this route when the toolkit should ship the rule to every project.
99
+ 1. Author a new rule in the toolkit at `governance/rules/<domain>/<num>-<name>.md` following `${CLAUDE_SKILL_DIR}/../create-rule/references/rule.md`, commit, then re-run install. Take this route when the toolkit should ship the rule to every project.
100
100
  2. Invoke `create-rule`, which scaffolds the file into the target project at a non-colliding number. Take this route when the rule is specific to this project and no sync should ever overwrite it.
101
101
  3. Install the matching non-`<tech>` rules and skip the tech-specific layer.
102
102
  4. Abort.