@erclx/canon 5.38.0 → 5.39.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 (149) hide show
  1. package/README.md +1 -1
  2. package/claude/.claude-plugin/plugin.json +1 -1
  3. package/claude/skills/api-design/SKILL.md +12 -9
  4. package/claude/skills/auto-ship/SKILL.md +43 -23
  5. package/claude/skills/backlog-triage/SKILL.md +62 -53
  6. package/claude/skills/backlog-triage/references/apply.md +69 -0
  7. package/claude/skills/build-in-slices/SKILL.md +8 -4
  8. package/claude/skills/canon-cli/SKILL.md +5 -1
  9. package/claude/skills/canon-feedback/SKILL.md +18 -8
  10. package/claude/skills/canon-feedback-triage/SKILL.md +10 -3
  11. package/claude/skills/canvas-board/SKILL.md +36 -17
  12. package/claude/skills/ci-workflow/SKILL.md +5 -4
  13. package/claude/skills/code-craft/SKILL.md +10 -6
  14. package/claude/skills/codebase-layout/SKILL.md +3 -5
  15. package/claude/skills/context-fold/REQUIREMENT.md +4 -4
  16. package/claude/skills/context-fold/SKILL.md +42 -23
  17. package/claude/skills/context-fold/references/context-refresh.md +4 -3
  18. package/claude/skills/context-fold/references/context.md +79 -64
  19. package/claude/skills/create-rule/SKILL.md +7 -3
  20. package/claude/skills/create-skill/SKILL.md +27 -7
  21. package/claude/skills/create-skill/references/skill-reference.md +41 -17
  22. package/claude/skills/decision-escalate/SKILL.md +8 -5
  23. package/claude/skills/deploy-app/SKILL.md +1 -1
  24. package/claude/skills/deprecation-migration/SKILL.md +12 -4
  25. package/claude/skills/design-taste/SKILL.md +17 -11
  26. package/claude/skills/docs-sync/REQUIREMENT.md +1 -0
  27. package/claude/skills/docs-sync/SKILL.md +17 -6
  28. package/claude/skills/docs-sync/references/docs.md +54 -21
  29. package/claude/skills/docs-sync/references/readme.md +32 -8
  30. package/claude/skills/document-health/SKILL.md +3 -4
  31. package/claude/skills/draft-and-pick/SKILL.md +73 -47
  32. package/claude/skills/draft-doc/SKILL.md +9 -4
  33. package/claude/skills/draft-doc/references/context.md +4 -4
  34. package/claude/skills/draft-doc/references/docs.md +1 -0
  35. package/claude/skills/draft-doc/references/wiki.md +3 -2
  36. package/claude/skills/draft-figure/SKILL.md +9 -7
  37. package/claude/skills/draft-identity/SKILL.md +24 -52
  38. package/claude/skills/draft-identity/references/card-route.md +46 -0
  39. package/claude/skills/draft-ready/SKILL.md +19 -7
  40. package/claude/skills/draft-screencast/SKILL.md +6 -112
  41. package/claude/skills/draft-screencast/references/beats-template.md +119 -0
  42. package/claude/skills/draft-slides/SKILL.md +7 -4
  43. package/claude/skills/git-branch/SKILL.md +3 -3
  44. package/claude/skills/git-commit/SKILL.md +5 -3
  45. package/claude/skills/git-followup/SKILL.md +16 -9
  46. package/claude/skills/git-issue/SKILL.md +6 -5
  47. package/claude/skills/git-pr/SKILL.md +56 -44
  48. package/claude/skills/git-ship/SKILL.md +43 -34
  49. package/claude/skills/git-ship/references/ci-watch.md +31 -0
  50. package/claude/skills/git-split/SKILL.md +28 -100
  51. package/claude/skills/git-split/references/independent.md +40 -0
  52. package/claude/skills/git-split/references/stacked.md +73 -0
  53. package/claude/skills/git-stage/SKILL.md +9 -7
  54. package/claude/skills/git-worktree/SKILL.md +27 -49
  55. package/claude/skills/git-worktree/references/cleanup.md +55 -0
  56. package/claude/skills/markdown-craft/SKILL.md +2 -2
  57. package/claude/skills/markdown-craft/references/markdown.md +82 -53
  58. package/claude/skills/plan-feature/SKILL.md +52 -46
  59. package/claude/skills/plan-feature/references/batches.md +46 -0
  60. package/claude/skills/plan-groundwork/SKILL.md +60 -74
  61. package/claude/skills/plan-groundwork/references/output.md +48 -0
  62. package/claude/skills/plan-intake/SKILL.md +28 -21
  63. package/claude/skills/plan-intake-answer/SKILL.md +14 -13
  64. package/claude/skills/read-frames/SKILL.md +2 -0
  65. package/claude/skills/record-screencast/SKILL.md +31 -11
  66. package/claude/skills/review-address/SKILL.md +76 -158
  67. package/claude/skills/review-address/references/rebase-only.md +34 -0
  68. package/claude/skills/review-craft/SKILL.md +27 -11
  69. package/claude/skills/review-pr/SKILL.md +91 -40
  70. package/claude/skills/review-ui/SKILL.md +62 -37
  71. package/claude/skills/review-ui/references/hosted-preview.md +30 -0
  72. package/claude/skills/role-orchestrator/SKILL.md +105 -74
  73. package/claude/skills/role-orchestrator/references/orchestrator-filing.md +26 -0
  74. package/claude/skills/role-planner/SKILL.md +66 -64
  75. package/claude/skills/role-reviewer/SKILL.md +57 -46
  76. package/claude/skills/role-worker/SKILL.md +68 -63
  77. package/claude/skills/search-craft/SKILL.md +7 -5
  78. package/claude/skills/session-compact/SKILL.md +16 -11
  79. package/claude/skills/session-map/SKILL.md +31 -10
  80. package/claude/skills/session-relay/SKILL.md +32 -65
  81. package/claude/skills/session-resume/SKILL.md +18 -13
  82. package/claude/skills/session-worktree/SKILL.md +70 -42
  83. package/claude/skills/systematic-debugging/SKILL.md +6 -1
  84. package/claude/skills/target-check/SKILL.md +13 -6
  85. package/claude/skills/target-setup/SKILL.md +39 -27
  86. package/claude/skills/task-board/SKILL.md +68 -60
  87. package/claude/skills/task-board/references/create-report.md +36 -0
  88. package/claude/skills/task-complete/SKILL.md +20 -18
  89. package/claude/skills/teach-workspace/SKILL.md +61 -33
  90. package/claude/skills/test-craft/SKILL.md +2 -1
  91. package/claude/skills/test-first/SKILL.md +15 -9
  92. package/claude/skills/ui-checklist/SKILL.md +18 -16
  93. package/claude/skills/ux-audit/SKILL.md +9 -10
  94. package/claude/skills/ux-measure/SKILL.md +22 -18
  95. package/claude/skills/video-craft/SKILL.md +15 -7
  96. package/claude/skills/write-human/SKILL.md +9 -1
  97. package/claude/skills/youtube-transcripts/SKILL.md +2 -1
  98. package/docs/agents/context-audit-checks.md +19 -1
  99. package/docs/agents/context-audit.md +2 -2
  100. package/docs/agents/driver.md +1 -1
  101. package/docs/agents/hooks.md +21 -1
  102. package/docs/agents/index.md +10 -14
  103. package/docs/agents/indexes.md +25 -29
  104. package/docs/agents/install-and-sync.md +124 -235
  105. package/docs/agents/markdown-audit-density.md +39 -0
  106. package/docs/agents/markdown-audit-weight.md +9 -7
  107. package/docs/agents/markdown-audit.md +18 -14
  108. package/docs/agents/migrate.md +41 -16
  109. package/docs/agents/output-shape.md +60 -45
  110. package/docs/agents/overview.md +36 -12
  111. package/docs/agents/routing.md +1 -1
  112. package/docs/agents/rule-citations.md +1 -1
  113. package/docs/agents/skills-reach.md +1 -1
  114. package/docs/agents/targets.md +25 -77
  115. package/docs/target/migrations.md +1 -1
  116. package/docs/target/projects.md +2 -2
  117. package/docs/workflow/ai-workflow.md +2 -2
  118. package/docs/workflow/parallel-features.md +2 -2
  119. package/docs/workflow/skill-map.md +1 -1
  120. package/docs/workflow/visual-design-workflow.md +1 -1
  121. package/package.json +1 -1
  122. package/src/commands/claude.ts +1 -1
  123. package/src/commands/context.ts +106 -7
  124. package/src/commands/hooks.ts +63 -0
  125. package/src/commands/markdown.ts +169 -32
  126. package/src/context/audit.ts +256 -5
  127. package/src/context/classify/prompts.ts +1 -1
  128. package/src/context/gate.ts +23 -7
  129. package/src/context/shape-gated.ts +28 -0
  130. package/src/design/document.ts +1 -1
  131. package/src/design/tokens.ts +1 -1
  132. package/src/gate/measures.ts +15 -190
  133. package/src/gate/stages.ts +7 -23
  134. package/src/hooks/reply-links.ts +110 -0
  135. package/src/markdown/density.ts +258 -0
  136. package/src/markdown/gate.ts +57 -18
  137. package/src/markdown/reference-shape.ts +103 -0
  138. package/src/markdown/scope.ts +174 -0
  139. package/src/markdown/structure.ts +9 -59
  140. package/src/shipped/references.ts +1 -1
  141. package/tooling/claude/seeds/.claude/hooks/reply-links.sh +72 -0
  142. package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +22 -1
  143. package/tooling/claude/seeds/.claude/settings.json +4 -0
  144. package/docs/agents/commands.md +0 -154
  145. package/docs/agents/docs.md +0 -27
  146. package/docs/agents/drift-surfaces.md +0 -201
  147. package/docs/agents/gov-detect.md +0 -47
  148. package/docs/agents/scripting.md +0 -142
  149. package/src/markdown/growth.ts +0 -43
@@ -19,8 +19,8 @@ Format a `## Toolkit feedback` block from the current session, then open it as a
19
19
 
20
20
  From the conversation so far, identify:
21
21
 
22
- - Target project name or kind, never its full path. The path names a folder on one machine and says nothing a triage session can route on, where the project's own name does. Name a private project by its kind instead, such as `a Next.js app`, since the report leaves the machine.
23
- - Toolkit surface and its type (plugin skill, tooling config, governance rule, seed, or CLI). The type leads the `### Surface` field, ahead of the first comma, because the CLI picks the issue's domain labels from that text alone.
22
+ - Target project name or kind, never its path, which names one machine's folder and nothing triage routes on. Name a private project by kind, such as `a Next.js app`, since reports leave the machine.
23
+ - Toolkit surface and its type (plugin skill, tooling config, governance rule, seed, or CLI). The type leads `### Surface`, ahead of the first comma, since the CLI labels from it alone.
24
24
  - Specific toolkit file or name when the session cites one
25
25
 
26
26
  ### Behavior and fix
@@ -40,14 +40,22 @@ From the same conversation, identify:
40
40
 
41
41
  Format as a single fenced markdown block, one `###` heading per field. Read `${CLAUDE_SKILL_DIR}/references/template.md` on reaching this point for the block and each field's fallback.
42
42
 
43
- `canon feedback` refuses a report missing `### Surface`, `### Observed`, or `### Proposed fix`, naming the one it did not find. `### From project`, `### Expected`, and `### Repro` are optional, so write the literal fallback the template shows rather than dropping the heading, which is what keeps a field the session cannot fill reading as absent instead of unreported.
43
+ ### Required and optional fields
44
44
 
45
- `### Suggested shape`, `### Why`, and `### Links` are optional the other way. Omit the heading when the session has nothing for it and write no fallback, since a report filed without them is complete and a placeholder would read as a reporter who had nothing to say.
45
+ The fields fall into three groups, and each treats a missing value differently.
46
46
 
47
- Headings rather than bold labels, because a GitHub issue form renders a submitted field as `### <label>`. One shape reaches the toolkit whichever route a report takes, and the CLI parses both with one parser. The retired `**Surface:**` form is refused rather than accepted, so a block carrying it has to be rewritten.
47
+ | Fields | When the session has nothing |
48
+ | ------------------------------------------------- | ----------------------------------------------------------------------------------- |
49
+ | `### Surface`, `### Observed`, `### Proposed fix` | Required, and `canon feedback` refuses a report missing one, naming it |
50
+ | `### From project`, `### Expected`, `### Repro` | Write the template's literal fallback, so the field reads as absent, not unreported |
51
+ | `### Suggested shape`, `### Why`, `### Links` | Omit the heading with no fallback, since a placeholder reads as nothing to say |
48
52
 
49
53
  Keep Observed and Expected to one or two lines each, so the report scans. Length belongs in Proposed fix, Suggested shape, and Why.
50
54
 
55
+ ### Headings, not bold labels
56
+
57
+ A GitHub issue form renders a submitted field as `### <label>`, so one shape reaches the toolkit whichever route a report takes, and the CLI parses both with one parser. The retired `**Surface:**` form is refused, so a block carrying it has to be rewritten.
58
+
51
59
  The issue body is the request. Put everything the toolkit needs to act on it there, since a comment is easy to miss and a body and a comment that differ leave triage choosing. A comment carries only what happens after filing.
52
60
 
53
61
  ## Step 2: ship to the toolkit
@@ -70,12 +78,14 @@ cat <<'EOF' | canon feedback
70
78
  EOF
71
79
  ```
72
80
 
73
- The CLI opens a GitHub issue on the toolkit repo, labeled `feedback` and each domain label the surface type names, such as `skills` for a plugin skill, and prints the issue URL, which this skill reports back on its own line. It needs `gh` authenticated. `git-issue` is not the route, since it files on the current repository and this report belongs on the toolkit's.
81
+ The CLI opens a GitHub issue on the toolkit repo, labeled `feedback` and each domain label the surface type names, such as `skills` for a plugin skill, and prints the issue URL for this skill to report on its own line. It needs `gh` authenticated, and `git-issue` is not the route, since it files on the current repository.
82
+
83
+ ### Reading the outcome
74
84
 
75
85
  Read the outcome off stdout, never off the exit code, since a shell wrapper can flatten it. Stdout takes one of three shapes:
76
86
 
77
87
  - A line opening with `https://` is the filed issue. Report the URL.
78
- - A block opening with `## Toolkit feedback` is a failed call. The reason is on stderr, so show the block in chat with it and `📋 Paste this into an issue at https://github.com/erclx/canon/issues/new`.
88
+ - A block opening with `## Toolkit feedback` is a failed call. Show it in chat with the stderr reason and `📋 Paste this into an issue at https://github.com/erclx/canon/issues/new`.
79
89
  - Empty stdout is a refusal. Step 3 says how to repair it from stderr.
80
90
 
81
91
  If `canon` is not on PATH, fall back: print the block in chat and tell the user `📋 Copy the block above into a toolkit-repo session.`
@@ -85,4 +95,4 @@ If `canon` is not on PATH, fall back: print the block in chat and tell the user
85
95
  A report that was not filed reads one of two ways on stdout, and stderr carries the reason in both:
86
96
 
87
97
  - Empty stdout, with a named missing field on stderr. Add that heading with a real value or its stated fallback, then re-run. Do not report the defect as filed.
88
- - The block on stdout, with `gh` absent or its call failed on stderr. The stderr names which, since installing `gh` and fixing an authenticated call are different repairs. Show the block in chat with the reason and the paste line from Step 2.
98
+ - The block on stdout, with `gh` absent or its call failed on stderr, which names which, since the two repairs differ. Show the block in chat with the reason and the paste line from Step 2.
@@ -11,17 +11,20 @@ Consume the feedback queue that `canon feedback` fills. Each open `feedback` iss
11
11
 
12
12
  The record is an ordinary intake folder at `.canon/intake/<nn>-feedback-triage/`. Read `${CLAUDE_SKILL_DIR}/../plan-intake/references/intake.md` before writing any file in it, since it holds the item format, the frontmatter, the index shape, and the answer contract this skill is bound by.
13
13
 
14
- Run from the toolkit repo root. This skill reads GitHub issues and writes only inside its claimed folder. It posts no comment, close, or label to GitHub.
14
+ - Run from the toolkit repo root
15
+ - Read GitHub issues and write only inside the claimed folder, posting no comment, close, or label to GitHub
15
16
 
16
17
  ## Guards
17
18
 
18
- - Resolve `.canon/tasks/` and `.canon/intake/` at the main worktree root, not `pwd`. Run `git worktree list --porcelain | grep -m 1 '^worktree ' | cut -d' ' -f2-`, falling back to `pwd` outside a git repo.
19
+ - Resolve `.canon/tasks/` and `.canon/intake/` at the main worktree root, from `git worktree list --porcelain | grep -m 1 '^worktree ' | cut -d' ' -f2-`, falling back to `pwd` outside git
19
20
  - If `gh` is not on PATH, stop: `❌ gh CLI not found. Install it to read feedback issues.`
20
21
  - If `gh auth status` fails, stop: `❌ gh is not authenticated. Run gh auth login.`
21
22
  - If no open `feedback` issues exist, stop: `✅ No open feedback issues.`
22
23
 
23
24
  ### Slots and records
24
25
 
26
+ Two more guards hold through every step.
27
+
25
28
  - Never fill a `You:` slot, and never read an empty one as agreement. Answering runs through `plan-intake-answer` or the operator's own edit.
26
29
  - Branch on each `canon` record's `ok` and `reason` rather than on the exit code, which a shell function wrapping `canon` can flatten to zero.
27
30
 
@@ -45,7 +48,11 @@ Run `canon records ordinal intake feedback-triage --claim --json` and take its `
45
48
 
46
49
  ## Step 4: measure each issue
47
50
 
48
- For each remaining issue, measure its claim against the tree during this pass. Grep for the construct its defect names and count the sites, check whether the behavior it asks for exists, and search the log for a commit or pull request that shipped it under another task. Never carry a figure from the issue forward as current, since it states what was true when it was filed.
51
+ For each remaining issue, measure its claim against the tree during this pass, never carrying a figure from the issue forward, since it states what was true when filed.
52
+
53
+ - Grep for the construct its defect names and count the sites
54
+ - Check whether the behavior it asks for exists
55
+ - Search the log for a commit or pull request that shipped it under another task
49
56
 
50
57
  Classify each against the toolkit's own surfaces:
51
58
 
@@ -37,9 +37,11 @@ canon canvas serve --json
37
37
 
38
38
  Read `url` off the record rather than composing one, since the server walks past a port already in use. Report the refusal and its `reason` when `ok` is false, and stop there.
39
39
 
40
- Then fetch the printed address and check the shell itself, not a capture:
40
+ ### Check the shell
41
41
 
42
- - The body is non-empty and carries a `<script` tag. An empty `200` means the shell failed to build, usually a dependency missing from the canvas tool's install, and every capture still passes because captures go through the frame route alone. Report it as a blank shell and stop.
42
+ Fetch the printed address and check the shell itself, not a capture, since every capture goes through the frame route alone and passes on a blank shell.
43
+
44
+ - The body is non-empty and carries a `<script` tag. An empty `200` means the shell failed to build, usually a missing dependency, so report a blank shell and stop.
43
45
  - `<url>/api/pages` answers with JSON listing the pages.
44
46
 
45
47
  Hand the operator the address as a markdown link carrying the URL as its text and its target.
@@ -48,22 +50,36 @@ Hand the operator the address as a markdown link carrying the URL as its text an
48
50
 
49
51
  - Add a page for each decision being drafted: `canon canvas page add <page> --json`.
50
52
  - Follow the house style in `${CLAUDE_SKILL_DIR}/references/canvas.md` before drafting an explanation frame.
51
- - Add each frame through the verb, which writes the starting file and its box in one locked step: `canon canvas frame add <page> <frame> --width <px> --height <px> --json`. Give the width the frame should render at, since a capture and the canvas both render at it. The verb places the frame after the last one, and a position the operator asks for goes through `frame move`.
53
+ - Add each frame with `canon canvas frame add <page> <frame> --width <px> --height <px> --json`, which writes the file and its box in one locked step
54
+
55
+ Give each frame the width it should render at, since a capture and the canvas both render at it. The verb places the frame after the last one, and a position the operator asks for goes through `frame move`.
52
56
 
53
57
  ### Layout and naming
54
58
 
55
- - Lay frames out with `canon canvas frame move <page> <frame> --x <px> --y <px> --json` rather than writing `layout.json` by hand, since the operator's drags write the same file under a lock.
59
+ Lay frames out through the verbs rather than by hand, since the operator's drags write the same `layout.json` under a lock.
60
+
61
+ - Move a frame with `canon canvas frame move <page> <frame> --x <px> --y <px> --json`
56
62
  - Name pages and frames for what they hold, such as `pricing` and `pricing-dense`, so the operator can say which one by name.
57
- - After an insert or a resize, re-lay the page with `canon canvas arrange <page> --json`. It keeps the rows the operator dragged, places each on the standard gap, and drops layout entries whose frame file is gone. `--check` reports without writing.
63
+ - After an insert or a resize, re-lay the page with `canon canvas arrange <page> --json`. It keeps dragged rows, sets the standard gap, and drops entries whose file is gone.
64
+ - Run `arrange --check` to report without writing
58
65
 
59
66
  ## Step 3: edit a frame through its file
60
67
 
61
68
  Write the frame's whole document to the `path` the add verb reported. The open canvas reloads the frame when its file changes.
62
69
 
63
- - From a linked worktree, `Edit` and `Write` refuse a main-root path. Write the whole file through one plain `Bash` heredoc instead, the route `session-worktree` states for a main-root write, and never take the redirect to a worktree copy.
64
- - Change one property of one element with `canon canvas edit <page>/<frame> --element <index> --set <property>=<value> --json` when the set it accepts covers the change, since it leaves every other byte as it was.
65
- - Fit the box to the content once the write lands: `canon canvas fit <page>/<frame> --json`. Read each row's `wide` and `font`. A `wide` frame needs its box widened, which fit never does, and a `font` frame names a family the canvas does not serve, so set its text to a served face and fit again. A fit that grew a frame leaves the rows below overlapped until `canvas arrange` runs.
66
- - Use the project's custom properties for every value the token stylesheet defines. The record from `serve` names the token source under `tokens`, and a `none` source means frames render unstyled, so say so rather than inventing values to cover it.
70
+ - From a linked worktree, `Edit` and `Write` refuse a main-root path. Write the whole file through one plain `Bash` heredoc, the route `session-worktree` states, never a worktree copy.
71
+ - Change one property with `canon canvas edit <page>/<frame> --element <index> --set <property>=<value> --json` when its set covers the change, since it leaves every other byte as it was
72
+ - Use the project's custom properties for every value the token stylesheet defines. The `serve` record names the source under `tokens`, and `none` means frames render unstyled, so say so.
73
+
74
+ ### Fit the box
75
+
76
+ Fit the box to the content once the write lands, with `canon canvas fit <page>/<frame> --json`, and read each row's `wide` and `font`.
77
+
78
+ - A `wide` frame needs its box widened, which fit never does
79
+ - A `font` frame names a family the canvas does not serve, so set its text to a served face and fit again
80
+ - A fit that grew a frame leaves the rows below overlapped until `canvas arrange` runs
81
+
82
+ ### Mark the frame
67
83
 
68
84
  Mark the frame before the first write, so the operator sees which frame is being worked on before anything lands, and clear the mark once the edits to it are done:
69
85
 
@@ -74,7 +90,7 @@ canon canvas editing <page>/<frame> --done --json
74
90
 
75
91
  - A mark lapses after five minutes, so mark the frame again during a longer edit.
76
92
  - Clear it on every exit from the edit, including one that stopped on a refusal. Clearing a frame that holds no mark succeeds.
77
- - When the mark call fails with `unknown command 'editing'`, the installed CLI predates the mark, so go on without it rather than stopping. Never run `canvas edit` in its place, whatever the error suggests, since that verb writes the frame.
93
+ - On `unknown command 'editing'`, the CLI predates the mark, so go on without it. Never run `canvas edit` in its place, since that verb writes the frame.
78
94
 
79
95
  ## Step 4: read what the operator pointed at
80
96
 
@@ -85,7 +101,7 @@ canon canvas selection --json
85
101
  ```
86
102
 
87
103
  - `selection: null` means nothing is selected or the selected frame is gone. Ask which one rather than guessing.
88
- - An `element` carrying `stale: true` was picked against an earlier version of the file, so its `index` may now land on a different element. Treat the pick as unknown and ask the operator to pick again, rather than acting on the index or matching its `tag` and `text` by eye.
104
+ - An `element` carrying `stale: true` was picked against an earlier file, so its `index` may land elsewhere. Ask the operator to pick again rather than matching its `tag` and `text` by eye.
89
105
  - A fresh `element` gives the `index` that `canvas edit` takes.
90
106
 
91
107
  ## Step 5: respect the operator's inspector edits
@@ -98,17 +114,20 @@ The operator restyles elements from the inspector, and each edit lands as inline
98
114
 
99
115
  ## Step 6: capture finished work
100
116
 
101
- - Capture a frame once it is finished: `canon canvas capture <page>/<frame> --json`. Each PNG is the frame's whole document, so its height follows the content rather than the box.
102
- - Capture a whole page once its frames are finished: `canon canvas capture <page> --composite --json`. The image shows each frame clipped to its box at its layout position.
103
- - Capture once per finished frame or page, not after every edit. The live canvas is the working view, and a capture is the record handed on.
117
+ Capture once per finished frame or page, not after every edit. The live canvas is the working view, and a capture is the record handed on.
118
+
119
+ - Capture a frame with `canon canvas capture <page>/<frame> --json`. Each PNG is the whole document, so its height follows the content rather than the box.
120
+ - Capture a page with `canon canvas capture <page> --composite --json`, which shows each frame clipped to its box at its layout position
104
121
  - Read each `path` off the record rather than composing one.
105
- - A capture refused because a font is not installed names the family it read off the frame's text. Set that text's `font-family` to a named family the machine has, never a generic keyword such as `sans-serif`, and capture again, rather than reporting the frame as captured.
122
+
123
+ A capture refused because a font is not installed names the family it read off the frame's text. Set that text's `font-family` to a named family the machine has, never a generic keyword such as `sans-serif`, and capture again rather than reporting the frame as captured.
106
124
 
107
125
  ## Step 7: carry a picked direction back
108
126
 
109
- When the operator picks a frame, the decision leaves the canvas.
127
+ When the operator picks a frame, the decision leaves the canvas. Leave structure and layout on the canvas, and name the frame in the plan that builds it.
110
128
 
111
- - Carry visual values, being color, type, spacing, and radius, into the stylesheet the design document's lead names, and the intent behind them into the document's sections under the `design.md` standard. A project with no stylesheet yet takes the values under `.claude/design/project/` after `canon design install`, and the lead names that path. Leave structure and layout on the canvas, and name the frame in the plan that builds it.
129
+ - Carry color, type, spacing, and radius into the stylesheet the design document's lead names, and their intent into its sections under the `design.md` standard
130
+ - A project with no stylesheet yet takes the values under `.claude/design/project/` after `canon design install`, and the lead names that path
112
131
  - Name the frame the decision came from in the reply, and leave the frame on the canvas until the operator clears it.
113
132
  - Never cite a frame path from a tracked file. The folder is gitignored, so the citation resolves on this machine alone.
114
133
 
@@ -11,7 +11,8 @@ Generate GitHub Actions workflow files for CI pipelines. Enforce parallel job ex
11
11
 
12
12
  ## Guards
13
13
 
14
- - A request for what runs inside a deploy, publish, or release job stops at the gate. Credentials, environments, and deploy targets are invisible to this skill, so emit the job with its `needs` wiring and a placeholder step, then name what the caller fills in. Never guess a deploy command.
14
+ - A request for what runs inside a deploy, publish, or release job stops at the gate, since credentials, environments, and targets are invisible here. Never guess a deploy command.
15
+ - Emit such a job with its `needs` wiring and a placeholder step, then name what the caller fills in
15
16
  - The build, test, and deploy commands belong to the project. Read them from its scripts rather than asserting a second copy in the workflow.
16
17
 
17
18
  ## Workflow setup
@@ -26,9 +27,9 @@ Generate GitHub Actions workflow files for CI pipelines. Enforce parallel job ex
26
27
 
27
28
  ## Job granularity
28
29
 
29
- - Start a new pipeline with the checks that share setup in one job: static analysis, unit tests, and build. A project with no run history has nothing to measure, and one job is the shape that costs least to reverse.
30
- - Keep them in one job while the gate runs under roughly two minutes end to end. Each extra job repays checkout, dependency install, and toolchain setup before it reaches a stage, so a split at that duration costs more than the parallelism returns.
31
- - Split once a run log puts the gate past that, then apply the dependency rules below. The run log is the revision trigger rather than the entry condition, since repository size and stage count answer nothing.
30
+ - Start a new pipeline with static analysis, unit tests, and build in one job, since they share setup. A project with no run history has nothing to measure, and one job costs least to reverse.
31
+ - Keep them in one job while the gate runs under roughly two minutes. Each extra job repays checkout, dependency install, and toolchain setup, so a split at that duration costs more than it returns.
32
+ - Split once a run log puts the gate past that, then apply the dependency rules below. The run log is the trigger, since repository size and stage count answer nothing.
32
33
  - Give E2E, release, and deploy their own jobs from the start. Each carries a data dependency or a gate, so this rule never folds them into the check job.
33
34
 
34
35
  ## Job dependencies
@@ -7,7 +7,7 @@ metadata:
7
7
 
8
8
  # Code craft
9
9
 
10
- A session writing code takes its shape from whatever sits nearby. It copies a function rather than changing the one it found, spreads one decision across the files it happened to open, and adds a class hierarchy for a second case that may never come. Each choice reads fine in the diff and costs the next change. This skill carries the judgment at the moment the shape is chosen, before the body exists.
10
+ A session writing code takes its shape from what sits nearby. It copies a function rather than changing it, spreads one decision across the files it opened, and builds a hierarchy for a case that may never come. Each reads fine in the diff and costs the next change. This skill carries the judgment as the shape is chosen, before the body exists.
11
11
 
12
12
  Load it before writing a new function, class, or module, and before extracting, abstracting, or copying existing code. Skip it for a change that fills in a body whose shape is already fixed.
13
13
 
@@ -24,7 +24,7 @@ Good design is design that makes the likely change cheap. Judge a shape by the c
24
24
  A unit is worth having when its interface is much simpler than what it does, so a caller learns a little and gets a lot.
25
25
 
26
26
  - Add a function or a class only when its name and parameters are easier to hold than its body. One that forwards its arguments to another call with nothing added is a pass-through, so inline it.
27
- - Split a module by the decision it hides, such as a file format, a storage choice, or a pricing rule, rather than by processing step. A split by step makes every change to one decision touch every step.
27
+ - Split a module by the decision it hides, such as a file format, a storage choice, or a pricing rule, not by processing step, which makes one decision's change touch every step
28
28
  - Keep a decision in one unit, so changing it opens one file. A decision whose details leak into its callers is not hidden, whatever the folder says.
29
29
  - Prefer one longer function a reader can follow top to bottom over many tiny ones they have to stitch back together.
30
30
 
@@ -32,9 +32,9 @@ A unit is worth having when its interface is much simpler than what it does, so
32
32
 
33
33
  Each principle below has a case where the other side wins. State which case you are in before following either.
34
34
 
35
- - **One piece of knowledge, one place, against false sharing.** Merge two copies when they encode the same rule, so changing the rule means changing both. Leave them apart when they only look alike and would change for different reasons, since merging them couples two things that drift.
36
- - **Build only what is asked, against seams that ease change.** Build no capability for a feature nobody has asked for. A refactor, a test, or a parameter that makes the asked-for code easier to change is not speculative, and building it is not a breach.
37
- - **One reason to change, against too many pieces.** Split a unit when two unrelated changes would both land in it. Stop splitting when the pieces only make sense read together, since a reader then rebuilds the whole across files.
35
+ - **One piece of knowledge, one place, against false sharing.** Merge two copies encoding one rule, so a change never misses one. Leave apart two that only look alike, since merging couples them.
36
+ - **Build only what is asked, against seams that ease change.** Build no capability nobody asked for. A refactor, test, or parameter easing change to the asked-for code is not speculative.
37
+ - **One reason to change, against too many pieces.** Split a unit two unrelated changes would both land in. Stop when the pieces only make sense together and a reader rebuilds the whole.
38
38
 
39
39
  ## Reach for a pattern only past its wrong case
40
40
 
@@ -51,7 +51,7 @@ A pattern earns its indirection only when the problem it solves is present now.
51
51
 
52
52
  ## Pass hidden inputs in
53
53
 
54
- - Pass the clock, the environment, randomness, and any global into the code that reads them, rather than reaching for them inside. A function that reads the time itself cannot be tested at a chosen time.
54
+ - Pass the clock, the environment, randomness, and any global into the code that reads them, rather than reaching for them inside, since a function reading the time cannot be tested at a chosen one
55
55
  - Keep business rules free of transport and storage code, so a rule can be read and tested without a request or a database.
56
56
  - Skip ports and adapters for an application that only reads and writes records. The layers cost more than the change they protect against.
57
57
 
@@ -86,6 +86,8 @@ Read `${CLAUDE_SKILL_DIR}/references/adopted.md` only when extending this guidan
86
86
 
87
87
  ### Defaults and fixes
88
88
 
89
+ Defaults and fixes carry their own signs.
90
+
89
91
  - You wrote a default value, a threshold, or a fallback the task never named.
90
92
  - A fix is adding a special case, a catch, or a disabled check rather than changing the code that misbehaved.
91
93
  - The code reads the current time, an environment variable, or a global from inside a rule.
@@ -101,6 +103,8 @@ Check each line against the code the change produced. A line answering no is fix
101
103
 
102
104
  ### Inputs, scope, and fixes
103
105
 
106
+ Check the inputs, the scope, and the fixes the same way.
107
+
104
108
  - Clock, environment, and global reads are passed in rather than taken inside a rule.
105
109
  - The diff holds no feature, option, or default the task did not ask for or state.
106
110
  - Every fix changes the code that misbehaved rather than silencing it.
@@ -7,11 +7,9 @@ metadata:
7
7
 
8
8
  # Codebase layout
9
9
 
10
- A session placing a new file copies the folder next to it, so a flat folder stays flat until a refactor pays to split it. In one target, two source folders grew to 46 and 36 flat files under installed rules against it, and the split cost a pull request touching 98 files. This skill carries the placement call to the moment the path is written, which is the one moment it is cheap.
10
+ A session placing a new file copies the folder next to it, so a flat folder stays flat until a refactor pays to split it. In one target, two folders grew to 46 and 36 flat files under rules against it, and the split touched 98 files. This skill carries the placement call to the moment the path is written, the one moment it is cheap.
11
11
 
12
- Load it before writing a new path into a plan, not after. A worker copies the path the plan gives it, so the placement is settled once the plan is.
13
-
14
- Skip it when every path the work names already exists.
12
+ Load it before writing a new path into a plan, not after, since a worker copies the path the plan gives it. Skip it when every path the work names already exists.
15
13
 
16
14
  ## Read the project's strategy first
17
15
 
@@ -33,7 +31,7 @@ Skip it when every path the work names already exists.
33
31
 
34
32
  ## Split before the file lands
35
33
 
36
- - Split a folder when the new file brings a second role into it, before the file lands rather than in a later refactor. The split that touched 98 files would have touched a handful when the folder held eleven.
34
+ - Split a folder when the new file brings a second role into it, before the file lands rather than in a later refactor. The 98-file split would have touched a handful when the folder held eleven.
37
35
  - Treat roughly ten files as a prompt to look, not a gate. A folder holding one role can stay flat at any size, and a folder mixing two roles is worth splitting at six.
38
36
  - Give a new role a named folder in the plan, rather than dropping its first file beside the nearest neighbor.
39
37
 
@@ -7,7 +7,7 @@ description: What the context-entry fold is for, the gaps it closes, and why it
7
7
 
8
8
  ## Gap
9
9
 
10
- Without this skill, the context entries describe the repository the session opened with. A decision a plan settled mid-cycle lives only in the conversation and dies with it, and an entry naming a module the diff rewrote keeps stating what the module used to do.
10
+ Without this skill, the context entries describe the repository the session opened with. An entry keeps listing a folder the diff moved and a trap the diff fixed, so it states what the repository used to be.
11
11
 
12
12
  The trigger side carries a gap of its own. "Sync the docs" names either corpus to the person saying it, so a description leaving its corpus to the opening clause alone competes with its public-facing sibling on nothing the routing field states, and the context folder the request was about goes untouched.
13
13
 
@@ -20,9 +20,9 @@ This skill writes canonical docs at the end of a long build. An appended figure,
20
20
  ## Must
21
21
 
22
22
  - Name the context entries in a trigger phrase rather than in the opening clause alone, so a bare request to sync the docs separates this skill from `docs-sync` on something both descriptions state
23
- - Take decisions from the session and the refresh scope from the diff
23
+ - Take the refresh scope from the diff, and from the session only the requirements or direction change the report names
24
24
  - Write tracked docs at the current worktree root, since only that copy commits with the branch
25
- - Write a decision to the domain context entry it constrains, whatever other domains its reasoning touches, so a decision has one home that loads on demand
25
+ - Write an entry only when the diff adds, moves, or removes a folder, makes a folder's bullet untrue, or changes a trap, and never write a decision, which the pull request records
26
26
  - Report a requirements or direction change in one line naming `document-health`, rather than writing it, so the identity record changes only when the operator reviews it
27
27
  - Close on an audit of what the fold touched, running `canon context audit` and reporting the findings on files this run wrote or the diff carries
28
28
  - Classify the fold's whole diff baseline through `canon context classify diff`, calling the verb rather than reimplementing its pattern or its prompt in the skill body, since an earlier commit on the branch carries a doc edit the fold is equally responsible for
@@ -48,7 +48,7 @@ This skill writes canonical docs at the end of a long build. An appended figure,
48
48
  ## Guards
49
49
 
50
50
  - Neither a `canon/` nor a `.claude/` directory: stop and name the command that sets one up
51
- - No session divergence and no diff a context entry could describe: stop with a pass, since both conditions have to hold
51
+ - No direction change in the session and no diff a context entry could describe: stop with a pass, since both conditions have to hold
52
52
 
53
53
  ## Out of scope
54
54
 
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: context-fold
3
- description: Folds a session's decisions and its diff into the project's context entries, then audits what it touched. Use when asked to "fold the session into context", "update the context entries", "refresh the context folder", when design or requirements changed mid-cycle, after a pivot, or before shipping. Do NOT use for `README.md` or `docs/`, which is `docs-sync`, or to mark a shipped task's outcomes on the board, which is `task-complete`.
3
+ description: Folds a branch's diff into the project's context entries, rewriting a folder or a gotcha the diff left untrue, then audits what it touched. Use when asked to "fold the session into context", "update the context entries", "refresh the context folder", when design or requirements changed mid-cycle, after a pivot, or before shipping. Do NOT use for `README.md` or `docs/`, which is `docs-sync`, or to mark a shipped task's outcomes on the board, which is `task-complete`.
4
4
  metadata:
5
5
  family: ship
6
6
  ---
@@ -23,58 +23,77 @@ git merge-base HEAD origin/main 2>/dev/null || git merge-base HEAD main 2>/dev/n
23
23
 
24
24
  Take the union of `git diff --name-only <base> HEAD`, `git diff --name-only HEAD`, and `git ls-files --others --exclude-standard`. Read content with `git diff <base> HEAD` and `git diff HEAD`.
25
25
 
26
- Prefer `origin/main` over local `main`. On `main` itself the local ref resolves to HEAD, so every committed change drops out of the set and the skill goes blind to the work it is meant to read.
27
-
28
- The baseline is unusable when no merge base resolves against either ref, or when the base came from local `main` and equals HEAD. On an unusable baseline, read `${CLAUDE_SKILL_DIR}/references/unusable-baseline.md` before Step 3 for the set that step takes instead.
26
+ - Prefer `origin/main` over local `main`. On `main` itself the local ref resolves to HEAD, so every committed change drops out of the set and the skill goes blind to its work.
27
+ - The baseline is unusable when no merge base resolves against either ref, or when the base came from local `main` and equals HEAD
28
+ - On an unusable baseline, read `${CLAUDE_SKILL_DIR}/references/unusable-baseline.md` before Step 3 for the set that step takes instead
29
29
 
30
30
  ## Step 1: read the context catalog
31
31
 
32
- Read `canon/context/index.md` from the current worktree root (`pwd`), not the main worktree root, to see which domain entries exist. Entries are tracked files and edits must commit with the branch. A project the surface move has not reached holds the folder under `.claude/` rather than `canon/`, so read and write it at whichever root already carries it.
32
+ Read `canon/context/index.md` from the current worktree root (`pwd`), not the main worktree root, to see which domain entries exist.
33
+
34
+ - Entries are tracked files, so edits must commit with the branch
35
+ - A project the surface move has not reached holds the folder under `.claude/` rather than `canon/`, so read and write it at whichever root already carries it
33
36
 
34
37
  Read `canon/REQUIREMENTS.md` beside it when it exists, for the direction a session decision is measured against. This skill never writes it.
35
38
 
36
39
  ## Step 2: identify what changed
37
40
 
38
- Two sources feed this step. The session carries judgments no diff can show. The diff carries facts about the repository the session may never have mentioned.
39
-
40
- Review the session for decisions that diverged from the original plan:
41
+ Review the session for requirements added, removed, or changed in scope, which After completion reports and this skill never writes. Then resolve the diff baseline and keep the changed paths for Step 3.
41
42
 
42
- - Requirements added, removed, or changed scope
43
- - Technical decisions made or revised
44
- - Design or UX decisions that differ from what the context entries state
43
+ Stop when both of these hold, since a session-only skip would drop the diff-driven refresh for a mechanical change nobody narrated:
45
44
 
46
- Then resolve the diff baseline and keep the changed paths for Step 3.
45
+ - The session shows no direction change
46
+ - The diff carries no path a context entry could describe, being a change confined to the task board, scratch, or files outside source and docs
47
47
 
48
- Stop when the session shows no divergence **and** the diff carries no path a context entry could describe, being a change confined to the task board, scratch, or files outside the repository's source and docs. Report `✅ No context updates needed. Session matched the original plan.` Both conditions have to hold, since a session-only skip would drop the diff-driven refresh for a mechanical change nobody narrated.
48
+ Report `✅ No context updates needed. Session matched the original plan.`
49
49
 
50
50
  ## Step 3: refresh context entries
51
51
 
52
- Skip this step silently when `canon/context/` does not exist or its catalog lists no entries.
52
+ Skip this step silently when `canon/context/` does not exist or its catalog lists no entries. Otherwise read `${CLAUDE_SKILL_DIR}/references/context-refresh.md` for the diff it reads, the widening a removed capability takes, when a new entry is created, and the output lines.
53
53
 
54
- Otherwise read `${CLAUDE_SKILL_DIR}/references/context-refresh.md` for the diff it reads, the widening a removed capability takes, when a new entry is created, and the output lines.
55
-
56
- Write a session decision into the entry for the domain it constrains, under that entry's `## Decisions`, whatever other domains its reasoning touches. Every write follows these rules:
54
+ Write an entry only when the diff adds, moves, or removes a folder, makes a folder's existing bullet untrue, or adds, fixes, or removes a trap, and skip the step otherwise. Never write a decision, which the pull request records. Every write follows these rules:
57
55
 
58
56
  - Never write `canon/REQUIREMENTS.md`. Report a requirements change in After completion.
59
- - Update only the sections affected by session decisions or the diff, and leave unrelated sections alone.
60
- - Rewrite a restated or superseded statement in place rather than appending the replacement beside it. State the fact that stands and keep the earlier reasoning only where it is the alternative that lost, per `${CLAUDE_SKILL_DIR}/references/context.md`.
57
+ - Update only the Layout H3 or the gotcha the trigger names, and leave unrelated sections alone.
58
+ - Edit the bullet that went untrue in place, and never append a correction beside it, per `${CLAUDE_SKILL_DIR}/references/context.md`
61
59
  - Follow `${CLAUDE_SKILL_DIR}/../markdown-craft/references/markdown.md` and the `write-human` skill for all edits.
62
60
 
63
61
  Write each updated file immediately. Claude Code's tool permission dialog is the confirmation gate. Do not wait for user input.
64
62
 
65
63
  ## Step 4: audit what the fold touched
66
64
 
67
- Run the structural audit, then the content classifier, and answer both before the report.
65
+ Run the structural audit, the markdown audit, and the content classifier, and answer each before the report. Findings never stop the fold.
66
+
67
+ ### Structural audit
68
+
69
+ `canon context audit --json` takes a project root rather than a file list, so it reports the whole folder.
68
70
 
69
71
  ```bash
70
72
  canon context audit --json
71
73
  ```
72
74
 
73
- The verb takes a project root rather than a file list, so it reports the whole folder. Report only the findings whose `rel` names a file Step 3 wrote this run or a file the diff carries, one line each as `⚠ Audit: <rel>, <finding>`, and leave the rest unreported, since a finding in an entry this run never touched belongs to whoever next edits it. Repair a finding in a file Step 3 wrote this run when the fix is inside what it already rewrote, such as a bare reference or a missing section it dropped. Report a missing subcommand or a refusal as `⚠ Audit: <message>` and continue.
75
+ - Report only the findings whose `rel` names a file Step 3 wrote this run or a file the diff carries, one line each as `⚠ Audit: <rel>, <finding>`
76
+ - Leave the rest unreported, since a finding in an entry this run never touched belongs to whoever next edits it
77
+ - Repair a finding in a file Step 3 wrote this run when the fix is inside what it already rewrote, such as a bare reference or a missing section it dropped
78
+ - Report a missing subcommand or a refusal as `⚠ Audit: <message>` and continue
79
+
80
+ ### Markdown audit
81
+
82
+ Run `canon markdown audit <path>` over every entry Step 3 wrote this run, and fix each ban and density finding it reports per the markdown standard Step 3 follows.
83
+
84
+ - Fix a finding inside a section Step 3 rewrote, then re-run the audit on that entry until it reports none there
85
+ - Report a finding in a section Step 3 left alone as `⚠ Audit: <rel>, <finding>`, since the rule above keeps unrelated sections as they are
86
+ - Report a refusal as `⚠ Audit: <message>` and continue
87
+
88
+ ### Classify
89
+
90
+ Skip the classifier only when the Diff baseline section could not resolve a base ref at all, reporting `⚠ No diff to scope against. Skipped the classify check.` The verb needs a resolvable ref, which is the one condition it cannot answer for itself.
74
91
 
75
- Then classify. Skip the classifier only when the Diff baseline section could not resolve a base ref at all, reporting `⚠ No diff to scope against. Skipped the classify check.` The verb needs a resolvable ref to run against, which is the one condition it cannot answer for itself.
92
+ Otherwise read `${CLAUDE_SKILL_DIR}/references/classify.md` for the invocation, its scope, the record fields, applying a finding, the one-line keep reason, the unreachable and missing-subcommand lines, and the report shape.
76
93
 
77
- Otherwise read `${CLAUDE_SKILL_DIR}/references/classify.md` for the invocation, its scope, the record fields, applying a finding, the one-line keep reason, the unreachable and missing-subcommand lines, and the report shape. `${CLAUDE_SKILL_DIR}` names this skill's own directory, resolved once when the skill loaded. Read the reference by that resolved path rather than guessing a `.claude/skills/context-fold/references/classify.md` path from the toolkit's install-time layout, which is a different root than the one this skill's own files live under. The invocation is `canon context classify diff --base <base> --json`, and it runs whether or not that reference resolves. Findings never stop the fold.
94
+ - `${CLAUDE_SKILL_DIR}` names this skill's own directory, resolved once when the skill loaded, so read the reference by that resolved path
95
+ - Never guess a `.claude/skills/context-fold/references/classify.md` path from the install-time layout, which is a different root than this skill's own files
96
+ - The invocation is `canon context classify diff --base <base> --json`, and it runs whether or not that reference resolves
78
97
 
79
98
  ## After completion
80
99
 
@@ -13,9 +13,10 @@ When the baseline is unusable, scope this step to the working tree and untracked
13
13
 
14
14
  Reuse the diff from the baseline above, names and content both. For each domain listed in `canon/context/index.md`, read its own entry: a flat `canon/context/<domain>.md`, or, for a domain split into a folder, its `canon/context/<domain>/index.md` and every sibling file that index links. Follow the index rather than globbing the folder, since a folder can hold a file the index does not list yet.
15
15
 
16
- - Map the entry's section headings, whether they sit in one flat file or spread across a nested domain's sibling files, to the changed files. An entry is relevant when its prose references files, modules, or decisions touched by the diff.
17
- - For each relevant entry, rewrite only the sections affected by the diff. Same pattern as `docs-sync`. Do not touch unrelated sections. Never rewrite a split domain's own `index.md` directly, since a regen overwrites it the same way it overwrites the top-level catalog. Rewrite the sibling file the affected section actually lives in instead.
18
- - Rewrite a restated or superseded statement in place rather than appending beside it, the same rule the body states for a session decision.
16
+ - Treat an entry as relevant only when the diff adds, moves, or removes a folder its Layout lists, makes a folder's bullet untrue, or changes a trap it names
17
+ - For each relevant entry, rewrite only the H3 or the gotcha the trigger names, and leave unrelated sections alone
18
+ - Never rewrite a split domain's own `index.md`, which a regen overwrites, and rewrite the sibling file the section lives in instead
19
+ - Edit the bullet that went untrue in place and never append one beside it, the same rule the body states.
19
20
  - Write a reference to another entry as the path that entry sits at, rather than as its bare filename. `${CLAUDE_SKILL_DIR}/references/context.md` states the form, and a bare name strands the reference once a domain splits into subfolders.
20
21
 
21
22
  ## When the diff removes a capability