@erclx/canon 5.31.0 → 5.33.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (413) hide show
  1. package/README.md +1 -1
  2. package/claude/.claude-plugin/plugin.json +1 -1
  3. package/claude/skills/api-design/references/adopted.md +1 -1
  4. package/claude/skills/auto-ship/REQUIREMENT.md +4 -16
  5. package/claude/skills/auto-ship/SKILL.md +13 -58
  6. package/claude/skills/auto-ship/references/draft-mark.md +2 -2
  7. package/claude/skills/auto-ship/references/failure-recovery.md +1 -5
  8. package/claude/skills/auto-ship/references/tier-failures.md +1 -1
  9. package/claude/skills/auto-ship/references/ui-checklist.md +2 -2
  10. package/claude/skills/auto-ship/references/verb-absent.md +3 -27
  11. package/claude/skills/auto-ship/references/worktree-name.md +1 -1
  12. package/claude/skills/backlog-triage/REQUIREMENT.md +2 -2
  13. package/claude/skills/backlog-triage/SKILL.md +2 -2
  14. package/claude/skills/canon-cli/REQUIREMENT.md +19 -18
  15. package/claude/skills/canon-cli/SKILL.md +75 -32
  16. package/claude/skills/canon-feedback/REQUIREMENT.md +1 -1
  17. package/claude/skills/canon-feedback/SKILL.md +11 -14
  18. package/claude/skills/canon-feedback-triage/REQUIREMENT.md +13 -14
  19. package/claude/skills/canon-feedback-triage/SKILL.md +49 -30
  20. package/claude/skills/{canvas → canvas-board}/REQUIREMENT.md +5 -6
  21. package/claude/skills/{canvas → canvas-board}/SKILL.md +7 -7
  22. package/{standards → claude/skills/canvas-board/references}/canvas.md +12 -1
  23. package/{standards → claude/skills/canvas-board/references}/design.md +13 -5
  24. package/claude/skills/ci-workflow/REQUIREMENT.md +0 -1
  25. package/claude/skills/context-fold/REQUIREMENT.md +28 -48
  26. package/claude/skills/context-fold/SKILL.md +26 -95
  27. package/claude/skills/context-fold/references/classify.md +7 -8
  28. package/claude/skills/context-fold/references/completion-report.md +4 -8
  29. package/claude/skills/context-fold/references/context-refresh.md +7 -17
  30. package/{standards → claude/skills/context-fold/references}/context.md +19 -10
  31. package/claude/skills/context-fold/references/unusable-baseline.md +4 -8
  32. package/claude/skills/create-rule/REQUIREMENT.md +0 -1
  33. package/claude/skills/create-rule/SKILL.md +2 -2
  34. package/{standards → claude/skills/create-rule/references}/rule.md +12 -5
  35. package/claude/skills/create-skill/REQUIREMENT.md +6 -4
  36. package/claude/skills/create-skill/SKILL.md +10 -9
  37. package/{standards → claude/skills/create-skill/references}/skill-paths.md +1 -0
  38. package/{standards → claude/skills/create-skill/references}/skill.md +18 -15
  39. package/claude/skills/decision-escalate/REQUIREMENT.md +1 -1
  40. package/claude/skills/decision-escalate/SKILL.md +1 -1
  41. package/claude/skills/design-taste/REQUIREMENT.md +3 -5
  42. package/claude/skills/design-taste/SKILL.md +2 -4
  43. package/claude/skills/design-taste/references/vocabulary.md +1 -1
  44. package/claude/skills/docs-sync/REQUIREMENT.md +3 -3
  45. package/claude/skills/docs-sync/SKILL.md +3 -3
  46. package/{standards → claude/skills/docs-sync/references}/docs.md +11 -0
  47. package/{standards → claude/skills/docs-sync/references}/readme.md +9 -2
  48. package/claude/skills/document-health/REQUIREMENT.md +2 -2
  49. package/claude/skills/document-health/SKILL.md +4 -5
  50. package/claude/skills/document-health/references/axes.md +4 -6
  51. package/claude/skills/draft-and-pick/REQUIREMENT.md +16 -14
  52. package/claude/skills/draft-and-pick/SKILL.md +40 -32
  53. package/claude/skills/draft-and-pick/references/live-arms.md +9 -9
  54. package/claude/skills/draft-doc/REQUIREMENT.md +5 -5
  55. package/claude/skills/draft-doc/SKILL.md +9 -10
  56. package/claude/skills/draft-doc/references/requirements.md +61 -0
  57. package/claude/skills/draft-doc/references/wiki-kind.md +53 -0
  58. package/claude/skills/draft-doc/references/wiki.md +50 -30
  59. package/claude/skills/draft-figure/REQUIREMENT.md +2 -2
  60. package/claude/skills/draft-figure/SKILL.md +5 -5
  61. package/claude/skills/draft-figure/references/architecture-set.md +4 -4
  62. package/claude/skills/draft-figure/references/hand-drawn.md +2 -2
  63. package/claude/skills/draft-figure/references/mermaid-path.md +55 -0
  64. package/claude/skills/draft-figure/references/mermaid.md +43 -34
  65. package/claude/skills/draft-identity/REQUIREMENT.md +3 -3
  66. package/claude/skills/draft-identity/SKILL.md +10 -8
  67. package/claude/skills/draft-ready/REQUIREMENT.md +1 -1
  68. package/claude/skills/draft-ready/SKILL.md +7 -7
  69. package/claude/skills/draft-ready/references/assembly.md +1 -1
  70. package/{standards → claude/skills/draft-ready/references}/ready.md +13 -5
  71. package/claude/skills/git-branch/SKILL.md +1 -1
  72. package/{standards → claude/skills/git-branch/references}/branch.md +1 -1
  73. package/claude/skills/git-commit/SKILL.md +2 -2
  74. package/claude/skills/git-followup/REQUIREMENT.md +1 -1
  75. package/claude/skills/git-followup/SKILL.md +1 -1
  76. package/claude/skills/git-issue/SKILL.md +1 -1
  77. package/claude/skills/git-issue/references/issue.md +3 -3
  78. package/claude/skills/git-pr/SKILL.md +13 -13
  79. package/claude/skills/git-pr/references/evidence.md +2 -2
  80. package/claude/skills/git-pr/references/final-command.md +38 -14
  81. package/claude/skills/git-pr/references/labels.md +5 -1
  82. package/{standards → claude/skills/git-pr/references}/pr.md +19 -9
  83. package/{standards → claude/skills/git-pr/references}/publish.md +5 -3
  84. package/claude/skills/git-pr/references/task-number.md +1 -1
  85. package/claude/skills/git-ship/REQUIREMENT.md +0 -2
  86. package/claude/skills/git-ship/SKILL.md +5 -12
  87. package/claude/skills/git-split/SKILL.md +3 -3
  88. package/claude/skills/git-stage/SKILL.md +1 -1
  89. package/claude/skills/plan-feature/REQUIREMENT.md +1 -1
  90. package/claude/skills/plan-feature/SKILL.md +2 -6
  91. package/{standards → claude/skills/plan-feature/references}/plan.md +9 -10
  92. package/claude/skills/plan-groundwork/SKILL.md +5 -6
  93. package/{standards → claude/skills/plan-groundwork/references}/groundwork.md +17 -4
  94. package/claude/skills/plan-intake/SKILL.md +2 -3
  95. package/{standards → claude/skills/plan-intake/references}/intake.md +17 -2
  96. package/claude/skills/plan-intake-answer/REQUIREMENT.md +1 -1
  97. package/claude/skills/plan-intake-answer/SKILL.md +1 -1
  98. package/claude/skills/review-address/SKILL.md +2 -2
  99. package/claude/skills/review-address/references/post-review-findings.md +1 -1
  100. package/claude/skills/review-craft/REQUIREMENT.md +3 -3
  101. package/claude/skills/review-craft/SKILL.md +2 -2
  102. package/claude/skills/review-craft/references/ui.md +4 -4
  103. package/claude/skills/review-pr/REQUIREMENT.md +2 -2
  104. package/claude/skills/review-pr/SKILL.md +8 -10
  105. package/claude/skills/review-pr/references/body-variants.md +2 -2
  106. package/claude/skills/review-pr/references/key-changes.md +3 -3
  107. package/claude/skills/review-pr/references/post.md +4 -2
  108. package/claude/skills/review-ui/REQUIREMENT.md +1 -2
  109. package/claude/skills/review-ui/SKILL.md +2 -2
  110. package/claude/skills/review-ui/references/post.md +1 -1
  111. package/claude/skills/role-orchestrator/REQUIREMENT.md +3 -3
  112. package/claude/skills/role-orchestrator/SKILL.md +10 -10
  113. package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +3 -3
  114. package/claude/skills/role-orchestrator/references/orchestrator-handoff.md +9 -9
  115. package/claude/skills/role-orchestrator/references/orchestrator-launch.md +23 -1
  116. package/claude/skills/role-orchestrator/references/orchestrator-parked.md +2 -2
  117. package/claude/skills/role-orchestrator/references/orchestrator-refill.md +2 -5
  118. package/claude/skills/role-orchestrator/references/orchestrator-resume.md +4 -1
  119. package/claude/skills/role-planner/REQUIREMENT.md +2 -1
  120. package/claude/skills/role-planner/SKILL.md +15 -4
  121. package/claude/skills/role-reviewer/SKILL.md +2 -2
  122. package/claude/skills/role-worker/REQUIREMENT.md +1 -0
  123. package/claude/skills/role-worker/SKILL.md +11 -3
  124. package/claude/skills/session-compact/REQUIREMENT.md +1 -4
  125. package/claude/skills/session-compact/SKILL.md +3 -13
  126. package/claude/skills/session-compact/references/handoff-note.md +2 -2
  127. package/claude/skills/session-map/REQUIREMENT.md +1 -9
  128. package/claude/skills/session-map/SKILL.md +9 -17
  129. package/{standards → claude/skills/session-map/references}/session.md +17 -11
  130. package/claude/skills/session-relay/REQUIREMENT.md +1 -1
  131. package/claude/skills/session-resume/REQUIREMENT.md +6 -8
  132. package/claude/skills/session-resume/SKILL.md +3 -9
  133. package/claude/skills/session-worktree/SKILL.md +6 -6
  134. package/claude/skills/session-worktree/references/main-root-writes.md +2 -2
  135. package/claude/skills/systematic-debugging/REQUIREMENT.md +0 -1
  136. package/claude/skills/target-check/REQUIREMENT.md +3 -3
  137. package/claude/skills/target-check/SKILL.md +1 -1
  138. package/claude/skills/target-check/references/domains.md +1 -1
  139. package/claude/skills/target-setup/REQUIREMENT.md +4 -4
  140. package/claude/skills/target-setup/SKILL.md +3 -3
  141. package/claude/skills/target-setup/references/detect.md +2 -2
  142. package/claude/skills/task-board/REQUIREMENT.md +7 -12
  143. package/claude/skills/task-board/SKILL.md +9 -21
  144. package/{standards → claude/skills/task-board/references}/board.md +9 -0
  145. package/claude/skills/task-board/references/decline.md +1 -1
  146. package/{standards → claude/skills/task-board/references}/tasks.md +15 -10
  147. package/claude/skills/task-complete/REQUIREMENT.md +47 -0
  148. package/claude/skills/task-complete/SKILL.md +86 -0
  149. package/claude/skills/{task-board → task-complete}/references/archive.md +5 -5
  150. package/claude/skills/task-complete/references/receipt-sweep.md +32 -0
  151. package/claude/skills/task-complete/references/unusable-baseline.md +19 -0
  152. package/claude/skills/teach-workspace/REQUIREMENT.md +6 -2
  153. package/claude/skills/teach-workspace/SKILL.md +9 -5
  154. package/claude/skills/teach-workspace/references/lesson-craft.md +1 -1
  155. package/claude/skills/teach-workspace/references/promotion-fold.md +29 -0
  156. package/claude/skills/teach-workspace/references/promotion.md +3 -3
  157. package/claude/skills/teach-workspace/references/revisit.md +1 -1
  158. package/{standards → claude/skills/teach-workspace/references}/teach.md +17 -5
  159. package/claude/skills/ui-checklist/SKILL.md +1 -1
  160. package/claude/skills/ux-audit/REQUIREMENT.md +2 -2
  161. package/claude/skills/ux-audit/SKILL.md +3 -4
  162. package/claude/skills/ux-measure/SKILL.md +1 -1
  163. package/claude/skills/write-human/REQUIREMENT.md +0 -1
  164. package/claude/skills/write-human/SKILL.md +1 -1
  165. package/docs/agents/audits.md +1 -1
  166. package/docs/agents/canvas.md +1 -1
  167. package/docs/agents/commands.md +4 -8
  168. package/docs/agents/context-audit-checks.md +11 -25
  169. package/docs/agents/context-audit.md +7 -15
  170. package/docs/agents/context-classify.md +5 -5
  171. package/docs/agents/counts.md +5 -5
  172. package/docs/agents/drift-surfaces.md +2 -2
  173. package/docs/agents/index.md +5 -7
  174. package/docs/agents/indexes.md +1 -1
  175. package/docs/agents/install-and-sync.md +6 -11
  176. package/docs/agents/intake.md +1 -1
  177. package/docs/agents/key-changes.md +5 -5
  178. package/docs/agents/label-coverage.md +11 -0
  179. package/docs/agents/migrate.md +1 -1
  180. package/docs/agents/records-push.md +2 -2
  181. package/docs/agents/records-stale.md +13 -48
  182. package/docs/agents/records-validate.md +4 -8
  183. package/docs/agents/records.md +6 -28
  184. package/docs/agents/restated.md +1 -1
  185. package/docs/agents/rule-citations.md +2 -2
  186. package/docs/agents/sandbox.md +4 -4
  187. package/docs/agents/skills-audit.md +2 -2
  188. package/docs/agents/state-scoped-risk.md +2 -2
  189. package/docs/agents/superseded.md +2 -2
  190. package/docs/agents/tasks-plans.md +1 -1
  191. package/docs/agents/tasks-validate.md +1 -1
  192. package/docs/agents/tasks.md +3 -3
  193. package/docs/agents/teach.md +1 -1
  194. package/docs/agents/upstream.md +26 -2
  195. package/docs/target/migrations.md +32 -0
  196. package/docs/target/projects.md +5 -7
  197. package/docs/target/scenarios.md +2 -2
  198. package/docs/target/sync.md +4 -4
  199. package/docs/workflow/ai-workflow.md +7 -38
  200. package/docs/workflow/index.md +1 -1
  201. package/docs/workflow/operating-model.md +10 -10
  202. package/docs/workflow/parallel-features.md +12 -12
  203. package/docs/workflow/skill-map-on-request.md +21 -24
  204. package/docs/workflow/skill-map.md +23 -34
  205. package/docs/workflow/visual-design-workflow.md +13 -16
  206. package/governance/renames.toml +0 -30
  207. package/governance/rules/canon/605-worktrees.md +1 -1
  208. package/governance/rules/canon/context.md +13 -0
  209. package/governance/rules/{standards → canon}/plan.md +4 -5
  210. package/governance/rules/canon/tasks.md +18 -0
  211. package/governance/rules/claude/skill.md +17 -0
  212. package/governance/stacks/base.toml +2 -4
  213. package/package.json +4 -4
  214. package/scripts/core/install-check.sh +4 -4
  215. package/scripts/core/regen-web-previews.ts +1 -1
  216. package/scripts/lib/ui.sh +0 -159
  217. package/src/audits/catalog.ts +5 -98
  218. package/src/claude/cases/authoring.ts +0 -18
  219. package/src/claude/cases/misc.ts +1 -14
  220. package/src/claude/cases/setup.ts +7 -20
  221. package/src/claude/cases/workflow.ts +6 -34
  222. package/src/claude/seeds.ts +1 -7
  223. package/src/claude/skills-audit.ts +3 -3
  224. package/src/cli/help.ts +4 -5
  225. package/src/cli/ui.ts +2 -3
  226. package/src/cli.ts +0 -4
  227. package/src/commands/claude.ts +9 -15
  228. package/src/commands/context.ts +18 -280
  229. package/src/commands/feedback.ts +22 -91
  230. package/src/commands/gov.ts +2 -15
  231. package/src/commands/labels.ts +326 -7
  232. package/src/commands/migrate.ts +6 -1
  233. package/src/commands/pr.ts +1 -1
  234. package/src/commands/records.ts +17 -403
  235. package/src/commands/sandbox.ts +3 -6
  236. package/src/commands/sync.ts +5 -3
  237. package/src/commands/tasks.ts +3 -3
  238. package/src/commands/upstream.ts +135 -0
  239. package/src/context/audit.ts +10 -19
  240. package/src/context/classify/extract.ts +6 -13
  241. package/src/context/classify/patterns.ts +2 -41
  242. package/src/context/classify/prompts.ts +2 -6
  243. package/src/context/classify/run.ts +3 -3
  244. package/src/context/folders.ts +8 -13
  245. package/src/context/gate.ts +11 -91
  246. package/src/context/requirements.ts +13 -4
  247. package/src/counts/scan.ts +3 -3
  248. package/src/design/budget.ts +1 -1
  249. package/src/design/components.ts +3 -3
  250. package/src/design/document.ts +1 -1
  251. package/src/design/regen.ts +1 -1
  252. package/src/design/render.ts +1 -1
  253. package/src/feedback/body.ts +0 -12
  254. package/src/gate/measures.ts +7 -58
  255. package/src/gate/sequencer.ts +56 -1
  256. package/src/gate/stages.ts +1 -7
  257. package/src/gov/citations.ts +9 -3
  258. package/src/gov/install.ts +2 -3
  259. package/src/gov/restated.ts +3 -3
  260. package/src/gov/stacks.ts +1 -1
  261. package/src/hooks/post-merge.ts +1 -1
  262. package/src/labels/apply.ts +39 -0
  263. package/src/labels/format.ts +3 -3
  264. package/src/labels/phase.ts +3 -3
  265. package/src/labels/sections.ts +43 -0
  266. package/src/markdown/structure.ts +2 -2
  267. package/src/migrate/record-layout.ts +3 -3
  268. package/src/migrate/skill-names.ts +20 -1
  269. package/src/pr/paths.ts +4 -4
  270. package/src/records/backup.ts +16 -6
  271. package/src/records/ordinal.ts +1 -1
  272. package/src/records/prune.ts +2 -1
  273. package/src/records/stale-canonical.ts +33 -3
  274. package/src/records/validate.ts +2 -188
  275. package/src/roots/record.ts +1 -1
  276. package/src/sandbox/census.ts +1 -1
  277. package/src/sandbox/coverage.ts +2 -6
  278. package/src/sandbox/equivalence.ts +5 -44
  279. package/src/sandbox/expect.ts +4 -4
  280. package/src/sandbox/provision.ts +13 -36
  281. package/src/sandbox/scenario.ts +137 -55
  282. package/src/sandbox/tree.ts +2 -6
  283. package/src/shipped/references.ts +3 -3
  284. package/src/standards/read.ts +44 -0
  285. package/src/sync/git.ts +1 -1
  286. package/src/sync/seeds-report.ts +1 -1
  287. package/src/tasks/archive.ts +5 -5
  288. package/src/tasks/branch.ts +3 -3
  289. package/src/tasks/label.ts +1 -1
  290. package/src/tasks/reach.ts +2 -2
  291. package/src/tasks/record.ts +2 -2
  292. package/src/tasks/validate.ts +2 -2
  293. package/src/teach/workspace.ts +1 -1
  294. package/src/upstream/cursor.ts +1 -1
  295. package/src/upstream/due.ts +128 -0
  296. package/src/upstream/releases.ts +2 -1
  297. package/standards/index.md +0 -35
  298. package/standards/standard.md +1 -7
  299. package/tooling/base/reference.md +2 -2
  300. package/tooling/base/seeds/.github/pull_request_template.md +2 -2
  301. package/tooling/claude/reference.md +7 -21
  302. package/tooling/claude/seeds/.claude/hooks/pr-create-log.sh +9 -1
  303. package/tooling/claude/seeds/.claude/hooks/records-index.sh +8 -20
  304. package/tooling/claude/seeds/.claude/hooks/review-post-scan.sh +171 -0
  305. package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +3 -3
  306. package/tooling/claude/seeds/.claude/settings.json +9 -0
  307. package/tooling/claude/seeds/CLAUDE.md +1 -3
  308. package/tooling/claude/seeds/canon/REQUIREMENTS.md +2 -9
  309. package/tooling/web/configs/e2e/screenshot.ts +0 -1
  310. package/claude/skills/auto-ship/references/review-findings.md +0 -20
  311. package/claude/skills/bash-cli-script/REQUIREMENT.md +0 -43
  312. package/claude/skills/bash-cli-script/SKILL.md +0 -53
  313. package/claude/skills/bash-cli-script/references/template.md +0 -19
  314. package/claude/skills/canon-operator/REQUIREMENT.md +0 -62
  315. package/claude/skills/canon-operator/SKILL.md +0 -113
  316. package/claude/skills/canon-rollout/REQUIREMENT.md +0 -59
  317. package/claude/skills/canon-rollout/SKILL.md +0 -140
  318. package/claude/skills/canon-rollout/references/failure-recovery.md +0 -20
  319. package/claude/skills/context-fold/references/anchor-sweep.md +0 -58
  320. package/claude/skills/context-fold/references/promoted-pages.md +0 -29
  321. package/claude/skills/context-fold/references/receipt-sweep.md +0 -43
  322. package/claude/skills/context-fold/references/wireframe-sweep.md +0 -45
  323. package/claude/skills/create-standard/REQUIREMENT.md +0 -33
  324. package/claude/skills/create-standard/SKILL.md +0 -31
  325. package/claude/skills/design-extract/REQUIREMENT.md +0 -42
  326. package/claude/skills/design-extract/SKILL.md +0 -108
  327. package/claude/skills/draft-and-pick/references/frame.html +0 -118
  328. package/claude/skills/draft-doc/references/wireframes.md +0 -48
  329. package/claude/skills/markdown-propose/REQUIREMENT.md +0 -47
  330. package/claude/skills/markdown-propose/SKILL.md +0 -122
  331. package/claude/skills/markdown-propose/references/format.md +0 -118
  332. package/claude/skills/memory-capture/REQUIREMENT.md +0 -50
  333. package/claude/skills/memory-capture/SKILL.md +0 -117
  334. package/claude/skills/memory-review/REQUIREMENT.md +0 -52
  335. package/claude/skills/memory-review/SKILL.md +0 -129
  336. package/claude/skills/memory-review/references/later-phases.md +0 -118
  337. package/claude/skills/memory-review/references/receipt-format.md +0 -64
  338. package/claude/skills/project-commands/REQUIREMENT.md +0 -42
  339. package/claude/skills/project-commands/SKILL.md +0 -87
  340. package/claude/skills/repo-metadata/REQUIREMENT.md +0 -37
  341. package/claude/skills/repo-metadata/SKILL.md +0 -54
  342. package/claude/skills/restate-plainly/REQUIREMENT.md +0 -41
  343. package/claude/skills/restate-plainly/SKILL.md +0 -41
  344. package/claude/skills/review-branch/REQUIREMENT.md +0 -40
  345. package/claude/skills/review-branch/SKILL.md +0 -137
  346. package/claude/skills/seed-sync/REQUIREMENT.md +0 -45
  347. package/claude/skills/seed-sync/SKILL.md +0 -158
  348. package/claude/skills/sketch-design/REQUIREMENT.md +0 -38
  349. package/claude/skills/sketch-design/SKILL.md +0 -94
  350. package/claude/skills/ux-walkthrough/REQUIREMENT.md +0 -56
  351. package/claude/skills/ux-walkthrough/SKILL.md +0 -53
  352. package/claude/skills/ux-walkthrough/references/builds.md +0 -15
  353. package/claude/skills/ux-walkthrough/references/candidate-pages.md +0 -11
  354. package/claude/skills/ux-walkthrough/references/measuring.md +0 -22
  355. package/claude/skills/ux-walkthrough/references/record.md +0 -36
  356. package/claude/skills/ux-walkthrough/references/relay.md +0 -25
  357. package/docs/agents/architecture-record.md +0 -36
  358. package/docs/agents/review-classification.md +0 -76
  359. package/governance/rules/canon/603-memory.md +0 -11
  360. package/governance/rules/lang/120-bash.md +0 -18
  361. package/governance/rules/standards/architecture.md +0 -13
  362. package/governance/rules/standards/context.md +0 -14
  363. package/governance/rules/standards/design.md +0 -12
  364. package/governance/rules/standards/groundwork.md +0 -13
  365. package/governance/rules/standards/intake.md +0 -12
  366. package/governance/rules/standards/memory.md +0 -12
  367. package/governance/rules/standards/readme.md +0 -12
  368. package/governance/rules/standards/ready.md +0 -13
  369. package/governance/rules/standards/requirements.md +0 -12
  370. package/governance/rules/standards/rule.md +0 -13
  371. package/governance/rules/standards/session.md +0 -13
  372. package/governance/rules/standards/skill.md +0 -21
  373. package/governance/rules/standards/standard.md +0 -13
  374. package/governance/rules/standards/tasks.md +0 -15
  375. package/governance/rules/standards/teach.md +0 -14
  376. package/governance/rules/standards/wiki.md +0 -13
  377. package/governance/rules/standards/wireframes.md +0 -13
  378. package/scripts/config.sh +0 -11
  379. package/scripts/lib/gov.sh +0 -14
  380. package/scripts/lib/sandbox-fixtures.sh +0 -191
  381. package/scripts/lib/sandbox-git.sh +0 -125
  382. package/scripts/lib/sandbox-path.sh +0 -50
  383. package/scripts/sandbox-hook.sh +0 -99
  384. package/src/autoship/classify.ts +0 -75
  385. package/src/autoship/paths.ts +0 -50
  386. package/src/commands/autoship.ts +0 -129
  387. package/src/commands/repo.ts +0 -393
  388. package/src/context/architecture.ts +0 -654
  389. package/src/context/wireframe-states.ts +0 -238
  390. package/src/gov/standard-rules.ts +0 -179
  391. package/src/records/migrate.ts +0 -78
  392. package/src/records/stale.ts +0 -243
  393. package/src/repo/metadata.ts +0 -206
  394. package/src/sandbox/hooks.ts +0 -128
  395. package/standards/architecture.md +0 -127
  396. package/standards/memory.md +0 -158
  397. package/standards/mermaid.md +0 -64
  398. package/standards/requirements.md +0 -79
  399. package/standards/wiki.md +0 -77
  400. package/standards/wireframes.md +0 -143
  401. package/tooling/claude/seeds/.claude/memory/index.md +0 -8
  402. package/tooling/claude/seeds/canon/ARCHITECTURE.md +0 -23
  403. package/tooling/claude/seeds/canon/wireframes/index.md +0 -8
  404. /package/{standards → claude/skills/create-skill/references}/skill-practice.md +0 -0
  405. /package/{standards → claude/skills/create-skill/references}/skill-requirement.md +0 -0
  406. /package/{standards → claude/skills/draft-figure/references}/figures.md +0 -0
  407. /package/{standards → claude/skills/git-branch/references}/slug.md +0 -0
  408. /package/{standards → claude/skills/git-commit/references}/commit.md +0 -0
  409. /package/{standards → claude/skills/git-commit/references}/versioning.md +0 -0
  410. /package/{standards → claude/skills/plan-feature/references}/plan-lifecycle.md +0 -0
  411. /package/{standards → claude/skills/plan-groundwork/references}/groundwork-spikes.md +0 -0
  412. /package/{standards → claude/skills/task-board/references}/tasks-decline.md +0 -0
  413. /package/{standards → claude/skills/teach-workspace/references}/glossary.md +0 -0
@@ -1,17 +1,26 @@
1
1
  import { readFile } from 'node:fs/promises'
2
2
  import { join, relative } from 'node:path'
3
- import { wordCount } from '@/context/architecture'
4
3
  import { bodyLines } from '@/markdown/scan'
5
4
  import { surfaceDir } from '@/roots/surface'
6
5
 
7
6
  /**
8
7
  * The record this measures, relative to `root`, resolved at either surface
9
- * root for the reason `architectureRel` gives.
8
+ * root, since a project that has moved holds it under either.
10
9
  */
11
10
  export function requirementsRel(root: string): string {
12
11
  return relative(root, surfaceDir(root, 'REQUIREMENTS.md'))
13
12
  }
14
13
 
14
+ /**
15
+ * Counts whitespace-delimited tokens, the unit the record's word cap is stated
16
+ * in. A code span counts as the tokens it holds, so a line citing a long path
17
+ * pays for it the way a reader does. A caller gating on the count hands in
18
+ * prose with fenced lines already dropped.
19
+ */
20
+ export function wordCount(text: string): number {
21
+ return text.match(/\S+/g)?.length ?? 0
22
+ }
23
+
15
24
  export interface RequirementsReport {
16
25
  readonly rel: string
17
26
  /** The whole record's word count, frontmatter left out. */
@@ -43,8 +52,8 @@ function isMissing(error: unknown): boolean {
43
52
  /**
44
53
  * Measures the record, or reports nothing when the project carries none.
45
54
  *
46
- * Absent rather than zeroed, for the reason `measureArchitecture` gives, and a
47
- * record present and unreadable propagates the same way.
55
+ * Absent rather than zeroed, so a project with no record is never told it holds an
56
+ * empty one, and a record present and unreadable propagates.
48
57
  */
49
58
  export async function measureRequirements(
50
59
  root: string,
@@ -35,8 +35,8 @@ export type CountsReport =
35
35
 
36
36
  /**
37
37
  * A calendar date, which reads a sentence as a historical record rather than
38
- * a live claim about the tree. `canon/ARCHITECTURE.md` and the context
39
- * entries carry a figure this way deliberately, and every one of them stays
38
+ * a live claim about the tree. The context entries
39
+ * carry a figure this way deliberately, and every one of them stays
40
40
  * correct forever, so a sentence carrying one is read past rather than
41
41
  * matched.
42
42
  */
@@ -142,7 +142,7 @@ const QUANTIFIERS = ['all']
142
142
  * match at all. No syntactic rule tells a qualifier that narrows a catalog
143
143
  * from one that only restates it, and the sentence was true when written, so
144
144
  * the fix was not a narrower matcher: the clause was dated as a past state,
145
- * the way `canon/ARCHITECTURE.md` dates its own figures, which is the class
145
+ * the way a context entry dates its own figures, which is the class
146
146
  * the date exclusion below already reads past.
147
147
  */
148
148
  const ARTICLES = ['the', 'a', 'an']
@@ -1,5 +1,5 @@
1
1
  /**
2
- * The prose budget `standards/design.md` sets for a design record, and the
2
+ * The prose budget `claude/skills/canvas-board/references/design.md` sets for a design record, and the
3
3
  * counter the `design` gate stage reads it through.
4
4
  *
5
5
  * The limits live here and in the standard, never in the stage, so the stage
@@ -15,7 +15,7 @@
15
15
  * `buildDesignCss`'s `components` option, which is what widening that option
16
16
  * from a boolean to `boolean | readonly Component[]` bought.
17
17
  *
18
- * It does not live in `canon/DESIGN.md`. `standards/design.md` keeps CSS class
18
+ * It does not live in `canon/DESIGN.md`. `claude/skills/canvas-board/references/design.md` keeps CSS class
19
19
  * names out of that record and says they live in code, which is here.
20
20
  */
21
21
 
@@ -250,8 +250,8 @@ const TEACH_CHROME: Component = {
250
250
  'navigation shared by every teach page. Recovered from two gitignored',
251
251
  'course.css files that predate a regression that dropped this layer from the',
252
252
  "generator, and rewritten onto this module's tokens rather than the",
253
- 'incompatible palette they carried. See canon/wireframes/teach/chrome.md for',
254
- 'the shape.',
253
+ 'incompatible palette they carried. See canon/context/features/teach/chrome.md',
254
+ 'for the shape.',
255
255
  ].join('\n '),
256
256
  reads: [
257
257
  '--color-background',
@@ -94,7 +94,7 @@ function borderRows(tokens: readonly BorderToken[]): string[][] {
94
94
  * and every reason behind them lives in the entry.
95
95
  */
96
96
  const LEAD = [
97
- 'Authoring guidance: `standards/design.md`. Rendered from `src/design/tokens.ts` by `canon design regen`, so edit the module and never this file.',
97
+ 'Authoring guidance: `claude/skills/canvas-board/references/design.md`. Rendered from `src/design/tokens.ts` by `canon design regen`, so edit the module and never this file.',
98
98
  'Why each value was chosen lives in `canon/context/design/tokens.md`.',
99
99
  ].join(' ')
100
100
 
@@ -16,7 +16,7 @@ import { NEUTRAL_TOKENS } from '@/design/neutral'
16
16
  * gate stage is what keeps silently out of it.
17
17
  */
18
18
 
19
- /** The rendered record, at the path `standards/design.md` fixes for it. */
19
+ /** The rendered record, at the path `claude/skills/canvas-board/references/design.md` fixes for it. */
20
20
  export const DESIGN_DOCUMENT = join('canon', 'DESIGN.md')
21
21
 
22
22
  /**
@@ -105,7 +105,7 @@ interface Confidence {
105
105
  }
106
106
 
107
107
  /**
108
- * The columns the confidence ratio reads, fixed by `standards/design.md`. The
108
+ * The columns the confidence ratio reads, fixed by `claude/skills/canvas-board/references/design.md`. The
109
109
  * first column of each table names its row, and `Multiplier` and `When used`
110
110
  * restate what the row already carries, so none of them is something a source
111
111
  * could anchor and none belongs in the denominator.
@@ -1,5 +1,3 @@
1
- const SLUG_FALLBACK = 'general'
2
- const SLUG_MAX_LENGTH = 40
3
1
  const TITLE_MAX_LENGTH = 72
4
2
 
5
3
  /**
@@ -79,16 +77,6 @@ function surfaceField(body: string): string | undefined {
79
77
  return readField(body, 'Surface')?.split('\n')[0]?.trim()
80
78
  }
81
79
 
82
- export function deriveSlug(body: string): string {
83
- const slug = (surfaceField(body) ?? '')
84
- .toLowerCase()
85
- .replace(/[^a-z0-9]+/g, '-')
86
- .replace(/^-+|-+$/g, '')
87
- .slice(0, SLUG_MAX_LENGTH)
88
- .replace(/-+$/g, '')
89
- return slug || SLUG_FALLBACK
90
- }
91
-
92
80
  /**
93
81
  * Each label must exist on the toolkit repository, because `gh issue create`
94
82
  * refuses the whole issue on an unknown label rather than dropping it.
@@ -7,14 +7,6 @@ import {
7
7
  type ClientCommand,
8
8
  clientCommandCitationsIn,
9
9
  } from '@/gate/client-commands'
10
- import {
11
- isOverCount,
12
- isOverLength,
13
- isOverRisks,
14
- measureArchitecture,
15
- missingRevisit,
16
- overWords,
17
- } from '@/context/architecture'
18
10
  import { isOverWordCap, measureRequirements } from '@/context/requirements'
19
11
  import {
20
12
  auditSkills,
@@ -253,62 +245,19 @@ function citedPaths(record: { paths?: unknown } | undefined): string[] {
253
245
  }
254
246
 
255
247
  /**
256
- * The canonical records against the caps each states for itself. The
257
- * architecture record carries five: the line ceiling its allowances derive,
258
- * the entry cap, the revisit sentence closing each decision, the words a
259
- * decision may hold, and the bullets its Risks section may hold. The
260
- * requirements record carries one, its own word count.
248
+ * The requirements record against the word cap it states for itself.
261
249
  *
262
250
  * Read in-process rather than through `context audit`, whose one gating stage
263
- * here runs `--citations-only` and never opens either record, which is why
264
- * the line ceiling went unenforced by `bun run check` until this stage. A
265
- * project carrying neither record, or records stating none of the caps,
266
- * passes, since each rule belongs to the record rather than to the toolkit.
251
+ * here runs `--citations-only` and never opens the record. A project carrying
252
+ * no record, or a record stating no cap, passes, since the rule belongs to the
253
+ * record rather than to the toolkit.
267
254
  */
268
255
  export const canonicalRecords: Measure = async (ctx) => {
269
- const [report, requirements] = await Promise.all([
270
- measureArchitecture(ctx.root),
271
- measureRequirements(ctx.root),
272
- ])
256
+ const requirements = await measureRequirements(ctx.root)
273
257
 
274
258
  const failures: string[] = []
275
259
  const emissions: Emission[] = []
276
260
 
277
- if (report === undefined) {
278
- emissions.push(info('No architecture record to measure'))
279
- } else {
280
- const decisions = report.decisions.length
281
- const lackingRevisit = missingRevisit(report)
282
- const longDecisions = overWords(report)
283
- failures.push(
284
- ...[
285
- isOverCount(report) &&
286
- `${decisions} decisions against a cap of ${report.entryCap}. Merge two or retire one in ${report.rel}, never compress.`,
287
- isOverLength(report) &&
288
- `${report.lines} lines against a ceiling of ${report.ceiling} in ${report.rel}.`,
289
- lackingRevisit.length > 0 &&
290
- `No revisit sentence in ${lackingRevisit.map((heading) => `"${heading}"`).join(', ')}. Close each with one opening "Revisit when" in ${report.rel}.`,
291
- longDecisions.length > 0 &&
292
- `${longDecisions.map((entry) => `"${entry.heading}" (${entry.words})`).join(', ')} past ${report.wordCap} words a decision in ${report.rel}. Cut the reasoning to the trade, never split one decision across two headings.`,
293
- isOverRisks(report) &&
294
- `${report.risksBullets} risk bullets against a cap of ${report.riskCap} in ${report.rel}. Drop what is no longer open.`,
295
- ].filter((failure): failure is string => typeof failure === 'string'),
296
- )
297
-
298
- const cap =
299
- report.entryCap === undefined
300
- ? 'no entry cap stated'
301
- : `a cap of ${report.entryCap}`
302
- emissions.push(info(`${decisions} decisions against ${cap}`))
303
- if (report.riskCap !== undefined && report.risksBullets === undefined) {
304
- emissions.push(
305
- info(
306
- `No Risks section to count against a cap of ${report.riskCap} in ${report.rel}`,
307
- ),
308
- )
309
- }
310
- }
311
-
312
261
  if (requirements === undefined) {
313
262
  emissions.push(info('No requirements record to measure'))
314
263
  } else if (isOverWordCap(requirements)) {
@@ -368,7 +317,7 @@ export const designProse: Measure = async (ctx) => {
368
317
  if (failures.length > 0) {
369
318
  return {
370
319
  emissions: [],
371
- failure: `${failures.join(' ')} Cut to the budget in standards/design.md, moving the why to the context entry.`,
320
+ failure: `${failures.join(' ')} Cut to the budget in claude/skills/canvas-board/references/design.md, moving the why to the context entry.`,
372
321
  }
373
322
  }
374
323
  if (emissions.length === 0)
@@ -415,7 +364,7 @@ export const skillProvenance: Measure = async (ctx) => {
415
364
  /**
416
365
  * Every listed practice skill against the closing sections, and every skill on
417
366
  * the wider ledger list against the ledger, both of which
418
- * `standards/skill-practice.md` requires.
367
+ * `claude/skills/create-skill/references/skill-practice.md` requires.
419
368
  *
420
369
  * Read in-process for the reason `skillProvenance` is, so the verb keeps its
421
370
  * missing-requirement-only exit. The list names shipped folders alone, so a
@@ -1,3 +1,5 @@
1
+ import { readFileSync } from 'node:fs'
2
+ import { availableParallelism } from 'node:os'
1
3
  import { join } from 'node:path'
2
4
  import { execa } from 'execa'
3
5
  import type {
@@ -44,6 +46,28 @@ export interface StageResult {
44
46
  readonly queuedMs?: number
45
47
  }
46
48
 
49
+ export interface LoadReading {
50
+ /** The 1-minute load average. */
51
+ readonly loadAverage: number
52
+ readonly cores: number
53
+ }
54
+
55
+ /**
56
+ * Reads the 1-minute load average from `/proc/loadavg`. A platform without
57
+ * it, as macOS, has no reading to give, so this answers `undefined` rather
58
+ * than throwing into a stage that has already failed.
59
+ */
60
+ export function readProcLoad(): LoadReading | undefined {
61
+ try {
62
+ const first = readFileSync('/proc/loadavg', 'utf8').split(' ')[0]
63
+ const loadAverage = Number.parseFloat(first)
64
+ if (!Number.isFinite(loadAverage)) return undefined
65
+ return { loadAverage, cores: availableParallelism() }
66
+ } catch {
67
+ return undefined
68
+ }
69
+ }
70
+
47
71
  export interface GateContext extends MeasureContext {
48
72
  /** Whether the format stage writes or checks. */
49
73
  readonly write: boolean
@@ -58,6 +82,11 @@ export interface GateContext extends MeasureContext {
58
82
  * wait and reads as a hung suite.
59
83
  */
60
84
  readonly onQueue?: (label: string, holder: LockHolder) => void
85
+ /**
86
+ * Reads the machine load a failed locked stage ran under. Defaults to
87
+ * `/proc/loadavg`, and answers `undefined` where there is none.
88
+ */
89
+ readonly readLoad?: () => LoadReading | undefined
61
90
  }
62
91
 
63
92
  export interface ChangedSet {
@@ -195,7 +224,11 @@ async function executeStage(
195
224
  ]
196
225
 
197
226
  try {
198
- const outcome = await runChecks(stage, ctx, queued)
227
+ const outcome = withLoadLine(
228
+ await runChecks(stage, ctx, queued),
229
+ stage,
230
+ ctx,
231
+ )
199
232
  return held.waitedOn === undefined
200
233
  ? outcome
201
234
  : { ...outcome, queuedMs: held.waitedMs }
@@ -204,6 +237,28 @@ async function executeStage(
204
237
  }
205
238
  }
206
239
 
240
+ /**
241
+ * The lock serializes suites and does nothing about the rest of the box, so a
242
+ * starved spawn test and a real failure read alike. The load beside the
243
+ * failure is what lets a report tell them apart.
244
+ */
245
+ function withLoadLine(
246
+ outcome: StageOutcome,
247
+ stage: Stage,
248
+ ctx: GateContext,
249
+ ): StageOutcome {
250
+ if (outcome.status !== 'failed') return outcome
251
+
252
+ const reading = (ctx.readLoad ?? readProcLoad)()
253
+ if (reading === undefined) return outcome
254
+
255
+ const text = `Load average ${reading.loadAverage} on ${reading.cores} cores when the ${stage.label} stage failed`
256
+ return {
257
+ ...outcome,
258
+ emissions: [...outcome.emissions, { kind: 'info', text }],
259
+ }
260
+ }
261
+
207
262
  async function runChecks(
208
263
  stage: Stage,
209
264
  ctx: GateContext,
@@ -198,17 +198,11 @@ export const STAGES: readonly Stage[] = [
198
198
  argv: ['gov', 'regen'],
199
199
  failure: 'Consumed-copy regen failed',
200
200
  },
201
- {
202
- kind: 'drift',
203
- pathspec: 'governance/rules/standards',
204
- failure:
205
- 'Standard-pointer rules drifted. Run bun run check and commit governance/rules/standards and .claude/rules.',
206
- },
207
201
  {
208
202
  kind: 'drift',
209
203
  pathspec: '.claude/rules',
210
204
  failure:
211
- 'Consumed copies drifted. Run bun run check and commit governance/rules/standards and .claude/rules.',
205
+ 'Consumed copies drifted. Run bun run check and commit .claude/rules.',
212
206
  },
213
207
  ],
214
208
  success: 'Consumed copies clean',
@@ -6,6 +6,7 @@ import { isMarked } from '@/sweep/exempt-marker'
6
6
  import { gitEnv } from '@/git/env'
7
7
  import { listRuleFiles } from '@/gov/payload'
8
8
  import { parseFrontmatter } from '@/indexes/frontmatter'
9
+ import { movedStandardPath } from '@/standards/read'
9
10
  import { findBacktickSpans } from '@/markdown/backticks'
10
11
 
11
12
  /**
@@ -177,8 +178,9 @@ export function classifySpan(span: string): CitationForm | undefined {
177
178
  *
178
179
  * A standard name takes the authoring root alone, matching `standardRoots` in
179
180
  * `@/standards/read`, which reads `standards/` at the working root and then the
180
- * package corpus. This verb refuses a tree holding no rule corpus, so it runs
181
- * only where those two roots are one directory. `internal/standards/` is
181
+ * package corpus, plus the skill reference a retired name moved to. This verb
182
+ * refuses a tree holding no rule corpus, so it runs only where those two roots
183
+ * are one directory. `internal/standards/` is
182
184
  * deliberately absent: `canon standards <name>` never reaches it, so admitting it
183
185
  * here would pass a citation that refuses for the session opening it, which is a
184
186
  * gate failing open.
@@ -191,7 +193,11 @@ function candidatesFor(
191
193
  cited: string,
192
194
  ruleFile: string,
193
195
  ): string[] {
194
- if (form === 'standard') return [join('standards', `${cited}.md`)]
196
+ if (form === 'standard') {
197
+ const moved = movedStandardPath(cited)
198
+
199
+ return [join('standards', `${cited}.md`), ...(moved ? [moved] : [])]
200
+ }
195
201
  if (form === 'sibling') return [join(dirname(ruleFile), cited)]
196
202
  return [cited]
197
203
  }
@@ -66,9 +66,8 @@ export function installedRuleNames(
66
66
  }
67
67
 
68
68
  /**
69
- * Mirrors `rule_subdir` in `scripts/lib/gov.sh`, which stays in bash for the
70
- * sandbox loops. A rule sitting directly under `governance/rules/` has no
71
- * subdirectory and installs flat.
69
+ * A rule sitting directly under `governance/rules/` has no subdirectory and
70
+ * installs flat.
72
71
  */
73
72
  export function ruleSubdir(src: string, rulesRoot: string): string {
74
73
  const subdir = dirname(relative(rulesRoot, src))
@@ -36,8 +36,8 @@ const SKILL_ROOTS: readonly string[] = [SHIPPED_SKILLS_REL, PROJECT_SKILLS_REL]
36
36
  /**
37
37
  * Path pairs whose duplication is deliberate and already recorded.
38
38
  *
39
- * The seed is authored from the always-loaded file and `seed-sync`
40
- * exists to reconcile the two, so a bullet appearing in both is the design
39
+ * The seed is authored from the always-loaded file and a hand merge
40
+ * reconciles the two, so a bullet appearing in both is the design
41
41
  * rather than a defect. Excluding by pair rather than by content is what the
42
42
  * plan settled on: the duplication is a location fact this repository already
43
43
  * records, and a content test would have to rediscover it on every run.
@@ -611,7 +611,7 @@ function authorityFor(
611
611
  if (candidate.kind === 'seed') {
612
612
  return {
613
613
  authority: 'claude-md',
614
- reason: `${INSTRUCTIONS_REL} is authored first and the seed carries it to a target, so an edit starts there and reaches the seed through seed-sync`,
614
+ reason: `${INSTRUCTIONS_REL} is authored first and the seed carries it to a target, so an edit starts there and reaches the seed through a hand merge`,
615
615
  }
616
616
  }
617
617
 
package/src/gov/stacks.ts CHANGED
@@ -79,7 +79,7 @@ export function loadGovStack(
79
79
  * shape rather than two the caller has to tell apart.
80
80
  *
81
81
  * The directory wins over a rule file of the same name. They cannot collide
82
- * while `standards/rule.md` requires a numeric prefix on a rule slug, since a
82
+ * while `claude/skills/create-rule/references/rule.md` requires a numeric prefix on a rule slug, since a
83
83
  * band folder carries none.
84
84
  */
85
85
  export function expandStackEntry(root: string, entry: string): string[] {
@@ -163,7 +163,7 @@ function archiveLines(
163
163
  }
164
164
  return (
165
165
  `\n📋 Task not archived for #${number}: ${text(fields, 'message') ?? reason}\n` +
166
- 'Run /task-board to resolve it by hand.\n\n'
166
+ `Run /task-complete archive #${number} to resolve it by hand.\n\n`
167
167
  )
168
168
  }
169
169
 
@@ -0,0 +1,39 @@
1
+ /** What a label apply decided to do, before any write. */
2
+ export interface LabelDiff {
3
+ /** Earned labels the pull request lacks and the remote carries, so addable. */
4
+ readonly toAdd: readonly string[]
5
+ /** Every earned label the pull request lacks, whether or not it is addable. */
6
+ readonly owed: readonly string[]
7
+ /** Owed labels the remote does not carry, which are reported and never created. */
8
+ readonly missingOnRemote: readonly string[]
9
+ }
10
+
11
+ /**
12
+ * Diffs what a branch earns against what its pull request already carries and
13
+ * what the remote can attach.
14
+ *
15
+ * The diff only adds. A label on the pull request that the map does not earn
16
+ * is a person's decision and never appears here, so nothing in the result can
17
+ * be turned into a removal. Order follows `earned`, which the map declares, so
18
+ * two runs over one branch produce one list.
19
+ *
20
+ * A label the remote lacks is separated from the addable set rather than
21
+ * dropped, because the REST add endpoint creates any label it is handed and
22
+ * that write to the repository settings is not the map's call.
23
+ */
24
+ export function diffLabels(
25
+ earned: readonly string[],
26
+ present: readonly string[],
27
+ remote: readonly string[],
28
+ ): LabelDiff {
29
+ const has = new Set(present)
30
+ const carried = new Set(remote)
31
+
32
+ const owed = earned.filter((label) => !has.has(label))
33
+
34
+ return {
35
+ owed,
36
+ toAdd: owed.filter((label) => carried.has(label)),
37
+ missingOnRemote: owed.filter((label) => !carried.has(label)),
38
+ }
39
+ }
@@ -1,5 +1,5 @@
1
1
  /**
2
- * Which rule in `standards/pr.md`'s `## Title` section a title breaks.
2
+ * Which rule in `claude/skills/git-pr/references/pr.md`'s `## Title` section a title breaks.
3
3
  *
4
4
  * `structure` stands alone rather than beside the other three, because a
5
5
  * title failing the shape match has no parsed `<type>`, `<scope>`, or
@@ -28,9 +28,9 @@ const LEADING_LETTERS = /^[A-Za-z]+/
28
28
 
29
29
  /**
30
30
  * Grades a pull request title, or a commit subject sharing the same form,
31
- * against `standards/pr.md`'s structure, casing, and length rules.
31
+ * against `claude/skills/git-pr/references/pr.md`'s structure, casing, and length rules.
32
32
  *
33
- * Does not check `<type>` against `standards/commit.md`'s fixed enum.
33
+ * Does not check `<type>` against `claude/skills/git-commit/references/commit.md`'s fixed enum.
34
34
  * `pr.md`'s own `## Title` section states format, casing, and length only,
35
35
  * and names no type list of its own to check against.
36
36
  */
@@ -3,7 +3,7 @@ import { RECORD_ENTRIES, RECORD_ROOTS } from '@/roots/record'
3
3
  import type { RecordRoot } from '@/roots/record'
4
4
 
5
5
  /**
6
- * The two version namespaces `standards/versioning.md` keeps apart, and why a
6
+ * The two version namespaces `claude/skills/git-commit/references/versioning.md` keeps apart, and why a
7
7
  * pull request cannot be sorted between them by pattern alone.
8
8
  *
9
9
  * A phase label (`v68.5`) and a semver reference (`v3.44`) both match
@@ -186,7 +186,7 @@ const RELEASE_TITLE_PREFIX = 'chore(main): release '
186
186
  * phase label past this check. Together they name release-please's own act of
187
187
  * opening the pull request, which nothing else on the remote can perform.
188
188
  */
189
- function isReleasePullRequest(input: PhaseScanInput): boolean {
189
+ export function isReleasePullRequest(input: PhaseScanInput): boolean {
190
190
  return (
191
191
  input.headRefName.startsWith(RELEASE_HEAD_PREFIX) &&
192
192
  input.title.startsWith(RELEASE_TITLE_PREFIX)
@@ -265,7 +265,7 @@ function sessionLinks(text: string): string[] {
265
265
  * The split runs on the pull request rather than on each token. A release
266
266
  * pull request's tokens are read as the semver references its generated body
267
267
  * legitimately carries, and every other pull request's tokens are read as
268
- * leaked phase labels, which is what `standards/versioning.md` names the
268
+ * leaked phase labels, which is what `claude/skills/git-commit/references/versioning.md` names the
269
269
  * defect this exists to catch.
270
270
  *
271
271
  * A release pull request reports no board reference either, and the ground is
@@ -0,0 +1,43 @@
1
+ import { linesOutsideFences } from '@/markdown/scan'
2
+
3
+ /**
4
+ * The closed list of section headings a pull request body may carry, in the
5
+ * sentence case `claude/skills/git-pr/references/pr.md` states.
6
+ */
7
+ const ALLOWED_HEADINGS: readonly string[] = [
8
+ '## Summary',
9
+ '## Key changes',
10
+ '## Technical context',
11
+ '## Testing',
12
+ '## For the reviewer',
13
+ ]
14
+
15
+ const REQUIRED_HEADINGS: readonly string[] = ['## Summary', '## Key changes']
16
+
17
+ const H2 = /^##\s/
18
+
19
+ export interface SectionsCheck {
20
+ /** Level-two headings the closed list does not hold, as written. */
21
+ readonly outside: readonly string[]
22
+ /** Required headings the body never carries. */
23
+ readonly missing: readonly string[]
24
+ }
25
+
26
+ /**
27
+ * Grades the level-two headings of a pull request body against the closed list.
28
+ *
29
+ * The comparison is exact, so `## Key Changes` fails. `canon pr key-changes`
30
+ * reads its section case-insensitively, which keeps a body posted before the
31
+ * rename parsing while the scan holds new text to one spelling. Subheadings and
32
+ * fenced lines are not headings, so the list governs level two alone.
33
+ */
34
+ export function checkSections(body: string): SectionsCheck {
35
+ const headings = linesOutsideFences(body)
36
+ .map((line) => line.trim())
37
+ .filter((line) => H2.test(line))
38
+
39
+ return {
40
+ outside: headings.filter((heading) => !ALLOWED_HEADINGS.includes(heading)),
41
+ missing: REQUIRED_HEADINGS.filter((heading) => !headings.includes(heading)),
42
+ }
43
+ }
@@ -6,7 +6,7 @@ const HEADING = /^#{1,6}\s/
6
6
  * A section marker holding its line alone, which is the signpost a document
7
7
  * uses where its own template asks for bold rather than a heading.
8
8
  *
9
- * `standards/plan.md` gives `## Summary` a heading and marks the four sections
9
+ * `claude/skills/plan-feature/references/plan.md` gives `## Summary` a heading and marks the four sections
10
10
  * below it this way, so a conforming plan read as one run from its first line
11
11
  * to its last and all seven live plans reported past the depth checkpoint, at
12
12
  * 106 to 166 rendered lines. A measure firing on a whole corpus says nothing
@@ -659,7 +659,7 @@ function measureParagraph(block: readonly BodyLine[]): CadenceFinding {
659
659
  *
660
660
  * `compromise` reported 2 percent. It tags a fronted past participle as a
661
661
  * finite past-tense verb, so all twelve of those sentences in
662
- * `.claude/ARCHITECTURE.md` read as carrying one, eleven opening `Measured at`
662
+ * the repository's architecture record at that commit read as carrying one, eleven opening `Measured at`
663
663
  * and one `Overturned by`, which is the exact shape the measure exists to
664
664
  * catch. It is not even consistent with itself there: `Measured at` tags a verb
665
665
  * and `Measured against` tags an adjective.
@@ -346,9 +346,9 @@ function entriesOf(dir: string, isDirectory: boolean): string[] {
346
346
  }
347
347
 
348
348
  /**
349
- * What `draft-and-pick` Step 6 and `sketch-design` write into the folder they
350
- * archive a choice to: a capture per arm, named `arm-<id>`, and a design
351
- * handoff. A folder carrying neither is evidence.
349
+ * What `draft-and-pick` Step 6 writes into the folder it archives a choice to:
350
+ * a capture per canvas frame, named `arm-<id>`. A design handoff marks a pick
351
+ * folder an earlier skill wrote. A folder carrying neither is evidence.
352
352
  */
353
353
  const PICK_FILE = /^(?:arm-[^.]+\..+|design-handoff\.md)$/
354
354
 
@@ -99,6 +99,25 @@ export const SKILL_NAME_MAP: Readonly<Record<string, string>> = {
99
99
  'draft-diagram': 'draft-figure',
100
100
  }
101
101
 
102
+ /**
103
+ * The skills that took a two-word name from a single word, which the map above
104
+ * may not carry as a bare key.
105
+ *
106
+ * `canvas` became `canvas-board`, and a bare `canvas` key would rewrite every
107
+ * unrelated use of the word: `canon canvas serve`, `src/canvas/`,
108
+ * `.canon/canvas/`, and the `internal-canvas` skill. So each row keys on a form
109
+ * only the skill spells, a plugin invocation or a skill folder path. The tail
110
+ * guard rejects a following `-`, so a rewritten `canon:canvas-board` is not
111
+ * matched again.
112
+ *
113
+ * What this leaves behind is a prose mention of the skill by its bare name,
114
+ * which has no token for a sweep to find and is fixed by hand.
115
+ */
116
+ export const SKILL_CITATION_MAP: Readonly<Record<string, string>> = {
117
+ 'canon:canvas': 'canon:canvas-board',
118
+ 'skills/canvas': 'skills/canvas-board',
119
+ }
120
+
102
121
  /**
103
122
  * The skill rename.
104
123
  *
@@ -132,7 +151,7 @@ export const SKILL_NAME_MAP: Readonly<Record<string, string>> = {
132
151
  * listing every sweep reads never reaches them.
133
152
  */
134
153
  export const SKILL_NAME_RULES: RenameRules = defineRenameRules({
135
- replacements: SKILL_NAME_MAP,
154
+ replacements: { ...SKILL_NAME_MAP, ...SKILL_CITATION_MAP },
136
155
  keepMarker: 'canon-keep-retired',
137
156
  wholeToken: true,
138
157
  excludedPrefixes: ['scripts/eval/result-'],