@erclx/canon 4.126.0 → 5.1.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 (107) hide show
  1. package/README.md +5 -7
  2. package/claude/.claude-plugin/plugin.json +1 -1
  3. package/claude/skills/auto-ship/references/verb-absent.md +0 -1
  4. package/claude/skills/canon-feedback/REQUIREMENT.md +1 -1
  5. package/claude/skills/canon-feedback/SKILL.md +2 -2
  6. package/claude/skills/canon-operator/REQUIREMENT.md +2 -2
  7. package/claude/skills/canon-operator/SKILL.md +3 -3
  8. package/claude/skills/codebase-layout/REQUIREMENT.md +1 -0
  9. package/claude/skills/codebase-layout/SKILL.md +6 -0
  10. package/claude/skills/create-rule/REQUIREMENT.md +1 -1
  11. package/claude/skills/create-standard/REQUIREMENT.md +0 -2
  12. package/claude/skills/decision-escalate/REQUIREMENT.md +1 -2
  13. package/claude/skills/draft-context/REQUIREMENT.md +1 -1
  14. package/claude/skills/draft-docs/REQUIREMENT.md +1 -1
  15. package/claude/skills/draft-wireframes/REQUIREMENT.md +1 -1
  16. package/claude/skills/git-pr/references/task-number.md +2 -0
  17. package/claude/skills/plan-intake/SKILL.md +1 -1
  18. package/claude/skills/target-setup/REQUIREMENT.md +2 -2
  19. package/claude/skills/target-setup/SKILL.md +1 -1
  20. package/claude/skills/target-setup/references/detect.md +1 -1
  21. package/claude/skills/target-setup/references/indexes.md +1 -5
  22. package/claude/skills/task-board/references/archive.md +1 -0
  23. package/docs/agents/commands.md +1 -3
  24. package/docs/agents/counts.md +1 -2
  25. package/docs/agents/docs.md +1 -1
  26. package/docs/agents/drift-surfaces.md +6 -4
  27. package/docs/agents/index.md +1 -1
  28. package/docs/agents/indexes.md +1 -1
  29. package/docs/agents/install-and-sync.md +1 -8
  30. package/docs/agents/markdown-audit.md +2 -2
  31. package/docs/agents/restated.md +7 -5
  32. package/docs/agents/review-classification.md +1 -2
  33. package/docs/agents/scripting.md +2 -3
  34. package/docs/agents/skills-reach.md +3 -3
  35. package/docs/agents/state-scoped-risk.md +1 -1
  36. package/docs/agents/tasks-archive.md +1 -1
  37. package/docs/agents/tasks.md +4 -0
  38. package/docs/target/index.md +4 -4
  39. package/docs/target/{target-migrations.md → migrations.md} +17 -1
  40. package/docs/target/{target-projects.md → projects.md} +5 -7
  41. package/docs/target/{target-scenarios.md → scenarios.md} +1 -1
  42. package/docs/target/{target-sync.md → sync.md} +4 -2
  43. package/docs/workflow/ai-workflow.md +3 -7
  44. package/docs/workflow/operating-model.md +4 -4
  45. package/docs/workflow/parallel-features.md +1 -1
  46. package/docs/workflow/skill-map.md +1 -2
  47. package/docs/workflow/visual-design-workflow.md +5 -5
  48. package/docs/workflow/zshrc-aliases.md +1 -1
  49. package/package.json +1 -2
  50. package/scripts/core/check-plugin-boundary.sh +1 -1
  51. package/scripts/core/install-check.sh +3 -4
  52. package/scripts/core/regen-hero.sh +2 -9
  53. package/src/autoship/paths.ts +3 -5
  54. package/src/claude/cases/authoring.ts +1 -5
  55. package/src/claude/skills-reach.ts +1 -2
  56. package/src/cli.ts +0 -2
  57. package/src/commands/feedback-format.ts +0 -1
  58. package/src/commands/gov.ts +8 -7
  59. package/src/commands/labels.ts +3 -3
  60. package/src/commands/markdown.ts +2 -2
  61. package/src/commands/tasks.ts +82 -2
  62. package/src/counts/catalogs.ts +0 -16
  63. package/src/counts/scan.ts +1 -1
  64. package/src/docs/read.ts +25 -25
  65. package/src/gate/measures.ts +52 -0
  66. package/src/gate/stages.ts +9 -0
  67. package/src/gov/restated.ts +60 -22
  68. package/src/help.ts +0 -2
  69. package/src/init/steps.ts +1 -1
  70. package/src/labels/format.ts +2 -2
  71. package/src/migrate/skill-names.ts +4 -5
  72. package/src/secrets/shipped.ts +2 -2
  73. package/src/serve/static.ts +1 -2
  74. package/src/shipped/references.ts +7 -8
  75. package/src/sync/engine.ts +2 -2
  76. package/src/tasks/archive.ts +30 -0
  77. package/src/tasks/record.ts +106 -9
  78. package/standards/commit.md +1 -1
  79. package/standards/context.md +2 -0
  80. package/standards/docs.md +1 -0
  81. package/standards/index.md +0 -1
  82. package/standards/pr.md +1 -1
  83. package/standards/skill.md +1 -2
  84. package/standards/tasks.md +2 -2
  85. package/standards/wiki.md +2 -1
  86. package/tooling/base/reference.md +2 -2
  87. package/tooling/claude/reference.md +1 -1
  88. package/claude/skills/create-snippet/REQUIREMENT.md +0 -39
  89. package/claude/skills/create-snippet/SKILL.md +0 -30
  90. package/scripts/snippets/create.sh +0 -156
  91. package/snippets/align.md +0 -12
  92. package/snippets/claude/decision-memo.md +0 -39
  93. package/snippets/claude/feature-recap.md +0 -19
  94. package/snippets/claude/figma-steps.md +0 -24
  95. package/snippets/compact-summary.md +0 -5
  96. package/snippets/decision-help.md +0 -6
  97. package/snippets/meta-prompt.md +0 -14
  98. package/snippets/research-prompt.md +0 -7
  99. package/snippets/session-notes.md +0 -11
  100. package/snippets/snippets.toml +0 -5
  101. package/snippets/step-by-step.md +0 -10
  102. package/snippets/web-research.md +0 -21
  103. package/src/commands/snippets.ts +0 -90
  104. package/src/snippets/categories.ts +0 -66
  105. package/src/snippets/list.ts +0 -32
  106. package/src/snippets/presets.ts +0 -50
  107. package/standards/snippets.md +0 -76
package/README.md CHANGED
@@ -64,7 +64,6 @@ Each domain has a canonical source in this repo and a thin install or sync CLI o
64
64
  | Plugin skills | Skills that plan a feature, review a diff, sync the planning docs, and run the ship chain | Loaded live from the plugin, never copied |
65
65
  | Governance | Coding and authoring rules that load into a Claude session when a matching path is edited | Installed per project by `canon gov install`, refreshed by sync |
66
66
  | Standards | Authoring conventions for commits, branches, plans, tasks, and markdown | Opened by name, read by name with `canon standards <name>` |
67
- | Snippets | Reusable prompts fired by `@` reference | Resolved live from the plugin |
68
67
  | Tooling stacks | Golden configs, seeds, and a reference per framework | Laid down by `canon init`, reconciled by `canon tooling sync` |
69
68
  | Design system | Ships a `DESIGN.md` token format, a skill that drafts one from an existing project or from scratch, and a render command | `canon design render` |
70
69
  | Slides | A `SLIDES.md` source format with a layout catalog | `canon slides render` writes PowerPoint |
@@ -96,7 +95,7 @@ Working with an agent rather than reading this yourself? It loads `CLAUDE.md` at
96
95
  - [AI workflow](docs/workflow/ai-workflow.md): feature-development loop inside a toolkit-managed project
97
96
  - [Operating model](docs/workflow/operating-model.md): orchestrator, planner, and worker roles for building across parallel sessions
98
97
  - [Visual design workflow](docs/workflow/visual-design-workflow.md): tiered guide for design and wireframe authoring
99
- - [Target projects](docs/target/target-projects.md): scaffold, add a domain later, sync upstream drift
98
+ - [Target projects](docs/target/projects.md): scaffold, add a domain later, sync upstream drift
100
99
  - [Agents](docs/agents/index.md): CLI flags, exit codes, and JSON output shapes
101
100
  - [Docs index](docs/index.md): every reference doc in this repo
102
101
 
@@ -150,9 +149,9 @@ canon init
150
149
 
151
150
  `canon init` installs base tooling configs, Claude seeds, and governance rules in one pass, and scaffolds a `.claude/wiki/` stub for your project's own reference pages. Governance defaults to the `base` stack, so a bare init lands the coding and doc-authoring rules in `.claude/rules/`. Each rule names the standard it answers to and reads it with `canon standards <name>`, so no corpus is copied into your project.
152
151
 
153
- Pass `--stack <name>` for a framework stack, or `--skip governance` to leave rules out. A snippet resolves the same way, reached at its `@` reference through the plugin's live `claude/snippets` symlink rather than a copy. Run `canon tooling list --json` to see the catalog.
152
+ Pass `--stack <name>` for a framework stack, or `--skip governance` to leave rules out. Run `canon tooling list --json` to see the catalog.
154
153
 
155
- For the full journey from scaffold through adding a domain later to syncing upstream drift, see [target projects](docs/target/target-projects.md).
154
+ For the full journey from scaffold through adding a domain later to syncing upstream drift, see [target projects](docs/target/projects.md).
156
155
 
157
156
  ### Internal narrative
158
157
 
@@ -161,11 +160,10 @@ Each domain carries an entry written for someone maintaining the toolkit rather
161
160
  - [Claude Code plugin](canon/context/claude-plugin/index.md)
162
161
  - [Governance rules](canon/context/governance/index.md)
163
162
  - [Standards](canon/context/standards/index.md)
164
- - [Snippets](canon/context/snippets.md)
165
163
  - [Tooling stacks](canon/context/tooling/index.md)
166
164
  - [Design system](canon/context/design/index.md)
167
- - [Slides](canon/context/slides.md)
168
- - [Transcripts](canon/context/transcripts.md)
165
+ - [Slides](canon/context/features/slides.md)
166
+ - [Transcripts](canon/context/features/transcripts.md)
169
167
  - [Sandbox](canon/context/sandbox/index.md)
170
168
 
171
169
  ## Contributing
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "canon",
3
3
  "description": "Automated governance, versioning, and discovery tools for Claude Code.",
4
- "version": "4.126.0",
4
+ "version": "5.1.0",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -24,7 +24,6 @@ Behavior paths carry two spellings, the one a surface authors at and the one it
24
24
  - `claude/skills/` and `.claude/skills/`
25
25
  - `governance/rules/` and `.claude/rules/`
26
26
  - `standards/`, which is the authoring root and reaches a reader by resolution rather than by an install, so it carries no `.claude/` spelling
27
- - `snippets/`, which reaches a session through the `claude/snippets` symlink rather than an install, so it carries no `.claude/` spelling either
28
27
  - `internal/` and `tooling/`, which hold the stack references and the seed documents a target is handed
29
28
  - `CLAUDE.md` at the repository root, named as a file because a path prefix reaches nothing that sits in no folder
30
29
 
@@ -9,7 +9,7 @@ description: Why a toolkit defect is reported from session context alone, and wh
9
9
 
10
10
  Without this skill, a toolkit defect noticed inside a target project dies with the session. The user is told to mention it in the toolkit repository later, which means retyping a report they no longer have the context to write, so the defect is either reported badly or not at all.
11
11
 
12
- The report itself fails two ways. A block printed in chat needs a copy-paste into another repository, and a step that manual is skipped under any time pressure. A report that names no surface cannot be routed, because the toolkit acts on a plugin skill, a snippet, a CLI command, and a seed through different paths, and the difference is not recoverable from the symptom.
12
+ The report itself fails two ways. A block printed in chat needs a copy-paste into another repository, and a step that manual is skipped under any time pressure. A report that names no surface cannot be routed, because the toolkit acts on a plugin skill, a CLI command, and a seed through different paths, and the difference is not recoverable from the symptom.
13
13
 
14
14
  The last failure is the session's own effort. Asked to report, a session starts diagnosing instead, searching the toolkit and reading its surfaces to find the cause. That spends the context the report was meant to capture cheaply, and it produces a diagnosis from a project that cannot see the toolkit's current source.
15
15
 
@@ -10,7 +10,7 @@ Format a `## Toolkit feedback` block from the current session, then open it as a
10
10
  ## Guards
11
11
 
12
12
  - If nothing in session context points to a toolkit issue, stop: `❌ No toolkit issue in session context. Describe what broke, then re-invoke.`
13
- - If the surface type is ambiguous (snippet vs. plugin skill vs. CLI vs. seed), ask one line before formatting.
13
+ - If the surface type is ambiguous (plugin skill vs. CLI vs. seed), ask one line before formatting.
14
14
  - Do not probe the project, list files, grep, or read toolkit surfaces. Use only what the session already contains.
15
15
 
16
16
  ## Step 1: build the block
@@ -18,7 +18,7 @@ Format a `## Toolkit feedback` block from the current session, then open it as a
18
18
  From the conversation so far, identify:
19
19
 
20
20
  - Target project name or kind, never its full path. The path names a folder on one machine and says nothing a triage session can route on, where the project's own name does. Name a private project by its kind instead, such as `a Next.js app`, since the report leaves the machine.
21
- - Toolkit surface and its type (plugin skill, snippet, tooling config, governance rule, seed, or CLI). The type leads the `### Surface` field, ahead of the first comma, because the CLI picks the issue's domain labels from that text alone.
21
+ - Toolkit surface and its type (plugin skill, tooling config, governance rule, seed, or CLI). The type leads the `### Surface` field, ahead of the first comma, because the CLI picks the issue's domain labels from that text alone.
22
22
  - Specific toolkit file or name when the session cites one
23
23
  - Observed behavior
24
24
  - Expected behavior, or `unclear`
@@ -9,7 +9,7 @@ description: Why the toolkit has one front door, what orienting on live catalogs
9
9
 
10
10
  Without this skill, using the toolkit means knowing which skill to pick, and the user who most needs it is the one who cannot. A plain-language intent has no obvious owner among a dozen setup and sync skills, so the session guesses a command instead of resolving one, and a wrong guess installs into a project rather than reporting a mismatch.
11
11
 
12
- Two failures come from acting on memory. A session that names a stack, rule, or snippet from what it remembers rather than from the live catalog runs against an entry that has been renamed or removed. And a session that edits a managed file by hand produces a change the next sync overwrites, which reads as the toolkit undoing work rather than as the edit having been made in the wrong place.
12
+ Two failures come from acting on memory. A session that names a stack or rule from what it remembers rather than from the live catalog runs against an entry that has been renamed or removed. And a session that edits a managed file by hand produces a change the next sync overwrites, which reads as the toolkit undoing work rather than as the edit having been made in the wrong place.
13
13
 
14
14
  The third failure is duplication. A front door that answers everything itself reimplements first-time detection and seed diffing inline, badly, beside the skills that already do both. The value of a router is that it stops at the handoff.
15
15
 
@@ -23,7 +23,7 @@ The last failure is a section no route reaches. `## Route` maps an intent or a d
23
23
 
24
24
  - Orient on the toolkit's own docs and the live catalogs before acting
25
25
  - Map the stated intent to one lifecycle phase, then either run the simplest command that satisfies it or hand off
26
- - Resolve every stack, rule, snippet, and standard name from a catalog at runtime
26
+ - Resolve every stack, rule, and standard name from a catalog at runtime
27
27
  - Run the CLI non-interactively and report the command run, what changed, and the full path of anything written
28
28
  - Read the overwrite contract from the body before any install or sync, and name each surface it lists as overwritten before running one
29
29
  - Read the reverse walk beside the forward sections, so a folder the toolkit stopped shipping reaches the user
@@ -14,9 +14,9 @@ Run these from the target project root, in parallel, before acting:
14
14
 
15
15
  - `canon docs list`: the index of toolkit reference docs
16
16
  - `canon docs agents`: the CLI command catalog and invocation contract
17
- - `canon docs target-projects`: the scaffold, add-a-domain, and sync lifecycle
17
+ - `canon docs projects`: the scaffold, add-a-domain, and sync lifecycle
18
18
 
19
- Load a domain doc with `canon docs <topic>` only when the intent touches that domain. Read the live catalog for any domain you act on with `canon <domain> list --json`. Never hardcode stack, rule, snippet, or standards names.
19
+ Load a domain doc with `canon docs <topic>` only when the intent touches that domain. Read the live catalog for any domain you act on with `canon <domain> list --json`. Never hardcode stack, rule, or standards names.
20
20
 
21
21
  ## Diagnose
22
22
 
@@ -50,7 +50,7 @@ The two can name different rows, and a reply answers both rather than picking on
50
50
  - Governance rules for the project stack: hand off to `target-setup`, which installs them alone on its `gov` phase
51
51
  - Bootstrap the `index.md` system: hand off to `target-setup`, which bootstraps it on its `indexes` phase
52
52
  - Seed or standards drift in `CLAUDE.md` or `.claude/` preambles: hand off to `seed-sync`
53
- - Install one snippet, standard, or rule: run the domain `install` command
53
+ - Install one rule: run the domain `install` command
54
54
  - Sync one domain or every installed domain: run `canon <domain> sync` or `canon sync`
55
55
  - Fix only the ignore entries of the installed stack: run `canon tooling inject --gitignore <stack>`
56
56
  - Measure a surface without changing it: offer the audits under `### Audits`
@@ -20,6 +20,7 @@ Sharpening the rules does not reach the decision. Both were loaded and neither w
20
20
  - State the split trigger as a second role entering a folder, with a file count only as a prompt to look
21
21
  - State colocation with the one consumer and promotion on the second, and imports flowing from shared toward features toward the app entry
22
22
  - Require a one-clause placement reason on every new path the plan names
23
+ - State that a file is named for what it covers inside its folder, never repeating the folder's name as its stem or its prefix, since a name placed beside its neighbor copies the neighbor's prefix along with its folder
23
24
  - Hold the stack-neutral core in the body and defer category specifics to a reference loaded only when a new path falls in that category
24
25
  - Record the external layouts adopted and declined with the reason for each, so a later session extends the position instead of re-deriving it
25
26
  - Fire on a direct question about placement as well, such as where a file goes or whether a flat folder should split, since a session outside any plan still places files
@@ -23,6 +23,12 @@ Skip it when every path the work names already exists.
23
23
  - Name a folder for what it holds for a reader, being a feature, a route, or a role, over its technical kind alone. `checkout/` tells a reader what is inside where `helpers/` does not.
24
24
  - Never create a bucket named `misc`, `common`, `utils`, or `helpers` on its own. Qualify it by what it serves, or place the file with its consumer.
25
25
 
26
+ ## Name a file for what it covers inside its folder
27
+
28
+ - Never repeat the folder's name as a file's whole stem or as its prefix. `billing/invoice.md` says what `billing/billing-invoice.md` says with one word fewer in every path that cites it.
29
+ - Drop the prefix when a file moves into a subfolder that now states it, and retarget every citation of the old path in the same change.
30
+ - Read the stem as the basename up to its first dot, so `checkout/checkout.test.ts` repeats its folder as much as `checkout/checkout.md` does.
31
+
26
32
  ## Split before the file lands
27
33
 
28
34
  - Split a folder when the new file brings a second role into it, before the file lands rather than in a later refactor. The split that touched 98 files would have touched a handful when the folder held eleven.
@@ -42,4 +42,4 @@ The subdir gets picked by feel, so a UI copy rule lands in the always-on folder
42
42
  - Editing a rule that already exists
43
43
  - Toolkit source rules, which are authored in the toolkit rather than in a target
44
44
  - Installing the rules the toolkit ships, which the governance setup path owns
45
- - A standard, which `create-standard` owns, and a snippet, which `create-snippet` owns
45
+ - A standard, which `create-standard` owns
@@ -24,12 +24,10 @@ A standard written and left there is the third. The index entry and the context
24
24
  ## Must not
25
25
 
26
26
  - Work the standard's shape or frontmatter from memory
27
- - Write a snippet, which carries no frontmatter and answers to a different authoring contract
28
27
  - Write into `.claude/standards/`, which no repository generates and no resolver reads
29
28
 
30
29
  ## Out of scope
31
30
 
32
31
  - Editing a standard that already exists
33
- - A snippet, which `create-snippet` owns
34
32
  - A path-scoped coding rule, which `create-rule` owns
35
33
  - Reading a standard the toolkit ships, which `canon standards <name>` owns
@@ -15,7 +15,7 @@ A body written around a named tool fails a third way. A session on a surface car
15
15
 
16
16
  The opposite failure is the one that ships silently. A session that takes a preference decision itself produces work the operator did not ask for and never learns a choice was made, because nothing in the output says a fork was passed.
17
17
 
18
- `CLAUDE.md` states both branches of the rule, sending an ordinary judgment call to a pick with the tradeoff in one sentence and a preference-deciding call to the operator. The first branch has the toolkit's `snippets/decision-help.md` behind it, which installs into a project that took snippets as `.claude/snippets/decision-help.md`. The second branch now states how a question is shaped and where it is put, so this skill inherits both and adds only what a batch needs on top of one question.
18
+ `CLAUDE.md` states both branches of the rule, sending an ordinary judgment call to a pick with the tradeoff in one sentence and a preference-deciding call to the operator. The second branch now states how a question is shaped and where it is put, so this skill inherits both and adds only what a batch needs on top of one question.
19
19
 
20
20
  ## Must
21
21
 
@@ -40,6 +40,5 @@ The opposite failure is the one that ships silently. A session that takes a pref
40
40
  ## Out of scope
41
41
 
42
42
  - Making the ordinary judgment call, which is a pick plus a one-sentence tradeoff and needs no surface
43
- - The chat-side pick with no repository behind it, which the toolkit's `snippets/decision-help.md` covers and reaches a different reader
44
43
  - Writing the decision into a plan, task, or architecture record, which each owning standard governs and this skill only routes to
45
44
  - Deciding when to fire. The skill is user-invoked through `disable-model-invocation`, so escalating is the operator's call rather than a description match.
@@ -34,4 +34,4 @@ Without this skill, a session documenting a domain that has no context entry yet
34
34
  - Refreshing an existing `canon/context/<domain>.md` entry against a diff: `context-fold`
35
35
  - Drafting a `canon/wireframes/<surface>.md` file: `draft-wireframes`
36
36
  - Drafting a `docs/*.md` page: `draft-docs`
37
- - Drafting a standard, a snippet, or a governance rule: `create-standard`, `create-snippet`, `create-rule`
37
+ - Drafting a standard or a governance rule: `create-standard`, `create-rule`
@@ -32,4 +32,4 @@ Without this skill, a session drafting documentation for a surface that has no p
32
32
 
33
33
  - Rewriting or syncing an existing `docs/*.md` section against a diff since main: `docs-sync`
34
34
  - The context entries, requirements, architecture, wireframes, and task board: `context-fold`
35
- - Drafting a standard, a snippet, or a governance rule: `create-standard`, `create-snippet`, `create-rule`
35
+ - Drafting a standard or a governance rule: `create-standard`, `create-rule`
@@ -34,5 +34,5 @@ Without this skill, a session drafting a wireframe for a surface with no file ye
34
34
  - Stubbing a surface a diff touched, or reporting drift in an existing wireframe against a diff: `claude/skills/context-fold/references/wireframe-sweep.md`
35
35
  - Drafting a `canon/context/<domain>.md` entry: `draft-context`
36
36
  - Drafting a `docs/*.md` page: `draft-docs`
37
- - Drafting a standard, a snippet, or a governance rule: `create-standard`, `create-snippet`, `create-rule`
37
+ - Drafting a standard or a governance rule: `create-standard`, `create-rule`
38
38
  - Building or wiring an actual tier-1 or tier-2 rendering pipeline: the visual design workflow's own tier guidance, out of reach of a hand-drafting skill
@@ -21,6 +21,8 @@ The verb resolves the board at the main worktree root in-process, adds `Pull req
21
21
 
22
22
  The correction reaches only a line that does not read as a list of `#NNN` entries. A line that does takes the new number appended rather than replaced, reported as `appended`, so a task shipped in slices keeps every pull request.
23
23
 
24
+ The same write drops this branch from the task's `Pending branch:` line, which `canon tasks outcome` wrote when the branch ticked an outcome, so this step is what lets the merge-time archive close the task.
25
+
24
26
  Skip this silently when the record is `ok: false` and `reason` is `no-board`, `no-match`, or `ambiguous`. Those are the three cases a guessed write would compound: no board, no task naming the plan, or more than one. One pull request names one task, and a wrong match archives the wrong task unattended once the branch merges. Report any other refusal rather than swallowing it.
25
27
 
26
28
  The number is what lets the merge close the task. Every merge on `main` is a squash carrying it in the subject, so the number survives where a branch name does not, and `post-merge` reads it back to call `canon tasks archive`. Writing it here rather than at worktree time is what makes it a pull request number rather than a branch the squash discards.
@@ -73,7 +73,7 @@ Two heading levels is the right depth. A third means the cluster should have bee
73
73
 
74
74
  Write every item in the standard's item format, in the cluster file its fix belongs to. Close each item with a verdict and an empty operator slot, and never fill that slot or read an empty one as agreement.
75
75
 
76
- Where an item's call is the operator's, pair it with a suggestion rather than a bare question. The toolkit's `decision-help` snippet writes the same shape for chat use, and the standard's item format is the whole spec.
76
+ Where an item's call is the operator's, pair it with a suggestion rather than a bare question. The standard's item format is the whole spec.
77
77
 
78
78
  ## Step 6: write the index
79
79
 
@@ -27,7 +27,7 @@ two copies could disagree with nothing comparing them.
27
27
 
28
28
  ## Must
29
29
 
30
- - Read the toolkit catalogs before resolving, and hardcode no stack, rule, or snippet name
30
+ - Read the toolkit catalogs before resolving, and hardcode no stack or rule name
31
31
  - Preview the resolved arguments and the exact commands before the first write
32
32
  - Mark a fallback resolution as a fallback in the preview, where it can still be declined
33
33
  - Run every phase without a TTY, and carry an argument for each prompt a phase would otherwise open
@@ -41,7 +41,7 @@ two copies could disagree with nothing comparing them.
41
41
  - Generate a config the tooling stack ships as a golden file
42
42
  - Install Claude Code plugins, which provision a machine rather than a project
43
43
  - Fail an unattended scaffold on a server start, which is flaky enough to be a depth the operator asks for
44
- - Survive as a skill nothing invokes but a person typing its name. `canon-operator` hands first-time scaffold here and the target-projects page names it as the scaffold step, so a later read finding no caller but the author has found a body that should have stayed a verb
44
+ - Survive as a skill nothing invokes but a person typing its name. `canon-operator` hands first-time scaffold here and the target projects page names it as the scaffold step, so a later read finding no caller but the author has found a body that should have stayed a verb
45
45
 
46
46
  ## Guards
47
47
 
@@ -10,7 +10,7 @@ arguments, previews the chain, runs `canon init`, then verifies what landed and
10
10
  bootstraps the `index.md` system over the project's own documentation folders.
11
11
 
12
12
  The CLI holds the install logic. This skill resolves, previews, and routes. It
13
- reimplements no verb and hardcodes no stack, rule, or snippet name.
13
+ reimplements no verb and hardcodes no stack or rule name.
14
14
 
15
15
  ## Phases
16
16
 
@@ -11,7 +11,7 @@ they install rather than in how they read the project.
11
11
 
12
12
  ## Read the catalogs
13
13
 
14
- Run in parallel. Never hardcode stack, rule, snippet, or standards names. The
14
+ Run in parallel. Never hardcode stack, rule, or standards names. The
15
15
  catalog is the source of truth.
16
16
 
17
17
  Run from the target project's current directory. Do not cd into the toolkit
@@ -21,13 +21,9 @@ before scanning.
21
21
  ## Scan
22
22
 
23
23
  Walk the project root for folders containing three or more sibling `*.md` files.
24
- Prune `.git`, `node_modules`, `.claude`, `snippets`, anything matched by
24
+ Prune `.git`, `node_modules`, `.claude`, anything matched by
25
25
  `.gitignore`, and any folder that already contains an `index.md`.
26
26
 
27
- Skip `.claude/snippets/`. Snippets are invoked by reference (`@snippet-name`)
28
- rather than browsed, so they need neither `index.md` nor per-file frontmatter.
29
- Adding them creates noise that targets keep reporting.
30
-
31
27
  For each candidate, capture:
32
28
 
33
29
  - Folder path relative to project root
@@ -42,6 +42,7 @@ Each reason has one resolution and none of them is to archive around it:
42
42
  - `open-outcomes`: the named outcomes are unmarked or genuinely open. Run `context-fold` when the work shipped and nothing marked it. Leave the task on the board when the outcome is real. When the work is being abandoned, cut it by striking the body, `- ~~<outcome>~~ <why>`, whatever the checkbox holds, so the board records what was dropped rather than meeting this refusal a second time.
43
43
  - `ambiguous`: two tasks name one pull request, which is the misfile `${CLAUDE_SKILL_DIR}/../../standards/tasks.md` rules out. Resolve the citation by hand, since no sweep repairs it.
44
44
  - `earlier-slice`: the number is listed on the task but is not the last, so a later slice is still to merge. Leave the task on the board. Its last slice's merge archives it.
45
+ - `pending-branch`: a branch named in `detail` ticked an outcome before its own pull request number was recorded. Leave the task live, since that branch's merge archives it once `git-pr` records the number. When the operator decides a named branch was abandoned, archive by stem, which is the one case for it.
45
46
  - `no-match`: the stem or number names nothing on the board. Check the name against the listed stems.
46
47
  - `bad-input`: the command line was wrong rather than the board. Read the message, fix the arguments, and run it again. Nothing on the board needs repair, which is what separates this from the two above.
47
48
 
@@ -20,7 +20,6 @@ One row per top-level command, in the order `canon --help` prints them. A domain
20
20
  | `canon targets <verb>` | Report the projects this toolkit installed into |
21
21
  | `canon gov <verb>` | Install and sync governance rules, and audit the tree against them |
22
22
  | `canon standards <verb>` | List, audit, or print a standard by name |
23
- | `canon snippets <verb>` | List or scaffold prompt snippets |
24
23
  | `canon tooling <verb>` | Sync, diff, and verify tooling stacks |
25
24
  | `canon claude <verb>` | Install the Claude workflow and audit both skill corpora |
26
25
  | `canon wiki <verb>` | Scaffold the wiki pages |
@@ -61,7 +60,7 @@ A port already in use is the ordinary case rather than a refusal, so it walks fo
61
60
 
62
61
  A request naming a directory is redirected to its trailing-slash form rather than answered in place. A browser resolves a relative asset against the last slash of the URL it is on, so answering `/lesson` directly leaves the page asking for `/course.css` instead of `/lesson/course.css`, and it renders unstyled through the server that exists to prevent exactly that.
63
62
 
64
- Containment is tested after symlinks are followed rather than on the path as written, and the test sits immediately before the read rather than beside the request that produced it. Resolving a request lexically clears a link pointing outside the served root, and this repository is a live instance of that shape, since `claude/standards` and `claude/snippets` are links out of `claude/`. Position is what makes the property hold: a directory request appends its index after the request path has been checked, so a check placed earlier leaves that index untested. `--index` answers a directory holding no `index.html` with a listing read per request, where the default stays a 404. Every entry the listing names takes the same containment test a request for it would, so a link out of the root is absent rather than greyed, and dotfiles are hidden. With no `--entry` and no root `index.html`, the printed link is `/` and `entryExists` reads true. An `--entry` that escapes the root refuses with `no-entry` before a port is taken, because `url` is the field a caller hands to a reader.
63
+ Containment is tested after symlinks are followed rather than on the path as written, and the test sits immediately before the read rather than beside the request that produced it. Resolving a request lexically clears a link pointing outside the served root, and this repository is a live instance of that shape, since `claude/standards` is a link out of `claude/`. Position is what makes the property hold: a directory request appends its index after the request path has been checked, so a check placed earlier leaves that index untested. `--index` answers a directory holding no `index.html` with a listing read per request, where the default stays a 404. Every entry the listing names takes the same containment test a request for it would, so a link out of the root is absent rather than greyed, and dotfiles are hidden. With no `--entry` and no root `index.html`, the printed link is `/` and `entryExists` reads true. An `--entry` that escapes the root refuses with `no-entry` before a port is taken, because `url` is the field a caller hands to a reader.
65
64
 
66
65
  `canon demo` is the second browser command and the one that ships, since its purpose is running in a target rather than regenerating what this repository commits. It needs a browser binary the package does not carry, installed once with `bunx playwright install chromium`.
67
66
 
@@ -85,7 +84,6 @@ Each domain exposes a consistent shape where applicable: `list`, `install`, `syn
85
84
  - `targets`, in `targets.md`: `list`, `pulls`
86
85
  - `gov`, in `install-and-sync.md`: `list`, `install`, `sync`, `build`, `regen`, `test-order`, `counts`, `superseded`, `citations`, `restated`
87
86
  - `standards`, in `standards-audit.md`: `list`, `audit`, `<name>`
88
- - `snippets`, in `install-and-sync.md`: `list`, `create`
89
87
  - `tooling`, in `install-and-sync.md`: `list`, `sync`, `diff`, `reference`, `create`, `verify`, `inject`, `prune-gitignore`
90
88
  - `claude`, in `skills-audit.md`: `init`, `sync`, `setup`, `routing`, `plugin-update`, `seeds list`, `skills list`, `skills audit`, `skills drift`, `skills reach`, `skills rank`
91
89
  - `wiki`, in `scripting.md`: `init`
@@ -22,12 +22,11 @@ Under `--json` the record holds stdout alone and the frame still renders on stde
22
22
 
23
23
  ## The catalogs it reads
24
24
 
25
- A closed set of six, each with a filesystem reader behind it rather than every list command this CLI ships:
25
+ A closed set of five, each with a filesystem reader behind it rather than every list command this CLI ships:
26
26
 
27
27
  - `skills`: shipped plugin skills, a folder per `claude/skills/*/SKILL.md`
28
28
  - `rules`: authored governance rules, a file per `governance/rules/**/*.md`
29
29
  - `standards`: the authoring corpus at `standards/`
30
- - `snippets`: distinct entries across every `snippets/` category, matching what `regen-hero.sh` counts
31
30
  - `commands`: top-level `canon` commands, read off `src/cli.ts`'s registration imports
32
31
  - `audits`: the registered set in `src/audits/catalog.ts`, this entry included
33
32
 
@@ -16,7 +16,7 @@ A domain too large for one file splits into `<domain>/` with a generated `index.
16
16
 
17
17
  A sub-area file resolves by its bare name too, so `canon docs operating-model` reaches `docs/workflow/operating-model.md`. Three spellings are tried in order, being a sibling file, a folder of that name, then a sub-area file one level down, and each spelling is tried across both roots before the next one runs. A sibling file therefore wins over a folder of the same name, and both win over a sub-area file. Reading the folder last is what keeps the sub-area spelling from changing any name that resolved before it existed.
18
18
 
19
- A bare name carried by two folders resolves to neither. Eight context folders hold an `overview.md`, so `canon docs overview` names the available topics and exits 1 rather than answering with whichever folder sorts first.
19
+ The sub-area spelling keeps the root order too. The first root whose folders carry the name answers, so `canon docs indexes` reaches `docs/agents/indexes.md` even though a context folder holds an entry of the same name. A bare name carried by two folders of that one root resolves to neither, which names the available topics and exits 1 rather than answering with whichever folder sorts first.
20
20
 
21
21
  `canon docs list` stops at the folder where `canon docs <topic>` goes on to name each file inside it. The listing is the downstream catalog rather than the index of what a name reaches, so a sub-area file appears there only where it declares a target-facing `category` of its own, and no sub-area file of the context root appears at all. A name that resolves and does not list is the divergence the toolkit-internal topics already carry.
22
22
 
@@ -61,10 +61,12 @@ root reports zero entries for that domain and reads as clean, which is the most
61
61
  misleading state the report can produce.
62
62
 
63
63
  The field currently names no domain. Standards and snippets are the two the
64
- toolkit ever installed at a project root, and both closed their install channel,
65
- so a project still holding a root `standards/` or `snippets/` folder is carrying
66
- its own authoring surface rather than an unfinished install. Nothing proposes
67
- moving either, and no command relocates the content. Move it yourself.
64
+ toolkit ever installed at a project root. Standards closed its install channel
65
+ and snippets retired outright, so a project still holding a root `standards/`
66
+ folder is carrying its own authoring surface rather than an unfinished install.
67
+ Nothing proposes moving it, and no command relocates the content. Move it
68
+ yourself. A leftover `snippets/` folder reports under the reverse walk instead,
69
+ where `docs/target/sync.md` says what to do with it.
68
70
 
69
71
  ## Rules the target never received
70
72
 
@@ -42,7 +42,7 @@ CLI catalog and invocation rules for agents, split by command domain. Start with
42
42
  - [Records stale](records-stale.md): Reading the memory pen as a review queue, what makes an entry due, how a cited path is read and resolved, the order entries come back in, and the exit codes and refusals
43
43
  - [Records validate](records-validate.md): Validating the session records and the standards corpus, the per-kind checks, which root each kind defaults to, the exit codes, and the refusal reasons
44
44
  - [Records](records.md): The two roots a record folder resolves at, migrating a record a frontmatter change orphaned, claiming the ordinal intake and groundwork share, reading each folder's size and growth, pruning stale scratch, and where validation, the memory review queue, and the private-remote backup are described
45
- - [Restated instructions](restated.md): Counting the instructions the always-loaded file and every path-scoped rule share with the seed, the shipped skill bodies, and each other, how a match is decided, the three classes, which surface a later edit starts from, and why the sweep reports rather than gates
45
+ - [Restated instructions](restated.md): Counting the instructions the always-loaded file and every path-scoped rule share with the seed, the skill bodies, and each other, how a match is decided, the three classes, which surface a later edit starts from, and why the sweep reports rather than gates
46
46
  - [Review classification](review-classification.md): Deciding whether a changed set needs the review pass, the two tests it runs, why an empty set refuses rather than skipping, and the written fallback a target on an older binary falls back to
47
47
  - [Routing report](routing.md): Reading per CLAUDE.md section how many bullets name a path, what counts as naming one, when a rule counts as covering it, the two refusals, and why the verb reports rather than gates
48
48
  - [Rule citations](rule-citations.md): 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
@@ -48,4 +48,4 @@ Exit codes: `0` no errors, `1` root not a directory, or a folder failed frontmat
48
48
 
49
49
  A git-ignored indexed folder, such as `.canon/tasks/` or `.canon/memory/`, never appears in the output. `listIndexes` filters candidates through `git check-ignore` the same way `regen`'s whole-repo walk does, which is the right default for a documentation lookup since those rows are session scratch, but it is a gap against `regen`'s positional-path mode, which bypasses that filter for those two folders.
50
50
 
51
- For the system rationale, frontmatter contract, when to adopt, and bootstrap path, see `canon/context/indexes.md`.
51
+ For the system rationale, frontmatter contract, when to adopt, and bootstrap path, see `canon/context/context-model/indexes.md`.
@@ -76,12 +76,6 @@ installs into no project, so the domain has nothing in a target to reconcile.
76
76
  and then the corpus inside the package, and `canon standards list --json` carries
77
77
  the catalog.
78
78
 
79
- There is no `canon snippets sync` and no `canon snippets install` either, on the
80
- same ground: `claude/snippets` in the plugin cache symlinks live to the
81
- toolkit's own `snippets/`, so a session reaches one at its `@` reference with
82
- no copy to reconcile. `canon snippets list --json` carries the catalog and
83
- `canon snippets create` is the one verb left that still writes a file.
84
-
85
79
  ## Tooling diff and sync
86
80
 
87
81
  `canon tooling diff <stack> [target]` is the read-only comparison, and a session asking what differs reaches for it by default. It writes nothing and exits 1 when anything differs and 0 when nothing does, so it gates CI. `--json` adds the scan record on stdout with `ok: true`, and the frame goes to stderr. A refusal such as an unknown stack, an excluded stack, or a toolkit-root target still exits 1 and answers `{ ok: false, reason, message }`, so a caller branches on the record and reads a typo'd stack name as a refusal rather than as drift.
@@ -244,8 +238,7 @@ still prompts. `--skip` takes `wiki`, `governance`, and `records`, and warns
244
238
  without aborting on any other value. Records has nothing to run non-interactively,
245
239
  since the private backup repository does not exist yet at scaffold time, so its
246
240
  step only prints the one-time setup reminder and `--skip records` silences it.
247
- There is no `--standards` and no `--snippets`, since no run writes either corpus
248
- into the target.
241
+ There is no `--standards`, since no run writes that corpus into the target.
249
242
 
250
243
  ## Unguarded tooling primitives
251
244
 
@@ -5,14 +5,14 @@ description: Running the audit over any markdown path, where its bans and checkp
5
5
 
6
6
  # Markdown audit
7
7
 
8
- `canon markdown audit [path...]` reports any markdown file against the attribute standard `markdown.md`. An attribute standard governs a file rather than a folder, so this resolves no folder and requires no `index.md`, which is what puts `.claude/rules/`, `governance/`, and `snippets/` in reach. Folder-shaped findings stay in `canon context audit`, described in `context-audit.md`.
8
+ `canon markdown audit [path...]` reports any markdown file against the attribute standard `markdown.md`. An attribute standard governs a file rather than a folder, so this resolves no folder and requires no `index.md`, which is what puts `.claude/rules/` and `governance/` in reach. Folder-shaped findings stay in `canon context audit`, described in `context-audit.md`.
9
9
 
10
10
  ```bash
11
11
  canon markdown audit
12
12
  canon markdown audit --json
13
13
  canon markdown audit .claude/rules governance
14
14
  canon markdown audit docs/agents/commands.md
15
- canon markdown audit 'snippets/**/*.md'
15
+ canon markdown audit 'standards/**/*.md'
16
16
  ```
17
17
 
18
18
  | Option | Behavior |
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Restated instructions
3
- description: Counting the instructions the always-loaded file and every path-scoped rule share with the seed, the shipped skill bodies, and each other, how a match is decided, the three classes, which surface a later edit starts from, and why the sweep reports rather than gates
3
+ description: Counting the instructions the always-loaded file and every path-scoped rule share with the seed, the skill bodies, and each other, how a match is decided, the three classes, which surface a later edit starts from, and why the sweep reports rather than gates
4
4
  ---
5
5
 
6
6
  # Restated instructions
@@ -25,10 +25,10 @@ Under `--json` the record holds stdout alone and the frame still renders on stde
25
25
  Four surfaces, and they are not read symmetrically. Every top-level bullet in `CLAUDE.md` and in every path-scoped rule is a subject, and every surface below is searched, rules included a second time:
26
26
 
27
27
  - `tooling/claude/seeds/CLAUDE.md`, read as bullets, since the seed carries the same shape as the file it is authored from
28
- - `claude/skills/*/SKILL.md`, read as every prose line and bullet, since the motivating case was stated in a body as a paragraph rather than a list item
29
- - `governance/rules/**/*.md`, the authoring root rather than the consumed copy under `.claude/rules/`, read as bullets the same way the seed is
28
+ - `claude/skills/*/SKILL.md` and `.claude/skills/*/SKILL.md`, read as every prose line and bullet, since the motivating case was stated in a body as a paragraph rather than a list item. The second root holds the project's own skills, which are equally a place a rule gets restated
29
+ - `governance/rules/**/*.md` and `internal/rules/**/*.md`, the authoring roots rather than the consumed copy under `.claude/rules/`, read as bullets the same way the seed is. Each record's `file` carries the root it was read from
30
30
 
31
- A rule reads as both a subject and a candidate, unlike the seed and the shipped bodies. A stack ships a whole rule folder, so a bullet duplicated between two rules reaches a target exactly as a bullet duplicated between the always-loaded file and a rule does, and neither shape is visible from one side alone. A candidate sharing its subject's file is skipped, since two bullets inside one rule sharing anchors are adjacent instructions on one topic rather than the same rule shipped twice, and a pair found from one direction is not reported again from the other.
31
+ A rule reads as both a subject and a candidate, unlike the seed and the skill bodies. A stack ships a whole rule folder, so a bullet duplicated between two rules reaches a target exactly as a bullet duplicated between the always-loaded file and a rule does, and neither shape is visible from one side alone. A candidate sharing its subject's file is skipped, since two bullets inside one rule sharing anchors are adjacent instructions on one topic rather than the same rule shipped twice, and a pair found from one direction is not reported again from the other.
32
32
 
33
33
  Frontmatter, headings, tables, and fenced blocks are read past. A heading names a section instead of stating a rule, a fenced block is an example whose words belong to the prose around it, and a body's `description` restates that skill's own purpose, so sweeping it would match every subject naming its domain.
34
34
 
@@ -58,6 +58,8 @@ Polarity is read off the clause the anchors landed in, and off the densest such
58
58
 
59
59
  The marker also has to open its clause, because an instruction leads with its verb. `Never delete a task file` prohibits where `a fallback never fires` reports, and no test reading the marker anywhere in the clause tells those apart. What that costs is a prohibition written mid-clause, which now reads as description and lands the pair in the repetition class, so both surfaces still reach the report and only the label is weaker.
60
60
 
61
+ One mid-clause shape still counts. A `no` opening a clause or a comma-set phrase directly on a code span prohibits, as in `pinned to major tags, no` followed by the pinned tag, since sitting on an identifier it names what is ruled out. The phrase boundary keeps description out: `returns no` then a code span puts the marker after a verb and reports what happens. `not` and `never` in the same position are left out, because admitting them turned agreeing pairs into false contradictions.
62
+
61
63
  A mirror that disagrees stays a finding. The exclusion reaches a repetition alone, because the two files on a declared pair are meant to agree.
62
64
 
63
65
  ## Which surface is authoritative
@@ -76,6 +78,6 @@ Exit codes are `0` when no instruction is restated outside a declared mirror, `1
76
78
 
77
79
  Nothing wires this into `bun run check` or into a hook. A restatement is legitimate more often than not, and gating a measure whose ordinary result is a finding is what teaches contributors to route around the stage. `canon gov test-order` and `canon labels audit` are the siblings.
78
80
 
79
- Both refusals are absences rather than breaks. A target holds none of the seed, a shipped skills tree, or a rules tree, so `canon audits run` reads `no-instructions` and `no-surfaces` as a corpus that is not there rather than a verb that failed.
81
+ Both refusals are absences rather than breaks. A target may hold none of the seed, a skills tree, or a rules tree, so `canon audits run` reads `no-instructions` and `no-surfaces` as a corpus that is not there rather than a verb that failed.
80
82
 
81
83
  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 `counts` rather than the exit when a skill consumes this.
@@ -40,11 +40,10 @@ Most carry two spellings, the one a surface authors at and the one it reaches a
40
40
  | Plugin skills | `claude/skills/`, `.claude/skills/` |
41
41
  | Governance rules | `governance/rules/`, `.claude/rules/` |
42
42
  | Standards | `standards/` |
43
- | Snippets | `snippets/` |
44
43
  | Internal and seed | `internal/`, `tooling/` |
45
44
  | Root instructions | `CLAUDE.md` |
46
45
 
47
- `standards/` and `snippets/` carry one spelling apiece. Neither installs into a project, reaching a reader by resolution and through the `claude/snippets` symlink respectively, so there is no consumed copy to name.
46
+ `standards/` carries one spelling. It never installs into a project, reaching a reader by resolution, so there is no consumed copy to name.
48
47
 
49
48
  `CLAUDE.md` is matched as a whole path rather than as a prefix, because a prefix reaches nothing that sits in no folder. A nested `docs/CLAUDE.md` stays informational.
50
49
 
@@ -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 snippets list --json` | Presets and categories with their slugs |
18
17
  | `canon standards list --json` | Standards docs and the paths each governs |
19
18
  | `canon gov list --json` | Governance stacks, rule sets, and unreferenced rules |
20
19
  | `canon claude seeds list --json` | Seed doc sources with content |
@@ -25,8 +24,8 @@ Use these to discover what's available instead of hardcoding names.
25
24
  ### Catalog fields
26
25
 
27
26
  Every catalog serializes through `JSON.stringify`, so a name carrying a quote
28
- emits valid JSON. `canon tooling list` and `canon snippets list` previously built
29
- their output with `printf` and no escaping.
27
+ emits valid JSON. `canon tooling list` previously built
28
+ its output with `printf` and no escaping.
30
29
 
31
30
  `canon standards list` carries `appliesTo` per standard, the paths that standard's
32
31
  `## Scope` statement declares. It holds the backticked paths from the first
@@ -23,7 +23,7 @@ canon claude skills reach ~/repos/my-project
23
23
 
24
24
  ## The defect it reads for
25
25
 
26
- A plugin skill installs into a project and the toolkit's own tree is not there. A body naming `canon/context/transcripts.md` resolves for a session running in this repository and sends every other reader to nothing, and no stage asked the question until this one. The shape is wider than one folder: a seed naming a standard with no route and a machine-readable field naming a toolkit-only path are the same claim, true here and false in a target.
26
+ A plugin skill installs into a project and the toolkit's own tree is not there. A body naming `canon/context/features/transcripts.md` resolves for a session running in this repository and sends every other reader to nothing, and no stage asked the question until this one. The shape is wider than one folder: a seed naming a standard with no route and a machine-readable field naming a toolkit-only path are the same claim, true here and false in a target.
27
27
 
28
28
  ## What counts as a citation
29
29
 
@@ -39,7 +39,7 @@ A path the toolkit does not hold is dropped rather than reported. The measure as
39
39
 
40
40
  ## The ownership key
41
41
 
42
- A cited path counts when it sits under an authoring root no install channel delivers. Standards and snippets install nowhere and are read through the plugin corpus, governance rules install under `.claude/rules/`, and the rest is this repository's own source, catalogs, and contract pages.
42
+ A cited path counts when it sits under an authoring root no install channel delivers. Standards install nowhere and are read through the plugin corpus, governance rules install under `.claude/rules/`, and the rest is this repository's own source, catalogs, and contract pages.
43
43
 
44
44
  `src/`, `scripts/`, and bare `docs/` are deliberately outside the list. A body naming one of those is describing the reader's own tree, so listing them reports a correct citation on every run and buries the finding under the pass.
45
45
 
@@ -52,7 +52,7 @@ A path a seed installs is disowned twice, under its own name and under the folde
52
52
  A correct citation and a defective one are the same string, and the sentence around it is the difference. A citation counts as decided when its line names the toolkit as the owner, matching the bodies that already spell it that way. The repair for a finding is to say whose copy the path is, never to delete the citation, since the paths name real documents a reader wants.
53
53
 
54
54
  ```markdown
55
- Read `canon/context/indexes.md` from the toolkit if context on the system is needed.
55
+ Read `canon/context/context-model/indexes.md` from the toolkit if context on the system is needed.
56
56
  ```
57
57
 
58
58
  A line mentioning the toolkit for an unrelated reason exempts a citation on it. That is the accepted cost of a word over a notation every future body would have to learn.
@@ -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 sandbox tree, 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.
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` and `snippets` symlinks resolve into trees the field lists in their 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, and its `standards` symlink resolves into a tree the field lists in its own right, 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
 
@@ -22,7 +22,7 @@ canon tasks archive --pull-request 673 --json
22
22
  | `--json` | Emit a machine-readable record on stdout |
23
23
  | `--root <path>` | Board root, defaulting to the main worktree |
24
24
 
25
- Exit codes: `0` archived, `1` refused. Every gate is a refusal rather than a warning, because `.husky/post-merge` calls this with nobody watching. The `reason` field carries which gate fired: `no-board`, `no-match`, `ambiguous`, `no-outcomes`, `open-outcomes`, `earlier-slice`, or `bad-input`. `earlier-slice` fires when `--pull-request` names a number that is not the last on the task's `Pull request:` line, since outcomes are ticked at ship time and only the last slice's merge closes the task.
25
+ Exit codes: `0` archived, `1` refused. Every gate is a refusal rather than a warning, because `.husky/post-merge` calls this with nobody watching. The `reason` field carries which gate fired: `no-board`, `no-match`, `ambiguous`, `no-outcomes`, `open-outcomes`, `earlier-slice`, `pending-branch`, or `bad-input`. `earlier-slice` fires when `--pull-request` names a number that is not the last on the task's `Pull request:` line, since outcomes are ticked at ship time and only the last slice's merge closes the task. `pending-branch` fires when `--pull-request` meets a `Pending branch:` line, since a branch that ticked an outcome before `git-pr` recorded its number means the last number listed is not yet the last slice. The `detail` array names each pending branch. Selecting by stem skips both checks.
26
26
 
27
27
  An outcome whose body is struck reads as cut rather than open or closed, whatever its checkbox holds: `- ~~<outcome>~~ <why>`. A task carrying only cut outcomes archives, since the gate refuses `no-outcomes` only when both the closed and the cut counts are zero. The success record carries `closed` and `cut` as counts, so a reader tells a shipped task from an abandoned one without opening the file.
28
28