@erclx/canon 5.45.0 → 5.46.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 (137) hide show
  1. package/claude/.claude-plugin/plugin.json +1 -1
  2. package/claude/skills/api-design/REQUIREMENT.md +15 -31
  3. package/claude/skills/auto-ship/REQUIREMENT.md +14 -25
  4. package/claude/skills/backlog-triage/REQUIREMENT.md +12 -23
  5. package/claude/skills/build-in-slices/REQUIREMENT.md +15 -25
  6. package/claude/skills/canon-cli/REQUIREMENT.md +15 -27
  7. package/claude/skills/canon-feedback/REQUIREMENT.md +10 -18
  8. package/claude/skills/canon-feedback-triage/REQUIREMENT.md +10 -15
  9. package/claude/skills/canvas-board/REQUIREMENT.md +14 -28
  10. package/claude/skills/ci-workflow/REQUIREMENT.md +12 -21
  11. package/claude/skills/code-craft/REQUIREMENT.md +14 -28
  12. package/claude/skills/codebase-layout/REQUIREMENT.md +14 -31
  13. package/claude/skills/context-fold/REQUIREMENT.md +15 -39
  14. package/claude/skills/context-fold/references/context.md +3 -3
  15. package/claude/skills/create-rule/REQUIREMENT.md +10 -24
  16. package/claude/skills/create-rule/SKILL.md +3 -0
  17. package/claude/skills/create-skill/REQUIREMENT.md +10 -21
  18. package/claude/skills/decision-escalate/REQUIREMENT.md +12 -24
  19. package/claude/skills/deploy-app/REQUIREMENT.md +12 -22
  20. package/claude/skills/deprecation-migration/REQUIREMENT.md +14 -42
  21. package/claude/skills/design-identity/REQUIREMENT.md +14 -20
  22. package/claude/skills/design-taste/REQUIREMENT.md +16 -57
  23. package/claude/skills/docs-sync/REQUIREMENT.md +14 -23
  24. package/claude/skills/document-health/REQUIREMENT.md +15 -29
  25. package/claude/skills/document-health/SKILL.md +2 -2
  26. package/claude/skills/document-repair/REQUIREMENT.md +32 -0
  27. package/claude/skills/document-repair/SKILL.md +76 -0
  28. package/claude/skills/document-repair/references/batches.md +44 -0
  29. package/claude/skills/draft-and-pick/REQUIREMENT.md +4 -3
  30. package/claude/skills/draft-doc/REQUIREMENT.md +4 -3
  31. package/claude/skills/draft-figure/REQUIREMENT.md +4 -3
  32. package/claude/skills/draft-identity/REQUIREMENT.md +4 -3
  33. package/claude/skills/draft-ready/REQUIREMENT.md +4 -3
  34. package/claude/skills/draft-screencast/REQUIREMENT.md +4 -3
  35. package/claude/skills/draft-slides/REQUIREMENT.md +4 -3
  36. package/claude/skills/draw-figure/REQUIREMENT.md +15 -39
  37. package/claude/skills/git-branch/REQUIREMENT.md +12 -26
  38. package/claude/skills/git-commit/REQUIREMENT.md +11 -15
  39. package/claude/skills/git-followup/REQUIREMENT.md +11 -22
  40. package/claude/skills/git-issue/REQUIREMENT.md +9 -15
  41. package/claude/skills/git-pr/REQUIREMENT.md +13 -32
  42. package/claude/skills/git-pr/SKILL.md +10 -2
  43. package/claude/skills/git-pr/references/closing-issues.md +47 -0
  44. package/claude/skills/git-pr/references/pr.md +4 -0
  45. package/claude/skills/git-ship/REQUIREMENT.md +13 -26
  46. package/claude/skills/git-split/REQUIREMENT.md +10 -17
  47. package/claude/skills/git-stage/REQUIREMENT.md +12 -18
  48. package/claude/skills/git-worktree/REQUIREMENT.md +15 -19
  49. package/claude/skills/make-deck/REQUIREMENT.md +13 -21
  50. package/claude/skills/markdown-craft/REQUIREMENT.md +9 -3
  51. package/claude/skills/plan-feature/REQUIREMENT.md +15 -24
  52. package/claude/skills/plan-groundwork/REQUIREMENT.md +12 -28
  53. package/claude/skills/plan-groundwork/SKILL.md +5 -2
  54. package/claude/skills/plan-groundwork/references/output.md +47 -1
  55. package/claude/skills/plan-intake/REQUIREMENT.md +11 -26
  56. package/claude/skills/plan-intake/references/intake.md +2 -2
  57. package/claude/skills/plan-intake-answer/REQUIREMENT.md +14 -29
  58. package/claude/skills/plan-intake-answer/SKILL.md +7 -1
  59. package/claude/skills/plan-ready/REQUIREMENT.md +17 -36
  60. package/claude/skills/pr-evidence/REQUIREMENT.md +11 -17
  61. package/claude/skills/read-frames/REQUIREMENT.md +3 -8
  62. package/claude/skills/record-screencast/REQUIREMENT.md +14 -17
  63. package/claude/skills/review-address/REQUIREMENT.md +14 -38
  64. package/claude/skills/review-craft/REQUIREMENT.md +14 -32
  65. package/claude/skills/review-pr/REQUIREMENT.md +15 -34
  66. package/claude/skills/review-ui/REQUIREMENT.md +14 -39
  67. package/claude/skills/role-orchestrator/REQUIREMENT.md +2 -2
  68. package/claude/skills/role-orchestrator/references/orchestrator-refill.md +5 -0
  69. package/claude/skills/role-orchestrator/references/orchestrator-review-dispatch.md +9 -0
  70. package/claude/skills/role-reviewer/REQUIREMENT.md +15 -65
  71. package/claude/skills/role-reviewer/SKILL.md +5 -1
  72. package/claude/skills/role-worker/REQUIREMENT.md +1 -1
  73. package/claude/skills/role-worker/SKILL.md +2 -0
  74. package/claude/skills/script-screencast/REQUIREMENT.md +10 -16
  75. package/claude/skills/search-craft/REQUIREMENT.md +12 -36
  76. package/claude/skills/search-craft/SKILL.md +1 -1
  77. package/claude/skills/search-craft/references/adopted.md +2 -2
  78. package/claude/skills/session-compact/REQUIREMENT.md +13 -23
  79. package/claude/skills/session-map/REQUIREMENT.md +13 -29
  80. package/claude/skills/session-relay/REQUIREMENT.md +14 -58
  81. package/claude/skills/session-relay/SKILL.md +6 -0
  82. package/claude/skills/session-resume/REQUIREMENT.md +13 -27
  83. package/claude/skills/session-worktree/REQUIREMENT.md +14 -43
  84. package/claude/skills/systematic-debugging/REQUIREMENT.md +13 -34
  85. package/claude/skills/target-check/REQUIREMENT.md +16 -23
  86. package/claude/skills/target-setup/REQUIREMENT.md +11 -34
  87. package/claude/skills/task-board/REQUIREMENT.md +13 -22
  88. package/claude/skills/task-board/SKILL.md +7 -0
  89. package/claude/skills/task-board/references/tasks.md +1 -1
  90. package/claude/skills/task-complete/REQUIREMENT.md +11 -24
  91. package/claude/skills/task-complete/references/archive.md +1 -0
  92. package/claude/skills/teach-workspace/REQUIREMENT.md +14 -45
  93. package/claude/skills/test-craft/REQUIREMENT.md +15 -46
  94. package/claude/skills/test-first/REQUIREMENT.md +14 -20
  95. package/claude/skills/ui-checklist/REQUIREMENT.md +14 -29
  96. package/claude/skills/ux-audit/REQUIREMENT.md +3 -7
  97. package/claude/skills/ux-measure/REQUIREMENT.md +14 -28
  98. package/claude/skills/video-craft/REQUIREMENT.md +14 -27
  99. package/claude/skills/write-doc/REQUIREMENT.md +14 -24
  100. package/claude/skills/write-human/REQUIREMENT.md +15 -27
  101. package/claude/skills/youtube-transcripts/REQUIREMENT.md +9 -15
  102. package/docs/agents/context-audit.md +19 -12
  103. package/docs/agents/markdown-audit.md +15 -10
  104. package/docs/target/projects.md +2 -0
  105. package/docs/workflow/skill-map.md +6 -5
  106. package/governance/renames.toml +0 -2
  107. package/governance/rules/claude/output.md +5 -1
  108. package/governance/rules/code/routing.md +5 -1
  109. package/governance/stacks/base.toml +0 -1
  110. package/package.json +1 -1
  111. package/src/claude/cases/workflow.ts +12 -0
  112. package/src/commands/context.ts +57 -3
  113. package/src/commands/labels.ts +83 -3
  114. package/src/commands/markdown.ts +188 -21
  115. package/src/commands/sessions.ts +36 -3
  116. package/src/commands/tasks.ts +180 -0
  117. package/src/commands/worktrees.ts +2 -0
  118. package/src/context/coverage.ts +210 -0
  119. package/src/context/gate.ts +12 -3
  120. package/src/gate/stages.ts +1 -1
  121. package/src/init/steps.ts +45 -0
  122. package/src/intake/items.ts +14 -0
  123. package/src/labels/closing.ts +46 -0
  124. package/src/markdown/gated.ts +250 -0
  125. package/src/markdown/scope.ts +115 -2
  126. package/src/migrate/rename.ts +6 -0
  127. package/src/sessions/claim.ts +7 -0
  128. package/src/sessions/live.ts +53 -6
  129. package/src/sessions/registry.ts +11 -0
  130. package/src/sessions/resolve.ts +32 -5
  131. package/src/tasks/closes.ts +136 -0
  132. package/src/tasks/record.ts +1 -1
  133. package/src/worktrees/reclaim.ts +16 -1
  134. package/tooling/base/configs/scripts/verify.ts +1 -1
  135. package/tooling/claude/seeds/.claude/hooks/board-validate.sh +1 -1
  136. package/tooling/claude/seeds/CLAUDE.md +2 -2
  137. package/governance/rules/canon/task-scope.md +0 -12
@@ -36,12 +36,27 @@ const DENSITY_SCOPE = [
36
36
  /^(?:README|CONTRIBUTING)\.md$/,
37
37
  ]
38
38
 
39
+ /**
40
+ * The roots `canon init` gates in a new project when each passes at init time:
41
+ * every density surface a target authors itself, leaving out the toolkit's own
42
+ * `claude/skills/` and `tooling/` trees.
43
+ */
44
+ export const GATED_SCOPE_ROOTS: readonly string[] = [
45
+ 'canon/context/',
46
+ 'docs/',
47
+ '.claude/skills/',
48
+ 'wiki/',
49
+ 'README.md',
50
+ 'CONTRIBUTING.md',
51
+ ]
52
+
39
53
  /**
40
54
  * The path prefixes whose density findings fail a run, each added by the
41
55
  * rewrite batch that brought its folders to zero.
42
56
  *
43
57
  * It describes this repository's rewrite progress and nothing about a target's
44
- * corpus, which is why the audit reads it only inside a canon checkout.
58
+ * corpus, which is why the audit reads it only inside a canon checkout. A
59
+ * target keeps its own list in the file `src/markdown/gated.ts` reads.
45
60
  */
46
61
  export const GATED_PATHS: readonly string[] = [
47
62
  'canon/context/surfaces/',
@@ -50,8 +65,10 @@ export const GATED_PATHS: readonly string[] = [
50
65
  'canon/context/features/',
51
66
  'canon/context/context-model.md',
52
67
  'canon/context/index.md',
68
+ 'claude/skills/api-design/REQUIREMENT.md',
53
69
  'claude/skills/api-design/SKILL.md',
54
70
  'claude/skills/api-design/references/adopted.md',
71
+ 'claude/skills/auto-ship/REQUIREMENT.md',
55
72
  'claude/skills/auto-ship/SKILL.md',
56
73
  'claude/skills/auto-ship/references/draft-mark.md',
57
74
  'claude/skills/auto-ship/references/failure-recovery.md',
@@ -60,33 +77,45 @@ export const GATED_PATHS: readonly string[] = [
60
77
  'claude/skills/auto-ship/references/ui-checklist.md',
61
78
  'claude/skills/auto-ship/references/verb-absent.md',
62
79
  'claude/skills/auto-ship/references/worktree-name.md',
80
+ 'claude/skills/backlog-triage/REQUIREMENT.md',
63
81
  'claude/skills/backlog-triage/SKILL.md',
64
82
  'claude/skills/backlog-triage/references/apply.md',
83
+ 'claude/skills/build-in-slices/REQUIREMENT.md',
65
84
  'claude/skills/build-in-slices/SKILL.md',
66
85
  'claude/skills/build-in-slices/references/adopted.md',
86
+ 'claude/skills/canon-cli/REQUIREMENT.md',
67
87
  'claude/skills/canon-cli/SKILL.md',
88
+ 'claude/skills/canon-feedback-triage/REQUIREMENT.md',
68
89
  'claude/skills/canon-feedback-triage/SKILL.md',
90
+ 'claude/skills/canon-feedback/REQUIREMENT.md',
69
91
  'claude/skills/canon-feedback/SKILL.md',
70
92
  'claude/skills/canon-feedback/references/template.md',
93
+ 'claude/skills/canvas-board/REQUIREMENT.md',
71
94
  'claude/skills/canvas-board/SKILL.md',
72
95
  'claude/skills/canvas-board/references/canvas.md',
73
96
  'claude/skills/canvas-board/references/design.md',
97
+ 'claude/skills/ci-workflow/REQUIREMENT.md',
74
98
  'claude/skills/ci-workflow/SKILL.md',
75
99
  'claude/skills/ci-workflow/references/workflows.md',
100
+ 'claude/skills/code-craft/REQUIREMENT.md',
76
101
  'claude/skills/code-craft/SKILL.md',
77
102
  'claude/skills/code-craft/references/adopted.md',
103
+ 'claude/skills/codebase-layout/REQUIREMENT.md',
78
104
  'claude/skills/codebase-layout/SKILL.md',
79
105
  'claude/skills/codebase-layout/references/adopted.md',
80
106
  'claude/skills/codebase-layout/references/frontend.md',
81
107
  'claude/skills/codebase-layout/references/tests.md',
108
+ 'claude/skills/context-fold/REQUIREMENT.md',
82
109
  'claude/skills/context-fold/SKILL.md',
83
110
  'claude/skills/context-fold/references/classify.md',
84
111
  'claude/skills/context-fold/references/completion-report.md',
85
112
  'claude/skills/context-fold/references/context-refresh.md',
86
113
  'claude/skills/context-fold/references/context.md',
87
114
  'claude/skills/context-fold/references/unusable-baseline.md',
115
+ 'claude/skills/create-rule/REQUIREMENT.md',
88
116
  'claude/skills/create-rule/SKILL.md',
89
117
  'claude/skills/create-rule/references/rule.md',
118
+ 'claude/skills/create-skill/REQUIREMENT.md',
90
119
  'claude/skills/create-skill/SKILL.md',
91
120
  'claude/skills/create-skill/references/skill-disclosure.md',
92
121
  'claude/skills/create-skill/references/skill-frontmatter.md',
@@ -95,12 +124,16 @@ export const GATED_PATHS: readonly string[] = [
95
124
  'claude/skills/create-skill/references/skill-reference.md',
96
125
  'claude/skills/create-skill/references/skill-requirement.md',
97
126
  'claude/skills/create-skill/references/skill.md',
127
+ 'claude/skills/decision-escalate/REQUIREMENT.md',
98
128
  'claude/skills/decision-escalate/SKILL.md',
129
+ 'claude/skills/deploy-app/REQUIREMENT.md',
99
130
  'claude/skills/deploy-app/SKILL.md',
100
131
  'claude/skills/deploy-app/references/cloudflare.md',
101
132
  'claude/skills/deploy-app/references/vercel.md',
133
+ 'claude/skills/deprecation-migration/REQUIREMENT.md',
102
134
  'claude/skills/deprecation-migration/SKILL.md',
103
135
  'claude/skills/deprecation-migration/references/adopted.md',
136
+ 'claude/skills/design-taste/REQUIREMENT.md',
104
137
  'claude/skills/design-taste/SKILL.md',
105
138
  'claude/skills/design-taste/references/adopted.md',
106
139
  'claude/skills/design-taste/references/craft.md',
@@ -109,14 +142,27 @@ export const GATED_PATHS: readonly string[] = [
109
142
  'claude/skills/design-taste/references/systems.md',
110
143
  'claude/skills/design-taste/references/tells.md',
111
144
  'claude/skills/design-taste/references/vocabulary.md',
145
+ 'claude/skills/docs-sync/REQUIREMENT.md',
112
146
  'claude/skills/docs-sync/SKILL.md',
113
147
  'claude/skills/docs-sync/references/docs.md',
114
148
  'claude/skills/docs-sync/references/readme.md',
149
+ 'claude/skills/document-health/REQUIREMENT.md',
115
150
  'claude/skills/document-health/SKILL.md',
116
151
  'claude/skills/document-health/references/axes.md',
152
+ 'claude/skills/document-repair/REQUIREMENT.md',
153
+ 'claude/skills/document-repair/SKILL.md',
154
+ 'claude/skills/document-repair/references/batches.md',
155
+ 'claude/skills/draft-and-pick/REQUIREMENT.md',
156
+ 'claude/skills/draft-doc/REQUIREMENT.md',
157
+ 'claude/skills/draft-figure/REQUIREMENT.md',
158
+ 'claude/skills/draft-identity/REQUIREMENT.md',
159
+ 'claude/skills/draft-ready/REQUIREMENT.md',
160
+ 'claude/skills/draft-screencast/REQUIREMENT.md',
161
+ 'claude/skills/draft-slides/REQUIREMENT.md',
117
162
  'claude/skills/pick-by-eye/REQUIREMENT.md',
118
163
  'claude/skills/pick-by-eye/SKILL.md',
119
164
  'claude/skills/pick-by-eye/references/live-arms.md',
165
+ 'claude/skills/write-doc/REQUIREMENT.md',
120
166
  'claude/skills/write-doc/SKILL.md',
121
167
  'claude/skills/write-doc/references/context.md',
122
168
  'claude/skills/write-doc/references/docs.md',
@@ -129,76 +175,102 @@ export const GATED_PATHS: readonly string[] = [
129
175
  'claude/skills/write-doc/references/requirements.md',
130
176
  'claude/skills/write-doc/references/wiki-kind.md',
131
177
  'claude/skills/write-doc/references/wiki.md',
178
+ 'claude/skills/draw-figure/REQUIREMENT.md',
132
179
  'claude/skills/draw-figure/SKILL.md',
133
180
  'claude/skills/draw-figure/references/architecture-set.md',
134
181
  'claude/skills/draw-figure/references/figures.md',
135
182
  'claude/skills/draw-figure/references/hand-drawn.md',
136
183
  'claude/skills/draw-figure/references/mermaid-path.md',
137
184
  'claude/skills/draw-figure/references/mermaid.md',
185
+ 'claude/skills/design-identity/REQUIREMENT.md',
138
186
  'claude/skills/design-identity/SKILL.md',
139
187
  'claude/skills/design-identity/references/card-route.md',
188
+ 'claude/skills/plan-ready/REQUIREMENT.md',
140
189
  'claude/skills/plan-ready/SKILL.md',
141
190
  'claude/skills/plan-ready/references/assembly.md',
142
191
  'claude/skills/plan-ready/references/ready.md',
192
+ 'claude/skills/script-screencast/REQUIREMENT.md',
143
193
  'claude/skills/script-screencast/SKILL.md',
144
194
  'claude/skills/script-screencast/references/beats-template.md',
195
+ 'claude/skills/make-deck/REQUIREMENT.md',
145
196
  'claude/skills/make-deck/SKILL.md',
146
197
  'claude/skills/make-deck/references/deck.md',
198
+ 'claude/skills/git-branch/REQUIREMENT.md',
147
199
  'claude/skills/git-branch/SKILL.md',
148
200
  'claude/skills/git-branch/references/branch.md',
149
201
  'claude/skills/git-branch/references/slug.md',
202
+ 'claude/skills/git-commit/REQUIREMENT.md',
150
203
  'claude/skills/git-commit/SKILL.md',
151
204
  'claude/skills/git-commit/references/commit.md',
152
205
  'claude/skills/git-commit/references/versioning.md',
206
+ 'claude/skills/git-followup/REQUIREMENT.md',
153
207
  'claude/skills/git-followup/SKILL.md',
208
+ 'claude/skills/git-issue/REQUIREMENT.md',
154
209
  'claude/skills/git-issue/SKILL.md',
155
210
  'claude/skills/git-issue/references/issue.md',
211
+ 'claude/skills/git-pr/REQUIREMENT.md',
156
212
  'claude/skills/git-pr/SKILL.md',
157
213
  'claude/skills/git-pr/references/final-command.md',
158
214
  'claude/skills/git-pr/references/labels.md',
159
215
  'claude/skills/git-pr/references/pr.md',
160
216
  'claude/skills/git-pr/references/publish.md',
161
217
  'claude/skills/git-pr/references/task-number.md',
218
+ 'claude/skills/git-ship/REQUIREMENT.md',
162
219
  'claude/skills/git-ship/SKILL.md',
163
220
  'claude/skills/git-ship/references/ci-watch.md',
221
+ 'claude/skills/git-split/REQUIREMENT.md',
164
222
  'claude/skills/git-split/SKILL.md',
165
223
  'claude/skills/git-split/references/independent.md',
166
224
  'claude/skills/git-split/references/stacked.md',
225
+ 'claude/skills/git-stage/REQUIREMENT.md',
167
226
  'claude/skills/git-stage/SKILL.md',
227
+ 'claude/skills/git-worktree/REQUIREMENT.md',
168
228
  'claude/skills/git-worktree/SKILL.md',
169
229
  'claude/skills/git-worktree/references/cleanup.md',
230
+ 'claude/skills/markdown-craft/REQUIREMENT.md',
170
231
  'claude/skills/markdown-craft/SKILL.md',
171
232
  'claude/skills/markdown-craft/references/markdown.md',
233
+ 'claude/skills/plan-feature/REQUIREMENT.md',
172
234
  'claude/skills/plan-feature/SKILL.md',
173
235
  'claude/skills/plan-feature/references/batches.md',
174
236
  'claude/skills/plan-feature/references/plan-lifecycle.md',
175
237
  'claude/skills/plan-feature/references/plan.md',
238
+ 'claude/skills/plan-groundwork/REQUIREMENT.md',
176
239
  'claude/skills/plan-groundwork/SKILL.md',
177
240
  'claude/skills/plan-groundwork/references/groundwork-spikes.md',
178
241
  'claude/skills/plan-groundwork/references/groundwork.md',
179
242
  'claude/skills/plan-groundwork/references/output.md',
243
+ 'claude/skills/plan-intake-answer/REQUIREMENT.md',
180
244
  'claude/skills/plan-intake-answer/SKILL.md',
245
+ 'claude/skills/plan-intake/REQUIREMENT.md',
181
246
  'claude/skills/plan-intake/SKILL.md',
182
247
  'claude/skills/plan-intake/references/intake.md',
248
+ 'claude/skills/pr-evidence/REQUIREMENT.md',
183
249
  'claude/skills/pr-evidence/SKILL.md',
184
250
  'claude/skills/pr-evidence/references/evidence.md',
251
+ 'claude/skills/read-frames/REQUIREMENT.md',
185
252
  'claude/skills/read-frames/SKILL.md',
253
+ 'claude/skills/record-screencast/REQUIREMENT.md',
186
254
  'claude/skills/record-screencast/SKILL.md',
255
+ 'claude/skills/review-address/REQUIREMENT.md',
187
256
  'claude/skills/review-address/SKILL.md',
188
257
  'claude/skills/review-address/references/post-review-findings.md',
189
258
  'claude/skills/review-address/references/rebase-conflicts.md',
190
259
  'claude/skills/review-address/references/rebase-only.md',
191
260
  'claude/skills/review-address/references/rest-reads.md',
261
+ 'claude/skills/review-craft/REQUIREMENT.md',
192
262
  'claude/skills/review-craft/SKILL.md',
193
263
  'claude/skills/review-craft/references/adopted.md',
194
264
  'claude/skills/review-craft/references/security.md',
195
265
  'claude/skills/review-craft/references/ui.md',
266
+ 'claude/skills/review-pr/REQUIREMENT.md',
196
267
  'claude/skills/review-pr/SKILL.md',
197
268
  'claude/skills/review-pr/references/body-variants.md',
198
269
  'claude/skills/review-pr/references/close-out.md',
199
270
  'claude/skills/review-pr/references/key-changes.md',
200
271
  'claude/skills/review-pr/references/post.md',
201
272
  'claude/skills/review-pr/references/scope.md',
273
+ 'claude/skills/review-ui/REQUIREMENT.md',
202
274
  'claude/skills/review-ui/SKILL.md',
203
275
  'claude/skills/review-ui/references/close-out.md',
204
276
  'claude/skills/review-ui/references/driving.md',
@@ -225,38 +297,51 @@ export const GATED_PATHS: readonly string[] = [
225
297
  'claude/skills/role-orchestrator/references/orchestrator-watch.md',
226
298
  'claude/skills/role-planner/REQUIREMENT.md',
227
299
  'claude/skills/role-planner/SKILL.md',
300
+ 'claude/skills/role-reviewer/REQUIREMENT.md',
228
301
  'claude/skills/role-reviewer/SKILL.md',
229
302
  'claude/skills/role-worker/REQUIREMENT.md',
230
303
  'claude/skills/role-worker/SKILL.md',
304
+ 'claude/skills/search-craft/REQUIREMENT.md',
231
305
  'claude/skills/search-craft/SKILL.md',
232
306
  'claude/skills/search-craft/references/adopted.md',
307
+ 'claude/skills/session-compact/REQUIREMENT.md',
233
308
  'claude/skills/session-compact/SKILL.md',
234
309
  'claude/skills/session-compact/references/handoff-note.md',
310
+ 'claude/skills/session-map/REQUIREMENT.md',
235
311
  'claude/skills/session-map/SKILL.md',
236
312
  'claude/skills/session-map/references/session.md',
313
+ 'claude/skills/session-relay/REQUIREMENT.md',
237
314
  'claude/skills/session-relay/SKILL.md',
315
+ 'claude/skills/session-resume/REQUIREMENT.md',
238
316
  'claude/skills/session-resume/SKILL.md',
317
+ 'claude/skills/session-worktree/REQUIREMENT.md',
239
318
  'claude/skills/session-worktree/SKILL.md',
240
319
  'claude/skills/session-worktree/references/install-command.md',
241
320
  'claude/skills/session-worktree/references/main-root-writes.md',
321
+ 'claude/skills/systematic-debugging/REQUIREMENT.md',
242
322
  'claude/skills/systematic-debugging/SKILL.md',
243
323
  'claude/skills/systematic-debugging/references/adopted.md',
324
+ 'claude/skills/target-check/REQUIREMENT.md',
244
325
  'claude/skills/target-check/SKILL.md',
245
326
  'claude/skills/target-check/references/domains.md',
327
+ 'claude/skills/target-setup/REQUIREMENT.md',
246
328
  'claude/skills/target-setup/SKILL.md',
247
329
  'claude/skills/target-setup/references/detect.md',
248
330
  'claude/skills/target-setup/references/indexes.md',
249
331
  'claude/skills/target-setup/references/verify.md',
332
+ 'claude/skills/task-board/REQUIREMENT.md',
250
333
  'claude/skills/task-board/SKILL.md',
251
334
  'claude/skills/task-board/references/board.md',
252
335
  'claude/skills/task-board/references/create-report.md',
253
336
  'claude/skills/task-board/references/decline.md',
254
337
  'claude/skills/task-board/references/tasks-decline.md',
255
338
  'claude/skills/task-board/references/tasks.md',
339
+ 'claude/skills/task-complete/REQUIREMENT.md',
256
340
  'claude/skills/task-complete/SKILL.md',
257
341
  'claude/skills/task-complete/references/archive.md',
258
342
  'claude/skills/task-complete/references/receipt-sweep.md',
259
343
  'claude/skills/task-complete/references/unusable-baseline.md',
344
+ 'claude/skills/teach-workspace/REQUIREMENT.md',
260
345
  'claude/skills/teach-workspace/SKILL.md',
261
346
  'claude/skills/teach-workspace/references/glossary.md',
262
347
  'claude/skills/teach-workspace/references/lesson-build.md',
@@ -266,23 +351,43 @@ export const GATED_PATHS: readonly string[] = [
266
351
  'claude/skills/teach-workspace/references/promotion.md',
267
352
  'claude/skills/teach-workspace/references/revisit.md',
268
353
  'claude/skills/teach-workspace/references/teach.md',
354
+ 'claude/skills/test-craft/REQUIREMENT.md',
269
355
  'claude/skills/test-craft/SKILL.md',
270
356
  'claude/skills/test-craft/references/adopted.md',
271
357
  'claude/skills/test-craft/references/component.md',
272
358
  'claude/skills/test-craft/references/e2e.md',
273
359
  'claude/skills/test-craft/references/unit.md',
360
+ 'claude/skills/test-first/REQUIREMENT.md',
274
361
  'claude/skills/test-first/SKILL.md',
275
362
  'claude/skills/test-first/references/adopted.md',
363
+ 'claude/skills/ui-checklist/REQUIREMENT.md',
276
364
  'claude/skills/ui-checklist/SKILL.md',
365
+ 'claude/skills/ux-audit/REQUIREMENT.md',
277
366
  'claude/skills/ux-audit/SKILL.md',
367
+ 'claude/skills/ux-measure/REQUIREMENT.md',
278
368
  'claude/skills/ux-measure/SKILL.md',
369
+ 'claude/skills/video-craft/REQUIREMENT.md',
279
370
  'claude/skills/video-craft/SKILL.md',
280
371
  'claude/skills/video-craft/references/adopted.md',
372
+ 'claude/skills/write-human/REQUIREMENT.md',
281
373
  'claude/skills/write-human/SKILL.md',
282
374
  'claude/skills/write-human/references/adopted.md',
283
375
  'claude/skills/write-human/references/density.md',
284
376
  'claude/skills/write-human/references/machine-tells.md',
377
+ 'claude/skills/youtube-transcripts/REQUIREMENT.md',
285
378
  'claude/skills/youtube-transcripts/SKILL.md',
379
+ '.claude/skills/internal-canvas/REQUIREMENT.md',
380
+ '.claude/skills/internal-claude/REQUIREMENT.md',
381
+ '.claude/skills/internal-docs/REQUIREMENT.md',
382
+ '.claude/skills/internal-governance/REQUIREMENT.md',
383
+ '.claude/skills/internal-rule-audit/REQUIREMENT.md',
384
+ '.claude/skills/internal-sandbox-check/REQUIREMENT.md',
385
+ '.claude/skills/internal-scripts/REQUIREMENT.md',
386
+ '.claude/skills/internal-shipped-reference/REQUIREMENT.md',
387
+ '.claude/skills/internal-teach/REQUIREMENT.md',
388
+ '.claude/skills/internal-tooling/REQUIREMENT.md',
389
+ '.claude/skills/internal-upstream-digest/REQUIREMENT.md',
390
+ '.claude/skills/internal-web/REQUIREMENT.md',
286
391
  '.claude/skills/internal-',
287
392
  'docs/',
288
393
  'tooling/',
@@ -307,15 +412,23 @@ export function inDensityScope(rel: string): boolean {
307
412
  return DENSITY_SCOPE.some((pattern) => pattern.test(rel))
308
413
  }
309
414
 
310
- /** Whether a density finding of this kind on this path fails the run. */
415
+ /**
416
+ * Whether a density finding of this kind on this path fails the run.
417
+ *
418
+ * `alwaysGated` is off for a target's list, since no stage of a target's ever
419
+ * failed a push on a bullet run, and gating one unlisted would fail an older
420
+ * project's push on prose it has not touched since the limit landed.
421
+ */
311
422
  export function densityGates(
312
423
  rel: string,
313
424
  kind: DensityKind,
314
425
  gated: readonly string[] = GATED_PATHS,
426
+ alwaysGated = true,
315
427
  ): boolean {
316
428
  if (!inDensityScope(rel)) return false
317
429
  if (REQUIREMENT_SCOPE.test(rel)) return gated.includes(rel)
318
430
  if (
431
+ alwaysGated &&
319
432
  ALWAYS_GATED.includes(kind) &&
320
433
  BULLET_RUN_SCOPE.some((pattern) => pattern.test(rel))
321
434
  )
@@ -12,6 +12,12 @@
12
12
  * sweeps sharing a module constant would have to agree on a single map, and
13
13
  * the second rename this repository needed shares nothing with the first
14
14
  * except the scanning discipline above.
15
+ *
16
+ * Two misses survive a clean run. The sweep reads spelled text only, so a path
17
+ * assembled as `join('.claude', ...)` is never joined back into a token and
18
+ * keeps its old spelling. And rewriting a test's fixtures can collapse a
19
+ * fallback test into a copy of its neighbor, which keeps passing while it
20
+ * covers nothing, so read the rewritten fixtures rather than trusting the run.
15
21
  */
16
22
 
17
23
  /**
@@ -19,6 +19,12 @@ export interface ClaimReport {
19
19
  readonly refs: readonly string[]
20
20
  /** False when the session roster could not be read, so `claimed` covers the readings around it alone and cannot be trusted as a clean "unclaimed". */
21
21
  readonly sessionsReadable: boolean
22
+ /**
23
+ * Foreign-namespace records whose socket is gone. They read dead, so a branch
24
+ * one of them holds can read unclaimed, which a caller with a count above
25
+ * zero should treat as unverified.
26
+ */
27
+ readonly foreignDead: number
22
28
  /** False when the ref read failed, which is the same false clean under a different reading. */
23
29
  readonly refsReadable: boolean
24
30
  }
@@ -80,6 +86,7 @@ export async function checkClaim(
80
86
  sessions,
81
87
  refs: refs.refs,
82
88
  sessionsReadable: report.kind === 'resolved',
89
+ foreignDead: report.kind === 'resolved' ? report.foreignDead : 0,
83
90
  refsReadable: refs.readable,
84
91
  }
85
92
  }
@@ -1,4 +1,4 @@
1
- import { readFileSync } from 'node:fs'
1
+ import { existsSync, readFileSync, readlinkSync } from 'node:fs'
2
2
  import type { SessionRecord } from '@/sessions/registry'
3
3
 
4
4
  /**
@@ -7,13 +7,19 @@ import type { SessionRecord } from '@/sessions/registry'
7
7
  * `confirmed` means the running process was matched against the start time the
8
8
  * record stamped, so the pid belongs to the session that wrote the file.
9
9
  * `unverified` means the pid answers a signal probe and nothing more, which
10
- * cannot separate the original session from whatever inherited its pid.
10
+ * cannot separate the original session from whatever inherited its pid, or,
11
+ * for a `foreign` row, that its messaging socket still exists.
11
12
  */
12
13
  export type Confidence = 'confirmed' | 'unverified'
13
14
 
14
15
  export interface Liveness {
15
16
  readonly alive: boolean
16
17
  readonly confidence: Confidence
18
+ /**
19
+ * Set only when the record belongs to another pid namespace, so the pid was
20
+ * never probed. Absent rather than false on every other path.
21
+ */
22
+ readonly foreign?: true
17
23
  }
18
24
 
19
25
  export interface LivenessProbes {
@@ -21,6 +27,14 @@ export interface LivenessProbes {
21
27
  readonly procStartOf: (pid: number) => string | null
22
28
  /** Whether the pid answers at all, ignoring which process holds it. */
23
29
  readonly responds: (pid: number) => boolean
30
+ /**
31
+ * The reader's own pid namespace in `pid:[inode]` form, or null where it
32
+ * cannot be read. Optional so a caller with no use for the foreign branch,
33
+ * such as the gate's lock, states nothing and takes the pid path.
34
+ */
35
+ readonly ownDomain?: () => string | null
36
+ /** Whether the messaging socket a foreign record names still exists. */
37
+ readonly socketExists?: (path: string) => boolean
24
38
  }
25
39
 
26
40
  /**
@@ -51,7 +65,21 @@ function responds(pid: number): boolean {
51
65
  }
52
66
  }
53
67
 
54
- export const SYSTEM_PROBES: LivenessProbes = { procStartOf, responds }
68
+ /** The link target reads `pid:[inode]`, which a record's `pidDomain` ends with. */
69
+ function ownDomain(): string | null {
70
+ try {
71
+ return readlinkSync('/proc/self/ns/pid')
72
+ } catch {
73
+ return null
74
+ }
75
+ }
76
+
77
+ export const SYSTEM_PROBES: LivenessProbes = {
78
+ procStartOf,
79
+ responds,
80
+ ownDomain,
81
+ socketExists: existsSync,
82
+ }
55
83
 
56
84
  /**
57
85
  * Decides whether a record describes a session that is still running.
@@ -62,13 +90,32 @@ export const SYSTEM_PROBES: LivenessProbes = { procStartOf, responds }
62
90
  * probe alone stands, and every surviving row is marked so a caller never reads
63
91
  * a recycled pid as a confirmed identity.
64
92
  *
65
- * It reads two fields and asks for no more, so a record that is not a session,
66
- * such as the gate's machine lock, carries the same proof.
93
+ * A record from another pid namespace is judged first, on its messaging
94
+ * socket, because its pid names nothing in this namespace and either probe
95
+ * would read an unrelated process or none. That answer is always `unverified`,
96
+ * since a crashed session leaves its socket behind.
97
+ *
98
+ * The pid and start time are the only fields the rest needs, so a record that
99
+ * is not a session, such as the gate's machine lock, carries the same proof and
100
+ * takes the pid path for want of a `pidDomain`.
67
101
  */
68
102
  export function liveness(
69
- record: Pick<SessionRecord, 'pid' | 'procStart'>,
103
+ record: Pick<SessionRecord, 'pid' | 'procStart'> &
104
+ Partial<Pick<SessionRecord, 'pidDomain' | 'messagingSocketPath'>>,
70
105
  probes: LivenessProbes = SYSTEM_PROBES,
71
106
  ): Liveness {
107
+ const own = probes.ownDomain?.() ?? null
108
+ if (
109
+ own !== null &&
110
+ record.pidDomain !== undefined &&
111
+ !record.pidDomain.endsWith(own)
112
+ ) {
113
+ const socket = record.messagingSocketPath
114
+ const alive =
115
+ socket !== undefined && (probes.socketExists?.(socket) ?? false)
116
+ return { alive, confidence: 'unverified', foreign: true }
117
+ }
118
+
72
119
  const started = record.procStart
73
120
 
74
121
  if (started !== undefined && started.length > 0) {
@@ -45,6 +45,17 @@ export interface SessionRecord {
45
45
  * been handed to something else.
46
46
  */
47
47
  readonly procStart: string | undefined
48
+ /**
49
+ * The pid namespace the client stamped, ending in the `pid:[inode]` form that
50
+ * `/proc/self/ns/pid` reads as. A reader in another namespace cannot see the
51
+ * record's pid, so this is what tells a foreign row from a dead one.
52
+ */
53
+ readonly pidDomain: string | undefined
54
+ /**
55
+ * The socket the session listens on for messages. It is the only evidence of
56
+ * life a foreign-namespace reader can reach, since the pid is out of sight.
57
+ */
58
+ readonly messagingSocketPath: string | undefined
48
59
  }
49
60
 
50
61
  /**
@@ -22,6 +22,12 @@ export interface ResolvedSession {
22
22
  readonly cwd: string
23
23
  readonly kind: string
24
24
  readonly status: string
25
+ /**
26
+ * What decided the row was live. `socket` means the record belongs to another
27
+ * pid namespace and only its messaging socket answered, so the row can be a
28
+ * crashed session's leftover and no start time backs it.
29
+ */
30
+ readonly via: 'pid' | 'socket'
25
31
  readonly startedAt: string | null
26
32
  /**
27
33
  * The stamp the record carries beside `status`, kept alongside the dwell it
@@ -64,6 +70,13 @@ export type SessionReport =
64
70
  * tells a caller whether the roster can be trusted as an identity.
65
71
  */
66
72
  readonly confidence: Confidence
73
+ /**
74
+ * Foreign-namespace records whose socket is gone. They read dead, but the
75
+ * reader could not check their pid, so an empty roster beside a count
76
+ * above zero is a roster that could not be checked rather than one that
77
+ * ended.
78
+ */
79
+ readonly foreignDead: number
67
80
  readonly sessions: readonly ResolvedSession[]
68
81
  }
69
82
 
@@ -167,6 +180,7 @@ function present(
167
180
  record: SessionRecord,
168
181
  located: Located,
169
182
  now: number,
183
+ via: ResolvedSession['via'],
170
184
  ): ResolvedSession {
171
185
  return {
172
186
  name: record.name,
@@ -175,6 +189,7 @@ function present(
175
189
  cwd: record.cwd,
176
190
  kind: record.kind ?? 'unknown',
177
191
  status: record.status ?? 'unknown',
192
+ via,
178
193
  startedAt:
179
194
  record.startedAt === undefined
180
195
  ? null
@@ -213,21 +228,33 @@ export async function resolveSessions(
213
228
 
214
229
  if (registry.kind === 'absent') return { kind: 'absent', dir: registry.dir }
215
230
 
216
- const live: SessionRecord[] = []
231
+ const live: { record: SessionRecord; via: ResolvedSession['via'] }[] = []
217
232
  let confidence: Confidence = 'confirmed'
233
+ let foreignDead = 0
218
234
 
219
235
  for (const record of registry.records) {
220
236
  const state = liveness(record, probes)
221
- if (!state.alive) continue
237
+ if (!state.alive) {
238
+ if (state.foreign) foreignDead += 1
239
+ continue
240
+ }
222
241
  if (state.confidence === 'unverified') confidence = 'unverified'
223
- live.push(record)
242
+ live.push({ record, via: state.foreign ? 'socket' : 'pid' })
224
243
  }
225
244
 
226
245
  const sessions = await Promise.all(
227
- live.map(async (record) => present(record, await find(record.cwd), now)),
246
+ live.map(async ({ record, via }) =>
247
+ present(record, await find(record.cwd), now, via),
248
+ ),
228
249
  )
229
250
 
230
- return { kind: 'resolved', dir: registry.dir, confidence, sessions }
251
+ return {
252
+ kind: 'resolved',
253
+ dir: registry.dir,
254
+ confidence,
255
+ foreignDead,
256
+ sessions,
257
+ }
231
258
  }
232
259
 
233
260
  /** The environment slice the caller's own identity is read from. */