@erclx/canon 5.37.0 → 5.39.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 (197) hide show
  1. package/README.md +1 -1
  2. package/claude/.claude-plugin/plugin.json +1 -1
  3. package/claude/skills/api-design/SKILL.md +12 -9
  4. package/claude/skills/auto-ship/SKILL.md +43 -23
  5. package/claude/skills/backlog-triage/SKILL.md +62 -53
  6. package/claude/skills/backlog-triage/references/apply.md +69 -0
  7. package/claude/skills/build-in-slices/SKILL.md +8 -4
  8. package/claude/skills/canon-cli/SKILL.md +5 -1
  9. package/claude/skills/canon-feedback/SKILL.md +18 -8
  10. package/claude/skills/canon-feedback-triage/SKILL.md +10 -3
  11. package/claude/skills/canvas-board/SKILL.md +36 -17
  12. package/claude/skills/ci-workflow/SKILL.md +5 -4
  13. package/claude/skills/code-craft/SKILL.md +10 -6
  14. package/claude/skills/codebase-layout/SKILL.md +3 -5
  15. package/claude/skills/context-fold/REQUIREMENT.md +4 -4
  16. package/claude/skills/context-fold/SKILL.md +42 -23
  17. package/claude/skills/context-fold/references/context-refresh.md +4 -3
  18. package/claude/skills/context-fold/references/context.md +79 -64
  19. package/claude/skills/create-rule/SKILL.md +7 -3
  20. package/claude/skills/create-skill/SKILL.md +27 -7
  21. package/claude/skills/create-skill/references/skill-reference.md +41 -17
  22. package/claude/skills/decision-escalate/SKILL.md +8 -5
  23. package/claude/skills/deploy-app/SKILL.md +1 -1
  24. package/claude/skills/deprecation-migration/SKILL.md +12 -4
  25. package/claude/skills/design-taste/SKILL.md +17 -11
  26. package/claude/skills/docs-sync/REQUIREMENT.md +1 -0
  27. package/claude/skills/docs-sync/SKILL.md +17 -6
  28. package/claude/skills/docs-sync/references/docs.md +54 -21
  29. package/claude/skills/docs-sync/references/readme.md +32 -8
  30. package/claude/skills/document-health/SKILL.md +3 -4
  31. package/claude/skills/draft-and-pick/SKILL.md +73 -47
  32. package/claude/skills/draft-doc/SKILL.md +9 -4
  33. package/claude/skills/draft-doc/references/context.md +4 -4
  34. package/claude/skills/draft-doc/references/docs.md +1 -0
  35. package/claude/skills/draft-doc/references/wiki.md +3 -2
  36. package/claude/skills/draft-figure/SKILL.md +9 -7
  37. package/claude/skills/draft-identity/SKILL.md +24 -52
  38. package/claude/skills/draft-identity/references/card-route.md +46 -0
  39. package/claude/skills/draft-ready/SKILL.md +19 -7
  40. package/claude/skills/draft-screencast/SKILL.md +6 -112
  41. package/claude/skills/draft-screencast/references/beats-template.md +119 -0
  42. package/claude/skills/draft-slides/SKILL.md +7 -4
  43. package/claude/skills/git-branch/SKILL.md +3 -3
  44. package/claude/skills/git-commit/SKILL.md +5 -3
  45. package/claude/skills/git-followup/SKILL.md +16 -9
  46. package/claude/skills/git-issue/SKILL.md +6 -5
  47. package/claude/skills/git-issue/references/issue.md +11 -10
  48. package/claude/skills/git-pr/SKILL.md +56 -44
  49. package/claude/skills/git-ship/SKILL.md +43 -34
  50. package/claude/skills/git-ship/references/ci-watch.md +31 -0
  51. package/claude/skills/git-split/SKILL.md +28 -100
  52. package/claude/skills/git-split/references/independent.md +40 -0
  53. package/claude/skills/git-split/references/stacked.md +73 -0
  54. package/claude/skills/git-stage/SKILL.md +9 -7
  55. package/claude/skills/git-worktree/SKILL.md +27 -49
  56. package/claude/skills/git-worktree/references/cleanup.md +55 -0
  57. package/claude/skills/markdown-craft/SKILL.md +2 -2
  58. package/claude/skills/markdown-craft/references/markdown.md +82 -52
  59. package/claude/skills/plan-feature/SKILL.md +52 -46
  60. package/claude/skills/plan-feature/references/batches.md +46 -0
  61. package/claude/skills/plan-groundwork/SKILL.md +60 -74
  62. package/claude/skills/plan-groundwork/references/groundwork.md +53 -24
  63. package/claude/skills/plan-groundwork/references/output.md +48 -0
  64. package/claude/skills/plan-intake/SKILL.md +28 -21
  65. package/claude/skills/plan-intake-answer/SKILL.md +14 -13
  66. package/claude/skills/read-frames/SKILL.md +2 -0
  67. package/claude/skills/record-screencast/SKILL.md +31 -11
  68. package/claude/skills/review-address/SKILL.md +76 -158
  69. package/claude/skills/review-address/references/rebase-only.md +34 -0
  70. package/claude/skills/review-craft/SKILL.md +27 -11
  71. package/claude/skills/review-pr/SKILL.md +91 -40
  72. package/claude/skills/review-pr/references/post.md +1 -1
  73. package/claude/skills/review-ui/SKILL.md +62 -37
  74. package/claude/skills/review-ui/references/hosted-preview.md +30 -0
  75. package/claude/skills/role-orchestrator/SKILL.md +105 -74
  76. package/claude/skills/role-orchestrator/references/orchestrator-filing.md +26 -0
  77. package/claude/skills/role-orchestrator/references/orchestrator-parked.md +1 -1
  78. package/claude/skills/role-planner/SKILL.md +66 -64
  79. package/claude/skills/role-reviewer/SKILL.md +57 -46
  80. package/claude/skills/role-worker/SKILL.md +68 -63
  81. package/claude/skills/search-craft/SKILL.md +7 -5
  82. package/claude/skills/session-compact/SKILL.md +16 -11
  83. package/claude/skills/session-map/SKILL.md +31 -10
  84. package/claude/skills/session-relay/SKILL.md +32 -65
  85. package/claude/skills/session-resume/SKILL.md +18 -13
  86. package/claude/skills/session-worktree/SKILL.md +70 -42
  87. package/claude/skills/systematic-debugging/SKILL.md +6 -1
  88. package/claude/skills/target-check/SKILL.md +13 -6
  89. package/claude/skills/target-setup/SKILL.md +41 -30
  90. package/claude/skills/target-setup/references/verify.md +6 -5
  91. package/claude/skills/task-board/SKILL.md +68 -60
  92. package/claude/skills/task-board/references/create-report.md +36 -0
  93. package/claude/skills/task-board/references/tasks.md +3 -1
  94. package/claude/skills/task-complete/SKILL.md +20 -18
  95. package/claude/skills/teach-workspace/SKILL.md +61 -33
  96. package/claude/skills/test-craft/SKILL.md +2 -1
  97. package/claude/skills/test-first/SKILL.md +15 -9
  98. package/claude/skills/ui-checklist/SKILL.md +18 -16
  99. package/claude/skills/ux-audit/SKILL.md +9 -10
  100. package/claude/skills/ux-measure/SKILL.md +22 -18
  101. package/claude/skills/video-craft/SKILL.md +15 -7
  102. package/claude/skills/write-human/SKILL.md +9 -1
  103. package/claude/skills/youtube-transcripts/SKILL.md +2 -1
  104. package/docs/agents/context-audit-checks.md +19 -1
  105. package/docs/agents/context-audit.md +2 -2
  106. package/docs/agents/driver.md +1 -1
  107. package/docs/agents/hooks.md +21 -1
  108. package/docs/agents/index.md +10 -14
  109. package/docs/agents/indexes.md +25 -29
  110. package/docs/agents/install-and-sync.md +124 -235
  111. package/docs/agents/markdown-audit-density.md +39 -0
  112. package/docs/agents/markdown-audit-weight.md +9 -7
  113. package/docs/agents/markdown-audit.md +18 -14
  114. package/docs/agents/migrate.md +41 -16
  115. package/docs/agents/output-shape.md +60 -45
  116. package/docs/agents/overview.md +36 -12
  117. package/docs/agents/routing.md +1 -1
  118. package/docs/agents/rule-citations.md +1 -1
  119. package/docs/agents/skills-reach.md +1 -1
  120. package/docs/agents/targets.md +25 -77
  121. package/docs/target/migrations.md +1 -1
  122. package/docs/target/projects.md +3 -3
  123. package/docs/target/scenarios.md +1 -1
  124. package/docs/workflow/ai-workflow.md +2 -2
  125. package/docs/workflow/parallel-features.md +2 -2
  126. package/docs/workflow/skill-map.md +1 -1
  127. package/docs/workflow/visual-design-workflow.md +1 -1
  128. package/governance/detect.toml +6 -1
  129. package/package.json +6 -3
  130. package/scripts/core/install-check.sh +1 -1
  131. package/src/commands/claude.ts +1 -2
  132. package/src/commands/context.ts +106 -7
  133. package/src/commands/hooks.ts +63 -0
  134. package/src/commands/markdown.ts +169 -32
  135. package/src/commands/pr.ts +1 -1
  136. package/src/commands/records.ts +0 -1
  137. package/src/context/audit.ts +256 -5
  138. package/src/context/classify/prompts.ts +1 -1
  139. package/src/context/gate.ts +23 -7
  140. package/src/context/shape-gated.ts +28 -0
  141. package/src/design/document.ts +1 -1
  142. package/src/design/tokens.ts +1 -1
  143. package/src/docs/read.ts +15 -21
  144. package/src/gate/measures.ts +15 -190
  145. package/src/gate/stages.ts +21 -23
  146. package/src/hooks/reply-links.ts +110 -0
  147. package/src/markdown/density.ts +258 -0
  148. package/src/markdown/gate.ts +57 -18
  149. package/src/markdown/reference-shape.ts +103 -0
  150. package/src/markdown/scope.ts +174 -0
  151. package/src/markdown/structure.ts +10 -60
  152. package/src/sandbox/equivalence.ts +7 -9
  153. package/src/shipped/references.ts +1 -1
  154. package/src/teach/browser/head.ts +2 -2
  155. package/src/teach/browser/sidebar.ts +3 -3
  156. package/src/teach/browser/theme.ts +2 -2
  157. package/src/tooling/inject.ts +2 -2
  158. package/src/tooling/package.ts +15 -18
  159. package/src/tooling/verify-stack.ts +6 -3
  160. package/tooling/astro/configs/.oxfmtrc.json +8 -0
  161. package/tooling/astro/configs/.prettierrc +13 -0
  162. package/tooling/astro/manifest.toml +13 -0
  163. package/tooling/astro/reference.md +15 -5
  164. package/tooling/base/configs/.oxfmtrc.json +7 -0
  165. package/tooling/base/configs/scripts/verify.ts +1 -1
  166. package/tooling/base/manifest.toml +6 -6
  167. package/tooling/base/reference.md +12 -9
  168. package/tooling/base/seeds/.lintstagedrc +1 -3
  169. package/tooling/base/seeds/canon/context/ci.md +3 -3
  170. package/tooling/base/seeds/canon/context/development.md +2 -2
  171. package/tooling/claude/manifest.toml +5 -1
  172. package/tooling/claude/seeds/.claude/hooks/reply-links.sh +72 -0
  173. package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +22 -1
  174. package/tooling/claude/seeds/.claude/settings.json +4 -0
  175. package/tooling/go/reference.md +2 -2
  176. package/tooling/nextjs/configs/.oxlintrc.json +223 -0
  177. package/tooling/nextjs/manifest.toml +2 -5
  178. package/tooling/nextjs/reference.md +4 -4
  179. package/tooling/php/manifest.toml +6 -1
  180. package/tooling/php/reference.md +2 -2
  181. package/tooling/python/manifest.toml +6 -1
  182. package/tooling/python/reference.md +4 -4
  183. package/tooling/vite-react/manifest.toml +1 -4
  184. package/tooling/vite-react/reference.md +3 -3
  185. package/tooling/web/configs/.oxlintrc.json +213 -0
  186. package/tooling/web/manifest.toml +9 -13
  187. package/tooling/web/reference.md +14 -14
  188. package/docs/agents/commands.md +0 -154
  189. package/docs/agents/docs.md +0 -27
  190. package/docs/agents/drift-surfaces.md +0 -201
  191. package/docs/agents/gov-detect.md +0 -47
  192. package/docs/agents/scripting.md +0 -142
  193. package/src/markdown/growth.ts +0 -43
  194. package/tooling/base/configs/.prettierrc +0 -12
  195. package/tooling/base/seeds/.prettierignore +0 -0
  196. package/tooling/nextjs/configs/eslint.config.js +0 -91
  197. package/tooling/web/configs/eslint.config.js +0 -82
@@ -7,13 +7,14 @@ metadata:
7
7
 
8
8
  # Review address
9
9
 
10
- The worker's half of the review channel. `review-pr` posts findings to
11
- the PR from an independent session. This skill consumes them: fix, reply, push.
10
+ The worker's half of the review channel. `review-pr` posts findings to the PR from an independent session. This skill consumes them: fix, reply, push.
12
11
 
13
12
  ## Guards
14
13
 
15
- - Resolve `<number>` and `<tip>` off `canon pr head --json`. An `ambiguous-pull` refusal stops: `āŒ Two open PRs on this branch. Name the one to address.` A record with no `number` takes the lookup in `${CLAUDE_SKILL_DIR}/references/rest-reads.md`. Nothing resolving stops: `āŒ No open PR. Nothing to address.`
16
- - If the PR has no review comments or threads, run step 5's staleness test before deciding. A branch that passes both of its halves stops here: `āœ… No review findings to address.` One that fails either skips steps 1 through 4 and runs step 5 onward, since a branch goes stale from `main` moving and a closed review says nothing about whether it still merges.
14
+ - Resolve `<number>` and `<tip>` off `canon pr head --json`. An `ambiguous-pull` refusal stops: `āŒ Two open PRs on this branch. Name the one to address.`
15
+ - A record with no `number` takes the lookup in `${CLAUDE_SKILL_DIR}/references/rest-reads.md`. Nothing resolving stops: `āŒ No open PR. Nothing to address.`
16
+ - If the PR has no review comments or threads, run step 5's staleness test before deciding. A branch passing both halves stops here: `āœ… No review findings to address.`
17
+ - A branch failing either half skips steps 1 through 4 and runs step 5 onward, since a branch goes stale from `main` moving and a closed review says nothing about whether it still merges
17
18
  - Fix findings. Do not merge.
18
19
 
19
20
  ## Step 1: pull the review findings and CI status
@@ -26,30 +27,32 @@ Also read the CI check status so the fixes cover failing checks, not only review
26
27
  canon pr checks <number> --json
27
28
  ```
28
29
 
29
- Read the verdict off the record's `state` rather than off the exit. Treat `failing` as a finding to resolve alongside the review comments. A `pending` covers a tip whose runs have yet to conclude and a tip carrying no run at all, which the record separates on `matched`, and neither is a green to continue on. A record carrying `conflicted: true` is a third case: the branch conflicts with its base, so no run will start and the wait never ends. Stop and report it, since a rebase is the repair. When no record comes back at all, read the check runs on the tip through `${CLAUDE_SKILL_DIR}/references/rest-reads.md`.
30
+ Read the verdict off the record's `state` rather than off the exit.
31
+
32
+ | Record | Means |
33
+ | ------------------ | ----------------------------------------------------------------------------------------------------------- |
34
+ | `failing` | A finding to resolve alongside the review comments |
35
+ | `pending` | Runs not concluded, or no run on the tip, which `matched` separates. Neither is a green to continue on. |
36
+ | `conflicted: true` | The branch conflicts with its base, so no run will start. Stop and report it, since a rebase is the repair. |
37
+ | No record | Read the check runs on the tip through `${CLAUDE_SKILL_DIR}/references/rest-reads.md` |
30
38
 
31
39
  ## Step 2: address each finding
32
40
 
33
- For each finding, implement the fix in the working tree. When a finding is a
34
- question or a conscious-accept rather than a defect, note the reply text instead
35
- of editing. Handle each finding independently. Do not let one unresolved finding
36
- block the others.
41
+ For each finding, implement the fix in the working tree. When a finding is a question or a conscious-accept rather than a defect, note the reply text instead of editing. Handle each finding independently, so one unresolved finding blocks no other.
37
42
 
38
43
  ## Step 3: verify
39
44
 
40
- Run the project check (`bun run check` or the project's documented equivalent).
41
- Do not push a red follow-up.
45
+ Run the project check (`bun run check` or the project's documented equivalent). Do not push a red follow-up.
42
46
 
43
47
  ## Step 4: refresh stale docs
44
48
 
45
- The fixes may have changed or added behavior that `.claude/` context entries or docs 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.
49
+ The fixes may have changed behavior that `.claude/` context entries or docs describe. Refresh them with the `context-fold` skill, which maps changed files to the entries citing them and rewrites the stale sections.
50
+
51
+ Do not reimplement that mapping here. When a fix adds a capability with no existing entry, `context-fold` flags it rather than creating one.
46
52
 
47
53
  ## Step 5: rebase a stale branch
48
54
 
49
- A branch goes stale from `main` moving rather than from anything the branch did,
50
- so the test runs on every invocation, including the one the second guard sends
51
- straight here with no findings to fix. Fetch first. A stale local `origin/main`
52
- reports no conflict on a branch that has one.
55
+ A branch goes stale from `main` moving rather than from anything it did, so the test runs on every invocation, including one the guard sends straight here. Fetch first, since a stale local `origin/main` reports no conflict on a branch that has one.
53
56
 
54
57
  ```bash
55
58
  git fetch origin main
@@ -59,114 +62,59 @@ git diff -z --name-only --no-renames "$fork" HEAD |
59
62
  xargs -0 -r git --literal-pathspecs diff --name-only --no-renames "$fork" origin/main --
60
63
  ```
61
64
 
62
- `merge-tree` exiting non-zero means the branch no longer merges, and a path the
63
- last command prints means `main` changed a file it writes after it branched, so
64
- its green run tested a merge nobody will make. Even a clean merge can hide
65
- semantic conflicts, per Fowler's [Mainline Integration](https://martinfowler.com/articles/branching-patterns.html#mainline-integration),
66
- so either one sends the branch to `${CLAUDE_SKILL_DIR}/references/rebase-conflicts.md`
67
- for the sequence, the conflict rules, and the check to re-run. When that check
68
- fails after a clean rebase, the failure is the semantic conflict, fixed on the
69
- branch like any other. Neither firing skips to step 6, which covers a `main` that
70
- moved only on files the branch does not write.
71
-
72
- `git merge-tree` reads committed history, so this test says nothing about the
73
- fixes still sitting in the working tree. A branch that merges clean as committed,
74
- whose fixes touch lines `main` moved, passes here and reaches the remote
75
- unmergeable. Step 6 re-runs the test once those fixes are commits.
65
+ ### Reading the test
66
+
67
+ `merge-tree` exiting non-zero means the branch no longer merges. A path the last command prints means `main` changed a file the branch writes, so its green run tested a merge nobody will make.
68
+
69
+ - Either one sends the branch to `${CLAUDE_SKILL_DIR}/references/rebase-conflicts.md` for the sequence, the conflict rules, and the check to re-run
70
+ - Even a clean merge can hide semantic conflicts, per Fowler's [Mainline Integration](https://martinfowler.com/articles/branching-patterns.html#mainline-integration). A check failing after a clean rebase is one, fixed on the branch.
71
+ - Neither firing skips to step 6, which covers a `main` that moved only on files the branch does not write
72
+
73
+ `git merge-tree` reads committed history, so it says nothing about fixes still in the working tree. Step 6 re-runs the test once those fixes are commits.
76
74
 
77
75
  ## Step 6: push, then reply
78
76
 
79
- Push the fixes before posting the reply so the comment never runs ahead of the
80
- code it describes. Ship the fixes as a follow-up commit on the same branch with
81
- the `git-followup` skill, invoked with `reply-owned` so it stages, commits,
82
- pushes, and refreshes the open PR body without posting its own comment. This
83
- skill owns the reply. Do not reimplement that flow here.
84
-
85
- `git-followup` syncs the body and title against the fix commit on every
86
- invocation, including `reply-owned`, so the merge record reflects what this pass
87
- changed rather than only what opened the PR. The reply comment still carries the
88
- fix log mapped to each finding, since the two serve different readers: the body
89
- is the merge record and the reply is the review's own thread. A rebase in step 5
90
- rewrote the branch, so that push is a force-push and `git-followup` resolves it
91
- from the tracking branch. Worker branches are single-owner here, which is what
92
- makes overwriting the remote safe.
93
-
94
- `git-followup` stops on an unchanged tree. A run that answered every finding as a
95
- conscious-accept and whose rebase left the generated files alone has nothing for
96
- it to commit, so the rebase would never reach the remote. Push that case directly
97
- with `git push --force-with-lease`, then post the reply below.
98
-
99
- Once the fixes are commits, re-run step 5's staleness test against the new head.
100
- A conflict that appears only now is one the fixes introduced against lines `main`
101
- moved, which the earlier test could not see. Rebase again under
102
- `${CLAUDE_SKILL_DIR}/references/rebase-conflicts.md` and force-push, then
103
- continue. The second push costs one extra force-push in a
104
- case that needs the fix and the sibling to touch the same lines.
105
-
106
- Then write a summary reply to `.canon/tmp/pr/reply/reply-<number>.md`
107
- mapping each finding to what changed, or to a one-line reason when it is a
108
- conscious-accept rather than a defect. Key the filename on the PR number so two
109
- sessions addressing different pull requests never overwrite each other between
110
- the write and the post. Note any `.claude/` docs refreshed as a result of the
111
- fixes.
112
-
113
- The reply is a rendered-for-human GitHub surface, so load the `write-human`
114
- skill for voice and word choice, follow
115
- `${CLAUDE_SKILL_DIR}/../markdown-craft/references/markdown.md` for punctuation, and keep each
116
- mapping to a line or two.
117
-
118
- Open the body with the `## Review response` heading so it anchors as a section
119
- distinct from human threads and stays subordinate to the `## Review` heading the
120
- review itself carries. Follow it with a one-line summary sentence, then one
121
- bullet per finding, each opening with the bolded finding identifier.
122
- Close the body with `šŸ¤– Addressed by Claude Code` on its own line so the reply
123
- reads as an independent machine pass, not a human sign-off.
124
-
125
- A finding this run declined carries the fact that settled it, inside its own
126
- bullet rather than in a section of its own. Name the plan question that already
127
- answered it, the constraint the diff does not show, or the measurement the
128
- reviewer did not have. Answering the dispatch in the channel and leaving that
129
- fact there loses it when both sessions end, and the reviewer is left with a
130
- finding that stopped being mentioned. The rule fires on a bullet the body already
131
- writes, so nothing depends on judging mid-reply whether a reply was important.
132
-
133
- The rule reaches a finding and nothing else. A correction to what the reviewing
134
- session believes about the world, such as which session holds which branch or
135
- what an edit passes through before it lands, changes no finding on this pull
136
- request and belongs in that session's own record rather than on a thread that
137
- closes. Keep it off the comment, and answer it wherever the dispatch reached this
138
- session when one did. Nothing tests the reply for either rule, since the scan
139
- below reads it for banned characters and phase labels alone, so both halves hold
140
- while a run applies them.
141
-
142
- The `pull_request` check the git-pr surface carries reads a pull request's own
143
- title and body, not a reply comment, so the scan below stays the only gate here.
144
-
145
- When step 5 rebased the branch, say so in the summary sentence and name which
146
- files were resolved by hand and which the regen rebuilt. The next review is a
147
- full pass rather than a delta, and the reader is owed the reason.
148
-
149
- A run the second guard sent straight to step 5 has no findings to map, so it
150
- takes a different body rather than an empty list. Open it with `## Rebase`, not
151
- `## Review response`, since nothing on the pull request is being responded to and
152
- that heading claims a review this run never read. State which half of the test
153
- fired, being a branch that stopped merging or one `main` changed files under,
154
- name what landed on `main`, name the files resolved by hand and those
155
- the regen rebuilt, and close the same way. The heading stays outside the
156
- `## Review` family so the close-out's equality test on the first line never
157
- matches it.
158
-
159
- Before posting, follow `${CLAUDE_SKILL_DIR}/../git-pr/references/publish.md`
160
- and run its scan against the reply:
77
+ Push the fixes before posting the reply, so the comment never runs ahead of the code it describes. Ship them as a follow-up commit with `git-followup`, invoked with `reply-owned` so it stages, commits, pushes, and refreshes the PR body without its own comment.
78
+
79
+ ### What the push carries
80
+
81
+ This skill owns the reply, so do not reimplement the followup flow here.
82
+
83
+ - `git-followup` syncs the body and title on every invocation, `reply-owned` included, so the merge record reflects this pass. The reply still maps fixes to findings in the review's own thread.
84
+ - A rebase in step 5 rewrote the branch, so the push is a force-push `git-followup` resolves from the tracking branch. Worker branches are single-owner, which makes that safe.
85
+ - `git-followup` stops on an unchanged tree, as when every finding was a conscious-accept and the rebase left generated files alone. Push that with `git push --force-with-lease`.
86
+
87
+ Once the fixes are commits, re-run step 5's staleness test against the new head. A conflict appearing only now is one the fixes introduced against lines `main` moved, so rebase again under `${CLAUDE_SKILL_DIR}/references/rebase-conflicts.md` and force-push.
88
+
89
+ ### Write the reply
90
+
91
+ Write a summary reply to `.canon/tmp/pr/reply/reply-<number>.md`, keyed on the PR number so two sessions addressing different pull requests never overwrite each other. Load `write-human` for voice, follow `${CLAUDE_SKILL_DIR}/../markdown-craft/references/markdown.md`, and keep each mapping to a line or two.
92
+
93
+ | Part | Content |
94
+ | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------- |
95
+ | Heading | `## Review response`, distinct from human threads and subordinate to the review's own `## Review` |
96
+ | Summary | One sentence. After a step 5 rebase, say so and name files resolved by hand and those the regen rebuilt, since the next review is a full pass. |
97
+ | Findings | One bullet per finding, opening with the bolded identifier, naming what changed or a one-line reason for a conscious-accept |
98
+ | Docs | Any `.claude/` docs refreshed as a result of the fixes |
99
+ | Close | `šŸ¤– Addressed by Claude Code` on its own line, so the reply reads as a machine pass rather than a human sign-off |
100
+
101
+ A run the guard sent straight to step 5 has no findings to map, so it takes the `## Rebase` body in `${CLAUDE_SKILL_DIR}/references/rebase-only.md` instead. A run with findings skips that file.
102
+
103
+ ### What a declined finding carries
104
+
105
+ A finding this run declined carries the fact that settled it inside its own bullet, such as the plan question that answered it, a constraint the diff does not show, or a measurement the reviewer lacked. Left in the channel, that fact is lost when both sessions end.
106
+
107
+ The rule reaches a finding and nothing else. A correction to what the reviewing session believes about the world changes no finding here, so answer it wherever the dispatch reached this session and keep it off the comment.
108
+
109
+ ### Scan and post
110
+
111
+ Nothing tests the reply for either rule above. Follow `${CLAUDE_SKILL_DIR}/../git-pr/references/publish.md` and run its scan, which reads for banned characters and phase labels alone:
161
112
 
162
113
  ```bash
163
114
  canon labels scan --body-file .canon/tmp/pr/reply/reply-<number>.md
164
115
  ```
165
116
 
166
- The hook skips `.canon/tmp/`, so this scan is the only gate on the published
167
- reply. Fix any hit the standard names, then post the reply to the PR and
168
- keep the `id` the POST answers with, since Step 7 edits this exact comment rather
169
- than trusting whichever one `gh` considers last:
117
+ The hook skips `.canon/tmp/`, and the `pull_request` check reads only a pull request's own title and body, so this scan is the only gate on the reply. Fix any hit, then post and keep the `id` the POST answers with, since Step 7 edits this exact comment:
170
118
 
171
119
  ```bash
172
120
  gh api -X POST 'repos/{owner}/{repo}/issues/<number>/comments' -F body=@.canon/tmp/pr/reply/reply-<number>.md --jq .id > .canon/tmp/pr/reply/reply-<number>.id
@@ -174,39 +122,26 @@ gh api -X POST 'repos/{owner}/{repo}/issues/<number>/comments' -F body=@.canon/t
174
122
 
175
123
  ## Step 7: confirm resolution
176
124
 
177
- After the push, read Watching CI in `${CLAUDE_SKILL_DIR}/../git-ship/SKILL.md`
178
- without invoking that skill, start its background watch, end the turn on its
179
- line, and run the rest of this step and Step 8 on the wake. Reuse a watch
180
- already running on this PR, since it reads the new tip. On the wake, stop on `conflicted` naming a rebase, on a `reason` naming it,
181
- and on a timeout reporting CI unsettled. When every finding is addressed and
182
- the state is `passing`, append
183
- the closing confirmation to the reply file Step 6 already posted, so the thread
184
- carries one terminal state rather than a second comment under no heading:
125
+ After the push, read Watching CI in `${CLAUDE_SKILL_DIR}/../git-ship/SKILL.md` without invoking that skill, start its background watch, end the turn on its line, and run the rest of this step and Step 8 on the wake. Reuse a watch already running on this PR, since it reads the new tip.
185
126
 
186
- ```bash
187
- printf '\nāœ… All review findings addressed, CI green.\n' >> .canon/tmp/pr/reply/reply-<number>.md
188
- ```
127
+ - On the wake, stop on `conflicted` naming a rebase, on a `reason` naming it, and on a timeout reporting CI unsettled
128
+ - If any check fails, skip the edit and report the failing check so it can be fixed first
189
129
 
190
- A rebase-only run addressed no finding, so it appends its own confirmation
191
- instead of that one. Claiming findings were addressed on a pull request that
192
- carries none is false on a surface nothing else checks:
130
+ When every finding is addressed and the state is `passing`, append the closing confirmation to the reply file Step 6 posted, so the thread carries one terminal state rather than a second comment. A rebase-only run appends the line `${CLAUDE_SKILL_DIR}/references/rebase-only.md` gives instead.
193
131
 
194
132
  ```bash
195
- printf '\nāœ… Rebased onto origin/main, CI green. No review findings were open.\n' >> .canon/tmp/pr/reply/reply-<number>.md
133
+ printf '\nāœ… All review findings addressed, CI green.\n' >> .canon/tmp/pr/reply/reply-<number>.md
196
134
  ```
197
135
 
198
- Re-run the scan against the updated file, since the appended line is new
199
- content the Step 6 scan never saw:
136
+ Re-run the scan against the updated file, since the appended line is new content the Step 6 scan never saw:
200
137
 
201
138
  ```bash
202
139
  canon labels scan --body-file .canon/tmp/pr/reply/reply-<number>.md
203
140
  ```
204
141
 
205
- Then edit the exact comment Step 6 posted, read back from the id it saved,
206
- rather than posting a second comment. A shell variable assigned from `cat` and
207
- handed to `gh` still carries a runtime value the isolation rule cannot verify,
208
- so read the id as its own plain command and write the printed value as a
209
- literal in the `gh api` call rather than a substitution or a variable:
142
+ ### Edit the posted comment
143
+
144
+ Edit the exact comment Step 6 posted, read back from the id it saved, rather than posting a second one. A shell variable assigned from `cat` still carries a runtime value the isolation rule cannot verify, so print the id and write it as a literal:
210
145
 
211
146
  ```bash
212
147
  cat .canon/tmp/pr/reply/reply-<number>.id
@@ -217,18 +152,9 @@ gh api -X PATCH "repos/{owner}/{repo}/issues/comments/<id printed above>" \
217
152
  -F body=@.canon/tmp/pr/reply/reply-<number>.md
218
153
  ```
219
154
 
220
- `--edit-last` was the first shape and it targets the wrong object here.
221
- It edits the last comment posted by the authenticated user, not the last
222
- comment this run posted, and every session here authenticates as the one
223
- account the operator also comments from. A comment the operator leaves on
224
- their own pull request during the minutes Step 7 spends waiting on CI becomes
225
- that last comment, so `--edit-last` would overwrite it with the reply and the
226
- confirmation, silently. Targeting the id Step 6 captured closes that whether
227
- or not anyone commented in between.
155
+ Never use `--edit-last`, which edits the last comment the authenticated account posted. The operator comments from that same account, so a comment they leave during the CI wait would be silently overwritten.
228
156
 
229
- If any check fails, skip the edit. Report the failing check so it can be fixed
230
- first. This is a resolution signal, not a formal approval, since the PR author
231
- cannot approve their own PR.
157
+ This is a resolution signal, not a formal approval, since the PR author cannot approve their own PR.
232
158
 
233
159
  ## Step 8: output
234
160
 
@@ -237,15 +163,7 @@ Addressed <N> findings on PR #<number>. Follow-up pushed.
237
163
  <Rebased onto origin/main. <N> files resolved by hand, <N> rebuilt by the check.>
238
164
  ```
239
165
 
240
- Omit the second line when the branch still merged. Name any finding left as a
241
- reply rather than a code change, with its one-line reason.
242
-
243
- A rebase-only run drops the first line rather than reporting zero findings
244
- addressed, and leads with the rebase instead:
245
-
246
- ```plaintext
247
- Rebased PR #<number> onto origin/main. <N> files resolved by hand, <N> rebuilt by the check.
248
- ```
166
+ Omit the second line when the branch still merged. Name any finding left as a reply rather than a code change, with its one-line reason. A rebase-only run reports the line `${CLAUDE_SKILL_DIR}/references/rebase-only.md` gives instead.
249
167
 
250
168
  Do not merge. Hand back to the reviewer for re-review, or to the orchestrator where no live reviewer answers.
251
169
 
@@ -0,0 +1,34 @@
1
+ ---
2
+ title: Rebase-only run
3
+ description: The reply body, closing confirmation, and output line review-address takes when its guard sent it straight to the rebase with no review findings to map
4
+ ---
5
+
6
+ # Rebase-only run
7
+
8
+ Read from Steps 6, 7, and 8 of `review-address` when the second guard sent the run straight to step 5 with no findings open. A run carrying findings skips this file.
9
+
10
+ ## Reply body
11
+
12
+ A rebase-only run has no findings to map, so it takes a different body rather than an empty list. Open it with `## Rebase`, since nothing on the pull request is being responded to and `## Review response` claims a review this run never read.
13
+
14
+ - State which half of the staleness test fired, being a branch that stopped merging or one `main` changed files under
15
+ - Name what landed on `main`, then the files resolved by hand and those the regen rebuilt
16
+ - Close with `šŸ¤– Addressed by Claude Code` on its own line, the same as a review response
17
+
18
+ The heading stays outside the `## Review` family, so the close-out's equality test on the first line never matches it.
19
+
20
+ ## Closing confirmation
21
+
22
+ Claiming findings were addressed on a pull request carrying none is false on a surface nothing else checks. Append this line at Step 7 in place of the findings confirmation, then re-run the scan:
23
+
24
+ ```bash
25
+ printf '\nāœ… Rebased onto origin/main, CI green. No review findings were open.\n' >> .canon/tmp/pr/reply/reply-<number>.md
26
+ ```
27
+
28
+ ## Output
29
+
30
+ Drop the findings line rather than reporting zero findings addressed, and lead with the rebase:
31
+
32
+ ```plaintext
33
+ Rebased PR #<number> onto origin/main. <N> files resolved by hand, <N> rebuilt by the check.
34
+ ```
@@ -7,7 +7,7 @@ metadata:
7
7
 
8
8
  # Review craft
9
9
 
10
- A review with no stated axes reads the changed lines for bugs and stops there. What breaks in a consumer the diff never opened, a doc the change made false a section away from its hunk, or a screenshot showing the opposite of what a ticked box claims all go unread. This skill carries the judgment: what to look for, in what order, and how sure to be before calling it a finding.
10
+ A review with no stated axes reads the changed lines for bugs and stops there. A broken consumer the diff never opened, a doc made false a section from its hunk, or a screenshot contradicting a ticked box all go unread. This skill carries what to look for, in what order, and how sure to be.
11
11
 
12
12
  The procedure that loaded this skill owns everything else: which files to read, the filter that decides what gets reported, the severity ladder, and where the report goes. Nothing here grades a finding or posts one.
13
13
 
@@ -27,21 +27,35 @@ A risky claim resting on assertion alone is where the review spends its reading.
27
27
 
28
28
  An axis whose condition the diff meets is not optional. When the security or the rendered output axis names a reference and its condition holds, read that reference before moving to the next axis, however clear the diff looks without it.
29
29
 
30
- 1. **Design and scope.** Does the change do one thing, is it more complex than the problem needs, and does it build what nobody asked for? State a design finding as a concrete cost, such as a second path nobody calls, a layer with one caller, or a flag no caller passes, never as a preference. Walk it in the order `Walk the design` below gives.
30
+ 1. **Design and scope.** Does the change do one thing, is it more complex than the problem needs, and does it build what nobody asked for? Walk it in the order `Walk the design` below gives.
31
+ - State a design finding as a concrete cost, such as a second path nobody calls, a layer with one caller, or a flag no caller passes, never as a preference
31
32
  2. **Correctness and edge cases.** The empty input, the boundary value, the refused call, the second run, the concurrent run, and the error path a caller actually meets.
32
- 3. **What breaks outside the diff.** List every consumer of a changed contract, whether a function signature, a file format, a flag, an output shape, or a heading another tool matches, and check the change against each one. Then list each behavior the diff removes or changes, such as a guard, a refusal, a default, or an output, and search every doc the diff touches, in full rather than at the hunk, for a sentence still promising the old behavior. File that sentence as a finding against the doc, quoting it and naming its section, since the doc is what goes wrong for the next reader.
33
+ 3. **What breaks outside the diff.** List every consumer of a changed contract and check the change against each one.
34
+ - A contract is a function signature, a file format, a flag, an output shape, or a heading another tool matches
35
+ - List each behavior the diff removes or changes, such as a guard, a refusal, a default, or an output
36
+ - Search every doc the diff touches, in full rather than at the hunk, for a sentence still promising the old behavior
37
+ - File that sentence against the doc, quoting it and naming its section, since the doc is what misleads the next reader
33
38
  4. **Tests.** Hand each test the change adds or edits to `canon:test-craft` and its final filter. Report it rather than proceeding silently when that skill does not resolve.
34
- 5. **Guard the bar.** A change can pass by lowering its own bar: a threshold moved, a test skipped, deleted, or emptied of assertions, an inline suppression, a path dropped from a lint or type run, a stub that throws or an empty catch where behavior was promised, or a new config exception. Each is a finding unless the diff says why, and a suppression whose stated reason holds is the author's call.
35
- 6. **Performance.** A query or a remote call inside a loop, a read with no bound on its size, and a list endpoint with no pagination. A claimed speedup needs a before and an after measured the same way and repeated past run-to-run noise. One run on each side is an anecdote, and a result inside the noise argues for reverting the added complexity.
39
+ 5. **Guard the bar.** A change can pass by lowering its own bar. Each lowering is a finding unless the diff says why, and a suppression whose stated reason holds is the author's call.
40
+ - A threshold moved, or a test skipped, deleted, or emptied of assertions
41
+ - An inline suppression, a path dropped from a lint or type run, or a new config exception
42
+ - A stub that throws or an empty catch where behavior was promised
43
+ 6. **Performance.** A query or a remote call inside a loop, a read with no bound on its size, and a list endpoint with no pagination.
44
+ - A claimed speedup needs a before and an after measured the same way and repeated past run-to-run noise
45
+ - One run on each side is an anecdote, and a result inside the noise argues for reverting the added complexity
36
46
 
37
47
  ### Axes a condition opens
38
48
 
39
49
  Read each of these when the diff reaches what it names.
40
50
 
41
- 7. **Security.** Read `${CLAUDE_SKILL_DIR}/references/security.md` when the diff runs a command, writes or deletes a file, handles input from outside the process, touches a secret, adds a dependency, or changes a default a consumer installs.
42
- 8. **Rendered output.** Read `${CLAUDE_SKILL_DIR}/references/ui.md` when the diff touches a file that paints, such as markup, a stylesheet, a component, a template, or a design token, or when the pull request carries an evidence comment. A finding read off a stylesheet diff says what the author changed, and only the screenshot says what a user sees, so the reference opens the images and checks whether any exist.
43
- 9. **Developer experience and operations.** Ports, hooks, scripts, config, and scaffold defaults a consumer installs. A new required step nobody documented, a default that fails on a clean machine, or a hook that slows every commit is a finding even when the code is correct.
44
- 10. **Executable prose.** A skill body, a rule, or a prompt is instructions a model runs. Read it the way you read code: a step that races another, a precondition it never states, a branch with no exit, and two instructions that contradict each other are bugs.
51
+ 7. **Security.** Read `${CLAUDE_SKILL_DIR}/references/security.md` when the diff runs a command, writes or deletes a file, takes outside input, touches a secret, adds a dependency, or changes a default.
52
+ 8. **Rendered output.** Read `${CLAUDE_SKILL_DIR}/references/ui.md` when the diff touches a file that paints, or when the pull request carries an evidence comment.
53
+ - A file that paints is markup, a stylesheet, a component, a template, or a design token
54
+ - A stylesheet diff says what the author changed and only the screenshot says what a user sees, so the reference opens the images and checks whether any exist
55
+ 9. **Developer experience and operations.** Ports, hooks, scripts, config, and scaffold defaults a consumer installs.
56
+ - A new required step nobody documented, a default that fails on a clean machine, or a hook that slows every commit is a finding even when the code is correct
57
+ 10. **Executable prose.** A skill body, a rule, or a prompt is instructions a model runs, so read it the way you read code.
58
+ - A step that races another, a precondition it never states, a branch with no exit, and two instructions that contradict each other are bugs
45
59
 
46
60
  ### Walk the design
47
61
 
@@ -50,7 +64,7 @@ Walk the design axis in this order, and skip a step the change gives nothing to
50
64
  1. Name the next change this code is likely to need, and count the files and units it would touch. A count that grows with each new case is the cost to report.
51
65
  2. State what each new unit hides from its callers. A unit that passes its arguments straight through to another hides nothing and is a layer with no work.
52
66
  3. Find each rule or constant the change states, and check that it lives in one place. The same rule in two places drifts the first time one copy changes.
53
- 4. Look for a parameter that switches what a function does, a chain of calls reaching through one object into another, and a read or write of global state. Each ties a caller to internals it should not know.
67
+ 4. Look for a parameter that switches what a function does, a call chain reaching through one object into another, and a read or write of global state. Each ties a caller to internals.
54
68
  5. Ask each changed file for its one reason to change. A file that two unrelated requests would both edit carries two concerns.
55
69
  6. List what the code reads without being handed it, such as the clock, the environment, the filesystem, or a random source. A hidden input is what makes the code hard to test and to reuse.
56
70
  7. Match each pattern or abstraction the change introduces to a problem the code has today. One built for a case nobody has asked for is speculative.
@@ -60,7 +74,7 @@ Walk the design axis in this order, and skip a step the change gives nothing to
60
74
  Three scope checks follow the walk:
61
75
 
62
76
  - When a change carries two concerns that could land as two changes, name the split. Size is no finding on its own, since one concern can run long.
63
- - On a refactor, count the concepts a reader must hold before and after. Complexity moved into a new file or function is moved, not reduced, so report it as such rather than as a design gain.
77
+ - On a refactor, count the concepts a reader must hold before and after. Complexity moved into a new file or function is moved, not reduced, so never report it as a design gain.
64
78
  - Before calling removed code dead, state why it existed. Read `git blame` and the commit that added it, since a guard nobody remembers is often still guarding something.
65
79
 
66
80
  ## Hold every finding to the evidence bar
@@ -91,6 +105,8 @@ Three scope checks follow the walk:
91
105
 
92
106
  ### Claims and axes
93
107
 
108
+ These flags fire on a claim accepted without its evidence.
109
+
94
110
  - You are calling code dead without having read the commit that added it.
95
111
  - A performance claim rests on a number you cannot trace to a repeated measurement.
96
112
  - An axis condition held and you moved past it without reading the reference it names.