@erclx/canon 5.34.0 → 5.36.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 (248) hide show
  1. package/README.md +15 -17
  2. package/claude/.claude-plugin/plugin.json +1 -1
  3. package/claude/skills/api-design/REQUIREMENT.md +1 -1
  4. package/claude/skills/auto-ship/references/draft-mark.md +1 -1
  5. package/claude/skills/canon-cli/REQUIREMENT.md +2 -2
  6. package/claude/skills/canon-cli/SKILL.md +12 -12
  7. package/claude/skills/canvas-board/REQUIREMENT.md +1 -1
  8. package/claude/skills/canvas-board/SKILL.md +2 -2
  9. package/claude/skills/canvas-board/references/design.md +53 -36
  10. package/claude/skills/codebase-layout/REQUIREMENT.md +1 -1
  11. package/claude/skills/codebase-layout/SKILL.md +2 -2
  12. package/claude/skills/create-rule/REQUIREMENT.md +6 -8
  13. package/claude/skills/create-rule/SKILL.md +8 -8
  14. package/claude/skills/create-rule/references/rule.md +11 -23
  15. package/claude/skills/create-skill/SKILL.md +2 -1
  16. package/claude/skills/create-skill/references/skill-paths.md +12 -15
  17. package/{standards/standard.md → claude/skills/create-skill/references/skill-reference.md} +50 -45
  18. package/claude/skills/create-skill/references/skill.md +9 -3
  19. package/claude/skills/design-taste/REQUIREMENT.md +6 -6
  20. package/claude/skills/design-taste/SKILL.md +2 -2
  21. package/claude/skills/design-taste/references/craft.md +1 -1
  22. package/claude/skills/design-taste/references/preflight.md +2 -2
  23. package/claude/skills/design-taste/references/tells.md +1 -1
  24. package/claude/skills/draft-and-pick/SKILL.md +1 -1
  25. package/claude/skills/draft-identity/SKILL.md +3 -2
  26. package/claude/skills/git-commit/references/versioning.md +13 -13
  27. package/claude/skills/git-pr/SKILL.md +1 -1
  28. package/claude/skills/git-pr/references/publish.md +1 -1
  29. package/claude/skills/markdown-craft/references/markdown.md +3 -2
  30. package/claude/skills/plan-feature/SKILL.md +1 -1
  31. package/claude/skills/review-address/REQUIREMENT.md +1 -1
  32. package/claude/skills/review-address/SKILL.md +2 -2
  33. package/claude/skills/review-craft/references/ui.md +1 -1
  34. package/claude/skills/review-pr/SKILL.md +3 -3
  35. package/claude/skills/review-pr/references/post.md +1 -1
  36. package/claude/skills/review-ui/REQUIREMENT.md +1 -1
  37. package/claude/skills/review-ui/SKILL.md +1 -1
  38. package/claude/skills/role-orchestrator/REQUIREMENT.md +2 -2
  39. package/claude/skills/role-orchestrator/SKILL.md +11 -12
  40. package/claude/skills/role-orchestrator/references/orchestrator-cloud-launch.md +3 -1
  41. package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +11 -8
  42. package/claude/skills/role-orchestrator/references/orchestrator-handback.md +10 -4
  43. package/claude/skills/role-orchestrator/references/orchestrator-launch.md +2 -2
  44. package/claude/skills/role-orchestrator/references/orchestrator-poll.md +11 -12
  45. package/claude/skills/role-orchestrator/references/orchestrator-review-dispatch.md +12 -15
  46. package/claude/skills/role-orchestrator/references/orchestrator-reviewer-launch.md +6 -4
  47. package/claude/skills/role-orchestrator/scripts/poll.ts +50 -1
  48. package/claude/skills/role-reviewer/REQUIREMENT.md +17 -7
  49. package/claude/skills/role-reviewer/SKILL.md +17 -10
  50. package/claude/skills/role-worker/REQUIREMENT.md +1 -1
  51. package/claude/skills/role-worker/SKILL.md +6 -6
  52. package/claude/skills/session-compact/references/handoff-note.md +1 -1
  53. package/claude/skills/target-setup/SKILL.md +2 -2
  54. package/claude/skills/target-setup/references/detect.md +3 -3
  55. package/claude/skills/test-craft/SKILL.md +2 -2
  56. package/claude/skills/ux-audit/REQUIREMENT.md +1 -1
  57. package/claude/skills/ux-audit/SKILL.md +2 -2
  58. package/claude/skills/ux-measure/REQUIREMENT.md +1 -1
  59. package/claude/skills/write-human/references/machine-tells.md +12 -0
  60. package/docs/agents/audits.md +1 -1
  61. package/docs/agents/commands.md +14 -13
  62. package/docs/agents/comments.md +1 -1
  63. package/docs/agents/counts.md +5 -6
  64. package/docs/agents/drift-surfaces.md +15 -19
  65. package/docs/agents/gov-detect.md +1 -1
  66. package/docs/agents/index.md +2 -3
  67. package/docs/agents/install-and-sync.md +10 -34
  68. package/docs/agents/markdown-audit.md +22 -12
  69. package/docs/agents/migrate.md +1 -1
  70. package/docs/agents/output-shape.md +1 -1
  71. package/docs/agents/overview.md +2 -2
  72. package/docs/agents/records-stale.md +1 -1
  73. package/docs/agents/records-validate.md +11 -23
  74. package/docs/agents/records.md +1 -1
  75. package/docs/agents/routing.md +1 -1
  76. package/docs/agents/rule-citations.md +9 -17
  77. package/docs/agents/scripting.md +2 -20
  78. package/docs/agents/state-scoped-risk.md +1 -1
  79. package/docs/agents/tasks-validate.md +1 -1
  80. package/docs/agents/teach.md +1 -1
  81. package/docs/target/index.md +1 -0
  82. package/docs/target/migrations.md +4 -0
  83. package/docs/target/projects.md +10 -10
  84. package/docs/target/scenarios.md +5 -6
  85. package/docs/target/standards-moved.md +32 -0
  86. package/docs/target/sync.md +5 -5
  87. package/docs/workflow/ai-workflow.md +1 -1
  88. package/docs/workflow/operating-model.md +16 -18
  89. package/docs/workflow/skill-map.md +1 -1
  90. package/docs/workflow/visual-design-workflow.md +3 -3
  91. package/governance/detect.toml +32 -36
  92. package/governance/renames.toml +44 -1
  93. package/governance/rules/lib/{305-e2e-reliability.md → e2e-reliability.md} +1 -1
  94. package/governance/rules/lib/{306-test-scope.md → test-scope.md} +2 -2
  95. package/governance/rules/ui/{410-a11y.md → a11y.md} +1 -1
  96. package/governance/rules/ui/{440-surface-capture.md → surface-capture.md} +3 -3
  97. package/governance/stacks/base.toml +15 -8
  98. package/governance/stacks/go.toml +2 -0
  99. package/governance/stacks/node.toml +1 -1
  100. package/governance/stacks/php.toml +2 -0
  101. package/governance/stacks/python.toml +1 -1
  102. package/package.json +1 -4
  103. package/scripts/core/install-check.sh +4 -10
  104. package/src/audits/catalog.ts +0 -9
  105. package/src/capture/frame-values.ts +3 -6
  106. package/src/claude/routing.ts +1 -1
  107. package/src/claude/skills-reach.ts +4 -6
  108. package/src/cli/help-all.ts +96 -0
  109. package/src/cli/help.ts +29 -29
  110. package/src/cli.ts +8 -3
  111. package/src/commands/claude.ts +29 -0
  112. package/src/commands/design.ts +22 -1
  113. package/src/commands/gov.ts +29 -11
  114. package/src/commands/init.ts +10 -1
  115. package/src/commands/labels.ts +4 -44
  116. package/src/commands/markdown.ts +96 -3
  117. package/src/commands/migrate.ts +1 -1
  118. package/src/commands/records.ts +5 -21
  119. package/src/commands/sync.ts +11 -0
  120. package/src/commands/tooling.ts +10 -4
  121. package/src/counts/catalogs.ts +0 -6
  122. package/src/design/budget.ts +14 -10
  123. package/src/design/document.ts +5 -5
  124. package/src/design/parse.ts +21 -4
  125. package/src/design/render.ts +3 -3
  126. package/src/gate/boundaries.ts +2 -2
  127. package/src/gate/measures.ts +7 -29
  128. package/src/gate/sequencer.ts +51 -2
  129. package/src/gate/stages.ts +0 -18
  130. package/src/gov/citations.ts +16 -71
  131. package/src/gov/stacks.ts +3 -3
  132. package/src/inventory/subjects.ts +1 -1
  133. package/src/markdown/bans.ts +1 -1
  134. package/src/markdown/ceiling.ts +6 -1
  135. package/src/markdown/colons.ts +86 -0
  136. package/src/markdown/gate.ts +15 -0
  137. package/src/markdown/heading-case.ts +74 -0
  138. package/src/migrate/scratch-evidence.ts +2 -2
  139. package/src/records/validate.ts +6 -194
  140. package/src/sandbox/provision.ts +0 -5
  141. package/src/secrets/shipped.ts +1 -2
  142. package/src/serve/static.ts +1 -2
  143. package/src/shipped/references.ts +42 -93
  144. package/src/sync/check.ts +18 -14
  145. package/src/sync/copy.ts +4 -5
  146. package/src/tooling/inject.ts +6 -37
  147. package/src/tooling/read.ts +2 -3
  148. package/src/tooling/scan.ts +4 -17
  149. package/src/tooling/subfolder.ts +2 -66
  150. package/tooling/astro/manifest.toml +0 -1
  151. package/tooling/astro/reference.md +0 -8
  152. package/tooling/base/configs/scripts/verify.json +1 -1
  153. package/tooling/base/configs/scripts/verify.ts +22 -17
  154. package/tooling/base/manifest.toml +7 -7
  155. package/tooling/base/reference.md +19 -32
  156. package/tooling/base/seeds/.github/workflows/verify.yml +0 -9
  157. package/tooling/base/seeds/.lintstagedrc +2 -4
  158. package/tooling/base/seeds/canon/context/ci.md +4 -6
  159. package/tooling/base/seeds/canon/context/development.md +2 -2
  160. package/tooling/claude/reference.md +1 -1
  161. package/tooling/claude/seeds/.claude/hooks/review-post-scan.sh +13 -1
  162. package/tooling/claude/seeds/.claude/hooks/scratch-guard.sh +1 -1
  163. package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +27 -2
  164. package/tooling/claude/seeds/CLAUDE.md +1 -1
  165. package/tooling/claude/seeds/canon/DESIGN.md +24 -37
  166. package/tooling/go/reference.md +1 -1
  167. package/tooling/php/reference.md +1 -1
  168. package/tooling/python/reference.md +2 -2
  169. package/tooling/shell/configs/.github/workflows/shell.yml +30 -0
  170. package/tooling/shell/manifest.toml +12 -0
  171. package/tooling/shell/reference.md +46 -0
  172. package/tooling/vite-react/manifest.toml +0 -1
  173. package/tooling/vite-react/reference.md +0 -8
  174. package/tooling/web/configs/.github/workflows/readme-screenshot.yml +3 -5
  175. package/tooling/web/configs/.github/workflows/verify.yml +0 -9
  176. package/tooling/web/manifest.toml +1 -2
  177. package/tooling/web/reference.md +4 -6
  178. package/docs/agents/standards-audit.md +0 -40
  179. package/governance/rules/tooling/765-spelling.md +0 -19
  180. package/governance/stacks/astro.toml +0 -2
  181. package/governance/stacks/nextjs.toml +0 -2
  182. package/governance/stacks/node-server.toml +0 -2
  183. package/governance/stacks/python-fastapi.toml +0 -2
  184. package/governance/stacks/react.toml +0 -2
  185. package/src/commands/standards.ts +0 -278
  186. package/src/labels/spelling.ts +0 -120
  187. package/src/standards/audit.ts +0 -146
  188. package/src/standards/list.ts +0 -33
  189. package/src/standards/read.ts +0 -177
  190. package/src/standards/scope.ts +0 -56
  191. package/standards/index.md +0 -10
  192. package/tooling/base/configs/.vscode/extensions.json +0 -9
  193. package/tooling/base/configs/.vscode/settings.json +0 -3
  194. package/tooling/base/configs/scripts/verify.sh +0 -2
  195. package/tooling/base/seeds/.cspell/project-terms.txt +0 -0
  196. package/tooling/base/seeds/.cspell/tech-stack.txt +0 -25
  197. package/tooling/base/seeds/cspell.json +0 -20
  198. package/tooling/go/seeds/.cspell/tech-stack.txt +0 -16
  199. package/tooling/nextjs/seeds/.cspell/tech-stack.txt +0 -3
  200. package/tooling/php/seeds/.cspell/tech-stack.txt +0 -5
  201. package/tooling/python/seeds/.cspell/tech-stack.txt +0 -18
  202. package/tooling/vite-react/seeds/.cspell/project-terms.txt +0 -1
  203. package/tooling/vite-react/seeds/.cspell/tech-stack.txt +0 -2
  204. package/tooling/web/configs/.vscode/extensions.json +0 -13
  205. package/tooling/web/configs/.vscode/settings.json +0 -10
  206. package/tooling/web/seeds/.cspell/tech-stack.txt +0 -21
  207. /package/governance/rules/canon/{606-git.md → git.md} +0 -0
  208. /package/governance/rules/canon/{611-indexes.md → indexes.md} +0 -0
  209. /package/governance/rules/canon/{604-scratch.md → scratch.md} +0 -0
  210. /package/governance/rules/canon/{602-tasks.md → task-scope.md} +0 -0
  211. /package/governance/rules/canon/{605-worktrees.md → worktrees.md} +0 -0
  212. /package/governance/rules/claude/{566-output.md → output.md} +0 -0
  213. /package/governance/rules/code/{000-code.md → routing.md} +0 -0
  214. /package/governance/rules/code/{010-testing.md → testing.md} +0 -0
  215. /package/governance/rules/framework/{210-astro.md → astro.md} +0 -0
  216. /package/governance/rules/framework/{220-fastapi.md → fastapi.md} +0 -0
  217. /package/governance/rules/framework/{230-nextjs.md → nextjs.md} +0 -0
  218. /package/governance/rules/framework/{200-react.md → react.md} +0 -0
  219. /package/governance/rules/framework/{260-shadcn.md → shadcn.md} +0 -0
  220. /package/governance/rules/framework/{250-tailwind.md → tailwind.md} +0 -0
  221. /package/governance/rules/lang/{130-go.md → go.md} +0 -0
  222. /package/governance/rules/lang/{140-php.md → php.md} +0 -0
  223. /package/governance/rules/lang/{110-python.md → python.md} +0 -0
  224. /package/governance/rules/lang/{100-typescript.md → typescript.md} +0 -0
  225. /package/governance/rules/lib/{370-database.md → database.md} +0 -0
  226. /package/governance/rules/lib/{340-pydantic.md → pydantic.md} +0 -0
  227. /package/governance/rules/lib/{360-security-server.md → security-server.md} +0 -0
  228. /package/governance/rules/lib/{350-security-web.md → security-web.md} +0 -0
  229. /package/governance/rules/lib/{320-tanstack-query.md → tanstack-query.md} +0 -0
  230. /package/governance/rules/lib/{335-testing-go.md → testing-go.md} +0 -0
  231. /package/governance/rules/lib/{336-testing-php.md → testing-php.md} +0 -0
  232. /package/governance/rules/lib/{330-testing-py.md → testing-py.md} +0 -0
  233. /package/governance/rules/lib/{300-testing-ts.md → testing-ts.md} +0 -0
  234. /package/governance/rules/lib/{310-zod.md → zod.md} +0 -0
  235. /package/governance/rules/tooling/{700-ci-workflow.md → ci-workflow.md} +0 -0
  236. /package/governance/rules/tooling/{790-code-comments.md → code-comments.md} +0 -0
  237. /package/governance/rules/tooling/{780-config-comments.md → config-comments.md} +0 -0
  238. /package/governance/rules/tooling/{775-dependencies.md → dependencies.md} +0 -0
  239. /package/governance/rules/ui/{480-canvas.md → canvas.md} +0 -0
  240. /package/governance/rules/ui/{400-ui.md → copy.md} +0 -0
  241. /package/governance/rules/ui/{460-design-taste.md → design-taste.md} +0 -0
  242. /package/governance/rules/ui/{420-forms.md → forms.md} +0 -0
  243. /package/governance/rules/ui/{465-interface-casing.md → interface-casing.md} +0 -0
  244. /package/governance/rules/ui/{450-link-behavior.md → link-behavior.md} +0 -0
  245. /package/governance/rules/ui/{470-motion.md → motion.md} +0 -0
  246. /package/governance/rules/ui/{430-ux-completeness.md → ux-completeness.md} +0 -0
  247. /package/tooling/{base → shell}/configs/.editorconfig +0 -0
  248. /package/tooling/{base → shell}/configs/.shellcheckrc +0 -0
@@ -30,7 +30,7 @@ A project that has never synced under a toolkit new enough to write a stamp fall
30
30
 
31
31
  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 merged by hand, 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. A surface still at its `.claude/` spelling with nothing under `canon/`, such as `.claude/REQUIREMENTS.md`, is reported under `unmovedSurfaces`, since rules glob the `canon/` spelling alone, and `canon migrate surface-roots` moves it. <!-- canon-keep-surface-root -->
32
32
 
33
- `unmigrated` currently names no domain, since standards and snippets are the two the toolkit ever installed at the project root, standards closed its install channel, and snippets retired outright. A target still holding a root `standards/` folder from an older toolkit is carrying its own authoring surface now, not an unfinished install, and nothing proposes moving it. A leftover `.claude/snippets/` reports under `reverse` below instead.
33
+ `unmigrated` currently names no domain, since snippets is the one the toolkit ever installed at the project root, and it retired outright. A leftover `.claude/snippets/` reports under `reverse` below instead.
34
34
 
35
35
  ### Rules you never received
36
36
 
@@ -40,7 +40,9 @@ Take a clean section as reporting rather than as delivering. Nothing here instal
40
40
 
41
41
  Since `canon gov install` records the stack you gave it, the list is read by comparing that stack's current rules against what you hold right now, with no date involved at all. That is what lets it name a rule the toolkit shipped before you last synced: nothing here depends on when you installed. A target stamped before this recording shipped falls back to the older read below.
42
42
 
43
- The fallback filters to what your stack can receive, read off the rule folders you already carry plus the folders the base stack takes whole. A rule under `lang/` or `ui/` belongs to some stacks and not others, so an unfiltered list would name rules you can never install. A target with neither a recorded stack nor a governance anchor reports nothing at all, since there is no date to measure against either.
43
+ The fallback filters to what your stack can receive, read off the rule folders you already carry plus the folders holding a base rule. A rule under `lang/` or `ui/` belongs to some stacks and not others, so an unfiltered list would name rules you can never install. A target with neither a recorded stack nor a governance anchor reports nothing at all, since there is no date to measure against either.
44
+
45
+ A target recorded on a stack the toolkit retired, such as `react` or `astro`, reads as having no recorded stack and takes this fallback, so it keeps receiving updates to the rules it holds and is offered new rules only in the rule folders it already carries. Run `canon gov detect . --stack node --json` to see which rules its manifests propose beyond those.
44
46
 
45
47
  In the fallback, an empty section is not proof either way when the toolkit running the check is not a full git clone. The read needs history to reach your anchor, and an install from the registry ships none, so the section goes quiet rather than saying it could not measure. Run the check from a clone before reading a clean result as a complete one. The stack-based read above is untouched by this, since it consults no history.
46
48
 
@@ -72,13 +74,11 @@ Reconcile the configs with `canon tooling diff <stack> <path>` to read which fil
72
74
 
73
75
  It never touches user-owned seed files. Governance rules in `.claude/rules/` and tooling configs refresh in place. Stale `.claude/GOV.md` from earlier installs is removed.
74
76
 
75
- Standards take no part in that run. Nothing installed them, so there is no copy to reconcile and no `canon standards sync` to reach for.
76
-
77
77
  ## Targeted
78
78
 
79
79
  - Claude seed docs such as `CLAUDE.md` and `canon/REQUIREMENTS.md`: merge by hand against the toolkit copy, section by section, keeping the project's customizations. A `stale` seed is safe to take whole.
80
80
  - 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.
81
- - Tooling configs and seeds: `canon tooling <stack> <path>` overwrites golden configs and merges dictionary seeds, and drops every other seed once
81
+ - Tooling configs and seeds: `canon tooling <stack> <path>` overwrites golden configs and copies each seed once, leaving an existing file alone
82
82
  - Reference docs for a stack: `canon tooling reference <stack>` reads and never writes, so there is nothing to sync
83
83
  - Index regeneration after markdown edits: `canon indexes regen`
84
84
 
@@ -17,7 +17,7 @@ Project docs split across three roots at the project root. What the project auth
17
17
  ```plaintext
18
18
  canon/
19
19
  ├── REQUIREMENTS.md ← problem, goals, non-goals
20
- ├── DESIGN.md ← visual intent and token decisions (UI projects)
20
+ ├── DESIGN.md ← visual intent, pointing at the stylesheet (UI projects)
21
21
  └── context/ ← per-domain narrative loaded on demand via index.md
22
22
 
23
23
  .claude/
@@ -18,12 +18,12 @@ This page covers the roles and the loop. For merge order and fan-out rules, see
18
18
 
19
19
  The split is by vantage, not by capability. All four are Claude Code sessions.
20
20
 
21
- | Role | Session | Owns | Does not |
22
- | ------------ | ------------------------------------- | ------------------------------------------------------- | --------------------------------- |
23
- | Orchestrator | One warm, long-lived session | The cross-feature call, deep PR review, merge order | Edit tracked files, merge PRs |
24
- | Reviewer | One cold session per pull request | The per-pull-request read, posted through `review-pr` | Fix findings, lift a draft, merge |
25
- | Planner | One session per row, warm or cold | Measure the row against the tree, write one plan | Enter a worktree, write the board |
26
- | Worker | One cold worktree session per feature | Implement, self-check, open PR, answer the orchestrator | Write the shared board, merge |
21
+ | Role | Session | Owns | Does not |
22
+ | ------------ | ------------------------------------- | ---------------------------------------------------- | ---------------------------------- |
23
+ | Orchestrator | One warm, long-lived session | The cross-feature call, review dispatch, merge order | Review in place, edit, merge PRs |
24
+ | Reviewer | One cold session per pull request | One PR's read through `review-pr`, the lift on close | Fix findings, ready by hand, merge |
25
+ | Planner | One session per row, warm or cold | Measure the row against the tree, write one plan | Enter a worktree, write the board |
26
+ | Worker | One cold worktree session per feature | Implement, self-check, open PR, answer the reviewer | Write the shared board, merge |
27
27
 
28
28
  Each role is asserted explicitly rather than inferred. The orchestrator loads
29
29
  `role-orchestrator` at the start of its session, a worker loads `role-worker`,
@@ -72,9 +72,9 @@ One feature travels this path end to end.
72
72
 
73
73
  1. The next feature is planned with `plan-feature`, writing a plan to `.canon/plans/`. The orchestrator runs it warm when the row turns on a contract other features consume or a dependency on another row, and dispatches a planner under `role-planner` otherwise. A cold planner measures the row against the tree rather than trusting what the row claims, and it reads what is in flight by composing the live session roster with open pull requests. A bare branch or worktree is not evidence on its own, since this repository leaves both behind after a squash merge.
74
74
  2. Orchestrator checks the plan waits on nobody, checks the branch is unclaimed, and checks no conflict holds the plan behind a track in flight, then dispatches a background worker with `claude --bg` against the plan, naming the branch and the model on the launch rather than leaving the worker to derive either. No count caps how many run at once. The branch travels as the argument to the worker's own worktree call, which is the one place the name is read rather than inferred. It falls back to naming the invocation for a human to run through `session-worktree` and `auto-ship` when the plan still waits on an answer only the operator can give, the branch check refuses, or a conflict holds the plan behind a track already in flight. Either way, the worker enters its own worktree, builds, self-checks, opens a PR, and stops at the PR boundary.
75
- 3. A reviewer under `role-reviewer`, or the orchestrator, posts `review-pr` findings, and `review-ui` drives any visual checklist beside it.
76
- 4. Orchestrator tells the session holding that branch to run `review-address` once the pass posted a finding at any severity, resolving the target then with `canon sessions list --branch` and reporting the invocation for the human when no live session holds it. The worker addresses the findings, rebases onto `origin/main` when a sibling landed first on a file it writes, then pushes a follow-up. A pass carrying only minor findings dispatches too, since the grade runs low often enough that a floor at should-fix loses fixes a worker would have made. `review-pr` states that threshold and the heading follows it, so an open heading is itself the signal to send.
77
- 5. Orchestrator closes the review out with `review-pr` again. The second pass reads only the commits the follow-up added, or the worker's response alone when the follow-up added none, and posts under `## Review` when it finds anything and under `## Review closed` when it finds nothing, so a reader learns from the heading whether work is still owed and takes the merge decision from the counts on the line under it. A pass finding nothing where a close-out already stands rewrites that comment to cover what it read rather than posting a second one, so the thread carries one live verdict. Repeat from step 4 until a pass closes the review.
75
+ 3. Orchestrator dispatches a reviewer under `role-reviewer` for every pull request but a release one, which posts `review-pr` findings, and `review-ui` drives any visual checklist beside it.
76
+ 4. The reviewer tells the session holding that branch to run `review-address` once the pass posted a finding at any severity, resolving it with `canon sessions list --branch` and falling back to the orchestrator when none is live. The worker addresses the findings, rebases onto `origin/main` when a sibling landed first on a file it writes, then pushes a follow-up. A pass carrying only minor findings dispatches too, since the grade runs low often enough that a floor at should-fix loses fixes a worker would have made. `review-pr` states that threshold and the heading follows it, so an open heading is itself the signal to send.
77
+ 5. The worker asks that reviewer for the re-review directly, and the reviewer closes the review out with `review-pr` again. The second pass reads only the commits the follow-up added, or the worker's response alone when the follow-up added none, and posts under `## Review` when it finds anything and under `## Review closed` when it finds nothing, so a reader learns from the heading whether work is still owed and takes the merge decision from the counts on the line under it. A pass finding nothing where a close-out already stands rewrites that comment to cover what it read rather than posting a second one, so the thread carries one live verdict. Repeat from step 4 until a pass closes the review. Each reviewer then runs `canon pr lift`, which lifts the draft mark once every gate it reads is clear.
78
78
  6. The human reads the result and merges. After each merge, the orchestrator tells any trailing worker whose files the merged diff touches to run `review-address`, which rebases whether or not the review left anything open.
79
79
 
80
80
  There is no loop construct here. Each worker is a single build that halts at the
@@ -86,11 +86,11 @@ from merging promptly so the next PR does not rot against a moving main.
86
86
 
87
87
  The worker's chain carries no review step. The session that wrote the code is
88
88
  structurally blind to its own misreadings, because the same misreading wrote
89
- both the code and any review of it, so the first review a change gets is the
90
- orchestrator's.
89
+ both the code and any review of it, so the first review a change gets is a
90
+ dispatched reviewer's.
91
91
 
92
92
  - Worker gate, inside `auto-ship`: the session that wrote the code. Its job is "did I build the plan and does it pass?" The verify commands and the test order read decide whether the PR opens, and the draft mark holds the merge.
93
- - Orchestrator review, via `review-pr`: a fresh session with cross-feature context (the board, a sibling PR in flight, a downstream contract). Its job is "is this right and does it fit?" It can question the plan itself. This is the merge gate.
93
+ - Reviewer pass, via `review-pr`: a fresh session holding one pull request, briefed with the cross-feature facts the orchestrator's wave pass found (a sibling PR in flight, a shared file, the merge order). Its job is "is this right and does it fit?" It can question the plan itself. This is the merge gate.
94
94
 
95
95
  The human read at merge is the final gate. No layer repeats another.
96
96
 
@@ -190,7 +190,7 @@ coordination costs more than the change it was too small.
190
190
 
191
191
  Two tiers hold work at different altitudes.
192
192
 
193
- - Tasks (`.canon/tasks/`): the active few pulled into the current turn, one file each. Gitignored, high churn. Shape governed by `canon standards tasks`. `priority.md` beside them carries execution order, and `backlog.md` carries what nobody is scheduling, both shaped by `canon standards board`.
193
+ - Tasks (`.canon/tasks/`): the active few pulled into the current turn, one file each. Gitignored, high churn. Shape governed by the `task-board` skill. `priority.md` beside them carries execution order, and `backlog.md` carries what nobody is scheduling, both shaped by the same skill.
194
194
  - Edits: a few lines, done immediately with no ceremony.
195
195
 
196
196
  Nothing above these sequences work into versions. Scope is stated in
@@ -202,11 +202,9 @@ before another is carried nowhere at all.
202
202
 
203
203
  Review attention binds, and no number caps worker tracks, so stop adding once you cannot review every output. A row waits only on a conflict a merge cannot settle, which the `role-orchestrator` dispatch runbook states once. A shared file is not one: both rows build, and the branch merging second resolves any conflict in its own session after the first lands, since no practice source serializes on a file. [Fowler](https://martinfowler.com/articles/branching-patterns.html) has whoever integrates second check health "even if it's a clean merge", and [DORA](https://dora.dev/capabilities/trunk-based-development/) keeps branches to hours with no integration phase.
204
204
 
205
- Review splits by vantage. A reviewer under `role-reviewer` takes a pull
206
- request's read, first pass included, when three await one (a number set by
207
- hand), when a diff is too large to hold, or when it changes code or a skill or
208
- rule body. Prose stays with the orchestrator, which keeps one cross-branch pass
209
- per wave over file sets, the board, and merge order.
205
+ Review splits by vantage. A reviewer under `role-reviewer` takes every pull
206
+ request's read but a release one's and trades each round with the worker. The
207
+ orchestrator keeps one cross-branch pass per wave over file sets and merge order.
210
208
 
211
209
  Inbound turns cost the controlling session as well, so weigh the spend before
212
210
  widening. A message from one of your other sessions arrives as a new turn
@@ -90,7 +90,7 @@ Each row sits under the group its skill's `metadata.family` names. The landing p
90
90
 
91
91
  | Skill | When to use |
92
92
  | ------------------------- | ----------------------------------------------------------------------------------------------------------- |
93
- | `canon:role-orchestrator` | To assert the control session that owns the queue and reviews each worker's PR |
93
+ | `canon:role-orchestrator` | To assert the control session that owns the queue and dispatches a reviewer for each worker's PR |
94
94
  | `canon:role-planner` | To assert the thinking role for a cold session writing a plan, a groundwork track, or an intake pass |
95
95
  | `canon:role-reviewer` | To assert the reviewing role for a cold session dispatched to review one pull request |
96
96
  | `canon:role-worker` | To assert the worker role for a cold session building one branch under one plan |
@@ -14,19 +14,19 @@ The tier framework sits alongside [Claude Design](../../wiki/claude/design.md),
14
14
 
15
15
  ## Tier 0: prose only
16
16
 
17
- The default. `canon/DESIGN.md` holds visual intent as token tables for color, typography, spacing, and borders, with one Personality paragraph and at most three one-line rules a section, motion and iconography included.
17
+ The default. `canon/DESIGN.md` holds visual intent, being one Overview paragraph, at most three one-line rules a section, and a table naming what each color and shape role is for. Its lead names the stylesheet the values live in, since a hand-typed copy of them drifts from the CSS.
18
18
 
19
19
  Claude Code reads it and writes the implementation. Works for CLI tools, internal dashboards, admin panels, and backend-focused projects.
20
20
 
21
21
  ### Seed shape
22
22
 
23
- The toolkit seed in `tooling/claude/seeds/canon/DESIGN.md` ships a token-table template with a starting set of roles, and `claude/skills/canvas-board/references/design.md` carries the same tables under `## Template` with placeholder rows. The column headers are what the renderer parses, so they stay verbatim in either, while the rows and values are the project's own.
23
+ The toolkit seed in `tooling/claude/seeds/canon/DESIGN.md` ships an intent template with a starting set of roles, each naming its custom property, and `claude/skills/canvas-board/references/design.md` carries the same tables under `## Template` with placeholder rows. The column headers are what the parser reads, so they stay verbatim in either, while the rows are the project's own. The seed's lead asks for the project's own stylesheet, such as `src/styles/tokens.css` or a Tailwind `@theme` block, and falls back to `.claude/design/project/` only when the project has none.
24
24
 
25
25
  `canon design render` writes an HTML plus CSS preview to `.canon/tmp/render/design/` for eyeballing the current system without leaving Claude Code. See `canon/context/design/index.md`.
26
26
 
27
27
  A project wanting a neutral starting point to override runs `canon design install`, which copies one stylesheet to `.claude/design/base.css` carrying an achromatic token set as custom properties and two components built on them. Greys run from near-black to near-white and the accent is monochrome, so the only palette the project renders is one it writes itself. That file is toolkit-owned and `canon design sync` refreshes it, so a project overrides a value in `.claude/design/project/` instead, which sync never touches. Nothing arrives without that install, and the two channels are independent: a record the project wrote is its own, and the installed stylesheet is the toolkit's.
28
28
 
29
- A cell no source anchors ends in `? verify`, and the preview shows that marker beside the value rather than folding it in, so a swatch and a font sample stay built from the value alone. A confidence line above the sections names how many cells are anchored against how many are tagged, which is what tells a reader whether they are looking at a record of the code or a proposal about it. It reads the columns a source could anchor and leaves out the row names, so the ratio is not diluted by cells no tag could ever reach. The proposal path tags nearly all of them, so that count reads low on day one by design.
29
+ A record generated from a token source carries the values in tables instead, which is the shape this toolkit's own record takes. There a cell no source anchors ends in `? verify`, and the preview shows that marker beside the value rather than folding it in, so a swatch and a font sample stay built from the value alone. A confidence line above the sections names how many cells are anchored against how many are tagged, which is what tells a reader whether they are looking at a record of the code or a proposal about it. It reads the columns a source could anchor and leaves out the row names, so the ratio is not diluted by cells no tag could ever reach. The proposal path tags nearly all of them, so that count reads low on day one by design.
30
30
 
31
31
  ### Tools
32
32
 
@@ -21,71 +21,67 @@
21
21
  deps = []
22
22
  files = [".claude/skills", "claude/skills"]
23
23
 
24
- ["700-ci-workflow"]
24
+ ["ci-workflow"]
25
25
  deps = []
26
26
  files = [".github/workflows"]
27
27
 
28
- ["765-spelling"]
29
- deps = ["cspell"]
30
- files = [".cspell", "cspell.json", ".cspell.json", "cspell.config.*"]
31
-
32
- ["775-dependencies"]
28
+ ["dependencies"]
33
29
  deps = []
34
30
  files = ["**/package.json", "**/pyproject.toml", "**/go.mod", "**/composer.json"]
35
31
 
36
- ["780-config-comments"]
32
+ ["config-comments"]
37
33
  deps = []
38
34
  files = [".editorconfig", "**/Dockerfile*", "**/*.config.*", "**/.env.example"]
39
35
 
40
- ["790-code-comments"]
36
+ ["code-comments"]
41
37
  deps = []
42
38
  files = ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx", "**/*.sh", "**/*.py"]
43
39
 
44
- ["130-go"]
40
+ ["go"]
45
41
  deps = []
46
42
  files = ["**/go.mod"]
47
43
 
48
- ["140-php"]
44
+ ["php"]
49
45
  deps = []
50
46
  files = ["**/composer.json"]
51
47
 
52
- ["200-react"]
48
+ ["react"]
53
49
  deps = ["react"]
54
50
  files = []
55
51
 
56
- ["210-astro"]
52
+ ["astro"]
57
53
  deps = ["astro"]
58
54
  files = ["**/astro.config.*"]
59
55
 
60
- ["220-fastapi"]
56
+ ["fastapi"]
61
57
  deps = ["fastapi"]
62
58
  files = []
63
59
 
64
- ["230-nextjs"]
60
+ ["nextjs"]
65
61
  deps = ["next"]
66
62
  files = ["**/next.config.*"]
67
63
 
68
- ["250-tailwind"]
64
+ ["tailwind"]
69
65
  deps = ["tailwindcss", "@tailwindcss/vite", "@tailwindcss/postcss"]
70
66
  files = ["**/tailwind.config.*"]
71
67
 
72
- ["260-shadcn"]
68
+ ["shadcn"]
73
69
  deps = []
74
70
  files = ["**/components.json"]
75
71
 
76
- ["305-e2e-reliability"]
72
+ ["e2e-reliability"]
77
73
  deps = ["@playwright/test", "playwright", "cypress"]
78
74
  files = ["**/e2e"]
79
75
 
80
- ["306-test-scope"]
76
+ ["test-scope"]
81
77
  deps = ["@playwright/test", "playwright", "cypress"]
82
78
  files = ["**/e2e"]
83
79
 
84
- ["310-zod"]
80
+ ["zod"]
85
81
  deps = ["zod"]
86
82
  files = []
87
83
 
88
- ["320-tanstack-query"]
84
+ ["tanstack-query"]
89
85
  deps = [
90
86
  "@tanstack/react-query",
91
87
  "@tanstack/vue-query",
@@ -95,23 +91,23 @@ deps = [
95
91
  ]
96
92
  files = []
97
93
 
98
- ["335-testing-go"]
94
+ ["testing-go"]
99
95
  deps = []
100
96
  files = ["**/go.mod"]
101
97
 
102
- ["336-testing-php"]
98
+ ["testing-php"]
103
99
  deps = ["phpunit/phpunit", "pestphp/pest"]
104
100
  files = ["**/phpunit.xml", "**/phpunit.xml.dist"]
105
101
 
106
- ["340-pydantic"]
102
+ ["pydantic"]
107
103
  deps = ["pydantic"]
108
104
  files = []
109
105
 
110
- ["350-security-web"]
106
+ ["security-web"]
111
107
  deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
112
108
  files = ["index.html", "*/index.html"]
113
109
 
114
- ["360-security-server"]
110
+ ["security-server"]
115
111
  deps = [
116
112
  "express",
117
113
  "fastify",
@@ -133,7 +129,7 @@ deps = [
133
129
  ]
134
130
  files = []
135
131
 
136
- ["370-database"]
132
+ ["database"]
137
133
  deps = [
138
134
  "prisma",
139
135
  "@prisma/client",
@@ -160,42 +156,42 @@ deps = [
160
156
  ]
161
157
  files = ["**/migrations", "**/schema.prisma", "**/*.sql"]
162
158
 
163
- ["400-ui"]
159
+ ["copy"]
164
160
  deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
165
161
  files = ["index.html", "*/index.html"]
166
162
 
167
- ["410-a11y"]
163
+ ["a11y"]
168
164
  deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
169
165
  files = ["index.html", "*/index.html"]
170
166
 
171
- ["420-forms"]
167
+ ["forms"]
172
168
  deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
173
169
  files = ["index.html", "*/index.html"]
174
170
 
175
- ["430-ux-completeness"]
171
+ ["ux-completeness"]
176
172
  deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
177
173
  files = ["index.html", "*/index.html"]
178
174
 
179
- ["440-surface-capture"]
175
+ ["surface-capture"]
180
176
  deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
181
177
  files = ["index.html", "*/index.html"]
182
178
 
183
- ["450-link-behavior"]
179
+ ["link-behavior"]
184
180
  deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
185
181
  files = ["index.html", "*/index.html"]
186
182
 
187
- ["460-design-taste"]
183
+ ["design-taste"]
188
184
  deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
189
185
  files = ["canon/DESIGN.md", "index.html", "*/index.html"]
190
186
 
191
- ["465-interface-casing"]
187
+ ["interface-casing"]
192
188
  deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
193
189
  files = ["index.html", "*/index.html"]
194
190
 
195
- ["470-motion"]
191
+ ["motion"]
196
192
  deps = ["react", "vue", "svelte", "astro", "next", "solid-js", "preact"]
197
193
  files = ["index.html", "*/index.html"]
198
194
 
199
- ["480-canvas"]
195
+ ["canvas"]
200
196
  deps = []
201
197
  files = [".canon/canvas"]
@@ -24,7 +24,6 @@
24
24
  "555-tasks" = "655-tasks"
25
25
  "558-plan" = "658-plan"
26
26
  "501-markdown" = "801-markdown"
27
- "065-spelling" = "765-spelling"
28
27
  "075-dependencies" = "775-dependencies"
29
28
  "080-config-comments" = "780-config-comments"
30
29
  "090-code-comments" = "790-code-comments"
@@ -33,3 +32,47 @@
33
32
  "655-tasks" = "tasks"
34
33
  "570-skill" = "skill"
35
34
  "801-markdown" = "markdown"
35
+ "602-tasks" = "task-scope"
36
+ "604-scratch" = "scratch"
37
+ "605-worktrees" = "worktrees"
38
+ "606-git" = "git"
39
+ "611-indexes" = "indexes"
40
+ "566-output" = "output"
41
+ "000-code" = "routing"
42
+ "010-testing" = "testing"
43
+ "200-react" = "react"
44
+ "210-astro" = "astro"
45
+ "220-fastapi" = "fastapi"
46
+ "230-nextjs" = "nextjs"
47
+ "250-tailwind" = "tailwind"
48
+ "260-shadcn" = "shadcn"
49
+ "100-typescript" = "typescript"
50
+ "110-python" = "python"
51
+ "130-go" = "go"
52
+ "140-php" = "php"
53
+ "300-testing-ts" = "testing-ts"
54
+ "305-e2e-reliability" = "e2e-reliability"
55
+ "306-test-scope" = "test-scope"
56
+ "310-zod" = "zod"
57
+ "320-tanstack-query" = "tanstack-query"
58
+ "330-testing-py" = "testing-py"
59
+ "335-testing-go" = "testing-go"
60
+ "336-testing-php" = "testing-php"
61
+ "340-pydantic" = "pydantic"
62
+ "350-security-web" = "security-web"
63
+ "360-security-server" = "security-server"
64
+ "370-database" = "database"
65
+ "700-ci-workflow" = "ci-workflow"
66
+ "775-dependencies" = "dependencies"
67
+ "780-config-comments" = "config-comments"
68
+ "790-code-comments" = "code-comments"
69
+ "400-ui" = "copy"
70
+ "410-a11y" = "a11y"
71
+ "420-forms" = "forms"
72
+ "430-ux-completeness" = "ux-completeness"
73
+ "440-surface-capture" = "surface-capture"
74
+ "450-link-behavior" = "link-behavior"
75
+ "460-design-taste" = "design-taste"
76
+ "465-interface-casing" = "interface-casing"
77
+ "470-motion" = "motion"
78
+ "480-canvas" = "canvas"
@@ -32,4 +32,4 @@ paths:
32
32
 
33
33
  ## Authority
34
34
 
35
- - Follow `.claude/rules/canon/lib/300-testing-ts.md` for framework choice, file placement, and test naming.
35
+ - Follow `.claude/rules/canon/lib/testing-ts.md` for framework choice, file placement, and test naming.
@@ -20,5 +20,5 @@ paths:
20
20
 
21
21
  - Answer a question about the running page with a script against the dev server rather than with the suite.
22
22
  - Do not enable `fullyParallel` in `playwright.config.ts`.
23
- - Follow `.claude/rules/canon/ui/440-surface-capture.md` for capture scope.
24
- - Follow `.claude/rules/canon/lib/305-e2e-reliability.md` for waits and guards.
23
+ - Follow `.claude/rules/canon/ui/surface-capture.md` for capture scope.
24
+ - Follow `.claude/rules/canon/lib/e2e-reliability.md` for waits and guards.
@@ -60,4 +60,4 @@ paths:
60
60
 
61
61
  - Let content reflow at a viewport 320 CSS pixels wide with no loss of content or function and no two-dimensional scrolling. Only content whose meaning depends on both axes, such as a data table, a map, or a diagram, may scroll sideways (WCAG Reflow, 1.4.10, Level AA).
62
62
  - Treat 320 as the criterion's own test condition rather than a device width. It is equivalent to a 1280 pixel window at 400 percent zoom, so a layout that breaks there breaks for a person who zooms.
63
- - Hold the same 320 floor for the content region beside persistent chrome a person can resize. The criterion measures the viewport, so this extension is this rule's own rather than the criterion's: a panel widened to 480 in a 768 window leaves 288 for the content, under the floor at a window the criterion passes. `440-surface-capture` states where the frame for it gets taken.
63
+ - Hold the same 320 floor for the content region beside persistent chrome a person can resize. The criterion measures the viewport, so this extension is this rule's own rather than the criterion's: a panel widened to 480 in a 768 window leaves 288 for the content, under the floor at a window the criterion passes. `surface-capture` states where the frame for it gets taken.
@@ -26,12 +26,12 @@ paths:
26
26
  ## What a capture covers
27
27
 
28
28
  - Capture the full page. Do not capture a component in isolation.
29
- - Declare the widths a layout case captures. Always include 320, the reflow floor from the reflow criterion in `410-a11y`, then add each breakpoint bucket the project writes rules for, read from the `## Layout` section of `DESIGN.md`.
29
+ - Declare the widths a layout case captures. Always include 320, the reflow floor from the reflow criterion in `a11y`, then add each breakpoint bucket the project writes rules for, read from the `## Layout` section of `DESIGN.md`.
30
30
  - Fall back to the 320 floor alone when the project has no `DESIGN.md` or its record carries no `## Layout` section. Do not impose another project's breakpoints.
31
31
  - Add a layout case at each bound when a surface renders persistent chrome a person can resize, such as a draggable sidebar or a split pane, one with the chrome at its narrowest and one at its widest. Take both at the narrowest declared width where the chrome stays persistent rather than collapsing, since a frame where it has turned into an overlay shows none of the width it takes.
32
- - Read those bounds from the code that clamps the chrome, since `## Layout` has no slot for them. Judge each frame by the content width left beside the chrome rather than by the window width, against the 320 floor `410-a11y` holds for that region.
32
+ - Read those bounds from the code that clamps the chrome, since `## Layout` has no slot for them. Judge each frame by the content width left beside the chrome rather than by the window width, against the 320 floor `a11y` holds for that region.
33
33
  - Apply the declaration to a case that covers layout only. A case driving a menu open or an answer chosen tests a state, so it takes one width rather than the full set.
34
- - Read a capture at 320 as proof that a frame was taken there, not that the page reflows correctly. The criterion is stated in `410-a11y` and nothing here enforces it.
34
+ - Read a capture at 320 as proof that a frame was taken there, not that the page reflows correctly. The criterion is stated in `a11y` and nothing here enforces it.
35
35
  - Write the capture into a folder named `evidence`. The image is collected for the pull request comment when any segment of its path is literally `evidence` and its filename carries an image extension, so the folder name is fixed and its position in the tree is the project's own.
36
36
  - Several `evidence/` folders in one project is the ordinary shape rather than a problem to consolidate. One per surface is how a project with more than one rendered surface ends up.
37
37
  - Drive a state a screenshot cannot reach. An initial render reports nothing about a menu that opens, an answer that is chosen, or a rail that tracks scrolling.
@@ -1,9 +1,16 @@
1
1
  extends = ""
2
- # Four audience groups whole. Every rule authored under them ships to a base
3
- # consumer, so adding one is a single edit rather than a file and a name here.
4
- # `canon` carries the toolkit workflow and canonical-doc rules, `claude` the
5
- # session conduct and `.claude/` authoring rules, `tooling` the dev setup and
6
- # CI workflow rules, and `writing` the prose and document-shape rules. The
7
- # `code` group is left to the stacks that write code, so a docs or writing
8
- # project loads no rule it can never apply.
9
- rules = ["canon", "claude", "tooling", "writing"]
2
+ # Named rule by rule rather than by folder, so a rule authored later under
3
+ # `canon` or `claude` reaches no project until it is added here or proposed by
4
+ # `canon gov detect`. Every other rule is opt-in.
5
+ rules = [
6
+ "output",
7
+ "task-scope",
8
+ "scratch",
9
+ "worktrees",
10
+ "git",
11
+ "indexes",
12
+ "context",
13
+ "tasks",
14
+ "plan",
15
+ "markdown",
16
+ ]
@@ -0,0 +1,2 @@
1
+ extends = "base"
2
+ rules = ["code", "go", "testing-go"]
@@ -1,2 +1,2 @@
1
1
  extends = "base"
2
- rules = ["code", "100-typescript"]
2
+ rules = ["code", "typescript", "testing-ts"]
@@ -0,0 +1,2 @@
1
+ extends = "base"
2
+ rules = ["code", "php", "testing-php"]
@@ -1,2 +1,2 @@
1
1
  extends = "base"
2
- rules = ["code", "110-python", "340-pydantic", "330-testing-py", "360-security-server", "370-database"]
2
+ rules = ["code", "python", "testing-py"]
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@erclx/canon",
3
3
  "type": "module",
4
- "version": "5.34.0",
4
+ "version": "5.36.0",
5
5
  "description": "Runs your agent's work and keeps its code good, on one setup for every repo.",
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -10,7 +10,6 @@
10
10
  "files": [
11
11
  "src",
12
12
  "scripts",
13
- "standards",
14
13
  "governance",
15
14
  "tooling",
16
15
  "claude",
@@ -25,7 +24,6 @@
25
24
  "access": "public"
26
25
  },
27
26
  "scripts": {
28
- "check:spell": "cspell '**' '.*/**' '.*' --no-progress --color --show-context",
29
27
  "format": "prettier --write --log-level warn --ignore-path .gitignore --ignore-path .prettierignore . && shfmt --write --indent 2 scripts/ tooling/ claude/",
30
28
  "check:format": "prettier --check --log-level warn --ignore-path .gitignore --ignore-path .prettierignore . && shfmt --diff --indent 2 scripts/ tooling/ claude/",
31
29
  "check:shell": "find scripts tooling claude .claude/hooks -name '*.sh' -exec shellcheck --severity=warning {} + && find .husky -maxdepth 1 -type f -exec shellcheck --severity=warning --shell=sh {} +",
@@ -71,7 +69,6 @@
71
69
  "@types/bun": "^1.2.10",
72
70
  "@types/micromatch": "^4.0.10",
73
71
  "astro": "^6.1.9",
74
- "cspell": "^8.17.1",
75
72
  "happy-dom": "^20.14.5",
76
73
  "husky": "^9.1.7",
77
74
  "micromatch": "^4.0.8",
@@ -97,23 +97,17 @@ log_step "Assert scaffold"
97
97
  # catches a failed domain, and the gate stays green while the target is
98
98
  # missing everything that domain provides.
99
99
  #
100
- # Standards name no path because that corpus never installs into a target. A
101
- # scaffold reads a standard through `canon standards <name>`, resolving against
102
- # the toolkit rather than a copy this gate could assert on. The two
100
+ # Authoring references name no path because they ship inside the plugin's
101
+ # skills rather than installing into a target. The two
103
102
  # rule paths stand for the `claude` and `canon` groups `base` takes whole.
104
103
  for path in "CLAUDE.md" ".claude/wiki/index.md" ".claude" "canon/context/index.md" \
105
- ".prettierrc" ".editorconfig" ".lintstagedrc" ".husky/pre-commit" ".github/workflows/verify.yml" "scripts/verify.sh" \
106
- ".claude/rules/canon/claude/566-output.md" ".claude/rules/canon/canon/604-scratch.md"; do
104
+ ".prettierrc" ".lintstagedrc" ".husky/pre-commit" ".github/workflows/verify.yml" "scripts/verify.ts" \
105
+ ".claude/rules/canon/claude/output.md" ".claude/rules/canon/canon/scratch.md"; do
107
106
  if [ ! -e "$TARGET_DIR/$path" ]; then
108
107
  log_error "Missing after canon init: $path"
109
108
  fi
110
109
  log_info "Found: $path"
111
110
  done
112
111
 
113
- if [ ! -x "$TARGET_DIR/scripts/verify.sh" ]; then
114
- log_error "Not executable after canon init: scripts/verify.sh"
115
- fi
116
- log_info "Executable: scripts/verify.sh"
117
-
118
112
  log_step "Verification passed"
119
113
  log_info "Manual check still needed: bun link and global canon invocation"
@@ -468,7 +468,6 @@ const RECORD_KINDS: readonly (readonly [string, Corpus])[] = [
468
468
  ['plans', 'per-machine'],
469
469
  ['groundwork', 'per-machine'],
470
470
  ['intake', 'per-machine'],
471
- ['standards', 'tracked'],
472
471
  ['teach', 'per-machine'],
473
472
  ]
474
473
 
@@ -588,14 +587,6 @@ export const AUDITS: readonly AuditSpec[] = [
588
587
  argv: ['records', 'validate', kind, '--json'],
589
588
  gatingExits: [],
590
589
  corpus,
591
- // `standards` is the one tracked kind here, so it takes none of the
592
- // per-machine default the other five inherit from their corpus. A target
593
- // reads standards through `canon standards` rather than a copy in its own
594
- // tree, so carrying no standards folder at all is the
595
- // ordinary state of every project but this repository.
596
- ...(kind === 'standards' && {
597
- absentReasons: ['no-folder'] satisfies RecordRefusal[],
598
- }),
599
590
  counts: findingsOnly,
600
591
  })),
601
592
  {
@@ -121,9 +121,6 @@ const plural = (count: number, noun: string): string =>
121
121
  const frameRow = (cells: string): string =>
122
122
  `<span class="frame">│</span> <span class="ok">✓</span> ${cells}`
123
123
 
124
- /** Rule names carry a numeric prefix that orders the load, not the identity. */
125
- const slug = (name: string): string => name.replace(/^\d+-/, '')
126
-
127
124
  /** Indented to the depth a rule inside the `<style>` block sits at. */
128
125
  const indentTokens = (css: string): string =>
129
126
  css
@@ -194,13 +191,13 @@ export function buildFrameValues(catalogs: FrameCatalogs): FrameValues {
194
191
  }
195
192
 
196
193
  const tokenCss = indentTokens(catalogs.tokenCss)
197
- const rules = gov.rules.map((entry) => slug(entry.name))
194
+ const rules = gov.rules.map((entry) => entry.name)
198
195
  // A rule no stack names is opt-in behind `--add`, so featuring one advertises
199
196
  // an entry no ordinary `canon gov install` delivers. The column samples the
200
197
  // stack-reached subset while its count and remainder describe the whole.
201
198
  const stacked = new Set(gov.stacks.flatMap((stack) => stack.rules))
202
199
  const deliveredEntries = gov.rules.filter((entry) => stacked.has(entry.name))
203
- const deliveredRules = deliveredEntries.map((entry) => slug(entry.name))
200
+ const deliveredRules = deliveredEntries.map((entry) => entry.name)
204
201
 
205
202
  for (const [label, list] of [
206
203
  ['skills', skills],
@@ -236,7 +233,7 @@ export function buildFrameValues(catalogs: FrameCatalogs): FrameValues {
236
233
  const scope =
237
234
  globs.length > 0 ? clip(globs.join(' '), GLOB_WIDTH) : 'every session'
238
235
  return frameRow(
239
- `<span class="name">${escape(pad(slug(entry.name), 24))}</span>` +
236
+ `<span class="name">${escape(pad(entry.name, 24))}</span>` +
240
237
  `<span class="domain">${escape(pad(`[${entry.domain}]`, 12))}</span>` +
241
238
  `<span class="muted">${escape(scope)}</span>`,
242
239
  )
@@ -16,7 +16,7 @@ const PATH_TOKEN = /^[.A-Za-z0-9_][A-Za-z0-9._/-]*$/
16
16
  /** A placeholder segment, which a shape carries and a real path does not. */
17
17
  const SHAPE = /<[^>]*>/
18
18
 
19
- /** An alphabetic extension, which separates `cspell.json` from `3.6.0`. */
19
+ /** An alphabetic extension, which separates `tsconfig.json` from `3.6.0`. */
20
20
  const EXTENSION = /\.[a-z]{2,5}$/
21
21
 
22
22
  /** Extensions a folder is probed with, so a glob narrowed by type still hits. */