@erclx/canon 5.41.0 → 5.42.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 (154) hide show
  1. package/claude/.claude-plugin/plugin.json +1 -1
  2. package/claude/skills/api-design/references/adopted.md +34 -14
  3. package/claude/skills/auto-ship/REQUIREMENT.md +1 -0
  4. package/claude/skills/auto-ship/SKILL.md +22 -2
  5. package/claude/skills/auto-ship/references/draft-mark.md +32 -6
  6. package/claude/skills/auto-ship/references/failure-recovery.md +15 -13
  7. package/claude/skills/auto-ship/references/tier-failures.md +31 -10
  8. package/claude/skills/auto-ship/references/ui-checklist.md +9 -4
  9. package/claude/skills/auto-ship/references/worktree-name.md +9 -3
  10. package/claude/skills/build-in-slices/references/adopted.md +35 -21
  11. package/claude/skills/canvas-board/references/canvas.md +17 -6
  12. package/claude/skills/canvas-board/references/design.md +26 -7
  13. package/claude/skills/code-craft/references/adopted.md +58 -20
  14. package/claude/skills/codebase-layout/references/adopted.md +49 -16
  15. package/claude/skills/codebase-layout/references/frontend.md +11 -4
  16. package/claude/skills/codebase-layout/references/tests.md +4 -2
  17. package/claude/skills/context-fold/references/classify.md +10 -15
  18. package/claude/skills/context-fold/references/completion-report.md +11 -9
  19. package/claude/skills/context-fold/references/context-refresh.md +26 -9
  20. package/claude/skills/context-fold/references/unusable-baseline.md +5 -3
  21. package/claude/skills/create-rule/REQUIREMENT.md +5 -0
  22. package/claude/skills/create-rule/SKILL.md +9 -1
  23. package/claude/skills/create-rule/references/checklist.md +26 -0
  24. package/claude/skills/create-rule/references/rule.md +98 -20
  25. package/claude/skills/create-skill/SKILL.md +1 -0
  26. package/claude/skills/create-skill/references/skill-disclosure.md +10 -2
  27. package/claude/skills/create-skill/references/skill-frontmatter.md +43 -0
  28. package/claude/skills/create-skill/references/skill-paths.md +7 -4
  29. package/claude/skills/create-skill/references/skill-practice.md +6 -3
  30. package/claude/skills/create-skill/references/skill-requirement.md +4 -2
  31. package/claude/skills/create-skill/references/skill.md +67 -44
  32. package/claude/skills/deploy-app/references/vercel.md +2 -1
  33. package/claude/skills/deprecation-migration/references/adopted.md +44 -25
  34. package/claude/skills/design-taste/references/adopted.md +9 -1
  35. package/claude/skills/design-taste/references/craft.md +3 -1
  36. package/claude/skills/design-taste/references/kinds.md +8 -7
  37. package/claude/skills/design-taste/references/preflight.md +12 -0
  38. package/claude/skills/design-taste/references/systems.md +7 -6
  39. package/claude/skills/design-taste/references/tells.md +24 -25
  40. package/claude/skills/design-taste/references/vocabulary.md +7 -5
  41. package/claude/skills/document-health/references/axes.md +54 -30
  42. package/claude/skills/draft-and-pick/references/live-arms.md +2 -2
  43. package/claude/skills/draft-doc/references/context.md +4 -3
  44. package/claude/skills/draft-doc/references/docs.md +6 -3
  45. package/claude/skills/draft-doc/references/readme/agent-facing.md +6 -0
  46. package/claude/skills/draft-doc/references/readme/application.md +8 -2
  47. package/claude/skills/draft-doc/references/readme/cli.md +5 -1
  48. package/claude/skills/draft-doc/references/readme/library.md +4 -0
  49. package/claude/skills/draft-doc/references/readme/plugin.md +9 -1
  50. package/claude/skills/draft-doc/references/readme.md +30 -13
  51. package/claude/skills/draft-doc/references/requirements.md +17 -4
  52. package/claude/skills/draft-doc/references/wiki-kind.md +20 -10
  53. package/claude/skills/draft-figure/references/architecture-set.md +7 -3
  54. package/claude/skills/draft-figure/references/figures.md +8 -6
  55. package/claude/skills/draft-figure/references/hand-drawn.md +3 -1
  56. package/claude/skills/draft-figure/references/mermaid-path.md +19 -9
  57. package/claude/skills/draft-figure/references/mermaid.md +10 -5
  58. package/claude/skills/draft-ready/references/ready.md +22 -15
  59. package/claude/skills/git-branch/references/branch.md +11 -1
  60. package/claude/skills/git-branch/references/slug.md +17 -5
  61. package/claude/skills/git-commit/references/commit.md +8 -0
  62. package/claude/skills/git-commit/references/versioning.md +23 -17
  63. package/claude/skills/git-followup/REQUIREMENT.md +1 -1
  64. package/claude/skills/git-followup/SKILL.md +5 -6
  65. package/claude/skills/git-issue/references/issue.md +29 -16
  66. package/claude/skills/git-pr/REQUIREMENT.md +1 -5
  67. package/claude/skills/git-pr/SKILL.md +11 -22
  68. package/claude/skills/git-pr/references/final-command.md +21 -8
  69. package/claude/skills/git-pr/references/labels.md +45 -28
  70. package/claude/skills/git-pr/references/pr.md +28 -9
  71. package/claude/skills/git-pr/references/publish.md +42 -28
  72. package/claude/skills/git-pr/references/task-number.md +20 -8
  73. package/claude/skills/git-ship/SKILL.md +1 -1
  74. package/claude/skills/plan-feature/references/plan-lifecycle.md +10 -3
  75. package/claude/skills/plan-feature/references/plan.md +57 -20
  76. package/claude/skills/plan-groundwork/references/groundwork-spikes.md +4 -1
  77. package/claude/skills/plan-groundwork/references/groundwork.md +14 -16
  78. package/claude/skills/plan-intake/references/intake.md +29 -24
  79. package/claude/skills/pr-evidence/REQUIREMENT.md +40 -0
  80. package/claude/skills/pr-evidence/SKILL.md +53 -0
  81. package/claude/skills/pr-evidence/references/evidence.md +150 -0
  82. package/claude/skills/review-address/references/post-review-findings.md +10 -3
  83. package/claude/skills/review-address/references/rebase-conflicts.md +15 -7
  84. package/claude/skills/review-address/references/rest-reads.md +3 -1
  85. package/claude/skills/review-craft/references/adopted.md +35 -18
  86. package/claude/skills/review-craft/references/security.md +42 -7
  87. package/claude/skills/review-craft/references/ui.md +23 -8
  88. package/claude/skills/review-pr/SKILL.md +6 -6
  89. package/claude/skills/review-pr/references/body-variants.md +29 -9
  90. package/claude/skills/review-pr/references/close-out.md +20 -5
  91. package/claude/skills/review-pr/references/key-changes.md +27 -3
  92. package/claude/skills/review-pr/references/post.md +83 -31
  93. package/claude/skills/review-pr/references/scope.md +54 -19
  94. package/claude/skills/review-ui/references/close-out.md +7 -5
  95. package/claude/skills/review-ui/references/driving.md +24 -4
  96. package/claude/skills/review-ui/references/post.md +43 -15
  97. package/claude/skills/role-orchestrator/references/orchestrator-cloud-launch.md +67 -17
  98. package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +80 -40
  99. package/claude/skills/role-orchestrator/references/orchestrator-handback.md +52 -15
  100. package/claude/skills/role-orchestrator/references/orchestrator-handoff.md +48 -26
  101. package/claude/skills/role-orchestrator/references/orchestrator-inbound.md +12 -13
  102. package/claude/skills/role-orchestrator/references/orchestrator-launch.md +72 -36
  103. package/claude/skills/role-orchestrator/references/orchestrator-output.md +12 -4
  104. package/claude/skills/role-orchestrator/references/orchestrator-parked.md +64 -24
  105. package/claude/skills/role-orchestrator/references/orchestrator-poll.md +80 -26
  106. package/claude/skills/role-orchestrator/references/orchestrator-refill.md +41 -18
  107. package/claude/skills/role-orchestrator/references/orchestrator-resume.md +19 -7
  108. package/claude/skills/role-orchestrator/references/orchestrator-review-dispatch.md +22 -12
  109. package/claude/skills/role-orchestrator/references/orchestrator-reviewer-launch.md +15 -6
  110. package/claude/skills/role-orchestrator/references/orchestrator-sweep.md +25 -7
  111. package/claude/skills/role-orchestrator/references/orchestrator-watch.md +34 -8
  112. package/claude/skills/role-orchestrator/scripts/poll.ts +16 -24
  113. package/claude/skills/role-worker/REQUIREMENT.md +1 -0
  114. package/claude/skills/role-worker/SKILL.md +8 -0
  115. package/claude/skills/search-craft/references/adopted.md +18 -6
  116. package/claude/skills/session-map/references/session.md +26 -7
  117. package/claude/skills/session-worktree/references/main-root-writes.md +25 -8
  118. package/claude/skills/systematic-debugging/references/adopted.md +30 -16
  119. package/claude/skills/target-check/references/domains.md +39 -11
  120. package/claude/skills/target-setup/references/detect.md +80 -65
  121. package/claude/skills/target-setup/references/indexes.md +8 -6
  122. package/claude/skills/task-board/references/board.md +86 -30
  123. package/claude/skills/task-board/references/decline.md +29 -13
  124. package/claude/skills/task-board/references/tasks-decline.md +12 -5
  125. package/claude/skills/task-board/references/tasks.md +65 -33
  126. package/claude/skills/task-complete/references/archive.md +41 -17
  127. package/claude/skills/task-complete/references/receipt-sweep.md +23 -9
  128. package/claude/skills/task-complete/references/unusable-baseline.md +10 -3
  129. package/claude/skills/teach-workspace/references/glossary.md +6 -2
  130. package/claude/skills/teach-workspace/references/lesson-build.md +44 -16
  131. package/claude/skills/teach-workspace/references/lesson-craft.md +12 -7
  132. package/claude/skills/teach-workspace/references/pedagogy.md +6 -3
  133. package/claude/skills/teach-workspace/references/promotion-fold.md +17 -11
  134. package/claude/skills/teach-workspace/references/promotion.md +31 -8
  135. package/claude/skills/teach-workspace/references/revisit.md +8 -2
  136. package/claude/skills/teach-workspace/references/teach.md +17 -9
  137. package/claude/skills/test-craft/references/adopted.md +48 -14
  138. package/claude/skills/test-craft/references/component.md +7 -4
  139. package/claude/skills/test-craft/references/e2e.md +25 -7
  140. package/claude/skills/test-craft/references/unit.md +3 -1
  141. package/claude/skills/test-first/references/adopted.md +12 -4
  142. package/claude/skills/ui-checklist/REQUIREMENT.md +1 -1
  143. package/claude/skills/ui-checklist/SKILL.md +1 -1
  144. package/claude/skills/video-craft/references/adopted.md +62 -18
  145. package/claude/skills/write-human/references/adopted.md +21 -8
  146. package/docs/workflow/parallel-features.md +1 -1
  147. package/docs/workflow/skill-map.md +1 -0
  148. package/package.json +1 -1
  149. package/src/claude/cases/workflow.ts +5 -0
  150. package/src/commands/pr.ts +142 -28
  151. package/src/markdown/scope.ts +144 -0
  152. package/src/pr/lift.ts +6 -3
  153. package/src/pr/review-state.ts +182 -0
  154. package/claude/skills/git-pr/references/evidence.md +0 -124
@@ -5,9 +5,7 @@ description: The catalog reads, evidence list, argument resolution, gap handling
5
5
 
6
6
  # Detect and resolve
7
7
 
8
- What the `install` and `gov` phases both do before they write anything. Stated
9
- once here rather than twice in the body, since the two phases differ in what
10
- they install rather than in how they read the project.
8
+ What the `install` and `gov` phases both do before they write anything. Stated once here rather than twice in the body, since the two phases differ in what they install rather than in how they read the project.
11
9
 
12
10
  ## Contents
13
11
 
@@ -19,25 +17,20 @@ they install rather than in how they read the project.
19
17
 
20
18
  ## Read the catalogs
21
19
 
22
- Run in parallel. Never hardcode stack, rule, or standards names. The
23
- catalog is the source of truth.
20
+ Run in parallel. Never hardcode stack, rule, or standards names. The catalog is the source of truth.
24
21
 
25
- Run from the target project's current directory. Do not cd into the toolkit
26
- source tree. The `canon` CLI is global.
22
+ Run from the target project's current directory. Do not cd into the toolkit source tree. The `canon` CLI is global.
27
23
 
28
24
  ```bash
29
25
  canon gov list --json 2>/dev/null
30
26
  canon tooling list --json 2>/dev/null
31
27
  ```
32
28
 
33
- The `gov` phase needs only the first. Run both anyway on a bare invocation,
34
- since the chain reaches the tooling resolution a moment later.
29
+ The `gov` phase needs only the first. Run both anyway on a bare invocation, since the chain reaches the tooling resolution a moment later.
35
30
 
36
31
  ## Detect
37
32
 
38
- A monorepo keeps its languages in subfolders, so read the markers from every
39
- folder to depth two rather than from the root alone. Collect the language roots
40
- first:
33
+ A monorepo keeps its languages in subfolders, so read the markers from every folder to depth two rather than from the root alone. Collect the language roots first:
41
34
 
42
35
  ```bash
43
36
  git ls-files --cached --others --exclude-standard \
@@ -45,25 +38,21 @@ git ls-files --cached --others --exclude-standard \
45
38
  | awk -F/ 'NF <= 3'
46
39
  ```
47
40
 
48
- Every folder holding a marker is a language root, and the repository root is
49
- one when it holds a marker itself. Going through git keeps ignored trees such as
50
- `node_modules/`, `vendor/`, and `.venv/` off the list, since each carries
51
- markers of its own. Outside a git repository, fall back to
52
- `find . -maxdepth 3 \( -path '*/.*' -o -name node_modules -o -name vendor \) -prune -o -type f -print`
53
- filtered to the same five names.
41
+ Every folder holding a marker is a language root, the repository root included when it holds one itself. Going through git keeps ignored trees such as `node_modules/`, `vendor/`, and `.venv/` off the list, since each carries markers of its own.
54
42
 
55
- Depth two reaches a service folder at depth one and a workspace package under
56
- `packages/<name>/` at depth two. Deeper, the walk starts finding fixtures and
57
- examples as false roots.
43
+ - Outside a git repository, fall back to `find . -maxdepth 3 \( -path '*/.*' -o -name node_modules -o -name vendor \) -prune -o -type f -print` filtered to the same five names
44
+ - Depth two reaches a service folder at depth one and a workspace package under `packages/<name>/`. Deeper, the walk finds fixtures and examples as false roots.
58
45
 
59
- Then read these per language root in parallel, skipping any that do not exist:
46
+ ### Per root
47
+
48
+ Read these per language root in parallel, skipping any that do not exist:
60
49
 
61
50
  - `package.json`: `dependencies` and `devDependencies`
62
51
  - The root's own configs: `astro.config.*`, `next.config.*`, `vite.config.*`, `tailwind.config.*`, `tsconfig.json`, `pyproject.toml`, `go.mod`, `composer.json`, `Cargo.toml`
63
52
 
64
- A non-JavaScript marker outranks a `package.json` in the same folder. A Go or
65
- Composer service often carries a `package.json` only to host scripts, so that
66
- folder is a Go or PHP root rather than a JavaScript one.
53
+ A non-JavaScript marker outranks a `package.json` in the same folder. A Go or Composer service often carries a `package.json` only to host scripts, so that folder is a Go or PHP root.
54
+
55
+ ### Once, at the root
67
56
 
68
57
  Read these once, from the repository root:
69
58
 
@@ -72,39 +61,56 @@ Read these once, from the repository root:
72
61
 
73
62
  ## Resolve arguments
74
63
 
75
- Governance installs once, at the repository root, and a rule's `paths:` globs
76
- already reach every subfolder. Tooling installs per folder. So resolve one
77
- governance stack for the whole repository and one tooling stack per language
78
- root.
64
+ Governance installs once, at the repository root, and a rule's `paths:` globs already reach every subfolder. Tooling installs per folder, so resolve one governance stack for the whole repository and one tooling stack per language root.
65
+
66
+ ### Governance stack
67
+
68
+ Match the repository root's detected language against stack names in the catalog. Governance stacks are per language, so a framework never names one, and its rules arrive as extras.
69
+
70
+ - If the root matched nothing, `base` is the stack, even when subfolders matched. No subfolder owns the repository, and picking one by order states a preference nobody gave.
71
+ - Mark it `fallback` in the preview only when no root matched anywhere
72
+
73
+ ### Tooling stack
74
+
75
+ For each language root, pick the closest tooling stack from `canon tooling list --json`, such as `vite-react`, `astro`, or `nextjs`. It is distinct from the governance stack.
76
+
77
+ - Fall back to `base` for a root with no framework or language match, and carry that fallback into its preview row
78
+ - Map `next` in a root's dependencies, or a `next.config.ts`, `.js`, or `.mjs` there, to the `node` governance stack and the `nextjs` tooling stack
79
+ - The `next` dependency name alone matches no stack, and the Next.js rule arrives as an extra
80
+
81
+ ### Extras
82
+
83
+ Run `canon gov detect <target> --stack <stack> --json` from the target and take its `proposals` array as the candidate extras. Each proposal names a `rule` and the `evidence` that matched it across every language root to depth two.
84
+
85
+ - The verb already leaves out every rule the picked stack resolves, so do not dedupe again
86
+ - Do not match a rule's `description` or `paths` by hand
87
+ - The verb proposes no language rule, since a stack reaches each one
88
+
89
+ A language root below the repository root whose language the stack does not carry contributes its language rule by name, read from `canon gov list --json`.
90
+
91
+ ### Subfolder tooling and skips
79
92
 
80
- - **Stack:** pick the governance stack by matching the repository root's detected language against stack names in the catalog. Governance stacks are per language, so a framework never names one, and its rules arrive as extras. If the root matched nothing, `base` is the stack, including when subfolders matched, since no subfolder owns the repository and picking one by order would state a preference nobody gave. Mark it `fallback` in the preview only when no root matched anywhere.
81
- - **Tooling stack:** for each language root, pick the closest tooling stack from `canon tooling list --json` (e.g. `vite-react`, `astro`, `nextjs`). Distinct from the governance stack. Fall back to `base` for a root with no framework or language match, and carry that fallback into its preview row.
82
- - **Next.js:** map `next` in a root's `package.json` dependencies, or a `next.config.ts`/`.js`/`.mjs` file in that root, to the `node` governance stack and the `nextjs` tooling stack. The dependency name does not match the tooling stack name by itself, and the Next.js rule arrives as an extra.
83
- - **Extras:** run `canon gov detect <target> --stack <stack> --json` from the target and take its `proposals` array as the candidate extras. Each proposal names a `rule` and the `evidence` that matched it across every language root to depth two. The verb already leaves out every rule the picked stack resolves, so do not dedupe again, and do not match a rule's `description` or `paths` by hand.
84
- - **Subfolder language rules:** a language root below the repository root whose language the picked stack does not carry contributes its language rule by name, read from `canon gov list --json`. The verb proposes no language rule, since a stack reaches each one.
85
- - **Subfolder tooling:** a language root below the repository root takes its own `canon tooling sync <stack> <path> --skip base`, since `canon init` already lands `base` once at the root. Leave a root whose stack resolves to `base` out of the commands, since that sync would land nothing. A repository-root `package.json` hosting only formatters and hooks is that case, and it adds no row.
86
- - **Skip (`--skip`):** `wiki` installs by default. Add `--skip wiki` only when the user explicitly wants it left out.
93
+ A language root below the repository root takes its own `canon tooling sync <stack> <path> --skip base`, since `canon init` already lands `base` once at the root.
94
+
95
+ - Leave a root whose stack resolves to `base` out of the commands, since that sync lands nothing. A root `package.json` hosting only formatters and hooks is that case and adds no row.
96
+ - `wiki` installs by default. Add `--skip wiki` only when the user explicitly wants it left out.
87
97
 
88
98
  ## Gap handling
89
99
 
90
- If a detected technology has no matching rule or stack, do not guess. Surface
91
- the gap.
100
+ If a detected technology has no matching rule or stack, do not guess. Surface the gap.
101
+
102
+ On the full chain, either defer and author a rule in the toolkit before re-running, or proceed with the matched layer and list the gap in the final report. Rules and stacks are authored in the toolkit repository, never in the target project on the fly.
92
103
 
93
- On the full chain, either defer and author a rule in the toolkit before
94
- re-running, or proceed with the matched layer and list the gap in the final
95
- report. Rules and stacks are authored in the toolkit repository, never in the
96
- target project on the fly.
104
+ ### The gov phase
97
105
 
98
106
  On the `gov` phase, stop and present four options rather than picking:
99
107
 
100
- 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.
101
- 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.
108
+ 1. Author a rule in the toolkit at `governance/rules/<domain>/<num>-<name>.md` per `${CLAUDE_SKILL_DIR}/../create-rule/references/rule.md`, commit, and re-run install, when every project should get it.
109
+ 2. Invoke `create-rule`, which scaffolds the file into the target project at a non-colliding number. Take this when the rule is project-specific and no sync should overwrite it.
102
110
  3. Install the matching non-`<tech>` rules and skip the tech-specific layer.
103
111
  4. Abort.
104
112
 
105
- `--skip-gaps` takes option 3 ahead of the prompt, which is what keeps the phase
106
- non-interactive. This skill authors no rule itself. Option 1 writes in the
107
- toolkit repository, and option 2 hands the project-local file to `create-rule`.
113
+ `--skip-gaps` takes option 3 ahead of the prompt, which keeps the phase non-interactive. This skill authors no rule itself, since option 1 writes in the toolkit and option 2 hands the file to `create-rule`.
108
114
 
109
115
  ## Preview
110
116
 
@@ -112,28 +118,37 @@ Before executing, output:
112
118
 
113
119
  - **Detected:** each technology with its evidence file, path included, so a subfolder marker reads as one
114
120
  - **Stack:** picked governance stack and resolved rule count. Mark it `fallback` when no detected language matched a catalog name.
115
- - **Tooling stack:** one row per language root, each carrying its path, its picked tooling stack, a `fallback` mark on the same test, and its own command. On the repository root's row, name what `base` lands: configs, seeds, and gitignore entries in every case, plus the JavaScript development dependencies, scripts, and hook activation wherever a `package.json` exists to carry them. A project outside that ecosystem runs none of the second group and keeps the first. Omit these rows entirely on the `gov` phase, which syncs no tooling.
116
- - **Extras:** each proposal with the evidence the verb returned, plus each subfolder language rule, listed in full as the list the operator confirms. A second matched stack reaches the install only through this list, since `canon init --stack` takes one stack, so a shortened list reads as that stack dropped.
121
+ - **Tooling stack:** one row per language root, each with its path, picked stack, a `fallback` mark on the same test, and its own command. Omit these rows on the `gov` phase.
122
+ - **Extras:** each proposal with the evidence the verb returned, plus each subfolder language rule, listed in full as the list the operator confirms
117
123
  - **Skip:** any `--skip` entries with reason
118
124
  - **Target:** resolved target path
119
125
  - **Commands:** the full chain that will run
120
126
 
121
- A resolved name and a fallback read alike once written, so mark the fallback
122
- here rather than in the report. The preview is the last point before the first
123
- write, and the report runs after the files have landed.
127
+ ### The root tooling row
128
+
129
+ On the repository root's row, name what `base` lands. Configs, seeds, and gitignore entries land in every case.
130
+
131
+ - The JavaScript development dependencies, scripts, and hook activation land wherever a `package.json` exists to carry them
132
+ - A project outside that ecosystem runs none of that second group and keeps the first
133
+
134
+ ### Why mark it here
135
+
136
+ A resolved name and a fallback read alike once written, so mark the fallback in the preview rather than the report. The preview is the last point before the first write.
137
+
138
+ The extras list stays whole for a similar reason. `canon init --stack` takes one stack, so a second matched stack reaches the install only through this list, and a shortened list reads as that stack dropped.
124
139
 
125
140
  ### Confirm the extras
126
141
 
127
- The extras are the one part of the preview the operator confirms before the
128
- install runs, since a proposal is evidence that a project might want a rule
129
- rather than proof that it does. Put the list through the structured question
130
- surface with three options: take every proposal, which is the recommended
131
- first option, take none, or name a subset, which the operator types as a
132
- comma-separated list. Pass what they kept to `--add` and drop the flag when
133
- they kept nothing.
134
-
135
- An `--extras` argument answers ahead of time and skips the question.
136
- `--extras <a>,<b>` takes the named rules, and `--extras none` takes none. With
137
- neither and no one to answer, take every proposal and list each in the report,
138
- since a proposed rule costs one file to delete and stopping would break every
139
- headless setup.
142
+ The extras are the one part of the preview the operator confirms before the install runs, since a proposal is evidence that a project might want a rule rather than proof that it does. Put the list through the structured question surface with three options.
143
+
144
+ - Take every proposal, the recommended first option
145
+ - Take none
146
+ - Name a subset, which the operator types as a comma-separated list
147
+
148
+ Pass what they kept to `--add`, and drop the flag when they kept nothing.
149
+
150
+ ### Answering ahead
151
+
152
+ An `--extras` argument answers ahead of time and skips the question. `--extras <a>,<b>` takes the named rules, and `--extras none` takes none.
153
+
154
+ With neither and no one to answer, take every proposal and list each in the report. A proposed rule costs one file to delete, and stopping would break every headless setup.
@@ -29,7 +29,8 @@ before scanning.
29
29
 
30
30
  - Bootstrap un-indexed folders only. Skip folders that already contain an `index.md`.
31
31
  - All-or-nothing per chosen folder. Every `*.md` sibling in a chosen folder gets `title` and `description` injected, or none does. Partial migration creates folders that hard-error on regen.
32
- - This phase is where an install wanting the Claude layer without the tooling chain arrives, once `canon claude init` has seeded the docs. The work is the same either way, since the scan below prunes `.claude` and reads the project's own documentation folders whichever route reached it.
32
+ - An install wanting the Claude layer without the tooling chain arrives here once `canon claude init` has seeded the docs
33
+ - The work is the same either way, since the scan prunes `.claude` and reads the project's own documentation folders whichever route reached it
33
34
 
34
35
  ## Scan
35
36
 
@@ -75,7 +76,8 @@ candidate list and stop rather than choosing on the operator's behalf.
75
76
  For each chosen folder, read every `*.md` sibling and draft frontmatter:
76
77
 
77
78
  - `title`: derived from the first H1. If absent, derive from the filename in sentence case.
78
- - `description`: one line summarizing the file's purpose, drawn from the first paragraph after the H1. Follow `${CLAUDE_SKILL_DIR}/../markdown-craft/references/markdown.md` § Frontmatter descriptions for length and style.
79
+ - `description`: one line summarizing the file's purpose, drawn from the first paragraph after the H1
80
+ - Follow `${CLAUDE_SKILL_DIR}/../markdown-craft/references/markdown.md` § Frontmatter descriptions for the description's length and style
79
81
 
80
82
  Surface every drafted entry to the user grouped by file:
81
83
 
@@ -131,10 +133,10 @@ canon indexes regen --json
131
133
  ```
132
134
 
133
135
  Count the `written` actions in that record and report the number. Read the real
134
- run the same way the dry run is read, since the exit carries nothing reliable
135
- back to a session. An operator's shell profile may wrap `canon` in a function
136
- that runs the binary and then a second command and takes the second status, so a
137
- regen that errored on a sibling missing `title` arrives here as a clean pass.
136
+ run the way the dry run is read, since the exit carries nothing reliable back.
137
+
138
+ - An operator's shell profile may wrap `canon` in a function that takes a second command's status
139
+ - A regen that errored on a sibling missing `title` then arrives here as a clean pass
138
140
 
139
141
  ## Offer the convention seed
140
142
 
@@ -40,51 +40,104 @@ A board failing these is non-conforming even when it satisfies every shape rule
40
40
 
41
41
  `canon tasks list` reports each task's readiness from `priority.md` and `backlog.md`, so a reader never infers it from the folder.
42
42
 
43
- `backlog.md` is optional. A project small enough that every task it holds would be planned soon carries none, and the ordering rules below then describe the whole board.
43
+ | File | Rule |
44
+ | ------------- | ----------------------------------------------------------------------------------------- |
45
+ | `priority.md` | Required. Carries execution order and what each task waits on |
46
+ | `backlog.md` | Optional. A project whose every task would be planned soon carries none |
47
+ | `index.md` | Generated from sibling frontmatter by a hook passing the changed path. Never hand-edit it |
44
48
 
45
- `index.md` is generated from sibling frontmatter. The folder is gitignored, so the whole-repo index walk skips it and a hook passing the changed path regenerates it instead. Never hand-edit it.
46
-
47
- The catalog is the one reader that filters nothing, so it carries a row per sibling alongside the tasks, handoffs included. Anything reading the catalog as the backlog therefore does its own filtering, and a reader that takes every row as a task reports the handoffs as queued work.
49
+ The folder is gitignored, so the whole-repo index walk skips it. The catalog filters nothing and carries a row per sibling, handoffs included, so a reader taking every row as a task reports the handoffs as queued work.
48
50
 
49
51
  ## Ordering
50
52
 
51
- `priority.md` carries execution order and what each task is waiting on. The generated index sorts by filename and says nothing about order, so without this file board state gets reconstructed by hand every session. Why a row sits where it does inside its group is stated on the row itself, in the column that already carries what the task is waiting on, one line per row.
53
+ `priority.md` carries execution order and what each task waits on. The generated index sorts by filename and says nothing about order, so without this file board state gets rebuilt by hand every session.
54
+
55
+ ### Where the rationale lives
56
+
57
+ Why a row sits where it does is stated on the row, in the cell that already says what the task waits on, one line per row.
52
58
 
53
- That cell is the only home sequencing rationale has. Rationale spanning several rows, why one group of work runs before another, is carried by nothing and reaches a later session only through whoever remembers it. Naming the gap is deliberate: a second document holding it would be the version-sequencing surface this board replaced, and a row already states what it waits on, which is the part of the reasoning a reader acts on.
59
+ - Rationale spanning several rows has no home, and the gap is deliberate. A second document holding it would be the version-sequencing surface this board replaced.
60
+ - The row already states what it waits on, which is the part of the reasoning a reader acts on.
54
61
 
55
- Group tasks by readiness rather than by status, one row per task, under the columns each group fixes below. Keep it to links and blockers: tables, plus at most one sentence per section. A paragraph in `priority.md` is a defect whatever it says. Stating the shape this way is what lets a single diff fail, since a size cap only trips after the fact and every addition looks defensible on its own.
62
+ ### The shape
63
+
64
+ Group tasks by readiness rather than by status, one row per task, under the columns each group fixes. Keep it to links and blockers, being tables plus at most one sentence per section.
65
+
66
+ - A paragraph in `priority.md` is a defect whatever it says
67
+ - Stating the shape lets a single diff fail. A size cap trips only after the fact, and every addition looks defensible on its own.
56
68
 
57
69
  ### Readiness groups
58
70
 
59
- Readiness is three groups under fixed headings, `## Run now`, `## Up next`, and `## Needs a plan`, in that order. The names are the contract rather than a suggestion, because a board grouped by readiness under names of its own satisfies every other rule here and still reads as empty to anything counting rows under a heading. Add no fourth group. A task belongs to exactly one, and the tests are read in order.
71
+ Readiness is three groups under fixed headings, `## Run now`, `## Up next`, and `## Needs a plan`, in that order. A task belongs to exactly one, and the tests are read in order.
72
+
73
+ | Group | Test |
74
+ | ----------------- | -------------------------------------------------------------------------------------- |
75
+ | `## Run now` | A written plan covers every open outcome, and nothing stated keeps the task from start |
76
+ | `## Up next` | A written plan exists, and the `Waiting on` column names why the task cannot start |
77
+ | `## Needs a plan` | Everything else. No plan, or a plan that no longer describes the work |
78
+
79
+ The names are the contract. A board grouped by readiness under names of its own reads as empty to anything counting rows under a heading, so add no fourth group.
80
+
81
+ ### What blocks a run
82
+
83
+ A collision with running work blocks a task only where no merge settles it, being a contract, a relocation, or a sweep. A shared file alone is none, since the branch merging second rebases.
84
+
85
+ - A worker is handed a task from `## Run now` alone, and its `Touches` column states the set to read
86
+ - Each group's columns follow from its test. Neither half of the `## Run now` test is checkable without the file set and the plan beside the task.
87
+
88
+ ### The `Touches` cell
60
89
 
61
- - `## Run now`: a written plan covers every open outcome, and the task carries no reason it cannot start. A collision with running work is one such reason only where no merge settles it, being a contract, a relocation, or a sweep. A shared file alone is none, since the branch merging second rebases. The `Touches` column states the set to read. A worker is handed a task from this group alone.
62
- - `## Up next`: a written plan exists, and the task carries a stated reason it cannot start. The `Waiting on` column names that reason.
63
- - `## Needs a plan`: everything else. The task has no plan, or the plan it carries no longer describes the work.
90
+ A `Touches` cell is copied from its plan's list, so it states what the branch sets out to write rather than a bound on it. A branch outgrows it while the row still reads as it did at dispatch.
64
91
 
65
- Each group fixes its own columns, which follow from the test above it rather than from preference. Neither half of the `## Run now` test is checkable without the file set and the plan sitting beside the task.
92
+ - Once a branch runs, correct the cell from the diff rather than the plan, which is the prediction that already went stale
93
+ - `canon tasks plan-reach <plan>` reads that diff against every live plan and every cell in the group
94
+ - The row's owner writes the correction. A worker never edits this board.
66
95
 
67
- A `Touches` cell is copied from its plan's own list, so it states what the branch sets out to write rather than a bound on it, and a branch outgrows it while the row still reads as it did at dispatch. Correct the cell from the branch rather than from the plan once one is running, since the plan is the prediction that already went stale and only the diff says what was written. `canon tasks plan-reach <plan>` reads that diff against every live plan and every cell in this group, and the row's owner is the one who writes the correction: a worker never edits this board.
96
+ ### Cell width
68
97
 
69
- A cell holds no code span whose longest unbroken run passes 60 characters, since a span has no break point and a wider one makes its table scroll sideways in the preview. Write a brace-glob out as separate paths for the same reason. `canon tasks validate` reports both in its `wide` array and moves no exit code.
98
+ A cell holds no code span whose longest unbroken run passes 60 characters. A span has no break point, and a wider one makes its table scroll sideways in the preview.
99
+
100
+ - Write a brace-glob out as separate paths for the same reason
101
+ - `canon tasks validate` reports both in its `wide` array and moves no exit code
70
102
 
71
103
  ### Row order
72
104
 
73
- Row position inside `## Needs a plan` is the order those tasks get planned in, top first. The three tests answer whether a task can start, which is mechanical, and none of them answers which task is worth starting, which is a judgment no column holds. Position is where that judgment is recorded, so the top row is the answer to what to plan next and a reader needs no other surface to get it. The other two groups take the same reading, and it costs them little, since a group holding what is already planned is short by construction.
105
+ Row position inside `## Needs a plan` is the order those tasks get planned in, top first. The three tests answer whether a task can start, and none answers which task is worth starting, a judgment no column holds.
74
106
 
75
- Position alone carries it, and no rank column exists. A number beside each row is a second thing to keep in step with the order it duplicates, and the file is edited by one session at a time, so the order the rows are written in is already unambiguous. State on each row why it sits where it does, in the same cell that carries what it is waiting on. A position with no stated reason is re-derived from memory by the next session, which is the failure the ordering replaces rather than moves.
107
+ - Position records that judgment, so the top row answers what to plan next. The other two groups read position the same way, and they are short by construction.
108
+ - No rank column exists. A number beside each row duplicates the order, and one session edits the file at a time, so the written order is unambiguous.
109
+ - A position with no stated reason gets re-derived from memory by the next session, the failure the ordering replaces
76
110
 
77
111
  ### The waiting-on cell
78
112
 
79
- The `Waiting on` column under `## Up next` carries that reason in one of three forms. `## Needs a plan` states no file set at all, because a task with no plan has no bounded one to state. A group with no rows keeps its heading and its header row.
113
+ The `Waiting on` column under `## Up next` carries the reason in one of three forms. `## Needs a plan` states no file set, because a task with no plan has no bounded one. A group with no rows keeps its heading and header row.
114
+
115
+ | Form | The cell names |
116
+ | ------------------ | ----------------------------------------------------------------------------- |
117
+ | Collision | The file the running task holds, and whether a contract, relocation, or sweep |
118
+ | Sibling task | That task |
119
+ | External condition | The condition and what would satisfy it |
120
+
121
+ Naming what would satisfy a condition separates a blocked row from one nobody examined, so a condition with no way out fails the test. The header text is the contract, since a reader resolves the column by header rather than position.
122
+
123
+ ### The needs-a-plan cell
124
+
125
+ Under `## Needs a plan` the cell takes two clauses, being what the task needs before it can be planned and then why it sits at this position. The second clause names what the row ranks against, a sibling row or the class of rows it sits in.
80
126
 
81
- Under `## Up next` a collision names the file held by the task already running and which hold it is: a contract, a relocation, or a sweep. A sibling task names that task, and an external condition names both the condition and what would satisfy it. Naming what would satisfy it is what separates a blocked row from one nobody has examined, so a cell stating a condition with no way out of it fails the test. The header text is the contract the way the group names are, because anything reading the cell resolves the column by header rather than by position.
127
+ - The row `leads`, `heads`, `opens`, `closes`, `trails`, `precedes`, `follows`, or `outranks` what it names, or `sits under`, `above`, or `below` it
128
+ - Either form puts something other than this row in the clause, which makes the position readable by anyone but its author
129
+ - `canon tasks validate` reads that clause back and recognizes this vocabulary alone. A phrasing outside it reports as unranked, and widening it is a change to the check.
82
130
 
83
- Under `## Needs a plan` the cell carries two halves and each takes one clause: what the task needs before it can be planned, then why it sits at this position. The second clause is comparative, and it names what the row is ranked against in one of two forms: a sibling row, or the class of rows it sits in. The row `leads`, `heads`, `opens`, `closes`, `trails`, `precedes`, `follows`, or `outranks` whichever it names, or `sits under`, `above`, or `below` it. Either form puts something other than this row in the clause, which is what makes the position readable by anyone but its author.
131
+ ### What the cell drifts into
84
132
 
85
- Why the task matters is not that claim, and it is what the cell drifts into. A reason naming no other row ranks against nothing, so every row reads defensible on its own and the order records when each was filed. The comparison replaces that reason rather than joining it, since the cell still takes two clauses and no third one is licensed by naming a rival in the second. A cell running past that is the paragraph this file already deletes, arriving one row at a time rather than all at once, and the group is where it costs the most, since it holds the rows nobody has read recently and is the longest group on any board that needs a backlog at all.
133
+ Why the task matters is not the comparative claim, and it is what the cell drifts into. A reason naming no other row ranks against nothing, so every row reads defensible and the order records only when each was filed.
86
134
 
87
- `canon tasks validate` reads that clause back, so a cell phrased comparatively and unusually reports as unranked. The vocabulary above is the whole of what it recognizes, and widening it is a change to the check rather than something the cell may decide for itself.
135
+ - The comparison replaces that reason rather than joining it, and no third clause is licensed by naming a rival in the second
136
+ - A longer cell is the deleted paragraph arriving one row at a time. It costs most in this group, which holds the rows nobody read recently.
137
+
138
+ ### Template
139
+
140
+ The tests live here so the board does not carry them. A sentence under each heading produces the deleted paragraph, and a criterion with no home gets restated from memory each time.
88
141
 
89
142
  ```markdown
90
143
  ---
@@ -112,19 +165,22 @@ description: One line on what the board covers
112
165
  | [vXX.Y <slug>](vXX.Y-<slug>.md) | <what it needs before it can be planned, and which row or class it ranks against> |
113
166
  ```
114
167
 
115
- The tests live here so the board does not carry them. Writing them as a sentence under each heading produces the paragraph the rule above deletes, and a criterion with no home gets restated from memory every time the board is touched.
116
-
117
168
  ## The backlog
118
169
 
119
- A task sits on the board when it would plausibly be planned within the next few waves, and on `backlog.md` otherwise. The call is a judgment, so restate it whenever the board is swept rather than making it once: a backlogged task rises when the work in front of it lands or the world changes under it, and a board row falls to the backlog when it stops being near-term.
170
+ A task sits on the board when it would plausibly be planned within the next few waves, and on `backlog.md` otherwise. Restate that judgment whenever the board is swept, since a backlogged task rises when the work in front of it lands and a board row falls when it stops being near-term.
171
+
172
+ ### Why a split
173
+
174
+ A test over age or origin was the alternative, and neither predicts what gets picked next. Leaving everything on the board produces a group too long to rank.
120
175
 
121
- A mechanical test over age or origin was the alternative and neither predicts what gets picked next, which is the judgment the ordering exists to carry. Leaving everything on the board is the other alternative, and it is what produces a group too long to rank, where the ordering means nothing because nobody can hold the whole list in one reading.
176
+ - The split keeps the board short enough for its order to be read, at the cost of a second surface
177
+ - The trade pays only while the backlog carries no order, no groups, and no readiness claim
122
178
 
123
- What the split buys is that the board is short enough for its order to be read, and what it costs is a second surface to keep. That trade only pays while the backlog stays honest about what it is, which is why it carries no order, no groups, and no readiness claim.
179
+ ### Shape
124
180
 
125
- Nothing is deleted. A backlogged task keeps its file, its findings, and its frontmatter, and the backlog row is a pointer at that file. The folder is gitignored and has no history behind it, so a row dropped without landing somewhere readable is gone with nothing to recover it from.
181
+ Nothing is deleted. A backlogged task keeps its file, findings, and frontmatter, and the row points at that file. The folder has no history, so a row dropped without landing somewhere readable is gone.
126
182
 
127
- The backlog is a flat list of links under one heading, sorted by filename. Sorting mechanically is what keeps it from reading as a queue: the order is the same order the index already sorts in, so no position on it means anything.
183
+ The backlog is a flat list of links under one heading, sorted by filename. The order matches the index, so no position on it reads as a queue.
128
184
 
129
185
  ```markdown
130
186
  ---
@@ -140,8 +196,8 @@ Unordered. Nothing here is scheduled, and a task rises to `priority.md` when it
140
196
  - [vXX.Y <slug>](vXX.Y-<slug>.md)
141
197
  ```
142
198
 
143
- Add no fourth readiness group in place of this file. The three group names are the contract, and a backlog is a separate surface rather than a group because it makes no readiness claim at all: it says nobody has scheduled the task, which is a fact about attention rather than about whether the work can start.
199
+ Add no fourth readiness group in place of this file. A backlog makes no readiness claim, only that nobody has scheduled the task, a fact about attention rather than whether the work can start.
144
200
 
145
201
  ## Validation
146
202
 
147
- `canon tasks validate` reads the board against the tree, and what it checks, what it refuses on, and what it reports are at `canon tasks validate --help`. Run it when the readiness claim is made rather than on a schedule, since the board is gitignored per-machine scratch and no shared moment exists to hang it on.
203
+ `canon tasks validate` reads the board against the tree, and `canon tasks validate --help` states what it checks, refuses on, and reports. Run it when the readiness claim is made rather than on a schedule, since the board is per-machine scratch and no shared moment exists to hang it on.
@@ -7,15 +7,13 @@ description: How task-board gathers the reason a task is decided against, runs c
7
7
 
8
8
  The Decline mode of `task-board`. The session reads this file when the request names a task decided against.
9
9
 
10
- Read `${CLAUDE_SKILL_DIR}/references/tasks-decline.md` first. It holds the declined folder, the `Declined:` line, and what the move does to a plan and a board row.
11
-
12
- 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.
13
-
14
- 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.
10
+ - Read `${CLAUDE_SKILL_DIR}/references/tasks-decline.md` first, for the declined folder, the `Declined:` line, and what the move does to a plan and a board row
11
+ - A declined task carries no `post-merge` hook of its own, so every decline request arrives here directly
12
+ - `canon tasks decline` moves the file, edits `priority.md` or `backlog.md`, and regenerates the index as one unit. Do none of the three by hand.
15
13
 
16
14
  ## Step 1: gather the reason
17
15
 
18
- 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.
16
+ Ask for the reason when the request carries none, and stop rather than guessing with `❌ No reason. Say why the task is being declined.` The command refuses without `--reason <text>`, so asking first saves the round trip.
19
17
 
20
18
  ## Step 2: run the decline
21
19
 
@@ -25,18 +23,36 @@ Pass the task's filename stem:
25
23
  canon tasks decline <stem> --reason "<text>" [--by <name>] --json
26
24
  ```
27
25
 
28
- 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`.
26
+ Branch on the record's `ok`, then on `reason`, never on the exit. A shell wrapper can flatten the exit, the same hazard `canon tasks archive` carries.
27
+
28
+ ### Success record
29
+
30
+ A successful decline returns one record whose fields match `canon tasks archive` where the two overlap.
29
31
 
30
- 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 `plans`, one `from` and `to` for each live plan the task was the last live citation of, empty when nothing moved, the same shape `canon tasks archive` uses for its own `plans` field.
32
+ | Field | Holds |
33
+ | -------------------- | ------------------------------------------------------------------------ |
34
+ | `from`, `to` | The task's old and new path |
35
+ | `priorityRowRemoved` | Whether a `priority.md` row was dropped |
36
+ | `backlogRowRemoved` | Whether a `backlog.md` row was dropped, a field archive lacks |
37
+ | `indexRegenerated` | Whether the index was rewritten |
38
+ | `plans` | A `from` and `to` per live plan the task last cited, empty if none moved |
39
+
40
+ `backlogRowRemoved` is decline's own, since a task can be declined straight off `backlog.md` and archive never checks that file.
31
41
 
32
42
  ## Step 3: route on a refusal
33
43
 
34
- - `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.
35
- - `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.
36
- - `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.
44
+ Each refusal names its cause and the fix.
45
+
46
+ | `reason` | Cause | Fix |
47
+ | ----------- | -------------------------------------------------------------------- | ------------------------------------------ |
48
+ | `no-match` | No task matches, or one starts with the stem and needs its full name | Check against the listed stems |
49
+ | `ambiguous` | The stem is a prefix of more than one task | Pass the full stem |
50
+ | `bad-input` | The command line was wrong rather than the board | Read the message, fix the arguments, rerun |
51
+
52
+ Archive's own `ambiguous` fires on a shared pull request instead, and decline takes no pull-request selector. A `bad-input` leaves nothing on the board to repair, which separates it from the other two.
37
53
 
38
- 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.
54
+ Never move a plan by hand from this skill. The command carries the plan along when no other live task cites it and retargets the `Plan:` line, and a second mover relocates the same file differently.
39
55
 
40
56
  ## Step 4: clear prose naming the task
41
57
 
42
- 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.
58
+ The command drops the 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 changed rows, since a stale count reads as board state.
@@ -27,12 +27,19 @@ A declined task works when a later reader can tell, from the folder and the file
27
27
 
28
28
  ## Declining
29
29
 
30
- A task decided against moves to `.canon/tasks/declined/` rather than `.canon/tasks/archive/`. The two folders answer different questions: archive means the work shipped, declined means somebody decided against doing it. Neither reading fits a task that is merely unscheduled, which stays on `backlog.md` rather than moving anywhere, since nobody has decided against it and it may still rise when the board has room.
30
+ A task decided against moves to `.canon/tasks/declined/` rather than `.canon/tasks/archive/`. Archive means the work shipped, and declined means somebody decided against doing it.
31
31
 
32
- `canon tasks decline` carries no outcome-state gate, so a task can be decided against at any outcome state, open outcomes included.
32
+ - A merely unscheduled task fits neither. It stays on `backlog.md`, since nobody decided against it and it may still rise.
33
+ - `canon tasks decline` carries no outcome-state gate, so a task can be declined at any outcome state, open outcomes included
34
+ - The move clears whichever of `priority.md` or `backlog.md` holds the task's row
33
35
 
34
- The decision is recorded on the task itself with a `Declined:` line, in the `Plan:`/`Pull request:` family: `Declined: <reason>, <who> on <YYYY-MM-DD>`. It anchors the same way `Pull request:` does, after the last origin line the task carries. The line is free prose after the colon, since it names no file to link.
36
+ ### The `Declined:` line
35
37
 
36
- Declining a task moves its plan alongside it the same way archiving does, when the declining task is that plan's last live citation. A plan several tasks share stays where it is, and a declined task's plan lands in `.canon/plans/archive/` indistinguishable from a shipped one by folder alone. The task file under `.canon/tasks/declined/` is what records which it was.
38
+ The decision is recorded on the task with a `Declined:` line in the `Plan:` and `Pull request:` family, as `Declined: <reason>, <who> on <YYYY-MM-DD>`. It anchors after the last origin line the task carries, as `Pull request:` does, and stays free prose since it names no file to link.
37
39
 
38
- The move clears whichever of `priority.md` or `backlog.md` holds the task's row.
40
+ ### The plan
41
+
42
+ Declining moves the plan alongside the task when the task is that plan's last live citation, as archiving does. A plan several tasks share stays where it is.
43
+
44
+ - A declined task's plan lands in `.canon/plans/archive/`, indistinguishable from a shipped one by folder alone
45
+ - The task file under `.canon/tasks/declined/` records which it was