@erclx/canon 5.25.0 → 5.27.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 (315) hide show
  1. package/README.md +4 -3
  2. package/claude/.claude-plugin/plugin.json +1 -1
  3. package/claude/skills/api-design/SKILL.md +2 -0
  4. package/claude/skills/auto-ship/SKILL.md +3 -11
  5. package/claude/skills/auto-ship/references/review-findings.md +20 -0
  6. package/claude/skills/backlog-triage/SKILL.md +2 -0
  7. package/claude/skills/bash-cli-script/SKILL.md +2 -0
  8. package/claude/skills/build-in-slices/SKILL.md +2 -0
  9. package/claude/skills/canon-cli/SKILL.md +2 -0
  10. package/claude/skills/canon-feedback/SKILL.md +2 -0
  11. package/claude/skills/canon-feedback-triage/SKILL.md +2 -0
  12. package/claude/skills/canon-operator/SKILL.md +2 -0
  13. package/claude/skills/canon-rollout/SKILL.md +3 -11
  14. package/claude/skills/canon-rollout/references/failure-recovery.md +20 -0
  15. package/claude/skills/canvas/SKILL.md +14 -1
  16. package/claude/skills/ci-workflow/SKILL.md +2 -0
  17. package/claude/skills/code-craft/SKILL.md +2 -0
  18. package/claude/skills/codebase-layout/SKILL.md +2 -0
  19. package/claude/skills/context-fold/REQUIREMENT.md +6 -2
  20. package/claude/skills/context-fold/SKILL.md +9 -21
  21. package/claude/skills/context-fold/references/anchor-sweep.md +2 -2
  22. package/claude/skills/context-fold/references/completion-report.md +26 -0
  23. package/claude/skills/create-rule/SKILL.md +2 -0
  24. package/claude/skills/create-skill/SKILL.md +2 -0
  25. package/claude/skills/create-standard/SKILL.md +2 -0
  26. package/claude/skills/decision-escalate/SKILL.md +2 -0
  27. package/claude/skills/deploy-app/SKILL.md +2 -0
  28. package/claude/skills/deprecation-migration/SKILL.md +2 -0
  29. package/claude/skills/design-extract/SKILL.md +2 -0
  30. package/claude/skills/design-taste/REQUIREMENT.md +1 -1
  31. package/claude/skills/design-taste/SKILL.md +6 -2
  32. package/claude/skills/design-taste/references/adopted.md +40 -0
  33. package/claude/skills/design-taste/references/kinds.md +1 -1
  34. package/claude/skills/design-taste/references/systems.md +1 -7
  35. package/claude/skills/design-taste/references/tells.md +2 -24
  36. package/claude/skills/docs-sync/REQUIREMENT.md +2 -1
  37. package/claude/skills/docs-sync/SKILL.md +2 -0
  38. package/claude/skills/document-health/REQUIREMENT.md +2 -0
  39. package/claude/skills/document-health/SKILL.md +23 -0
  40. package/claude/skills/document-health/references/axes.md +12 -0
  41. package/claude/skills/draft-and-pick/SKILL.md +3 -1
  42. package/claude/skills/draft-doc/SKILL.md +2 -0
  43. package/claude/skills/draft-doc/references/wiki.md +1 -1
  44. package/claude/skills/draft-figure/SKILL.md +2 -0
  45. package/claude/skills/draft-identity/SKILL.md +3 -1
  46. package/claude/skills/draft-ready/SKILL.md +2 -0
  47. package/claude/skills/draft-screencast/SKILL.md +11 -7
  48. package/claude/skills/draft-slides/REQUIREMENT.md +17 -12
  49. package/claude/skills/draft-slides/SKILL.md +33 -20
  50. package/claude/skills/git-branch/SKILL.md +2 -0
  51. package/claude/skills/git-commit/SKILL.md +2 -0
  52. package/claude/skills/git-followup/SKILL.md +2 -0
  53. package/claude/skills/git-issue/SKILL.md +2 -0
  54. package/claude/skills/git-issue/references/issue.md +10 -0
  55. package/claude/skills/git-pr/SKILL.md +2 -0
  56. package/claude/skills/git-pr/references/evidence.md +14 -6
  57. package/claude/skills/git-pr/references/labels.md +12 -0
  58. package/claude/skills/git-ship/SKILL.md +2 -0
  59. package/claude/skills/git-split/SKILL.md +21 -8
  60. package/claude/skills/git-stage/SKILL.md +2 -0
  61. package/claude/skills/git-worktree/SKILL.md +2 -0
  62. package/claude/skills/index-lookup/SKILL.md +2 -0
  63. package/claude/skills/markdown-propose/SKILL.md +2 -0
  64. package/claude/skills/markdown-propose/references/format.md +9 -0
  65. package/claude/skills/memory-capture/SKILL.md +2 -0
  66. package/claude/skills/memory-review/SKILL.md +2 -0
  67. package/claude/skills/memory-review/references/later-phases.md +7 -0
  68. package/claude/skills/plan-feature/SKILL.md +2 -0
  69. package/claude/skills/plan-groundwork/SKILL.md +2 -0
  70. package/claude/skills/plan-intake/SKILL.md +2 -0
  71. package/claude/skills/plan-intake-answer/SKILL.md +2 -0
  72. package/claude/skills/project-commands/SKILL.md +2 -0
  73. package/claude/skills/read-frames/SKILL.md +2 -0
  74. package/claude/skills/record-screencast/SKILL.md +2 -0
  75. package/claude/skills/repo-metadata/SKILL.md +2 -0
  76. package/claude/skills/restate-plainly/SKILL.md +2 -0
  77. package/claude/skills/review-address/SKILL.md +3 -7
  78. package/claude/skills/review-address/references/post-review-findings.md +16 -0
  79. package/claude/skills/review-branch/SKILL.md +2 -0
  80. package/claude/skills/review-craft/SKILL.md +2 -0
  81. package/claude/skills/review-craft/references/ui.md +2 -2
  82. package/claude/skills/review-pr/SKILL.md +4 -8
  83. package/claude/skills/review-pr/references/body-variants.md +52 -0
  84. package/claude/skills/review-pr/references/key-changes.md +16 -0
  85. package/claude/skills/review-pr/references/post.md +15 -43
  86. package/claude/skills/review-ui/SKILL.md +3 -1
  87. package/claude/skills/review-ui/references/post.md +4 -2
  88. package/claude/skills/role-orchestrator/SKILL.md +5 -14
  89. package/claude/skills/role-orchestrator/references/orchestrator-cloud-launch.md +8 -0
  90. package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +13 -0
  91. package/claude/skills/role-orchestrator/references/orchestrator-handback.md +1 -1
  92. package/claude/skills/role-orchestrator/references/orchestrator-inbound.md +23 -0
  93. package/claude/skills/role-orchestrator/references/orchestrator-launch.md +5 -33
  94. package/claude/skills/role-orchestrator/references/orchestrator-poll.md +1 -21
  95. package/claude/skills/role-orchestrator/references/orchestrator-review-dispatch.md +1 -1
  96. package/claude/skills/role-orchestrator/references/orchestrator-reviewer-launch.md +38 -0
  97. package/claude/skills/role-orchestrator/references/orchestrator-watch.md +26 -0
  98. package/claude/skills/role-planner/SKILL.md +2 -0
  99. package/claude/skills/role-reviewer/REQUIREMENT.md +1 -1
  100. package/claude/skills/role-reviewer/SKILL.md +2 -0
  101. package/claude/skills/role-worker/SKILL.md +2 -0
  102. package/claude/skills/search-craft/REQUIREMENT.md +1 -1
  103. package/claude/skills/search-craft/SKILL.md +5 -1
  104. package/claude/skills/search-craft/references/adopted.md +30 -0
  105. package/claude/skills/seed-sync/SKILL.md +2 -0
  106. package/claude/skills/session-compact/SKILL.md +2 -0
  107. package/claude/skills/session-map/SKILL.md +2 -0
  108. package/claude/skills/session-relay/SKILL.md +2 -0
  109. package/claude/skills/session-resume/SKILL.md +2 -0
  110. package/claude/skills/session-worktree/SKILL.md +3 -11
  111. package/claude/skills/session-worktree/references/install-command.md +20 -0
  112. package/claude/skills/sketch-design/SKILL.md +2 -0
  113. package/claude/skills/systematic-debugging/SKILL.md +2 -0
  114. package/claude/skills/target-check/SKILL.md +2 -0
  115. package/claude/skills/target-setup/SKILL.md +2 -0
  116. package/claude/skills/target-setup/references/detect.md +8 -0
  117. package/claude/skills/target-setup/references/indexes.md +13 -0
  118. package/claude/skills/target-setup/references/verify.md +8 -0
  119. package/claude/skills/task-board/SKILL.md +2 -0
  120. package/claude/skills/teach-workspace/SKILL.md +5 -15
  121. package/claude/skills/teach-workspace/references/lesson-build.md +75 -0
  122. package/claude/skills/teach-workspace/references/lesson-craft.md +13 -69
  123. package/claude/skills/teach-workspace/references/revisit.md +22 -0
  124. package/claude/skills/test-craft/SKILL.md +2 -0
  125. package/claude/skills/test-first/SKILL.md +4 -0
  126. package/claude/skills/test-first/references/adopted.md +36 -0
  127. package/claude/skills/ui-checklist/SKILL.md +2 -0
  128. package/claude/skills/ux-audit/SKILL.md +2 -0
  129. package/claude/skills/ux-measure/SKILL.md +2 -0
  130. package/claude/skills/ux-walkthrough/SKILL.md +2 -0
  131. package/claude/skills/video-craft/SKILL.md +2 -0
  132. package/claude/skills/write-human/SKILL.md +3 -1
  133. package/claude/skills/write-human/references/machine-tells.md +13 -0
  134. package/claude/skills/youtube-transcripts/SKILL.md +2 -0
  135. package/docs/agents/canvas.md +24 -6
  136. package/docs/agents/capture.md +6 -6
  137. package/docs/agents/commands.md +5 -5
  138. package/docs/agents/index.md +5 -5
  139. package/docs/agents/install-and-sync.md +7 -0
  140. package/docs/agents/key-changes.md +1 -1
  141. package/docs/agents/pr-evidence.md +38 -15
  142. package/docs/agents/pr-local.md +19 -13
  143. package/docs/agents/pr-preview.md +44 -21
  144. package/docs/agents/records-stale.md +22 -9
  145. package/docs/agents/records.md +1 -1
  146. package/docs/agents/sandbox.md +29 -5
  147. package/docs/agents/scripting.md +8 -1
  148. package/docs/agents/skills-audit.md +11 -3
  149. package/docs/agents/slides.md +15 -3
  150. package/docs/workflow/ai-workflow.md +1 -1
  151. package/docs/workflow/index.md +1 -0
  152. package/docs/workflow/operating-model.md +5 -6
  153. package/docs/workflow/parallel-features.md +23 -2
  154. package/docs/workflow/skill-map-on-request.md +42 -0
  155. package/docs/workflow/skill-map.md +3 -34
  156. package/docs/workflow/zshrc-aliases.md +1 -1
  157. package/package.json +1 -1
  158. package/scripts/core/regen-hero.ts +1 -1
  159. package/scripts/lib/sandbox-git.sh +1 -9
  160. package/scripts/lib/sandbox-path.sh +6 -162
  161. package/scripts/sandbox-hook.sh +99 -0
  162. package/src/audits/run.ts +1 -1
  163. package/src/canvas/address.ts +12 -3
  164. package/src/canvas/capture.ts +1 -9
  165. package/src/canvas/client/inspector/align-grid.tsx +162 -0
  166. package/src/canvas/client/inspector/color-field.tsx +398 -0
  167. package/src/canvas/client/inspector/color-inputs.tsx +139 -0
  168. package/src/canvas/client/inspector/color-picker.tsx +668 -0
  169. package/src/canvas/client/inspector/color-space.ts +240 -0
  170. package/src/canvas/client/inspector/field.tsx +5 -1
  171. package/src/canvas/client/inspector/fields.css +547 -17
  172. package/src/canvas/client/inspector/size-field.tsx +69 -0
  173. package/src/canvas/client/inspector/values.ts +166 -1
  174. package/src/canvas/client/inspector.tsx +236 -73
  175. package/src/canvas/client/selection.tsx +197 -0
  176. package/src/canvas/client/shell.css +104 -12
  177. package/src/canvas/client/state.ts +69 -9
  178. package/src/canvas/client/surface.tsx +147 -22
  179. package/src/canvas/content.ts +50 -1
  180. package/src/canvas/edit.ts +37 -4
  181. package/src/canvas/editing.ts +203 -0
  182. package/src/canvas/global.d.ts +15 -0
  183. package/src/canvas/server.ts +149 -12
  184. package/src/canvas/tokens.ts +59 -17
  185. package/src/capture/render.ts +45 -7
  186. package/src/capture/sources.ts +43 -0
  187. package/src/census/count.ts +2 -2
  188. package/src/claude/cases/workflow.ts +5 -0
  189. package/src/claude/seeds.ts +2 -2
  190. package/src/claude/skills-audit.ts +96 -14
  191. package/src/claude/skills-drift.ts +1 -1
  192. package/src/claude/skills-families.ts +36 -0
  193. package/src/claude/skills-list.ts +76 -15
  194. package/src/commands/audits.ts +2 -2
  195. package/src/commands/canvas.ts +179 -2
  196. package/src/commands/claude.ts +94 -11
  197. package/src/commands/design.ts +142 -2
  198. package/src/commands/feedback.ts +3 -3
  199. package/src/commands/gov.ts +1 -1
  200. package/src/commands/hooks.ts +1 -1
  201. package/src/commands/indexes.ts +1 -1
  202. package/src/commands/init.ts +1 -1
  203. package/src/commands/intake.ts +1 -1
  204. package/src/commands/migrate.ts +1 -1
  205. package/src/commands/pr.ts +105 -58
  206. package/src/commands/records.ts +89 -7
  207. package/src/commands/repo.ts +1 -1
  208. package/src/commands/sandbox.ts +103 -11
  209. package/src/commands/sessions.ts +1 -1
  210. package/src/commands/slides.ts +31 -77
  211. package/src/commands/sync.ts +1 -1
  212. package/src/commands/tasks.ts +2 -2
  213. package/src/commands/teach.ts +1 -1
  214. package/src/commands/transcripts.ts +1 -1
  215. package/src/commands/worktrees.ts +1 -1
  216. package/src/comments/scan.ts +1 -1
  217. package/src/comments/trend.ts +1 -1
  218. package/src/context/audit.ts +1 -1
  219. package/src/context/citations.ts +1 -1
  220. package/src/context/classify/extract.ts +2 -2
  221. package/src/design/project-fonts.ts +392 -0
  222. package/src/design/tokens.ts +2 -18
  223. package/src/docs/read.ts +1 -1
  224. package/src/{github.ts → feedback/github.ts} +2 -2
  225. package/src/{client-commands.ts → gate/client-commands.ts} +1 -1
  226. package/src/gate/measures.ts +53 -13
  227. package/src/gate/sequencer.ts +1 -1
  228. package/src/gate/stages.ts +9 -0
  229. package/src/{git-files.ts → git/files.ts} +2 -2
  230. package/src/{git-ignore.ts → git/ignore.ts} +1 -1
  231. package/src/{worktree.ts → git/worktree.ts} +1 -1
  232. package/src/gov/citations.ts +2 -2
  233. package/src/gov/install.ts +1 -1
  234. package/src/gov/payload.ts +1 -1
  235. package/src/gov/superseded.ts +3 -3
  236. package/src/gov/test-order.ts +2 -2
  237. package/src/help.ts +1 -1
  238. package/src/hooks/post-merge.ts +1 -1
  239. package/src/indexes/walk.ts +1 -1
  240. package/src/labels/audit.ts +1 -1
  241. package/src/markdown/ceiling.ts +1 -1
  242. package/src/markdown/files.ts +1 -1
  243. package/src/migrate/apply.ts +1 -1
  244. package/src/pr/bijection.ts +1 -1
  245. package/src/pr/evidence.ts +96 -43
  246. package/src/pr/local.ts +16 -10
  247. package/src/pr/preview.ts +78 -2
  248. package/src/record-root.ts +1 -0
  249. package/src/records/backup.ts +2 -1
  250. package/src/records/push-guard.ts +1 -1
  251. package/src/records/stale-canonical.ts +146 -0
  252. package/src/records/stale.ts +1 -1
  253. package/src/sandbox/headless/dispatch.ts +264 -0
  254. package/src/sandbox/headless/run.ts +653 -0
  255. package/src/sandbox/headless/watch.ts +145 -0
  256. package/src/sandbox/hooks.ts +128 -0
  257. package/src/sandbox/provision.ts +607 -0
  258. package/src/sandbox/tree.ts +99 -4
  259. package/src/secrets/marker.ts +2 -2
  260. package/src/secrets/scan.ts +2 -2
  261. package/src/sessions/claim.ts +1 -1
  262. package/src/sessions/resolve.ts +1 -1
  263. package/src/sessions/transfer/bundle.ts +1 -1
  264. package/src/shipped/references.ts +2 -2
  265. package/src/slides/convert/export.ts +2 -16
  266. package/src/slides/decks.ts +110 -0
  267. package/src/slides/package/fonts.ts +6 -2
  268. package/src/standards/audit.ts +2 -2
  269. package/src/standards/read.ts +1 -1
  270. package/src/sync/check.ts +2 -2
  271. package/src/sync/engine.ts +2 -2
  272. package/src/sync/git.ts +1 -1
  273. package/src/sync/history.ts +1 -1
  274. package/src/sync/reverse.ts +1 -1
  275. package/src/sync/seeds-report.ts +1 -1
  276. package/src/sync/target.ts +1 -1
  277. package/src/sync/workflow.ts +1 -1
  278. package/src/targets/pulls.ts +2 -2
  279. package/src/targets/sweep.ts +2 -2
  280. package/src/tasks/answers.ts +1 -1
  281. package/src/tasks/archive.ts +1 -1
  282. package/src/tasks/reach.ts +1 -1
  283. package/src/tasks/trunk.ts +1 -1
  284. package/src/teach/nav.ts +1 -1
  285. package/src/tooling/inject.ts +2 -2
  286. package/src/tooling/subfolder.ts +1 -1
  287. package/src/web/readme-citations.ts +2 -2
  288. package/src/worktrees/bare-flag.ts +1 -1
  289. package/src/worktrees/reclaim.ts +2 -2
  290. package/src/worktrees/remove.ts +1 -1
  291. package/standards/architecture.md +1 -0
  292. package/standards/canvas.md +3 -2
  293. package/standards/requirements.md +2 -0
  294. package/standards/skill-practice.md +2 -1
  295. package/standards/skill.md +2 -0
  296. package/standards/wiki.md +12 -3
  297. package/tooling/base/configs/.github/workflows/pr-local-preview.yml +2 -2
  298. package/scripts/lib/sandbox-dispatch.sh +0 -190
  299. package/scripts/manage-sandbox.sh +0 -472
  300. package/src/slides/layouts.ts +0 -478
  301. package/src/slides/parse.ts +0 -84
  302. package/src/slides/render.ts +0 -110
  303. package/src/slides/styles.ts +0 -96
  304. /package/claude/skills/write-human/references/{source-material.md → adopted.md} +0 -0
  305. /package/src/{commands/feedback-format.ts → feedback/body.ts} +0 -0
  306. /package/src/{github-format.ts → feedback/github-format.ts} +0 -0
  307. /package/src/{git-base.ts → git/base.ts} +0 -0
  308. /package/src/{git-env.ts → git/env.ts} +0 -0
  309. /package/src/{frontmatter.ts → markdown/frontmatter.ts} +0 -0
  310. /package/src/{binary.ts → sweep/binary.ts} +0 -0
  311. /package/src/{exempt-marker.ts → sweep/exempt-marker.ts} +0 -0
  312. /package/src/{copy.ts → sync/copy.ts} +0 -0
  313. /package/src/{target.ts → targets/validate.ts} +0 -0
  314. /package/src/{paths.ts → tasks/paths.ts} +0 -0
  315. /package/src/{seed-marker.ts → tooling/seed-marker.ts} +0 -0
@@ -26,7 +26,7 @@ One row per top-level command, in the order `canon --help` prints them. A domain
26
26
  | `canon indexes <verb>` | Regenerate `index.md` files from sibling frontmatter, or flatten them |
27
27
  | `canon docs [topic]` | Emit toolkit reference docs (`list`, or a topic by name) |
28
28
  | `canon design <verb>` | Render or regenerate `canon/DESIGN.md` tokens, emit their CSS, install the base stylesheet |
29
- | `canon slides <verb>` | Render a `.claude/SLIDES.md` deck, or list its layouts |
29
+ | `canon slides <verb>` | Render a deck folder of HTML slides, or list the decks |
30
30
  | `canon capture [source]` | Render HTML or a URL to PNG and prove each declared font resolved |
31
31
  | `canon serve [dir]` | Serve a directory on loopback and print the link that opens it |
32
32
  | `canon demo <verb>` | Compile and record a running app |
@@ -91,12 +91,12 @@ Each domain exposes a consistent shape where applicable: `list`, `install`, `syn
91
91
  - `wiki`, in `scripting.md`: `init`
92
92
  - `indexes`, in `indexes.md`: `regen`, `list`
93
93
  - `docs`, in `docs.md`: `list`, `<topic>`
94
- - `design`, in `install-and-sync.md` for `install` and `sync`, and described below for the rest: `render`, `regen`, `css`, `install`, `sync`
94
+ - `design`, in `install-and-sync.md` for `install`, `sync`, and `fonts`, and below for the rest: `render`, `regen`, `css`, `install`, `sync`, `fonts`
95
95
  - `slides`, described below: `render`, `list`
96
96
  - `demo`, in `demo.md`: `compile`, `run`, `frames`
97
97
  - `inventory`, described above: `run`
98
98
  - `teach`, in `teach.md`: `list`, `open`, `resource`, `glossary`, `lesson`, `stylesheet`, `nav`, `render`
99
- - `canvas`, described below: `serve`, `list`, `page add`, `page rename`, `frame add`, `frame move`, `selection`, `edit`, `capture`
99
+ - `canvas`, described below: `serve`, `list`, `page add`, `page rename`, `frame add`, `frame move`, `frame resize`, `selection`, `edit`, `editing`, `capture`
100
100
  - `sandbox`, in `sandbox.md`: `reset`, `clean`, `check`, `coverage`
101
101
  - `tasks`, in `tasks.md`: `next-label`, `archive`, `decline`, `plan-citations`, `plan-answers`, `plan-branch`, `plan-reach`, `plan-link`, `pull-request`, `outcome`, `list`, `validate`
102
102
  - `intake`, in `intake.md`: `list`, `answer`
@@ -128,8 +128,8 @@ Subcommands no other page describes:
128
128
  - `claude plugin-update` matches the installed marketplace plugin against `claude/.claude-plugin/plugin.json`'s own name and runs `claude plugin update` on it, reading the version back off `claude plugin list --json`, since the update call reports none of its own (`--json`).
129
129
  - `claude skills rank` scores either skill corpus's descriptions against a case corpus by TF-IDF cosine similarity, reporting rank-one and top-three (`--cases <path>`).
130
130
  - `design regen` rewrites this repository's `canon/DESIGN.md` from `src/design/tokens.ts` and `src/design/base.css` from `src/design/neutral.ts`. `design css` emits the tokens and components as CSS on stdout, with `--no-components` for properties alone, and `design render` declares each vendored face the typography table names under `--embed-fonts`.
131
- - `slides render` renders a `.claude/SLIDES.md` source into a PowerPoint deck and reports any unrecognized layout name on stderr, and `slides list --json` emits the layout catalog.
132
- - `slides render --source <folder>` lays out each `.html` file in filename order in Chromium at 1280 by 720 and rebuilds it as editable shapes. Each element drawn as a picture prints one `✗` line on stderr naming the slide, the selector, and the properties that forced it. A link left out, being a `#slide-N` past the deck's end or any target that is neither that nor an absolute URL, prints one too, and the exit stays 0.
131
+ - `slides list --json` emits one row per deck under `.canon/slides/`, carrying `name`, `title`, `slides`, and `path`.
132
+ - `slides render [deck]` takes a deck name or a folder, defaulting to the only deck, and lays out each `.html` file in filename order in Chromium at 1280 by 720 and rebuilds it as editable shapes. Each element drawn as a picture prints one `✗` line on stderr naming the slide, the selector, and the properties that forced it. A link left out, being a `#slide-N` past the deck's end or any target that is neither that nor an absolute URL, prints one too, and the exit stays 0.
133
133
  - A deck folder's `deck.json` and the faces it embeds, its per-slide `<body>` attributes, transitions and entrances, speaker notes, and charts are described in `slides.md`.
134
134
  - `canvas`, with its verbs, content format, and write routes, is described in `canvas.md`.
135
135
  - `labels scan` fails a pull request or a posted review whose title, body, or review comment carries a phase label, a label a code span quotes, a gitignored record path, a session link, a title word no dictionary holds, or a title breaking `standards/pr.md`'s format, casing, or length rule (`--event`, `--body-file`, `--json`).
@@ -10,7 +10,7 @@ CLI catalog and invocation rules for agents, split by command domain. Start with
10
10
 
11
11
  - [Architecture record](architecture-record.md): The findings canon context audit reads off the architecture record, being the entry cap, revisit sentence, length, decision word, and risk bullet gates the record states for itself, the claim coverage report, and the word counts, plus the requirements record's word cap
12
12
  - [Audits](audits.md): Running every health check as one set, what the single verdict means, the exit code each outcome takes, the retained baseline and the delta it reports, and which corpora are kept out of the record
13
- - [Canvas](canvas.md): The canvas server, its content format, and the verbs that list, arrange, select, edit, and capture frames
13
+ - [Canvas](canvas.md): The canvas server, its content format, and the verbs that list, arrange, select, edit, mark, and capture frames
14
14
  - [Capture](capture.md): Rendering HTML sources to PNG, what the command asserts about fonts, and why the selector has no default
15
15
  - [Census](census.md): Tracked-plus-untracked file count, a breakdown by extension, and a line total that skips whatever reads as binary
16
16
  - [Command catalog](commands.md): Every top-level command with its purpose, each domain's subcommands and the page describing them, the browser commands, and the version skew report
@@ -37,11 +37,11 @@ CLI catalog and invocation rules for agents, split by command domain. Start with
37
37
  - [Overview](overview.md): What this folder covers, the invocation rules every command inherits, and where domain behavior is documented instead
38
38
  - [The pull request evidence comparison](pr-evidence.md): What canon pr evidence compares, the marker that lets it edit its own comment rather than duplicate it, the refusal reasons it names, what the --check read reports as owed, and why the comparison anchors at the merge base rather than the previous push
39
39
  - [The pull request frame store](pr-frames.md): How canon pr frames pushes a UI review frame to a never-merged branch through the GitHub API and returns a branch-path link, which ref it writes, the pass segment that keeps an earlier image fixed, the refusal reasons it names, and how --drop and --prune rewrite the branch so a dropped frame leaves history
40
- - [The pull request local preview](pr-local.md): How canon pr local finds the server a worktree is running, why a server in another worktree is never reported, the refusal reasons it names, and how a close workflow removes the link with --remove
41
- - [The pull request preview deploy](pr-preview.md): How canon pr preview finds a fenced Cloudflare Pages deploy, dispatches it on a pull request's branch, reads the alias the run prints, the refusal reasons it names, and why an unfenced deploy is refused before anything runs
40
+ - [The pull request local preview](pr-local.md): How canon pr local finds the server a worktree is running, why a server in another worktree is never reported, the refusal reasons it names, and how a close workflow drops the address line with --remove
41
+ - [The pull request preview deploy](pr-preview.md): How canon pr preview finds a fenced Cloudflare Pages deploy, refuses a branch its push filter does not serve, dispatches it on a pull request's branch, reads the alias the run prints, the refusal reasons it names, and why an unfenced deploy is refused before anything runs
42
42
  - [Head-sensitive pull request reads](pr-reads.md): Resolving a branch tip from the remote rather than from the pull request object, reading what a review pass covered off its own marker rather than off GitHub's submission stamps, why an empty run list is not a pass, the refusal reasons each verb names, and what the remote read costs
43
43
  - [Records push](records-push.md): Backing the record folders to a private remote and restoring them, which folders the payload carries, the one-time setup, the refusal reasons, and the hook that runs the push
44
- - [Records stale](records-stale.md): Reading the memory pen as a review queue, what makes an entry due, how a cited path is read and resolved, the order entries come back in, and the exit codes and refusals
44
+ - [Records stale](records-stale.md): Reading the memory pen as a review queue, what makes an entry due, how a cited path is read and resolved, the order entries come back in, counting the releases since the requirements and architecture records were last reviewed, and the exit codes and refusals
45
45
  - [Records validate](records-validate.md): Validating the session records and the standards corpus, the per-kind checks, which root each kind defaults to, the exit codes, and the refusal reasons
46
46
  - [Records](records.md): The two roots a record folder resolves at, migrating a record a frontmatter change orphaned, claiming the ordinal intake and groundwork share, reading each folder's size and growth, pruning stale scratch, and where validation, the memory review queue, and the private-remote backup are described
47
47
  - [Restated instructions](restated.md): Counting the instructions the always-loaded file and every path-scoped rule share with the seed, the skill bodies, and each other, how a match is decided, the three classes, which surface a later edit starts from, and why the sweep reports rather than gates
@@ -54,7 +54,7 @@ CLI catalog and invocation rules for agents, split by command domain. Start with
54
54
  - [Sessions](sessions.md): Resolving live peer sessions to the worktree and branch each holds, reading which row is the caller, the liveness confidence field, what each session surface can see, and where moving a session to another machine is described
55
55
  - [Skill audit](skills-audit.md): Measuring both skill corpora against the skill standards, the checks it reads, the requirement gate that is the only failing one, and the drift verb that names bodies rewritten since a ref
56
56
  - [Citation reach](skills-reach.md): Reporting the skill bodies that cite a path no target project receives, which corpus the verb reads, the ownership key that decides what counts, the one-word qualifier that marks a citation as decided, and why the verb reports instead of gating
57
- - [Slides](slides.md): What a folder of HTML slides declares for the whole deck in deck.json, the faces it embeds, what each slide declares on its own body, transitions and entrances, the master built from the project's tokens, speaker notes, charts, and what each refusal reports
57
+ - [Slides](slides.md): Where a deck folder lives and what it holds, what it declares for the whole deck in deck.json, the faces it embeds, what each slide declares on its own body, transitions and entrances, the master built from the project's tokens, speaker notes, charts, and what each refusal reports
58
58
  - [Standard success criteria](standards-audit.md): Reading the corpus against the success-criterion gate, the two headings it accepts, why the check scopes to arrival rather than the whole corpus, and the exit codes it sets
59
59
  - [State-scoped risk](state-scoped-risk.md): Reading committed state rather than an arriving change, the shipped-tree corpus the secret scan reads, what it keys on and how a deliberate value is exempted, the advisory check and its network failure mode, and why one gates while the other reports
60
60
  - [Superseded values](superseded.md): Reading where the tree still asserts a value a changed convention no longer produces, why the sweep keys on the value rather than the file, the family stem behind a templated citation, the exemption marker, the blind spots it cannot reach, and why it reports rather than gates
@@ -57,6 +57,13 @@ touches, because that subfolder is project-authored by location the way
57
57
  `.claude/rules/project/` is. An override named exactly like the shipped file is
58
58
  still the project's.
59
59
 
60
+ A project's faces sit in that subfolder too, under `fonts/` with plain
61
+ `@font-face` rules in `fonts.css`. `canon design fonts add <file> --family <name>`
62
+ copies a `woff2`, `woff`, `ttf`, or `otf` face in and appends its rule
63
+ (`--weight`, `--style`, `--json`), refusing bytes that disagree with the
64
+ extension as `invalid-font`. `fonts list --json` emits one row per rule, with a
65
+ `problem` where the file is missing or lies outside the subfolder.
66
+
60
67
  The override ships absent rather than empty. An empty file is one the project
61
68
  did not ask for and did not write, the reconciliation already handles a missing
62
69
  side, and an empty override invites a target to fill it before it has an
@@ -113,4 +113,4 @@ One class stays open and is named rather than closed. A bullet can cite where so
113
113
 
114
114
  ## Where it runs
115
115
 
116
- `review-pr` Step 3 calls it and files an `unmet` path as a `should-fix` finding under the `**PR body**` block the stale ticked box already takes, since what both corrupt is the merge record rather than a file in the diff. A body is edited between pushes, so a finding names the head the comparison ran at. `unnamed` is read there and raised off no count, since the step's own history is a question sent over bullets that already answered it. `unresolved` and `incidental` are reported nowhere.
116
+ `review-pr` Step 3 calls it through its `references/key-changes.md` and files an `unmet` path as a `should-fix` finding under the `**PR body**` block the stale ticked box already takes, since what both corrupt is the merge record rather than a file in the diff. A body is edited between pushes, so a finding names the head the comparison ran at. `unnamed` is read there and raised off no count, since the step's own history is a question sent over bullets that already answered it. `unresolved` and `incidental` are reported nowhere.
@@ -70,8 +70,8 @@ shows a reviewer, each field present only when that comment holds it:
70
70
 
71
71
  | Field | What it carries |
72
72
  | ----------- | ----------------------------------------------------------------- |
73
- | `preview` | The hosted `**Preview:**` address the comment opens with. |
74
- | `local` | The `**Local preview:**` address under it. |
73
+ | `preview` | The hosted `**Preview:**` address on the comment's address line. |
74
+ | `local` | The `**Local preview:**` address beside it. |
75
75
  | `checklist` | The checklist between its delimiters, with any ticked boxes kept. |
76
76
 
77
77
  These come from the comment already posted, never from the flags the call
@@ -142,11 +142,34 @@ details wrapper lands once, not twice.
142
142
 
143
143
  ## The preview line
144
144
 
145
- `--preview <url>` opens the body with the branch's preview address, and a run
145
+ Every body opens with `## Evidence`. Under it sits one address line carrying
146
+ whichever previews apply, joined by a middle dot:
147
+
148
+ ```plaintext
149
+ ## Evidence
150
+
151
+ **Preview:** <url> · **Local preview:** <url>
152
+
153
+ **Base:** `<base>` · **Head:** `<head>`
154
+ ```
155
+
156
+ The Base and Head line follows only when the comment carries screenshots.
157
+
158
+ `--preview <url>` puts the branch's hosted address on that line, and a run
146
159
  without it carries forward the address the marked comment already holds. With
147
- no evidence in the diff and an address in hand, the body is the address and the
148
- marker alone, reported as `ok`. `canon docs pr-preview` covers where the
149
- address comes from.
160
+ no evidence in the diff and an address in hand, the body is the heading, the
161
+ address line, and the marker alone, reported as `ok`. `canon docs pr-preview`
162
+ covers where the address comes from.
163
+
164
+ A carried hosted address is dropped when a deploy workflow resolves and its
165
+ push path filter matches no path the pull request changed, since the site it
166
+ links shows none of the change. An explicit `--preview` is always kept.
167
+
168
+ The carry-forward reads every line above the commit line, the checklist, and
169
+ the comparison for each prefix, wherever it sits. A comment posted before the
170
+ heading opened the body, with each address on a line of its own at the top,
171
+ reads the same way, so an open pull request keeps its links on its first
172
+ re-render.
150
173
 
151
174
  ## The checklist line
152
175
 
@@ -173,11 +196,10 @@ gone.
173
196
 
174
197
  ## The local preview line
175
198
 
176
- `--local <url>` adds `**Local preview:** <url>` to the opening block: under the
177
- hosted `**Preview:**` line when there is one, and as the first line when there
178
- is not. The hosted line always keeps the first position, since that is the one
179
- line the carry-forward reads for it. A run without the option carries forward
180
- the local address the marked comment already holds, the same as the other two.
199
+ `--local <url>` adds `**Local preview:** <url>` to the address line, after the
200
+ hosted segment when there is one and alone when there is not. A run without the
201
+ option carries forward the local address the marked comment already holds, the
202
+ same as the other two.
181
203
 
182
204
  The option does not turn `no-evidence` into `ok` on its own. A branch with a
183
205
  dev server running and no rendered change would otherwise get a comment holding
@@ -206,10 +228,11 @@ canon pr evidence 1341 --check --json
206
228
  - `evidence` is owed when the changed set carries an evidence image and no
207
229
  comment carries the marker.
208
230
  - `preview` is owed when the pull request has a marked comment or an evidence
209
- change, a deploy workflow resolves in the checkout the verb runs from, and
210
- the marked comment's first line is no `**Preview:**` line. A
211
- `**Local preview:**` line does not satisfy it. A project deploying nothing is
212
- never owed a preview.
231
+ change, a deploy workflow resolves in the checkout the verb runs from, its
232
+ push path filter matches a path the pull request changed, and the marked
233
+ comment carries no `**Preview:**` address. A `**Local preview:**` address
234
+ does not satisfy it. A project deploying nothing is never owed a preview,
235
+ and neither is a branch its deploy does not build from.
213
236
 
214
237
  The record carries `owed`, `commentId` when a marked comment exists, and the
215
238
  same `preview`, `local`, and `checklist` fields the other reasons carry, so a
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: The pull request local preview
3
- description: How canon pr local finds the server a worktree is running, why a server in another worktree is never reported, the refusal reasons it names, and how a close workflow removes the link with --remove
3
+ description: How canon pr local finds the server a worktree is running, why a server in another worktree is never reported, the refusal reasons it names, and how a close workflow drops the address line with --remove
4
4
  ---
5
5
 
6
6
  # The pull request local preview
@@ -10,7 +10,7 @@ worktree is running. `git-pr` calls it ahead of the evidence comparison and
10
10
  passes the address through `canon pr evidence --local`, so a reviewer on the
11
11
  same machine gets the running branch to click into beside the screenshots and
12
12
  the checklist. A workflow on the pull request's `closed` event calls it again
13
- with `--remove`, which replaces the line with a note.
13
+ with `--remove`, which drops the address line and leaves nothing in its place.
14
14
 
15
15
  ```bash
16
16
  canon pr local --json
@@ -62,9 +62,9 @@ to it on this pull request would show a reviewer the wrong code.
62
62
  | `ok` | A server answered. `url` carries the address and `port` the port. |
63
63
  | `no-server` | Nothing inside this worktree served an HTML page. |
64
64
  | `no-listener-reader` | Neither `lsof` nor `/proc` is available, so no socket could be read. |
65
- | `removed` | `--remove` replaced the local line on the evidence comment. |
65
+ | `removed` | `--remove` dropped the address line from the evidence comment. |
66
66
  | `no-comment` | `--remove` found no comment carrying the evidence marker. |
67
- | `no-line` | `--remove` found the comment but no local line on it. |
67
+ | `no-line` | `--remove` found the comment but no address line on it. |
68
68
  | `gh-missing` | `--remove` needs `gh` and it is not on the path. |
69
69
  | `gh-failed` | `--remove` could not read the comments or could not edit the comment. |
70
70
 
@@ -84,12 +84,19 @@ on:
84
84
  types: [closed]
85
85
  ```
86
86
 
87
- It reads the comment carrying the `pr-evidence` marker, replaces the
88
- `**Local preview:**` line with the `--note` text, and edits the comment itself
89
- through `gh api`. The verb writes here rather than handing a body back, because
90
- its caller is a workflow with no session to post one. Every other byte of the
91
- comment stays as it was, which keeps the marker, the checklist delimiters, and
92
- any ticked box intact. A second run finds no line and reports `no-line`.
87
+ It reads the comment carrying the `pr-evidence` marker, drops the address line
88
+ under `## Evidence`, the hosted `**Preview:**` segment and the
89
+ `**Local preview:**` segment together, and edits the comment itself through
90
+ `gh api`. The hosted link goes too because the deploy workflow deletes the
91
+ branch's preview deployments on the same close. No note replaces the line, and
92
+ the blank line it sat on goes with it so no gap doubles under the heading. A
93
+ comment in the older layout, with each address on its own line at the top,
94
+ loses both lines the same way.
95
+
96
+ The verb writes here rather than handing a body back, because its caller is a
97
+ workflow with no session to post one. Every other byte of the comment stays as
98
+ it was, which keeps the marker, the checklist delimiters, and any ticked box
99
+ intact. A second run finds no line and reports `no-line`.
93
100
 
94
101
  A fork pull request gets a read-only token, so the workflow skips the edit with
95
102
  a notice rather than failing the close.
@@ -100,6 +107,5 @@ The link can still go dead while the pull request is open, such as when the
100
107
  session holding the server retires. Only the close is covered, and a re-render
101
108
  after a push carries the line forward whether the server still answers or not.
102
109
 
103
- The hosted `**Preview:**` line from `canon pr preview` stays on the comment
104
- after close, even though its deployments are deleted then. `canon docs
105
- pr-preview` covers that path.
110
+ `canon docs pr-preview` covers how the hosted address is minted and when it is
111
+ refused.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: The pull request preview deploy
3
- description: How canon pr preview finds a fenced Cloudflare Pages deploy, dispatches it on a pull request's branch, reads the alias the run prints, the refusal reasons it names, and why an unfenced deploy is refused before anything runs
3
+ description: How canon pr preview finds a fenced Cloudflare Pages deploy, refuses a branch its push filter does not serve, dispatches it on a pull request's branch, reads the alias the run prints, the refusal reasons it names, and why an unfenced deploy is refused before anything runs
4
4
  ---
5
5
 
6
6
  # The pull request preview deploy
@@ -8,8 +8,8 @@ description: How canon pr preview finds a fenced Cloudflare Pages deploy, dispat
8
8
  `canon pr preview` publishes a pull request's branch to a Cloudflare Pages
9
9
  preview and reports the address. `git-pr` calls it after the evidence
10
10
  comparison, then re-renders that comment through `canon pr evidence --preview`
11
- so the link opens it. A reviewer gets a page to click into before merging
12
- rather than screenshots and a checklist alone.
11
+ so the link sits on the address line under its heading. A reviewer gets a page
12
+ to click into before merging rather than screenshots and a checklist alone.
13
13
 
14
14
  ```bash
15
15
  canon pr preview --json
@@ -31,6 +31,24 @@ the first file, in path order, that meets four tests:
31
31
  The workflow is read before the pull request, so a project with no fenced
32
32
  deploy is refused without a network call.
33
33
 
34
+ ## Which branches it serves
35
+
36
+ A dispatch runs the workflow whatever its `on.push.paths` filter says, so a
37
+ branch that touched nothing the site builds from would get a preview showing
38
+ none of its change. The verb reads the pull request's changed paths and matches
39
+ them against the picked workflow's own `on.push.paths` or `on.push.paths-ignore`
40
+ list, applying `!` patterns in order the way GitHub does. When nothing matches,
41
+ it refuses as `unserved` and dispatches nothing. `--check` answers `unserved`
42
+ the same way.
43
+
44
+ The push filter is the one statement of what the site builds from, since it
45
+ already decides when production deploys. A workflow with neither list, with no
46
+ push trigger, or that does not parse as YAML serves every change, so a project
47
+ whose every change ships keeps minting for every branch.
48
+
49
+ A removed path counts, the same as GitHub's own push filter counts it, so a
50
+ branch whose only site change deletes a file still gets a preview.
51
+
34
52
  ## Why an unfenced deploy is refused
35
53
 
36
54
  Cloudflare Pages publishes a deploy that names no branch to production. A
@@ -62,19 +80,21 @@ keeps the match independent of the local clock.
62
80
 
63
81
  `reason` on the record is what a caller branches on, not the exit code:
64
82
 
65
- | Reason | What it means |
66
- | --------------- | -------------------------------------------------------------------------- |
67
- | `ok` | The preview was published. `url` carries the address and `runId` the run. |
68
- | `no-deploy` | No dispatchable workflow runs `pages deploy`. |
69
- | `unfenced` | The deploy passes no `--branch`, so nothing was dispatched. |
70
- | `no-alias` | The workflow prints no alias line, or the finished run's log carried none. |
71
- | `run-failed` | The deploy run finished without succeeding. `runId` names it. |
72
- | `timeout` | The run did not finish inside `--timeout` minutes, 15 by default. |
73
- | `bad-timeout` | `--timeout` was not a positive number. |
74
- | `gh-missing` | `gh` is not on the path. |
75
- | `gh-failed` | `gh` could not read the pull request, or list or dispatch the workflow. |
76
- | `no-branch` | The pull request carries no head branch name. |
77
- | `check-timeout` | `--check` was combined with `--timeout`. |
83
+ | Reason | What it means |
84
+ | -------------------- | -------------------------------------------------------------------------- |
85
+ | `ok` | The preview was published. `url` carries the address and `runId` the run. |
86
+ | `no-deploy` | No dispatchable workflow runs `pages deploy`. |
87
+ | `unserved` | The push path filter matches no changed path, so nothing was dispatched. |
88
+ | `unreadable-changes` | The pull request's changed paths could not be read. |
89
+ | `unfenced` | The deploy passes no `--branch`, so nothing was dispatched. |
90
+ | `no-alias` | The workflow prints no alias line, or the finished run's log carried none. |
91
+ | `run-failed` | The deploy run finished without succeeding. `runId` names it. |
92
+ | `timeout` | The run did not finish inside `--timeout` minutes, 15 by default. |
93
+ | `bad-timeout` | `--timeout` was not a positive number. |
94
+ | `gh-missing` | `gh` is not on the path. |
95
+ | `gh-failed` | `gh` could not read the pull request, or list or dispatch the workflow. |
96
+ | `no-branch` | The pull request carries no head branch name. |
97
+ | `check-timeout` | `--check` was combined with `--timeout`. |
78
98
 
79
99
  The exit is 0 on `ok` and 1 on every refusal. A `timeout` leaves the run
80
100
  going, so the preview may still land after the verb has given up on it.
@@ -107,10 +127,11 @@ reason but `fresh`.
107
127
 
108
128
  ## How the address reaches the pull request
109
129
 
110
- `canon pr evidence --preview <url>` puts `**Preview:** <url>` on the first line
111
- of the evidence body. With no evidence image in the diff, the body is that line
112
- and the trailing marker alone, so a pull request whose screenshots did not
113
- change still gets one comment a later call can find and edit.
130
+ `canon pr evidence --preview <url>` puts `**Preview:** <url>` on the address
131
+ line under the evidence body's `## Evidence` heading. With no evidence image in
132
+ the diff, the body is the heading, that line, and the trailing marker alone, so
133
+ a pull request whose screenshots did not change still gets one comment a later
134
+ call can find and edit.
114
135
 
115
136
  A later `canon pr evidence` run without `--preview` reads the address off the
116
137
  marked comment and carries it into the new body. `git-followup` re-renders the
@@ -123,7 +144,9 @@ way, which is what keeps that push from wiping boxes a reviewer already ticked.
123
144
  A `pull_request` trigger on `closed` in the same workflow runs a cleanup job
124
145
  that deletes every preview deployment Cloudflare holds for the branch. The
125
146
  deploy job carries `if: github.event_name != 'pull_request'`, so a closed pull
126
- request never deploys.
147
+ request never deploys. The same close runs `canon pr local --remove`, which
148
+ drops the address line from the evidence comment, hosted link included, so the
149
+ comment never links a deployment that no longer exists.
127
150
 
128
151
  ## What this does not cover
129
152
 
@@ -1,25 +1,26 @@
1
1
  ---
2
2
  title: Records stale
3
- description: Reading the memory pen as a review queue, what makes an entry due, how a cited path is read and resolved, the order entries come back in, and the exit codes and refusals
3
+ description: Reading the memory pen as a review queue, what makes an entry due, how a cited path is read and resolved, the order entries come back in, counting the releases since the requirements and architecture records were last reviewed, and the exit codes and refusals
4
4
  ---
5
5
 
6
6
  # Records stale
7
7
 
8
- `canon records stale memory` reports each memory entry's review state and every backticked path it cites that the project no longer holds. It answers what a review of the pen should read next, so a skill takes the queue from the verb rather than re-deriving it by grep.
8
+ `canon records stale memory` reports each memory entry's review state and every backticked path it cites that the project no longer holds. It answers what a review of the pen should read next, so a skill takes the queue from the verb rather than re-deriving it by grep. `canon records stale canonical` reports when the requirements and architecture records were last reviewed and how many releases have shipped since.
9
9
 
10
10
  ```bash
11
11
  canon records stale memory
12
12
  canon records stale memory --json
13
13
  canon records stale memory --days 60 --json
14
+ canon records stale canonical --json
14
15
  ```
15
16
 
16
- | Option | Behavior |
17
- | --------------- | ------------------------------------------------------------- |
18
- | `--json` | Add a machine-readable record on stdout |
19
- | `--days <n>` | Days after a review before an entry is due again (default 30) |
20
- | `--root <path>` | Project root, defaulting to the main worktree |
17
+ | Option | Behavior |
18
+ | --------------- | --------------------------------------------------------------------------------------------------- |
19
+ | `--json` | Add a machine-readable record on stdout |
20
+ | `--days <n>` | Days after a review before a memory entry is due again (default 30) |
21
+ | `--root <path>` | Project root, defaulting to the main worktree for `memory` and the current worktree for `canonical` |
21
22
 
22
- `memory` is the only kind it reads, since a memory entry is the one record carrying a review date. Any other argument refuses as `unknown-kind`.
23
+ `memory` and `canonical` are the two kinds it reads, since each is a record carrying a review date. Any other argument refuses as `unknown-kind`.
23
24
 
24
25
  It reports and never writes. It moves, archives, and rewrites no entry, matching `validate` and `size`.
25
26
 
@@ -53,10 +54,22 @@ canon records stale memory --json | jq -r '[.entries[] | select(.due)][0:20][] |
53
54
 
54
55
  The record carries `total`, `due`, `days`, the `folder` read relative to the root, and one `entries` row per entry with `name`, `category`, `reviewed`, `due`, and `unresolved`.
55
56
 
57
+ ## Canonical records
58
+
59
+ `canonical` reads `REQUIREMENTS.md` and `ARCHITECTURE.md` at whichever surface root carries each, `canon/` ahead of `.claude/`, and omits one the project does not hold. Both are tracked, so `--root` defaults to the worktree the caller stands in rather than the main one, and a stamp a branch just wrote reads back from that branch.
60
+
61
+ Each doc's review point is an optional `reviewed: YYYY-MM-DD` frontmatter field, set by whoever finishes a review, per `canon standards requirements` and `canon standards architecture`. It is a date rather than a commit, since a commit written on a feature branch never reaches a trunk that squash-merges. The field is read the way the memory field is, so a value that is not a calendar date comes back as `invalidReviewed`.
62
+
63
+ The count is every release tag merged into `HEAD` whose creator date falls after the reviewed day. A release tag ends in a dotted version, bare as `v5.25.0` or behind a component prefix as `canon-v2.1.0`, so an eval, deploy, or snapshot tag on the trunk never inflates it. A lightweight tag's creator date is its commit's date and an annotated tag's is the tagging date, so a project mixing both counts by two clocks.
64
+
65
+ The record carries `tagged`, false when `HEAD` has merged no release tag or the repository has no commit yet, and one `docs` row per doc with `path`, `reviewed`, `releasesSince`, and `latestRelease`. `releasesSince` is null on a doc never reviewed and `0` on one reviewed after every tag. With no tags it is also `0`, which is why `tagged` travels beside it.
66
+
67
+ It gates nothing, and no hook, gate stage, or workflow runs it. `canon:document-health` reads it when asked to review the two records.
68
+
56
69
  ## Exit codes and refusals
57
70
 
58
71
  Exit codes: `0` the reading completed, whatever it found, and `1` refused. A due entry is a queue position rather than a failure, so nothing here gates.
59
72
 
60
- A `reason` field carries which gate fired: `no-folder` when the project holds no memory folder at either record root, `unknown-kind` for any kind but `memory`, and `bad-days` when `--days` is not a positive whole number. An empty pen is not a refusal. It reports an empty list and exits `0`.
73
+ A `reason` field carries which gate fired: `no-folder` when the project holds no memory folder at either record root, `unknown-kind` for any kind but `memory` or `canonical`, `bad-days` when `--days` is not a positive whole number or is passed to `canonical`, and `unreadable-tags` when `canonical` cannot read the tags. An empty pen is not a refusal. It reports an empty list and exits `0`.
61
74
 
62
75
  The pen is shared scratch at the main worktree root, so `--root` defaults there, the same default `validate memory` takes. A pen at the legacy `.claude/memory/` root resolves the way every record verb resolves it, per `records.md`. <!-- canon-keep-record-root -->
@@ -118,7 +118,7 @@ Exit codes: `0` nothing to prune, or `--write` deleted every candidate. `1` refu
118
118
 
119
119
  ## Stale
120
120
 
121
- `canon records stale memory` reports which memory entries are due for review and which cite a path the tree no longer holds, ordered so a review takes the first N as a batch. What makes an entry due, how a cited path resolves, and the refusals are in `records-stale.md`.
121
+ `canon records stale memory` reports which memory entries are due for review and which cite a path the tree no longer holds, ordered so a review takes the first N as a batch. `canon records stale canonical` reports when the requirements and architecture records were last reviewed and how many releases have shipped since. What makes an entry due, how a cited path resolves, how the release count is taken, and the refusals are in `records-stale.md`.
122
122
 
123
123
  ## Push and pull
124
124
 
@@ -9,7 +9,7 @@ description: Scenario routing, the expectation scoring surface, and the coverage
9
9
 
10
10
  ## Scenarios
11
11
 
12
- Scenarios live under `sandbox/`, one folder per category. `sandbox/fixtures/` is the exception, holding file content that scenarios stage rather than scenarios of its own, so both pickers filter it out. That tree sits outside `files` in `package.json`, so an installed `canon` carries the command, reports it as toolkit-only on one line, and exits 1 rather than failing on the missing directory. Route non-interactively with `SANDBOX_SCENARIO`:
12
+ Scenarios live under `sandbox/`, one folder per category. `sandbox/fixtures/` is the exception, holding file content that scenarios stage rather than scenarios of its own, so the picker and the coverage report both filter it out. That tree sits outside `files` in `package.json`, so an installed `canon` carries the command, reports it as toolkit-only on one line, and exits 1 rather than failing on the missing directory. Route non-interactively with `SANDBOX_SCENARIO`:
13
13
 
14
14
  ```bash
15
15
  SANDBOX_SCENARIO=sync canon sandbox infra:tooling
@@ -39,15 +39,39 @@ The verdict `state` is `pass`, `fail`, or `unchecked`. An arm with no `expect.to
39
39
 
40
40
  Omitting `--writes`, `--escapes`, or `--envelope` does not silently drop the assertion kinds that need them. Write scope, escape scope, the turn ceiling, and the reply assertion report as unchecked and appear in the count, so the standalone command cannot claim more coverage than it had. Supplying `--escapes` without `--escapes-watched` reports the same way: a zero-escape result with no root confirmed watched is unmeasured rather than a pass. A verdict never reports `pass` with zero assertions.
41
41
 
42
- An arm declaring `escape_scope` asserts a bound on `run.sh`'s own escape watch rather than on the sandbox tree. `write_scope` skips when the run wrote nothing, since a required output missing is itself a finding, but `escape_scope` passes on zero escapes outright, since a clean run producing none is the expected outcome for a destination nothing requires a skill to touch, provided `--escapes-watched` confirms a root held something to watch. Declaring `escape_scope = []` asserts that a correct run reaches none of the watched destinations at all. `canon/context/sandbox/isolation.md` names what the watch reaches and what it cannot.
42
+ An arm declaring `escape_scope` asserts a bound on the headless runner's own escape watch rather than on the sandbox tree. `write_scope` skips when the run wrote nothing, since a required output missing is itself a finding, but `escape_scope` passes on zero escapes outright, since a clean run producing none is the expected outcome for a destination nothing requires a skill to touch, provided `--escapes-watched` confirms a root held something to watch. Declaring `escape_scope = []` asserts that a correct run reaches none of the watched destinations at all. `canon/context/sandbox/isolation.md` names what the watch reaches and what it cannot.
43
43
 
44
44
  An envelope that parses but carries no `result` field skips the reply assertion the same way an absent file does. An envelope carrying an empty `result` fails it, since a run that returned no text is a finding rather than a gap in the input.
45
45
 
46
46
  Exit 0 means `pass` or `unchecked`. Exit 1 means `fail`, or a caller error: a malformed target, or a sandbox that was never provisioned. A missing sandbox reports as an error rather than a failed verdict, because failing every path assertion would read as a skill that did nothing. `--strict` moves `unchecked` to exit 1 for a caller that has finished arming its scenarios.
47
47
 
48
+ ## Headless runs
49
+
50
+ `canon sandbox run` provisions a scenario, drives one `claude -p` session over it, and scores the result with `canon sandbox check`. `sandbox/run.sh` is a wrapper that passes its arguments to the verb, so either spelling runs the same code.
51
+
52
+ ```bash
53
+ canon sandbox run <category>:<command> "<prompt>" [arm]
54
+ canon sandbox run claude:plan-feature "/canon:plan-feature add a widget" small
55
+ ```
56
+
57
+ Every run bills a real session through the `claude` binary on `PATH`. The session runs with `--plugin-dir` pointed at this checkout's `claude/`, so it loads the branch's skills rather than an installed copy, and provisioning injects no skill into the tree for the same reason. Four variables override the flags it hands to `claude -p`:
58
+
59
+ | Variable | Default |
60
+ | ---------------------------------- | -------------------------------- |
61
+ | `CANON_SKILL_TEST_MODEL` | `sonnet` |
62
+ | `CANON_SKILL_TEST_TOOLS` | `Bash,Read,Glob,Grep,Edit,Write` |
63
+ | `CANON_SKILL_TEST_MAX_TURNS` | `30` |
64
+ | `CANON_SKILL_TEST_PERMISSION_MODE` | `bypassPermissions` |
65
+
66
+ The max-turns value is the only budget a run has. An arm's `max_turns` is asserted after the run and cannot raise it.
67
+
68
+ Stdout carries one JSON record: the session's envelope with `verdict`, `escapes`, and `sessions` merged in, described under the skills census below. Stderr carries the framed timeline, the provisioning output, the session's own stderr, the verdict report, and a warning for each escape, new session record, or reaped process. An envelope that does not parse still prints its verdict, under `is_error: true`.
69
+
70
+ Exit codes follow whichever step stopped the run. Provisioning's code ends a run before the session starts, and a session that exits non-zero ends it with that code after writing a dead-run record, `{is_error, exit_code, raw_output}`, to the same runs folder the merged record uses. Otherwise the verdict's code stands, except that an envelope that does not parse forces 1. An interrupt reaps the session's process group before the runner exits.
71
+
48
72
  ## Provisioning equivalence
49
73
 
50
- `canon sandbox equivalence` proves a change moved nothing in what scenarios provision. It provisions every arm of the named targets on a base ref and on the working checkout, builds a manifest of each tree, and names what differs. It runs offline and never calls `sandbox/run.sh` or a `claude` binary, so no arm it runs bills a model.
74
+ `canon sandbox equivalence` proves a change moved nothing in what scenarios provision. It provisions every arm of the named targets on a base ref and on the working checkout, builds a manifest of each tree, and names what differs. It runs offline and never calls `canon sandbox run` or a `claude` binary, so no arm it runs bills a model.
51
75
 
52
76
  ```bash
53
77
  canon sandbox equivalence claude --base origin/main --json
@@ -95,8 +119,8 @@ A skill pairs to a scenario by filename, `<category>-<command>` first and bare `
95
119
 
96
120
  `exempt` means no arm should be written and holds only with a reason, declared in `sandbox/exempt.toml` and limited to a harness limit the checker cannot reach past or a skill that writes no artifact. An armed arm outranks an exemption. An exemption naming no shipped skill, or naming one an arm now asserts, exits 1 without `--strict`. Each armed arm reports as `<category>:<command>/<arm>`, so two same-named arms under different scenarios stay distinct.
97
121
 
98
- `sandbox/run.sh` calls this after a headless run and merges the verdict into the envelope it prints. It also writes that merged record to `.canon/tmp/runs/sandbox/<target>-<arm>-<timestamp>.json` with a `writes` array appended, and logs the path on stderr. Both fields are what a later re-score needs, since `--envelope` and `--writes` read files the run deletes on exit.
122
+ `canon sandbox run` calls this after a headless run and merges the verdict into the envelope it prints. It also writes that merged record to `.canon/tmp/runs/sandbox/<target>-<arm>-<timestamp>.json` with a `writes` array appended, and logs the path on stderr. Both fields are what a later re-score needs, since `--envelope` and `--writes` read files the run deletes on exit.
99
123
 
100
124
  Two more fields ride alongside the verdict rather than inside it. `escapes` lists what the run wrote under a watched toolkit root, which the verdict cannot assert over because those files sit outside the sandbox tree. `sessions` reports the nested-dispatch bound, carrying `watched` for whether the client's session registry was there to read, `new` for the records that appeared while the run was in flight, `concurrent` for the records present both before and after, and `reap` for what the run found in the session's process group afterwards. Neither field fails a run on its own.
101
125
 
102
- `run.sh` passes `concurrent` through `--concurrent-sessions` to `sandbox check`, and `checkEscapeScope` appends a witness count to an `unbounded escape:` message rather than lets it soften the verdict.
126
+ `canon sandbox run` passes `concurrent` through `--concurrent-sessions` to `sandbox check`, and `checkEscapeScope` appends a witness count to an `unbounded escape:` message rather than lets it soften the verdict.
@@ -17,7 +17,7 @@ Use these to discover what's available instead of hardcoding names.
17
17
  | `canon standards list --json` | Standards docs and the paths each governs |
18
18
  | `canon gov list --json` | Governance stacks, rule sets, and unreferenced rules |
19
19
  | `canon claude seeds list --json` | Seed doc sources with content |
20
- | `canon claude skills list --json` | Plugin skills, descriptions, requirement flag |
20
+ | `canon claude skills list --json` | Plugin skills, descriptions, requirement flag, family vocabulary |
21
21
  | `canon docs list --json` | Consumer docs plus per-domain context |
22
22
  | `canon audits list --json` | Audits the set runs, the corpus each reads, and whether it gates |
23
23
 
@@ -68,6 +68,13 @@ or unparseable returns an empty description rather than failing the listing, so
68
68
  one malformed file cannot hide the rest of the catalog. `--names` emits skill
69
69
  names one per line.
70
70
 
71
+ Each skill in `--json` carries `family`, the `metadata.family` its frontmatter
72
+ declares, or `null` where it declares none. A top-level `families` array holds
73
+ the vocabulary as `{ key, group }` entries in skill map order, where `group` is
74
+ the map heading the family's rows sit under. Read a new skill's family from it
75
+ rather than from the map. `--by-family` prints the human listing as one step per
76
+ family, with a trailing step for any skill whose family is missing or unknown.
77
+
71
78
  Each entry also carries `requirement`, whether the folder holds a sibling
72
79
  `REQUIREMENT.md`. Every skill is meant to carry one, so a `false` is a gap to
73
80
  close rather than a recorded exemption, and the flag answers which skills are
@@ -36,7 +36,9 @@ Each check traces to a line in the standard.
36
36
  - Folder name in kebab-case
37
37
  - Each `REQUIREMENT.md` declaring `Gap` and `Must`, matched at any heading level
38
38
  - No ISO date in `SKILL.md` or any file under `references/`, reported as `datedProvenance` in the JSON record's `findings`
39
- - Each listed practice skill closing with `## Excuses and rebuttals`, `## Red flags`, and `## Before handing over`, and carrying `references/adopted.md`, reported as `practiceShape`
39
+ - Each listed practice skill closing with `## Excuses and rebuttals`, `## Red flags`, and `## Before handing over`, and each skill on the wider ledger list carrying `references/adopted.md`, reported together as `practiceShape`
40
+ - Each file under `references/` running over 100 lines opening with a `## Contents` H2, reported as `referenceContents`
41
+ - Each skill under `claude/skills/` declaring a `metadata.family` that names a key in `checkpoints.families`, reported as `family`
40
42
 
41
43
  A body whose frontmatter does not parse reports as declaring neither field rather than ending the run, so one malformed file cannot hide the corpus behind it. A key present with an empty value reads as absent, since a blank `name` would otherwise report as a name disagreeing with every folder. A folder carrying no requirement is reported once under presence rather than counted again for the sections it therefore lacks.
42
44
 
@@ -44,7 +46,11 @@ The date check reads prose alone. A date inside a fence or a code span is exampl
44
46
 
45
47
  Each finding names the file and the line, such as `claude/skills/<name>/references/<file>.md line 12: <date>`. A date after "measured" or "verified" reports like any other, unlike the context audit, because a skill body states the rule a session follows today rather than a reading of the tree.
46
48
 
47
- The practice check reads only the skills the audit lists, which the JSON record carries as `checkpoints.practiceSkills`. The list names folders under the toolkit's shipped `claude/skills/` corpus alone, so a project's own skill is never read as a practice skill and a same-named folder under `.claude/skills/` produces no finding. Where `claude/skills/` resolves, a listed folder it does not hold reports as a missing skill, so a renamed or misspelled entry cannot pass unread. Each closing section matches only as an exact H2 outside a fence, so an H3 or a heading carrying more words reports as missing.
49
+ The practice check reads only the skills the audit lists, which the JSON record carries as `checkpoints.practiceSkills` for the closing sections and `checkpoints.ledgerSkills` for the ledger. The ledger list holds every practice skill plus the skills that cite outside sources without a practice's closing shape, so a skill on it alone owes the ledger and none of the sections.
50
+
51
+ Both lists name folders under the toolkit's shipped `claude/skills/` corpus alone, so a project's own skill is never read as a practice skill and a same-named folder under `.claude/skills/` produces no finding. Where `claude/skills/` resolves, a listed folder it does not hold reports as a missing skill, so a renamed or misspelled entry cannot pass unread. Each closing section matches only as an exact H2 outside a fence, so an H3 or a heading carrying more words reports as missing.
52
+
53
+ The contents check counts every line of a reference, frontmatter included, the way `wc -l` does, so a file of exactly 100 lines passes and one of 101 needs the list. `## Contents` matches the same way the closing sections do, as an exact H2 outside a fence. `SKILL.md` is never read for it, and the threshold travels in the JSON record as `checkpoints.contentsThreshold`.
48
54
 
49
55
  ## What it leaves alone
50
56
 
@@ -56,7 +62,9 @@ A check with no rule behind it prints an opinion as a defect, which is where the
56
62
 
57
63
  ## Exit codes
58
64
 
59
- Exit codes are `0` for a clean run, `1` for a refusal, and `2` for a skill folder carrying no `REQUIREMENT.md`. Only presence sets a failing code. Name, description, folder, requirement-section, dated-provenance, and practice shape findings print and return `0`, because each is a judgment a reader settles and failing a push on one would make the check something to route around. In the toolkit, two `bun run check` stages read the same report in-process and fail a push on dated provenance and on practice shape, since its own corpus is held at zero on both.
65
+ Exit codes are `0` for a clean run, `1` for a refusal, and `2` for a skill folder carrying no `REQUIREMENT.md`. Only presence sets a failing code. Name, description, folder, requirement-section, dated-provenance, practice shape, reference contents, and family findings print and return `0`, because each is a judgment a reader settles and failing a push on one would make the check something to route around. In the toolkit, three `bun run check` stages read the same report in-process and fail a push on dated provenance, on practice shape, and on family, since its own corpus is held at zero on all three.
66
+
67
+ No stage reads reference contents, so a long reference without a list stays a report.
60
68
 
61
69
  ## The requirement gate
62
70
 
@@ -1,16 +1,28 @@
1
1
  ---
2
2
  title: Slides
3
- description: What a folder of HTML slides declares for the whole deck in deck.json, the faces it embeds, what each slide declares on its own body, transitions and entrances, the master built from the project's tokens, speaker notes, charts, and what each refusal reports
3
+ description: Where a deck folder lives and what it holds, what it declares for the whole deck in deck.json, the faces it embeds, what each slide declares on its own body, transitions and entrances, the master built from the project's tokens, speaker notes, charts, and what each refusal reports
4
4
  ---
5
5
 
6
6
  # Slides
7
7
 
8
- `canon slides render --source <folder>` turns a folder of `.html` slides into an editable PowerPoint deck. Each slide describes its own shapes. What belongs to the whole deck, being the bands, the numbers, and the mark, sits in one file beside them, and the master that carries it takes the project's own colors and face.
8
+ `canon slides render <deck>` turns a folder of `.html` slides into an editable PowerPoint deck. Each deck lives in its own folder under `.canon/slides/`, which `canon records push` backs and git ignores, and `canon slides list --json` lists them. Each slide describes its own shapes. What belongs to the whole deck, being the bands, the numbers, and the mark, sits in one file beside them, and the master that carries it takes the project's own colors and face.
9
9
 
10
10
  ```bash
11
- canon slides render --source slides/q3-review
11
+ canon slides list --json
12
+ canon slides render q3-review
12
13
  ```
13
14
 
15
+ ## The deck folder
16
+
17
+ | Path | Holds |
18
+ | -------------------------------- | ---------------------------------------------------- |
19
+ | `.canon/slides/<deck>/*.html` | the slides, rendered in filename order |
20
+ | `.canon/slides/<deck>/deck.json` | what belongs to the whole deck, described below |
21
+ | `.canon/slides/<deck>/assets/` | images the slides reference by a relative path |
22
+ | `.canon/slides/layouts/` | the project's shared layouts, never listed as a deck |
23
+
24
+ A folder holding no `.html` file is not a deck. `render` with no name takes the only deck there is, and refuses with the list when there are several. It also takes a folder path outside `.canon/slides/`.
25
+
14
26
  ## The deck file
15
27
 
16
28
  `deck.json` beside the slides is optional. Without it the deck gets its defaults.