@erclx/canon 5.55.0 → 5.57.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 (84) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/claude/.claude-plugin/plugin.json +1 -1
  3. package/claude/skills/api-design/SKILL.md +8 -10
  4. package/claude/skills/auto-ship/SKILL.md +4 -5
  5. package/claude/skills/auto-ship/references/failure-recovery.md +37 -17
  6. package/claude/skills/auto-ship/references/tier-failures.md +9 -7
  7. package/claude/skills/auto-ship/references/worktree-name.md +8 -5
  8. package/claude/skills/backlog-triage/SKILL.md +10 -10
  9. package/claude/skills/backlog-triage/references/apply.md +6 -6
  10. package/claude/skills/canon-feedback-triage/SKILL.md +7 -5
  11. package/claude/skills/context-fold/references/classify.md +17 -4
  12. package/claude/skills/create-rule/references/rule.md +4 -0
  13. package/claude/skills/create-skill/SKILL.md +2 -2
  14. package/claude/skills/deploy-app/SKILL.md +2 -0
  15. package/claude/skills/deprecation-migration/SKILL.md +7 -9
  16. package/claude/skills/document-health/references/axes.md +1 -1
  17. package/claude/skills/git-followup/REQUIREMENT.md +4 -4
  18. package/claude/skills/git-followup/SKILL.md +24 -7
  19. package/claude/skills/git-issue/references/issue.md +9 -11
  20. package/claude/skills/git-pr/references/closing-issues.md +8 -0
  21. package/claude/skills/git-pr/references/publish.md +4 -5
  22. package/claude/skills/git-split/SKILL.md +11 -4
  23. package/claude/skills/markdown-craft/SKILL.md +1 -1
  24. package/claude/skills/markdown-craft/references/markdown.md +2 -2
  25. package/claude/skills/markdown-craft/references/tables.md +9 -7
  26. package/claude/skills/plan-feature/REQUIREMENT.md +2 -1
  27. package/claude/skills/plan-feature/SKILL.md +19 -1
  28. package/claude/skills/plan-feature/references/onboarding.md +51 -0
  29. package/claude/skills/plan-feature/references/plan.md +18 -0
  30. package/claude/skills/plan-groundwork/SKILL.md +1 -1
  31. package/claude/skills/plan-intake/REQUIREMENT.md +3 -3
  32. package/claude/skills/plan-intake/SKILL.md +4 -0
  33. package/claude/skills/plan-intake/references/intake.md +10 -0
  34. package/claude/skills/review-address/SKILL.md +10 -8
  35. package/claude/skills/review-craft/SKILL.md +7 -9
  36. package/claude/skills/review-craft/references/adopted.md +10 -8
  37. package/claude/skills/review-pr/SKILL.md +2 -0
  38. package/claude/skills/review-pr/references/key-changes.md +8 -6
  39. package/claude/skills/review-ui/references/driving.md +10 -8
  40. package/claude/skills/role-orchestrator/references/orchestrator-parked.md +6 -4
  41. package/claude/skills/role-orchestrator/references/orchestrator-refill.md +9 -3
  42. package/claude/skills/role-reviewer/SKILL.md +5 -5
  43. package/claude/skills/search-craft/SKILL.md +5 -7
  44. package/claude/skills/session-worktree/SKILL.md +2 -0
  45. package/claude/skills/session-worktree/references/main-root-writes.md +2 -0
  46. package/claude/skills/systematic-debugging/SKILL.md +9 -9
  47. package/claude/skills/systematic-debugging/references/adopted.md +1 -1
  48. package/claude/skills/target-update/REQUIREMENT.md +1 -0
  49. package/claude/skills/target-update/SKILL.md +22 -0
  50. package/claude/skills/task-board/SKILL.md +2 -4
  51. package/claude/skills/task-board/references/tasks.md +5 -5
  52. package/claude/skills/task-complete/references/archive.md +5 -2
  53. package/claude/skills/test-craft/SKILL.md +2 -0
  54. package/claude/skills/test-craft/references/adopted.md +2 -0
  55. package/claude/skills/ui-checklist/SKILL.md +8 -9
  56. package/claude/skills/write-doc/SKILL.md +8 -8
  57. package/claude/skills/write-doc/references/readme.md +2 -0
  58. package/claude/skills/write-doc/references/wiki-kind.md +11 -4
  59. package/docs/agents/context-audit.md +16 -14
  60. package/docs/agents/markdown-audit.md +11 -4
  61. package/docs/agents/migrate.md +15 -13
  62. package/docs/agents/output-shape.md +2 -0
  63. package/docs/target/migrations.md +3 -3
  64. package/docs/workflow/operating-model.md +2 -0
  65. package/package.json +1 -1
  66. package/src/commands/markdown.ts +25 -29
  67. package/src/commands/tasks.ts +10 -4
  68. package/src/labels/density.ts +5 -46
  69. package/src/markdown/density.ts +41 -6
  70. package/src/markdown/scope.ts +6 -1
  71. package/src/markdown/structure.ts +18 -9
  72. package/src/markdown/tables.ts +32 -18
  73. package/src/pr/bijection.ts +5 -3
  74. package/src/pr/paths.ts +32 -10
  75. package/src/process/harness.ts +8 -0
  76. package/src/process/seeded-package.ts +21 -0
  77. package/src/records/validate.ts +1 -0
  78. package/src/serve/static.ts +2 -60
  79. package/src/tasks/branch.ts +6 -1
  80. package/src/tasks/record.ts +44 -0
  81. package/tooling/base/reference.md +7 -6
  82. package/tooling/claude/reference.md +7 -5
  83. package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +7 -6
  84. package/src/serve/live.ts +0 -113
@@ -54,13 +54,11 @@ Read `${CLAUDE_SKILL_DIR}/references/adopted.md` only when extending this guidan
54
54
 
55
55
  ## Excuses and rebuttals
56
56
 
57
- | Excuse | Rebuttal |
58
- | ---------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
59
- | The model already knows the good sites | It does, and it does not use that knowledge unprompted. Left to rank, a search puts guides written to rank above a field's reference pages. |
60
- | One search was enough | One search gives nothing to check a wrong fact against. The scoped search is what catches the open summary's error. |
61
- | The open results look authoritative | Ranking rewards pages written to rank, so advocates and thin guides sit beside the field's own record and tilt the summary. |
62
- | I scoped it, so every result is in scope | The domain filter is not strict, so a scoped search can return results from outside its list. |
63
- | The summary already answers it | A summary paraphrases. Fetch the page when two summaries disagree, since that is where the error sits. |
57
+ - **The model already knows the good sites.** It does, and it does not use that knowledge unprompted. Left to rank, a search puts guides written to rank above a field's reference pages.
58
+ - **One search was enough.** One search gives nothing to check a wrong fact against. The scoped search is what catches the open summary's error.
59
+ - **The open results look authoritative.** Ranking rewards pages written to rank, so advocates and thin guides sit beside the field's own record and tilt the summary.
60
+ - **I scoped it, so every result is in scope.** The domain filter is not strict, so a scoped search can return results from outside its list.
61
+ - **The summary already answers it.** A summary paraphrases. Fetch the page when two summaries disagree, since that is where the error sits.
64
62
 
65
63
  ## Red flags
66
64
 
@@ -73,6 +73,8 @@ Resolve `<type>` here too, since Step 3 previews it and Step 5 renames onto it,
73
73
  | A plan, through tier 1 or tier 2 | The `type` field of `canon tasks plan-branch <plan> --json` |
74
74
  | A branch, a bare user name, or anything else | `feat` |
75
75
 
76
+ The points below govern how the type is read.
77
+
76
78
  - The verb is the reading because a type read off a plan's sections is a judgment two sessions can grade differently, and the verb answers the same for both
77
79
  - Branch on the record rather than on the exit code, which a shell function wrapping `canon` can flatten to zero
78
80
  - Take `feat` and say the verb did not answer where it refuses, the record has no `type`, or the binary has no `plan-branch`
@@ -22,6 +22,8 @@ Each kind of write takes one route, and none of them is a stream editor.
22
22
  | Change inside a file | A `canon` verb resolving the main root in-process, such as `canon tasks outcome` or `canon tasks pull-request` |
23
23
  | Delete or move | One plain `rm` or `mv` per call rather than chained |
24
24
 
25
+ Three habits keep those routes from being refused or silently wrong.
26
+
25
27
  - Send `mkdir -p` for a missing folder as its own command first, since a `&&` compound is refused for complexity
26
28
  - Where no verb covers an edit, read the whole file and write it back whole through the heredoc route
27
29
  - Never reach for a stream editor, which rewrites the line it anchored to and exits zero on a non-match
@@ -23,7 +23,9 @@ No fixes without root-cause investigation first. If phase 1 is incomplete, no fi
23
23
  - State. Run the case alone and again after the others, and look for shared caches, globals, and fixtures one case leaks into the next.
24
24
  - None of these. Add logging at the suspect and record the conditions of each occurrence, which hands off to the no-root-cause section below rather than to a fix.
25
25
  3. Check what changed. Run `git diff` and `git log --oneline -10` from the project root to see recent changes.
26
- - For a regression with a known good commit, bisect rather than reading the log by eye: `git bisect start HEAD <good commit>`, then `git bisect run <the project's focused test command>` where a test reproduces the failure. Run `git bisect reset` once it names the commit, since bisect leaves the checkout on an old one.
26
+ - For a regression with a known good commit, bisect rather than reading the log by eye, with `git bisect start HEAD <good commit>`
27
+ - Where a test reproduces the failure, run `git bisect run <the project's focused test command>`
28
+ - Run `git bisect reset` once it names the commit, since bisect leaves the checkout on an old one
27
29
  4. For multi-component systems, add instrumentation at each component boundary and run once to see which layer fails before investigating further.
28
30
  5. Trace bad values backward to their source. Fix at the origin, not the symptom.
29
31
 
@@ -69,14 +71,12 @@ Most "no root cause" conclusions are incomplete investigations. Exhaust phase 1
69
71
 
70
72
  ## Excuses and rebuttals
71
73
 
72
- | Excuse | Rebuttal |
73
- | --------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- |
74
- | "I know what the bug is, so I'll just fix it" | Then reproducing it costs a minute. When the reading is wrong, the fix moves the symptom and reports success over a cause still in place. |
75
- | "Quick fix for now, investigate later" | Later never reads the code again. The quick fix becomes the record of what the bug was, and it names the wrong place. |
76
- | "It's probably flaky, rerun it" | A rerun that passes says the failure is intermittent, not that it is gone. Take the timing, environment, or state branch in phase 1. |
77
- | "It works on my machine" | That is the environment branch's first data point. Diff versions, config, and data against where it fails rather than closing on it. |
78
- | "The error says to run this, so I'll run it" | The error is data about the failure. Whatever wrote it is the thing that is broken, so surface the step to the user rather than running it. |
79
- | "I'll verify manually instead of a test" | A manual check leaves nothing behind. The failing test is what shows the fix reached the cause, and what catches the bug's return. |
74
+ - **"I know what the bug is, so I'll just fix it."** Then reproducing it costs a minute. When the reading is wrong, the fix moves the symptom and reports success over a cause still in place.
75
+ - **"Quick fix for now, investigate later."** Later never reads the code again. The quick fix becomes the record of what the bug was, and it names the wrong place.
76
+ - **"It's probably flaky, rerun it."** A rerun that passes says the failure is intermittent, not that it is gone. Take the timing, environment, or state branch in phase 1.
77
+ - **"It works on my machine."** That is the environment branch's first data point. Diff versions, config, and data against where it fails rather than closing on it.
78
+ - **"The error says to run this, so I'll run it."** The error is data about the failure. Whatever wrote it is the thing that is broken, so surface the step to the user rather than running it.
79
+ - **"I'll verify manually instead of a test."** A manual check leaves nothing behind. The failing test is what shows the fix reached the cause, and what catches the bug's return.
80
80
 
81
81
  ## Red flags
82
82
 
@@ -20,7 +20,7 @@ External sources were read and filtered rather than imported. This file is the r
20
20
 
21
21
  The excuses, red flags, and closing checklist follow the shape every practice skill in this toolkit carries, from `addyosmani/agent-skills@2686b620`, [`docs/skill-anatomy.md`](https://github.com/addyosmani/agent-skills/blob/2686b620fc1fed2e8f60c704839c766b8594c6b6/docs/skill-anatomy.md).
22
22
 
23
- Each excuse row rebuts a reason a session gives to skip the investigation rather than an objection nobody raised. Three come from the source's own rationalizations table and the rest from this skill's earlier red flags.
23
+ Each excuse rebuts a reason a session gives to skip the investigation rather than an objection nobody raised. Three come from the source's own rationalizations table and the rest from this skill's earlier red flags.
24
24
 
25
25
  ### Default shelf
26
26
 
@@ -17,6 +17,7 @@ The verbs report every fact, so the gap is the judgment between them. A session
17
17
  - Read every fact from a `canon` verb, so a later release changes what the skill reports with no edit to its body
18
18
  - Stop and ask on a refused migration, a stranded file, an unattributed folder, and a rule the stack newly ships
19
19
  - Keep a customized file and a drifted seed as the project wrote them, naming the toolkit change each one skipped
20
+ - Keep the shared checkout on its branch, writing on a worktree or a declined-worktree branch the preview names
20
21
  - End on a clean `target-check` or on named remainders, with nothing written when nothing is pending
21
22
 
22
23
  ## Must not
@@ -66,6 +66,8 @@ Target update: `<path>`, canon `<installed>` to `<running>`.
66
66
 
67
67
  **Drift:** <each non-empty cause from sync --check, with its count and paths>
68
68
 
69
+ **Where it lands:** <the linked worktree this run is already in, or the worktree `.claude/worktrees/<name>/` it will enter, or the branch it will create in place when the operator declines a worktree>
70
+
69
71
  **Calls for you:** <each judgment call below this run meets, with the default this skill takes>
70
72
 
71
73
  **Commands, in order:** <the exact commands Steps 4 to 6 will run>
@@ -77,6 +79,26 @@ Summarize the changelog for this project, not for the toolkit. Drop an entry tha
77
79
 
78
80
  When the changelog range is empty, `migrate status` lists nothing pending or refused, and the drift lines hold nothing a step here would take, write nothing. Invoke `canon:target-check` and report the target current with its table.
79
81
 
82
+ ### Take a branch after the go-ahead
83
+
84
+ The migrations, the sync, and the commits write the project, so they land on their own branch rather than on the one the shared checkout holds, where every other session in it would follow. Step 1 stays where it ran, since it writes the machine rather than the project.
85
+
86
+ Compare `git rev-parse --git-dir` with `git rev-parse --git-common-dir`, then take the first row that fits:
87
+
88
+ | State | This skill |
89
+ | ------------------------------------------ | ------------------------------------------------------------------------------------------------- |
90
+ | Different, so already in a linked worktree | Uses it and enters nothing, since a second worktree would nest inside the first |
91
+ | Equal, and the operator took the worktree | Invokes `canon:session-worktree` with `chore/update-canon`, then runs Steps 4 to 6 from inside it |
92
+ | Equal, declined, on `main` or `master` | Invokes `canon:git-branch` for `chore/update-canon`, then runs Steps 4 to 6 in place |
93
+ | Equal, declined, on any other branch | Stops and says so, since `canon:git-branch` would rename that branch under every session on it |
94
+
95
+ Four points govern the choice:
96
+
97
+ - Offer the worktree as the default in the preview's `Where it lands` line, and take a decline from the operator's reply to it
98
+ - Report it rather than proceeding silently when `canon:session-worktree` does not resolve, as in a project that installed governance without the plugin, then fall back to `canon:git-branch`
99
+ - Stop when neither skill resolves, saying the run would otherwise write onto the shared checkout's branch
100
+ - Run the Guards' dirty-tree test again from the new tree. A fresh worktree starts clean, so a refusal there is a real one.
101
+
80
102
  ## Step 4: migrate
81
103
 
82
104
  Run each pending migration in the order `migrate status` gave, one at a time, as the entry's `verb` with `--write --json` appended. The verb carries the flags its dry run used, so a bare `canon migrate <name>` would apply a plan the preview never showed.
@@ -74,10 +74,8 @@ Write `.canon/tasks/vXX.Y-<slug>.md` under the claimed label, reading the file f
74
74
 
75
75
  A task file with no row is a dropped task, so name its surface in the same pass that creates it. The test and both file shapes are in `${CLAUDE_SKILL_DIR}/references/board.md`.
76
76
 
77
- | Task | Surface |
78
- | ------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------- |
79
- | Plausibly planned within the next few waves | A row under `## Needs a plan` in `.canon/tasks/priority.md`, through `canon tasks place <stem> --group needs-a-plan --waiting "<reason>"` |
80
- | Anything else | A line in `.canon/tasks/backlog.md`, which is unordered |
77
+ - A task plausibly planned within the next few waves takes a row under `## Needs a plan` in `.canon/tasks/priority.md`, through `canon tasks place <stem> --group needs-a-plan --waiting "<reason>"`.
78
+ - Any other task takes a line in `.canon/tasks/backlog.md`, which is unordered.
81
79
 
82
80
  Position the row against its siblings with `--before <stem>` or `--after <stem>`, and state what it ranks against in the reason.
83
81
 
@@ -147,11 +147,11 @@ A task with no origin is lost context or work nobody decided to do. The reverse
147
147
 
148
148
  `Plan:` points at `../plans/feature-<slug>.md` while the task is open. Retarget both halves of the link as things move rather than dropping it, so a completed task still leads to its reasoning.
149
149
 
150
- | State | Target |
151
- | ----------------------------- | --------------------------------------- |
152
- | Open | `../plans/feature-<slug>.md` |
153
- | Shipped, plan archived | `../plans/archive/feature-<slug>.md` |
154
- | Task archived a folder deeper | `../../plans/archive/feature-<slug>.md` |
150
+ - Open: `../plans/feature-<slug>.md`
151
+ - Shipped, plan archived: `../plans/archive/feature-<slug>.md`
152
+ - Task archived a folder deeper: `../../plans/archive/feature-<slug>.md`
153
+
154
+ Three rules cover the line itself:
155
155
 
156
156
  - One plan per task, or one per slice as distinct plans on one line. A plan cited by two tasks is a misfile.
157
157
  - `canon tasks plan-link <task> <plan>` writes or corrects the line, and `--add` appends a slice's plan, so it is never hand-edited
@@ -56,8 +56,11 @@ An empty `plans` means the task cited no live plan, or a sibling still holds eve
56
56
  Each reason has one resolution, and none of them is to archive around it.
57
57
 
58
58
  - `open-outcomes`: the named outcomes are unmarked or genuinely open. Run `task-complete` when the work shipped unmarked, and leave the task on the board when the outcome is real.
59
- - An outcome only the operator can check is marked `- [ ] Operator check: <outcome>` rather than struck, which the archive passes and the record lists under `operatorChecks`. The mark has to land before the pull request opens.
60
- - Abandoned work, an outcome another repository owes, and an operator outcome nobody marked in time take the strike. The orchestrator's merge sweep strikes it with its reason and lists it in the report, per `${CLAUDE_SKILL_DIR}/../role-orchestrator/references/orchestrator-refill.md`, and the archive then runs. An outcome this repository owes is never struck for that.
59
+ - An outcome only the operator can check is marked `- [ ] Operator check: <outcome>` rather than struck, so the archive passes it and lists it under `operatorChecks`
60
+ - The mark has to land before the pull request opens
61
+ - Abandoned work, an outcome another repository owes, and an operator outcome nobody marked in time take the strike
62
+ - The orchestrator's merge sweep strikes it with its reason and lists it in the report, per `${CLAUDE_SKILL_DIR}/../role-orchestrator/references/orchestrator-refill.md`, and the archive then runs
63
+ - An outcome this repository owes is never struck for that
61
64
  - `ambiguous`: two tasks name one pull request, the misfile `${CLAUDE_SKILL_DIR}/references/tasks.md` rules out. Resolve the citation by hand, since no sweep repairs it.
62
65
  - `earlier-slice`: the number is listed on the task but is not the last. Leave the task on the board, and its last slice's merge archives it.
63
66
 
@@ -31,6 +31,8 @@ Size a test by what it touches rather than by what it covers. Pick the first row
31
31
  | Rendered behavior: states, interactions, conditional rendering, validation, focus | Component |
32
32
  | A journey across routes, or what only a real browser renders: layout, scroll, motion | End to end |
33
33
 
34
+ Four rules govern how a session reads the table.
35
+
34
36
  - Read the row off the behavior, never off the file. A component file holding a pure formatter takes a unit test for the formatter.
35
37
  - Split a behavior that spans rows. Test the copy at unit and the render at component, rather than asserting both in one browser run.
36
38
  - Write the lower test when a higher one catches a break no lower test did. A red end to end run with every unit and component test green names a missing lower test.
@@ -19,6 +19,8 @@ Three sources settle which layer a test belongs at and how the decision table re
19
19
  | Sizing by what a test touches | Google's small, medium, and large sizes ([Software Engineering at Google, ch. 11](https://abseil.io/resources/swe-book/html/ch11.html)) |
20
20
  | The component layer carrying UI weight | Kent C. Dodds's trophy ([Write tests](https://kentcdodds.com/blog/write-tests)) and Testing Library's [guiding principles](https://testing-library.com/docs/guiding-principles) |
21
21
 
22
+ Each source below is read for what it settles.
23
+
22
24
  - Fowler writes a lower test when a higher one catches what no lower one did. It is the body's layer rule and the decision table's reason.
23
25
  - Google's sizes name what a test may touch rather than cover. The table keys on the same, so it transfers across stacks without naming a runner.
24
26
  - Testing Library holds that tests resembling use give more confidence
@@ -33,15 +33,14 @@ The evidence comment already heads the list with `## What to look at`, so the fi
33
33
  - [ ] <route>[, <width>]: <verb> <target> → <expected visual result>
34
34
  ```
35
35
 
36
- Write each box so a session driving the running app can run it without guessing:
37
-
38
- | Part | Rule |
39
- | ----- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
40
- | Route | A path or the control that reaches it. A box naming none is driven from the address the driver opens. Write "from the page the app opens on" for a state reached by a sequence. |
41
- | Width | Only when the change can differ by width, such as layout, spacing, or anything responsive. Copy, color, or a state rendering the same everywhere leaves it off. |
42
- | Verb | An action a driver performs, such as "scroll to", "click", "resize to", or "tab to". Never "read" or "look at", which name no action. |
43
- | Taste | End the line with `(taste)` when the result is a judgment of look or feel. A driver reports such a box as needing a person's eyes rather than passing it. |
44
- | Setup | State inline any setup the page does not open in. End the line with `(local only)` when a hosted preview cannot reach that state, such as a stopped service or a seeded record. |
36
+ Write each box so a session driving the running app can run it without guessing, with one rule for each part:
37
+
38
+ - **Route.** A path or the control that reaches it. A box naming none is driven from the address the driver opens.
39
+ - Write "from the page the app opens on" for a state reached by a sequence.
40
+ - **Width.** Only when the change can differ by width, such as layout, spacing, or anything responsive. Copy, color, or a state rendering the same everywhere leaves it off.
41
+ - **Verb.** An action a driver performs, such as "scroll to", "click", "resize to", or "tab to". Never "read" or "look at", which name no action.
42
+ - **Taste.** End the line with `(taste)` when the result is a judgment of look or feel. A driver reports such a box as needing a person's eyes rather than passing it.
43
+ - **Setup.** State inline any setup the page does not open in. End the line with `(local only)` when a hosted preview cannot reach that state, such as a stopped service or a seeded record.
45
44
 
46
45
  When the plan cites `canon/design/<surface>/` under `**Design references:**`, name the reference as the comparison on each box for that surface, such as "→ matches `canon/design/<surface>/` in light and dark". The reviewer then judges the build against the accepted design instead of against taste.
47
46
 
@@ -13,12 +13,12 @@ Drafts one brand-new project document end to end: resolve its kind, read the sta
13
13
 
14
14
  Each kind has one standard and one reference. Load the reference for the resolved kind and no other, since every step below that differs by kind lives there.
15
15
 
16
- | Kind | Lands at | Standard | Reference |
17
- | ------- | -------------------------------------------------------- | ----------------------------------------------------------- | --------------------------------------------- |
18
- | docs | a page under `docs/` | `${CLAUDE_SKILL_DIR}/../docs-sync/references/docs.md` | `${CLAUDE_SKILL_DIR}/references/docs.md` |
19
- | context | an entry under `canon/context/` | `${CLAUDE_SKILL_DIR}/../context-fold/references/context.md` | `${CLAUDE_SKILL_DIR}/references/context.md` |
20
- | wiki | a reference page on a subject owned outside this project | `${CLAUDE_SKILL_DIR}/references/wiki.md` | `${CLAUDE_SKILL_DIR}/references/wiki-kind.md` |
21
- | readme | a `README.md`, at the root or in a folder | `${CLAUDE_SKILL_DIR}/../docs-sync/references/readme.md` | `${CLAUDE_SKILL_DIR}/references/readme.md` |
16
+ - **docs** lands at a page under `docs/`. Standard `${CLAUDE_SKILL_DIR}/../docs-sync/references/docs.md`, reference `${CLAUDE_SKILL_DIR}/references/docs.md`.
17
+ - **context** lands at an entry under `canon/context/`. Standard `${CLAUDE_SKILL_DIR}/../context-fold/references/context.md`, reference `${CLAUDE_SKILL_DIR}/references/context.md`.
18
+ - **wiki** lands at a reference page on a subject owned outside this project. Standard `${CLAUDE_SKILL_DIR}/references/wiki.md`, reference `${CLAUDE_SKILL_DIR}/references/wiki-kind.md`.
19
+ - **readme** lands at a `README.md`, at the root or in a folder. Standard `${CLAUDE_SKILL_DIR}/../docs-sync/references/readme.md`, reference `${CLAUDE_SKILL_DIR}/references/readme.md`.
20
+
21
+ Resolve the kind from the request by the rules below.
22
22
 
23
23
  - Read the kind off the destination the request names: a path, a folder, or the document's own name, such as "a context entry" or "a wiki page".
24
24
  - Ask which kind when the request names no destination, offering the candidates the subject fits with the likeliest first
@@ -30,10 +30,10 @@ Each kind has one standard and one reference. Load the reference for the resolve
30
30
 
31
31
  Read these in parallel, from the project root where a path is relative:
32
32
 
33
- - The kind's standard from the table above: the reader the document serves, its frontmatter, its structure, and what it links out to rather than restates
33
+ - The kind's standard from the kind list above: the reader the document serves, its frontmatter, its structure, and what it links out to rather than restates
34
34
  - `${CLAUDE_SKILL_DIR}/../markdown-craft/references/markdown.md`: punctuation and formatting for all generated text
35
35
  - The `write-human` skill: voice, rhythm, and sentence construction for all generated text
36
- - The kind's reference from the table above
36
+ - The kind's reference from the kind list above
37
37
 
38
38
  ## Guards
39
39
 
@@ -23,6 +23,8 @@ Read the target if it exists, and branch on its headings.
23
23
  | Carries no H1, or only headings restating the scaffolding tool | Generator output | Continue, drafting over it rather than syncing its sections |
24
24
  | Does not exist | Nothing to read | Continue |
25
25
 
26
+ Three notes qualify those routes.
27
+
26
28
  - On the authored branch, report rather than offering to overwrite it or to conform it, since the project's own citations into its README are invisible from here
27
29
  - A hand-authored README opening with a badge block, or a title the H1 test misses, falls into the no-H1 branch the same as a scaffold page
28
30
  - The Confirm step catches that case before the write, so it is load-bearing. Never skip it on the reasoning that the guard already decided.
@@ -17,10 +17,17 @@ If `<wiki-root>` does not resolve, say so and ask whether to create it before dr
17
17
 
18
18
  The standard sets two tests and a page has to pass both. Run them before drafting anything, since a page failing either is non-conforming however well it is written.
19
19
 
20
- | Test | Fails on | Refusal |
21
- | ------------------------------------------- | ------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------ |
22
- | Owned outside this repository | A subject describing how this repository works | `❌ <subject> is owned by this project, so it belongs in the docs surface or a context entry. Re-run write-doc naming that destination.` |
23
- | Owned by the vendor the folder split covers | A third-party tool or a vendor-neutral concept, however reference-like it reads | `❌ <subject> is outside the wiki's folder split. Route it to the docs surface or a skill body rather than adding a second folder for it.` |
20
+ The first test is owned outside this repository, and it fails on a subject describing how this repository works. Refuse with this line:
21
+
22
+ ```plaintext
23
+ ❌ <subject> is owned by this project, so it belongs in the docs surface or a context entry. Re-run write-doc naming that destination.
24
+ ```
25
+
26
+ The second test is owned by the vendor the folder split covers, and it fails on a third-party tool or a vendor-neutral concept, however reference-like it reads. Refuse with this line:
27
+
28
+ ```plaintext
29
+ ❌ <subject> is outside the wiki's folder split. Route it to the docs surface or a skill body rather than adding a second folder for it.
30
+ ```
24
31
 
25
32
  On the first test, offer the docs or context kind of this skill. The standard names one owner and one subfolder for the second.
26
33
 
@@ -22,19 +22,19 @@ canon context audit tooling/base/seeds --gate
22
22
 
23
23
  ## Output
24
24
 
25
- | Check | Reports | Reaches | Finding |
26
- | ------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | ----------------------- | ----------------------------------------------------------- |
27
- | Citations | A path into an audited folder that resolves nowhere | Every audited folder | Gates always |
28
- | Requirements record | Words past the cap the record states as `This record holds at most 600 words.` | `canon/REQUIREMENTS.md` | Gates past a stated cap, never under `--citations-only` |
29
- | Required sections | An entry missing `Overview` or `Layout`. A split folder answers by any sibling | `canon/context/` | Gates under `--gate` |
30
- | Closed set | An H2 outside `Overview`, `Layout`, and `Gotchas`, under `extraSections` | `canon/context/` | Gates under `--gate` |
31
- | Shape | `retired-section`, `gotcha-count`, `gotcha-heading`, `gotcha-paragraph`, `layout-heading`, `layout-bullets`, `layout-paragraphs`, `layout-depth` | `canon/context/` | Gates under `--gate` in a `SHAPE_GATED_FOLDERS` folder only |
32
- | Index drift | An entry its index does not link, or a link resolving to nothing | Every audited folder | Gates under `--gate` |
33
- | Coverage | A folder directly under a code root that no Layout names, one with a Layout H3 in two entries, and a declared root matching nothing, under `coverage` | `canon/context/` | Gates under `--gate`, never under `--citations-only` |
34
- | Reference form | A backticked bare filename matching a sibling entry, under `bareReferences` | Split folders | Reports |
35
- | Length | An entry past about 150 rendered lines at 80 columns, with its `causes` | Every audited folder | Reports |
36
- | Tables | Six or more body rows whose first column mostly carries a path, command, or link | Every audited folder | Reports |
37
- | Provenance | A date, change number, or release label. A date after measured, verified, driven, passed, or fired is excluded | `canon/context/` | Reports |
25
+ | Check | Reports | Reaches | Finding |
26
+ | ------------------- | ----------------------------------------------------------------------------------------------------------------------- | ----------------------- | ----------------------------------------------------------- |
27
+ | Citations | A path into an audited folder that resolves nowhere | Every audited folder | Gates always |
28
+ | Requirements record | Words past the cap the record states as `This record holds at most 600 words.` | `canon/REQUIREMENTS.md` | Gates past a stated cap, never under `--citations-only` |
29
+ | Required sections | An entry missing `Overview` or `Layout`. A split folder answers by any sibling | `canon/context/` | Gates under `--gate` |
30
+ | Closed set | An H2 outside `Overview`, `Layout`, and `Gotchas`, under `extraSections` | `canon/context/` | Gates under `--gate` |
31
+ | Shape | A break of the entry shape, in any kind listed under the table | `canon/context/` | Gates under `--gate` in a `SHAPE_GATED_FOLDERS` folder only |
32
+ | Index drift | An entry its index does not link, or a link resolving to nothing | Every audited folder | Gates under `--gate` |
33
+ | Coverage | A folder directly under a code root no Layout names, a Layout H3 in two entries, or an unmatched root, under `coverage` | `canon/context/` | Gates under `--gate`, never under `--citations-only` |
34
+ | Reference form | A backticked bare filename matching a sibling entry, under `bareReferences` | Split folders | Reports |
35
+ | Length | An entry past about 150 rendered lines at 80 columns, with its `causes` | Every audited folder | Reports |
36
+ | Tables | Six or more body rows whose first column mostly carries a path, command, or link | Every audited folder | Reports |
37
+ | Provenance | A date, change number, or release label. A date after measured, verified, driven, passed, or fired is excluded | `canon/context/` | Reports |
38
38
 
39
39
  The coverage roots come from `roots` in `canon/config/context.toml`, a list of folders or globs such as `packages/*/src`.
40
40
 
@@ -42,7 +42,7 @@ The coverage roots come from `roots` in `canon/config/context.toml`, a list of f
42
42
  - A file that is not valid TOML, or holds no list of strings under `roots`, gates under `--gate`
43
43
  - With no declaration and no `src/`, the audit reports no code root and never gates
44
44
 
45
- A shape break is any of these:
45
+ The shape kinds are `retired-section`, `gotcha-count`, `gotcha-heading`, `gotcha-paragraph`, `layout-heading`, `layout-bullets`, `layout-paragraphs`, and `layout-depth`. A shape break is any of these:
46
46
 
47
47
  - A `## Decisions` H2, or a `Gotchas` section past five bullets or holding a heading or paragraph
48
48
  - A `Layout` H3 titled neither a code-spanned path nor `Other folders`, or a heading below H3 under `Layout`
@@ -56,6 +56,8 @@ The development entry may carry a `Scripts` H3 exempt from both folder caps. `SH
56
56
  | `1` | Refused, with the reason on stderr |
57
57
  | `2` | A gating finding for the mode the run took |
58
58
 
59
+ The exit code follows the mode the run took. The bullets cover where the gate runs, what refuses, and how a seed opts out.
60
+
59
61
  - `bun run check` runs `--gate` against every `tooling/<stack>/seeds/` directory carrying a `.claude/` folder
60
62
  - A root resolving no audited folder refuses with `1` and warns, a root measuring no entry warns, and a seed short a section fails with `2`
61
63
  - A seed omitting a required section on purpose sets `stub: true` in its frontmatter. Only the value `true` counts, and both install paths strip the field.
@@ -26,24 +26,31 @@ The ban set and checkpoints ship in `src/markdown/bans.ts` and `src/markdown/str
26
26
  | --------------- | ------------------------------------------------------------------------------------ | ----------------- |
27
27
  | Bans | The two characters `markdown.md` bans, outside frontmatter, fences, spans, and links | Always |
28
28
  | Links | A relative link resolving to nothing on disk | Always |
29
- | Density | The six limits below, under `density` | On a gated prefix |
29
+ | Density | The six limits and two table limits below, under `density` | On a gated prefix |
30
30
  | Reference shape | A `kind: reference` page breaking its shape, under `referenceShape` | On a gated prefix |
31
- | Tables | The four table limits below, under `tables` | Never |
31
+ | Tables | The row count and wide token limits below, under `tables` | Never |
32
32
  | Colons | A colon followed by more text in a prose line, under `colons` | Never |
33
33
  | Heading case | A capital after the first word of a heading or `title`, under `headingCase` | Never |
34
34
 
35
35
  A page marked `kind: reference` holds its opening, then `Output`, `Refusals`, and `See also` as H2s, each at most once and in that order. It takes no H3 and no table headed `Flag` or `Option`. An unmarked page is never measured.
36
36
 
37
- Tables take the four limits in the `markdown-craft` skill's `tables.md`, on the density paths but never `CLAUDE.md`. A cell past 120 visible characters reports as `table-cell`, more than 8 body rows as `table-rows`, a list after a table as `table-then-list`, and a code span with a run past 30 characters as `table-token`. None sets the exit code.
37
+ Tables take the four limits in the `markdown-craft` skill's `tables.md`, on the density paths but never `CLAUDE.md`.
38
+
39
+ - A cell past 120 visible characters reports as `table-cell` and a list after a table as `table-then-list`, both under `density`
40
+ - More than 8 body rows reports as `table-rows` and a code span with a run past 30 characters as `table-token`, both under `tables` and neither setting the exit code
38
41
 
39
42
  | Density limit | Finding |
40
43
  | ------------------- | ---------------------------------------------------------- |
41
44
  | Paragraph length | A prose paragraph past 350 characters |
42
45
  | Paragraphs in a row | More than 2 paragraphs with nothing else between them |
43
- | Bullet length | A top-level bullet past 200 characters |
46
+ | Bullet length | A bullet past 200 characters, a nested one on its own |
44
47
  | Bullets in a row | More than 5 plain top-level bullets |
45
48
  | Heading depth | Any heading past H3 |
46
49
  | H3 opening | An H3 whose first block is neither a paragraph nor a table |
50
+ | Table cell | A table cell past 120 visible characters |
51
+ | List after table | A list as the block directly after a table |
52
+
53
+ Five notes fix how the limits count and where they apply.
47
54
 
48
55
  - A paragraph under a list item counts toward that bullet, never as a paragraph
49
56
  - A table, fence, list, heading, or bold section marker ends a run of paragraphs
@@ -8,21 +8,23 @@ kind: reference
8
8
 
9
9
  `canon migrate <verb>` moves a project off a retired name or layout. Each verb reports its plan and writes nothing until `--write`, takes `--json`, and, except `rename`, takes `--root`. A second run rewrites nothing, which confirms the exclusions and markers fired.
10
10
 
11
- | Verb | Moves |
12
- | ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------- |
13
- | `status` | Nothing. It lists every migration the project still needs, in run order. |
14
- | `rename` | The retired `aitk` name. `--scope target` rewrites toolkit-owned folders only. |
15
- | `skill-names` | Plugin skills off their `claude-` and `draft-` prefixes and other retired names, with every citation |
16
- | `records` | Session records from `.claude/` to `.canon/`, with every tracked citation |
17
- | `surface-roots` | `context/`, `wireframes/`, `ARCHITECTURE.md`, `REQUIREMENTS.md`, `DESIGN.md`, and the stamp folder from `.claude/` to `canon/`, by `git mv` |
18
- | `record-tree` | Citations inside `.canon/` folders a session still follows: `diagrams`, `memory`, `plans`, `proposals`, `review`, `tasks`, `teach` |
19
- | `rule-layout` | A flat installed-rule layout onto the `canon/`-wrapped one |
20
- | `scratch-evidence` | A folder a durable record cites out of `.tmp/`, with its citations |
21
- | `record-layout` | Review receipts, memory archives, feedback, renders, picks, and evidence into their current folders |
22
- | `session-defaults` | The seeded session defaults into an existing `.claude/settings.json`: `Agent`, `Task`, and both merge commands denied, auto memory off |
11
+ | Verb | Moves |
12
+ | ------------------ | --------------------------------------------------------------------------------------------------------------- |
13
+ | `status` | Nothing. It lists every migration the project still needs, in run order. |
14
+ | `rename` | The retired `aitk` name. `--scope target` rewrites toolkit-owned folders only. |
15
+ | `skill-names` | Plugin skills off their `claude-` and `draft-` prefixes and other retired names, with every citation |
16
+ | `records` | Session records from `.claude/` to `.canon/`, with every tracked citation |
17
+ | `surface-roots` | Records such as `context/` and `REQUIREMENTS.md`, and the stamp folder, from `.claude/` to `canon/` by `git mv` |
18
+ | `record-tree` | Citations inside the `.canon/` folders a session still follows, listed below the table |
19
+ | `rule-layout` | A flat installed-rule layout onto the `canon/`-wrapped one |
20
+ | `scratch-evidence` | A folder a durable record cites out of `.tmp/`, with its citations |
21
+ | `record-layout` | Review receipts, memory archives, feedback, renders, picks, and evidence into their current folders |
22
+ | `session-defaults` | The seeded session defaults into an existing `.claude/settings.json`, listed below the table |
23
+
24
+ `record-tree` follows citations in `diagrams`, `memory`, `plans`, `proposals`, `review`, `tasks`, and `teach`. `session-defaults` denies `Agent`, `Task`, and both merge commands, and turns auto memory off. The bullets below add detail per verb.
23
25
 
24
26
  - `skill-names` takes no `--scope`, and skips the changelog, eval transcripts, and the pointer each renamed `draft-` skill leaves at its old name
25
- - `surface-roots` leaves `rules/`, `skills/`, `hooks/`, and `settings.json` where Claude Code reads them
27
+ - `surface-roots` moves `context/`, `wireframes/`, `ARCHITECTURE.md`, `REQUIREMENTS.md`, `DESIGN.md`, and the stamp folder, and leaves `rules/`, `skills/`, `hooks/`, and `settings.json` in place
26
28
  - `rule-layout` classifies each flat file against the stamp as clean, edited, or unclaimed. Clean and edited files move untouched, and an unclaimed name stays.
27
29
  - `record-layout` labels each evidence folder `(pick)` or `(evidence)` in the dry run
28
30
  - `session-defaults` adds a key only when absent, merge entries included, and each older project runs it once. `--write` restores a removed `Agent` or `Task` and never removes a deny entry.
@@ -54,6 +54,8 @@ Discover names at runtime rather than hardcoding them.
54
54
  | `canon docs list --json` | Consumer docs plus per-domain context |
55
55
  | `canon audits list --json` | Audits the set runs, the corpus each reads, and whether it gates |
56
56
 
57
+ The table names the verbs, and three notes cover what some of them carry.
58
+
57
59
  - `gov list` expands each stack to its rules and carries `unreferenced`, the rules no stack reaches, which install only through `--add`
58
60
  - `claude skills list` reports shipped skills only. Each carries `family` (or `null`) and `requirement`, and a `false` requirement is a gap to close. `--names` and `--by-family` change the render.
59
61
  - A skill with unparseable frontmatter returns an empty description rather than failing the listing
@@ -62,19 +62,19 @@ The seven `draft-` skills took verb-first names for what each makes. `canon migr
62
62
  | `draft-ready` | `plan-ready` <!-- canon-keep-retired --> |
63
63
  | `draft-screencast` | `script-screencast` <!-- canon-keep-retired --> |
64
64
 
65
+ Replace a citation of a skill with no successor by hand, or delete the sentence.
66
+
65
67
  - `canvas` is now `canvas-board`. The sweep rewrites only `canon:canvas` and `skills/canvas`, so replace a bare prose mention by hand. <!-- canon-keep-retired -->
66
68
  - `draft-ready` is rewritten only as `canon:draft-ready` and `skills/draft-ready`, since bare it also describes a pull request. Replace a bare mention of the skill by hand. <!-- canon-keep-retired -->
67
69
  - `design-extract` and `sketch-design` are replaced by `canon:canvas-board`. <!-- canon-keep-retired -->
68
70
  - `review-branch`, `seed-sync`, `restate-plainly`, `bash-cli-script`, `canon-operator`, and `canon-rollout` have no successor <!-- canon-keep-retired -->
69
71
  - `create-standard`, `markdown-propose`, `memory-review`, `project-commands`, `repo-metadata`, and `ux-walkthrough` have no successor <!-- canon-keep-retired -->
70
72
 
71
- Replace a citation of a skill with no successor by hand, or delete the sentence.
73
+ The `memory` record kind left `canon records`, so `canon records validate memory` refuses as an unknown kind and `canon records migrate` is gone.
72
74
 
73
75
  - `canon repo metadata`, `canon autoship`, and the `120-bash` rule are gone, and `canon gov sync` removes the rule <!-- canon-keep-retired -->
74
76
  - `memory-capture`, the `603-memory` rule, and the `memory` standard are gone, so send a lesson to the context entry that owns the fact <!-- canon-keep-retired -->
75
77
 
76
- The `memory` record kind left `canon records`, so `canon records validate memory` refuses as an unknown kind and `canon records migrate` is gone.
77
-
78
78
  Two held files run, `.husky/post-merge` and `.claude/hooks/pr-create-log.sh`, and a stale copy calls a missing binary or names a removed skill. Resync what the toolkit owns before sweeping what the project wrote, and run the second line once per stack.
79
79
 
80
80
  ```bash
@@ -17,6 +17,8 @@ One warm session holds the cross-feature call and reviews. Cold worker sessions
17
17
  | Planner | One session per row, warm or cold | Measure the row against the tree, write one plan | Enter a worktree, write the board |
18
18
  | Worker | One cold worktree session per feature | Implement, self-check, open PR, answer the reviewer | Write the shared board, merge |
19
19
 
20
+ Each role keeps to its own writes, and five rules cover how the roles meet.
21
+
20
22
  - The orchestrator loads `role-orchestrator`, a worker loads `role-worker` through `auto-ship` Step 0, and a planner and a reviewer load theirs from the launch that dispatches them
21
23
  - The orchestrator decides which rows conflict, what merges first, and whether a row runs at all. Per-row planning can go cold.
22
24
  - A dispatched planner writes only the plan, and reports what the task file got wrong rather than repairing it
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@erclx/canon",
3
3
  "type": "module",
4
- "version": "5.55.0",
4
+ "version": "5.57.0",
5
5
  "description": "Runs your agent's work and keeps its code good, on one setup for every repo.",
6
6
  "license": "MIT",
7
7
  "bin": {