@erclx/canon 4.123.0 → 4.124.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 (92) hide show
  1. package/claude/.claude-plugin/plugin.json +1 -1
  2. package/claude/skills/auto-ship/SKILL.md +2 -4
  3. package/claude/skills/codebase-layout/REQUIREMENT.md +1 -1
  4. package/claude/skills/codebase-layout/SKILL.md +1 -1
  5. package/claude/skills/create-rule/SKILL.md +5 -2
  6. package/claude/skills/design-taste/SKILL.md +1 -1
  7. package/claude/skills/draft-ready/REQUIREMENT.md +1 -1
  8. package/claude/skills/memory-review/SKILL.md +1 -1
  9. package/claude/skills/memory-review/references/later-phases.md +1 -1
  10. package/claude/skills/memory-review/references/receipt-format.md +1 -1
  11. package/claude/skills/test-first/REQUIREMENT.md +1 -1
  12. package/docs/agents/counts.md +3 -3
  13. package/docs/agents/drift-surfaces.md +2 -2
  14. package/docs/agents/rule-citations.md +4 -4
  15. package/docs/agents/test-order.md +1 -1
  16. package/docs/index.md +3 -0
  17. package/docs/target-migrations.md +93 -0
  18. package/docs/target-projects.md +4 -216
  19. package/docs/target-scenarios.md +56 -0
  20. package/docs/target-sync.md +93 -0
  21. package/docs/workflow/ai-workflow.md +2 -201
  22. package/docs/workflow/index.md +2 -0
  23. package/docs/workflow/operating-model.md +17 -46
  24. package/docs/workflow/parallel-features.md +77 -0
  25. package/docs/workflow/skill-map.md +148 -0
  26. package/governance/renames.toml +34 -0
  27. package/governance/rules/{claude/560-diagrams.md → canon/660-diagrams.md} +1 -1
  28. package/governance/rules/{claude/562-session.md → canon/662-session.md} +1 -1
  29. package/governance/rules/code/000-code.md +21 -0
  30. package/governance/rules/lib/300-testing-ts.md +0 -4
  31. package/governance/rules/lib/330-testing-py.md +0 -4
  32. package/governance/rules/{claude/500-prose.md → writing/800-prose.md} +1 -1
  33. package/governance/rules/{claude/501-markdown.md → writing/801-markdown.md} +1 -1
  34. package/governance/rules/{claude/502-mermaid.md → writing/802-mermaid.md} +1 -1
  35. package/governance/stacks/base.toml +7 -6
  36. package/governance/stacks/node.toml +1 -1
  37. package/governance/stacks/python.toml +1 -1
  38. package/package.json +1 -1
  39. package/scripts/core/install-check.sh +3 -5
  40. package/src/claude/routing.ts +1 -1
  41. package/src/commands/gov.ts +1 -1
  42. package/src/gate/measures.ts +1 -6
  43. package/src/gov/citations.ts +1 -1
  44. package/src/gov/list.ts +1 -1
  45. package/src/gov/restated.ts +2 -2
  46. package/src/init/steps.ts +1 -1
  47. package/src/labels/spelling.ts +1 -1
  48. package/src/records/prune.ts +1 -1
  49. package/src/shipped/references.ts +1 -1
  50. package/standards/rule.md +4 -6
  51. package/tooling/base/reference.md +1 -1
  52. package/tooling/claude/seeds/.claude/hooks/path-form.sh +1 -1
  53. package/tooling/claude/seeds/.claude/hooks/scratch-guard.sh +1 -1
  54. package/tooling/web/reference.md +1 -1
  55. package/governance/rules/core/000-constitution.md +0 -30
  56. package/governance/rules/core/020-concurrency.md +0 -22
  57. package/governance/rules/core/030-error-handling.md +0 -31
  58. package/governance/rules/core/040-performance.md +0 -20
  59. package/governance/rules/core/050-logging.md +0 -20
  60. package/governance/rules/core/060-naming.md +0 -19
  61. package/governance/rules/snippets/600-at-references.md +0 -9
  62. /package/governance/rules/{core/025-indexes.md → canon/601-indexes.md} +0 -0
  63. /package/governance/rules/{core/035-tasks.md → canon/602-tasks.md} +0 -0
  64. /package/governance/rules/{core/045-memory.md → canon/603-memory.md} +0 -0
  65. /package/governance/rules/{core/055-scratch.md → canon/604-scratch.md} +0 -0
  66. /package/governance/rules/{core/085-worktrees.md → canon/605-worktrees.md} +0 -0
  67. /package/governance/rules/{core/087-git.md → canon/606-git.md} +0 -0
  68. /package/governance/rules/{claude/510-context.md → canon/610-context.md} +0 -0
  69. /package/governance/rules/{claude/511-indexes.md → canon/611-indexes.md} +0 -0
  70. /package/governance/rules/{claude/520-wireframes.md → canon/620-wireframes.md} +0 -0
  71. /package/governance/rules/{claude/530-requirements.md → canon/630-requirements.md} +0 -0
  72. /package/governance/rules/{claude/540-architecture.md → canon/640-architecture.md} +0 -0
  73. /package/governance/rules/{claude/545-decisions.md → canon/645-decisions.md} +0 -0
  74. /package/governance/rules/{claude/550-design.md → canon/650-design.md} +0 -0
  75. /package/governance/rules/{claude/555-tasks.md → canon/655-tasks.md} +0 -0
  76. /package/governance/rules/{claude/556-groundwork.md → canon/656-groundwork.md} +0 -0
  77. /package/governance/rules/{claude/557-intake.md → canon/657-intake.md} +0 -0
  78. /package/governance/rules/{claude/558-plan.md → canon/658-plan.md} +0 -0
  79. /package/governance/rules/{claude/559-memory.md → canon/659-memory.md} +0 -0
  80. /package/governance/rules/{claude/561-teach.md → canon/661-teach.md} +0 -0
  81. /package/governance/rules/{claude/563-ready.md → canon/663-ready.md} +0 -0
  82. /package/governance/rules/{core/005-behavior.md → claude/565-behavior.md} +0 -0
  83. /package/governance/rules/{core/015-output.md → claude/566-output.md} +0 -0
  84. /package/governance/rules/{core/070-planning.md → claude/567-planning.md} +0 -0
  85. /package/governance/rules/{core → code}/010-testing.md +0 -0
  86. /package/governance/rules/{ci → tooling}/700-ci-workflow.md +0 -0
  87. /package/governance/rules/{core/065-spelling.md → tooling/765-spelling.md} +0 -0
  88. /package/governance/rules/{core/075-dependencies.md → tooling/775-dependencies.md} +0 -0
  89. /package/governance/rules/{core/080-config-comments.md → tooling/780-config-comments.md} +0 -0
  90. /package/governance/rules/{core/090-code-comments.md → tooling/790-code-comments.md} +0 -0
  91. /package/governance/rules/{claude/580-readme.md → writing/880-readme.md} +0 -0
  92. /package/governance/rules/{claude/591-standard-authoring.md → writing/891-standard-authoring.md} +0 -0
@@ -0,0 +1,148 @@
1
+ ---
2
+ title: Skill map
3
+ description: When to reach for each plugin skill, grouped by the moment a project meets it
4
+ category: Workflow
5
+ ---
6
+
7
+ # Skill map
8
+
9
+ Groups run in the order a project meets them, so a reader at a known point scans to that group and reads across. The set reconciles the scenarios in [AI workflow](ai-workflow.md) with the lifecycle [target projects](../target-projects.md) describes, rather than inventing a third vocabulary beside those two, so a group name matches neither source exactly and every moment either one names has a group. Each row says when to reach for the skill. What it does is the skill's own description.
10
+
11
+ This page is the corpus the coverage claim is measured against: every name `canon claude skills list --names` reports takes exactly one row here. A skill serving two moments sits at the earlier one, and a mention on any other page is prose rather than routing.
12
+
13
+ ## Set up a project
14
+
15
+ | Skill | When to use |
16
+ | ---------------------- | ------------------------------------------------------------------------------------------------------ |
17
+ | `canon:target-setup` | On a fresh scaffold, to detect the stack and run the install chain, or to reach one phase of it alone |
18
+ | `canon:canon-operator` | On a project that already exists, to read what it carries before an install is picked |
19
+ | `canon:sketch-design` | Before `design-extract`'s greenfield path, to trace a design direction from reference images or URLs |
20
+ | `canon:design-extract` | Before the first UI feature, to draft `canon/DESIGN.md` |
21
+ | `canon:draft-diagram` | Once the architecture is written, to draft per-kind entries under `.canon/diagrams/` |
22
+ | `canon:repo-metadata` | When the GitHub About text, homepage, or topics may have drifted, to reconcile them against the README |
23
+
24
+ ## Decide what to build
25
+
26
+ | Skill | When to use |
27
+ | -------------------------- | --------------------------------------------------------------------------------- |
28
+ | `canon:plan-intake` | When the input is a pile of findings rather than one feature |
29
+ | `canon:plan-intake-answer` | When an intake folder holds unread slots waiting on your decision |
30
+ | `canon:backlog-triage` | When the backlog needs pruning, to file a verdict per row and apply approved ones |
31
+ | `canon:plan-groundwork` | When the state is unmeasured and more than one approach is live |
32
+ | `canon:decision-escalate` | When open decisions turn on your preference and want batching into one set |
33
+ | `canon:draft-and-pick` | When the call is taste and wants several candidates rendered side by side |
34
+ | `canon:task-board` | When a decided item needs a file on the board, or a shipped one needs archiving |
35
+ | `canon:plan-feature` | When the approach is settled and the next step is a plan |
36
+ | `canon:codebase-layout` | When a plan or change adds a file and you need to decide which folder holds it |
37
+
38
+ ## Build the feature
39
+
40
+ | Skill | When to use |
41
+ | ---------------------------- | ---------------------------------------------------------------------------------------------------------- |
42
+ | `canon:session-worktree` | At the plan-to-execute boundary, to get an isolated tree and branch, or to route a refused main-root write |
43
+ | `canon:auto-ship` | After plan approval, to chain implement, verify, review, draft PR |
44
+ | `canon:project-commands` | When the project's own command needs running |
45
+ | `canon:test-first` | Before implementing a planned change, to run its test red, green, then refactor |
46
+ | `canon:test-craft` | When writing or changing any test, to pick its layer and filter what it asserts |
47
+ | `canon:review-craft` | When reviewing a change, for what to look for and how much evidence a finding needs |
48
+ | `canon:systematic-debugging` | When a test fails or a bug surfaces, to force root cause first |
49
+ | `canon:ui-checklist` | After a UI change, to write what to look at and name what ships untested |
50
+
51
+ ## Check the work before it leaves the branch
52
+
53
+ | Skill | When to use |
54
+ | ------------------------ | --------------------------------------------------------------------------------------- |
55
+ | `canon:review-branch` | On the local branch diff, before anything is pushed |
56
+ | `canon:standards-audit` | When changed markdown has to answer to the authoring standards |
57
+ | `canon:document-health` | When the documents themselves have to answer for length, placement, and staleness |
58
+ | `canon:markdown-propose` | When a markdown claim needs rewriting and the change should wait for an answer per file |
59
+ | `canon:ux-audit` | To read UI source for missing states, edge cases, and inconsistencies |
60
+ | `canon:ux-measure` | To start the interface and measure paint, processor, and layout cost |
61
+ | `canon:ux-walkthrough` | To run a multi-finding inspection pass over a running app with the operator |
62
+
63
+ ## Ship it
64
+
65
+ | Skill | When to use |
66
+ | ---------------------- | ------------------------------------------------------------------------------------------------- |
67
+ | `canon:git-ship` | To run the whole post-feature chain from the verify gate through open PR |
68
+ | `canon:memory-capture` | First skill in that chain, to route what the session learned to the surface owning it |
69
+ | `canon:context-fold` | When decisions diverged from the plan, or a shipped task needs its outcomes marked |
70
+ | `canon:docs-fold` | Never on purpose. A pointer at the old name that names `context-fold` <!-- canon-keep-retired --> |
71
+ | `canon:docs-sync` | When a change since main left `README.md` or `docs/` stale |
72
+ | `canon:git-stage` | When the staged set spans several concerns and wants one commit each |
73
+ | `canon:git-commit` | When the staged set is one concern, or was staged hunk by hand |
74
+ | `canon:git-branch` | When a branch name needs generating or renaming to conventional form |
75
+ | `canon:git-pr` | When a pull request needs a title and body written from the diff |
76
+ | `canon:memory-review` | When the pen has grown, to propose where each entry belongs |
77
+
78
+ ## After the pull request opens
79
+
80
+ | Skill | When to use |
81
+ | ---------------------- | -------------------------------------------------------------------- |
82
+ | `canon:review-pr` | From an independent session, to post findings on the PR itself |
83
+ | `canon:review-address` | On the worker's side, to fix posted findings and push a follow-up |
84
+ | `canon:git-followup` | For a small self-review edit on a branch whose PR is already open |
85
+ | `canon:git-split` | When a branch turns out to carry unrelated commits |
86
+ | `canon:git-issue` | When something surfaced that belongs on the tracker rather than here |
87
+ | `canon:git-worktree` | After a PR merges, to list worktrees and reclaim the slot |
88
+
89
+ ## Run several tracks at once
90
+
91
+ | Skill | When to use |
92
+ | ------------------------- | ----------------------------------------------------------------------------------------------------------- |
93
+ | `canon:role-orchestrator` | To assert the control session that owns the queue and reviews each worker's PR |
94
+ | `canon:role-planner` | To assert the thinking role for a cold session writing a plan, a groundwork track, or an intake pass |
95
+ | `canon:role-worker` | To assert the worker role for a cold session building one branch under one plan |
96
+ | `canon:session-relay` | When this session owes another session a message, with or without a role |
97
+ | `canon:session-resume` | At the start of a session, to pick up what a previous one left |
98
+ | `canon:session-compact` | Before a compaction or a move to another machine, to write a plain session's handoff note outside the board |
99
+ | `canon:session-map` | At the close of an orchestrating session, to write its board-side handoff |
100
+
101
+ ## Keep the project current with the toolkit
102
+
103
+ | Skill | When to use |
104
+ | ----------------------------- | -------------------------------------------------------------------------------------- |
105
+ | `canon:target-check` | In a target project, to report per domain what it holds against what the toolkit ships |
106
+ | `canon:seed-sync` | After a toolkit update, to reconcile installed seeds without losing customizations |
107
+ | `canon:canon-feedback` | When something in the toolkit is broken, missing, or off, to open an issue on it |
108
+ | `canon:canon-feedback-triage` | In the toolkit repo, to work through the open feedback issues |
109
+ | `canon:canon-rollout` | In the toolkit repo, to take one change out to every consuming project at once |
110
+
111
+ ## Generate an artifact on demand
112
+
113
+ | Skill | When to use |
114
+ | ------------------------- | ----------------------------------------------------------------------------------------------------------------- |
115
+ | `canon:create-rule` | For a project-specific governance rule the toolkit does not ship |
116
+ | `canon:create-skill` | For a new `SKILL.md` |
117
+ | `canon:create-snippet` | For a reusable prompt |
118
+ | `canon:create-standard` | For a new authoring convention |
119
+ | `canon:draft-docs` | For a brand-new `docs/*.md` page, drafted against `standards/docs.md` |
120
+ | `canon:draft-ready` | For finished files a worker should copy, written as a ready folder with its overview, thin plan, and task |
121
+ | `canon:draft-context` | For a brand-new `canon/context/<domain>.md` entry, drafted against `standards/context.md` |
122
+ | `canon:draft-wireframes` | For a brand-new `canon/wireframes/<surface>.md` file, drafted against `standards/wireframes.md` |
123
+ | `canon:draft-wiki` | For a brand-new wiki reference page on a subject owned outside the project, drafted against `standards/wiki.md` |
124
+ | `canon:draft-figure` | For a hand-drawn figure inside an existing doc, drafted against `standards/figures.md` in Mermaid or freehand SVG |
125
+ | `canon:draft-readme` | For a project's `README.md`, drafted against `standards/readme.md` |
126
+ | `canon:bash-script` | For an interactive, human-facing shell tool |
127
+ | `canon:bash-cli-script` | For a non-interactive automation, CI, or pipeline script |
128
+ | `canon:ci-workflow` | For a GitHub Actions workflow file |
129
+ | `canon:draft-slides` | For a deck, drafted as `.claude/SLIDES.md` and rendered to PowerPoint |
130
+ | `canon:draft-screencast` | For a recording script with beats and defaults already seeded |
131
+ | `canon:record-screencast` | For compiling and running a screencast draft into a recording and a still |
132
+ | `canon:draft-identity` | For a project's logo mark and its social card, drafted through `draft-and-pick`'s pick loop |
133
+
134
+ ## Answer a question at any point
135
+
136
+ | Skill | When to use |
137
+ | --------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
138
+ | `canon:canon-cli` | Before running an unfamiliar verb, a sync, or an install, to learn which command to run, which reference doc covers it, or what it overwrites, merges, or leaves alone |
139
+ | `canon:index-lookup` | To find where a topic is documented across the tracked `index.md` catalogs |
140
+ | `canon:youtube-transcripts` | When a video transcript is wanted in the repo as context |
141
+ | `canon:read-frames` | To read a recorded demo back frame by frame and report what each one shows, with no verdict on whether the recording looks right |
142
+ | `canon:teach-workspace` | To learn a subject across sessions, in a workspace that holds the progress |
143
+ | `canon:write-human` | Before drafting or revising prose, for voice, rhythm, and density |
144
+ | `canon:restate-plainly` | When an answer or a document has to be read again in plain words |
145
+
146
+ Every row answers a question rather than marking a point in a project's life, so a phase above would send a reader to the wrong group.
147
+
148
+ A learning workspace produces two halves and only one of them leaves. A lesson is worked through once and stays in the workspace, and a reference page or a glossary carries no learner, so it belongs wherever the project already keeps prose on that subject. Asking `canon:teach-workspace` to promote sorts each durable page by who owns its subject, sending an Anthropic-owned subject to the wiki, an internal one to the matching context entry, and everything else, subject-neutral material included, to the public docs. It proposes and waits, because a promoted page is public prose that needs a line naming who owns the subject, and it writes nothing to a destination: each page the operator confirms goes to a handoff file that `canon:context-fold` folds in from a branch. A project with no wiki folder gets a refusal naming `canon wiki init` rather than a folder it never asked for.
@@ -11,3 +11,37 @@
11
11
  # stay. A key must name no live rule and every chain must end on one, which
12
12
  # `src/gov/renames.test.ts` checks against this file.
13
13
  [renamed]
14
+ "005-behavior" = "565-behavior"
15
+ "015-output" = "566-output"
16
+ "070-planning" = "567-planning"
17
+ "025-indexes" = "601-indexes"
18
+ "035-tasks" = "602-tasks"
19
+ "045-memory" = "603-memory"
20
+ "055-scratch" = "604-scratch"
21
+ "085-worktrees" = "605-worktrees"
22
+ "087-git" = "606-git"
23
+ "510-context" = "610-context"
24
+ "511-indexes" = "611-indexes"
25
+ "520-wireframes" = "620-wireframes"
26
+ "530-requirements" = "630-requirements"
27
+ "540-architecture" = "640-architecture"
28
+ "545-decisions" = "645-decisions"
29
+ "550-design" = "650-design"
30
+ "555-tasks" = "655-tasks"
31
+ "556-groundwork" = "656-groundwork"
32
+ "557-intake" = "657-intake"
33
+ "558-plan" = "658-plan"
34
+ "559-memory" = "659-memory"
35
+ "560-diagrams" = "660-diagrams"
36
+ "561-teach" = "661-teach"
37
+ "562-session" = "662-session"
38
+ "563-ready" = "663-ready"
39
+ "500-prose" = "800-prose"
40
+ "501-markdown" = "801-markdown"
41
+ "502-mermaid" = "802-mermaid"
42
+ "580-readme" = "880-readme"
43
+ "591-standard-authoring" = "891-standard-authoring"
44
+ "065-spelling" = "765-spelling"
45
+ "075-dependencies" = "775-dependencies"
46
+ "080-config-comments" = "780-config-comments"
47
+ "090-code-comments" = "790-code-comments"
@@ -10,7 +10,7 @@ paths:
10
10
  ## Authority
11
11
 
12
12
  - Follow the diagrams standard for which question an entry answers, the entry kinds and their source signals, the frontmatter, and the explanation prose beneath the fence. It is the single source. Read it with `canon standards diagrams`.
13
- - Layout, budgets, accessibility, labels, and render verification inside the fence are a separate topic. `502-mermaid` routes them to `mermaid.md`.
13
+ - Layout, budgets, accessibility, labels, and render verification inside the fence are a separate topic. `802-mermaid` routes them to `mermaid.md`.
14
14
  - A diagram entry carries structure and flow, not implementation. Read the standard before adding or revising a kind.
15
15
 
16
16
  ## Scope
@@ -8,7 +8,7 @@ paths:
8
8
 
9
9
  ## What a handoff carries
10
10
 
11
- - Follow this rule rather than `555-tasks.md` for a `session-` file. A handoff is not a task and carries neither `## Outcomes` nor `## Findings`.
11
+ - Follow this rule rather than `655-tasks.md` for a `session-` file. A handoff is not a task and carries neither `## Outcomes` nor `## Findings`.
12
12
 
13
13
  ## Authority
14
14
 
@@ -0,0 +1,21 @@
1
+ ---
2
+ description: Code placement, dependency, error, and naming choices a model does not make by default
3
+ ---
4
+
5
+ # Code standards
6
+
7
+ ## Placement
8
+
9
+ - Load the `canon:codebase-layout` skill before placing a new file, and report it rather than proceeding silently when it does not resolve.
10
+ - Prioritize native platform capabilities over third-party libraries.
11
+ - Ensure data and configuration reside in designated Single Source of Truth locations.
12
+
13
+ ## Errors
14
+
15
+ - Return structured error types for recoverable failures.
16
+ - Never expose internal implementation details in error messages.
17
+
18
+ ## Naming
19
+
20
+ - Prefix booleans with `is`, `has`, `should`, or `can`: `isLoading`, `hasAccess`.
21
+ - Prefix event handlers with `handle`: `handleClick`, `handleSubmit`.
@@ -9,10 +9,6 @@ paths:
9
9
 
10
10
  # TypeScript/JavaScript testing tooling
11
11
 
12
- ## Layer
13
-
14
- - Load the `canon:test-craft` skill to pick the layer a test belongs at before choosing the tooling below, and report it rather than proceeding silently when the skill does not resolve.
15
-
16
12
  ## Unit and integration
17
13
 
18
14
  - Use Vitest for unit and integration tests.
@@ -8,10 +8,6 @@ paths:
8
8
 
9
9
  # Python testing tooling
10
10
 
11
- ## Layer
12
-
13
- - Load the `canon:test-craft` skill to pick the layer a test belongs at before choosing the tooling below, and report it rather than proceeding silently when the skill does not resolve.
14
-
15
11
  ## Framework
16
12
 
17
13
  - Use `pytest` for all tests. Do not use `unittest.TestCase`.
@@ -12,4 +12,4 @@ paths:
12
12
  - Load it before drafting a passage, not after revising one.
13
13
  - Report it rather than proceeding silently when the skill does not resolve.
14
14
  - Do not work these rules from memory.
15
- - Punctuation, formatting, and file references are a separate topic. `501-markdown` routes them.
15
+ - Punctuation, formatting, and file references are a separate topic. `801-markdown` routes them.
@@ -11,4 +11,4 @@ paths:
11
11
  - Follow the markdown standard for headings, paragraph and list structure, code spans, punctuation, emphasis, file references, and the wording of a `title` or `description`. It is the single source. Read it with `canon standards markdown`.
12
12
  - Read it before a substantial markdown edit. Do not work the banned characters from memory.
13
13
  - Run `canon markdown audit <path>` after the edit, and rewrite the sentence carrying a hit rather than swapping the token for a near-synonym.
14
- - Voice, rhythm, and sentence construction are a separate topic. `500-prose` routes them.
14
+ - Voice, rhythm, and sentence construction are a separate topic. `800-prose` routes them.
@@ -11,4 +11,4 @@ paths:
11
11
  - Apply this rule only when the edit drafts or revises a Mermaid fence. Skip it on a markdown edit carrying no diagram.
12
12
  - Follow the mermaid standard for direction and layout, node and edge budgets, the accessibility fields, punctuation inside labels, and how a render is verified. It is the single source. Read it with `canon standards mermaid`.
13
13
  - Read it before drafting the fence. Do not work the layout or the budgets from memory.
14
- - Which diagram a document carries and what question it answers is a separate topic. `560-diagrams` routes it.
14
+ - Which diagram a document carries and what question it answers is a separate topic. `660-diagrams` routes it.
@@ -1,8 +1,9 @@
1
1
  extends = ""
2
- # All four folders whole. Every rule authored under them ships to a base
2
+ # Four audience groups whole. Every rule authored under them ships to a base
3
3
  # consumer, so adding one is a single edit rather than a file and a name here.
4
- # `snippets` carries the `@`-reference convention rule, which lost its only
5
- # other delivery path when `canon snippets install` retired. `ci` carries the
6
- # workflow rule, whose glob is the only inbound route to the `ci-workflow`
7
- # skill.
8
- rules = ["core", "claude", "snippets", "ci", "120-bash"]
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", "120-bash"]
@@ -1,2 +1,2 @@
1
1
  extends = "base"
2
- rules = ["100-typescript"]
2
+ rules = ["code", "100-typescript"]
@@ -1,2 +1,2 @@
1
1
  extends = "base"
2
- rules = ["110-python", "340-pydantic", "330-testing-py", "360-security-server", "370-database"]
2
+ rules = ["code", "110-python", "340-pydantic", "330-testing-py", "360-security-server", "370-database"]
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@erclx/canon",
3
3
  "type": "module",
4
- "version": "4.123.0",
4
+ "version": "4.124.0",
5
5
  "description": "Infrastructure and quality tooling for developer workflows",
6
6
  "license": "MIT",
7
7
  "bin": {
@@ -91,13 +91,11 @@ log_step "Assert scaffold"
91
91
  # Standards and snippets name no path because neither corpus installs into a
92
92
  # target. A scaffold reads a standard through `canon standards <name>` and a
93
93
  # snippet through the plugin's live `claude/snippets` symlink, both resolving
94
- # against the toolkit rather than a copy this gate could assert on. The
95
- # `@`-reference convention rule is the one snippets-domain file that still
96
- # installs, since `base` carries `governance/rules/snippets/` as a
97
- # folder-whole entry the same way it does `core` and `claude`.
94
+ # against the toolkit rather than a copy this gate could assert on. The two
95
+ # rule paths stand for the `claude` and `canon` groups `base` takes whole.
98
96
  for path in "CLAUDE.md" ".claude/wiki/index.md" ".claude" "canon/context/index.md" "canon/wireframes/index.md" ".canon/diagrams/index.md" \
99
97
  ".prettierrc" ".editorconfig" ".lintstagedrc" ".husky/pre-commit" ".github/workflows/verify.yml" "scripts/verify.sh" \
100
- ".claude/rules/canon/core/000-constitution.md" ".claude/rules/canon/snippets/600-at-references.md"; do
98
+ ".claude/rules/canon/claude/565-behavior.md" ".claude/rules/canon/canon/604-scratch.md"; do
101
99
  if [ ! -e "$TARGET_DIR/$path" ]; then
102
100
  log_error "Missing after canon init: $path"
103
101
  fi
@@ -196,7 +196,7 @@ function frontmatter(text: string): string {
196
196
  *
197
197
  * A glob opening `**` reaches every folder in the tree, so it answers that a
198
198
  * file type is governed and never that a named path is. Counting one would
199
- * report every markdown path covered by `501-markdown` and leave the column
199
+ * report every markdown path covered by `801-markdown` and leave the column
200
200
  * saying nothing a reader could act on.
201
201
  */
202
202
  function isAnchored(glob: string): boolean {
@@ -234,7 +234,7 @@ export function register(program: Command): void {
234
234
  'after',
235
235
  [
236
236
  '',
237
- 'Measures the rule in .claude/rules/canon/core/070-planning.md that asks for',
237
+ 'Measures the rule in .claude/rules/canon/claude/567-planning.md that asks for',
238
238
  'the test before the code. It reports and never gates, because pairing',
239
239
  'a test to an implementation is a judgment.',
240
240
  '',
@@ -101,12 +101,7 @@ const output = (text: string): Emission => ({ kind: 'output', text })
101
101
  /**
102
102
  * Rules no stack reaches, sorted the way `canon gov list` emits them.
103
103
  * `260-shadcn` and `320-tanstack-query` are opt-in libraries a project may not
104
- * want. `600-at-references` used to sit here too, shipping with no stack on
105
- * purpose since a rule under `claude/` would reach every base consumer through
106
- * the folder-whole entry there. Its own install channel, `canon snippets
107
- * install`, retired with nothing left to deliver it, so `base` now carries
108
- * `snippets` as a folder-whole entry of its own and the rule reaches every base
109
- * consumer through that instead.
104
+ * want.
110
105
  *
111
106
  * `130-go`, `140-php`, `335-testing-go`, and `336-testing-php` are opt-in by
112
107
  * `--add` until a Go or PHP stack ships, which `target-setup` reaches by
@@ -266,7 +266,7 @@ export function collectCitations(text: string): RawCitation[] {
266
266
  *
267
267
  * A rule spelling a whole path there is declaring that exact artifact, and a
268
268
  * body line naming it again is naming what the rule governs rather than
269
- * pointing a reader somewhere. `governance/rules/claude/560-diagrams.md` tells
269
+ * pointing a reader somewhere. `governance/rules/canon/660-diagrams.md` tells
270
270
  * its reader to convert a `.claude/DIAGRAMS.md` left by an older install, which
271
271
  * is correctly absent from this tree and correctly named in the rule.
272
272
  */
package/src/gov/list.ts CHANGED
@@ -31,7 +31,7 @@ export interface GovCatalog {
31
31
  /**
32
32
  * Reports each stack's own entries expanded, so a folder entry reaches a
33
33
  * consumer as the rules it stands for. the `setup` skill dedupes `--add` extras
34
- * against this list, and a stack answering `core` there would re-add every
34
+ * against this list, and a stack answering `canon` there would re-add every
35
35
  * rule that folder already carries.
36
36
  *
37
37
  * The `extends` chain is deliberately not resolved, which is what the bash
@@ -698,8 +698,8 @@ export function readRestated(root: string): RestatedReport {
698
698
 
699
699
  // Every candidate's rare set is invariant across the subject loop, so it is
700
700
  // built once here rather than per pair. The corpora multiply out to hundreds
701
- // of thousands of pairings, and rebuilding a set inside that is the shape
702
- // `.claude/rules/canon/core/040-performance.md` names.
701
+ // of thousands of pairings, and rebuilding a set inside that would dominate
702
+ // the run.
703
703
  const rareCandidates = candidates.map((candidate) => ({
704
704
  ...candidate,
705
705
  rare: distinctive(candidate.analysis),
package/src/init/steps.ts CHANGED
@@ -5,7 +5,7 @@ import type { DomainStep } from '@/init/run'
5
5
  export type RunFactory = (args: readonly string[]) => () => Promise<boolean>
6
6
 
7
7
  /**
8
- * States the same fact as `docs/target-projects.md`'s backup section in its
8
+ * States the same fact as `docs/target-migrations.md`'s backup section in its
9
9
  * own words. Keep the two in step by hand; nothing compares them.
10
10
  */
11
11
  const RECORDS_SETUP_NOTICE =
@@ -8,7 +8,7 @@ import { execa } from 'execa'
8
8
  *
9
9
  * `no-binary` is the binary being absent anywhere from the root upward.
10
10
  * `cspell` is a devDependency of this repository alone, per
11
- * `075-dependencies.md`'s ban on importing a transitive-only package, so a
11
+ * `775-dependencies.md`'s ban on importing a transitive-only package, so a
12
12
  * target project that never adopted it gets no coverage from this check
13
13
  * rather than a network fetch or a forced new dependency.
14
14
  *
@@ -35,7 +35,7 @@ const LEGACY_MOVES: ReadonlyMap<string, string> = new Map([
35
35
  * Scratch-root names a different migration moves out of scratch for good,
36
36
  * derived from that migration's own table rather than duplicated in a second
37
37
  * hand-kept list. `RECORD_LAYOUT_MOVES` names `memory-archive`, the
38
- * retired-entry archive `045-memory` says never to delete, and `PROMOTED_FOLDERS`
38
+ * retired-entry archive `603-memory` says never to delete, and `PROMOTED_FOLDERS`
39
39
  * names an evidence folder a durable record cites by name. A project that has
40
40
  * not run either migration still carries these at the scratch root, where an
41
41
  * ordinary slug's own age test would eventually offer them.
@@ -212,7 +212,7 @@ const PHASE_LABEL = /\bv\d+\.\d+(?!\.\d)\b/g
212
212
  * number, such as `create-rule`, `memory-review`, and `target-setup` already
213
213
  * write correctly, from matching. The segment group between `rules/` and the
214
214
  * numbered file admits both a governance-namespace path
215
- * (`canon/core/055-scratch.md`) and a project-namespace one
215
+ * (`canon/canon/604-scratch.md`) and a project-namespace one
216
216
  * (`project/<subdir>/<n>-<slug>.md`) without distinguishing them, since
217
217
  * either shape is the same broken citation.
218
218
  */
package/standards/rule.md CHANGED
@@ -32,7 +32,7 @@ Write both when both apply. A rule stating the directive and a skill stating how
32
32
  ## Location
33
33
 
34
34
  - A toolkit-shipped rule lives at `.claude/rules/canon/<subdirectory>/<n>-<slug>.md`. The wrapper marks the file as toolkit-owned and replaced on sync, so a reader unfamiliar with the numbering convention still knows not to edit it.
35
- - Subdirectories group by domain: `core/`, `lang/`, `framework/`, `lib/`, `ui/`, `claude/`, `snippets/`, `ci/`
35
+ - Subdirectories group by domain or audience: `code/`, `lang/`, `framework/`, `lib/`, `ui/`, `claude/`, `canon/`, `tooling/`, `writing/`
36
36
  - `<n>` is a number from the band reserved for the rule's source and `<slug>` is a one-to-three-word kebab topic
37
37
  - A rule the project authored itself lives at `.claude/rules/project/<subdirectory>/<n>-<slug>.md`, a sibling of `canon/` rather than nested inside it, keeping the same subdirectory names
38
38
  - This repository's own toolkit-only rules, which never ship to a target, live at `.claude/rules/internal/<subdirectory>/<n>-<slug>.md`, a second sibling of `canon/`. See "Two sources numbering into one folder" below.
@@ -40,11 +40,9 @@ Write both when both apply. A rule stating the directive and a skill stating how
40
40
 
41
41
  ## Reserved numbers
42
42
 
43
- `000-899` is reserved for a rule set that ships to targets. `000-599` is what the first six subdirectories above already divide, at 100 per subdirectory. `ci/` was the first to draw from the headroom past that, taking `700-799`.
43
+ `000-899` is reserved for a rule set that ships to targets, and the nine subdirectories above divide it at 100 per subdirectory, in the order listed. No band is left over, so a subdirectory a shipped set adds later joins an existing band or takes one a retired subdirectory freed.
44
44
 
45
- `snippets/` holds one rule rather than a subdirectory's worth of them, and draws a single number, `600`, from the nearer overflow band rather than claiming a hundred for one file. The rest of `600-699`, along with `800-899`, is what remains for a subdirectory a shipped set has not added yet.
46
-
47
- A project-authored rule takes `900-999`, one sequence across every subdirectory under `.claude/rules/project/`. Scanning for a free number instead is what fails, because a shipped set fills its own band release by release, so what reads as free today is what a later release lands on. One target authored `claude/561-self-check.md` on a day nothing shipped at 561, met `claude/561-teach.md` on its next install, and now reads two numbers differently from everywhere else.
45
+ A project-authored rule takes `900-999`, one sequence across every subdirectory under `.claude/rules/project/`. Scanning for a free number instead is what fails, because a shipped set fills its own band release by release, so what reads as free today is what a later release lands on. One target authored `claude/561-self-check.md` on a day nothing shipped at 561, met the shipped teach rule, then numbered 561, on its next install, and now reads two numbers differently from everywhere else.
48
46
 
49
47
  The cost is that a project-authored rule's leading digit stops naming its domain. Its subdirectory names it instead, and install preserves that either way. What a shared band costs is worse: a session that loads two rules reading as one number, with nothing in the folder to say which is which.
50
48
 
@@ -54,7 +52,7 @@ The cost is that a project-authored rule's leading digit stops naming its domain
54
52
 
55
53
  The reservation above divides one pair, being a shipped set against the rules a project wrote for itself. A third source, a rule set held back from targets and installed only where it was authored, needs its own division too. This repository is the one place all three sources exist at once, and it divides the third pair two ways at once rather than one: `canon/` and `internal/` separate a shipped rule from an internal one by location, the same way `project/` separates a project-authored one, and within each subdirectory the numbering still divides by source as well, one source taking the top of the band and the other the gaps between the tens.
56
54
 
57
- The numbering half stays because location alone does not carry to a reader who only sees the number, such as one comparing `core/070-planning.md` against a citation written before the rules moved into `canon/`.
55
+ The numbering half stays because location alone does not carry to a reader who only sees the number, such as one comparing `claude/567-planning.md` against a citation written before the rules moved into `canon/`.
58
56
 
59
57
  The collision this prevents is silent. Two rules that resolve to the same `<n>-<slug>` path leave one file in the installed folder, and neither the install nor the session that reads it reports which source lost. Nothing checks a division outside the reserved bands, so it holds only while both sources follow it. Separating `canon/` from `internal/` by folder removes the filename-collision case specifically, since the two no longer install to the same directory, but the number still carries the source signal for a reader who has only the number in view.
60
58
 
@@ -4,7 +4,7 @@
4
4
 
5
5
  The base layer covers every project the toolkit scaffolds, whatever language sits on top. It ships formatting, spelling, shell linting, conventional commits, git hooks, CI, and one maintenance script. Every other stack extends it, so a decision made here is one every stack inherits.
6
6
 
7
- A repository with several language roots layers this stack once at the root and skips it per subtree, since git honors only one `core.hooksPath` and a re-dropped husky silently breaks. `canon docs target-projects` carries the recipe.
7
+ A repository with several language roots layers this stack once at the root and skips it per subtree, since git honors only one `core.hooksPath` and a re-dropped husky silently breaks. `canon docs target-scenarios` carries the recipe.
8
8
 
9
9
  ## What ships as golden configs
10
10
 
@@ -9,7 +9,7 @@
9
9
  # to infer on every response and hands the answer back instead.
10
10
  #
11
11
  # The entrypoint branch (bare vs. `file://` link) stays prose in
12
- # governance/rules/core/015-output.md. CLAUDE_CODE_ENTRYPOINT is not among
12
+ # governance/rules/claude/566-output.md. CLAUDE_CODE_ENTRYPOINT is not among
13
13
  # the environment variables Claude Code documents as passed to a hook
14
14
  # subprocess, unlike CLAUDE_PROJECT_DIR, so a hook cannot read it reliably.
15
15
  #
@@ -57,5 +57,5 @@ marker="$marker_dir/$key"
57
57
  mkdir -p "$marker_dir"
58
58
  : >"$marker"
59
59
 
60
- msg='Temporary file write outside the project scratch folder. Write temp files to .canon/tmp/<slug>/ in the project root, or .claude/.tmp/<slug>/ where the project carries no .canon/ root, not system temp. See the Scratch rule (055-scratch, under core/ in your installed governance rules).'
60
+ msg='Temporary file write outside the project scratch folder. Write temp files to .canon/tmp/<slug>/ in the project root, or .claude/.tmp/<slug>/ where the project carries no .canon/ root, not system temp. See the Scratch rule (604-scratch, under canon/ in your installed governance rules).'
61
61
  jq -nc --arg msg "$msg" '{hookSpecificOutput:{hookEventName:"PreToolUse",additionalContext:$msg}}'
@@ -16,7 +16,7 @@ Golden config files live in `tooling/web/configs/` and are copied into the targe
16
16
  - `scripts/screenshot.sh`: sources `scripts/lib/preview-server.sh`, then runs the capture against the served preview.
17
17
  - `scripts/lib/preview-server.sh`: sourced, never executed. Builds, serves on `PREVIEW_PORT`, blocks until the port answers, and traps the whole process group on exit, including the detached grandchild `lsof` finds. Both capture scripts source it so the startup lives once.
18
18
  - `scripts/readme-screenshot.sh`: captures one case under `SCREENSHOT_FILTER` and copies its light and dark frames to `assets/evidence/readme/`. `README_FILTER` ships empty with `header/1280` as its example, and the script exits 1 until a project fills it, since a shipped default would capture the wrong part of the page in every project but one. Its copy reads from `screenshots/<hostname>/`, which is where the harness writes.
19
- - `.github/workflows/readme-screenshot.yml`: refreshes that frame on a pull request and commits it back to the branch. The path list ships as `REPLACE_WITH_PROJECT_PATHS`, and the job's first step after checkout exits 1 while it stays, since a job that never fires leaves no run and no diff to notice. The workflow's own path is in the list so the installing pull request reaches that step. When a commit-back is right and when a report is, `governance/rules/ci/700-ci-workflow.md` states the test.
19
+ - `.github/workflows/readme-screenshot.yml`: refreshes that frame on a pull request and commits it back to the branch. The path list ships as `REPLACE_WITH_PROJECT_PATHS`, and the job's first step after checkout exits 1 while it stays, since a job that never fires leaves no run and no diff to notice. The workflow's own path is in the list so the installing pull request reaches that step. When a commit-back is right and when a report is, `governance/rules/tooling/700-ci-workflow.md` states the test.
20
20
  - `.vscode/extensions.json` and `.vscode/settings.json`: editor wiring for ESLint, Tailwind, Playwright, Vitest.
21
21
  - `.github/workflows/verify.yml`: `static-checks`, `unit-tests`, `build-verify`, and `e2e-tests` jobs.
22
22
  - `scripts/verify.sh`: extends base verify with typecheck, lint, unit tests, and build in the full order. Its last stage runs `scripts/check-card-exclusion.sh` whenever that file is installed, which puts the social card route's build exclusion on the default path rather than behind a flag nobody passes. The stage tests for the script rather than for a framework, so this layer owns when the check runs and the stack shipping a card route owns what it reads. The astro reference carries the route itself.
@@ -1,30 +0,0 @@
1
- ---
2
- description: Define senior architect persona and core philosophy
3
- ---
4
-
5
- # Role persona
6
-
7
- You are a Senior Principal Architect.
8
- Your primary directive is to maintain long-term system health over short-term convenience.
9
-
10
- ## Readability and simplicity
11
-
12
- - Optimize for readability. Code is read far more than it is written.
13
- - Code must be self-documenting through clear naming and explicit structure.
14
- - Comments are permitted ONLY to explain intent, never logic.
15
- - Prefer the simplest implementation that satisfies the requirement (KISS).
16
-
17
- ## Design philosophy
18
-
19
- - Implement only the functionality required for the immediate task (YAGNI).
20
- - Extract shared logic into single-purpose utilities. Never duplicate behavior across modules (DRY).
21
- - Each function, module, and component should have a single reason to change (SRP).
22
- - Apply SRP to directories: once a folder mixes distinct roles and grows past a handful of files, split it into subfolders by role. Load the `canon:codebase-layout` skill before placing a new file, and report it rather than proceeding silently when it does not resolve.
23
- - Favor composition over inheritance.
24
- - Prioritize native platform capabilities over third-party libraries.
25
-
26
- ## Data integrity
27
-
28
- - Favor explicit behavior over implicit magic or conventions.
29
- - Ensure data and configuration reside in designated Single Source of Truth locations.
30
- - Treat data as immutable unless mutation is explicitly required.
@@ -1,22 +0,0 @@
1
- ---
2
- description: Enforce safe concurrency and async operation patterns
3
- ---
4
-
5
- # Concurrency standards
6
-
7
- ## Async lifecycle
8
-
9
- - Make async operations cancellable. Clean up on scope exit or caller cancellation.
10
- - Coordinate dependent async operations explicitly. Document execution order.
11
- - Set explicit timeouts on all external async operations.
12
- - Do not fire-and-forget async operations without cleanup handlers.
13
- - Batch independent async operations. Do not run them sequentially when parallelizable.
14
-
15
- ## Race conditions
16
-
17
- - Do not ignore race conditions in concurrent flows.
18
- - Protect shared mutable state with locks, queues, or single-writer patterns.
19
-
20
- ## Failure handling
21
-
22
- - Handle partial failures in batched operations independently. Do not fail the entire batch for a single error.