@erclx/canon 5.34.0 → 5.35.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 (143) hide show
  1. package/README.md +3 -5
  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/SKILL.md +10 -11
  6. package/claude/skills/create-skill/SKILL.md +2 -1
  7. package/claude/skills/create-skill/references/skill-paths.md +12 -15
  8. package/{standards/standard.md → claude/skills/create-skill/references/skill-reference.md} +50 -45
  9. package/claude/skills/create-skill/references/skill.md +9 -3
  10. package/claude/skills/draft-and-pick/SKILL.md +1 -1
  11. package/claude/skills/git-commit/references/versioning.md +13 -13
  12. package/claude/skills/git-pr/SKILL.md +1 -1
  13. package/claude/skills/git-pr/references/publish.md +1 -1
  14. package/claude/skills/review-address/REQUIREMENT.md +1 -1
  15. package/claude/skills/review-address/SKILL.md +2 -2
  16. package/claude/skills/review-pr/SKILL.md +3 -3
  17. package/claude/skills/review-pr/references/post.md +1 -1
  18. package/claude/skills/review-ui/REQUIREMENT.md +1 -1
  19. package/claude/skills/review-ui/SKILL.md +1 -1
  20. package/claude/skills/role-orchestrator/REQUIREMENT.md +2 -2
  21. package/claude/skills/role-orchestrator/SKILL.md +11 -12
  22. package/claude/skills/role-orchestrator/references/orchestrator-cloud-launch.md +3 -1
  23. package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +11 -8
  24. package/claude/skills/role-orchestrator/references/orchestrator-handback.md +10 -4
  25. package/claude/skills/role-orchestrator/references/orchestrator-launch.md +2 -2
  26. package/claude/skills/role-orchestrator/references/orchestrator-poll.md +11 -12
  27. package/claude/skills/role-orchestrator/references/orchestrator-review-dispatch.md +12 -15
  28. package/claude/skills/role-orchestrator/references/orchestrator-reviewer-launch.md +6 -4
  29. package/claude/skills/role-orchestrator/scripts/poll.ts +50 -1
  30. package/claude/skills/role-reviewer/REQUIREMENT.md +17 -7
  31. package/claude/skills/role-reviewer/SKILL.md +17 -10
  32. package/claude/skills/role-worker/REQUIREMENT.md +1 -1
  33. package/claude/skills/role-worker/SKILL.md +6 -6
  34. package/claude/skills/session-compact/references/handoff-note.md +1 -1
  35. package/claude/skills/target-setup/SKILL.md +2 -2
  36. package/claude/skills/target-setup/references/detect.md +3 -3
  37. package/docs/agents/audits.md +1 -1
  38. package/docs/agents/commands.md +2 -4
  39. package/docs/agents/counts.md +5 -6
  40. package/docs/agents/drift-surfaces.md +15 -19
  41. package/docs/agents/index.md +2 -3
  42. package/docs/agents/install-and-sync.md +7 -31
  43. package/docs/agents/markdown-audit.md +10 -12
  44. package/docs/agents/migrate.md +1 -1
  45. package/docs/agents/records-stale.md +1 -1
  46. package/docs/agents/records-validate.md +11 -23
  47. package/docs/agents/records.md +1 -1
  48. package/docs/agents/routing.md +1 -1
  49. package/docs/agents/rule-citations.md +11 -14
  50. package/docs/agents/scripting.md +2 -20
  51. package/docs/agents/state-scoped-risk.md +1 -1
  52. package/docs/agents/tasks-validate.md +1 -1
  53. package/docs/agents/teach.md +1 -1
  54. package/docs/target/index.md +1 -0
  55. package/docs/target/migrations.md +4 -0
  56. package/docs/target/projects.md +9 -9
  57. package/docs/target/scenarios.md +5 -6
  58. package/docs/target/standards-moved.md +32 -0
  59. package/docs/target/sync.md +5 -5
  60. package/docs/workflow/operating-model.md +16 -18
  61. package/docs/workflow/skill-map.md +1 -1
  62. package/governance/detect.toml +0 -4
  63. package/governance/renames.toml +0 -1
  64. package/governance/stacks/base.toml +15 -8
  65. package/governance/stacks/go.toml +2 -0
  66. package/governance/stacks/node.toml +1 -1
  67. package/governance/stacks/php.toml +2 -0
  68. package/governance/stacks/python.toml +1 -1
  69. package/package.json +1 -4
  70. package/scripts/core/install-check.sh +2 -3
  71. package/src/audits/catalog.ts +0 -9
  72. package/src/claude/routing.ts +1 -1
  73. package/src/claude/skills-reach.ts +4 -6
  74. package/src/cli/help.ts +3 -4
  75. package/src/cli.ts +0 -2
  76. package/src/commands/gov.ts +5 -9
  77. package/src/commands/init.ts +1 -1
  78. package/src/commands/labels.ts +4 -44
  79. package/src/commands/migrate.ts +1 -1
  80. package/src/commands/records.ts +4 -20
  81. package/src/commands/tooling.ts +2 -4
  82. package/src/counts/catalogs.ts +0 -6
  83. package/src/gate/boundaries.ts +2 -2
  84. package/src/gate/measures.ts +6 -28
  85. package/src/gate/sequencer.ts +51 -2
  86. package/src/gate/stages.ts +0 -18
  87. package/src/gov/citations.ts +11 -43
  88. package/src/markdown/bans.ts +1 -1
  89. package/src/migrate/scratch-evidence.ts +2 -2
  90. package/src/records/validate.ts +6 -194
  91. package/src/sandbox/provision.ts +0 -5
  92. package/src/secrets/shipped.ts +1 -2
  93. package/src/serve/static.ts +1 -2
  94. package/src/shipped/references.ts +29 -80
  95. package/src/sync/check.ts +18 -14
  96. package/src/tooling/inject.ts +6 -37
  97. package/src/tooling/read.ts +2 -3
  98. package/src/tooling/scan.ts +4 -17
  99. package/src/tooling/subfolder.ts +2 -66
  100. package/tooling/base/configs/scripts/verify.json +1 -1
  101. package/tooling/base/configs/scripts/verify.ts +1 -12
  102. package/tooling/base/manifest.toml +1 -2
  103. package/tooling/base/reference.md +10 -16
  104. package/tooling/base/seeds/.github/workflows/verify.yml +0 -3
  105. package/tooling/base/seeds/.lintstagedrc +1 -2
  106. package/tooling/base/seeds/canon/context/ci.md +0 -1
  107. package/tooling/base/seeds/canon/context/development.md +1 -1
  108. package/tooling/claude/reference.md +1 -1
  109. package/tooling/claude/seeds/.claude/hooks/review-post-scan.sh +13 -1
  110. package/tooling/go/reference.md +1 -1
  111. package/tooling/php/reference.md +1 -1
  112. package/tooling/python/reference.md +2 -2
  113. package/tooling/web/configs/.github/workflows/verify.yml +0 -3
  114. package/tooling/web/manifest.toml +0 -1
  115. package/tooling/web/reference.md +2 -4
  116. package/docs/agents/standards-audit.md +0 -40
  117. package/governance/rules/tooling/765-spelling.md +0 -19
  118. package/governance/stacks/astro.toml +0 -2
  119. package/governance/stacks/nextjs.toml +0 -2
  120. package/governance/stacks/node-server.toml +0 -2
  121. package/governance/stacks/python-fastapi.toml +0 -2
  122. package/governance/stacks/react.toml +0 -2
  123. package/src/commands/standards.ts +0 -278
  124. package/src/labels/spelling.ts +0 -120
  125. package/src/standards/audit.ts +0 -146
  126. package/src/standards/list.ts +0 -33
  127. package/src/standards/read.ts +0 -177
  128. package/src/standards/scope.ts +0 -56
  129. package/standards/index.md +0 -10
  130. package/tooling/base/configs/.vscode/extensions.json +0 -9
  131. package/tooling/base/configs/.vscode/settings.json +0 -3
  132. package/tooling/base/seeds/.cspell/project-terms.txt +0 -0
  133. package/tooling/base/seeds/.cspell/tech-stack.txt +0 -25
  134. package/tooling/base/seeds/cspell.json +0 -20
  135. package/tooling/go/seeds/.cspell/tech-stack.txt +0 -16
  136. package/tooling/nextjs/seeds/.cspell/tech-stack.txt +0 -3
  137. package/tooling/php/seeds/.cspell/tech-stack.txt +0 -5
  138. package/tooling/python/seeds/.cspell/tech-stack.txt +0 -18
  139. package/tooling/vite-react/seeds/.cspell/project-terms.txt +0 -1
  140. package/tooling/vite-react/seeds/.cspell/tech-stack.txt +0 -2
  141. package/tooling/web/configs/.vscode/extensions.json +0 -13
  142. package/tooling/web/configs/.vscode/settings.json +0 -10
  143. package/tooling/web/seeds/.cspell/tech-stack.txt +0 -21
@@ -1,28 +1,25 @@
1
1
  ---
2
2
  title: Records validate
3
- description: Validating the session records and the standards corpus, the per-kind checks, which root each kind defaults to, the exit codes, and the refusal reasons
3
+ description: Validating the session records, the per-kind checks, which root they default to, the exit codes, and the refusal reasons
4
4
  ---
5
5
 
6
6
  # Records validate
7
7
 
8
- `canon records validate <kind>` reports where a file and the standard governing it disagree. Four kinds are gitignored folders under the record root, resolved at `.canon/` first: `plans`, `groundwork`, `intake`, and `teach`. The fifth is `standards`, the authoring corpus, which is tracked and installed rather than scratch.
8
+ `canon records validate <kind>` reports where a file and the standard governing it disagree. Four kinds exist, each a gitignored folder under the record root resolved at `.canon/` first: `plans`, `groundwork`, `intake`, and `teach`.
9
9
 
10
10
  ```bash
11
11
  canon records validate plans
12
- canon records validate standards
13
12
  canon records validate intake --json
14
13
  ```
15
14
 
16
- | Option | Behavior |
17
- | --------------- | ------------------------------------------------------------------- |
18
- | `--json` | Add a machine-readable record on stdout |
19
- | `--root <path>` | Project root, defaulting to the main worktree except on `standards` |
15
+ | Option | Behavior |
16
+ | --------------- | --------------------------------------------- |
17
+ | `--json` | Add a machine-readable record on stdout |
18
+ | `--root <path>` | Project root, defaulting to the main worktree |
20
19
 
21
- It reads and never writes, and the reason splits by kind. A session record is per-machine scratch with no history behind it, so a repair that guessed wrong could not be undone. A standard installs into every target and is cited by bare filename, so a rename the verb performed would reach further than the file it moved, which is why a finding naming one says so.
20
+ It reads and never writes. A session record is per-machine scratch with no history behind it, so a repair that guessed wrong could not be undone.
22
21
 
23
- `standards` reads the authoring root at `standards/` where it exists and a copy at `.claude/standards/` otherwise. The authoring root wins because it is the only tree anyone authors in and the only one the resolver answers from, so a finding fixed anywhere else is fixed where nothing reads it. No repository generates the second candidate any more, which leaves it as a floor under a target holding a copy an older toolkit installed. The walk stays flat, matching the catalog.
24
-
25
- Nothing fires it automatically. The four record folders are gitignored, so the standards-audit hook exits early on them and any check reading changed files from git never lists one. The corpus is tracked and still unreached, since the markdown audit reads content across the files git lists and rules on no filename. The verb runs at the moment a session claims the record is finished, which is the same placement `canon tasks validate` takes over the board.
22
+ Nothing fires it automatically. The four record folders are gitignored, so the standards-audit hook exits early on them and any check reading changed files from git never lists one. The verb runs at the moment a session claims the record is finished, which is the same placement `canon tasks validate` takes over the board.
26
23
 
27
24
  The two record roots every kind resolves at are in `records.md`.
28
25
 
@@ -33,37 +30,28 @@ The two record roots every kind resolves at are in `records.md`.
33
30
  | `plans` | A filename that is not `feature-<slug>.md`, a missing `# Feature:` heading, a missing required section, a files-to-touch entry naming no file or saying nothing about one, a question carrying no suggestion or no answer slot, and a batch still staged with a `**Batch N**` sub-heading inside the one file rather than split into its own plan |
34
31
  | `groundwork` | A track with no `README.md` or no `01-current-state.md`, a file missing `title` or `description`, a `README.md` with no `date` as `YYYY-MM-DD`, an unnumbered file, and a track holding a decision without its handoff or the reverse |
35
32
  | `intake` | A dump with no `00-overview.md`, the same frontmatter and numbering checks, an item missing any of `Problem`, `Fix`, `Worth it`, or `You`, and an item carrying `Open` with no `Suggested` |
36
- | `standards` | A standard missing `title` or `description`, an absent `## Scope` section, a scope section carrying no `Does not govern:` list, a statement anchoring nothing, and a filename naming no part of the path the statement governs |
37
33
  | `teach` | A workspace folder carrying no two-digit ordinal, an absent `MISSION.md`, `RESOURCES.md`, or `GLOSSARY.md`, a file missing `title` or `description`, a mission with no `date` as `YYYY-MM-DD` or no `## Success looks like` section, an unnumbered learning record, and a reference page opening with an ordinal |
38
34
 
39
35
  The half-closed track is the groundwork check a reader cannot run by eye. A folder holding `06` without `07` reads as closed to anyone scanning filenames while the file a returning session actually opens is absent.
40
36
 
41
37
  The item check skips `00-overview.md` and `99-next-session.md`, since neither holds items and running it over the handoff would report every heading it carries.
42
38
 
43
- The standards filename check derives a word from the governed path rather than counting words in the name. Every member of the corpus is named for the artifact its scope statement governs, and one word is what that produces rather than the rule itself, so a check keyed on word count would pass a conforming single word naming the wrong artifact. Each path segment offers its own word, a dotted container segment offers none, a hyphenated segment offers its parts, and the singular and the plural both match.
44
-
45
- The scope statement is read exactly as `canon standards list` reads it for the catalog's `appliesTo` field: backticked spans in the first sentence alone, with an attribute standard resolving where that sentence backticks nothing and the statement says it governs an attribute. One sentence read two ways would let a standard pass the check while publishing a different jurisdiction to every consumer of the catalog. An attribute standard is exempt from the filename derivation because it governs no path to derive from, and a statement that anchors nothing and claims no attribute is reported as `scope-unanchored` rather than passed, since silence there would let the backticks be removed to disable the check.
46
-
47
- An absent `## Scope` section suppresses the filename finding. The name derives from the statement, so a missing section leaves nothing to derive against, and reporting both would name one defect twice and point the fix at the wrong file. The walk skips `index.md`, which is generated from its siblings rather than authored.
48
-
49
- A plan section opens as a bold label or as an H2 and the check counts both, naming the standard's spelling when it reports one missing. The corpus splits roughly four to one between the two forms, so failing the variant would report nearly every plan on a rule that costs a reader nothing.
39
+ A plan section opens as a bold label or as an H2 and the check counts both, naming the reference's spelling when it reports one missing. Plans split roughly four to one between the two forms, so failing the variant would report nearly every plan on a rule that costs a reader nothing.
50
40
 
51
41
  A section runs to the next marker-shaped line whatever it names, so a plan carrying a label of its own closes the section above it rather than collecting into it. Fenced blocks are dropped before any of this, since a plan showing the shape it writes puts real-looking bullets and headings inside a fence.
52
42
 
53
43
  ## Exit codes and refusals
54
44
 
55
- Exit codes: `0` every check passed, `1` refused, `2` at least one record carries a finding. A `reason` field carries which gate fired: `no-folder` when none of the kind's directories exist, and `unknown-kind` when the argument names no published kind. A `no-folder` message names every candidate, so a record kind's refusal names both record roots and the `standards` refusal names the authoring root and the installed copy.
45
+ Exit codes: `0` every check passed, `1` refused, `2` at least one record carries a finding. A `reason` field carries which gate fired: `no-folder` when none of the kind's directories exist, and `unknown-kind` when the argument names no published kind. A `no-folder` message names every candidate, so a refusal names both record roots.
56
46
 
57
47
  An exit code says nothing about a call made from a session, since a shell profile may wrap the binary in a function taking its status from a later command. Read the record's `findings` array and its `reason` rather than the exit when a skill consumes this.
58
48
 
59
49
  The four record folders are shared scratch at the main worktree root, so `--root` defaults to the first entry of `git worktree list` rather than the working directory. A linked worktree validates the same records every other session reads.
60
50
 
61
- `standards` takes the other default, the root of the checkout the caller stands in. The corpus is tracked, so a linked worktree holds its own edited copy, and resolving the main root there would report on a tree the session never touched while saying nothing about which one it read. A session that adds or renames a standard inside a worktree is the case, and it is the one the check exists for.
62
-
63
51
  Skills branch on the findings rather than on the exit code:
64
52
 
65
53
  ```bash
66
54
  canon records validate plans --json | jq -r '.findings[] | "\(.kind): \(.subject)"'
67
55
  ```
68
56
 
69
- For the shapes each check enforces, see `claude/skills/plan-feature/references/plan.md`, `claude/skills/plan-groundwork/references/groundwork.md`, `claude/skills/plan-intake/references/intake.md`, and `standards/standard.md`.
57
+ For the shapes each check enforces, see `claude/skills/plan-feature/references/plan.md`, `claude/skills/plan-groundwork/references/groundwork.md`, and `claude/skills/plan-intake/references/intake.md`.
@@ -17,7 +17,7 @@ A refusal names every root it looked at, so a message reading `no-folder` says w
17
17
 
18
18
  ## Validate
19
19
 
20
- `canon records validate <kind>` reports where a record folder or the standards corpus disagrees with the standard governing it. Its flags, the per-kind checks, and the refusals are in `records-validate.md`.
20
+ `canon records validate <kind>` reports where a record folder disagrees with the standard governing it. Its flags, the per-kind checks, and the refusals are in `records-validate.md`.
21
21
 
22
22
  ## Ordinal
23
23
 
@@ -32,7 +32,7 @@ Three things are read past. A nested bullet belongs to the one above it rather t
32
32
 
33
33
  A bullet is path-scoped here when it names a path. That is evidence for the tier judgment rather than the judgment itself, and the gap runs both ways: a bullet naming a folder can still apply every session, and one firing on a path it never spells is invisible to the count. Read a section's number as a place to look rather than as a verdict on it.
34
34
 
35
- A backticked token counts when it carries a separator or an alphabetic extension, which admits `src/cli.ts` and `cspell.json` while leaving a flag, a bare word, and a version string out.
35
+ A backticked token counts when it carries a separator or an alphabetic extension, which admits `src/cli.ts` and `tsconfig.json` while leaving a flag, a bare word, and a version string out.
36
36
 
37
37
  A shape counts as the folder above its placeholder. `canon/context/<domain>.md` names `canon/context/` and nothing narrower, so dropping the token whole would report the section carrying it as naming no path at all. A placeholder opening the first segment has no openable prefix and is dropped.
38
38
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Rule citations
3
- description: Resolving every path a governance rule cites and every frontmatter glob the internal corpus declares, the three forms a citation is written in, the shapes that look like citations and are not, the two classes where an absent path is correct, why the glob half reads one corpus, and why this one gates
3
+ description: Resolving every path a governance rule cites and every frontmatter glob the internal corpus declares, the two forms a citation is written in, the shapes that look like citations and are not, the two classes where an absent path is correct, why the glob half reads one corpus, and why this one gates
4
4
  ---
5
5
 
6
6
  # Rule citations
@@ -28,32 +28,29 @@ Under `--json` the record holds stdout alone and the frame still renders on stde
28
28
 
29
29
  Two files agreeing is what a drift check measures. Whether either one is right about the tree is a different question, and this is the stage that asks it.
30
30
 
31
- ## The three forms
31
+ ## The two forms
32
32
 
33
- A citation reaches a reader in one of three shapes, and each resolves against a different root.
33
+ A citation reaches a reader in one of two shapes, and each resolves against a different root.
34
34
 
35
- | Form | Shape | Resolves against |
36
- | ---------- | ------------------------ | ---------------------------------- |
37
- | `standard` | `canon standards <name>` | `standards/<name>.md` |
38
- | `path` | a backticked path | the root |
39
- | `sibling` | a bare `<nnn>-<slug>.md` | the folder the citing rule sits in |
35
+ | Form | Shape | Resolves against |
36
+ | --------- | ------------------------ | ---------------------------------- |
37
+ | `path` | a backticked path | the root |
38
+ | `sibling` | a bare `<nnn>-<slug>.md` | the folder the citing rule sits in |
40
39
 
41
- `standard` is the live form and carries most of the corpus, which is what makes scoping this check to the two path shapes a check over almost nothing.
40
+ A call to the retired standards verb is no form here. A rule holding one fails the shipped-references stage of `canon gate run`, which reads every shipped file for it.
42
41
 
43
- A standard name resolves against the authoring root and nowhere else, matching `standardRoots` in `src/standards/read.ts`, which reads `standards/` at the working root and then the package corpus. The stage refuses a tree holding no rule corpus, so it runs only where those two roots are one directory. `internal/standards/` is deliberately not tried: `canon standards <name>` never reaches it, so admitting it would pass a citation that refuses for the session opening it, which is a gate failing open.
44
-
45
- A `path` is anchored on the whole backticked span rather than on a trailing pattern inside it. Cutting `standards/tooling-reference.md` out of `internal/standards/tooling-reference.md` and resolving that against the standards root reports a file that exists as missing, which is a mistake made by hand while measuring this corpus before the stage was written.
42
+ A `path` is anchored on the whole backticked span rather than on a trailing pattern inside it. Cutting `tooling-reference.md` out of `internal/standards/tooling-reference.md` and resolving that against the root alone reports a file that exists as missing, which is a mistake made by hand while measuring this corpus before the stage was written.
46
43
 
47
44
  ## What is not a citation
48
45
 
49
46
  A rule body is full of backticked spans carrying a slash, and almost none of them names a file in this tree. The stage declines four shapes outright.
50
47
 
51
- - A placeholder or glob segment describes a shape rather than naming a file: `canon/context/<domain>.md`, `standards/<name>.md`, `app/**/route.ts`, `${CLAUDE_SKILL_DIR}/../../standards/<name>.md`.
48
+ - A placeholder or glob segment describes a shape rather than naming a file: `canon/context/<domain>.md`, `app/**/route.ts`, `${CLAUDE_SKILL_DIR}/../references/<name>.md`.
52
49
  - A bare filename names a convention: `route.ts`, `manifest.toml`, `components.json`, `playwright.config.ts`. A bare name is read as a citation only when it matches a rule filename, which is how one authored rule would point at a sibling such as `605-worktrees.md`.
53
50
  - A span carrying no file extension is a folder or a module specifier: `src/pages/`, `next/font`, `try/except`, `react-hooks/set-state-in-effect`, `oven-sh/setup-bun@v2`, `@/lib/utils`.
54
51
  - A fenced block displays a path rather than pointing at one.
55
52
 
56
- The extension test is what carries most of the separation, and it costs one real path: `claude/standards` is a symlink this stage declines to check because nothing in the span says it is a file. Declining is the right direction for a gate, where a guess that goes wrong fails a push over prose.
53
+ The extension test is what carries most of the separation, and it costs the real paths that name a folder or a symlink, which this stage declines to check because nothing in the span says it is a file. Declining is the right direction for a gate, where a guess that goes wrong fails a push over prose.
57
54
 
58
55
  ## Where an absent path is correct
59
56
 
@@ -14,7 +14,6 @@ Use these to discover what's available instead of hardcoding names.
14
14
  | Command | Returns |
15
15
  | --------------------------------- | ---------------------------------------------------------------- |
16
16
  | `canon tooling list --json` | Stacks, extends chain, dep and script counts |
17
- | `canon standards list --json` | Standards docs and the paths each governs |
18
17
  | `canon gov list --json` | Governance stacks, rule sets, evidence, and unreferenced rules |
19
18
  | `canon gov detect --json` | Opt-in rules a target's dependencies and paths propose |
20
19
  | `canon claude seeds list --json` | Seed doc sources with content |
@@ -28,20 +27,6 @@ Every catalog serializes through `JSON.stringify`, so a name carrying a quote
28
27
  emits valid JSON. `canon tooling list` previously built
29
28
  its output with `printf` and no escaping.
30
29
 
31
- `canon standards list` carries `appliesTo` per standard, the paths that standard's
32
- `## Scope` statement declares. It holds the backticked paths from the first
33
- sentence of the statement, the single entry `*` for a standard governing an
34
- attribute rather than a document type, and an empty array when the statement
35
- declares nothing a parser can read. A consumer mapping a file to its governing
36
- standards reads this rather than holding a table of its own, and reports an empty
37
- array rather than skipping the standard behind it.
38
-
39
- Each standard also carries `source`, the labeled path of the copy `canon standards
40
- <name>` would read: `standards/<name>.md` for the working root and
41
- `<canon>/standards/<name>.md` for the package corpus. A project's own standard
42
- lists beside the package's, and one sharing a package name lists once, as the
43
- project's copy.
44
-
45
30
  `canon claude seeds list` reads the same plan `canon claude init` applies, so the
46
31
  listing and the install cannot disagree. It now reports
47
32
  `canon/context/index.md`, which `init` has always installed and the listing
@@ -94,7 +79,7 @@ CANON_NON_INTERACTIVE=1 canon tooling diff astro /path/to/project
94
79
  CANON_NON_INTERACTIVE=1 canon tooling sync astro /path/to/project --write
95
80
 
96
81
  # Install a governance stack (the stack argument is required headlessly)
97
- CANON_NON_INTERACTIVE=1 canon gov install astro --add 260-shadcn /path/to/project
82
+ CANON_NON_INTERACTIVE=1 canon gov install node --add 210-astro,260-shadcn /path/to/project
98
83
 
99
84
  # Update installed governance rules, dropping a retired .claude/GOV.md
100
85
  CANON_NON_INTERACTIVE=1 canon gov sync /path/to/project
@@ -116,11 +101,8 @@ canon tooling inject base /path/to/project --configs --seeds
116
101
  # Prints the number removed on stdout, diagnostics on stderr
117
102
  canon tooling prune-gitignore base /path/to/project
118
103
 
119
- # Print one standard. Nothing installs the corpus, so this is how a target reads one
120
- CANON_NON_INTERACTIVE=1 canon standards slug >slug.md
121
-
122
104
  # Bootstrap a project. Any flag suppresses the confirmation prompt
123
- CANON_NON_INTERACTIVE=1 canon init --stack astro --skip wiki /path/to/project
105
+ CANON_NON_INTERACTIVE=1 canon init --stack node --skip wiki /path/to/project
124
106
 
125
107
  # Run every domain sync. The git workflow is refused headlessly, so nothing is pushed
126
108
  CANON_NON_INTERACTIVE=1 canon sync /path/to/project
@@ -24,7 +24,7 @@ canon secrets scan ../my-app
24
24
 
25
25
  The corpus is the package's own `files` field rather than a list the check keeps. That field is the single statement of which trees leave this repository, so a second list beside it would answer the same question and drift. It also carries the negations the publish already makes, which is what puts the eval tree and every test file out of scope by the rule that keeps them out of the tarball rather than by an exclusion this check invented. The sandbox tree sits under no `files` entry at all, so the same field leaves it out without a negation.
26
26
 
27
- The plugin reaches a target by a different route, loading live from `claude/` rather than from a tarball. That folder is a `files` entry too, and its `standards` symlink resolves into a tree the field lists in its own right, so both routes land inside the same corpus.
27
+ The plugin reaches a target by a different route, loading live from `claude/` rather than from a tarball. That folder is a `files` entry too, so both routes land inside the same corpus.
28
28
 
29
29
  Three root files are read whether or not the field names them, being `package.json`, the readme, and the license, since npm packs those on every publish. A negation still removes one, because a field that excludes a file outranks the default that included it.
30
30
 
@@ -130,4 +130,4 @@ Skills branch on the findings rather than on the exit code:
130
130
  canon tasks validate --json | jq -r '.findings[] | "\(.kind): \(.subject)"'
131
131
  ```
132
132
 
133
- For the board format, see `canon standards board`. For the `Pull request:` line and the archive rules, see `canon standards tasks`.
133
+ The `task-board` skill's `board.md` and `tasks.md` references carry the board format, the `Pull request:` line, and the archive rules.
@@ -81,7 +81,7 @@ canon teach resource regular-expressions \
81
81
  | `--json` | Emit a machine-readable record on stdout |
82
82
  | `--root <path>` | Teach root, defaulting to the main worktree |
83
83
 
84
- The pair splits on the first `=`, so a URL carrying its own separator survives intact. Say in the title which claims rest on the source, since the entry is the only place a later session reads that from. Which sources qualify is the source ladder in `canon standards teach`, and a source below its first two rungs also names why no higher one covers the claim.
84
+ The pair splits on the first `=`, so a URL carrying its own separator survives intact. Say in the title which claims rest on the source, since the entry is the only place a later session reads that from. Which sources qualify is the source ladder in `claude/skills/teach-workspace/references/teach.md`, and a source below its first two rungs also names why no higher one covers the claim.
85
85
 
86
86
  A URL either heading already lists is refused rather than written twice. Two entries for one source split what rests on it across two lines, and a reader checking a claim then finds half of the answer. The exception is a `--read` URL already under `## Leads`, which moves to `## Read` under the title the call carries, since opening a lead is how it becomes read. A `--read` URL already under `## Read`, and any `--lead` URL already listed, stays refused, and a refusal leaves the whole batch unwritten.
87
87
 
@@ -13,4 +13,5 @@ Scaffold, sync, and migrate a toolkit-managed project, with worked setups for th
13
13
  - [Target migrations](migrations.md): One-time moves a project scaffolded under an older toolkit runs before its next sync
14
14
  - [Target projects](projects.md): Scaffold, add domains later, and sync upstream drift in a toolkit-managed project
15
15
  - [Target scenarios](scenarios.md): Worked setups for a markdown-heavy project, a web application, and a monorepo
16
+ - [Target standards moved](standards-moved.md): Which skill owns each standard the retired standards verb used to serve, for a project that still calls it
16
17
  - [Target sync](sync.md): Check what drifted in a toolkit-managed project and pull it in, per domain or all at once
@@ -124,6 +124,10 @@ The walk checks both `.claude/snippets` and a root `snippets/`, since a toolkit
124
124
 
125
125
  The walk reads the toolkit's own history, so it needs a cloned toolkit. Installed from the registry it reports `historyUnavailable` and names nothing, so check for `.claude/snippets/` and a root `snippets/` by hand there, and treat what you find as `unattributed`.
126
126
 
127
+ ## Stop calling the standards verb, once
128
+
129
+ `canon standards` is gone. Replace each call with a skill reference from [target standards moved](standards-moved.md). <!-- canon-allow-reference: verb retired -->
130
+
127
131
  ## Keep or delete the wireframes folder, your call
128
132
 
129
133
  The toolkit retired the wireframes record. Its standard, its generated rule, its seeded folder, and the `@canon/wireframes/index.md` import in the seed `CLAUDE.md` no longer ship, and no skill reads or writes `canon/wireframes/` any more. The canvas holds visual direction instead.
@@ -38,7 +38,7 @@ The `canon` CLI is separate. Twenty skills invoke it in a command position, and
38
38
  bun install --global @erclx/canon
39
39
  ```
40
40
 
41
- The package ships the catalogs the CLI reads, not only `src/`, so `canon init` resolves governance, tooling, and the seeds from wherever the package landed, and `canon standards <name>` reads the corpus from there too.
41
+ The package ships the catalogs the CLI reads, not only `src/`, so `canon init` resolves governance, tooling, and the seeds from wherever the package landed.
42
42
 
43
43
  Pointing Claude Code at a checkout stays the development path, where a local skill edit overrides the installed copy for that session.
44
44
 
@@ -82,25 +82,25 @@ Nothing watches a figure once it is drawn. Run `canon:draft-figure` again when t
82
82
 
83
83
  ### Stack decision
84
84
 
85
- The default path is `base`. `canon init` on `base` installs base tooling configs, Claude seeds, and the `canon`, `claude`, `tooling`, and `writing` governance rule groups, and scaffolds an empty `.claude/wiki/`. Most projects need nothing more.
85
+ The default path is `base`. `canon init` on `base` installs base tooling configs, Claude seeds, and the ten `base` governance rules, and scaffolds an empty `.claude/wiki/`. Most projects need nothing more.
86
86
 
87
- Escalate only for real web apps. The `target-setup` skill reads `package.json` and the framework configs, then picks the matching tooling stack (`canon tooling list --json` names the current set) and the matching governance stack (`react`, `nextjs`, `astro`, `node`). A Next.js app lands on `nextjs`, which extends `react` with the App Router rule a Vite React app does not get.
87
+ Escalate for a project writing code. The `target-setup` skill reads `package.json` and the framework configs, then picks the matching tooling stack (`canon tooling list --json` names the current set) and the governance stack for the root's language (`node`, `python`, `go`, `php`). Framework rules arrive as extras `canon gov detect` proposes from the manifest, so a Next.js app lands on `node` with the App Router rule proposed, and a Vite React app gets no such proposal.
88
88
 
89
89
  In a monorepo the skill reads each folder holding a `package.json`, `pyproject.toml`, `go.mod`, `composer.json`, or `Cargo.toml` to depth two, skipping what git ignores. Each of those folders gets its own tooling stack and a `canon tooling sync <stack> <folder> --skip base` in the preview. Governance still installs once at the root, since a rule's `paths:` globs reach every subfolder, so a subfolder's language rules join the root install through `--add`.
90
90
 
91
- `node-server` is named rather than detected. It carries the server-side security and persistence rules for a project writing request handlers or a persistence layer in TypeScript, and the detect step matches a runtime or a framework against stack names, so the stack never resolves on its own. `canon gov detect` proposes its two rules from a server framework or database client in the manifest, which you confirm in the preview. Pass the stack deliberately with `canon init --stack node-server` or `canon gov install node-server <target>`.
91
+ The server-side security and persistence rules belong to no stack. `canon gov detect` proposes both from a server framework or database client in the manifest, which you confirm in the preview, or add them by hand with `--add 360-security-server,370-database`.
92
92
 
93
93
  Markdown-heavy projects, CLI tools, docs sites, research notebooks, and scripting repos stay on `base`. Escalation is a ceiling move, not a default.
94
94
 
95
- A project the toolkit ships no stack for lands on `base` the same way, and the skill marks that resolution as a fallback in its preview rather than reporting it as a match. Configs, seeds, and gitignore entries land either way, and the JavaScript development dependencies, scripts, and hook activation land only where a `package.json` exists to carry them. A project outside that ecosystem declines at the preview and takes `canon:target-setup gov` for the governance layer alone, which is language-neutral. Go and PHP ship tooling stacks but no governance stack, so a project in either takes the `go` or `php` tooling stack, lands on `base` for governance, and picks up its language and testing rules through `--add`, for example `canon gov install base --add 130-go,335-testing-go .`
95
+ A project the toolkit ships no stack for lands on `base` the same way, and the skill marks that resolution as a fallback in its preview rather than reporting it as a match. Configs, seeds, and gitignore entries land either way, and the JavaScript development dependencies, scripts, and hook activation land only where a `package.json` exists to carry them. A project outside that ecosystem declines at the preview and takes `canon:target-setup gov` for the governance layer alone, which is language-neutral. Go and PHP ship a governance stack beside their tooling stack, so a project in either takes `go` or `php` for both.
96
96
 
97
97
  Run `canon tooling list --json` and `canon gov list --json` to see the current catalogs. Never hardcode stack names.
98
98
 
99
99
  ### Core domains and skips
100
100
 
101
- `canon init` installs base tooling, Claude workflow, and governance, and scaffolds `.claude/wiki/`. Governance defaults to the `base` stack, so a bare init carries the rules that route a project. Pass `--stack <name>` to install a framework stack instead.
101
+ `canon init` installs base tooling, Claude workflow, and governance, and scaffolds `.claude/wiki/`. Governance defaults to the `base` stack, so a bare init carries the rules that route a project. Pass `--stack <name>` to install a language stack instead.
102
102
 
103
- No standard is written into the project. Each governance rule's authority line names `canon standards <name>`, which answers from the corpus inside the CLI's own package, and every toolkit skill names the copy in its own plugin root. `canon markdown audit` needs no standard at all, its ban set and checkpoints shipping with the package as data.
103
+ No reference corpus is written into the project. Each governance rule carries its operative lines inline and names the plugin skill that owns the rest, and every toolkit skill reads the references in its own plugin root. A target that installs governance without the plugin gets the inline lines alone, since no verb answers for a skill's reference there. `canon markdown audit` needs no reference at all, its ban set and checkpoints shipping with the package as data.
104
104
 
105
105
  `governance` and `wiki` are skippable:
106
106
 
@@ -117,7 +117,7 @@ When a new need appears after scaffold, install the one domain without re-runnin
117
117
  - Project-specific rule the toolkit does not ship: invoke `canon:create-rule`. It scaffolds a rule into `.claude/rules/project/` with a non-colliding number, and `canon gov sync` leaves it untouched. A rule placed under `.claude/rules/canon/` instead is deleted on the next sync, since that folder belongs to the toolkit.
118
118
  - Index.md system for a markdown-heavy folder that emerged: invoke `canon:target-setup indexes`
119
119
 
120
- Standards are not on that list, and there is nothing to add for them. They install into no project, by default or by flag, so a session reads one with `canon standards <name>`, resolving against the toolkit rather than a project copy. A project holding a `.claude/standards/` folder from an older toolkit is carrying a stale artifact nothing reads, and deleting it is safe. The toolkit retired snippets entirely, and [target migrations](migrations.md) covers the `.claude/snippets/` folder an older one left behind.
120
+ Skill references are not on that list, and there is nothing to add for them. They install into no project, by default or by flag, and a session reads one from the plugin that loaded the skill rather than from a project copy. A project holding a `standards` folder under `.claude/` from an older toolkit is carrying a stale artifact nothing reads, and deleting it is safe. The toolkit retired snippets entirely, and [target migrations](migrations.md) covers the `.claude/snippets/` folder an older one left behind.
121
121
 
122
122
  Per-domain mechanics live in the corresponding `docs/<domain>.md`. The skill body in `claude/skills/<skill>/SKILL.md` covers detection and preview.
123
123
 
@@ -134,5 +134,5 @@ When the toolkit updates, a target pulls changes per domain. A project scaffolde
134
134
  - [agents](../agents/index.md): CLI flags, exit codes, and JSON output shapes
135
135
  - [target migrations](migrations.md), [target sync](sync.md), [target scenarios](scenarios.md): the one-time moves, the recurring sync, and worked setups
136
136
  - [AI workflow](../workflow/ai-workflow.md): feature-development loop inside a toolkit-managed project
137
- - [tooling](../../canon/context/tooling/index.md), [governance](../../canon/context/governance/index.md), [claude plugin](../../canon/context/claude-plugin/index.md), [indexes](../../canon/context/context-model/indexes.md), [standards](../../canon/context/standards/index.md): per-domain mechanics
137
+ - [tooling](../../canon/context/tooling/index.md), [governance](../../canon/context/governance/index.md), [claude plugin](../../canon/context/claude-plugin/index.md), [indexes](../../canon/context/context-model/indexes.md), [skill references](../../canon/context/claude-plugin/skill-references/index.md): per-domain mechanics
138
138
  - [sandbox](../../canon/context/sandbox/index.md): scenario catalog for verifying domain flows
@@ -26,7 +26,7 @@ bun create vite my-app && cd my-app
26
26
  claude
27
27
  ```
28
28
 
29
- Invoke `canon:target-setup`. The skill reads `package.json` and the Vite config, resolves tooling to `vite-react` and governance to `react`, and runs `canon init` with the resolved flags.
29
+ Invoke `canon:target-setup`. The skill reads `package.json` and the Vite config, resolves tooling to `vite-react` and governance to `node`, proposes `200-react` and the other rules its manifest matches as extras, and runs `canon init` with the resolved flags.
30
30
 
31
31
  Ongoing maintenance:
32
32
 
@@ -34,23 +34,22 @@ Ongoing maintenance:
34
34
  - Seed drift: merge by hand against the toolkit copy
35
35
  - Catch-all sync: `canon sync .`
36
36
  - Governance rule refresh only: `canon gov sync .`
37
- - Layer a new rule on top, for example `260-shadcn` after adopting shadcn: `canon gov install react --add 260-shadcn .`
37
+ - Layer a new rule on top, for example `260-shadcn` after adopting shadcn: `canon gov install node --add 260-shadcn .`
38
38
 
39
39
  ## Monorepo with multiple language roots
40
40
 
41
41
  The repo root owns the shared `base` layer, and each language lives in its own subfolder.
42
42
 
43
43
  ```bash
44
- canon init --stack react .
44
+ canon init --stack node --add 200-react .
45
45
  canon tooling sync vite-react ./frontend --skip base --write
46
46
  canon tooling sync python ./backend --skip base --write
47
47
  ```
48
48
 
49
- `--skip base` drops the `base` layer from each subtree sync, so husky, prettier, cspell, commitlint, and CI stay single at the repo root. The one exception is base's verify runner, `scripts/verify.sh`, `scripts/verify.ts`, and `scripts/verify.json`, which every subtree still receives so it can verify on its own. Without it, every subtree re-drops husky, and since git honors only one `core.hooksPath` the extra hook dirs silently break. Each subtree still gets its own framework configs (eslint, vitest, tsconfig, vite), and its own stack reference reads through `canon tooling reference <stack>`.
49
+ `--skip base` drops the `base` layer from each subtree sync, so husky, prettier, commitlint, and CI stay single at the repo root. The one exception is base's verify runner, `scripts/verify.sh`, `scripts/verify.ts`, and `scripts/verify.json`, which every subtree still receives so it can verify on its own. Without it, every subtree re-drops husky, and since git honors only one `core.hooksPath` the extra hook dirs silently break. Each subtree still gets its own framework configs (eslint, vitest, tsconfig, vite), and its own stack reference reads through `canon tooling reference <stack>`.
50
50
 
51
51
  A sync whose target sits below the git root knows it is writing into a subfolder:
52
52
 
53
53
  - It withholds `.github/`, since GitHub reads workflows only at the repository root, and names each withheld file. Run the subtree from a job in the root workflow instead, with `working-directory` set to the subtree path the sync prints, such as `working-directory: frontend`.
54
- - It writes a nested `cspell.json` that registers the subtree's word lists, so a root `cspell '**'` reads them for files under that folder. It leaves a spell config the subtree already has alone.
55
54
  - It installs no dependencies and adds no scripts to a subtree without a `package.json`. It names what it skipped and ends on `run 'bun init' in <path>, then sync again`.
56
- - The subtree carries no `check` script, since that lives in the root's base layer, so run `./scripts/verify.sh` there. It skips the format, spell, and shell phases a subtree does not declare, since the root runs them, and still fails on a missing lint, typecheck, or test script, the phases its stack's `scripts/verify.json` requires.
55
+ - The subtree carries no `check` script, since that lives in the root's base layer, so run `./scripts/verify.sh` there. It skips the format and shell phases a subtree does not declare, since the root runs them, and still fails on a missing lint, typecheck, or test script, the phases its stack's `scripts/verify.json` requires.
@@ -0,0 +1,32 @@
1
+ ---
2
+ title: Target standards moved
3
+ description: Which skill owns each standard the retired standards verb used to serve, for a project that still calls it
4
+ category: Agent surface
5
+ ---
6
+
7
+ # Target standards moved
8
+
9
+ `canon standards <name>` is gone, and with it the name map that sent an old call to a new home. A rule, skill, or `CLAUDE.md` of your own that still runs it now gets commander's too-many-arguments error and no content, so search the project for the call and replace it. The surrounding step is in [target migrations](migrations.md). <!-- canon-allow-reference: says the verb is gone -->
10
+
11
+ Each standard now lives at `references/<name>.md` in the skill that owns it. Load that skill and read the reference it names:
12
+
13
+ - `task-board`: `board`, `tasks`, `tasks-decline`
14
+ - `context-fold`: `context`
15
+ - `canvas-board`: `canvas`, `design`
16
+ - `docs-sync`: `docs`, `readme`
17
+ - `draft-figure`: `figures`, `mermaid`
18
+ - `create-rule`: `rule`
19
+ - `create-skill`: `skill`, `skill-paths`, `skill-practice`, `skill-requirement`
20
+ - `git-branch`: `branch`, `slug`
21
+ - `git-commit`: `commit`, `versioning`
22
+ - `git-pr`: `pr`, `publish`
23
+ - `markdown-craft`: `markdown`
24
+ - `teach-workspace`: `glossary`, `teach`
25
+ - `plan-groundwork`: `groundwork`, `groundwork-spikes`
26
+ - `plan-intake`: `intake`
27
+ - `plan-feature`: `plan`, `plan-lifecycle`
28
+ - `draft-ready`: `ready`
29
+ - `draft-doc`: `requirements`, `wiki`
30
+ - `session-map`: `session`
31
+
32
+ One name moved under a new filename. `standard`, the shape of a standard itself, became `skill-reference.md` in `create-skill`, since the toolkit no longer ships a standards folder to hold one.
@@ -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
 
@@ -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 |
@@ -25,10 +25,6 @@ files = [".claude/skills", "claude/skills"]
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
28
  ["775-dependencies"]
33
29
  deps = []
34
30
  files = ["**/package.json", "**/pyproject.toml", "**/go.mod", "**/composer.json"]
@@ -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"
@@ -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
+ "566-output",
7
+ "602-tasks",
8
+ "604-scratch",
9
+ "605-worktrees",
10
+ "606-git",
11
+ "611-indexes",
12
+ "context",
13
+ "tasks",
14
+ "plan",
15
+ "markdown",
16
+ ]