@erclx/canon 4.0.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 (643) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +129 -0
  3. package/claude/.claude-plugin/plugin.json +19 -0
  4. package/claude/skills/bash-cli-script/REQUIREMENT.md +42 -0
  5. package/claude/skills/bash-cli-script/SKILL.md +48 -0
  6. package/claude/skills/bash-cli-script/references/template.md +43 -0
  7. package/claude/skills/bash-script/REQUIREMENT.md +36 -0
  8. package/claude/skills/bash-script/SKILL.md +100 -0
  9. package/claude/skills/bash-script/references/patterns.md +349 -0
  10. package/claude/skills/canon-cli/REQUIREMENT.md +41 -0
  11. package/claude/skills/canon-cli/SKILL.md +103 -0
  12. package/claude/skills/canon-feedback-file/REQUIREMENT.md +40 -0
  13. package/claude/skills/canon-feedback-file/SKILL.md +80 -0
  14. package/claude/skills/canon-feedback-triage/REQUIREMENT.md +40 -0
  15. package/claude/skills/canon-feedback-triage/SKILL.md +63 -0
  16. package/claude/skills/canon-operator/REQUIREMENT.md +61 -0
  17. package/claude/skills/canon-operator/SKILL.md +108 -0
  18. package/claude/skills/canon-rollout/REQUIREMENT.md +59 -0
  19. package/claude/skills/canon-rollout/SKILL.md +147 -0
  20. package/claude/skills/canon-screencast/REQUIREMENT.md +39 -0
  21. package/claude/skills/canon-screencast/SKILL.md +167 -0
  22. package/claude/skills/canon-slides-draft/REQUIREMENT.md +39 -0
  23. package/claude/skills/canon-slides-draft/SKILL.md +62 -0
  24. package/claude/skills/ci-workflow/REQUIREMENT.md +40 -0
  25. package/claude/skills/ci-workflow/SKILL.md +65 -0
  26. package/claude/skills/ci-workflow/references/workflows.md +98 -0
  27. package/claude/skills/claude-address-review/REQUIREMENT.md +57 -0
  28. package/claude/skills/claude-address-review/SKILL.md +212 -0
  29. package/claude/skills/claude-address-review/references/rebase-conflicts.md +39 -0
  30. package/claude/skills/claude-autoship/REQUIREMENT.md +50 -0
  31. package/claude/skills/claude-autoship/SKILL.md +207 -0
  32. package/claude/skills/claude-design-extract/REQUIREMENT.md +42 -0
  33. package/claude/skills/claude-design-extract/SKILL.md +102 -0
  34. package/claude/skills/claude-diagram/REQUIREMENT.md +45 -0
  35. package/claude/skills/claude-diagram/SKILL.md +177 -0
  36. package/claude/skills/claude-docs/REQUIREMENT.md +60 -0
  37. package/claude/skills/claude-docs/SKILL.md +287 -0
  38. package/claude/skills/claude-docs/references/anchor-sweep.md +58 -0
  39. package/claude/skills/claude-docs/references/wireframe-sweep.md +45 -0
  40. package/claude/skills/claude-feature/REQUIREMENT.md +36 -0
  41. package/claude/skills/claude-feature/SKILL.md +115 -0
  42. package/claude/skills/claude-groundwork/REQUIREMENT.md +48 -0
  43. package/claude/skills/claude-groundwork/SKILL.md +142 -0
  44. package/claude/skills/claude-intake/REQUIREMENT.md +49 -0
  45. package/claude/skills/claude-intake/SKILL.md +114 -0
  46. package/claude/skills/claude-intake-answer/REQUIREMENT.md +48 -0
  47. package/claude/skills/claude-intake-answer/SKILL.md +90 -0
  48. package/claude/skills/claude-markdown-propose/REQUIREMENT.md +48 -0
  49. package/claude/skills/claude-markdown-propose/SKILL.md +118 -0
  50. package/claude/skills/claude-markdown-propose/references/format.md +107 -0
  51. package/claude/skills/claude-memory-capture/REQUIREMENT.md +50 -0
  52. package/claude/skills/claude-memory-capture/SKILL.md +101 -0
  53. package/claude/skills/claude-memory-review/REQUIREMENT.md +50 -0
  54. package/claude/skills/claude-memory-review/SKILL.md +210 -0
  55. package/claude/skills/claude-memory-review/references/receipt-format.md +48 -0
  56. package/claude/skills/claude-orchestrate/REQUIREMENT.md +121 -0
  57. package/claude/skills/claude-orchestrate/SKILL.md +241 -0
  58. package/claude/skills/claude-orchestrate/references/orchestrator-dispatch.md +132 -0
  59. package/claude/skills/claude-orchestrate/references/orchestrator-handoff.md +32 -0
  60. package/claude/skills/claude-orchestrate/references/orchestrator-parked.md +72 -0
  61. package/claude/skills/claude-orchestrate/references/orchestrator-poll.md +87 -0
  62. package/claude/skills/claude-orchestrate/references/orchestrator-resume.md +30 -0
  63. package/claude/skills/claude-orchestrate/references/orchestrator-sweep.md +21 -0
  64. package/claude/skills/claude-orchestrate/scripts/poll.sh +373 -0
  65. package/claude/skills/claude-orchestrate/scripts/watch.sh +181 -0
  66. package/claude/skills/claude-pr-review/REQUIREMENT.md +47 -0
  67. package/claude/skills/claude-pr-review/SKILL.md +295 -0
  68. package/claude/skills/claude-review/REQUIREMENT.md +39 -0
  69. package/claude/skills/claude-review/SKILL.md +142 -0
  70. package/claude/skills/claude-seed-sync/REQUIREMENT.md +45 -0
  71. package/claude/skills/claude-seed-sync/SKILL.md +156 -0
  72. package/claude/skills/claude-standards-audit/REQUIREMENT.md +33 -0
  73. package/claude/skills/claude-standards-audit/SKILL.md +99 -0
  74. package/claude/skills/claude-tasks/REQUIREMENT.md +43 -0
  75. package/claude/skills/claude-tasks/SKILL.md +161 -0
  76. package/claude/skills/claude-teach/REQUIREMENT.md +56 -0
  77. package/claude/skills/claude-teach/SKILL.md +196 -0
  78. package/claude/skills/claude-teach/references/lesson-craft.md +59 -0
  79. package/claude/skills/claude-teach/references/pedagogy.md +67 -0
  80. package/claude/skills/claude-teach/references/promotion.md +54 -0
  81. package/claude/skills/claude-ui-test/REQUIREMENT.md +40 -0
  82. package/claude/skills/claude-ui-test/SKILL.md +77 -0
  83. package/claude/skills/claude-ux-audit/REQUIREMENT.md +40 -0
  84. package/claude/skills/claude-ux-audit/SKILL.md +79 -0
  85. package/claude/skills/claude-ux-measure/REQUIREMENT.md +48 -0
  86. package/claude/skills/claude-ux-measure/SKILL.md +122 -0
  87. package/claude/skills/claude-worker/REQUIREMENT.md +54 -0
  88. package/claude/skills/claude-worker/SKILL.md +96 -0
  89. package/claude/skills/claude-worktree/REQUIREMENT.md +58 -0
  90. package/claude/skills/claude-worktree/SKILL.md +136 -0
  91. package/claude/skills/create-rule/REQUIREMENT.md +45 -0
  92. package/claude/skills/create-rule/SKILL.md +68 -0
  93. package/claude/skills/create-skill/REQUIREMENT.md +38 -0
  94. package/claude/skills/create-skill/SKILL.md +32 -0
  95. package/claude/skills/create-snippet/REQUIREMENT.md +39 -0
  96. package/claude/skills/create-snippet/SKILL.md +30 -0
  97. package/claude/skills/create-standard/REQUIREMENT.md +35 -0
  98. package/claude/skills/create-standard/SKILL.md +29 -0
  99. package/claude/skills/decision-escalate/REQUIREMENT.md +45 -0
  100. package/claude/skills/decision-escalate/SKILL.md +79 -0
  101. package/claude/skills/docs-sync/REQUIREMENT.md +41 -0
  102. package/claude/skills/docs-sync/SKILL.md +95 -0
  103. package/claude/skills/git-branch/REQUIREMENT.md +38 -0
  104. package/claude/skills/git-branch/SKILL.md +60 -0
  105. package/claude/skills/git-commit/REQUIREMENT.md +36 -0
  106. package/claude/skills/git-commit/SKILL.md +49 -0
  107. package/claude/skills/git-followup/REQUIREMENT.md +43 -0
  108. package/claude/skills/git-followup/SKILL.md +48 -0
  109. package/claude/skills/git-issue/REQUIREMENT.md +38 -0
  110. package/claude/skills/git-issue/SKILL.md +65 -0
  111. package/claude/skills/git-pr/REQUIREMENT.md +50 -0
  112. package/claude/skills/git-pr/SKILL.md +164 -0
  113. package/claude/skills/git-pr/references/labels.md +95 -0
  114. package/claude/skills/git-ship/REQUIREMENT.md +42 -0
  115. package/claude/skills/git-ship/SKILL.md +55 -0
  116. package/claude/skills/git-split/REQUIREMENT.md +39 -0
  117. package/claude/skills/git-split/SKILL.md +162 -0
  118. package/claude/skills/git-stage/REQUIREMENT.md +39 -0
  119. package/claude/skills/git-stage/SKILL.md +73 -0
  120. package/claude/skills/git-worktree/REQUIREMENT.md +38 -0
  121. package/claude/skills/git-worktree/SKILL.md +130 -0
  122. package/claude/skills/migration-claude-md/REQUIREMENT.md +40 -0
  123. package/claude/skills/migration-claude-md/SKILL.md +76 -0
  124. package/claude/skills/migration-context/REQUIREMENT.md +36 -0
  125. package/claude/skills/migration-context/SKILL.md +95 -0
  126. package/claude/skills/migration-standards-drop/REQUIREMENT.md +55 -0
  127. package/claude/skills/migration-standards-drop/SKILL.md +113 -0
  128. package/claude/skills/migration-superseded/REQUIREMENT.md +44 -0
  129. package/claude/skills/migration-superseded/SKILL.md +115 -0
  130. package/claude/skills/project-commands/REQUIREMENT.md +42 -0
  131. package/claude/skills/project-commands/SKILL.md +85 -0
  132. package/claude/skills/restate-plainly/REQUIREMENT.md +41 -0
  133. package/claude/skills/restate-plainly/SKILL.md +39 -0
  134. package/claude/skills/session-map/REQUIREMENT.md +57 -0
  135. package/claude/skills/session-map/SKILL.md +70 -0
  136. package/claude/skills/session-resume/REQUIREMENT.md +49 -0
  137. package/claude/skills/session-resume/SKILL.md +51 -0
  138. package/claude/skills/setup-gov/REQUIREMENT.md +37 -0
  139. package/claude/skills/setup-gov/SKILL.md +77 -0
  140. package/claude/skills/setup-indexes/REQUIREMENT.md +45 -0
  141. package/claude/skills/setup-indexes/SKILL.md +153 -0
  142. package/claude/skills/setup-init/REQUIREMENT.md +45 -0
  143. package/claude/skills/setup-init/SKILL.md +127 -0
  144. package/claude/skills/setup-plugins/REQUIREMENT.md +42 -0
  145. package/claude/skills/setup-plugins/SKILL.md +81 -0
  146. package/claude/skills/setup-plugins/references/plugin-catalog.md +53 -0
  147. package/claude/skills/setup-verify/REQUIREMENT.md +39 -0
  148. package/claude/skills/setup-verify/SKILL.md +51 -0
  149. package/claude/skills/systematic-debugging/REQUIREMENT.md +41 -0
  150. package/claude/skills/systematic-debugging/SKILL.md +70 -0
  151. package/claude/skills/write-human/REQUIREMENT.md +46 -0
  152. package/claude/skills/write-human/SKILL.md +68 -0
  153. package/claude/skills/write-human/references/density.md +38 -0
  154. package/claude/skills/write-human/references/machine-tells.md +107 -0
  155. package/claude/skills/write-human/references/source-material.md +37 -0
  156. package/claude/skills/youtube-transcripts/REQUIREMENT.md +38 -0
  157. package/claude/skills/youtube-transcripts/SKILL.md +34 -0
  158. package/docs/agents/audits.md +98 -0
  159. package/docs/agents/capture.md +37 -0
  160. package/docs/agents/census.md +23 -0
  161. package/docs/agents/commands.md +146 -0
  162. package/docs/agents/comments.md +34 -0
  163. package/docs/agents/context-audit-checks.md +120 -0
  164. package/docs/agents/context-audit.md +83 -0
  165. package/docs/agents/counts.md +76 -0
  166. package/docs/agents/demo.md +86 -0
  167. package/docs/agents/docs.md +17 -0
  168. package/docs/agents/gate.md +84 -0
  169. package/docs/agents/index.md +47 -0
  170. package/docs/agents/indexes.md +35 -0
  171. package/docs/agents/install-and-sync.md +385 -0
  172. package/docs/agents/intake.md +81 -0
  173. package/docs/agents/key-changes.md +103 -0
  174. package/docs/agents/label-coverage.md +73 -0
  175. package/docs/agents/markdown-audit.md +197 -0
  176. package/docs/agents/output-shape.md +70 -0
  177. package/docs/agents/overview.md +26 -0
  178. package/docs/agents/records.md +170 -0
  179. package/docs/agents/restated.md +81 -0
  180. package/docs/agents/review-classification.md +77 -0
  181. package/docs/agents/routing.md +61 -0
  182. package/docs/agents/rule-citations.md +98 -0
  183. package/docs/agents/sandbox.md +71 -0
  184. package/docs/agents/scripting.md +149 -0
  185. package/docs/agents/sessions.md +120 -0
  186. package/docs/agents/skills-audit.md +94 -0
  187. package/docs/agents/skills-reach.md +64 -0
  188. package/docs/agents/standards-audit.md +38 -0
  189. package/docs/agents/state-scoped-risk.md +105 -0
  190. package/docs/agents/superseded.md +85 -0
  191. package/docs/agents/targets.md +83 -0
  192. package/docs/agents/tasks.md +200 -0
  193. package/docs/agents/teach.md +158 -0
  194. package/docs/agents/test-order.md +56 -0
  195. package/docs/agents/worktrees.md +62 -0
  196. package/docs/ai-workflow.md +317 -0
  197. package/docs/index.md +23 -0
  198. package/docs/operating-model.md +223 -0
  199. package/docs/target-projects.md +258 -0
  200. package/docs/visual-design-workflow.md +151 -0
  201. package/docs/zshrc-aliases.md +65 -0
  202. package/governance/rules/ci/700-ci-workflow.md +44 -0
  203. package/governance/rules/claude/500-prose.md +15 -0
  204. package/governance/rules/claude/501-markdown.md +14 -0
  205. package/governance/rules/claude/510-context.md +28 -0
  206. package/governance/rules/claude/511-indexes.md +14 -0
  207. package/governance/rules/claude/520-wireframes.md +12 -0
  208. package/governance/rules/claude/530-requirements.md +11 -0
  209. package/governance/rules/claude/540-architecture.md +11 -0
  210. package/governance/rules/claude/550-design.md +11 -0
  211. package/governance/rules/claude/555-tasks.md +12 -0
  212. package/governance/rules/claude/556-groundwork.md +11 -0
  213. package/governance/rules/claude/557-intake.md +11 -0
  214. package/governance/rules/claude/558-plan.md +22 -0
  215. package/governance/rules/claude/559-memory.md +11 -0
  216. package/governance/rules/claude/560-diagrams.md +18 -0
  217. package/governance/rules/claude/561-teach.md +13 -0
  218. package/governance/rules/claude/562-session.md +15 -0
  219. package/governance/rules/claude/570-skill.md +24 -0
  220. package/governance/rules/claude/575-hooks.md +17 -0
  221. package/governance/rules/claude/576-settings.md +14 -0
  222. package/governance/rules/claude/580-readme.md +11 -0
  223. package/governance/rules/claude/590-rule-authoring.md +12 -0
  224. package/governance/rules/claude/591-standard-authoring.md +12 -0
  225. package/governance/rules/claude/592-claude-md.md +19 -0
  226. package/governance/rules/core/000-constitution.md +30 -0
  227. package/governance/rules/core/005-behavior.md +27 -0
  228. package/governance/rules/core/010-testing.md +35 -0
  229. package/governance/rules/core/015-output.md +20 -0
  230. package/governance/rules/core/020-concurrency.md +22 -0
  231. package/governance/rules/core/025-indexes.md +9 -0
  232. package/governance/rules/core/030-error-handling.md +31 -0
  233. package/governance/rules/core/035-tasks.md +13 -0
  234. package/governance/rules/core/040-performance.md +20 -0
  235. package/governance/rules/core/045-memory.md +12 -0
  236. package/governance/rules/core/050-logging.md +20 -0
  237. package/governance/rules/core/055-scratch.md +9 -0
  238. package/governance/rules/core/060-naming.md +19 -0
  239. package/governance/rules/core/065-spelling.md +19 -0
  240. package/governance/rules/core/070-planning.md +18 -0
  241. package/governance/rules/core/075-dependencies.md +25 -0
  242. package/governance/rules/core/080-config-comments.md +22 -0
  243. package/governance/rules/core/085-worktrees.md +17 -0
  244. package/governance/rules/core/087-git.md +11 -0
  245. package/governance/rules/core/090-code-comments.md +39 -0
  246. package/governance/rules/framework/200-react.md +51 -0
  247. package/governance/rules/framework/210-astro.md +41 -0
  248. package/governance/rules/framework/220-fastapi.md +43 -0
  249. package/governance/rules/framework/230-nextjs.md +48 -0
  250. package/governance/rules/framework/250-tailwind.md +32 -0
  251. package/governance/rules/framework/260-shadcn.md +34 -0
  252. package/governance/rules/lang/100-typescript.md +40 -0
  253. package/governance/rules/lang/110-python.md +42 -0
  254. package/governance/rules/lang/120-bash.md +19 -0
  255. package/governance/rules/lib/300-testing-ts.md +39 -0
  256. package/governance/rules/lib/305-e2e-reliability.md +34 -0
  257. package/governance/rules/lib/306-test-scope.md +25 -0
  258. package/governance/rules/lib/310-zod.md +25 -0
  259. package/governance/rules/lib/320-tanstack-query.md +32 -0
  260. package/governance/rules/lib/330-testing-py.md +44 -0
  261. package/governance/rules/lib/340-pydantic.md +38 -0
  262. package/governance/rules/lib/350-security-web.md +32 -0
  263. package/governance/rules/lib/360-security-server.md +39 -0
  264. package/governance/rules/lib/370-database.md +35 -0
  265. package/governance/rules/snippets/505-at-references.md +9 -0
  266. package/governance/rules/ui/400-ui.md +36 -0
  267. package/governance/rules/ui/410-a11y.md +48 -0
  268. package/governance/rules/ui/420-forms.md +36 -0
  269. package/governance/rules/ui/430-ux-completeness.md +65 -0
  270. package/governance/rules/ui/440-surface-capture.md +34 -0
  271. package/governance/rules/ui/450-link-behavior.md +19 -0
  272. package/governance/stacks/astro.toml +2 -0
  273. package/governance/stacks/base.toml +8 -0
  274. package/governance/stacks/node-server.toml +2 -0
  275. package/governance/stacks/node.toml +2 -0
  276. package/governance/stacks/python-fastapi.toml +2 -0
  277. package/governance/stacks/python.toml +2 -0
  278. package/governance/stacks/react.toml +2 -0
  279. package/package.json +69 -0
  280. package/scripts/config.sh +11 -0
  281. package/scripts/core/bootstrap.sh +81 -0
  282. package/scripts/core/check-color-source.sh +41 -0
  283. package/scripts/core/check-ignore-parity.sh +162 -0
  284. package/scripts/core/check-plugin-boundary.sh +45 -0
  285. package/scripts/core/check-seed-independence.sh +59 -0
  286. package/scripts/core/check-skill-paths.sh +24 -0
  287. package/scripts/core/clean.sh +36 -0
  288. package/scripts/core/install-check.sh +101 -0
  289. package/scripts/core/list-seed-roots.sh +18 -0
  290. package/scripts/core/regen-claude-copies.sh +10 -0
  291. package/scripts/core/regen-hero.sh +217 -0
  292. package/scripts/core/regen-indexes.sh +10 -0
  293. package/scripts/core/regen-tooling-paths.sh +61 -0
  294. package/scripts/core/repair-bare-flag.sh +19 -0
  295. package/scripts/core/snapshot.sh +134 -0
  296. package/scripts/core/update.sh +35 -0
  297. package/scripts/docs/list.sh +165 -0
  298. package/scripts/lib/frontmatter.sh +30 -0
  299. package/scripts/lib/gov.sh +14 -0
  300. package/scripts/lib/sandbox-fixtures.sh +191 -0
  301. package/scripts/lib/sandbox-git.sh +125 -0
  302. package/scripts/lib/sandbox-path.sh +206 -0
  303. package/scripts/lib/tooling.sh +35 -0
  304. package/scripts/lib/ui.sh +266 -0
  305. package/scripts/lib/worktree.sh +20 -0
  306. package/scripts/manage-sandbox.sh +466 -0
  307. package/scripts/snippets/create.sh +156 -0
  308. package/scripts/standards/list.sh +115 -0
  309. package/scripts/tooling/create.sh +109 -0
  310. package/scripts/tooling/verify.sh +179 -0
  311. package/snippets/align.md +12 -0
  312. package/snippets/claude/decision-memo.md +39 -0
  313. package/snippets/claude/feature-recap.md +19 -0
  314. package/snippets/claude/figma-steps.md +24 -0
  315. package/snippets/compact-summary.md +5 -0
  316. package/snippets/decision-help.md +6 -0
  317. package/snippets/meta-prompt.md +14 -0
  318. package/snippets/research-prompt.md +7 -0
  319. package/snippets/session-notes.md +11 -0
  320. package/snippets/snippets.toml +5 -0
  321. package/snippets/step-by-step.md +10 -0
  322. package/snippets/web-research.md +21 -0
  323. package/src/audits/baseline.ts +201 -0
  324. package/src/audits/catalog.ts +876 -0
  325. package/src/audits/run.ts +204 -0
  326. package/src/autoship/classify.ts +75 -0
  327. package/src/autoship/paths.ts +51 -0
  328. package/src/binary.ts +16 -0
  329. package/src/browser/engine.ts +40 -0
  330. package/src/census/count.ts +113 -0
  331. package/src/claude/cases/all.ts +24 -0
  332. package/src/claude/cases/authoring.ts +53 -0
  333. package/src/claude/cases/claude-workflow.ts +158 -0
  334. package/src/claude/cases/git.ts +44 -0
  335. package/src/claude/cases/misc.ts +27 -0
  336. package/src/claude/cases/setup.ts +94 -0
  337. package/src/claude/gitignore.ts +51 -0
  338. package/src/claude/routing.ts +283 -0
  339. package/src/claude/seeds-list.ts +47 -0
  340. package/src/claude/seeds.ts +150 -0
  341. package/src/claude/settings.ts +151 -0
  342. package/src/claude/skills-audit.ts +228 -0
  343. package/src/claude/skills-drift.ts +156 -0
  344. package/src/claude/skills-list.ts +99 -0
  345. package/src/claude/skills-rank.ts +320 -0
  346. package/src/claude/skills-reach.ts +227 -0
  347. package/src/cli-run.ts +43 -0
  348. package/src/cli.ts +200 -0
  349. package/src/commands/audits.ts +350 -0
  350. package/src/commands/autoship.ts +129 -0
  351. package/src/commands/capture.ts +133 -0
  352. package/src/commands/census.ts +105 -0
  353. package/src/commands/claude.ts +1286 -0
  354. package/src/commands/comments.ts +240 -0
  355. package/src/commands/context.ts +857 -0
  356. package/src/commands/demo.ts +389 -0
  357. package/src/commands/deps.ts +173 -0
  358. package/src/commands/design.ts +36 -0
  359. package/src/commands/docs.ts +60 -0
  360. package/src/commands/feedback-format.ts +23 -0
  361. package/src/commands/feedback.ts +112 -0
  362. package/src/commands/gate.ts +189 -0
  363. package/src/commands/gov.ts +1265 -0
  364. package/src/commands/indexes.ts +184 -0
  365. package/src/commands/init.ts +113 -0
  366. package/src/commands/intake.ts +406 -0
  367. package/src/commands/inventory.ts +256 -0
  368. package/src/commands/labels.ts +361 -0
  369. package/src/commands/markdown.ts +544 -0
  370. package/src/commands/migrate.ts +175 -0
  371. package/src/commands/pass-through.ts +39 -0
  372. package/src/commands/pr.ts +411 -0
  373. package/src/commands/records.ts +728 -0
  374. package/src/commands/sandbox.ts +468 -0
  375. package/src/commands/secrets.ts +132 -0
  376. package/src/commands/serve.ts +159 -0
  377. package/src/commands/sessions.ts +408 -0
  378. package/src/commands/slides.ts +126 -0
  379. package/src/commands/snippets.ts +84 -0
  380. package/src/commands/standards.ts +247 -0
  381. package/src/commands/sync.ts +428 -0
  382. package/src/commands/targets.ts +319 -0
  383. package/src/commands/tasks.ts +743 -0
  384. package/src/commands/teach.ts +786 -0
  385. package/src/commands/tooling.ts +573 -0
  386. package/src/commands/transcripts.ts +44 -0
  387. package/src/commands/upgrade.ts +231 -0
  388. package/src/commands/wiki.ts +100 -0
  389. package/src/commands/worktrees.ts +191 -0
  390. package/src/comments/scan.ts +338 -0
  391. package/src/comments/trend.ts +207 -0
  392. package/src/comments/vocabulary.ts +85 -0
  393. package/src/context/architecture.ts +364 -0
  394. package/src/context/audit.ts +790 -0
  395. package/src/context/citations.ts +196 -0
  396. package/src/context/folders.ts +186 -0
  397. package/src/context/gate.ts +57 -0
  398. package/src/context/index-drift.ts +64 -0
  399. package/src/context/narration.ts +99 -0
  400. package/src/copy.ts +30 -0
  401. package/src/counts/catalogs.ts +96 -0
  402. package/src/counts/numbers.ts +79 -0
  403. package/src/counts/scan.ts +314 -0
  404. package/src/demo/beats.ts +135 -0
  405. package/src/demo/compile.ts +326 -0
  406. package/src/demo/container.ts +63 -0
  407. package/src/demo/cursors.ts +55 -0
  408. package/src/demo/drive.ts +357 -0
  409. package/src/demo/pointer.ts +178 -0
  410. package/src/demo/theme.ts +112 -0
  411. package/src/deps/audit.ts +153 -0
  412. package/src/design/parse.ts +116 -0
  413. package/src/design/render.ts +249 -0
  414. package/src/docs/read.ts +77 -0
  415. package/src/exec.ts +16 -0
  416. package/src/exempt-marker.ts +43 -0
  417. package/src/frontmatter.ts +13 -0
  418. package/src/gate/measures.ts +682 -0
  419. package/src/gate/sequencer.ts +386 -0
  420. package/src/gate/stages.ts +412 -0
  421. package/src/git-env.ts +36 -0
  422. package/src/git-files.ts +105 -0
  423. package/src/git-ignore.ts +46 -0
  424. package/src/github-format.ts +13 -0
  425. package/src/github.ts +24 -0
  426. package/src/gov/adapter.ts +103 -0
  427. package/src/gov/citations.ts +514 -0
  428. package/src/gov/consumed.ts +129 -0
  429. package/src/gov/install.ts +132 -0
  430. package/src/gov/list.ts +106 -0
  431. package/src/gov/payload.ts +39 -0
  432. package/src/gov/restated.ts +814 -0
  433. package/src/gov/stacks.ts +205 -0
  434. package/src/gov/superseded.ts +415 -0
  435. package/src/gov/test-order.ts +407 -0
  436. package/src/indexes/frontmatter.ts +46 -0
  437. package/src/indexes/regen.ts +84 -0
  438. package/src/indexes/render.ts +201 -0
  439. package/src/indexes/walk.ts +83 -0
  440. package/src/init/flags.ts +60 -0
  441. package/src/init/plan.ts +114 -0
  442. package/src/init/run.ts +46 -0
  443. package/src/init/steps.ts +77 -0
  444. package/src/intake/folder.ts +320 -0
  445. package/src/intake/items.ts +174 -0
  446. package/src/inventory/config.ts +117 -0
  447. package/src/inventory/group.ts +76 -0
  448. package/src/inventory/subjects.ts +114 -0
  449. package/src/inventory/walk.ts +129 -0
  450. package/src/labels/audit.ts +82 -0
  451. package/src/labels/coverage.ts +79 -0
  452. package/src/labels/map.ts +101 -0
  453. package/src/labels/phase.ts +95 -0
  454. package/src/markdown/bans.ts +94 -0
  455. package/src/markdown/files.ts +102 -0
  456. package/src/markdown/gate.ts +28 -0
  457. package/src/markdown/scan.ts +295 -0
  458. package/src/markdown/structure.ts +730 -0
  459. package/src/migrate/apply.ts +115 -0
  460. package/src/migrate/plan.ts +103 -0
  461. package/src/migrate/rename.ts +183 -0
  462. package/src/pr/bijection.ts +145 -0
  463. package/src/pr/paths.ts +335 -0
  464. package/src/process/harness.ts +167 -0
  465. package/src/project-root.ts +19 -0
  466. package/src/records/backup.ts +455 -0
  467. package/src/records/migrate.ts +78 -0
  468. package/src/records/size.ts +260 -0
  469. package/src/records/validate.ts +1162 -0
  470. package/src/sandbox/census.ts +228 -0
  471. package/src/sandbox/coverage.ts +115 -0
  472. package/src/sandbox/expect.ts +629 -0
  473. package/src/sandbox/tree.ts +47 -0
  474. package/src/secrets/marker.ts +30 -0
  475. package/src/secrets/patterns.ts +142 -0
  476. package/src/secrets/scan.ts +123 -0
  477. package/src/secrets/shipped.ts +111 -0
  478. package/src/seed-marker.ts +74 -0
  479. package/src/serve/static.ts +322 -0
  480. package/src/sessions/claim.ts +85 -0
  481. package/src/sessions/live.ts +79 -0
  482. package/src/sessions/registry.ts +137 -0
  483. package/src/sessions/resolve.ts +333 -0
  484. package/src/slides/layouts.ts +391 -0
  485. package/src/slides/open.ts +18 -0
  486. package/src/slides/parse.ts +84 -0
  487. package/src/slides/render.ts +88 -0
  488. package/src/slides/styles.ts +44 -0
  489. package/src/snippets/categories.ts +66 -0
  490. package/src/snippets/list.ts +32 -0
  491. package/src/snippets/presets.ts +50 -0
  492. package/src/standards/audit.ts +132 -0
  493. package/src/standards/read.ts +100 -0
  494. package/src/sync/check.ts +692 -0
  495. package/src/sync/engine.ts +576 -0
  496. package/src/sync/git.ts +225 -0
  497. package/src/sync/history.ts +123 -0
  498. package/src/sync/layout.ts +140 -0
  499. package/src/sync/reverse.ts +268 -0
  500. package/src/sync/seeds-report.ts +126 -0
  501. package/src/sync/stamp.ts +358 -0
  502. package/src/sync/target.ts +70 -0
  503. package/src/sync/workflow.ts +200 -0
  504. package/src/target.ts +43 -0
  505. package/src/targets/pulls.ts +250 -0
  506. package/src/targets/registry.ts +203 -0
  507. package/src/targets/resolve.ts +145 -0
  508. package/src/targets/sweep.ts +246 -0
  509. package/src/tasks/archive.ts +506 -0
  510. package/src/tasks/record.ts +311 -0
  511. package/src/tasks/trunk.ts +89 -0
  512. package/src/tasks/validate.ts +1001 -0
  513. package/src/teach/lesson.ts +180 -0
  514. package/src/teach/workspace.ts +842 -0
  515. package/src/tooling/gitignore.ts +122 -0
  516. package/src/tooling/inject.ts +193 -0
  517. package/src/tooling/list.ts +39 -0
  518. package/src/tooling/manifest.ts +176 -0
  519. package/src/tooling/package.ts +166 -0
  520. package/src/tooling/read.ts +65 -0
  521. package/src/tooling/scan.ts +147 -0
  522. package/src/tooling/stamp.ts +44 -0
  523. package/src/transcripts/fetch.ts +156 -0
  524. package/src/transcripts/metadata.ts +54 -0
  525. package/src/transcripts/vtt.ts +114 -0
  526. package/src/ui.ts +266 -0
  527. package/src/version/compare.ts +53 -0
  528. package/src/version/installed.ts +40 -0
  529. package/src/version/manager.ts +67 -0
  530. package/src/version/skew.ts +192 -0
  531. package/src/wiki/init.ts +85 -0
  532. package/src/worktree.ts +143 -0
  533. package/src/worktrees/reclaim.ts +306 -0
  534. package/standards/architecture.md +72 -0
  535. package/standards/branch.md +59 -0
  536. package/standards/commit.md +72 -0
  537. package/standards/context.md +151 -0
  538. package/standards/design.md +93 -0
  539. package/standards/diagrams.md +152 -0
  540. package/standards/glossary.md +75 -0
  541. package/standards/groundwork.md +211 -0
  542. package/standards/index.md +36 -0
  543. package/standards/intake.md +192 -0
  544. package/standards/issue.md +94 -0
  545. package/standards/markdown.md +137 -0
  546. package/standards/memory.md +144 -0
  547. package/standards/plan.md +172 -0
  548. package/standards/pr.md +139 -0
  549. package/standards/publish.md +51 -0
  550. package/standards/readme.md +208 -0
  551. package/standards/requirements.md +70 -0
  552. package/standards/rule.md +118 -0
  553. package/standards/session.md +109 -0
  554. package/standards/skill.md +300 -0
  555. package/standards/slug.md +39 -0
  556. package/standards/snippets.md +76 -0
  557. package/standards/standard.md +170 -0
  558. package/standards/tasks.md +254 -0
  559. package/standards/teach.md +153 -0
  560. package/standards/versioning.md +71 -0
  561. package/standards/wireframes.md +113 -0
  562. package/tooling/astro/configs/astro.config.mjs +31 -0
  563. package/tooling/astro/configs/eslint.config.js +79 -0
  564. package/tooling/astro/configs/playwright.config.ts +26 -0
  565. package/tooling/astro/configs/tsconfig.json +12 -0
  566. package/tooling/astro/configs/vitest.config.ts +22 -0
  567. package/tooling/astro/manifest.toml +34 -0
  568. package/tooling/astro/reference.md +60 -0
  569. package/tooling/base/configs/.editorconfig +5 -0
  570. package/tooling/base/configs/.github/pull_request_template.md +18 -0
  571. package/tooling/base/configs/.github/workflows/verify.yml +35 -0
  572. package/tooling/base/configs/.husky/commit-msg +1 -0
  573. package/tooling/base/configs/.husky/post-merge +61 -0
  574. package/tooling/base/configs/.husky/post-rewrite +21 -0
  575. package/tooling/base/configs/.husky/pre-commit +1 -0
  576. package/tooling/base/configs/.husky/pre-push +1 -0
  577. package/tooling/base/configs/.prettierrc +12 -0
  578. package/tooling/base/configs/.shellcheckrc +1 -0
  579. package/tooling/base/configs/.vscode/extensions.json +9 -0
  580. package/tooling/base/configs/.vscode/settings.json +3 -0
  581. package/tooling/base/configs/commitlint.config.js +11 -0
  582. package/tooling/base/configs/scripts/verify.sh +64 -0
  583. package/tooling/base/manifest.toml +30 -0
  584. package/tooling/base/reference.md +98 -0
  585. package/tooling/base/seeds/.claude/context/ci.md +33 -0
  586. package/tooling/base/seeds/.claude/context/development.md +37 -0
  587. package/tooling/base/seeds/.claude/context/index.md +11 -0
  588. package/tooling/base/seeds/.cspell/project-terms.txt +0 -0
  589. package/tooling/base/seeds/.cspell/tech-stack.txt +19 -0
  590. package/tooling/base/seeds/.lintstagedrc +8 -0
  591. package/tooling/base/seeds/.prettierignore +0 -0
  592. package/tooling/base/seeds/cspell.json +20 -0
  593. package/tooling/claude/manifest.toml +14 -0
  594. package/tooling/claude/reference.md +79 -0
  595. package/tooling/claude/seeds/.claude/ARCHITECTURE.md +13 -0
  596. package/tooling/claude/seeds/.claude/DESIGN.md +62 -0
  597. package/tooling/claude/seeds/.claude/REQUIREMENTS.md +18 -0
  598. package/tooling/claude/seeds/.claude/diagrams/index.md +8 -0
  599. package/tooling/claude/seeds/.claude/hooks/index-reminder.sh +50 -0
  600. package/tooling/claude/seeds/.claude/hooks/memory-index.sh +68 -0
  601. package/tooling/claude/seeds/.claude/hooks/path-form.sh +57 -0
  602. package/tooling/claude/seeds/.claude/hooks/scratch-guard.sh +52 -0
  603. package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +86 -0
  604. package/tooling/claude/seeds/.claude/hooks/tasks-index.sh +71 -0
  605. package/tooling/claude/seeds/.claude/memory/index.md +8 -0
  606. package/tooling/claude/seeds/.claude/settings.json +47 -0
  607. package/tooling/claude/seeds/.claude/tasks/index.md +8 -0
  608. package/tooling/claude/seeds/.claude/wireframes/index.md +8 -0
  609. package/tooling/claude/seeds/CLAUDE.md +29 -0
  610. package/tooling/claude/user/settings.template.json +10 -0
  611. package/tooling/claude/user/statusline-command.sh +53 -0
  612. package/tooling/python/configs/.coveragerc +14 -0
  613. package/tooling/python/configs/.python-version +1 -0
  614. package/tooling/python/configs/mypy.ini +6 -0
  615. package/tooling/python/configs/pytest.ini +4 -0
  616. package/tooling/python/configs/ruff.toml +15 -0
  617. package/tooling/python/configs/scripts/verify.sh +77 -0
  618. package/tooling/python/manifest.toml +16 -0
  619. package/tooling/python/reference.md +66 -0
  620. package/tooling/python/seeds/.cspell/tech-stack.txt +19 -0
  621. package/tooling/python/seeds/tests/test_smoke.py +2 -0
  622. package/tooling/vite-react/configs/playwright.config.ts +26 -0
  623. package/tooling/vite-react/configs/tsconfig.json +35 -0
  624. package/tooling/vite-react/configs/vite.config.ts +24 -0
  625. package/tooling/vite-react/configs/vitest.config.ts +26 -0
  626. package/tooling/vite-react/manifest.toml +23 -0
  627. package/tooling/vite-react/reference.md +55 -0
  628. package/tooling/vite-react/seeds/.cspell/project-terms.txt +1 -0
  629. package/tooling/vite-react/seeds/.cspell/tech-stack.txt +1 -0
  630. package/tooling/web/configs/.github/workflows/verify.yml +134 -0
  631. package/tooling/web/configs/.vscode/extensions.json +13 -0
  632. package/tooling/web/configs/.vscode/settings.json +10 -0
  633. package/tooling/web/configs/e2e/home.spec.ts +6 -0
  634. package/tooling/web/configs/e2e/screenshot.ts +53 -0
  635. package/tooling/web/configs/eslint.config.js +82 -0
  636. package/tooling/web/configs/scripts/screenshot.sh +28 -0
  637. package/tooling/web/configs/scripts/verify.sh +80 -0
  638. package/tooling/web/configs/scripts/worktree-port.sh +74 -0
  639. package/tooling/web/configs/src/test/setup.ts +8 -0
  640. package/tooling/web/manifest.toml +58 -0
  641. package/tooling/web/reference.md +115 -0
  642. package/tooling/web/seeds/.cspell/tech-stack.txt +18 -0
  643. package/tsconfig.json +14 -0
@@ -0,0 +1,466 @@
1
+ #!/usr/bin/env bash
2
+ set -e
3
+ set -o pipefail
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "$(readlink -f "${BASH_SOURCE[0]}")")" && pwd)"
6
+ PROJECT_ROOT="$(dirname "$SCRIPT_DIR")"
7
+ export PROJECT_ROOT
8
+
9
+ source "$PROJECT_ROOT/scripts/config.sh"
10
+ source "$PROJECT_ROOT/scripts/lib/ui.sh"
11
+ source "$PROJECT_ROOT/scripts/lib/sandbox-path.sh"
12
+ source "$PROJECT_ROOT/scripts/lib/sandbox-git.sh"
13
+ source "$PROJECT_ROOT/scripts/lib/sandbox-fixtures.sh"
14
+
15
+ # Without this, git falls back to a terminal prompt when no helper supplies a
16
+ # credential, and an unauthenticated run blocks on /dev/tty instead of failing.
17
+ # The harness must never require a TTY.
18
+ export GIT_TERMINAL_PROMPT=0
19
+
20
+ show_help() {
21
+ echo -e "${GREY}┌${NC}"
22
+ echo -e "${GREY}├${NC} ${WHITE}Usage:${NC} canon sandbox [cat:cmd]"
23
+ echo -e "${GREY}│${NC}"
24
+ echo -e "${GREY}│${NC} ${WHITE}Arguments:${NC}"
25
+ echo -e "${GREY}│${NC} cat:cmd ${GREY}# Scenario to provision (e.g. git:commit)${NC}"
26
+ echo -e "${GREY}│${NC}"
27
+ echo -e "${GREY}│${NC} ${WHITE}Commands:${NC}"
28
+ echo -e "${GREY}│${NC} reset ${GREY}# Reset sandbox to baseline${NC}"
29
+ echo -e "${GREY}│${NC} clean ${GREY}# Wipe the sandbox${NC}"
30
+ echo -e "${GREY}│${NC}"
31
+ echo -e "${GREY}│${NC} ${WHITE}Options:${NC}"
32
+ echo -e "${GREY}│${NC} -h, --help ${GREY}# Show this help message${NC}"
33
+ echo -e "${GREY}│${NC}"
34
+ echo -e "${GREY}│${NC} ${WHITE}Examples:${NC}"
35
+ echo -e "${GREY}│${NC} canon sandbox"
36
+ echo -e "${GREY}│${NC} canon sandbox git:commit"
37
+ echo -e "${GREY}│${NC} canon sandbox reset"
38
+ echo -e "${GREY}│${NC} canon sandbox clean"
39
+ echo -e "${GREY}└${NC}"
40
+ exit 0
41
+ }
42
+
43
+ ANCHOR_FIXTURE_DIR="$PROJECT_ROOT/scripts/sandbox/fixtures/anchor/create"
44
+
45
+ # Where an anchor scenario's tree comes from and where its remote points are two
46
+ # concerns, and only the remote needs a network. Taking the tree from a fixture
47
+ # stops an arm provisioning from whatever the previous arm force-pushed, which is
48
+ # what made two identical sweeps of the sixteen arms disagree on eleven.
49
+ stage_anchor_tree() {
50
+ # The nine anchor scenarios configure a real remote from their own stage_setup,
51
+ # and sandbox_anchor_url runs inside a command substitution there, where
52
+ # log_error would exit only the subshell and leave an empty remote behind. The
53
+ # guard has to fire here, in the main shell, before any of them run.
54
+ require_sandbox_anchor_config
55
+
56
+ log_step "Staging anchor tree from fixture"
57
+
58
+ assert_fixtures_suffixed "$ANCHOR_FIXTURE_DIR"
59
+ if [ "$(count_fixture_files "$ANCHOR_FIXTURE_DIR")" -eq 0 ]; then
60
+ log_error "Anchor fixture provisions nothing: $ANCHOR_FIXTURE_DIR"
61
+ fi
62
+
63
+ if [ -d "$SANDBOX" ]; then
64
+ rm -rf "$SANDBOX"
65
+ fi
66
+ mkdir -p "$SANDBOX"
67
+
68
+ (
69
+ cd "$SANDBOX"
70
+ create_from_fixtures "$ANCHOR_FIXTURE_DIR"
71
+ git init >/dev/null
72
+ git add .
73
+ git commit -m "feat(sandbox): initial sandbox setup from anchor" --no-verify >/dev/null
74
+ )
75
+ log_info "Anchor tree staged from fixture, remote stays $ANCHOR_REPO"
76
+ }
77
+
78
+ select_sandbox_category() {
79
+ local categories=()
80
+ if ls -d "$SANDBOX_DIR"/*/ >/dev/null 2>&1; then
81
+ # Twin of FIXTURES_DIR in src/commands/sandbox.ts. The exec boundary rules out
82
+ # a shared constant, so a new exclusion has to land on both sides.
83
+ mapfile -t categories < <(find "$SANDBOX_DIR" -mindepth 1 -maxdepth 1 -type d -not -name fixtures -exec basename {} \; | sort)
84
+ fi
85
+
86
+ if [ ${#categories[@]} -eq 0 ]; then
87
+ log_error "No sandbox categories found in $SANDBOX_DIR"
88
+ fi
89
+
90
+ select_option "Select category:" "${categories[@]}"
91
+ _CATEGORY=$SELECTED_OPTION
92
+ }
93
+
94
+ select_sandbox_command() {
95
+ local commands=()
96
+ if ls "$SANDBOX_DIR/$_CATEGORY/"*.sh >/dev/null 2>&1; then
97
+ mapfile -t commands < <(find "$SANDBOX_DIR/$_CATEGORY" -maxdepth 1 -name '*.sh' -exec basename {} .sh \; | sort)
98
+ fi
99
+
100
+ if [ ${#commands[@]} -eq 0 ]; then
101
+ log_error "No sandbox scripts found in $_CATEGORY"
102
+ fi
103
+
104
+ select_option "Select command:" "${commands[@]}"
105
+ _COMMAND=$SELECTED_OPTION
106
+ }
107
+
108
+ prompt_for_category_and_command() {
109
+ select_sandbox_category
110
+ select_sandbox_command
111
+ }
112
+
113
+ parse_command_argument() {
114
+ local input_arg="$1"
115
+
116
+ if [[ "$input_arg" != *":"* ]]; then
117
+ log_error "Invalid format. Use <category>:<command>, 'reset', 'clean', or --help"
118
+ fi
119
+ IFS=':' read -r _CATEGORY _COMMAND <<<"$input_arg"
120
+ }
121
+
122
+ resolve_command_and_category() {
123
+ local input_arg="$1"
124
+ if [ -z "$input_arg" ]; then
125
+ prompt_for_category_and_command
126
+ else
127
+ parse_command_argument "$input_arg"
128
+ fi
129
+ }
130
+
131
+ validate_environment() {
132
+ local current_category="$1"
133
+ local current_command="$2"
134
+
135
+ if [ ! -d "$SANDBOX_DIR" ]; then
136
+ log_error "Sandbox directory not found at: $SANDBOX_DIR"
137
+ fi
138
+
139
+ if [[ "$PWD" == "$SANDBOX" || "$PWD" == "$SANDBOX"/* ]]; then
140
+ log_warn "Detected execution inside the sandbox. Switching to project root..."
141
+ cd "$PROJECT_ROOT" || log_error "Failed to switch to project root."
142
+ fi
143
+ }
144
+
145
+ load_sandbox_script() {
146
+ local current_category="$1"
147
+ local current_command="$2"
148
+
149
+ local sandbox_file="$SANDBOX_DIR/$current_category/$current_command.sh"
150
+
151
+ if [ ! -f "$sandbox_file" ]; then
152
+ log_error "Sandbox script not found: $current_category/$current_command"
153
+ fi
154
+
155
+ # shellcheck source=/dev/null
156
+ source "$sandbox_file"
157
+ }
158
+
159
+ init_empty_sandbox() {
160
+ if [ -d "$SANDBOX" ]; then
161
+ rm -rf "$SANDBOX"
162
+ fi
163
+ mkdir -p "$SANDBOX"
164
+
165
+ cat <<EOF >"$SANDBOX/.gitignore"
166
+ .claude/.tmp/
167
+ node_modules
168
+ EOF
169
+ (
170
+ cd "$SANDBOX"
171
+ git init >/dev/null
172
+ git add .gitignore >/dev/null 2>/dev/null
173
+ git commit -m "feat(sandbox): initial empty sandbox setup" --no-verify >/dev/null
174
+ )
175
+ }
176
+
177
+ provision_sandbox() {
178
+ log_step "Provisioning $1:$2"
179
+
180
+ if [[ "$(type -t use_anchor)" == "function" ]]; then
181
+ use_anchor
182
+ stage_anchor_tree
183
+ else
184
+ init_empty_sandbox
185
+ fi
186
+
187
+ # Scoped to the throwaway sandbox repo so the operator's global git config is
188
+ # never written. Covers both the scenario pushes and the ones the agent makes
189
+ # itself once it is running inside the sandbox.
190
+ (cd "$SANDBOX" && configure_sandbox_git_credentials)
191
+ }
192
+
193
+ # Runs the real installer rather than copying the source tree. The two copies
194
+ # these replaced each reimplemented an installer's selection rules, so a change
195
+ # to what install produces left the sandbox provisioning the old shape and no
196
+ # scenario could observe the difference.
197
+ run_sandbox_install() {
198
+ local label="$1"
199
+ shift
200
+
201
+ local install_log
202
+ install_log="$(mktemp)"
203
+
204
+ # The installer's own frame would bury the provisioning timeline, so it stays
205
+ # captured unless it fails, where it is the only thing naming the cause.
206
+ if ! CANON_NON_INTERACTIVE=1 bun "$PROJECT_ROOT/src/cli.ts" "$@" \
207
+ >/dev/null 2>"$install_log"; then
208
+ cat "$install_log" >&2
209
+ rm -f "$install_log"
210
+ log_error "Could not install $label into the sandbox."
211
+ fi
212
+
213
+ rm -f "$install_log"
214
+ }
215
+
216
+ # The stack decides which rules land. `base` carries the language-agnostic core,
217
+ # which is what a scenario asserting on rule behavior reads. A scenario needing a
218
+ # framework's rules overrides the variable in `use_config`.
219
+ inject_gov_rules() {
220
+ [ ! -d "$PROJECT_ROOT/governance/rules" ] && return
221
+
222
+ run_sandbox_install "gov rules" gov install "${SANDBOX_GOV_STACK:-base}" "$SANDBOX"
223
+ }
224
+
225
+ inject_seeds() {
226
+ local seeds_source="$PROJECT_ROOT/tooling/claude/seeds"
227
+ if [ -d "$seeds_source" ]; then
228
+ cp -r "$seeds_source/." "$SANDBOX/"
229
+ fi
230
+ }
231
+
232
+ commit_environment_setup() {
233
+ (
234
+ cd "$SANDBOX"
235
+ git add .
236
+ if ! git diff --cached --quiet; then
237
+ git commit -m "chore(sandbox): initial environment setup" --no-verify >/dev/null
238
+ fi
239
+ )
240
+ }
241
+
242
+ # No standards injection. The corpus installs into no target, so a sandbox
243
+ # without one is the shape a scaffolded project has, and a scenario driving a
244
+ # skill that reads a standard exercises the `canon standards <name>` path a real
245
+ # project takes.
246
+ setup_sandbox_assets() {
247
+ [ -n "$SANDBOX_INJECT_SEEDS" ] && inject_seeds
248
+ [ -n "$SANDBOX_INJECT_GOV" ] && inject_gov_rules
249
+ commit_environment_setup
250
+ }
251
+
252
+ initialize_sandbox_environment() {
253
+ local current_category="$1"
254
+ local current_command="$2"
255
+
256
+ load_sandbox_script "$current_category" "$current_command"
257
+ [[ "$(type -t use_config)" == "function" ]] && use_config
258
+ validate_environment "$current_category" "$current_command"
259
+ provision_sandbox "$current_category" "$current_command"
260
+ setup_sandbox_assets
261
+ }
262
+
263
+ commit_sandbox_changes() {
264
+ if [ -z "$SANDBOX_SKIP_AUTO_COMMIT" ]; then
265
+ log_step "Staging environment changes"
266
+ (
267
+ cd "$SANDBOX"
268
+ git add . >/dev/null 2>/dev/null
269
+ git commit -m 'chore(sandbox): apply scenario specific setup' --no-verify >/dev/null
270
+ )
271
+ log_info "Git state clean after setup"
272
+ else
273
+ log_info "Skipping auto-commit"
274
+ fi
275
+ }
276
+
277
+ tag_sandbox_baseline() {
278
+ (
279
+ cd "$SANDBOX"
280
+ git update-ref refs/sandbox/baseline HEAD >/dev/null 2>&1
281
+ git write-tree | xargs -I {} git update-ref refs/sandbox/baseline-index {} >/dev/null 2>&1
282
+ )
283
+ }
284
+
285
+ inject_changed_skills() {
286
+ local changed untracked
287
+ changed=$(git -C "$PROJECT_ROOT" diff main --name-only -- 'claude/skills/**/SKILL.md' 2>/dev/null)
288
+ untracked=$(git -C "$PROJECT_ROOT" ls-files --others --exclude-standard -- 'claude/skills/**/SKILL.md' 2>/dev/null)
289
+
290
+ local combined
291
+ combined=$(printf '%s\n%s\n' "$changed" "$untracked" | awk 'NF && !seen[$0]++')
292
+
293
+ [ -z "$combined" ] && return
294
+
295
+ while IFS= read -r skill_path; do
296
+ # The diff against main lists a deleted skill alongside a changed one, and
297
+ # there is nothing left to inject for a name this branch removed.
298
+ [ -f "$PROJECT_ROOT/$skill_path" ] || continue
299
+
300
+ local skill_name
301
+ skill_name=$(basename "$(dirname "$skill_path")")
302
+ local target_dir="$SANDBOX/.claude/skills/$skill_name"
303
+ mkdir -p "$target_dir"
304
+ cp "$PROJECT_ROOT/$skill_path" "$target_dir/SKILL.md"
305
+ log_info "Injected dev skill: $skill_name"
306
+ done <<<"$combined"
307
+ }
308
+
309
+ execute_sandbox_and_commit() {
310
+ pushd "$SANDBOX" >/dev/null
311
+ stage_setup
312
+ popd >/dev/null
313
+
314
+ inject_changed_skills
315
+ commit_sandbox_changes
316
+ tag_sandbox_baseline
317
+ }
318
+
319
+ finalize_sandbox_run() {
320
+ local GREEN RED YELLOW WHITE GREY NC
321
+ set_palette 2
322
+ trap - EXIT
323
+ close_timeline
324
+ echo "" >&2
325
+ echo -e "${GREEN}✓ Sandbox Ready${NC}" >&2
326
+ }
327
+
328
+ cmd_clean() {
329
+ local GREEN RED YELLOW WHITE GREY NC
330
+ set_palette 2
331
+ log_step "Removing sandbox"
332
+ rm -rf "$SANDBOX"
333
+ log_rem "$SANDBOX"
334
+ trap - EXIT
335
+ close_timeline
336
+ echo "" >&2
337
+ echo -e "${GREEN}✓ Sandbox clean${NC}" >&2
338
+ }
339
+
340
+ reset_sandbox() {
341
+ local GREEN RED YELLOW WHITE GREY NC
342
+ set_palette 2
343
+ if [ ! -d "$SANDBOX/.git" ]; then
344
+ log_error "No sandbox found. Run \`canon sandbox\` first."
345
+ fi
346
+
347
+ log_step "Sandbox state"
348
+
349
+ local has_baseline=0
350
+ (cd "$SANDBOX" && git rev-parse refs/sandbox/baseline >/dev/null 2>&1) && has_baseline=1
351
+
352
+ if [ "$has_baseline" -eq 0 ]; then
353
+ log_error "No baseline found. Re-provision with \`canon sandbox <cat>:<cmd>\`."
354
+ fi
355
+
356
+ local is_dirty=0
357
+ (
358
+ cd "$SANDBOX"
359
+ if [ "$(git rev-parse HEAD)" != "$(git rev-parse refs/sandbox/baseline)" ]; then
360
+ exit 1
361
+ fi
362
+ local current_index baseline_index
363
+ current_index=$(git write-tree)
364
+ baseline_index=$(git rev-parse refs/sandbox/baseline-index 2>/dev/null || echo "")
365
+ if [ -n "$baseline_index" ] && [ "$current_index" != "$baseline_index" ]; then
366
+ exit 1
367
+ fi
368
+ if ! git diff --quiet 2>/dev/null; then
369
+ exit 1
370
+ fi
371
+ if [ -n "$(git ls-files --others --exclude-standard 2>/dev/null)" ]; then
372
+ exit 1
373
+ fi
374
+ ) || is_dirty=1
375
+
376
+ if [ "$is_dirty" -eq 0 ]; then
377
+ log_info "At baseline"
378
+ trap - EXIT
379
+ close_timeline
380
+ echo "" >&2
381
+ echo -e "${GREEN}✓ Sandbox at baseline${NC}" >&2
382
+ exit 0
383
+ fi
384
+
385
+ log_warn "Uncommitted changes detected"
386
+
387
+ select_option "Reset sandbox to initial state?" "Yes" "No"
388
+ if [ "$SELECTED_OPTION" == "No" ]; then
389
+ log_warn "Reset cancelled"
390
+ exit 0
391
+ fi
392
+
393
+ log_step "Resetting sandbox"
394
+ (
395
+ cd "$SANDBOX"
396
+ git reset --hard refs/sandbox/baseline --quiet
397
+ git clean -fd --quiet
398
+ local baseline_index
399
+ baseline_index=$(git rev-parse refs/sandbox/baseline-index 2>/dev/null || echo "")
400
+ if [ -n "$baseline_index" ] && [ "$baseline_index" != "$(git write-tree)" ]; then
401
+ git read-tree "$baseline_index"
402
+ git checkout-index -a -f
403
+ fi
404
+ )
405
+ log_info "Sandbox reset to baseline"
406
+
407
+ trap - EXIT
408
+ close_timeline
409
+ echo "" >&2
410
+ echo -e "${GREEN}✓ Sandbox reset complete${NC}" >&2
411
+ }
412
+
413
+ main() {
414
+ local no_header=0
415
+ if [[ "$1" == "--no-header" ]]; then
416
+ no_header=1
417
+ shift
418
+ fi
419
+
420
+ if [[ "$1" == "-h" || "$1" == "--help" ]]; then
421
+ show_help
422
+ fi
423
+
424
+ if [[ "$no_header" -eq 0 ]]; then
425
+ open_timeline "canon sandbox"
426
+ fi
427
+ trap close_timeline EXIT
428
+
429
+ if [[ "$PWD" != "$PROJECT_ROOT"* ]]; then
430
+ log_error "Context error: you must run this command from inside the toolkit repository."
431
+ fi
432
+
433
+ SANDBOX="$(resolve_sandbox_dir)"
434
+ SANDBOX_DIR="$PROJECT_ROOT/scripts/sandbox"
435
+
436
+ local unsafe
437
+ if ! unsafe="$(assert_sandbox_dir_safe "$SANDBOX" "$PROJECT_ROOT")"; then
438
+ log_error "$unsafe"
439
+ fi
440
+
441
+ if [[ "$1" == "reset" ]]; then
442
+ reset_sandbox
443
+ exit 0
444
+ fi
445
+
446
+ if [[ "$1" == "clean" ]]; then
447
+ cmd_clean
448
+ exit 0
449
+ fi
450
+
451
+ resolve_command_and_category "$1"
452
+ local category="$_CATEGORY"
453
+ local command="$_COMMAND"
454
+
455
+ if [ -n "${2:-}" ]; then
456
+ export SANDBOX_SCENARIO="$2"
457
+ export CANON_NON_INTERACTIVE="1"
458
+ fi
459
+
460
+ initialize_sandbox_environment "$category" "$command"
461
+ execute_sandbox_and_commit
462
+
463
+ finalize_sandbox_run
464
+ }
465
+
466
+ main "$@"
@@ -0,0 +1,156 @@
1
+ #!/usr/bin/env bash
2
+ set -e
3
+ set -o pipefail
4
+
5
+ SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
6
+ PROJECT_ROOT="${PROJECT_ROOT:-$(dirname "$(dirname "$SCRIPT_DIR")")}"
7
+
8
+ source "$PROJECT_ROOT/scripts/lib/ui.sh"
9
+ trap close_timeline EXIT
10
+
11
+ SNIPPETS_SOURCE="$PROJECT_ROOT/snippets"
12
+
13
+ show_help() {
14
+ echo -e "${GREY}┌${NC}"
15
+ echo -e "${GREY}├${NC} ${WHITE}Usage:${NC} canon snippets create"
16
+ echo -e "${GREY}│${NC}"
17
+ echo -e "${GREY}│${NC} Creates a new snippet: prompts for category and name, writes the file."
18
+ echo -e "${GREY}│${NC}"
19
+ echo -e "${GREY}│${NC} ${WHITE}Options:${NC}"
20
+ echo -e "${GREY}│${NC} -h, --help ${GREY}# Show this help message${NC}"
21
+ echo -e "${GREY}└${NC}"
22
+ exit 0
23
+ }
24
+
25
+ list_categories() {
26
+ echo "base (root, no prefix)"
27
+ find "$SNIPPETS_SOURCE" -mindepth 1 -maxdepth 1 -type d -exec basename {} \; | sort
28
+ echo "new category"
29
+ }
30
+
31
+ slug_error() {
32
+ local slug="$1"
33
+ local path="$2"
34
+ if [ -z "$slug" ]; then
35
+ echo "name cannot be empty"
36
+ return
37
+ fi
38
+ if [[ ! "$slug" =~ ^[a-z0-9]+(-[a-z0-9]+)*$ ]]; then
39
+ echo "kebab-case only (e.g. my-snippet)"
40
+ return
41
+ fi
42
+ if [ -f "$path" ]; then
43
+ echo "file already exists: $path"
44
+ return
45
+ fi
46
+ echo ""
47
+ }
48
+
49
+ ask_new_category() {
50
+ while true; do
51
+ ask "Category name?" "CATEGORY_INPUT"
52
+ if [ -z "$CATEGORY_INPUT" ]; then
53
+ log_warn "Category name cannot be empty"
54
+ continue
55
+ fi
56
+ if [[ ! "$CATEGORY_INPUT" =~ ^[a-z0-9]+(-[a-z0-9]+)*$ ]]; then
57
+ log_warn "Invalid category: kebab-case only (e.g. my-category)"
58
+ continue
59
+ fi
60
+ if [ -d "$SNIPPETS_SOURCE/$CATEGORY_INPUT" ]; then
61
+ log_warn "Category '$CATEGORY_INPUT' already exists"
62
+ continue
63
+ fi
64
+ CATEGORY_NAME="$CATEGORY_INPUT"
65
+ break
66
+ done
67
+ }
68
+
69
+ ask_name() {
70
+ local category="$1"
71
+ local is_base="$2"
72
+ local label
73
+ local error
74
+
75
+ label="Snippet name?"
76
+
77
+ while true; do
78
+ ask "$label" "NAME_INPUT"
79
+ local dest_path
80
+ if [ "$is_base" = "true" ]; then
81
+ dest_path="$SNIPPETS_SOURCE/$NAME_INPUT.md"
82
+ else
83
+ dest_path="$SNIPPETS_SOURCE/$category/$NAME_INPUT.md"
84
+ fi
85
+ error=$(slug_error "$NAME_INPUT" "$dest_path")
86
+ if [ -z "$error" ]; then
87
+ NAME="$NAME_INPUT"
88
+ break
89
+ fi
90
+ log_warn "Invalid name: $error"
91
+ done
92
+ }
93
+
94
+ cmd_create() {
95
+ local categories=()
96
+ mapfile -t categories < <(list_categories)
97
+
98
+ select_option "Category?" "${categories[@]}"
99
+ local selected="$SELECTED_OPTION"
100
+
101
+ local category
102
+ local is_base="false"
103
+
104
+ if [ "$selected" = "base (root, no prefix)" ]; then
105
+ is_base="true"
106
+ category="base"
107
+ elif [ "$selected" = "new category" ]; then
108
+ ask_new_category
109
+ category="$CATEGORY_NAME"
110
+ else
111
+ category="$selected"
112
+ fi
113
+
114
+ ask_name "$category" "$is_base"
115
+ local name="$NAME"
116
+
117
+ local dest_path
118
+ local install_path
119
+ if [ "$is_base" = "true" ]; then
120
+ dest_path="$SNIPPETS_SOURCE/$name.md"
121
+ install_path="snippets/$name"
122
+ else
123
+ dest_path="$SNIPPETS_SOURCE/$category/$name.md"
124
+ install_path="snippets/$category/$name"
125
+ fi
126
+
127
+ log_info "Installs as: @${install_path}"
128
+
129
+ log_step "Creating file"
130
+
131
+ if [ "$is_base" = "false" ]; then
132
+ mkdir -p "$SNIPPETS_SOURCE/$category"
133
+ fi
134
+
135
+ printf '<!-- TODO: write %s prompt -->\n' "$slug" >"$dest_path"
136
+
137
+ if [ "$is_base" = "true" ]; then
138
+ log_add "snippets/$name.md"
139
+ else
140
+ log_add "snippets/$category/$name.md"
141
+ fi
142
+ }
143
+
144
+ main() {
145
+ if [ "$1" = "-h" ] || [ "$1" = "--help" ]; then
146
+ show_help
147
+ fi
148
+
149
+ cmd_create
150
+
151
+ trap - EXIT
152
+ echo -e "${GREY}└${NC}\n"
153
+ echo -e "${GREEN}✓ Snippet created${NC}"
154
+ }
155
+
156
+ main "$@"