@erclx/canon 4.67.0 → 4.69.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 (160) hide show
  1. package/claude/.claude-plugin/plugin.json +1 -1
  2. package/claude/skills/{claude-autoship → auto-ship}/REQUIREMENT.md +3 -3
  3. package/claude/skills/{claude-autoship → auto-ship}/SKILL.md +36 -36
  4. package/claude/skills/canon-cli/REQUIREMENT.md +2 -2
  5. package/claude/skills/canon-cli/SKILL.md +2 -2
  6. package/claude/skills/canon-feedback-triage/REQUIREMENT.md +1 -1
  7. package/claude/skills/canon-feedback-triage/SKILL.md +3 -3
  8. package/claude/skills/canon-operator/REQUIREMENT.md +1 -1
  9. package/claude/skills/canon-operator/SKILL.md +4 -4
  10. package/claude/skills/canon-rollout/REQUIREMENT.md +6 -6
  11. package/claude/skills/canon-rollout/SKILL.md +7 -7
  12. package/claude/skills/{claude-design-extract → design-extract}/REQUIREMENT.md +4 -4
  13. package/claude/skills/{claude-design-extract → design-extract}/SKILL.md +1 -1
  14. package/claude/skills/{claude-docs → docs-fold}/REQUIREMENT.md +3 -3
  15. package/claude/skills/{claude-docs → docs-fold}/SKILL.md +14 -14
  16. package/claude/skills/{claude-docs → docs-fold}/references/anchor-sweep.md +1 -1
  17. package/claude/skills/{claude-docs → docs-fold}/references/wireframe-sweep.md +1 -1
  18. package/claude/skills/docs-sync/REQUIREMENT.md +3 -3
  19. package/claude/skills/docs-sync/SKILL.md +1 -1
  20. package/claude/skills/draft-and-pick/REQUIREMENT.md +4 -4
  21. package/claude/skills/draft-and-pick/SKILL.md +6 -6
  22. package/claude/skills/draft-context/REQUIREMENT.md +2 -2
  23. package/claude/skills/draft-context/SKILL.md +3 -3
  24. package/claude/skills/{claude-diagram → draft-diagram}/REQUIREMENT.md +4 -4
  25. package/claude/skills/{claude-diagram → draft-diagram}/SKILL.md +3 -3
  26. package/claude/skills/draft-docs/REQUIREMENT.md +1 -1
  27. package/claude/skills/draft-wireframes/REQUIREMENT.md +1 -1
  28. package/claude/skills/draft-wireframes/SKILL.md +2 -2
  29. package/claude/skills/git-followup/REQUIREMENT.md +1 -1
  30. package/claude/skills/git-followup/SKILL.md +1 -1
  31. package/claude/skills/git-pr/SKILL.md +3 -3
  32. package/claude/skills/git-ship/REQUIREMENT.md +2 -2
  33. package/claude/skills/git-ship/SKILL.md +8 -8
  34. package/claude/skills/git-worktree/REQUIREMENT.md +2 -2
  35. package/claude/skills/git-worktree/SKILL.md +3 -3
  36. package/claude/skills/identity/REQUIREMENT.md +2 -2
  37. package/claude/skills/identity/SKILL.md +3 -3
  38. package/claude/skills/{claude-markdown-propose → markdown-propose}/REQUIREMENT.md +8 -8
  39. package/claude/skills/{claude-markdown-propose → markdown-propose}/SKILL.md +5 -5
  40. package/claude/skills/{claude-markdown-propose → markdown-propose}/references/format.md +1 -1
  41. package/claude/skills/{claude-memory-capture → memory-capture}/REQUIREMENT.md +5 -5
  42. package/claude/skills/{claude-memory-capture → memory-capture}/SKILL.md +13 -13
  43. package/claude/skills/{claude-memory-review → memory-review}/REQUIREMENT.md +4 -4
  44. package/claude/skills/{claude-memory-review → memory-review}/SKILL.md +10 -10
  45. package/claude/skills/migration-context/SKILL.md +1 -1
  46. package/claude/skills/migration-standards-drop/REQUIREMENT.md +1 -1
  47. package/claude/skills/migration-superseded/REQUIREMENT.md +1 -1
  48. package/claude/skills/{claude-feature → plan-feature}/REQUIREMENT.md +4 -4
  49. package/claude/skills/{claude-feature → plan-feature}/SKILL.md +4 -4
  50. package/claude/skills/{claude-groundwork → plan-groundwork}/REQUIREMENT.md +5 -5
  51. package/claude/skills/{claude-groundwork → plan-groundwork}/SKILL.md +8 -8
  52. package/claude/skills/{claude-intake → plan-intake}/REQUIREMENT.md +6 -6
  53. package/claude/skills/{claude-intake → plan-intake}/SKILL.md +10 -10
  54. package/claude/skills/{claude-intake-answer → plan-intake-answer}/REQUIREMENT.md +4 -4
  55. package/claude/skills/{claude-intake-answer → plan-intake-answer}/SKILL.md +5 -5
  56. package/claude/skills/{claude-address-review → review-address}/REQUIREMENT.md +5 -5
  57. package/claude/skills/{claude-address-review → review-address}/SKILL.md +6 -6
  58. package/claude/skills/{claude-address-review → review-address}/references/rebase-conflicts.md +1 -1
  59. package/claude/skills/{claude-review → review-branch}/REQUIREMENT.md +4 -4
  60. package/claude/skills/{claude-review → review-branch}/SKILL.md +4 -4
  61. package/claude/skills/{claude-pr-review → review-pr}/REQUIREMENT.md +5 -5
  62. package/claude/skills/{claude-pr-review → review-pr}/SKILL.md +11 -11
  63. package/claude/skills/{claude-orchestrate → role-orchestrator}/REQUIREMENT.md +5 -5
  64. package/claude/skills/{claude-orchestrate → role-orchestrator}/SKILL.md +20 -20
  65. package/claude/skills/{claude-orchestrate → role-orchestrator}/references/orchestrator-dispatch.md +30 -30
  66. package/claude/skills/{claude-orchestrate → role-orchestrator}/references/orchestrator-handoff.md +2 -2
  67. package/claude/skills/{claude-orchestrate → role-orchestrator}/references/orchestrator-parked.md +8 -8
  68. package/claude/skills/{claude-orchestrate → role-orchestrator}/references/orchestrator-poll.md +8 -8
  69. package/claude/skills/{claude-orchestrate → role-orchestrator}/references/orchestrator-resume.md +1 -1
  70. package/claude/skills/{claude-orchestrate → role-orchestrator}/references/orchestrator-sweep.md +1 -1
  71. package/claude/skills/{claude-orchestrate → role-orchestrator}/scripts/poll.sh +6 -6
  72. package/claude/skills/{claude-planner → role-planner}/REQUIREMENT.md +12 -12
  73. package/claude/skills/{claude-planner → role-planner}/SKILL.md +4 -4
  74. package/claude/skills/{claude-worker → role-worker}/REQUIREMENT.md +8 -8
  75. package/claude/skills/{claude-worker → role-worker}/SKILL.md +6 -6
  76. package/claude/skills/{claude-seed-sync → seed-sync}/REQUIREMENT.md +2 -2
  77. package/claude/skills/{claude-seed-sync → seed-sync}/SKILL.md +3 -3
  78. package/claude/skills/session-map/REQUIREMENT.md +2 -2
  79. package/claude/skills/session-map/SKILL.md +2 -2
  80. package/claude/skills/session-resume/REQUIREMENT.md +2 -2
  81. package/claude/skills/session-resume/SKILL.md +2 -2
  82. package/claude/skills/{claude-worktree → session-worktree}/REQUIREMENT.md +3 -3
  83. package/claude/skills/{claude-worktree → session-worktree}/SKILL.md +6 -6
  84. package/claude/skills/setup-plugins/references/plugin-catalog.md +1 -1
  85. package/claude/skills/{claude-standards-audit → standards-audit}/REQUIREMENT.md +2 -2
  86. package/claude/skills/{claude-standards-audit → standards-audit}/SKILL.md +2 -2
  87. package/claude/skills/systematic-debugging/REQUIREMENT.md +1 -1
  88. package/claude/skills/{claude-tasks → task-board}/REQUIREMENT.md +3 -3
  89. package/claude/skills/{claude-tasks → task-board}/SKILL.md +7 -7
  90. package/claude/skills/{claude-teach → teach-workspace}/REQUIREMENT.md +2 -2
  91. package/claude/skills/{claude-teach → teach-workspace}/SKILL.md +4 -4
  92. package/claude/skills/test-first/REQUIREMENT.md +2 -2
  93. package/claude/skills/{claude-ui-test → ui-test}/REQUIREMENT.md +3 -3
  94. package/claude/skills/{claude-ui-test → ui-test}/SKILL.md +3 -3
  95. package/claude/skills/{claude-ux-audit → ux-audit}/REQUIREMENT.md +6 -6
  96. package/claude/skills/{claude-ux-audit → ux-audit}/SKILL.md +5 -5
  97. package/claude/skills/{claude-ux-measure → ux-measure}/REQUIREMENT.md +5 -5
  98. package/claude/skills/{claude-ux-measure → ux-measure}/SKILL.md +5 -5
  99. package/docs/agents/commands.md +1 -0
  100. package/docs/agents/install-and-sync.md +1 -1
  101. package/docs/agents/key-changes.md +3 -3
  102. package/docs/agents/markdown-audit.md +1 -1
  103. package/docs/agents/restated.md +1 -1
  104. package/docs/agents/review-classification.md +1 -1
  105. package/docs/agents/sandbox.md +13 -10
  106. package/docs/agents/sessions.md +1 -1
  107. package/docs/agents/state-scoped-risk.md +1 -1
  108. package/docs/agents/targets.md +1 -1
  109. package/docs/agents/tasks.md +4 -4
  110. package/docs/agents/teach.md +1 -1
  111. package/docs/target-projects.md +10 -10
  112. package/docs/workflow/ai-workflow.md +84 -84
  113. package/docs/workflow/operating-model.md +17 -17
  114. package/docs/workflow/visual-design-workflow.md +6 -6
  115. package/governance/rules/core/045-memory.md +1 -1
  116. package/governance/rules/core/085-worktrees.md +1 -1
  117. package/package.json +1 -1
  118. package/scripts/core/regen-agent-fixture.sh +1 -1
  119. package/scripts/core/regen-hero.sh +7 -7
  120. package/scripts/lib/sandbox-dispatch.sh +8 -0
  121. package/snippets/claude/decision-memo.md +1 -1
  122. package/src/autoship/paths.ts +1 -1
  123. package/src/claude/cases/all.ts +2 -2
  124. package/src/claude/cases/{claude-workflow.ts → workflow.ts} +33 -33
  125. package/src/claude/plugin-update.ts +48 -0
  126. package/src/commands/claude.ts +281 -1
  127. package/src/commands/feedback.ts +15 -5
  128. package/src/commands/gate.ts +3 -1
  129. package/src/commands/sandbox.ts +13 -4
  130. package/src/commands/sync.ts +3 -3
  131. package/src/design/components.ts +12 -0
  132. package/src/design/tokens.ts +1 -1
  133. package/src/gate/measures.ts +47 -1
  134. package/src/gov/restated.ts +2 -2
  135. package/src/markdown/structure.ts +1 -1
  136. package/src/migrate/rename.ts +4 -3
  137. package/src/pr/bijection.ts +1 -1
  138. package/src/pr/paths.ts +2 -2
  139. package/src/sandbox/expect.ts +26 -1
  140. package/src/shipped/references.ts +1 -1
  141. package/src/sync/seeds-report.ts +1 -1
  142. package/src/targets/pulls.ts +2 -2
  143. package/src/tasks/answers.ts +1 -1
  144. package/src/tasks/archive.ts +4 -4
  145. package/src/tasks/record.ts +2 -2
  146. package/src/tasks/validate.ts +1 -1
  147. package/src/teach/nav.ts +97 -3
  148. package/standards/glossary.md +8 -0
  149. package/standards/groundwork.md +1 -1
  150. package/standards/snippets.md +1 -1
  151. package/standards/tasks.md +3 -3
  152. package/standards/teach.md +2 -2
  153. package/tooling/base/configs/.husky/post-merge +3 -3
  154. package/tooling/claude/reference.md +5 -5
  155. package/tooling/claude/seeds/.claude/hooks/pr-create-log.sh +2 -2
  156. /package/claude/skills/{claude-memory-review → memory-review}/references/receipt-format.md +0 -0
  157. /package/claude/skills/{claude-orchestrate → role-orchestrator}/scripts/watch.sh +0 -0
  158. /package/claude/skills/{claude-teach → teach-workspace}/references/lesson-craft.md +0 -0
  159. /package/claude/skills/{claude-teach → teach-workspace}/references/pedagogy.md +0 -0
  160. /package/claude/skills/{claude-teach → teach-workspace}/references/promotion.md +0 -0
@@ -1,11 +1,11 @@
1
1
  ---
2
- name: claude-teach
2
+ name: teach-workspace
3
3
  description: Opens and runs a learning workspace on one subject, holding a mission, resources, numbered lessons, reference pages, a glossary, and learning records that survive across sessions, and proposes where a durable page from one belongs once it outgrows the workspace. Use when asked to "teach me X", "open a learning workspace", "I want to learn X", "quiz me on this", "continue the lesson", "resume my workspace on X", or "promote this reference page". Do NOT use to write project documentation, which belongs to the surface owning that document, and do NOT use to answer one question, which is an ordinary reply.
4
4
  disable-model-invocation: true
5
5
  argument-hint: <subject to learn, or the topic of a workspace to resume or promote>
6
6
  ---
7
7
 
8
- # Claude teach
8
+ # Teach workspace
9
9
 
10
10
  Run a learning workspace on one subject across sessions. The workspace holds what the learner has been through, so a session weeks later resumes from the folder rather than from the conversation.
11
11
 
@@ -213,7 +213,7 @@ Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. Fall back to
213
213
 
214
214
  The handoff is its own file rather than a shared one. The routed-facts file another skill writes is deleted by whichever pass folds it, so a second producer's unread work goes with it, and a sibling path costs the folding skill one more read and removes the interaction.
215
215
 
216
- An append is a whole-file operation, so send it as a plain single `Bash` command carrying a heredoc, per Step 0. Then tell the operator that `/claude-docs` folds the file in from a branch. The proposal costs nothing tracked and runs anywhere, while the page it describes is a tracked file, so the fold is a worktree operation and the workspace it came from is not.
216
+ An append is a whole-file operation, so send it as a plain single `Bash` command carrying a heredoc, per Step 0. Then tell the operator that `/docs-fold` folds the file in from a branch. The proposal costs nothing tracked and runs anywhere, while the page it describes is a tracked file, so the fold is a worktree operation and the workspace it came from is not.
217
217
 
218
218
  ## Output
219
219
 
@@ -236,7 +236,7 @@ A promotion pass reports its own shape instead, one line per page the operator c
236
236
 
237
237
  ```plaintext
238
238
  ➡️ Promoting: .canon/teach/<nn>-<topic>/reference/<slug>.md → <destination path>
239
- → Confirmed pages wait at .canon/tmp/teach-promotion/<slug>.md. Run /claude-docs from a branch to fold them in.
239
+ → Confirmed pages wait at .canon/tmp/teach-promotion/<slug>.md. Run /docs-fold from a branch to fold them in.
240
240
  ```
241
241
 
242
242
  A pass where the operator confirmed nothing writes no handoff file and reports that alone.
@@ -30,5 +30,5 @@ Without this skill, a session implementing a planned change writes the test afte
30
30
  ## Out of scope
31
31
 
32
32
  - Finding the cause of an unexplained failure: `canon:systematic-debugging`
33
- - Confirming visual output after a change lands: `070-planning.md` states the order and `claude-ui-test` covers it
34
- - The mechanical audit of whether an implementation reached history ahead of its test: `canon gov test-order`, invoked from `claude-autoship`
33
+ - Confirming visual output after a change lands: `070-planning.md` states the order and `ui-test` covers it
34
+ - The mechanical audit of whether an implementation reached history ahead of its test: `canon gov test-order`, invoked from `auto-ship`
@@ -1,9 +1,9 @@
1
1
  ---
2
- name: claude-ui-test
2
+ name: ui-test
3
3
  description: Why UI changes split into what a browser can assert and what only an eye can judge, and why the visual half is written to disk rather than printed
4
4
  ---
5
5
 
6
- # Claude UI test requirement
6
+ # UI test requirement
7
7
 
8
8
  ## Gap
9
9
 
@@ -37,7 +37,7 @@ Writing the checklist correctly to disk does not close the gap either. The file
37
37
 
38
38
  ## Out of scope
39
39
 
40
- - Judging whether the UI is any good, which `claude-ux-audit` owns
40
+ - Judging whether the UI is any good, which `ux-audit` owns
41
41
  - Unit and component tests, which belong to implementation
42
42
  - Deciding whether an outstanding checklist blocks the ship, which the calling pipeline gates on
43
43
  - Performing the visual verification, which needs a person
@@ -1,9 +1,9 @@
1
1
  ---
2
- name: claude-ui-test
2
+ name: ui-test
3
3
  description: Generates and runs Playwright e2e tests for UI changes, with a manual checklist for visual-only items. Use after implementing UI changes, or when asked "what should I test", "what do I verify", or "give me a test checklist". Do NOT use in empty sessions with no implementation context.
4
4
  ---
5
5
 
6
- # Claude UI test
6
+ # UI test
7
7
 
8
8
  ## Guards
9
9
 
@@ -59,7 +59,7 @@ If all changes are automatable, skip the manual checklist:
59
59
 
60
60
  Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. Fall back to `latest` on an empty result.
61
61
 
62
- When a manual checklist is produced, write it directly to `.canon/tmp/ui-checklist/<slug>.md` at the main worktree root, not the current worktree. Resolve that root the way `claude-worktree` does. Create the directory if it does not exist. Always overwrite. This is a handoff file rather than a deliverable: `git-pr` posts it as a pull request comment once one opens, then removes it, and nothing here talks to `gh` directly.
62
+ When a manual checklist is produced, write it directly to `.canon/tmp/ui-checklist/<slug>.md` at the main worktree root, not the current worktree. Resolve that root the way `session-worktree` does. Create the directory if it does not exist. Always overwrite. This is a handoff file rather than a deliverable: `git-pr` posts it as a pull request comment once one opens, then removes it, and nothing here talks to `gh` directly.
63
63
 
64
64
  From a linked worktree the file-editing tools refuse that path, so the checklist goes out through `Bash`. Send the `mkdir -p` and the heredoc as two plain commands rather than joining them with `&&`, which is refused as compound.
65
65
 
@@ -1,9 +1,9 @@
1
1
  ---
2
- name: claude-ux-audit
2
+ name: ux-audit
3
3
  description: Why UI roughness is reported against stated intent rather than taste, and why the audit observes without fixing
4
4
  ---
5
5
 
6
- # Claude UX audit requirement
6
+ # UX audit requirement
7
7
 
8
8
  ## Gap
9
9
 
@@ -34,7 +34,7 @@ The pass slides into fixing what it finds, and then the audit and the change lan
34
34
  ## Out of scope
35
35
 
36
36
  - Fixing what it found, which is a separate change with its own review
37
- - Feature planning, which `claude-feature` owns
38
- - Verifying one specific change, which `claude-ui-test` owns
39
- - Defining the intent it audits against, which `claude-design-extract` and the wireframes own
40
- - Measuring what a running interface costs to paint, block, or shift, which `claude-ux-measure` owns. Contrast stays here rather than going with it, being computable from two color values this skill already reads off the token table.
37
+ - Feature planning, which `plan-feature` owns
38
+ - Verifying one specific change, which `ui-test` owns
39
+ - Defining the intent it audits against, which `design-extract` and the wireframes own
40
+ - Measuring what a running interface costs to paint, block, or shift, which `ux-measure` owns. Contrast stays here rather than going with it, being computable from two color values this skill already reads off the token table.
@@ -1,14 +1,14 @@
1
1
  ---
2
- name: claude-ux-audit
3
- description: Audits the current UI for incomplete, inconsistent, or confusing patterns. Reads DESIGN.md and .claude/wireframes/ for intent, scans UI files, and outputs observations grouped by surface. Use when asked "audit the UX", "audit the UI", "UX audit", or "find UI roughness". Do NOT use for new feature planning or code changes, and do NOT use to measure what a running interface costs to paint, which is `claude-ux-measure`.
2
+ name: ux-audit
3
+ description: Audits the current UI for incomplete, inconsistent, or confusing patterns. Reads DESIGN.md and .claude/wireframes/ for intent, scans UI files, and outputs observations grouped by surface. Use when asked "audit the UX", "audit the UI", "UX audit", or "find UI roughness". Do NOT use for new feature planning or code changes, and do NOT use to measure what a running interface costs to paint, which is `ux-measure`.
4
4
  ---
5
5
 
6
- # Claude UX audit
6
+ # UX audit
7
7
 
8
8
  ## Guards
9
9
 
10
10
  - If no UI files exist in the project (no JSX, TSX, Vue, Svelte, or HTML under `src/`), stop: `❌ No UI surfaces found to audit.`
11
- - If the request asks what the interface costs to paint, block, or shift at runtime, run nothing and name `claude-ux-measure`. This skill reads source and reaches no number a browser produces. Contrast is the exception and stays here, since it is computable from the two color values already in the token table.
11
+ - If the request asks what the interface costs to paint, block, or shift at runtime, run nothing and name `ux-measure`. This skill reads source and reaches no number a browser produces. Contrast is the exception and stays here, since it is computable from the two color values already in the token table.
12
12
 
13
13
  ## Step 1: read context
14
14
 
@@ -59,7 +59,7 @@ If nothing is wrong, use: `✅ No observations.`
59
59
 
60
60
  Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. Fall back to `latest` on an empty result.
61
61
 
62
- Write the full report directly to `.canon/review/ux-audit-<slug>.md` at the main worktree root, not the current worktree. Resolve that root the way `claude-worktree` does. Create the directory if it does not exist. Always overwrite.
62
+ Write the full report directly to `.canon/review/ux-audit-<slug>.md` at the main worktree root, not the current worktree. Resolve that root the way `session-worktree` does. Create the directory if it does not exist. Always overwrite.
63
63
 
64
64
  From a linked worktree the file-editing tools refuse that path, so the report goes out through `Bash`. Send the `mkdir -p` and the heredoc as two plain commands rather than joining them with `&&`, which is refused as compound.
65
65
 
@@ -1,9 +1,9 @@
1
1
  ---
2
- name: claude-ux-measure
2
+ name: ux-measure
3
3
  description: Why a rendering cost question is answered with a number against a published threshold, and why the runner is detected rather than prescribed
4
4
  ---
5
5
 
6
- # Claude UX measure requirement
6
+ # UX measure requirement
7
7
 
8
8
  ## Gap
9
9
 
@@ -41,8 +41,8 @@ A session that does start one picks a runner on the spot. The reading then comes
41
41
 
42
42
  ## Out of scope
43
43
 
44
- - Judging the interface against stated intent, which `claude-ux-audit` owns
45
- - Contrast, which is computable from two color values in the token table `claude-ux-audit` already reads. A contrast failure from a color computed at runtime stays invisible to that reader, and the cost is accepted rather than overlooked.
44
+ - Judging the interface against stated intent, which `ux-audit` owns
45
+ - Contrast, which is computable from two color values in the token table `ux-audit` already reads. A contrast failure from a color computed at runtime stays invisible to that reader, and the cost is accepted rather than overlooked.
46
46
  - Network waterfall, bundle size, and accessibility, which no version of this measures
47
- - Writing behavioral tests against the interface, which `claude-ui-test` owns
47
+ - Writing behavioral tests against the interface, which `ui-test` owns
48
48
  - Fixing what the reading found
@@ -1,16 +1,16 @@
1
1
  ---
2
- name: claude-ux-measure
3
- description: Measures paint, processor, and layout cost against a running interface and reports numbers against published thresholds. Detects the project's existing browser harness rather than requiring one. Use when asked "how fast is this page", "measure the UI", "what does this cost to render", "check Core Web Vitals", or "profile the interface". Do NOT use to judge UI quality by reading source, which is `claude-ux-audit`.
2
+ name: ux-measure
3
+ description: Measures paint, processor, and layout cost against a running interface and reports numbers against published thresholds. Detects the project's existing browser harness rather than requiring one. Use when asked "how fast is this page", "measure the UI", "what does this cost to render", "check Core Web Vitals", or "profile the interface". Do NOT use to judge UI quality by reading source, which is `ux-audit`.
4
4
  ---
5
5
 
6
- # Claude UX measure
6
+ # UX measure
7
7
 
8
8
  Report numbers. A sentence about what the source looks like is what this exists to replace, so every finding is a reading beside the threshold it is measured against.
9
9
 
10
10
  ## Guards
11
11
 
12
12
  - If the project names no command that serves an interface and the user names no URL, stop: `❌ Nothing to serve. Name a running URL or a command that starts one.` Test for a servable interface rather than for source under a particular folder, since this measures what a browser receives and never reads the tree that produced it.
13
- - If the request is about intent, consistency, missing states, or contrast, run nothing and name `claude-ux-audit`. That skill reads source and this one runs the interface.
13
+ - If the request is about intent, consistency, missing states, or contrast, run nothing and name `ux-audit`. That skill reads source and this one runs the interface.
14
14
 
15
15
  ## Step 1: reach the interface
16
16
 
@@ -106,7 +106,7 @@ Report the reading and stop there. A remedy for a poor verdict is a change with
106
106
 
107
107
  Derive `<slug>` per `${CLAUDE_SKILL_DIR}/../../standards/slug.md`. Fall back to `latest` on an empty result.
108
108
 
109
- Write the full reading directly to `.canon/review/ux-measure-<slug>.md` at the main worktree root, not the current worktree. Resolve that root the way `claude-worktree` does. Create the directory if it does not exist. Always overwrite.
109
+ Write the full reading directly to `.canon/review/ux-measure-<slug>.md` at the main worktree root, not the current worktree. Resolve that root the way `session-worktree` does. Create the directory if it does not exist. Always overwrite.
110
110
 
111
111
  From a linked worktree the file-editing tools refuse that path, so the reading goes out through `Bash`. Send the `mkdir -p` and the heredoc as two plain commands rather than joining them with `&&`, which is refused as compound.
112
112
 
@@ -68,6 +68,7 @@ Full help: `canon <command> --help`. Behavior notes for the install and sync ver
68
68
  | `canon claude skills reach` | Report the bodies in either skill corpus citing a toolkit path no target project receives, exiting 2 on an unqualified one |
69
69
  | `canon claude skills rank` | Score either skill corpus's descriptions against a case corpus by TF-IDF cosine similarity, reporting rank-one and top-three (`--cases <path>`) |
70
70
  | `canon claude routing` | Report per `CLAUDE.md` section how many bullets name a path and how many of those a path-scoped rule already covers (`--json`) |
71
+ | `canon claude plugin-update` | Match the installed marketplace plugin against `claude/.claude-plugin/plugin.json`'s own name and run `claude plugin update` on it, reading the version back off `claude plugin list --json` since the update call reports none of its own (`--json`) |
71
72
  | `canon gov test-order` | Report where an implementation reached history ahead of the test covering it (`--json`) |
72
73
  | `canon gov superseded` | Report where the tree still asserts a value a changed convention no longer produces, keyed on the value and on the family stem behind a templated citation (`--json`) |
73
74
  | `canon gov restated` | Report every instruction the always-loaded file or a rule shares with the seed, a shipped skill body, or another rule, classed and with its anchors named (`--json`) |
@@ -232,7 +232,7 @@ finding the rendered half withheld.
232
232
  equivalent, since the domain walk lists what a target installed and cannot see a
233
233
  file that never arrived. There is no `customized` verdict here, because that one
234
234
  needs a stamp and seeds carry none, so a file history cannot attribute stays
235
- `drifted`. Reconcile the section with `claude-seed-sync`, which merges one
235
+ `drifted`. Reconcile the section with `seed-sync`, which merges one
236
236
  section at a time rather than replacing a file the project edits.
237
237
 
238
238
  A markdown seed installs rewritten rather than copied, since the `stub: true`
@@ -37,7 +37,7 @@ They are reported apart because they want different tolerances.
37
37
  - **`unmet`** is a whole path the body claims ahead of its bullet's first comma and the diff does not carry. This is the graded direction and it sets the exit code. A bullet naming an untouched file is wrong more often than not, and it corrupts the record that reaches the trunk.
38
38
  - **`unnamed`** is a changed file no bullet reached that a reader might have wanted one for. Reported with no grade, since a change can be too small to describe and still be correctly absent. Grading it would fire on nearly every branch.
39
39
  - **`incidental`** is a changed file no bullet reached that owes none: a test beside its subject, anything under a fixture or snapshot folder, and a lockfile a package manager writes. Held apart so the count above reads, and reported rather than dropped so a run still says what it set aside.
40
- - **`unresolved`** is a path the reading could not judge either way. Two causes reach it: a path written partially, such as `claude-worker/SKILL.md` for a file under `claude/skills/`, and a path past its bullet's first comma.
40
+ - **`unresolved`** is a path the reading could not judge either way. Two causes reach it: a path written partially, such as `role-worker/SKILL.md` for a file under `claude/skills/`, and a path past its bullet's first comma.
41
41
 
42
42
  Each direction splits on one question, which is whether the evidence is strong enough to raise with a person. A partial path and a trailing path can each credit a changed file and can never accuse one, because nothing separates a path written short from a path written wrong, or a second claim from a file cited for context. Neither split drops anything: what comes out of `unmet` lands in `unresolved` and what comes out of `unnamed` lands in `incidental`, so a count a reader can act on never costs a file the run stayed silent about.
43
43
 
@@ -49,7 +49,7 @@ Only `## Key Changes` is read. `## Technical Context` legitimately names files a
49
49
 
50
50
  Inside the section, every backticked span in a bullet is read, and the bullet's first comma outside a span divides the ones that can accuse from the ones that can only credit. That one lever was chosen by measurement. Over the 23 merged pull requests in this repository carrying the section, reading whole bullets reported 16 paths as claimed-but-untouched and every one was a file the body named for context. Cutting at the comma left 110 claims of the original 149 and took the false reports to 2. A list of sixteen clause-opening words tried beside it removed nothing the comma had not already removed, because this corpus punctuates every one of them.
51
51
 
52
- The cut used to decide whether a span was read at all, and the paths past the comma fell out of the claim set into `unnamed`. That was accepted on the ground that the ungraded direction does no damage, and it did: `claude-pr-review` read `unnamed` as a question to put to the branch author, so on 2026-09-01 the question went to three pull requests over bullets that had named the files all along. Reading the whole bullet as claims outright is the obvious repair and the corpus refuses it, taking `unmet` from 10 to 19 over the 40 most recent merged pull requests carrying the section, with all nine additions in the context class the cut exists to exclude. Reading the whole bullet and gating the accusation on the cut gives claims 243 to 314 and unnamed 1124 to 1058 with `unmet` identical entry for entry.
52
+ The cut used to decide whether a span was read at all, and the paths past the comma fell out of the claim set into `unnamed`. That was accepted on the ground that the ungraded direction does no damage, and it did: `review-pr` read `unnamed` as a question to put to the branch author, so on 2026-09-01 the question went to three pull requests over bullets that had named the files all along. Reading the whole bullet as claims outright is the obvious repair and the corpus refuses it, taking `unmet` from 10 to 19 over the 40 most recent merged pull requests carrying the section, with all nine additions in the context class the cut exists to exclude. Reading the whole bullet and gating the accusation on the cut gives claims 243 to 314 and unnamed 1124 to 1058 with `unmet` identical entry for entry.
53
53
 
54
54
  A span anywhere in the bullet has to survive all of these:
55
55
 
@@ -109,4 +109,4 @@ One class stays open and is named rather than closed. A bullet can cite where so
109
109
 
110
110
  ## Where it runs
111
111
 
112
- `claude-pr-review` 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.
112
+ `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.
@@ -162,7 +162,7 @@ The target push stage reads the same exit codes `canon gate run`'s own stage rea
162
162
 
163
163
  The target push stage excludes `CHANGELOG.md`, unlike every other surface here. A changelog a generator builds from commit subjects carries prose nobody wrote against the ban set, where this repository's own passes only because `release-please` builds it from subjects sessions already wrote to the rule. The stage passes an explicit file list rather than the bare invocation the other surfaces use, so a corpus with no file left once the changelog is set aside reads as a pass rather than falling back to the whole tree.
164
164
 
165
- The fifth surface reads the standards directly and is not a consolidation left half done. `claude/skills/claude-standards-audit/SKILL.md` greps the banned tokens agent-side, which is a session reading prose rather than a process it can shell out to, and it ships to every target. It is the likeliest place for the next drift, since nothing compares it against the verb.
165
+ The fifth surface reads the standards directly and is not a consolidation left half done. `claude/skills/standards-audit/SKILL.md` greps the banned tokens agent-side, which is a session reading prose rather than a process it can shell out to, and it ships to every target. It is the likeliest place for the next drift, since nothing compares it against the verb.
166
166
 
167
167
  The hook prefers a checkout's own `src/cli.ts` over a globally installed binary, so it and the push stage read one build. A published binary lags a branch by whatever has not been released, which would put a ban kind added on the branch into the push and not into the edit. It reads its findings out of the `--json` record rather than off the exit code, so an older binary still reports where the fallback applies. It reads `bans.emptySets` out of the same record, so a set the verb shipped empty reaches the author as a check narrowed to what it could measure rather than as a clean pass.
168
168
 
@@ -46,7 +46,7 @@ Every record names the anchors its match rested on, so a reader can weigh a find
46
46
 
47
47
  ## The three classes
48
48
 
49
- - **Mirror.** Both files sit on a declared path pair whose duplication is deliberate. `CLAUDE.md` and the seed are the one pair, since the seed is authored from it and `claude-seed-sync` exists to reconcile the two. Excluding by pair rather than by content is the point: the duplication is a location fact this repository already records, and a content test would rediscover it on every run.
49
+ - **Mirror.** Both files sit on a declared path pair whose duplication is deliberate. `CLAUDE.md` and the seed are the one pair, since the seed is authored from it and `seed-sync` exists to reconcile the two. Excluding by pair rather than by content is the point: the duplication is a location fact this repository already records, and a content test would rediscover it on every run.
50
50
  - **Repetition.** Two surfaces state one rule and neither is declared a copy of the other.
51
51
  - **Contradiction.** The prohibition falls on one surface alone, on a match strong enough to read that as a disagreement. This is a polarity reading rather than a judgment about meaning, so weigh each against the surfaces it names.
52
52
 
@@ -64,7 +64,7 @@ An empty set refuses with `no-changes` rather than skipping. Both tests are univ
64
64
 
65
65
  ## Why it is a verb
66
66
 
67
- The decision was three sentences in `claude-autoship`'s review step, applied by a session reading a bulleted list of paths. It failed three times. A driven arm on 2026-08-30 staged `.claude/skills/deploy-check/SKILL.md`, which that list names, and the chain skipped review and opened a draft pull request anyway. The rule was correct and the session did not apply it, and the two fixes before that one were each a rewrite of the same prose.
67
+ The decision was three sentences in `auto-ship`'s review step, applied by a session reading a bulleted list of paths. It failed three times. A driven arm on 2026-08-30 staged `.claude/skills/deploy-check/SKILL.md`, which that list names, and the chain skipped review and opened a draft pull request anyway. The rule was correct and the session did not apply it, and the two fixes before that one were each a rewrite of the same prose.
68
68
 
69
69
  A rule a session can talk itself out of moves into a verb. That is the same argument the quiz-order draw in `canon teach lesson` was decided on: an instruction is a hope where a verb is a check.
70
70
 
@@ -22,17 +22,18 @@ Scenario categories: `infra:*` (domain flows), `git:*`, `scaffold:*`. `create` s
22
22
  `canon sandbox check <category>:<command> [arm]` scores a provisioned sandbox against the arm's `expect.toml`, printing a verdict on stderr and, with `--json`, the same verdict as a record on stdout.
23
23
 
24
24
  ```bash
25
- canon sandbox check claude:docs drift --json
25
+ canon sandbox check claude:docs-fold drift --json
26
26
  ```
27
27
 
28
- | Flag | Effect |
29
- | ------------------- | --------------------------------------------------------------------------- |
30
- | `--envelope <file>` | Read `is_error`, `num_turns`, denials, and the reply text |
31
- | `--writes <file>` | Newline-delimited paths the session wrote, for write scope |
32
- | `--escapes <file>` | Newline-delimited paths written to a watched toolkit root, for escape scope |
33
- | `--escapes-watched` | At least one watched root held a target this run |
34
- | `--json` | Emit the verdict record on stdout |
35
- | `--strict` | Exit 1 on `unchecked` instead of 0 |
28
+ | Flag | Effect |
29
+ | ------------------------------ | ----------------------------------------------------------------------------------------------------------------- |
30
+ | `--envelope <file>` | Read `is_error`, `num_turns`, denials, and the reply text |
31
+ | `--writes <file>` | Newline-delimited paths the session wrote, for write scope |
32
+ | `--escapes <file>` | Newline-delimited paths written to a watched toolkit root, for escape scope |
33
+ | `--escapes-watched` | At least one watched root held a target this run |
34
+ | `--concurrent-sessions <file>` | Newline-delimited sessions live in the registry both before and after this run, a witness for an unbounded escape |
35
+ | `--json` | Emit the verdict record on stdout |
36
+ | `--strict` | Exit 1 on `unchecked` instead of 0 |
36
37
 
37
38
  The verdict `state` is `pass`, `fail`, or `unchecked`. An arm with no `expect.toml` is `unchecked` and exits 0, so the harness stays usable while expectations roll out. A declaration that exists but asserts nothing is a failure, since an expectation file that asserts nothing passes every run.
38
39
 
@@ -70,4 +71,6 @@ A skill pairs to a scenario by filename, `<category>-<command>` first and bare `
70
71
 
71
72
  `scripts/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/sandbox-runs/<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.
72
73
 
73
- 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, and `reap` for what the run found in the session's process group afterwards. Neither field fails a run on its own.
74
+ 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.
75
+
76
+ `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.
@@ -42,7 +42,7 @@ A bare run reports every repository and carries a `repository` field on each row
42
42
 
43
43
  The match can return more than one session. Read the count rather than the first row, since nothing stops two sessions holding one branch, and a caller that treats the result as singular picks among candidates without knowing it.
44
44
 
45
- Resolution reads a session's registered `cwd`, taken at whatever `locate()` finds there rather than wherever it has since worked. That registration updates whenever the harness enters a worktree: a worker dispatched onto `main` re-registers at its own branch once `claude-autoship` Step 0 runs. What stays fixed is a session moved by shell command, `cd` or `git -C` against another root, with no worktree entry behind it, so it answers only for the branch its last registered `cwd` sits in.
45
+ Resolution reads a session's registered `cwd`, taken at whatever `locate()` finds there rather than wherever it has since worked. That registration updates whenever the harness enters a worktree: a worker dispatched onto `main` re-registers at its own branch once `auto-ship` Step 0 runs. What stays fixed is a session moved by shell command, `cd` or `git -C` against another root, with no worktree entry behind it, so it answers only for the branch its last registered `cwd` sits in.
46
46
 
47
47
  A session whose `cwd` reflects a harness worktree entry, at launch or mid-session, resolves fully, covering every dispatched worker once Step 0 runs. A zero for a different branch it is genuinely working on is not evidence the branch is unclaimed, only that a shell-moved registration cannot see it.
48
48
 
@@ -5,7 +5,7 @@ description: Reading committed state rather than an arriving change, the shipped
5
5
 
6
6
  # State-scoped risk
7
7
 
8
- Every review surface a session can reach is scoped to a change. `claude-review` reads the branch diff, `claude-pr-review` reads a pull request, and `code-review` takes a diff, a branch, or a path. A risk that arrived before the range under review is invisible to all three by construction, which is what these two commands answer.
8
+ Every review surface a session can reach is scoped to a change. `review-branch` reads the branch diff, `review-pr` reads a pull request, and `code-review` takes a diff, a branch, or a path. A risk that arrived before the range under review is invisible to all three by construction, which is what these two commands answer.
9
9
 
10
10
  | Question | Command |
11
11
  | -------------------------------------------------------- | -------------------- |
@@ -78,7 +78,7 @@ Exit codes: `0` at least one target was read, `1` refused or every target refuse
78
78
 
79
79
  `checks` is `null` rather than `passing` when no check ran at all, which is not the same answer. A failure outranks a run still going, since a job that already failed cannot be cleared by one still in flight.
80
80
 
81
- `review` reads the first line of the newest pass carrying `## Review` or `## Review closed`, which `claude-pr-review` owns and posts. A target leaves a wave on `closed` rather than on a worker's reply.
81
+ `review` reads the first line of the newest pass carrying `## Review` or `## Review closed`, which `review-pr` owns and posts. A target leaves a wave on `closed` rather than on a worker's reply.
82
82
 
83
83
  A target that could not be read carries a `reason` rather than an empty pull list. Reading a failed query as no open work is what reports a target as done having read nothing, which is the failure mode of the hand-written shell loop this replaces.
84
84
 
@@ -148,9 +148,9 @@ The record carries `type`, `slug`, `branch`, `words`, and `conforms`. Exit codes
148
148
 
149
149
  `slug` is the plan filename with its `feature-` prefix and its extension taken off, and `type` is the constant `feat`. Reading a type off the plan's prose was the alternative, and it is the half of the derivation that has already disagreed with itself: one dispatch checked `fix/path-form-hook` against a worker that took `feat/path-form-hook`, both sides reading one plan. What makes the constant safe is that a branch type is cosmetic. `git-stage` reads a commit's type off the staged diff and `git-pr` reads a title off the diff, so the semantics a release reads never pass through the branch name. What it costs is a worktree listing where every plan-derived branch reads `feat/`, and nothing renames it later.
150
150
 
151
- `conforms` reads both caps `standards/branch.md` states, being 4 words on the description and 50 characters on the whole branch. A false reading is a row for a person rather than a name to shorten here, since a rename parts the branch slug from the plan slug that `claude-worktree` tier 1 and `git-pr`'s plan lookup both read back.
151
+ `conforms` reads both caps `standards/branch.md` states, being 4 words on the description and 50 characters on the whole branch. A false reading is a row for a person rather than a name to shorten here, since a rename parts the branch slug from the plan slug that `session-worktree` tier 1 and `git-pr`'s plan lookup both read back.
152
152
 
153
- Both sides of a dispatch call it. The orchestrator's collision check derives its candidate here, and `claude-autoship` Step 0 derives the worktree it enters from the same plan, so the branch a gate clears and the branch a session takes are one string by construction. They were two readings of one paragraph until 2026-09-06, when four dispatches on one plan produced three different strings.
153
+ Both sides of a dispatch call it. The orchestrator's collision check derives its candidate here, and `auto-ship` Step 0 derives the worktree it enters from the same plan, so the branch a gate clears and the branch a session takes are one string by construction. They were two readings of one paragraph until 2026-09-06, when four dispatches on one plan produced three different strings.
154
154
 
155
155
  ```bash
156
156
  canon tasks plan-branch dispatch-answer-gate --json | jq -r '.branch'
@@ -158,7 +158,7 @@ canon tasks plan-branch dispatch-answer-gate --json | jq -r '.branch'
158
158
 
159
159
  ## Plan link
160
160
 
161
- `canon tasks plan-link <task> <plan>` writes or corrects a task's `Plan:` line, as `Plan: [<label>](<target>)` right after the H1. `claude-feature` calls it right after a plan file lands, when Step 1 resolved an existing task for the feature, so the line is a mechanical write rather than hand-edited markdown.
161
+ `canon tasks plan-link <task> <plan>` writes or corrects a task's `Plan:` line, as `Plan: [<label>](<target>)` right after the H1. `plan-feature` calls it right after a plan file lands, when Step 1 resolved an existing task for the feature, so the line is a mechanical write rather than hand-edited markdown.
162
162
 
163
163
  Name the task by its filename stem, and the plan by its path or its slug, the same two forms `canon tasks plan-answers` accepts:
164
164
 
@@ -321,7 +321,7 @@ A task file neither surface names lands in a fourth array, on the same reasoning
321
321
  }
322
322
  ```
323
323
 
324
- Under the roster-checked hand-off `claude-tasks` and `claude-groundwork` state, filing a task and placing its row are two acts a different session each may take, so a task caught between the two is ordinary rather than a finding and this array moves no exit code. It still reports, since it is the only local detector for a row a hand-edit dropped, a handoff message that never arrived, or an orchestrator that ended before placing it.
324
+ Under the roster-checked hand-off `task-board` and `plan-groundwork` state, filing a task and placing its row are two acts a different session each may take, so a task caught between the two is ordinary rather than a finding and this array moves no exit code. It still reports, since it is the only local detector for a row a hand-edit dropped, a handoff message that never arrived, or an orchestrator that ended before placing it.
325
325
 
326
326
  Exit codes: `0` every check passed, `1` refused, `2` at least one finding. The `reason` field carries which gate refused: `no-board`, `no-ordering`, or `no-groups`. A board grouping under headings of its own trips `no-groups` rather than being read against columns it never declared.
327
327
 
@@ -5,7 +5,7 @@ description: Listing learning workspaces with what their records schedule next,
5
5
 
6
6
  # Teach
7
7
 
8
- Learning workspaces sit under `.canon/teach/<nn>-<topic>/`, and `standards/teach.md` fixes their layout, naming, and file formats, apart from the glossary, whose shape `standards/glossary.md` fixes, cited from the `claude-teach` skill, so it travels with the file wherever a promotion lands it. Every verb here resolves that folder against the main worktree root rather than against the working directory, so a session standing in a linked worktree reaches the one workspace the learner has rather than opening a second.
8
+ Learning workspaces sit under `.canon/teach/<nn>-<topic>/`, and `standards/teach.md` fixes their layout, naming, and file formats, apart from the glossary, whose shape `standards/glossary.md` fixes, cited from the `teach-workspace` skill, so it travels with the file wherever a promotion lands it. Every verb here resolves that folder against the main worktree root rather than against the working directory, so a session standing in a linked worktree reaches the one workspace the learner has rather than opening a second.
9
9
 
10
10
  That root resolution is also why the writing verbs exist at all. The file-editing tools refuse a main-root path from a linked worktree and offer a worktree copy instead, and a caller naming only the destination reports a success that did not happen. A whole-file create still goes out as a shell heredoc. Changing a line inside a file that already exists has no shell route, because the stream editors are banned, so `resource` and `glossary` are the route for the two files a running workspace edits.
11
11
 
@@ -72,15 +72,15 @@ Keep the `## Scripts` table in `.claude/context/development.md` current as scrip
72
72
  Scaffold installs tooling and seeds. It does not fill the planning docs or the design system. Complete those before the first feature session:
73
73
 
74
74
  1. Fill `.claude/REQUIREMENTS.md` and `.claude/ARCHITECTURE.md`. The seed provides the files, the scope and decisions are yours to write.
75
- 2. For a UI project, invoke `canon:claude-design-extract` to draft `.claude/DESIGN.md`. With no UI code yet it takes the greenfield path and proposes tokens from the requirements and a `## Personality` section. Skip for non-UI projects.
76
- 3. Optionally invoke `canon:claude-diagram` to draft entries under `.canon/diagrams/` from the architecture and the requirements. One file per diagram kind, so a later refresh of one kind leaves the others untouched. It renders each diagram it writes to verify the layout, which downloads the Mermaid CLI on first use and takes about 15 seconds.
75
+ 2. For a UI project, invoke `canon:design-extract` to draft `.claude/DESIGN.md`. With no UI code yet it takes the greenfield path and proposes tokens from the requirements and a `## Personality` section. Skip for non-UI projects.
76
+ 3. Optionally invoke `canon:draft-diagram` to draft entries under `.canon/diagrams/` from the architecture and the requirements. One file per diagram kind, so a later refresh of one kind leaves the others untouched. It renders each diagram it writes to verify the layout, which downloads the Mermaid CLI on first use and takes about 15 seconds.
77
77
  4. Start the feature loop. See [AI workflow](workflow/ai-workflow.md) for the per-feature sequence.
78
78
 
79
79
  A machine without a renderer still gets the diagrams and is told which check was skipped.
80
80
 
81
- Each diagram entry records the commit and date it was last verified against, and nothing maintains that record for you. The folder is redrawn on demand rather than swept on every ship, so `verified` carries the whole signal: an entry whose date sits far behind your branch is due a read, and no pass will name which one. Run `canon:claude-diagram` again when the code a kind is drawn from moves.
81
+ Each diagram entry records the commit and date it was last verified against, and nothing maintains that record for you. The folder is redrawn on demand rather than swept on every ship, so `verified` carries the whole signal: an entry whose date sits far behind your branch is due a read, and no pass will name which one. Run `canon:draft-diagram` again when the code a kind is drawn from moves.
82
82
 
83
- `.claude/ARCHITECTURE.md` carries the same mechanism on the same ship. `canon:claude-docs` anchors a decision it amends to the paths that decision cites, and reports an anchored decision whose cited path the branch touched.
83
+ `.claude/ARCHITECTURE.md` carries the same mechanism on the same ship. `canon:docs-fold` anchors a decision it amends to the paths that decision cites, and reports an anchored decision whose cited path the branch touched.
84
84
 
85
85
  ### Stack decision
86
86
 
@@ -175,7 +175,7 @@ The first line reports the plan and the second applies it, relocating each rule
175
175
 
176
176
  ### Rename the skill citations, once
177
177
 
178
- Twenty-five plugin skills dropped their `claude-` prefix for two-word names, so `canon:claude-docs` answers as `canon:docs-fold` and `canon:claude-tasks` as `canon:task-board`. A project that installed governance or tooling before that release holds files naming the old ones, and the plugin answers to none of them.
178
+ Twenty-five plugin skills dropped their `claude-` prefix for two-word names, so `canon:docs-fold` answers as `canon:docs-fold` and `canon:task-board` as `canon:task-board`. A project that installed governance or tooling before that release holds files naming the old ones, and the plugin answers to none of them.
179
179
 
180
180
  Two of those files run rather than sit there. `.husky/post-merge` prints a command for a person to type, and `.claude/hooks/pr-create-log.sh` hands a session a message naming a skill, so a stale copy tells someone to invoke something that no longer exists. A rule under `.claude/rules/canon/core/` names skills too, though a rule is read rather than run.
181
181
 
@@ -202,7 +202,7 @@ The report opens by naming the binary running it. The installed version reads ag
202
202
 
203
203
  #### Then the causes
204
204
 
205
- A `stale` file still matches what the toolkit installed, so the update is mechanical. A `customized` file carries local edits, so taking the upstream version is a decision and `canon:claude-seed-sync` is the tool for it. A `stranded` file sits where an older toolkit installed it and the toolkit has since moved, which is a relocation the report names but no command runs.
205
+ A `stale` file still matches what the toolkit installed, so the update is mechanical. A `customized` file carries local edits, so taking the upstream version is a decision and `canon:seed-sync` is the tool for it. A `stranded` file sits where an older toolkit installed it and the toolkit has since moved, which is a relocation the report names but no command runs.
206
206
 
207
207
  That attribution comes from `.claude/canon/config.json`, a stamp every install and sync writes. A target stamped before that path shipped is read from the retired `.claude/canon.json` instead, reported rather than migrated. Governance records a hash per installed file, plus the stack `canon gov install` was given, and tooling records the stack chain it resolved instead of any file hash, since its install runs no per-file walk to attribute.
208
208
 
@@ -210,7 +210,7 @@ Each domain holds its own toolkit commit, so syncing governance today does not m
210
210
 
211
211
  A project that has never synced under a toolkit new enough to write a stamp falls back to the toolkit's own git history. Installed content matching any version that history published proves the file untouched, so it reports `stale` naming the commit it came from, and content matching no published version stays `drifted`. That fallback needs the toolkit as a git checkout. Installed from the registry it ships source without history, and the report says attribution was unavailable rather than reading every file as a local edit.
212
212
 
213
- Further causes sit outside the per-domain scan, each naming something that walk cannot see. A seed the project edited is reported under `seeds` and reconciled with `canon:claude-seed-sync`, since no sync command touches a seed. A file a newer seed folder replaced is reported under `superseded`, such as `.claude/TASKS.md` against the `.canon/tasks/` that now ships, and nothing moves it because the content is the project's own. A domain sitting at the root layout with nothing under `.claude/` is reported under `unmigrated`, and no command moves it either. The project moves the content itself.
213
+ Further causes sit outside the per-domain scan, each naming something that walk cannot see. A seed the project edited is reported under `seeds` and reconciled with `canon:seed-sync`, since no sync command touches a seed. A file a newer seed folder replaced is reported under `superseded`, such as `.claude/TASKS.md` against the `.canon/tasks/` that now ships, and nothing moves it because the content is the project's own. A domain sitting at the root layout with nothing under `.claude/` is reported under `unmigrated`, and no command moves it either. The project moves the content itself.
214
214
 
215
215
  `unmigrated` currently names no domain, since standards and snippets are the two the toolkit ever installed at the project root and both closed their install channel. A target still holding a root `standards/` or `snippets/` folder from an older toolkit is carrying its own authoring surface now, not an unfinished install, and nothing proposes moving either.
216
216
 
@@ -258,7 +258,7 @@ Standards take no part in that run. Nothing installed them, so there is no copy
258
258
 
259
259
  ### Targeted
260
260
 
261
- - Claude seed docs such as `CLAUDE.md` and `.claude/REQUIREMENTS.md`: invoke `canon:claude-seed-sync`. The skill splits each file into a preamble (between the H1 and the first H2) plus one part per `##` section, then diffs part by part and proposes per-part edits. User customizations are preserved.
261
+ - Claude seed docs such as `CLAUDE.md` and `.claude/REQUIREMENTS.md`: invoke `canon:seed-sync`. The skill splits each file into a preamble (between the H1 and the first H2) plus one part per `##` section, then diffs part by part and proposes per-part edits. User customizations are preserved.
262
262
  - Governance rules already installed: `canon gov sync <path>` diffs and applies, and never adds new rules. A rule your recorded stack lists reports as `missing` instead.
263
263
  - Tooling configs and seeds: `canon tooling <stack> <path>` overwrites golden configs and merges seeds
264
264
  - Reference docs for a stack: `canon tooling reference <stack>` reads and never writes, so there is nothing to sync
@@ -281,7 +281,7 @@ claude
281
281
 
282
282
  In the session, invoke `canon:setup-init`. The skill detects no framework and resolves tooling to `base` and governance to `base`. The preview marks both stacks as fallbacks, since neither came from a match, then the chain runs `canon init`.
283
283
 
284
- Ongoing: run `canon sync --check .` to see what has drifted, then invoke `canon:claude-seed-sync` for seed drift or `canon sync .` for a catch-all refresh.
284
+ Ongoing: run `canon sync --check .` to see what has drifted, then invoke `canon:seed-sync` for seed drift or `canon sync .` for a catch-all refresh.
285
285
 
286
286
  ### Web application
287
287
 
@@ -295,7 +295,7 @@ Invoke `canon:setup-init`. The skill reads `package.json` and the Vite config, r
295
295
  Ongoing maintenance:
296
296
 
297
297
  - What has drifted: `canon sync --check .`
298
- - Seed drift: invoke `canon:claude-seed-sync`
298
+ - Seed drift: invoke `canon:seed-sync`
299
299
  - Catch-all sync: `canon sync .`
300
300
  - Governance rule refresh only: `canon gov sync .`
301
301
  - Layer a new rule on top, for example `260-shadcn` after adopting shadcn: `canon gov install react --add 260-shadcn .`