@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
@@ -8,7 +8,6 @@ import {
8
8
  writeFileSync,
9
9
  } from 'node:fs'
10
10
  import { basename, dirname, join, relative } from 'node:path'
11
- import { probeScenario, stageScenario } from '@/sandbox/hooks'
12
11
  import {
13
12
  FIXTURE_SUFFIX,
14
13
  FIXTURES_DIR,
@@ -34,9 +33,8 @@ import {
34
33
 
35
34
  /**
36
35
  * Provisions one scenario into the sandbox tree, and resets or cleans that tree.
37
- * A bash scenario's hooks run through `sandbox-hook.sh` and a TypeScript one's
38
- * arm runs in process through `scenario.ts`, and everything between them runs
39
- * here, in the order the retired bash dispatcher held.
36
+ * A scenario's arm runs in process through `scenario.ts`, and everything
37
+ * around it runs here, in the order the retired bash dispatcher held.
40
38
  *
41
39
  * Narration is part of the contract. `canon sandbox equivalence` compares the
42
40
  * log line for line against the bash harness, so every message, its frame
@@ -403,36 +401,22 @@ interface Scenario {
403
401
 
404
402
  /**
405
403
  * Reads what a scenario declares ahead of provisioning: its config exports and
406
- * whether it stages from the anchor. A bash scenario answers through the probe,
407
- * and a TypeScript one from its module, which is also what its stage runs.
404
+ * whether it stages from the anchor, from its module, which is also what its
405
+ * stage runs.
408
406
  */
409
407
  function declareScenario(
410
408
  root: string,
411
409
  scenario: Scenario,
412
410
  env: NodeJS.ProcessEnv,
413
- ):
414
- | { kind: 'sh'; file: string; isAnchor: boolean }
415
- | { kind: 'ts'; definition: ScenarioDefinition; isAnchor: boolean } {
411
+ ): { definition: ScenarioDefinition; isAnchor: boolean } {
416
412
  const name = `${scenario.category}/${scenario.command}`
417
413
  const resolved = resolveScenarioFile(
418
414
  join(root, 'sandbox'),
419
415
  scenario.category,
420
416
  scenario.command,
421
417
  )
422
- if (!resolved.ok && resolved.reason === 'ambiguous')
423
- fail(
424
- `Sandbox script ${name} exists as both .sh and .ts. Delete the one the port replaced.`,
425
- )
426
418
  if (!resolved.ok) fail(`Sandbox script not found: ${name}`)
427
419
 
428
- if (resolved.kind === 'sh') {
429
- const probe = probeScenario(resolved.file, env)
430
- if (!probe.ok) throw new Halt(probe.status)
431
- Object.assign(env, probe.exports)
432
-
433
- return { kind: 'sh', file: resolved.file, isAnchor: probe.isAnchor }
434
- }
435
-
436
420
  let definition: ScenarioDefinition
437
421
  try {
438
422
  definition = loadScenario(resolved.file)
@@ -443,7 +427,7 @@ function declareScenario(
443
427
  }
444
428
  Object.assign(env, scenarioExports(definition, root, env))
445
429
 
446
- return { kind: 'ts', definition, isAnchor: definition.anchor === true }
430
+ return { definition, isAnchor: definition.anchor === true }
447
431
  }
448
432
 
449
433
  async function provisionScenario(
@@ -481,21 +465,14 @@ async function provisionScenario(
481
465
  // A scenario that execs a verb as its last step hands the run to that verb,
482
466
  // whose own frame is the last one written, so nothing follows it here. An
483
467
  // in-process arm writes its exports straight into `env`.
484
- const staged =
485
- declared.kind === 'sh'
486
- ? stageScenario(declared.file, env)
487
- : {
488
- ...(await stageScenarioInProcess(declared.definition, {
489
- root,
490
- dir: sandbox,
491
- env,
492
- arm: scenario.arm,
493
- })),
494
- exports: {},
495
- }
468
+ const staged = await stageScenarioInProcess(declared.definition, {
469
+ root,
470
+ dir: sandbox,
471
+ env,
472
+ arm: scenario.arm,
473
+ })
496
474
  if (staged.ending === 'replaced') throw new Halt(staged.status, false)
497
475
  if (staged.ending === 'exited') throw new Halt(staged.status)
498
- Object.assign(env, staged.exports)
499
476
 
500
477
  const isSkipAutoCommit = (env.SANDBOX_SKIP_AUTO_COMMIT ?? '') !== ''
501
478
  const isSkipInject = (env.SANDBOX_SKIP_SKILL_INJECT ?? '') !== ''
@@ -602,7 +579,7 @@ function parseTarget(target: string): { category: string; command: string } {
602
579
  }
603
580
 
604
581
  export interface SandboxRequest {
605
- /** False where a caller already opened the frame, as `run.sh` and the picker do. */
582
+ /** False where a caller already opened the frame, as `canon sandbox run` and the picker do. */
606
583
  readonly isHeader: boolean
607
584
  /** `<category>:<command>`, `reset`, or `clean`. */
608
585
  readonly target: string
@@ -8,10 +8,19 @@ import {
8
8
  readFileSync,
9
9
  statSync,
10
10
  writeFileSync,
11
+ writeSync,
11
12
  } from 'node:fs'
12
13
  import { createRequire } from 'node:module'
13
14
  import { dirname, join, relative } from 'node:path'
14
- import { logError, logInfo, logStep, logWarn, palette, select } from '@/cli/ui'
15
+ import {
16
+ logError,
17
+ logInfo,
18
+ logStep,
19
+ logWarn,
20
+ palette,
21
+ pipeOutput,
22
+ select,
23
+ } from '@/cli/ui'
15
24
 
16
25
  /**
17
26
  * The TypeScript form of a sandbox scenario: `sandbox/<category>/<command>.ts`,
@@ -33,15 +42,13 @@ export const FIXTURE_SUFFIX = '.fixture'
33
42
  /** A scenario whose only arm carries this name routes none, as a bash file with no picker did. */
34
43
  export const DEFAULT_ARM_NAME = 'default'
35
44
 
36
- /** Every bash scenario passed this prompt to `select_or_route_scenario`. */
45
+ /** The picker's message unless a scenario names another. */
37
46
  const ROUTE_PROMPT = 'Which scenario?'
38
47
 
39
48
  /** Every scenario that sets the anchor pushes to this one throwaway repository. */
40
49
  export const SANDBOX_ANCHOR_REPO = 'canon-sandbox'
41
50
 
42
- const EXTENSIONS = ['.ts', '.sh'] as const
43
-
44
- export type ScenarioKind = 'ts' | 'sh'
51
+ const EXTENSION = '.ts'
45
52
 
46
53
  export type ArmSetup = (ctx: StageContext) => void | Promise<void>
47
54
 
@@ -50,6 +57,14 @@ export interface ScenarioDefinition {
50
57
  readonly config?: Readonly<Record<string, string>>
51
58
  /** Stages the tree from the anchor fixture and names the throwaway remote. */
52
59
  readonly anchor?: boolean
60
+ /**
61
+ * Stages and narrates ahead of the picker, so the picker's echo lands after
62
+ * it on the frame. Runs before the arm is
63
+ * routed, which leaves `ctx.arm` undefined.
64
+ */
65
+ readonly prepare?: ArmSetup
66
+ /** The picker's message, for a scenario that asks something other than the default. */
67
+ readonly prompt?: string
53
68
  /** In routing order, so the first arm is the one a headless caller gets. */
54
69
  readonly arms: Readonly<Record<string, ArmSetup>>
55
70
  }
@@ -61,43 +76,27 @@ export function scenario(definition: ScenarioDefinition): ScenarioDefinition {
61
76
  export interface ScenarioFile {
62
77
  readonly command: string
63
78
  readonly file: string
64
- readonly kind: ScenarioKind
65
79
  }
66
80
 
67
81
  /**
68
- * Lists the scenarios in one category folder, one per stem. A stem present in
69
- * both forms is reported apart rather than listed twice, since picking one
70
- * without saying so is the failure the refusal exists to prevent.
82
+ * Lists the scenarios in one category folder, one per `.ts` stem. A file in any
83
+ * other form is ignored rather than refused, so a hand-written leftover does not
84
+ * break the listing.
71
85
  */
72
86
  export function listScenarioFiles(categoryDir: string): {
73
87
  scenarios: ScenarioFile[]
74
- ambiguous: string[]
75
88
  } {
76
- const byStem = new Map<string, ScenarioFile[]>()
89
+ const scenarios: ScenarioFile[] = []
77
90
  for (const entry of readdirSync(categoryDir, { withFileTypes: true })) {
78
- if (!entry.isFile()) continue
79
- const kind = EXTENSIONS.find((ext) => entry.name.endsWith(ext))
80
- if (kind === undefined) continue
81
- const command = entry.name.slice(0, -kind.length)
82
- const found = byStem.get(command) ?? []
83
- found.push({
84
- command,
91
+ if (!entry.isFile() || !entry.name.endsWith(EXTENSION)) continue
92
+ scenarios.push({
93
+ command: entry.name.slice(0, -EXTENSION.length),
85
94
  file: join(categoryDir, entry.name),
86
- kind: kind === '.ts' ? 'ts' : 'sh',
87
95
  })
88
- byStem.set(command, found)
89
96
  }
97
+ scenarios.sort((a, b) => a.command.localeCompare(b.command))
90
98
 
91
- const scenarios: ScenarioFile[] = []
92
- const ambiguous: string[] = []
93
- for (const [command, found] of [...byStem].sort(([a], [b]) =>
94
- a.localeCompare(b),
95
- )) {
96
- if (found.length > 1) ambiguous.push(command)
97
- else if (found[0] !== undefined) scenarios.push(found[0])
98
- }
99
-
100
- return { scenarios, ambiguous }
99
+ return { scenarios }
101
100
  }
102
101
 
103
102
  /** Every category folder under `sandbox/`, fixtures excluded. */
@@ -112,21 +111,18 @@ export function listCategories(sandboxDir: string): string[] {
112
111
 
113
112
  export type ResolvedScenario =
114
113
  | ({ readonly ok: true } & ScenarioFile)
115
- | { readonly ok: false; readonly reason: 'missing' | 'ambiguous' }
114
+ | { readonly ok: false; readonly reason: 'missing' }
116
115
 
117
116
  export function resolveScenarioFile(
118
117
  sandboxDir: string,
119
118
  category: string,
120
119
  command: string,
121
120
  ): ResolvedScenario {
122
- const found = EXTENSIONS.map((ext) =>
123
- join(sandboxDir, category, `${command}${ext}`),
124
- ).filter((path) => existsSync(path) && statSync(path).isFile())
125
- if (found.length > 1) return { ok: false, reason: 'ambiguous' }
126
- const file = found[0]
127
- if (file === undefined) return { ok: false, reason: 'missing' }
128
-
129
- return { ok: true, command, file, kind: file.endsWith('.ts') ? 'ts' : 'sh' }
121
+ const file = join(sandboxDir, category, `${command}${EXTENSION}`)
122
+ if (!existsSync(file) || !statSync(file).isFile())
123
+ return { ok: false, reason: 'missing' }
124
+
125
+ return { ok: true, command, file }
130
126
  }
131
127
 
132
128
  function isRecord(value: unknown): value is Record<string, unknown> {
@@ -144,7 +140,7 @@ export function loadScenario(file: string): ScenarioDefinition {
144
140
  if (!isRecord(definition))
145
141
  throw new Error(`${file} has no default export from scenario()`)
146
142
 
147
- const { arms, config, anchor } = definition
143
+ const { arms, config, anchor, prepare, prompt } = definition
148
144
  if (!isRecord(arms) || Object.keys(arms).length === 0)
149
145
  throw new Error(`${file} declares no arms`)
150
146
  for (const [name, setup] of Object.entries(arms))
@@ -158,6 +154,10 @@ export function loadScenario(file: string): ScenarioDefinition {
158
154
  throw new Error(`${file} config holds a value that is not a string`)
159
155
  if (anchor !== undefined && typeof anchor !== 'boolean')
160
156
  throw new Error(`${file} anchor is not a boolean`)
157
+ if (prepare !== undefined && typeof prepare !== 'function')
158
+ throw new Error(`${file} prepare is not a function`)
159
+ if (prompt !== undefined && typeof prompt !== 'string')
160
+ throw new Error(`${file} prompt is not a string`)
161
161
 
162
162
  return definition as unknown as ScenarioDefinition
163
163
  }
@@ -169,7 +169,7 @@ export function armNames(definition: ScenarioDefinition): string[] {
169
169
  return names.length === 1 && names[0] === DEFAULT_ARM_NAME ? [] : names
170
170
  }
171
171
 
172
- /** Twin of `scripts/config.sh`, which derives the organization from the toolkit's own remote. */
172
+ /** Derives the organization from the toolkit's own remote unless `GITHUB_ORG` names one. */
173
173
  function deriveGithubOrg(root: string, env: NodeJS.ProcessEnv): string {
174
174
  if ((env.GITHUB_ORG ?? '') !== '') return env.GITHUB_ORG ?? ''
175
175
 
@@ -188,8 +188,8 @@ function deriveGithubOrg(root: string, env: NodeJS.ProcessEnv): string {
188
188
  }
189
189
 
190
190
  /**
191
- * What the bash probe reported for a scenario: its config, the organization
192
- * `config.sh` derives, and the anchor's repository name. These land in the one
191
+ * What provisioning reads off a scenario: its config, the derived organization,
192
+ * and the anchor's repository name. These land in the one
193
193
  * environment provisioning passes to every child, the seed and gov installs
194
194
  * included.
195
195
  */
@@ -225,6 +225,24 @@ export interface RunOptions {
225
225
  readonly stderr?: 'inherit' | 'ignore'
226
226
  /** Returns a failing status rather than stopping the arm, the `|| true` of the bash form. */
227
227
  readonly allowFailure?: boolean
228
+ /** Set for this command alone, the `NAME=value command` prefix of the bash form. */
229
+ readonly env?: Readonly<Record<string, string>>
230
+ }
231
+
232
+ export interface CaptureOptions {
233
+ /** Relative to the tree, the `cd` of a bash subshell. */
234
+ readonly cwd?: string
235
+ /** Fed to the command's stdin, the `<file` or `<<<` of the bash form. */
236
+ readonly input?: string
237
+ readonly env?: Readonly<Record<string, string>>
238
+ /** `inherit` leaves the stream on the terminal, where `pipe` hands it back for a file. */
239
+ readonly stderr?: 'pipe' | 'inherit' | 'ignore'
240
+ }
241
+
242
+ export interface Captured {
243
+ readonly status: number
244
+ readonly stdout: string
245
+ readonly stderr: string
228
246
  }
229
247
 
230
248
  export interface StageContext {
@@ -240,6 +258,8 @@ export interface StageContext {
240
258
  warn(message: string): void
241
259
  /** A bare frame line, the `echo -e "${GREY}│${NC}"` of the bash form. */
242
260
  bar(): void
261
+ /** Indents borrowed output inside the frame, the `pipe_output` of the bash form. */
262
+ pipe(text: string): void
243
263
  }
244
264
  fixtures(category: string, command: string, arm: string, stage: string): void
245
265
  git(...args: string[]): void
@@ -248,6 +268,18 @@ export interface StageContext {
248
268
  run(command: string, args: readonly string[], options?: RunOptions): number
249
269
  /** Runs a command and returns its stdout, stopping the arm on a failure. */
250
270
  read(command: string, args: readonly string[], options?: RunOptions): string
271
+ /**
272
+ * Runs a command and returns both streams with its status, never stopping the
273
+ * arm. For the `>file 2>file || status=$?` shape, where the outcome is the
274
+ * record the arm exists to hold.
275
+ */
276
+ capture(
277
+ command: string,
278
+ args: readonly string[],
279
+ options?: CaptureOptions,
280
+ ): Captured
281
+ /** Writes to a stream the way a bare `cat` or `echo` did, in order with the commands around it. */
282
+ print(text: string, stream?: 'stdout' | 'stderr'): void
251
283
  write(path: string, content: string): void
252
284
  append(path: string, content: string): void
253
285
  mkdir(path: string): void
@@ -291,14 +323,24 @@ export function createStageContext(options: ContextOptions): StageContext {
291
323
  args: readonly string[],
292
324
  stdout: 'inherit' | 'ignore' | 'pipe',
293
325
  stderr: 'inherit' | 'ignore' | 'pipe',
326
+ extra: {
327
+ cwd?: string
328
+ input?: string
329
+ env?: Readonly<Record<string, string>>
330
+ } = {},
294
331
  ) => {
295
- const stdio: StdioOptions = ['ignore', stdout, stderr]
332
+ const stdio: StdioOptions = [
333
+ extra.input === undefined ? 'ignore' : 'pipe',
334
+ stdout,
335
+ stderr,
336
+ ]
296
337
 
297
338
  return spawnSync(command, [...args], {
298
- cwd: dir,
299
- env,
339
+ cwd: extra.cwd === undefined ? dir : join(dir, extra.cwd),
340
+ env: extra.env === undefined ? env : { ...env, ...extra.env },
300
341
  encoding: 'utf8',
301
342
  stdio,
343
+ input: extra.input,
302
344
  })
303
345
  }
304
346
 
@@ -312,6 +354,7 @@ export function createStageContext(options: ContextOptions): StageContext {
312
354
  args,
313
355
  runOptions.stdout ?? 'inherit',
314
356
  runOptions.stderr ?? 'inherit',
357
+ { env: runOptions.env },
315
358
  )
316
359
  const status = result.status ?? 1
317
360
  if (status !== 0 && runOptions.allowFailure !== true)
@@ -325,7 +368,13 @@ export function createStageContext(options: ContextOptions): StageContext {
325
368
  args: readonly string[],
326
369
  runOptions: RunOptions = {},
327
370
  ): string => {
328
- const result = spawn(command, args, 'pipe', runOptions.stderr ?? 'inherit')
371
+ const result = spawn(
372
+ command,
373
+ args,
374
+ 'pipe',
375
+ runOptions.stderr ?? 'inherit',
376
+ { env: runOptions.env },
377
+ )
329
378
  const status = result.status ?? 1
330
379
  if (status !== 0 && runOptions.allowFailure !== true)
331
380
  throw new ScenarioStop(status, 'exited')
@@ -333,6 +382,26 @@ export function createStageContext(options: ContextOptions): StageContext {
333
382
  return status === 0 ? result.stdout : ''
334
383
  }
335
384
 
385
+ const capture = (
386
+ command: string,
387
+ args: readonly string[],
388
+ captureOptions: CaptureOptions = {},
389
+ ): Captured => {
390
+ const result = spawn(
391
+ command,
392
+ args,
393
+ 'pipe',
394
+ captureOptions.stderr ?? 'pipe',
395
+ captureOptions,
396
+ )
397
+
398
+ return {
399
+ status: result.status ?? 1,
400
+ stdout: result.stdout ?? '',
401
+ stderr: result.stderr ?? '',
402
+ }
403
+ }
404
+
336
405
  const git = (...args: string[]): void => {
337
406
  run('git', args)
338
407
  }
@@ -357,8 +426,7 @@ export function createStageContext(options: ContextOptions): StageContext {
357
426
 
358
427
  /**
359
428
  * `gh` answers an absent repository and an unreachable host with one status,
360
- * so the 404 alone separates them. Creating is the opt-in, for the reason
361
- * `ensure_sandbox_anchor_repo` in `scripts/lib/sandbox-git.sh` records.
429
+ * so the 404 alone separates them. Creating is the opt-in.
362
430
  */
363
431
  const ensureAnchorRepo = (org: string, repo: string): void => {
364
432
  const probe = spawn(
@@ -413,7 +481,7 @@ export function createStageContext(options: ContextOptions): StageContext {
413
481
  git('remote', 'add', 'origin', `https://github.com/${org}/${repo}.git`)
414
482
  }
415
483
 
416
- /** Twin of `stage_fixtures` in `scripts/lib/sandbox-fixtures.sh`. */
484
+ /** Copies a fixture folder into the tree. */
417
485
  const fixtures = (
418
486
  category: string,
419
487
  command: string,
@@ -476,12 +544,20 @@ export function createStageContext(options: ContextOptions): StageContext {
476
544
  const { GREY, NC } = palette(process.stderr)
477
545
  process.stderr.write(`${GREY}│${NC}\n`)
478
546
  },
547
+ // `pipe_output` read lines, so an empty body printed nothing at all.
548
+ pipe: (text) => {
549
+ if (text !== '') pipeOutput(text)
550
+ },
479
551
  },
480
552
  fixtures,
481
553
  git,
482
554
  commit: (subject) => git('commit', '-m', subject, '--no-verify', '-q'),
483
555
  run,
484
556
  read,
557
+ capture,
558
+ print: (text, stream = 'stdout') => {
559
+ writeSync(stream === 'stdout' ? 1 : 2, text)
560
+ },
485
561
  write: (path, content) => {
486
562
  mkdirSync(dirname(inTree(path)), { recursive: true })
487
563
  writeFileSync(inTree(path), content)
@@ -504,17 +580,18 @@ export function createStageContext(options: ContextOptions): StageContext {
504
580
  }
505
581
 
506
582
  /**
507
- * Picks the arm the way `select_or_route_scenario` did: a routed name first,
583
+ * Picks the arm: a routed name first,
508
584
  * echoed on the frame, then the first arm for a headless caller, then a prompt.
509
585
  */
510
586
  async function routeArm(
511
587
  names: readonly string[],
512
588
  env: NodeJS.ProcessEnv,
589
+ prompt: string,
513
590
  ): Promise<string> {
514
591
  const echo = (name: string): string => {
515
592
  const { GREY, NC, WHITE } = palette(process.stderr)
516
593
  process.stderr.write(
517
- `${GREY}│${NC}\n${GREY}◇${NC} ${ROUTE_PROMPT} ${WHITE}${name}${NC}\n`,
594
+ `${GREY}│${NC}\n${GREY}◇${NC} ${prompt} ${WHITE}${name}${NC}\n`,
518
595
  )
519
596
 
520
597
  return name
@@ -533,13 +610,13 @@ async function routeArm(
533
610
 
534
611
  if (!process.stdin.isTTY) {
535
612
  logError(
536
- `${ROUTE_PROMPT} requires a TTY. Pass an argument or set CANON_NON_INTERACTIVE=1.`,
613
+ `${prompt} requires a TTY. Pass an argument or set CANON_NON_INTERACTIVE=1.`,
537
614
  )
538
615
  throw new ScenarioStop(1, 'exited')
539
616
  }
540
617
 
541
618
  return select({
542
- message: ROUTE_PROMPT,
619
+ message: prompt,
543
620
  options: names.map((name) => ({ value: name, label: name })),
544
621
  })
545
622
  }
@@ -560,8 +637,13 @@ export async function stageScenarioInProcess(
560
637
  ): Promise<StageOutcome> {
561
638
  try {
562
639
  const names = armNames(definition)
640
+ await definition.prepare?.(
641
+ createStageContext({ ...options, arm: undefined }),
642
+ )
563
643
  const name =
564
- names.length === 0 ? DEFAULT_ARM_NAME : await routeArm(names, options.env)
644
+ names.length === 0
645
+ ? DEFAULT_ARM_NAME
646
+ : await routeArm(names, options.env, definition.prompt ?? ROUTE_PROMPT)
565
647
  const setup = Object.hasOwn(definition.arms, name)
566
648
  ? definition.arms[name]
567
649
  : undefined
@@ -8,11 +8,9 @@ import { join } from 'node:path'
8
8
  * in `CANON_SANDBOX_RUN_ID` for the rest of this process, so a script that
9
9
  * spawns a child inheriting `process.env` — `canon sandbox run` calling
10
10
  * `canon sandbox` to provision and then `canon sandbox check` — resolves the same tree in every one
11
- * of them, as do the hook and installer children provisioning spawns. A process
11
+ * of them, as do the installer children provisioning spawns. A process
12
12
  * that already carries the variable, inherited from such a parent, reuses it
13
13
  * rather than minting a new one.
14
- *
15
- * Twin of `mint_sandbox_run_id` in `scripts/lib/sandbox-path.sh`.
16
14
  */
17
15
  export function mintSandboxRunId(): string {
18
16
  const existing = process.env.CANON_SANDBOX_RUN_ID
@@ -28,9 +26,7 @@ export function mintSandboxRunId(): string {
28
26
  * per-run default is unit-testable on its own rather than only through the
29
27
  * command's registration.
30
28
  *
31
- * Twin of `resolve_sandbox_dir` in `scripts/lib/sandbox-path.sh`. The exec
32
- * boundary rules out a shared constant, so a change to the default lands on
33
- * both sides. The fall-through used to be one path per machine, so two
29
+ * The fall-through used to be one path per machine, so two
34
30
  * sessions each resolving the default at once provisioned over each other
35
31
  * with neither told; `mintSandboxRunId` gives the path a per-run component
36
32
  * instead, which is what makes two such sessions land on two different trees.
@@ -168,8 +168,8 @@ const DOCS_PATH = /(?<![\w./-])docs\/[^\s`)\]]*\.md\b/g
168
168
  * Reported unless `isStandardsPathReportable` reads the match as a
169
169
  * deliberate placeholder rather than a real citation. A body illustrating
170
170
  * the shape a project's own `standards/<name>.md` takes writes a bracketed
171
- * token this pattern also matches, such as `standards/<slug>.md` in
172
- * `create-standard/SKILL.md`, which names no real file. A bare,
171
+ * token this pattern also matches, such as `standards/<slug>.md`
172
+ * in a skill that drafts one, which names no real file. A bare,
173
173
  * non-bracketed match now reports whether or not the file exists, unlike
174
174
  * `DOCS_PATH`, which still gates on existence: a same-repository citation
175
175
  * under this corpus names no target project's own tree the way a `docs/`
@@ -206,7 +206,7 @@ const PHASE_LABEL = /\bv\d+\.\d+(?!\.\d)\b/g
206
206
  *
207
207
  * Anchored on the trailing `\d{3}-[\w-]+\.md` rather than on the bare
208
208
  * `.claude/rules/` prefix, which is what keeps a folder mention carrying no
209
- * number, such as `create-rule`, `memory-review`, and `target-setup` already
209
+ * number, such as `create-rule`, `target-check`, and `target-setup` already
210
210
  * write correctly, from matching. The segment group between `rules/` and the
211
211
  * numbered file admits both a governance-namespace path
212
212
  * (`canon/canon/604-scratch.md`) and a project-namespace one
@@ -59,7 +59,51 @@ export function standardRoots(root: string): StandardRoot[] {
59
59
  * map goes with the verb in the last slice of the retirement.
60
60
  */
61
61
  const MOVED_STANDARDS: Readonly<Record<string, string>> = {
62
+ board: 'claude/skills/task-board/references/board.md',
63
+ context: 'claude/skills/context-fold/references/context.md',
64
+ design: 'claude/skills/canvas-board/references/design.md',
65
+ docs: 'claude/skills/docs-sync/references/docs.md',
66
+ figures: 'claude/skills/draft-figure/references/figures.md',
67
+ readme: 'claude/skills/docs-sync/references/readme.md',
68
+ rule: 'claude/skills/create-rule/references/rule.md',
69
+ skill: 'claude/skills/create-skill/references/skill.md',
70
+ branch: 'claude/skills/git-branch/references/branch.md',
71
+ commit: 'claude/skills/git-commit/references/commit.md',
72
+ pr: 'claude/skills/git-pr/references/pr.md',
73
+ publish: 'claude/skills/git-pr/references/publish.md',
74
+ slug: 'claude/skills/git-branch/references/slug.md',
75
+ versioning: 'claude/skills/git-commit/references/versioning.md',
62
76
  markdown: 'claude/skills/markdown-craft/references/markdown.md',
77
+ canvas: 'claude/skills/canvas-board/references/canvas.md',
78
+ glossary: 'claude/skills/teach-workspace/references/glossary.md',
79
+ groundwork: 'claude/skills/plan-groundwork/references/groundwork.md',
80
+ 'groundwork-spikes':
81
+ 'claude/skills/plan-groundwork/references/groundwork-spikes.md',
82
+ intake: 'claude/skills/plan-intake/references/intake.md',
83
+ mermaid: 'claude/skills/draft-figure/references/mermaid.md',
84
+ plan: 'claude/skills/plan-feature/references/plan.md',
85
+ 'plan-lifecycle': 'claude/skills/plan-feature/references/plan-lifecycle.md',
86
+ ready: 'claude/skills/draft-ready/references/ready.md',
87
+ requirements: 'claude/skills/draft-doc/references/requirements.md',
88
+ 'skill-paths': 'claude/skills/create-skill/references/skill-paths.md',
89
+ 'skill-practice': 'claude/skills/create-skill/references/skill-practice.md',
90
+ session: 'claude/skills/session-map/references/session.md',
91
+ 'skill-requirement':
92
+ 'claude/skills/create-skill/references/skill-requirement.md',
93
+ tasks: 'claude/skills/task-board/references/tasks.md',
94
+ 'tasks-decline': 'claude/skills/task-board/references/tasks-decline.md',
95
+ teach: 'claude/skills/teach-workspace/references/teach.md',
96
+ wiki: 'claude/skills/draft-doc/references/wiki.md',
97
+ }
98
+
99
+ /**
100
+ * The package-relative path a retired standard now lives at, so a caller that
101
+ * resolves against a root of its own tests the same map the verb reads.
102
+ */
103
+ export function movedStandardPath(name: string): string | undefined {
104
+ if (!Object.hasOwn(MOVED_STANDARDS, name)) return undefined
105
+
106
+ return MOVED_STANDARDS[name]
63
107
  }
64
108
 
65
109
  function filename(name: string): string {
package/src/sync/git.ts CHANGED
@@ -96,7 +96,7 @@ export function pullRequestBody(changes: readonly DomainChange[]): string {
96
96
  '',
97
97
  `Sync ${domains} from toolkit.`,
98
98
  '',
99
- '## Key Changes',
99
+ '## Key changes',
100
100
  '',
101
101
  ]
102
102
 
@@ -34,7 +34,7 @@ export interface SeedsReport {
34
34
  * Classifies every seed the toolkit ships against the target's copy, and never
35
35
  * returns a change. Seeds are copy-once files a project is expected to edit, so
36
36
  * the engine's copy path would overwrite `CLAUDE.md` wholesale. Reporting alone
37
- * is what lets `seed-sync` merge one section at a time instead.
37
+ * is what lets an operator merge one section at a time by hand instead.
38
38
  *
39
39
  * Attribution reuses the history reader rather than the engine's own recovery
40
40
  * pass, which is private and takes a `SyncAdapter` seeds have no way to supply.
@@ -578,7 +578,7 @@ function isBulletFor(line: string, target: string): boolean {
578
578
 
579
579
  /**
580
580
  * Resolves the `Plan:` target against the board and against the project root
581
- * both, which is how `context-fold` reads the same line. It accepts `../plans/x.md`
581
+ * both, which is how `task-complete` reads the same line. It accepts `../plans/x.md`
582
582
  * and `.canon/plans/x.md` as one file, so a gate reading only the first form
583
583
  * would pass the second and strand the plan this exists to protect.
584
584
  *
@@ -633,7 +633,7 @@ function atOneRoot(path: string, plans: string[], root: string): string {
633
633
  /**
634
634
  * Names the other live tasks whose `Plan:` line lands on the same file through
635
635
  * any of its links. This is
636
- * the rule `context-fold` applies before it archives a plan, held here so one
636
+ * the rule the `post-merge` hook applies before it archives a plan, held here so one
637
637
  * question has one implementation: a plan another live task still cites is a
638
638
  * plan the sweep is correct to leave, and a guard that read the folder instead
639
639
  * refused every task sharing one plan and deadlocked the board against the
@@ -697,7 +697,7 @@ export type CitationOutcome = PlanCitations | ArchiveRefused
697
697
 
698
698
  /**
699
699
  * Answers where one task's plan sits and who else holds it, which is the whole
700
- * of the last-live-citation rule. `context-fold` reads this rather than scanning
700
+ * of the last-live-citation rule. The archive reads this rather than scanning
701
701
  * the board itself, so the sweep that moves a plan and the gate that refuses a
702
702
  * task archive cannot drift into disagreeing about which plan is free.
703
703
  *
@@ -897,7 +897,7 @@ async function resolveStem(
897
897
 
898
898
  /**
899
899
  * Archives one task as a single unit: the move, the ordering-row removal, and
900
- * the index regen. The hook and `task-board` both call this, so every gate
900
+ * the index regen. The hook and `task-complete` both call this, so every gate
901
901
  * refuses rather than reports. A caller with nobody watching cannot act on a
902
902
  * warning, and two callers gating differently is the drift this exists to stop.
903
903
  */
@@ -918,7 +918,7 @@ export async function archiveTask(
918
918
  const from = join(dir, `${stem}.md`)
919
919
  const text = await readFile(from, 'utf8')
920
920
 
921
- // `context-fold` ticks outcomes at ship time, before the merge, so an earlier
921
+ // `task-complete` ticks outcomes at ship time, before the merge, so an earlier
922
922
  // slice merging after the last slice shipped would find every box ticked
923
923
  // while the last slice is still open. Only the last number closes the task.
924
924
  const last = readPullRequest(text).at(-1)