@erclx/canon 4.121.0 → 4.122.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 (96) 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/backlog-triage/REQUIREMENT.md +47 -0
  4. package/claude/skills/backlog-triage/SKILL.md +139 -0
  5. package/claude/skills/canon-rollout/SKILL.md +6 -6
  6. package/claude/skills/context-fold/REQUIREMENT.md +75 -0
  7. package/claude/skills/context-fold/SKILL.md +162 -0
  8. package/claude/skills/{docs-fold → context-fold}/references/anchor-sweep.md +1 -1
  9. package/claude/skills/{docs-fold → context-fold}/references/classify.md +4 -2
  10. package/claude/skills/context-fold/references/context-refresh.md +48 -0
  11. package/claude/skills/context-fold/references/promoted-pages.md +29 -0
  12. package/claude/skills/context-fold/references/receipt-sweep.md +43 -0
  13. package/claude/skills/context-fold/references/unusable-baseline.md +25 -0
  14. package/claude/skills/{docs-fold → context-fold}/references/wireframe-sweep.md +1 -1
  15. package/claude/skills/docs-fold/REQUIREMENT.md +8 -58
  16. package/claude/skills/docs-fold/SKILL.md +3 -278
  17. package/claude/skills/docs-sync/REQUIREMENT.md +1 -1
  18. package/claude/skills/docs-sync/SKILL.md +1 -1
  19. package/claude/skills/draft-context/REQUIREMENT.md +2 -2
  20. package/claude/skills/draft-context/SKILL.md +3 -3
  21. package/claude/skills/draft-docs/REQUIREMENT.md +1 -1
  22. package/claude/skills/draft-wireframes/REQUIREMENT.md +1 -1
  23. package/claude/skills/draft-wireframes/SKILL.md +2 -2
  24. package/claude/skills/git-pr/SKILL.md +8 -146
  25. package/claude/skills/git-pr/references/evidence.md +114 -0
  26. package/claude/skills/git-pr/references/labels.md +20 -0
  27. package/claude/skills/git-pr/references/task-number.md +26 -0
  28. package/claude/skills/git-ship/SKILL.md +1 -1
  29. package/claude/skills/memory-capture/REQUIREMENT.md +2 -2
  30. package/claude/skills/memory-capture/SKILL.md +5 -5
  31. package/claude/skills/memory-review/REQUIREMENT.md +1 -1
  32. package/claude/skills/memory-review/SKILL.md +5 -101
  33. package/claude/skills/memory-review/references/later-phases.md +108 -0
  34. package/claude/skills/plan-feature/REQUIREMENT.md +1 -1
  35. package/claude/skills/review-address/REQUIREMENT.md +1 -1
  36. package/claude/skills/review-address/SKILL.md +1 -1
  37. package/claude/skills/review-branch/SKILL.md +1 -1
  38. package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +1 -1
  39. package/claude/skills/role-orchestrator/references/orchestrator-parked.md +2 -0
  40. package/claude/skills/role-orchestrator/references/orchestrator-refill.md +2 -2
  41. package/claude/skills/session-resume/REQUIREMENT.md +1 -1
  42. package/claude/skills/session-worktree/SKILL.md +4 -10
  43. package/claude/skills/task-board/REQUIREMENT.md +1 -1
  44. package/claude/skills/task-board/SKILL.md +6 -80
  45. package/claude/skills/task-board/references/archive.md +54 -0
  46. package/claude/skills/task-board/references/decline.md +40 -0
  47. package/claude/skills/teach-workspace/SKILL.md +8 -105
  48. package/claude/skills/teach-workspace/references/lesson-craft.md +51 -1
  49. package/claude/skills/teach-workspace/references/promotion.md +41 -0
  50. package/docs/agents/architecture-record.md +26 -0
  51. package/docs/agents/commands.md +87 -154
  52. package/docs/agents/context-audit-checks.md +2 -20
  53. package/docs/agents/context-audit.md +1 -1
  54. package/docs/agents/context-classify.md +1 -1
  55. package/docs/agents/drift-surfaces.md +192 -0
  56. package/docs/agents/index.md +12 -4
  57. package/docs/agents/install-and-sync.md +2 -181
  58. package/docs/agents/markdown-audit-weight.md +73 -0
  59. package/docs/agents/markdown-audit.md +3 -90
  60. package/docs/agents/migrate.md +34 -0
  61. package/docs/agents/records-stale.md +62 -0
  62. package/docs/agents/records.md +5 -1
  63. package/docs/agents/sandbox.md +1 -1
  64. package/docs/agents/tasks-archive.md +81 -0
  65. package/docs/agents/tasks-plans.md +147 -0
  66. package/docs/agents/tasks-validate.md +131 -0
  67. package/docs/agents/tasks.md +6 -333
  68. package/docs/target-projects.md +3 -3
  69. package/docs/workflow/ai-workflow.md +32 -27
  70. package/governance/rules/core/045-memory.md +1 -1
  71. package/package.json +1 -1
  72. package/src/claude/cases/setup.ts +1 -1
  73. package/src/claude/cases/workflow.ts +22 -1
  74. package/src/commands/records.ts +146 -0
  75. package/src/commands/sandbox.ts +6 -4
  76. package/src/context/classify/extract.ts +1 -1
  77. package/src/context/classify/ollama.ts +1 -1
  78. package/src/context/classify/run.ts +1 -1
  79. package/src/gate/measures.ts +1 -1
  80. package/src/migrate/skill-names.ts +15 -2
  81. package/src/records/stale.ts +243 -0
  82. package/src/sandbox/expect.ts +1 -1
  83. package/src/tasks/archive.ts +28 -4
  84. package/src/tasks/record.ts +1 -1
  85. package/src/tasks/validate.ts +36 -3
  86. package/standards/memory.md +13 -1
  87. package/standards/tasks.md +1 -1
  88. package/tooling/astro/reference.md +1 -1
  89. package/tooling/base/configs/.husky/post-merge +1 -1
  90. package/tooling/claude/reference.md +1 -1
  91. package/tooling/go/reference.md +1 -1
  92. package/tooling/nextjs/reference.md +1 -1
  93. package/tooling/php/reference.md +1 -1
  94. package/tooling/python/reference.md +1 -1
  95. package/tooling/vite-react/reference.md +1 -1
  96. package/tooling/web/reference.md +1 -1
@@ -58,7 +58,7 @@ Read in parallel from the project root. Skip any file or folder that does not ex
58
58
 
59
59
  `.canon/memory/` is a holding pen. Default every entry to promote or retire on review. Skip is the rare exception, reserved for active task overlap or user-type memories with no in-repo target.
60
60
 
61
- `memory-capture` routes a project fact naming a domain with a context entry to that entry, so a pen filled since routing shipped is mostly feedback: rules about how to work, which no context entry owns. Propose against what the pen holds rather than expecting the older mix. An entry carried from before routing may still name a domain that has a context entry, and that entry's action is **Promote to a context entry**, which hands it to `docs-fold` the same way capture does rather than editing the entry here.
61
+ `memory-capture` routes a project fact naming a domain with a context entry to that entry, so a pen filled since routing shipped is mostly feedback: rules about how to work, which no context entry owns. Propose against what the pen holds rather than expecting the older mix. An entry carried from before routing may still name a domain that has a context entry, and that entry's action is **Promote to a context entry**, which hands it to `context-fold` the same way capture does rather than editing the entry here.
62
62
 
63
63
  For each in-scope entry (see Scope), pick one action:
64
64
 
@@ -67,7 +67,7 @@ For each in-scope entry (see Scope), pick one action:
67
67
  - In a target project, append the rule to an existing file under `.claude/rules/project/` with `Edit`, since a project rule is project-owned and sync never overwrites it, or hand off to the `create-rule` skill when no existing file fits.
68
68
  - **Promote to a skill body**: the rule fires only when editing a specific path-scoped domain. Name the target skill.
69
69
  - **Promote to a standards file**: the rule is an authoring reference that belongs in the project's own standards folder as `<domain>.md`.
70
- - **Promote to a context entry**: the entry states a fact about a domain carrying an entry in `canon/context/index.md`. Append it to `.canon/tmp/handoff/memory-routing/<slug>.md` at the main worktree root, in the format `memory-capture` writes, and tell the user to run `/docs-fold` from a branch. Do not edit the context entry here. A project-identity or command fact takes this action when a context entry owns the subject, such as a development entry for commands, and **Retire** otherwise, naming a hand edit to `CLAUDE.md` as the reason. Memory review does not write the root file itself.
70
+ - **Promote to a context entry**: the entry states a fact about a domain carrying an entry in `canon/context/index.md`. Append it to `.canon/tmp/handoff/memory-routing/<slug>.md` at the main worktree root, in the format `memory-capture` writes, and tell the user to run `/context-fold` from a branch. Do not edit the context entry here. A project-identity or command fact takes this action when a context entry owns the subject, such as a development entry for commands, and **Retire** otherwise, naming a hand edit to `CLAUDE.md` as the reason. Memory review does not write the root file itself.
71
71
  - **Hand off to governance**: the rule is coding-standards class (typescript, testing, naming, error-handling, performance, logging, concurrency, planning), never a cross-domain behavior rule. Do not author the rule file inline. Never edit the synced `.claude/rules/` copies of toolkit rules, because `canon gov sync` overwrites them. Stop at handoff. This and **Promote to an always-loaded rule** never both claim one entry: class names the topic (coding-standards routes here), firing axis names the rest (applies-every-session routes to the rule promote).
72
72
  - In the toolkit repo, point the user at `internal-governance` and `${CLAUDE_SKILL_DIR}/../../standards/rule.md`, which own the source-of-truth rules under `governance/rules/`.
73
73
  - In a target project, point the user at the `create-rule` skill, which scaffolds a project-local rule under `.claude/rules/`.
@@ -91,7 +91,7 @@ Rules that resist crisp one-line phrasing default to **Retire** over promote. Ne
91
91
 
92
92
  Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. Fall back to `latest` on an empty result.
93
93
 
94
- Write the full proposal to `.canon/memory/review/memory-review-<slug>.md` at the main worktree root. Do not print it inline. Read `${CLAUDE_SKILL_DIR}/references/receipt-format.md` for the file structure, the item template, and how each action type varies the body. The four phases below rewrite items inside an existing receipt rather than authoring one, so none of them opens it.
94
+ Write the full proposal to `.canon/memory/review/memory-review-<slug>.md` at the main worktree root. Do not print it inline. Read `${CLAUDE_SKILL_DIR}/references/receipt-format.md` for the file structure, the item template, and how each action type varies the body. The four later phases rewrite items inside an existing receipt rather than authoring one, so none of them opens it.
95
95
 
96
96
  A phase changing items reads the receipt, applies every change for that phase, and writes the whole file back in one command. Batching is what keeps a per-item rewrite from costing a full read each time, and it is the only route from a linked worktree, where the guard above rules out editing a line in place.
97
97
 
@@ -99,105 +99,9 @@ Tell the user `✅ Wrote proposal to .canon/memory/review/memory-review-<slug>.m
99
99
 
100
100
  Rewrite the review file in place whenever the proposal changes mid-review. The file stays the source of truth for the current decisions.
101
101
 
102
- ## Challenge phase
102
+ ## Challenge, Discuss, Apply, and Cleanup phases
103
103
 
104
- Trigger: user says "challenge the promotes", "challenge before apply", or asks for a high-bar pass. Run before Apply. No mutations to memory files or promotion targets. Review file only.
105
-
106
- 1. Read the latest `.canon/memory/review/memory-review-*.md` at the main root.
107
- 2. For each promote item, apply three tests:
108
- - **Absorbed**: grep the target surface for the rule's keywords. If already stated or implied, flip to retire.
109
- - **Delta**: if the rule is a nice-to-have next to existing bullets, flip to retire.
110
- - **Generality**: if the rule fires only on one literal trigger phrase, rewrite broader or flip to retire.
111
- 3. Rewrite the review file in place with the updated actions and a one-line reason under each flip.
112
-
113
- ## Discuss phase
114
-
115
- Trigger: user says "discuss", "respond to questions", or any `Decision:` value contains `?` or an unrecognized verb. No mutations to memory files or targets. Review file only. Multi-round.
116
-
117
- 1. Read the latest `.canon/memory/review/memory-review-*.md` at the main root.
118
- 2. For each item whose `Decision:` contains `?` or any unrecognized verb (anything other than `apply`, `skip`, `defer`):
119
- - Write a `Take:` line under `Decision:`, separated by exactly one blank line. If a `Take:` line already exists, overwrite it.
120
- - Format: pick + one-line reason. Max 2 sentences. Decision-help style. State the recommendation (`apply` / `skip` / `retire` / specific alternative) first, then the reason. Do not enumerate tradeoffs unless one changes the call.
121
- - Leave the H2 emoji as 📝 pending.
122
- 3. Skip items whose `Decision:` is `apply`, `skip`, `defer`, or empty.
123
- 4. End with: `💬 Discussed: <nums> | ⏩ Skipped (committed or empty): <nums>`. Remind the user to refine `Decision:` lines and re-ping with "discuss" for another round, or "apply" when ready to commit.
124
-
125
- Do not act on any item. Do not archive memory files. Do not edit promotion targets. Discuss only.
126
-
127
- ## Apply phase
128
-
129
- Trigger: user says "apply", "commit", "ship the review", or re-pings with no question items remaining. Mutates tracked promotion targets and moves memory files into the archive.
130
-
131
- Before applying any item, check the worktree state:
132
-
133
- ```bash
134
- [ "$(git rev-parse --git-dir 2>/dev/null)" = "$(git rev-parse --git-common-dir 2>/dev/null)" ] && echo "MAIN" || echo "LINKED"
135
- ```
136
-
137
- If the result is `MAIN`, stop and tell the user: `❌ Apply phase mutates tracked files. Run /session-worktree first.` Discuss and Challenge phases only touch `.canon/review/` scratch and run from anywhere.
138
-
139
- Before applying a promote to an always-loaded rule in the toolkit repo, load `internal-governance`, which owns `internal/rules/core/` and `governance/rules/core/` and is the only route that may author into either. In a target project, hand off to `create-rule` with no load, since `internal-governance` is a toolkit-internal skill under `.claude/skills/` that a target project never has. An `Edit` appending to an existing file under `.claude/rules/project/` needs no load either.
140
-
141
- Promotions are a separate concern from any feature in flight. Keep the promoted edits on their own commit. Do not fold an always-loaded-rule or skill-body change into a feature's commits, because a feature reviewer should not have to vet a change to how the agent operates.
142
-
143
- For each item, parse the `Decision:` line:
144
-
145
- - `apply` (or affirmative): run the proposed action, flip emoji to ✅.
146
- - `skip`: leave the memory in place, flip emoji to ⏭.
147
- - `defer` or empty: leave 📝 pending, take no action.
148
- - Contains `?` or unrecognized verb: leave 📝 pending, take no action. Do not respond. Discussion is the Discuss phase's job.
149
-
150
- Free-form text after the verb is a reason. Capture it in the receipt but do not let it change the action. When committing an item, strip any empty `Take:` line so the receipt stays clean. `Take:` lines with content stay as discussion history.
151
-
152
- Action by action type:
153
-
154
- - **Promote**: use `Edit` to insert the rewritten rule into the target surface, then archive the memory file. A promote to an always-loaded rule in the toolkit repo never reaches this line: it stops as a handoff to `internal-governance`, the same as **Hand off** below, and archives only on the user's explicit confirmation.
155
- - **Promote to a context entry**: append the fact to `.canon/tmp/handoff/memory-routing/<slug>.md` at the main worktree root, then archive the memory file. `docs-fold` folds it in on its next run from a branch, which is what keeps one skill writing context entries.
156
- - **Hand off**: do not edit governance. Archive the memory file only if the user confirmed the handoff explicitly. Otherwise leave it in place.
157
- - **Retire**: archive the memory file.
158
-
159
- Archiving means creating `.canon/memory/archive/` at the main worktree root and moving the file there under its original name, overwriting any file already at that name. Send the `mkdir -p` and a plain `mv`, routed the way `session-worktree` states for a main-root move. Never delete a memory entry. Nothing recovers one from a gitignored folder.
160
-
161
- Do not hand-edit `.canon/memory/index.md`. Once every archive move is done, regenerate it instead:
162
-
163
- ```bash
164
- canon indexes regen --no-stage --root <main-root> <main-root>/.canon/memory/index.md
165
- ```
166
-
167
- An archive move is a shell `mv`, which skips the index hook the way `session-worktree` states. Without this call the index keeps a row per archived entry and drifts exactly the way the hand-appended one did. Run it once after the last move rather than per item.
168
-
169
- Apply promotion edits one at a time via `Edit`. Claude Code's tool permission dialog is the confirmation gate per edit. Never rewrite a whole promotion target.
170
-
171
- This governs the tracked surfaces a promote lands in, which sit at `pwd` and take `Edit` from anywhere. The receipt and the memory entries are main-root scratch and follow the guard instead.
172
-
173
- As each item resolves, update its status in the review file: flip the H2 emoji from 📝 to ✅ for applied, ⏭ for skipped, 📦 for retired, or 🤝 for handed off. Refresh the summary block counts at the top. Do not delete the file here. The sweep below decides whether it goes.
174
-
175
- **Chat shortcut:** the user replies with `all`, `none`, a comma-separated list of numbers, or `skip <nums>`. Write the matching verb into the `Decision:` slot of every item the reply names, `apply` for `all` or a bare list and `skip` for a `skip` reply, then run the parse above against the file. A reply of `none` writes nothing. A slot the reply does not name keeps its own value, so the receipt stays the source of truth and an empty slot still means take no action.
176
-
177
- ### Sweep the receipt
178
-
179
- Count the items still pending once the parse above has run. An item is pending when its H2 carries 📝, or when its H2 carries no status emoji and its `Decision:` slot holds nothing the parse above would act on or skip, since a receipt written by hand or by an older binary may lack the marker. Apply leaves one pending on `defer`, on empty, and on any unrecognized verb, so a receipt reaching this point may still be holding decisions.
180
-
181
- Leave the receipt in place when any remain. When none do, collect it per the collection rule in `${CLAUDE_SKILL_DIR}/../../standards/memory.md`, which owns what a fold writes and which entry types take one.
182
-
183
- `docs-fold` Step 9 sweeps the same folder on the same rule once per shipped branch, and either may reach a receipt first. Whichever does, the other finds no file and moves on.
184
-
185
- End with: `✅ Applied: <nums> | ⏭ Skipped: <nums> | 📝 Pending: <nums>`. Omit empty buckets. If anything is pending, remind the user they can refine `Decision:` lines and re-ping, run "discuss" for question items, or commit a skip with `skip <nums>` in chat.
186
-
187
- ## Cleanup phase
188
-
189
- Trigger: user says "cleanup" or "delete the receipt" after Apply has run.
190
-
191
- Cleanup folds one receipt's skips and removes that receipt, and does nothing else. It is the fallback route now that Apply and `docs-fold` Step 9 each collect a resolved receipt on their own, so it reaches a file those two left behind rather than being the only collector. Apply is still the only phase that moves a memory entry out of the pen, and it does so per approved item into `.canon/memory/archive/`. A user asking to sweep stale memories wants Propose, which classifies entries and writes a decision slot per entry.
192
-
193
- If no `.canon/memory/review/memory-review-*.md` exists at the main root, stop: `✅ No review receipt to clean up.` Every other refusal in this skill carries a message, and the phase reads a receipt before it does anything else.
194
-
195
- 1. Read the latest `.canon/memory/review/memory-review-*.md` at the main root and confirm Apply has run against it. If any item is still pending, by the test the Apply sweep states, stop and name the pending numbers.
196
- 2. Collect it per the collection rule in `${CLAUDE_SKILL_DIR}/../../standards/memory.md`, folding each ⏭ skipped item before the file goes. The fold happens wherever a receipt is collected, so this phase runs the same rule the Apply sweep does.
197
- 3. Delete that one file. Leave every other receipt beside it in place, because the pending test above covers the file it read and nothing has tested the rest.
198
- 4. Leave every memory entry in the pen. A skip records the decline on the entry and keeps the file, and applied promotions, governance handoffs, and user-type memories each stay as the review left them.
199
-
200
- Do not promote or archive a memory entry. The skip fold is the one rewrite this phase makes, and it records a decline on an entry that stays in the pen.
104
+ Each later phase runs on its own invocation against a receipt Propose already wrote, picked by the table above. Read `${CLAUDE_SKILL_DIR}/references/later-phases.md` on reaching any of them, for the phase's trigger, what it may mutate, its procedure, and the line it ends on. Challenge and Discuss rewrite the review file only, Apply stops on the main worktree, and Cleanup removes one receipt.
201
105
 
202
106
  ## After completion
203
107
 
@@ -0,0 +1,108 @@
1
+ ---
2
+ title: Memory review later phases
3
+ description: The Challenge, Discuss, Apply, and Cleanup phases of memory-review, each run on its own invocation against a receipt the Propose phase already wrote
4
+ ---
5
+
6
+ # Memory review later phases
7
+
8
+ The phases of `memory-review` after Propose. The session reads this file when the phase table in the skill picks Challenge, Discuss, Apply, or Cleanup, and reads only the section for that phase. The skill's Guards still hold for every phase here.
9
+
10
+ ## Challenge phase
11
+
12
+ Trigger: user says "challenge the promotes", "challenge before apply", or asks for a high-bar pass. Run before Apply. No mutations to memory files or promotion targets. Review file only.
13
+
14
+ 1. Read the latest `.canon/memory/review/memory-review-*.md` at the main root.
15
+ 2. For each promote item, apply three tests:
16
+ - **Absorbed**: grep the target surface for the rule's keywords. If already stated or implied, flip to retire.
17
+ - **Delta**: if the rule is a nice-to-have next to existing bullets, flip to retire.
18
+ - **Generality**: if the rule fires only on one literal trigger phrase, rewrite broader or flip to retire.
19
+ 3. Rewrite the review file in place with the updated actions and a one-line reason under each flip.
20
+
21
+ ## Discuss phase
22
+
23
+ Trigger: user says "discuss", "respond to questions", or any `Decision:` value contains `?` or an unrecognized verb. No mutations to memory files or targets. Review file only. Multi-round.
24
+
25
+ 1. Read the latest `.canon/memory/review/memory-review-*.md` at the main root.
26
+ 2. For each item whose `Decision:` contains `?` or any unrecognized verb (anything other than `apply`, `skip`, `defer`):
27
+ - Write a `Take:` line under `Decision:`, separated by exactly one blank line. If a `Take:` line already exists, overwrite it.
28
+ - Format: pick + one-line reason. Max 2 sentences. Decision-help style. State the recommendation (`apply` / `skip` / `retire` / specific alternative) first, then the reason. Do not enumerate tradeoffs unless one changes the call.
29
+ - Leave the H2 emoji as 📝 pending.
30
+ 3. Skip items whose `Decision:` is `apply`, `skip`, `defer`, or empty.
31
+ 4. End with: `💬 Discussed: <nums> | ⏩ Skipped (committed or empty): <nums>`. Remind the user to refine `Decision:` lines and re-ping with "discuss" for another round, or "apply" when ready to commit.
32
+
33
+ Do not act on any item. Do not archive memory files. Do not edit promotion targets. Discuss only.
34
+
35
+ ## Apply phase
36
+
37
+ Trigger: user says "apply", "commit", "ship the review", or re-pings with no question items remaining. Mutates tracked promotion targets and moves memory files into the archive.
38
+
39
+ Before applying any item, check the worktree state:
40
+
41
+ ```bash
42
+ [ "$(git rev-parse --git-dir 2>/dev/null)" = "$(git rev-parse --git-common-dir 2>/dev/null)" ] && echo "MAIN" || echo "LINKED"
43
+ ```
44
+
45
+ If the result is `MAIN`, stop and tell the user: `❌ Apply phase mutates tracked files. Run /session-worktree first.` Discuss and Challenge phases only touch `.canon/review/` scratch and run from anywhere.
46
+
47
+ Before applying a promote to an always-loaded rule in the toolkit repo, load `internal-governance`, which owns `internal/rules/core/` and `governance/rules/core/` and is the only route that may author into either. In a target project, hand off to `create-rule` with no load, since `internal-governance` is a toolkit-internal skill under `.claude/skills/` that a target project never has. An `Edit` appending to an existing file under `.claude/rules/project/` needs no load either.
48
+
49
+ Promotions are a separate concern from any feature in flight. Keep the promoted edits on their own commit. Do not fold an always-loaded-rule or skill-body change into a feature's commits, because a feature reviewer should not have to vet a change to how the agent operates.
50
+
51
+ For each item, parse the `Decision:` line:
52
+
53
+ - `apply` (or affirmative): run the proposed action, flip emoji to ✅.
54
+ - `skip`: leave the memory in place, flip emoji to ⏭.
55
+ - `defer` or empty: leave 📝 pending, take no action.
56
+ - Contains `?` or unrecognized verb: leave 📝 pending, take no action. Do not respond. Discussion is the Discuss phase's job.
57
+
58
+ Free-form text after the verb is a reason. Capture it in the receipt but do not let it change the action. When committing an item, strip any empty `Take:` line so the receipt stays clean. `Take:` lines with content stay as discussion history.
59
+
60
+ Action by action type:
61
+
62
+ - **Promote**: use `Edit` to insert the rewritten rule into the target surface, then archive the memory file. A promote to an always-loaded rule in the toolkit repo never reaches this line: it stops as a handoff to `internal-governance`, the same as **Hand off** below, and archives only on the user's explicit confirmation.
63
+ - **Promote to a context entry**: append the fact to `.canon/tmp/handoff/memory-routing/<slug>.md` at the main worktree root, then archive the memory file. `context-fold` folds it in on its next run from a branch, which is what keeps one skill writing context entries.
64
+ - **Hand off**: do not edit governance. Archive the memory file only if the user confirmed the handoff explicitly. Otherwise leave it in place.
65
+ - **Retire**: archive the memory file.
66
+
67
+ Archiving means creating `.canon/memory/archive/` at the main worktree root and moving the file there under its original name, overwriting any file already at that name. Send the `mkdir -p` and a plain `mv`, routed the way `session-worktree` states for a main-root move. Never delete a memory entry. Nothing recovers one from a gitignored folder.
68
+
69
+ Do not hand-edit `.canon/memory/index.md`. Once every archive move is done, regenerate it instead:
70
+
71
+ ```bash
72
+ canon indexes regen --no-stage --root <main-root> <main-root>/.canon/memory/index.md
73
+ ```
74
+
75
+ An archive move is a shell `mv`, which skips the index hook the way `session-worktree` states. Without this call the index keeps a row per archived entry and drifts exactly the way the hand-appended one did. Run it once after the last move rather than per item.
76
+
77
+ Apply promotion edits one at a time via `Edit`. Claude Code's tool permission dialog is the confirmation gate per edit. Never rewrite a whole promotion target.
78
+
79
+ This governs the tracked surfaces a promote lands in, which sit at `pwd` and take `Edit` from anywhere. The receipt and the memory entries are main-root scratch and follow the skill's heredoc guard instead.
80
+
81
+ As each item resolves, update its status in the review file: flip the H2 emoji from 📝 to ✅ for applied, ⏭ for skipped, 📦 for retired, or 🤝 for handed off. Refresh the summary block counts at the top. Do not delete the file here. The sweep below decides whether it goes.
82
+
83
+ **Chat shortcut:** the user replies with `all`, `none`, a comma-separated list of numbers, or `skip <nums>`. Write the matching verb into the `Decision:` slot of every item the reply names, `apply` for `all` or a bare list and `skip` for a `skip` reply, then run the parse above against the file. A reply of `none` writes nothing. A slot the reply does not name keeps its own value, so the receipt stays the source of truth and an empty slot still means take no action.
84
+
85
+ ### Sweep the receipt
86
+
87
+ Count the items still pending once the parse above has run. An item is pending when its H2 carries 📝, or when its H2 carries no status emoji and its `Decision:` slot holds nothing the parse above would act on or skip, since a receipt written by hand or by an older binary may lack the marker. Apply leaves one pending on `defer`, on empty, and on any unrecognized verb, so a receipt reaching this point may still be holding decisions.
88
+
89
+ Leave the receipt in place when any remain. When none do, collect it per the collection rule in `${CLAUDE_SKILL_DIR}/../../standards/memory.md`, which owns what a fold writes and which entry types take one.
90
+
91
+ `context-fold` Step 9 sweeps the same folder on the same rule once per shipped branch, and either may reach a receipt first. Whichever does, the other finds no file and moves on.
92
+
93
+ End with: `✅ Applied: <nums> | ⏭ Skipped: <nums> | 📝 Pending: <nums>`. Omit empty buckets. If anything is pending, remind the user they can refine `Decision:` lines and re-ping, run "discuss" for question items, or commit a skip with `skip <nums>` in chat.
94
+
95
+ ## Cleanup phase
96
+
97
+ Trigger: user says "cleanup" or "delete the receipt" after Apply has run.
98
+
99
+ Cleanup folds one receipt's skips and removes that receipt, and does nothing else. It is the fallback route now that Apply and `context-fold` Step 9 each collect a resolved receipt on their own, so it reaches a file those two left behind rather than being the only collector. Apply is still the only phase that moves a memory entry out of the pen, and it does so per approved item into `.canon/memory/archive/`. A user asking to sweep stale memories wants Propose, which classifies entries and writes a decision slot per entry.
100
+
101
+ If no `.canon/memory/review/memory-review-*.md` exists at the main root, stop: `✅ No review receipt to clean up.` Every other refusal in this skill carries a message, and the phase reads a receipt before it does anything else.
102
+
103
+ 1. Read the latest `.canon/memory/review/memory-review-*.md` at the main root and confirm Apply has run against it. If any item is still pending, by the test the Apply sweep states, stop and name the pending numbers.
104
+ 2. Collect it per the collection rule in `${CLAUDE_SKILL_DIR}/../../standards/memory.md`, folding each ⏭ skipped item before the file goes. The fold happens wherever a receipt is collected, so this phase runs the same rule the Apply sweep does.
105
+ 3. Delete that one file. Leave every other receipt beside it in place, because the pending test above covers the file it read and nothing has tested the rest.
106
+ 4. Leave every memory entry in the pen. A skip records the decline on the entry and keeps the file, and applied promotions, governance handoffs, and user-type memories each stay as the review left them.
107
+
108
+ Do not promote or archive a memory entry. The skip fold is the one rewrite this phase makes, and it records a decline on an entry that stays in the pen.
@@ -35,4 +35,4 @@ Without this skill, implementation starts before anyone knows what it touches. A
35
35
 
36
36
  - Executing the plan, which is the ship pipeline
37
37
  - Task-board state, which `task-board` owns. A plan links to its task and does not create one.
38
- - Reconciling the planning docs after the work lands, which `docs-fold` owns
38
+ - Reconciling the planning docs after the work lands, which `context-fold` owns
@@ -52,6 +52,6 @@ A declined finding fails on a third axis, which is where its reason ends up. A w
52
52
 
53
53
  - Writing the review, which `review-pr` owns. The split is by side of the channel: that one posts findings from an independent session and this one is the worker's return leg.
54
54
  - Staging, committing, and pushing the follow-up, which `git-followup` owns under this skill's direction
55
- - Refreshing the `.claude/` docs the fixes made stale, which `docs-fold` owns
55
+ - Refreshing the `.claude/` docs the fixes made stale, which `context-fold` owns
56
56
  - Re-reviewing its own fixes, which hands back to the orchestrator
57
57
  - Re-reading a rewritten branch, which `review-pr` absorbs by testing whether the prior reviewed commit still reaches the head and paying for a full pass when it does not
@@ -46,7 +46,7 @@ Do not push a red follow-up.
46
46
 
47
47
  ## Step 4: refresh stale docs
48
48
 
49
- The fixes may have changed or added behavior that `.claude/` context entries, docs, or wireframes describe. Refresh them with the `docs-fold` skill, which maps the changed files to the entries that reference them and rewrites the stale sections. Do not reimplement that mapping here. When a fix adds a new capability with no existing entry, `docs-fold` flags it rather than creating one.
49
+ The fixes may have changed or added behavior that `.claude/` context entries, docs, or wireframes describe. Refresh them with the `context-fold` skill, which maps the changed files to the entries that reference them and rewrites the stale sections. Do not reimplement that mapping here. When a fix adds a new capability with no existing entry, `context-fold` flags it rather than creating one.
50
50
 
51
51
  ## Step 5: rebase a stale branch
52
52
 
@@ -121,7 +121,7 @@ If there are no findings, write `✅ No findings.` to the file with a timestamp.
121
121
 
122
122
  The `.canon/review/` directory is gitignored. Do not stage or commit the file.
123
123
 
124
- The report is disposable. It outlives the ship chain that reads it, and `docs-fold` sweeps it once the branch it names is gone, because the durable record of what a review found is the comment `review-pr` posts on the pull request. A review run on a branch that never opens one leaves nothing behind once that branch is gone, so fold anything worth keeping into the pull request body or a task finding while the report is still on disk.
124
+ The report is disposable. It outlives the ship chain that reads it, and `context-fold` sweeps it once the branch it names is gone, because the durable record of what a review found is the comment `review-pr` posts on the pull request. A review run on a branch that never opens one leaves nothing behind once that branch is gone, so fold anything worth keeping into the pull request body or a task finding while the report is still on disk.
125
125
 
126
126
  ### Chat output
127
127
 
@@ -70,7 +70,7 @@ Take the comparison at the file path rather than at a folder above it. `canon ta
70
70
 
71
71
  The finding names which row contributed the containing path, and a bare-folder cell reports as a claim of its own beside the findings. Read that output as a candidate list, settle each pair by file, and narrow the cell that over-claimed rather than discounting the collision it caused.
72
72
 
73
- A declared set is what a branch sets out to write rather than a bound on it, so this gate clears against a prediction and the branch outgrows it hours later. A track can cross the set it cleared against and still merge clean, which is a gate reporting disjoint while a real overlap stood. Two classes account for nearly all of the crossing. The ship chain's own steps write past every plan, since `canon:docs-fold` refreshes whichever context entry a change reaches and `canon:docs-sync` reaches the public docs, and neither surface is one a planner can name before the change exists. The drift stages `bun run check` regenerates and asserts are the second, together with the test and sandbox siblings a source change drags in. Nothing here prevents either, because the files at issue are written long after this gate clears. What reads the other end is `canon tasks plan-reach`, which `canon:git-ship` runs at step 5 against the branch's own diff, so a crossing this gate could not see is named before the pull request opens rather than after it merges.
73
+ A declared set is what a branch sets out to write rather than a bound on it, so this gate clears against a prediction and the branch outgrows it hours later. A track can cross the set it cleared against and still merge clean, which is a gate reporting disjoint while a real overlap stood. Two classes account for nearly all of the crossing. The ship chain's own steps write past every plan, since `canon:context-fold` refreshes whichever context entry a change reaches and `canon:docs-sync` reaches the public docs, and neither surface is one a planner can name before the change exists. The drift stages `bun run check` regenerates and asserts are the second, together with the test and sandbox siblings a source change drags in. Nothing here prevents either, because the files at issue are written long after this gate clears. What reads the other end is `canon tasks plan-reach`, which `canon:git-ship` runs at step 5 against the branch's own diff, so a crossing this gate could not see is named before the pull request opens rather than after it merges.
74
74
 
75
75
  Disjointness is necessary and not sufficient, so hold a candidate whose sets do not touch when a stated reason serializes it, and write the reason on the hold. One row creating a skill and another auditing that catalog and counting it write nothing in common, and dispatching both still leaves the audit counting a denominator that moves underneath it. Nothing verifies that a reason was written, so the rule holds only while the dispatcher applies it.
76
76
 
@@ -41,6 +41,8 @@ Clearing a row answers yes to that question. It is not a count of how long the r
41
41
 
42
42
  A row this test clears moves out of `backlog.md` and onto the bottom of `## Needs a plan`, carrying a `Waiting on` cell that states what changed and ends with the word `last`. `canon tasks validate`'s ordering check reads `last` as the ordinal bottom placement already claims, and a cell stating only what changed matches neither that check's ordinal reading nor its rank reading, which raises the finding this pass would then have written against its own row. The next refill sweep's promotion step still orders the row against the rest of that heading the way it orders every other row there, per step 5 under `## Refilling the ready queue` in `role-orchestrator`.
43
43
 
44
+ This pass only clears a row upward. Declining or archiving a backlog row is `backlog-triage`, which files a verdict for every row and applies the ones the operator approved.
45
+
44
46
  ## Two ways a re-test goes wrong
45
47
 
46
48
  Both return a confident wrong answer rather than an error, which is why each gets a step of its own.
@@ -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 `docs-fold` for the plan sweep, then `task-board` to archive
17
+ - A task whose outcomes are all `[x]` runs `context-fold` for the plan sweep, then `task-board` to archive
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.
@@ -53,4 +53,4 @@ Promoting, demoting, and archiving a row all write `.canon/tasks/priority.md`, a
53
53
  - Re-resolve every Plan pointer after anything archives a plan
54
54
  - Read the file back after writing it, since the row that lands is the row a worker acts on
55
55
 
56
- A Plan pointer goes stale from a branch this board never sees. `docs-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.
56
+ 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.
@@ -45,5 +45,5 @@ A resume is a read, and a session that treats it as a cleanup pass offers to arc
45
45
  - 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.
46
46
  - The sections a role adds over the core handoff, which belong to that role's own surface
47
47
  - Archiving a shipped task out of the folder: `task-board`
48
- - Archiving a plan and marking an outcome, which `docs-fold` does when the work ships
48
+ - Archiving a plan and marking an outcome, which `context-fold` does when the work ships
49
49
  - Implementing the item it recommends, which is the next request rather than part of this one
@@ -47,21 +47,17 @@ Try each source in order. Stop at the first match.
47
47
  4b. **Session context.** When on `main` or `master` with no matching plan, read the current conversation to infer a kebab slug from the topic being discussed. Propose it: `Infer: <slug>. Confirm or rename?` Do not enter the worktree until the user confirms or provides a corrected name.
48
48
  5. **Ask.** None of the above applies. Ask the user for a name. Do not invent one.
49
49
 
50
- Tier 0 sits ahead of the inference because every tier below it answers from state the caller cannot set, and a caller that already knows the name has no way to say so. That gap is what a dispatched worker meets. It starts on `main`, so tier 1 cannot match, and a board carrying more than one plan puts tier 2 out of reach too, which lands the run on tier 3 and its instruction to ask somebody who is not there. A prompt naming the branch does not reach any of them, since no tier reads the prompt.
50
+ Tier 0 sits ahead of the inference because every tier below it answers from state the caller cannot set. A dispatched worker starts on `main` beside several plans, so without it the run lands on tier 3 and asks somebody who is not there.
51
51
 
52
52
  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.
53
53
 
54
54
  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.
55
55
 
56
- The verb is the reading rather than this body, because a type read off a plan's `## Summary` and `**Files to touch:**` lines is a judgment, and it has disagreed with itself in production. One dispatch checked `fix/path-form-hook` and the worker took `feat/path-form-hook`, both sides reading the same plan and grading it differently. The verb answers `feat` for every plan, so two sides calling it cannot part.
57
-
58
- The caller's type still wins over the verb's, because tier 0 is the one source that knows something no file states. The ordinary caller is `auto-ship` Step 0, which ran the verb itself and is handing over the answer it got, so nothing is overridden in that case either.
56
+ 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
57
 
60
58
  Branch on the record rather than on the exit code, which a shell function wrapping `canon` can flatten to zero. Take `feat` and say the verb did not answer where it refuses, where the record carries no `type` key, or where the installed binary carries no `plan-branch` subcommand.
61
59
 
62
- A wrong type is cheap because the branch type is cosmetic rather than because anything corrects it. `git-stage` reads a commit's type off the staged diff and `git-pr` reads a title off the diff too, so the semantics a release reads never pass through the branch name at all. Nothing downstream is wrong when a `feat/` sits over a fix, and a person scanning a worktree listing loses a signal.
63
-
64
- `git-branch` does not correct it, which three surfaces used to say it did. Its second guard reads `If branch name already follows conventions, stop`, and `${CLAUDE_SKILL_DIR}/../../standards/branch.md` makes the type vocabulary an axis without making the choice within that vocabulary one, so `feat/` over a fix conforms and the guard fires ahead of the Analysis line that would have re-derived the type.
60
+ A wrong type is cosmetic, since `git-stage` and `git-pr` read their types off the diff rather than the branch name. Nothing corrects it later either: `git-branch` stops on any name that already conforms, and `feat/` over a fix conforms.
65
61
 
66
62
  Then test both names the entry is about to claim. Neither read needs a worktree, and a stop after Step 4 leaves one built with the session sitting inside it, so both belong here rather than beside the rename:
67
63
 
@@ -74,7 +70,7 @@ The two tests catch different collisions. The branch test misses the one `${CLAU
74
70
 
75
71
  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.
76
72
 
77
- It reads both ref spaces rather than the local head alone, and it reads them the way `checkClaim` does, so a name this skill clears and a branch a dispatcher cleared are one answer. `git show-ref --verify` is what that replaces. It sees no remote-tracking ref, so a branch pushed from elsewhere passed the test and collided at the first push, and its exit code cannot separate an absent ref from a tree it could not read, which reports a failed read as a free name.
73
+ It reads both ref spaces rather than the local head alone, the way `checkClaim` does, so a name this skill clears and a branch a dispatcher cleared are one answer, and a branch pushed from elsewhere is caught before the first push rather than at it.
78
74
 
79
75
  ## Step 3: preview
80
76
 
@@ -153,8 +149,6 @@ Then report the port this worktree derives, on a second line:
153
149
 
154
150
  Branch on the exit rather than on the output, since the helper prints nothing to stdout when it refuses and reading that as a number reports an offset of zero, which is the main checkout's.
155
151
 
156
- The helper refuses a folder left behind after its worktree was removed, which Step 4 cannot land on, since it registers whatever it creates. The branch is here so a refusal is never read back as an offset of zero, which is the main checkout's port and the collision the helper exists to prevent.
157
-
158
152
  The offset is what `role-orchestrator` sends a reader here to read rather than assign, and what an operator overrides through `WORKTREE_PORT_OFFSET` when two worktrees derive the same value. Deriving it correctly and printing it nowhere leaves both instructions naming a number no surface emits.
159
153
 
160
154
  Do not invoke `ExitWorktree` from this skill. Exit is the user's call.
@@ -42,6 +42,6 @@ Placing a row without checking for another writer collides the same way. Two ses
42
42
 
43
43
  ## Out of scope
44
44
 
45
- - Editing the contents of a task that already exists, which `docs-fold` owns along with marking outcomes and sweeping plans
45
+ - Editing the contents of a task that already exists, which `context-fold` owns along with marking outcomes and sweeping plans
46
46
  - Deciding what the task should argue. This owns the file's existence and its shape, not its content.
47
47
  - Relocating a plan, which one skill owns so two do not relocate it differently
@@ -1,18 +1,18 @@
1
1
  ---
2
2
  name: task-board
3
- description: Creates a task file in `.canon/tasks/` with the filename, phase label, and frontmatter the standard requires, and archives a shipped one out of the folder. Use when asked to "add a task", "create a task", "queue this", "put this on the board", "archive that task", or "close out a shipped task". Do NOT use to mark an outcome `[x]`. That is `docs-fold`.
3
+ description: Creates a task file in `.canon/tasks/` with the filename, phase label, and frontmatter the standard requires, and archives a shipped one out of the folder. Use when asked to "add a task", "create a task", "queue this", "put this on the board", "archive that task", or "close out a shipped task". Do NOT use to mark an outcome `[x]`. That is `context-fold`.
4
4
  ---
5
5
 
6
6
  # Task board
7
7
 
8
- Owns the two operations that bring a task file into existence and take it out of the folder. `docs-fold` edits the contents of a task that already exists, marking outcomes `[x]`. Do not mark outcomes here, and do not move a plan by hand: the archive carries it.
8
+ Owns the two operations that bring a task file into existence and take it out of the folder. `context-fold` edits the contents of a task that already exists, marking outcomes `[x]`. Do not mark outcomes here, and do not move a plan by hand: the archive carries it.
9
9
 
10
10
  Read `${CLAUDE_SKILL_DIR}/../../standards/tasks.md` before writing any file. It holds the filename convention, the frontmatter contract, and the file format. Do not work them from memory.
11
11
 
12
12
  ## Guards
13
13
 
14
14
  - Resolve the board at the main worktree root, not `pwd`. Run `git worktree list --porcelain | grep -m 1 '^worktree ' | cut -d' ' -f2-`, falling back to `pwd` outside a git repo. Every read and write below resolves against that root. The board is gitignored scratch shared across worktrees, so a linked worktree writing to its own `pwd` creates a second board nothing else reads.
15
- - A new task file is a main-root write, so it goes out as a heredoc. Archiving already runs through `canon tasks archive`, which resolves the root in-process. Marking an outcome shipped is `docs-fold` and runs through `canon tasks outcome`. Resolve that root and route the write the way `session-worktree` states.
15
+ - A new task file is a main-root write, so it goes out as a heredoc. Archiving already runs through `canon tasks archive`, which resolves the root in-process. Marking an outcome shipped is `context-fold` and runs through `canon tasks outcome`. Resolve that root and route the write the way `session-worktree` states.
16
16
  - If `.canon/tasks/` does not exist at that root, stop: `❌ No .canon/tasks/ board. Run canon claude init to set it up.`
17
17
  - Route on the request rather than on a flag. Creating names work that does not exist yet, archiving names a task file already shipped, and declining names one decided against. If the request fits none of the three, stop: `❌ Ambiguous. Say whether to create a task, archive one, or decline one.`
18
18
  - Never hand-edit `.canon/tasks/index.md`. A hook regenerates it from sibling frontmatter after a write. Do not run the regen command directly, except after a shell write from a linked worktree: the hook matches `Write|Edit|MultiEdit` and nothing fires on `Bash`, so that one case regenerates explicitly with `canon indexes regen --no-stage --root <main-root> <main-root>/.canon/tasks/index.md`.
@@ -84,85 +84,11 @@ Say the origins were read even when nothing comes back, which is the ordinary re
84
84
 
85
85
  ## Archive
86
86
 
87
- The `post-merge` git hook archives the task a merge closed, so a request arriving here is usually one the hook could not resolve on its own. Run the steps below against whatever the hook left in place.
88
-
89
- Do not move the file, edit `priority.md`, or regenerate the index by hand. `canon tasks archive` owns all three as one unit and the hook calls the same command, so a hand-rolled move here drifts from the unattended path.
90
-
91
- ### Step 1: confirm the work reached main
92
-
93
- `docs-fold` marks outcomes on the branch as step 1 of the ship chain, so an all-`[x]` task routinely describes a pull request that is still open. The command gates on the outcomes and cannot tell those two apart, which is what puts this check here:
94
-
95
- ```bash
96
- git fetch origin main --quiet && git log origin/main --oneline -20
97
- ```
98
-
99
- Match the shipped outcomes against that log, widening to `gh pr list --state merged --limit 20` when a remote is configured and the log does not settle it. When the work is not on `main`, name the task and stop: `❌ Work not on main. Archiving now loses the task if the pull request is abandoned.`
100
-
101
- The board is gitignored, so an archived task has no history behind it and nothing restores one archived early. Skip this check when the task carries a `Pull request:` line and the last number it lists is merged, since the number already proves what the log is being read for.
102
-
103
- ### Step 2: run the archive
104
-
105
- Pass the task's filename stem, or the pull request number when the request names one:
106
-
107
- ```bash
108
- canon tasks archive <stem> --json
109
- ```
110
-
111
- The command refuses rather than reports, and the refusal reaches this skill through the record rather than through the exit. Branch on `ok`, then on `reason`. An operator's shell profile may wrap `canon` in a function that runs the binary and then a second command and takes the second status, which masks every non-zero exit rather than only an absent verb. The binary exits 1 for an unknown subcommand and 1 for an ordinary refusal alike, so the record is the only signal that survives the wrapper.
112
-
113
- On success the record carries `from`, `to`, `priorityRowRemoved`, and `indexRegenerated`, which is what moved, what row it cleared, and whether the index changed. It also carries `plan` when the task was the last live citation of a live plan, holding the `from` and `to` of the plan moved alongside it. A `plan` of `null` means the task cited no live plan, or that a sibling still holds it.
114
-
115
- ### Step 3: route on a refusal
116
-
117
- Each reason has one resolution and none of them is to archive around it:
118
-
119
- - `open-outcomes`: the named outcomes are unmarked or genuinely open. Run `docs-fold` when the work shipped and nothing marked it. Leave the task on the board when the outcome is real. When the work is being abandoned, cut it by striking the body, `- ~~<outcome>~~ <why>`, whatever the checkbox holds, so the board records what was dropped rather than meeting this refusal a second time.
120
- - `ambiguous`: two tasks name one pull request, which is the misfile `${CLAUDE_SKILL_DIR}/../../standards/tasks.md` rules out. Resolve the citation by hand, since no sweep repairs it.
121
- - `earlier-slice`: the number is listed on the task but is not the last, so a later slice is still to merge. Leave the task on the board. Its last slice's merge archives it.
122
- - `no-match`: the stem or number names nothing on the board. Check the name against the listed stems.
123
- - `bad-input`: the command line was wrong rather than the board. Read the message, fix the arguments, and run it again. Nothing on the board needs repair, which is what separates this from the two above.
124
-
125
- Do not move a plan by hand from this skill. The command carries the plan with the task when no other live task cites it, and retargets the archived task's `Plan:` line at the new path. A second mover drifts into relocating the same file differently.
126
-
127
- Leave `TASK-ARCHIVE.md` alone when it is present in the archive folder. It records the single-file era in the shape that era used, and splitting it would fabricate per-task files nobody wrote.
128
-
129
- ### Step 4: clear prose naming the task
130
-
131
- The command drops the task's row from `.canon/tasks/priority.md` and leaves prose alone. Remove any sentence that still names the archived task or counts the rows that changed, since a stale count reads as board state.
87
+ Read `${CLAUDE_SKILL_DIR}/references/archive.md` when the request names a shipped task to archive. It carries the check that the work reached `main`, the `canon tasks archive` call, the route for each refusal, and the prose to clear afterwards. Never move the file, edit `priority.md`, or regenerate the index by hand, since the command owns all three.
132
88
 
133
89
  ## Decline
134
90
 
135
- A task decided against carries no `post-merge` hook of its own, so every decline request arrives here directly rather than through work the hook already did.
136
-
137
- Do not move the file, edit `priority.md` or `backlog.md`, or regenerate the index by hand. `canon tasks decline` owns all three as one unit.
138
-
139
- ### Step 1: gather the reason
140
-
141
- Ask for the reason when the request does not carry one, and stop rather than guessing: `❌ No reason. Say why the task is being declined.` The command takes it as `--reason <text>` and refuses without it, so gathering it here saves a round trip through that refusal.
142
-
143
- ### Step 2: run the decline
144
-
145
- Pass the task's filename stem:
146
-
147
- ```bash
148
- canon tasks decline <stem> --reason "<text>" [--by <name>] --json
149
- ```
150
-
151
- The command refuses rather than reports, and the refusal reaches this skill through the record rather than through the exit, the same wrapper hazard `canon tasks archive` carries. Branch on `ok`, then on `reason`.
152
-
153
- On success the record carries `from`, `to`, `priorityRowRemoved`, `backlogRowRemoved`, and `indexRegenerated`, where `backlogRowRemoved` is decline's own field since a task can be declined straight off `backlog.md` and archive never checks that file. It also carries `plan` when the task was the last live citation of a live plan, holding the `from` and `to` of the plan moved alongside it, the same shape `canon tasks archive` uses for its own `plan` field.
154
-
155
- ### Step 3: route on a refusal
156
-
157
- - `no-match`: the stem does not name exactly one task. Either none matches, or exactly one starts with it and the full name is needed. Check the name against the listed stems.
158
- - `ambiguous`: the stem is a prefix more than one task starts with, unlike archive's own `ambiguous`, which fires on a shared pull request. Decline takes no pull-request selector, so this is the only route to it. Pass the full stem.
159
- - `bad-input`: the command line was wrong rather than the board. Read the message, fix the arguments, and run it again. Nothing on the board needs repair, which is what separates this from the two above.
160
-
161
- Do not move a plan by hand from this skill. The command carries the plan with the task when no other live task cites it, and retargets the declined task's `Plan:` line at the new path. A second mover drifts into relocating the same file differently.
162
-
163
- ### Step 4: clear prose naming the task
164
-
165
- The command drops the task's row from `.canon/tasks/priority.md` or `.canon/tasks/backlog.md` and leaves prose alone. Remove any sentence that still names the declined task or counts the rows that changed, since a stale count reads as board state.
91
+ Read `${CLAUDE_SKILL_DIR}/references/decline.md` when the request names a task decided against. It carries gathering the reason, the `canon tasks decline` call, the route for each refusal, and the prose to clear afterwards. Never move the file, edit `priority.md` or `backlog.md`, or regenerate the index by hand, since the command owns all three.
166
92
 
167
93
  ## Output
168
94
 
@@ -198,4 +124,4 @@ Archive, reporting the paths the command returned:
198
124
  <ordering and index disposition in one line>
199
125
  ```
200
126
 
201
- A refusal reports the reason and the resolution Step 3 routes it to, on one line each.
127
+ A refusal reports the reason and the resolution the mode's reference routes it to under its Step 3, on one line each.
@@ -0,0 +1,54 @@
1
+ ---
2
+ title: Archive a shipped task
3
+ description: How task-board confirms a task's work reached main, runs canon tasks archive, routes each refusal, and clears prose naming the archived task
4
+ ---
5
+
6
+ # Archive a shipped task
7
+
8
+ The Archive mode of `task-board`. The session reads this file when the request names a task file already shipped.
9
+
10
+ The `post-merge` git hook archives the task a merge closed, so a request arriving here is usually one the hook could not resolve on its own. Run the steps below against whatever the hook left in place.
11
+
12
+ Do not move the file, edit `priority.md`, or regenerate the index by hand. `canon tasks archive` owns all three as one unit and the hook calls the same command, so a hand-rolled move here drifts from the unattended path.
13
+
14
+ ## Step 1: confirm the work reached main
15
+
16
+ `context-fold` marks outcomes on the branch as step 1 of the ship chain, so an all-`[x]` task routinely describes a pull request that is still open. The command gates on the outcomes and cannot tell those two apart, which is what puts this check here:
17
+
18
+ ```bash
19
+ git fetch origin main --quiet && git log origin/main --oneline -20
20
+ ```
21
+
22
+ Match the shipped outcomes against that log, widening to `gh pr list --state merged --limit 20` when a remote is configured and the log does not settle it. When the work is not on `main`, name the task and stop: `❌ Work not on main. Archiving now loses the task if the pull request is abandoned.`
23
+
24
+ The board is gitignored, so an archived task has no history behind it and nothing restores one archived early. Skip this check when the task carries a `Pull request:` line and the last number it lists is merged, since the number already proves what the log is being read for.
25
+
26
+ ## Step 2: run the archive
27
+
28
+ Pass the task's filename stem, or the pull request number when the request names one:
29
+
30
+ ```bash
31
+ canon tasks archive <stem> --json
32
+ ```
33
+
34
+ The command refuses rather than reports, and the refusal reaches this skill through the record rather than through the exit. Branch on `ok`, then on `reason`. An operator's shell profile may wrap `canon` in a function that runs the binary and then a second command and takes the second status, which masks every non-zero exit rather than only an absent verb. The binary exits 1 for an unknown subcommand and 1 for an ordinary refusal alike, so the record is the only signal that survives the wrapper.
35
+
36
+ On success the record carries `from`, `to`, `priorityRowRemoved`, and `indexRegenerated`, which is what moved, what row it cleared, and whether the index changed. It also carries `plan` when the task was the last live citation of a live plan, holding the `from` and `to` of the plan moved alongside it. A `plan` of `null` means the task cited no live plan, or that a sibling still holds it.
37
+
38
+ ## Step 3: route on a refusal
39
+
40
+ Each reason has one resolution and none of them is to archive around it:
41
+
42
+ - `open-outcomes`: the named outcomes are unmarked or genuinely open. Run `context-fold` when the work shipped and nothing marked it. Leave the task on the board when the outcome is real. When the work is being abandoned, cut it by striking the body, `- ~~<outcome>~~ <why>`, whatever the checkbox holds, so the board records what was dropped rather than meeting this refusal a second time.
43
+ - `ambiguous`: two tasks name one pull request, which is the misfile `${CLAUDE_SKILL_DIR}/../../standards/tasks.md` rules out. Resolve the citation by hand, since no sweep repairs it.
44
+ - `earlier-slice`: the number is listed on the task but is not the last, so a later slice is still to merge. Leave the task on the board. Its last slice's merge archives it.
45
+ - `no-match`: the stem or number names nothing on the board. Check the name against the listed stems.
46
+ - `bad-input`: the command line was wrong rather than the board. Read the message, fix the arguments, and run it again. Nothing on the board needs repair, which is what separates this from the two above.
47
+
48
+ Do not move a plan by hand from this skill. The command carries the plan with the task when no other live task cites it, and retargets the archived task's `Plan:` line at the new path. A second mover drifts into relocating the same file differently.
49
+
50
+ Leave `TASK-ARCHIVE.md` alone when it is present in the archive folder. It records the single-file era in the shape that era used, and splitting it would fabricate per-task files nobody wrote.
51
+
52
+ ## Step 4: clear prose naming the task
53
+
54
+ The command drops the task's row from `.canon/tasks/priority.md` and leaves prose alone. Remove any sentence that still names the archived task or counts the rows that changed, since a stale count reads as board state.