@erclx/canon 5.48.0 → 5.50.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 (89) hide show
  1. package/claude/.claude-plugin/plugin.json +1 -1
  2. package/claude/skills/auto-ship/SKILL.md +1 -1
  3. package/claude/skills/canvas-board/REQUIREMENT.md +4 -3
  4. package/claude/skills/canvas-board/SKILL.md +8 -9
  5. package/claude/skills/context-fold/references/context.md +4 -3
  6. package/claude/skills/design-record/REQUIREMENT.md +33 -0
  7. package/claude/skills/design-record/SKILL.md +84 -0
  8. package/claude/skills/design-record/references/folder.md +69 -0
  9. package/claude/skills/design-taste/SKILL.md +1 -1
  10. package/claude/skills/markdown-craft/REQUIREMENT.md +1 -0
  11. package/claude/skills/markdown-craft/SKILL.md +6 -1
  12. package/claude/skills/markdown-craft/references/markdown.md +3 -3
  13. package/claude/skills/markdown-craft/references/tables.md +30 -0
  14. package/claude/skills/pick-by-eye/SKILL.md +10 -8
  15. package/claude/skills/plan-feature/SKILL.md +31 -16
  16. package/claude/skills/plan-feature/references/batches.md +5 -5
  17. package/claude/skills/plan-feature/references/plan.md +82 -33
  18. package/claude/skills/plan-groundwork/SKILL.md +8 -0
  19. package/claude/skills/plan-groundwork/references/groundwork.md +2 -1
  20. package/claude/skills/plan-intake/SKILL.md +8 -0
  21. package/claude/skills/plan-intake/references/intake.md +9 -1
  22. package/claude/skills/plan-ready/REQUIREMENT.md +3 -3
  23. package/claude/skills/plan-ready/SKILL.md +3 -3
  24. package/claude/skills/plan-ready/references/assembly.md +7 -7
  25. package/claude/skills/plan-ready/references/ready.md +8 -6
  26. package/claude/skills/review-ui/REQUIREMENT.md +1 -1
  27. package/claude/skills/review-ui/SKILL.md +4 -11
  28. package/claude/skills/review-ui/references/close-out.md +1 -1
  29. package/claude/skills/review-ui/references/drive-copy.md +38 -0
  30. package/claude/skills/review-ui/references/post.md +24 -3
  31. package/claude/skills/review-ui/references/verb-absent.md +18 -0
  32. package/claude/skills/role-orchestrator/SKILL.md +3 -2
  33. package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +1 -1
  34. package/claude/skills/role-orchestrator/references/orchestrator-hand-launch.md +60 -0
  35. package/claude/skills/role-orchestrator/references/orchestrator-launch.md +5 -0
  36. package/claude/skills/role-orchestrator/references/orchestrator-parked.md +1 -1
  37. package/claude/skills/role-orchestrator/references/orchestrator-reviewer-launch.md +1 -1
  38. package/claude/skills/role-planner/SKILL.md +1 -1
  39. package/claude/skills/role-worker/SKILL.md +4 -2
  40. package/claude/skills/session-compact/references/handoff-note.md +3 -1
  41. package/claude/skills/session-map/references/session.md +1 -1
  42. package/claude/skills/session-worktree/SKILL.md +1 -1
  43. package/claude/skills/task-board/references/board.md +2 -2
  44. package/claude/skills/task-board/references/tasks.md +1 -1
  45. package/docs/agents/index.md +1 -1
  46. package/docs/agents/markdown-audit.md +5 -2
  47. package/docs/agents/records.md +1 -1
  48. package/docs/target/migrations.md +7 -0
  49. package/docs/target/projects.md +1 -1
  50. package/docs/workflow/parallel-features.md +2 -2
  51. package/docs/workflow/skill-map.md +2 -1
  52. package/docs/workflow/visual-design-workflow.md +2 -1
  53. package/governance/ledger/ui/design-reference.md +1 -0
  54. package/governance/rules/ui/design-reference.md +1 -0
  55. package/package.json +1 -1
  56. package/src/claude/cases/misc.ts +5 -0
  57. package/src/commands/claude.ts +26 -1
  58. package/src/commands/gate.ts +57 -16
  59. package/src/commands/markdown.ts +98 -19
  60. package/src/commands/pr.ts +411 -23
  61. package/src/commands/records.ts +45 -8
  62. package/src/commands/tasks.ts +12 -0
  63. package/src/context/audit.ts +6 -5
  64. package/src/design/budget.ts +1 -1
  65. package/src/design/components.ts +1 -1
  66. package/src/design/document.ts +1 -1
  67. package/src/design/regen.ts +1 -1
  68. package/src/design/render.ts +1 -1
  69. package/src/gate/hand-suite.ts +52 -0
  70. package/src/gate/measures.ts +9 -2
  71. package/src/gate/sequencer.ts +17 -8
  72. package/src/hooks/post-merge.ts +11 -0
  73. package/src/markdown/gated.ts +5 -7
  74. package/src/markdown/scope.ts +60 -10
  75. package/src/markdown/structure.ts +1 -1
  76. package/src/markdown/tables.ts +150 -0
  77. package/src/pr/drive-copy.ts +218 -0
  78. package/src/pr/local.ts +26 -0
  79. package/src/pr/rest.ts +2 -0
  80. package/src/records/structure.ts +147 -0
  81. package/src/records/validate.ts +113 -12
  82. package/src/tasks/archive.ts +137 -4
  83. package/src/tasks/board.ts +68 -13
  84. package/src/tasks/validate.ts +54 -14
  85. package/tooling/base/configs/.github/workflows/pr-local-preview.yml +1 -1
  86. package/tooling/claude/reference.md +1 -0
  87. package/tooling/claude/seeds/.claude/hooks/standards-audit.sh +11 -1
  88. package/tooling/claude/seeds/CLAUDE.md +9 -0
  89. /package/claude/skills/{canvas-board → design-record}/references/design.md +0 -0
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "canon",
3
3
  "description": "Runs your agent's work and keeps its code good, on one setup for every repo.",
4
- "version": "5.48.0",
4
+ "version": "5.50.0",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -124,7 +124,7 @@ This chain adds one thing. Mark the pull request as a draft as soon as `git-ship
124
124
 
125
125
  ## Step 7: wait for the reviews
126
126
 
127
- Run this step only when the launch named a controlling session, since only a controller dispatches the reviewers. A hand-launched run has nobody reviewing, so it emits the Output block on the CI wake instead of waiting on a pass that cannot arrive.
127
+ Run this step only when the launch named a controlling session, since only a controller dispatches the reviewers. A launch naming no controller has nobody reviewing, so it emits the Output block on the CI wake instead of waiting on a pass that cannot arrive. A `Controller: <sessionId>` line names one, whether the launch was by hand or not.
128
128
 
129
129
  Read review state through `canon pr review-state` alone, since both families post as pull request reviews, and a worker polling issue comments instead stalled with both reviewers idle. Run it in the background with the number Step 6 returned, since the wait outlasts a foreground shell call, and act on the wake.
130
130
 
@@ -9,7 +9,7 @@ description: Scope boundary for driving the local design canvas, and the line be
9
9
 
10
10
  Without this skill, a session asked to draw on the canvas writes frames nothing is serving and reports them drawn. It trusts a passing capture, though a blank shell passes every capture while the operator sees an empty tab. From a linked worktree it writes a copy the canvas never serves, and it captures after every edit.
11
11
 
12
- It reads "this one" from the conversation rather than the operator's selection, or acts on a stale element pick and edits the wrong element. It restyles through a class while the operator's inspector edit sits inline, so the change never shows. A picked frame stays on the canvas as the only record, and the design document never learns it.
12
+ It reads "this one" from the conversation rather than the operator's selection, or acts on a stale element pick and edits the wrong element. It restyles through a class while the operator's inspector edit sits inline, so the change never shows. A picked frame stays on the canvas as the only record, and the project's design record never learns it.
13
13
 
14
14
  ## Must
15
15
 
@@ -17,7 +17,7 @@ It reads "this one" from the conversation rather than the operator's selection,
17
17
  - Pages and frames go through the verbs, so the session and the operator's drags share one writer, and a frame from a linked worktree takes the main-root route
18
18
  - The operator's selection decides what "this one" means, and a stale element pick reads as unknown
19
19
  - A frame's inline styles are read before a restyle, the run names which operator edits it kept and dropped, and capture runs once per finished frame or page
20
- - A picked value lands in the project's stylesheet and its intent in the design document, while a picked layout stays on the canvas for the plan that builds it
20
+ - A picked frame is handed to `design-record` by page and frame, while a picked layout stays on the canvas for the plan that builds it
21
21
 
22
22
  ## Must not
23
23
 
@@ -31,4 +31,5 @@ It reads "this one" from the conversation rather than the operator's selection,
31
31
  - Drafting candidates for a taste decision and taking the pick, which `pick-by-eye` owns
32
32
  - What the canvas verbs do internally, which the CLI's own contract owns
33
33
  - The content format a frame and a layout take, which the canvas standard owns
34
- - Tracing reference images into design values, writing the design document from code, and backing up the canvas folder, which no skill owns
34
+ - Landing a pick in the reference folder and carrying its values into the design document, which `design-record` owns
35
+ - Tracing reference images into design values and backing up the canvas folder, which no skill owns
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: canvas-board
3
- description: Drives the local design canvas, where pages hold HTML frames the operator sees, drags, selects, and edits in the browser. Starts the canvas when it is not running, confirms the live shell loads, makes pages and frames, edits a frame through its file, reads what the operator selected or restyled, captures finished frames, and carries a picked direction into the project's design document. Use when asked to "open the canvas", "put this on the canvas", "draw a frame for X", "change the one I selected", "what did I pick", "capture this frame", or "move that frame on the canvas". Do NOT use to draft candidates for a taste decision, which is `pick-by-eye`.
3
+ description: Drives the local design canvas, where pages hold HTML frames the operator sees, drags, selects, and edits in the browser. Starts the canvas when it is not running, confirms the live shell loads, makes pages and frames, edits a frame through its file, reads what the operator selected or restyled, captures finished frames, and hands a picked frame to `design-record`. Use when asked to "open the canvas", "put this on the canvas", "draw a frame for X", "change the one I selected", "what did I pick", "capture this frame", or "move that frame on the canvas". Do NOT use to draft candidates for a taste decision, which is `pick-by-eye`.
4
4
  metadata:
5
5
  family: decide
6
6
  ---
@@ -16,7 +16,7 @@ Every verb below is `canon canvas`. Run `canon canvas --help` for the verbs and
16
16
  - If `canon` is not on PATH, stop: `❌ canon CLI not found.`
17
17
  - If `canon canvas --help` reports no such command, stop: `❌ The installed canon carries no canvas command. Update the CLI and re-run.`
18
18
  - Write no frame before the canvas is serving and the shell has loaded. A frame nobody can see is a draft reported as delivered.
19
- - Never present a frame as the project's design. The canvas is a drafting surface and the project's design document holds what was decided.
19
+ - Never present a frame as the project's design. The canvas is a drafting surface and the project's design record holds what was decided.
20
20
  - Never promise the canvas survives a lost checkout. Its folder is gitignored and nothing backs it up.
21
21
 
22
22
  ## Step 1: start the canvas and confirm the shell
@@ -122,13 +122,12 @@ Capture once per finished frame or page, not after every edit. The live canvas i
122
122
 
123
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.
124
124
 
125
- ## Step 7: carry a picked direction back
125
+ ## Step 7: hand a picked frame on
126
126
 
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.
127
+ When the operator picks a frame, the decision leaves the canvas. Hand it to `canon:design-record`, which lands the frame in the project's reference folder and carries its values into the design document. Report it rather than proceeding silently when that skill does not resolve.
128
128
 
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
131
- - Name the frame the decision came from in the reply, and leave the frame on the canvas until the operator clears it.
129
+ - Name the page and frame the decision came from in the handoff and the reply, and leave the frame on the canvas until the operator clears it
130
+ - Name the frame in the plan that builds a picked layout, since the layout reaches code through that plan
132
131
  - Never cite a frame path from a tracked file. The folder is gitignored, so the citation resolves on this machine alone.
133
132
 
134
133
  ## Output
@@ -138,7 +137,7 @@ When the operator picks a frame, the decision leaves the canvas. Leave structure
138
137
  Page: <page>, <n> frames
139
138
  Selected: <page>/<frame>, element <index>, or none, or stale
140
139
  Capture: <path of each capture written>
141
- Carried: <the stylesheet and design document the pick went to, the plan that cites the frame, or not yet>
140
+ Handed: <the frame handed to design-record, the plan that cites it, or not yet>
142
141
  ```
143
142
 
144
- Write the canvas line's URL as a markdown link. Omit the capture line when nothing was captured and the carried line when no direction was picked. Emit every path from the project root.
143
+ Write the canvas line's URL as a markdown link. Omit the capture line when nothing was captured and the handed line when no frame was picked. Emit every path from the project root.
@@ -88,9 +88,10 @@ Entries get read top-down and often partially, so the boundary sits above the fo
88
88
 
89
89
  ## The development entry
90
90
 
91
- Only the `development` entry carries this section, as an H3 under `## Layout`. It is not a general-purpose heading for other domains.
91
+ Only the development entry carries this section, as an H3 under `## Layout`. That entry is the flat `development` entry or any entry directly under a `development/` folder, and the heading is not a general-purpose one for other domains.
92
92
 
93
- - `### Scripts`: a table of run commands (command plus purpose). The single discoverable surface for how to run the project. Keep run commands here, not scattered across `CLAUDE.md`.
93
+ - `### Scripts`: run commands as tables of command plus purpose. The single discoverable surface for how to run the project. Keep run commands here, not scattered across `CLAUDE.md`.
94
+ - Group a long set of commands into short tables, each under a lead sentence naming its group, since a table past 8 body rows breaks the table limits. This H3 alone may carry several lead paragraphs.
94
95
 
95
96
  ## What goes in
96
97
 
@@ -157,7 +158,7 @@ A domain outgrowing the ceiling splits into a folder, and small domains of one k
157
158
  - Name an entry inside either folder per the `codebase-layout` skill, which never repeats the folder's name as the entry's stem or prefix
158
159
  - Keep a split domain's `index.md` generated, since regen rewrites its body. The domain's own overview and layout go in a sibling file, which the `subtitle` names.
159
160
 
160
- Author a catalog that grows a row per shipped thing as a bullet list, never a markdown table. A table pads its columns to a shared width, so one row outgrowing its column reflows every row and conflicts with any sibling branch.
161
+ Author a catalog that grows a row per shipped thing as a bullet list, never a markdown table. A table pads its columns to a shared width, so one row outgrowing its column reflows every row and conflicts with any sibling branch. The development entry's `### Scripts` is the one exception, kept small by grouping.
161
162
 
162
163
  ## Examples
163
164
 
@@ -0,0 +1,33 @@
1
+ ---
2
+ name: design-record
3
+ description: What keeping the design record is for, the gaps it closes, and where it stops against the skills that pick and judge a design
4
+ ---
5
+
6
+ # Design record requirement
7
+
8
+ ## Gap
9
+
10
+ Without this skill, no surface sets up the design reference folder or keeps it. A pick reaches the folder only when the operator remembers the sync, or a session copies frames in by hand and they drift. A reference outlives the surface it showed, since nothing removes it.
11
+
12
+ Each project invents its own grouping, and its index restates the file tree rather than naming the code a group governs. A picked color reaches the stylesheet with no intent written down, or lands as a hand-typed value in the design document.
13
+
14
+ ## Must
15
+
16
+ - The folder takes the groups, file names, support folder, and index row form the folder standard fixes, and a project without one gets it set up rather than refused
17
+ - A pick lands through the design sync after its index row, and a project with no sync is told before any write and still gets the design document half
18
+ - A redraw keeps the index row and leaves the files to the sync, and a retired surface takes its files and row out in the change that removes it
19
+ - The run looks at each landed picture in both themes before reporting it landed
20
+ - A picked value lands in the stylesheet and its intent in the design document under the design document standard, and a generated record changes through its module alone
21
+
22
+ ## Must not
23
+
24
+ - Write, copy, or delete a reference file by hand, or capture frames in place of a missing sync
25
+ - Land a candidate the operator has not picked
26
+ - Restate when a pick lands against the build, which the design-reference rule states
27
+ - Be reached only by the author typing its name, since a pick from the picking or canvas skill should hand off to it
28
+
29
+ ## Out of scope
30
+
31
+ - Drafting candidates and taking the pick, which `pick-by-eye` owns
32
+ - Drawing, selecting, and capturing frames on the canvas, which `canvas-board` owns
33
+ - Judging whether a design is good, which `design-taste` owns
@@ -0,0 +1,84 @@
1
+ ---
2
+ name: design-record
3
+ description: Keeps the project's design record, being the design document at `canon/DESIGN.md` and the reference folder at `canon/design/` holding the accepted frames a build matches. Sets the folder up, lands a picked design through the project's design sync, keeps the index, redraws or retires a reference when its surface changes, and carries a pick's values into the stylesheet and its intent into the design document. Use whenever a picked frame or design moves into `canon/design/` or `canon/DESIGN.md`, before running the project's design sync or editing the index, including when asked to "land it in the design references", "add a design reference", "land this pick", "set up canon/design", "update the design index", "redraw the reference for X", "remove the reference for X", or "update DESIGN.md". Do NOT use to draft candidates or take a pick, which is `pick-by-eye`, to draw frames on the canvas, which is `canvas-board`, or to judge a design, which is `design-taste`.
4
+ metadata:
5
+ family: ship
6
+ ---
7
+
8
+ # Design record
9
+
10
+ Keep the record of what the project's design is. The record has two halves, each with its own standard to read before writing it.
11
+
12
+ | Half | Path | Standard |
13
+ | ---------------- | ----------------- | ------------------------------------------ |
14
+ | Design document | `canon/DESIGN.md` | `${CLAUDE_SKILL_DIR}/references/design.md` |
15
+ | Reference folder | `canon/design/` | `${CLAUDE_SKILL_DIR}/references/folder.md` |
16
+
17
+ The document holds the rules and each role's intent, and the folder holds the pictures a build matches.
18
+
19
+ ## Guards
20
+
21
+ - Write no reference file by hand, whether a copy, an edit, or a delete. The project's design sync writes the frames, so a hand-written file drifts from the frame it claims to show.
22
+ - Never land a candidate the operator has not picked. The folder holds accepted designs, and a draft lives on the canvas.
23
+
24
+ ## Step 1: read the record
25
+
26
+ Read `canon/design/index.md` from the project root, and list the group folders beside it.
27
+
28
+ - A missing folder or index is set up at Step 3, once Step 2 has found the sync
29
+ - An index carrying a file list or a canvas mapping is an older shape. Leave its rows in place, add new rows in the form `folder.md` gives, and say the index predates the standard.
30
+
31
+ ## Step 2: find the project's design sync
32
+
33
+ Find the sync before writing anything, since every folder step runs through it. Read the project's scripts, such as the `scripts` block of `package.json`, for the command that writes frames into `canon/design/`. Run its `--help` when it offers one, for its mapping file and its check.
34
+
35
+ When no sync resolves, skip Steps 3 to 5 and capture no frame in the sync's place. Report `⚠ No design sync found, so the pick did not land in canon/design/. Add one or name the command, then re-run.` and go on to Step 6, which needs no sync.
36
+
37
+ ## Step 3: set up the folder
38
+
39
+ Skip this step when `canon/design/index.md` exists, even as a stub, since a stub the project's stack seeded is the setup.
40
+
41
+ 1. Write `canon/design/index.md` from the template in `folder.md`, with one row per group the first pick needs.
42
+ 2. Leave the group folders to the sync, since git tracks no empty folder and the sync creates each one as it writes.
43
+
44
+ ## Step 4: land a pick
45
+
46
+ When the pick lands relative to the build is the design-reference rule's call, so follow it rather than choosing here.
47
+
48
+ 1. Name the group the surface belongs to, by where a user meets it in the app, per `folder.md`.
49
+ 2. Add or update the group's index row before running the sync, naming the code paths the surface governs and the states its frames show.
50
+ 3. Add the surface to the sync's mapping file, in the form the sync's own help gives.
51
+ 4. Run the sync, then its check, and report a missing or stray file the check names.
52
+ 5. Open each written PNG, light and dark, before reporting it landed, since a frame captured blank or in one theme passes the sync.
53
+
54
+ ## Step 5: redraw or retire a reference
55
+
56
+ A redraw follows an intentional design change and nothing else. Keep the index row, change the sync's mapping only where the frame moved on the canvas, and run the sync so it rewrites the files.
57
+
58
+ Retire a reference in the change that removes its surface from the app.
59
+
60
+ - Drop the surface from the sync's mapping and run the sync, so the sync removes its files
61
+ - Remove the group's index row when the group holds nothing else
62
+ - When the sync leaves the files and its check reports them stray, name each path and ask the operator, since no session deletes a reference by hand
63
+
64
+ ## Step 6: carry a pick into the design document
65
+
66
+ A pick that settles color, type, spacing, or radius changes the design document as well as the folder. Skip this step when the pick changed layout or structure alone, since the reference carries that.
67
+
68
+ - Carry each value into the stylesheet the document's lead names, and its intent into the document's sections under `design.md`
69
+ - A project with no stylesheet yet takes the values under `.claude/design/project/` after `canon design install`, and the lead names that path
70
+ - A values record names in its lead the module it renders from and the command that renders it. Edit that module and run that command, never the document.
71
+
72
+ Never cite a canvas frame path from the document or the index. The canvas folder is gitignored, so the citation resolves on one machine alone.
73
+
74
+ ## Output
75
+
76
+ ```plaintext
77
+ ✅ Design record: <landed, redrawn, retired, set up, or carried>
78
+ Group: <group>, <name>
79
+ Files: <each file the sync wrote or removed>
80
+ Index: <the row added, changed, or removed, or unchanged>
81
+ Design: <the stylesheet and design document the values went to, or unchanged>
82
+ ```
83
+
84
+ Emit every path from the project root. Omit the files line when nothing was written.
@@ -0,0 +1,69 @@
1
+ ---
2
+ title: Design reference folder
3
+ description: Shape and content rules for canon/design, the tracked folder of accepted design frames a build matches
4
+ ---
5
+
6
+ # Design reference folder
7
+
8
+ Applies to `canon/design/`. Each file is an accepted design a build matches, kept as a picture for a reader and as frame HTML for exact values. The folder holds what was picked, never a draft.
9
+
10
+ ## Scope
11
+
12
+ Governs the folder's groups, the file names inside them, the support folder, and the index at `canon/design/index.md`.
13
+
14
+ Does not govern:
15
+
16
+ - The design document at `canon/DESIGN.md`, which `design.md` beside this file governs
17
+ - When a pick lands and how a build is held to a reference, which the design-reference governance rule states
18
+ - The canvas content format a frame is drawn in, which the canvas standard owns
19
+
20
+ ## What a working folder looks like
21
+
22
+ A folder works when a builder opening it finds the reference for the surface they are changing without asking anyone:
23
+
24
+ - Does the group a surface sits in match where a user meets it in the app?
25
+ - Does each reference carry both themes, as a picture and as frame HTML?
26
+ - Does the index say which code each group governs?
27
+
28
+ ## Groups
29
+
30
+ Group by app part, being the places a user sees, such as `home`, `inspector`, or `menus`. A component folder splits one screen across many folders, and a concern folder mixes surfaces a builder edits apart.
31
+
32
+ - Give each app part one plain kebab-case folder directly under `canon/design/`
33
+ - Put the inputs every app part draws on, such as tokens, colors, and the logo, under `foundations/`, so they read apart from places in the app
34
+ - Gather a surface shown on several app parts, such as a toast, under the part a user meets it in first
35
+
36
+ ## Files
37
+
38
+ Each reference is one name in two themes, with a PNG and its frame HTML per theme.
39
+
40
+ - Name each file `<name>-dark` or `<name>-light`, as in `grid-dark.png` beside `grid-dark.html`
41
+ - Keep one HTML file without a theme suffix only for a frame that switches theme itself, beside both PNGs
42
+ - Put what every frame HTML loads, being its stylesheet, script, fonts, and vendored files, under `kit/`
43
+
44
+ ## The index
45
+
46
+ `canon/design/index.md` is prose for a reader. It names the link a file listing lacks, from a group to the code it governs.
47
+
48
+ - Write one row per group, carrying the group, what the user sees there, the code paths it governs, and the states its frames show
49
+ - List no files, since the tree and the sync's own check already answer what exists
50
+ - Keep the sync's canvas mapping out of the index, in a file the sync owns beside it
51
+
52
+ ### Template
53
+
54
+ The column headers stay verbatim. A row per group, `foundations` included.
55
+
56
+ ```markdown
57
+ # Design references
58
+
59
+ Each group holds accepted frames a build matches, light and dark.
60
+
61
+ | Group | What the user sees | Code | States |
62
+ | ------------- | ------------------ | ------------------ | ---------------- |
63
+ | `home` | <the surface> | `<path in source>` | <states shown> |
64
+ | `foundations` | Tokens and colors | `<stylesheet>` | <themes covered> |
65
+ ```
66
+
67
+ ## Lifetime
68
+
69
+ Keep a reference while its surface exists. Redraw it only on an intentional design change, and remove its folder or files and its index row in the change that removes the surface.
@@ -157,6 +157,6 @@ Run `${CLAUDE_SKILL_DIR}/references/preflight.md` against the output. It is the
157
157
  Four neighbors own the rest.
158
158
 
159
159
  - The candidate loop, the arm set, the render, and the pick: `pick-by-eye`
160
- - The shape of the project's design document and where its values live: `${CLAUDE_SKILL_DIR}/../canvas-board/references/design.md`
160
+ - The shape of the project's design document and where its values live: `${CLAUDE_SKILL_DIR}/../design-record/references/design.md`
161
161
  - Reading source for roughness: `ux-audit`. Measuring what a running interface costs to paint: `ux-measure`
162
162
  - Prose on the surface being designed: the `write-human` skill
@@ -14,6 +14,7 @@ The rules also have three carriers, a standard, a generated rule pointing at it,
14
14
  ## Must
15
15
 
16
16
  - Hold the format and structure reference in `references/markdown.md`, the one copy, read by sibling path from every skill that writes markdown
17
+ - Hold the table limits in `references/tables.md`, the one copy, since `markdown.md` sits at the document ceiling and points at it
17
18
  - Send the session to `canon markdown audit` after an edit, since the audit reads the bans from the package and a restated list would drift
18
19
  - Route voice to `write-human` and a Mermaid fence to `draw-figure` rather than restating either
19
20
 
@@ -7,10 +7,15 @@ metadata:
7
7
 
8
8
  # Markdown craft
9
9
 
10
- Read `${CLAUDE_SKILL_DIR}/references/markdown.md` before a substantial markdown edit. Every rule in it is a fact a scan can settle, so do not work the banned characters from memory.
10
+ Read the references below before a substantial markdown edit. Every rule in them is a fact a scan can settle, so do not work the banned characters from memory.
11
+
12
+ - `${CLAUDE_SKILL_DIR}/references/markdown.md`: headings, density, code spans, punctuation, and every other format rule
13
+ - `${CLAUDE_SKILL_DIR}/references/tables.md`: the four table limits and their fixes, read before writing a table or fixing a table finding
11
14
 
12
15
  Run `canon markdown audit <path>` after the edit, and fix every ban and density finding it reports before moving on. Rewrite the sentence carrying a ban hit rather than swapping the token for a near-synonym, and fix a density finding by its shape rather than trimming characters.
13
16
 
17
+ A table finding reports without failing the run. Fix it the way `tables.md` gives for its limit.
18
+
14
19
  ## Routes
15
20
 
16
21
  - Voice, rhythm, sentence construction, and information density: load `write-human`.
@@ -63,7 +63,7 @@ Two kinds of block are exempt from the 40-line checkpoint, since a subheading dr
63
63
  - A block whose lines are all list items at one level averaging under roughly 130 characters, since a flat list of short peers is already navigable
64
64
  - Weight decides rather than count, since a catalog of one-liners and a stack of paragraphs reach one count and read nothing alike. The cap on a bullet run is a separate rule.
65
65
  - Mixing prose into that list, or nesting levels in it, ends the exemption at any weight
66
- - A block whose lines are all table rows, at any length, since a subheading inside one splits the table rather than the run
66
+ - A block of table rows, since a heading splits the table rather than the run
67
67
  - Prose either side of the table ends that exemption, since the block has a seam and a heading breaks it there
68
68
 
69
69
  ### Bold section markers
@@ -77,7 +77,7 @@ A bold section marker holding its line alone breaks a run the way a heading does
77
77
 
78
78
  ## Density
79
79
 
80
- Six limits keep a file scannable on sight, each a fact `canon markdown audit` measures that fails the push wherever the surface's gate is on. Open an H3 with a lead sentence or a table, then a few bullets or a short paragraph, since monotone text is the defect whether all prose or all bullets.
80
+ Six limits keep a file scannable on sight, each a fact `canon markdown audit` measures that fails the push where the surface's gate is on. A table takes four more, in `tables.md` beside this file. Open an H3 with a lead sentence or a table, then a few bullets or a short paragraph, since monotone text is the defect whether all prose or all bullets.
81
81
 
82
82
  | Rule | Limit |
83
83
  | ------------------- | ------------------------------------------------- |
@@ -88,7 +88,7 @@ Six limits keep a file scannable on sight, each a fact `canon markdown audit` me
88
88
  | Heading depth | H3 at most, no H4 |
89
89
  | H3 opening | First block under an H3 is a paragraph or a table |
90
90
 
91
- Rules, `CLAUDE.md`, a requirements or design record, a changelog, examples, and `.canon/` records take no density finding, since a rule is one imperative per bullet and each record keeps its own shape.
91
+ Rules, a requirements or design record, a changelog, examples, and `.canon/` records take no density finding, since each keeps its own shape. `CLAUDE.md` takes the run limit and the H3 opening inside `## Key paths` alone.
92
92
 
93
93
  ### How each limit counts
94
94
 
@@ -0,0 +1,30 @@
1
+ ---
2
+ title: Table limits
3
+ description: The four limits a markdown table takes, being cell length, row count, a list after a table, and a wide code token, with the fix each one takes
4
+ ---
5
+
6
+ # Table limits
7
+
8
+ None of the density limits in `markdown.md` reads inside a table, so content too long for a bullet tends to move into a cell. Four table limits close that gap. `canon markdown audit` measures them on the paths density covers, outside fences, and reports each one without failing a push for now.
9
+
10
+ ## Limits
11
+
12
+ Each limit is a count or a shape a scan settles, read the way a renderer draws the table. An escaped pipe stays inside its cell, and pipe lines with no delimiter row are not a table.
13
+
14
+ | Rule | Limit |
15
+ | ---------------- | ----------------------------------------------------- |
16
+ | Cell length | 120 visible characters, counting a link by its label |
17
+ | Rows | 8 body rows, not counting the header |
18
+ | List after table | A list is never the next block after a table |
19
+ | Wide token | No code span in a cell holds a run past 30 characters |
20
+
21
+ A paragraph or a heading between a table and a list clears the third limit, and a blank line alone does not.
22
+
23
+ ## Fixes
24
+
25
+ Each limit has its own fix, and none of them is trimming characters until the count passes.
26
+
27
+ - Move a long cell's overflow into a bullet under the table's lead sentence, or under a lead of its own
28
+ - Split a long table into groups, each under a lead sentence naming its group, since a heading inside a table splits it and H4 is banned
29
+ - Give a list that follows a table a lead sentence of its own
30
+ - Move a wide token out of the table into a bullet, since a preview either widens its column or splits it at a hyphen or a slash
@@ -124,15 +124,16 @@ Read `canon canvas selection --json` when the answer points at the canvas, such
124
124
 
125
125
  1. Apply the winning arm to the real surface, in one change.
126
126
  2. Close out any document stating the decision as open, in the same change, naming the winner and the arms that stayed defensible. Skip this where nothing stated the decision.
127
- 3. Capture the picked round's frames with `canon canvas capture <page> --out <archive-dir> --json`. Each lands as `arm-<id>.png`, keeping the losing arms as a revert record.
128
- 4. Resolve `<archive-dir>` as `.canon/picks/<slug>/` against the main worktree root, since shared session scratch resolves there rather than in a linked worktree.
129
- 5. Delete every page folder on the run's list from under the `content` folder `canon canvas list --json` reports. Touch no page the run did not add, whatever its name.
130
- 6. Stop the canvas server if this run started it, and leave one the operator started running.
131
- 7. Leave the renders in a live track's `evidence/<slug>/renders/`, since `plan-groundwork` treats evidence as durable.
132
- 8. Report each page whose delete is refused, naming the path for the operator to remove. The pick is applied either way.
133
- 9. Report every surface that changed, each on its own line, name the winning arm by its id and its cost, and report the archive path.
127
+ 3. Hand the winning frame to `canon:design-record` by its page and frame, which lands it in the project's design record. Report it rather than proceeding silently when that skill does not resolve.
128
+ 4. Capture the picked round's frames with `canon canvas capture <page> --out <archive-dir> --json`. Each lands as `arm-<id>.png`, keeping the losing arms as a revert record.
129
+ 5. Resolve `<archive-dir>` as `.canon/picks/<slug>/` against the main worktree root, since shared session scratch resolves there rather than in a linked worktree.
130
+ 6. Delete every page folder on the run's list from under the `content` folder `canon canvas list --json` reports. Touch no page the run did not add, whatever its name.
131
+ 7. Stop the canvas server if this run started it, and leave one the operator started running.
132
+ 8. Leave the renders in a live track's `evidence/<slug>/renders/`, since `plan-groundwork` treats evidence as durable.
133
+ 9. Report each page whose delete is refused, naming the path for the operator to remove. The pick is applied either way.
134
+ 10. Report every surface that changed, each on its own line, name the winning arm by its id and its cost, and report the archive path.
134
135
 
135
- The picked round is the final one unless Step 4 resolved a revert. Archiving any other page lets item 5 delete the winning arm with nothing kept, and a variant left on the canvas is a second design nobody maintains.
136
+ The picked round is the final one unless Step 4 resolved a revert. Archiving any other page lets item 6 delete the winning arm with nothing kept, and a variant left on the canvas is a second design nobody maintains.
136
137
 
137
138
  ## Reading a measurement
138
139
 
@@ -149,6 +150,7 @@ A capture proves appearance and a measurement proves a relationship, so reach fo
149
150
  Cite these rather than restating them. A step reimplemented here rots against the skill that owns it.
150
151
 
151
152
  - `plan-feature` plans the work once the pick is made, and declares the pull request boundary that plan carries
153
+ - `design-record` lands the winning frame in the reference folder and its values in the design document, and runs before item 6 deletes the page its sync reads
152
154
  - `design-taste` carries the layer catalog, the ordering, grey-boxing, and the defaults an arm should reach past
153
155
  - `write-human` carries the voice for any copy an arm puts in front of a reader
154
156
 
@@ -17,8 +17,8 @@ metadata:
17
17
 
18
18
  Before Step 3, name the next three questions you would ask about what the ask must achieve, and predict the operator's answer to each. The test reads the ask's success criteria, never the plan's open questions.
19
19
 
20
- - A predictable answer settles its criterion, which Step 3 writes as a `**Verification:**` bullet rather than a question
21
- - Only a prediction still open goes under `**Questions:**` with a `- Suggested:` line, so a fully specified ask carries none and Small mode stays reachable
20
+ - A predictable answer settles its criterion, which Step 3 writes as a `## Verification` bullet rather than a question
21
+ - Only a prediction still open goes under `## Questions` with a `- Suggested:` line, so a fully specified ask carries none and Small mode stays reachable
22
22
  - When you can predict none of the three, ask before Step 3 through whatever route reaches the operator, including a message to a dispatching session
23
23
 
24
24
  ## Step 1: read the Claude setup
@@ -59,7 +59,7 @@ The section list, what each section holds, and the suggested-and-answer contract
59
59
 
60
60
  What this skill adds on top of the standard:
61
61
 
62
- - Reframe a vague ask as success criteria before `**Files to touch:**`, each an observable result and its check, which becomes one `**Verification:**` bullet. "Make it faster" names none.
62
+ - Reframe a vague ask as success criteria before `## Files to touch`, each an observable result and its check, which becomes one `## Verification` bullet. "Make it faster" names none.
63
63
  - Confirm a concrete project or use case drives the feature, and lift patterns from it where precedent exists. A feature with no named user is a guess.
64
64
  - Prefer one layout that serves both a new and a grown project over a dual-mode toggle or a migration shim. Two modes double what every later change has to hold.
65
65
 
@@ -68,16 +68,16 @@ What this skill adds on top of the standard:
68
68
  Every `- Suggested:` line takes senior judgment, picking the best option in one line with its reason or main tradeoff, and naming alternatives only when they change the pick.
69
69
 
70
70
  - Suggest a real default when best practice, the codebase, or prior context points to one
71
- - Load `canon:codebase-layout` before `**Files to touch:**` when an entry names a path that does not exist yet, and give each new path its placement reason. Report it if it does not resolve.
72
- - Fill `**Design references:**` with the `canon/design/<surface>/` folder for each surface a UI file in `**Files to touch:**` renders, and write `None identified.` in a project with no folder
73
- - Write `**Verification:**` as one bullet per outcome naming the test or command that proves it
74
- - Write `**Review focus:**` as the inputs or states that would break the change, carrying the risk you understood to the executor and the reviewer
71
+ - Load `canon:codebase-layout` before `## Files to touch` when an entry names a path that does not exist yet, and give each new path its placement reason. Report it if it does not resolve.
72
+ - Fill `## Design references` with the `canon/design/<surface>/` folder for each surface a UI file in `## Files to touch` renders, and write `None identified.` in a project with no folder
73
+ - Write `## Verification` as one bullet per outcome naming the test or command that proves it
74
+ - Write `## Review focus` as the inputs or states that would break the change, carrying the risk you understood to the executor and the reviewer
75
75
 
76
76
  ### Sources and size
77
77
 
78
78
  A small feature produces a short plan, not a padded one.
79
79
 
80
- - Cite the `**Sources:**` entry for every decision Step 2 sourced, each with its quoted passage or the word `unverified`
80
+ - Cite the `## Sources` entry for every decision Step 2 sourced, each with its quoted passage or the word `unverified`
81
81
  - Prefer `None identified.` over low-signal fillers
82
82
  - When three or more questions remain, keep chat output to the file pointer plus a short summary. Inline chat is fine when two or fewer remain.
83
83
 
@@ -99,21 +99,21 @@ A consumer list is a `Risks` entry, which already forces Full. A resource with m
99
99
  Output the plan to chat and write no plan file. The markers match the standard's, so a plan that later grows into a file keeps its shape.
100
100
 
101
101
  ```markdown
102
- **Files to touch:**
102
+ ## Files to touch
103
103
 
104
104
  - `path/to/file`: reason
105
105
 
106
- **Verification:**
106
+ ## Verification
107
107
 
108
108
  - <outcome>: `<test or command that proves it>`
109
109
  ```
110
110
 
111
- Small mode carries no `**Review focus:**`, since its Risks already came out `None identified.` and the reviewer has no breaking input to name.
111
+ Small mode carries no `## Review focus`, since its Risks already came out `None identified.` and the reviewer has no breaking input to name.
112
112
 
113
- If real questions exist, include a numbered `**Questions:**` section below, each with a `- Suggested:` line and an `- Answer:` slot:
113
+ If real questions exist, include a numbered `## Questions` section below, each with a `- Suggested:` line and an `- Answer:` slot:
114
114
 
115
115
  ```markdown
116
- **Questions:**
116
+ ## Questions
117
117
 
118
118
  1. <question>
119
119
  - Suggested: <pick>, <reason or tradeoff>
@@ -132,7 +132,10 @@ The plan is a main-root write, from a linked worktree and from a background sess
132
132
 
133
133
  Two commands check the file once it lands, and both write nothing.
134
134
 
135
- - Run `canon records validate plans` when the CLI is on PATH. It reports a section, a filename, or an answer slot that does not hold.
135
+ - Run `canon records validate plans feature-<slug>` when the CLI is on PATH. Its `findings` name a section, a filename, or an answer slot that does not hold.
136
+ - Fix each entry its `structure` array names before reporting, against `### Structure` in `${CLAUDE_SKILL_DIR}/references/plan.md`
137
+ - Read that array rather than the exit code, since a structure entry never sets the exit
138
+ - Say the check did not run when the binary refuses the plan argument or carries no `structure` key, rather than reporting the plan clean
136
139
  - Run `canon markdown audit .canon/plans/feature-<slug>.md`, naming the file, since the gitignored plan reaches no other gate. Rewrite a hit's sentence rather than swapping the token.
137
140
 
138
141
  When Step 1 resolved an existing task, run `canon tasks plan-link <task> .canon/plans/feature-<slug>.md` right after the file lands, naming the stem Step 1 read. Skip it when Step 1 found no task, and report a refusal rather than stopping, since `canon tasks validate` still catches an unlinked task through `plan-uncited`.
@@ -144,14 +147,26 @@ Then output in chat:
144
147
  ```markdown
145
148
  📝 Wrote .canon/plans/feature-<slug>.md
146
149
 
147
- **Questions:**
150
+ ## Questions
148
151
 
149
152
  1. <question>
150
153
  - Suggested: <pick>, <reason or tradeoff>
151
154
 
152
- Next: /session-worktree
155
+ Next: <line from the table below>
153
156
  ```
154
157
 
158
+ Pick the `Next:` line from the roster check `${CLAUDE_SKILL_DIR}/../task-board/SKILL.md` states under `### Check for a live orchestrator`, read there rather than restated here.
159
+
160
+ | Roster read | `Next:` line |
161
+ | -------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- |
162
+ | **Found** | `<name> places and dispatches <task>`, naming the orchestrator row the check matched |
163
+ | **Not found**, and this session's name starts with `worker-` or `planner-` | `Hand <task> to a worker`, naming no session, since none is live and the operator dispatches by hand |
164
+ | **Not found otherwise**, or the read fails | `/session-worktree` |
165
+
166
+ - With a live orchestrator and no planner role held, send the plan path to it through `canon:session-relay`, resolved from its `sessionId`
167
+ - A session holding `canon:role-planner` already owes that announcement through its own channel, so it sends none
168
+ - Say which row fired in one clause, since a line with no stated reason is one the next reader re-derives.
169
+
155
170
  Show only the path line and the `Next:` line when there are no questions. The `.canon/plans/` directory is gitignored, so do not stage or commit the file.
156
171
 
157
172
  Do not proceed to implementation until the user explicitly says to continue.
@@ -11,18 +11,18 @@ Applies to a feature plan that sequences its work into more than one batch. A de
11
11
 
12
12
  One batch is one pull request, and one pull request is one plan file, named for its own concern rather than a numeric suffix. `canon tasks plan-branch` derives one branch from one plan filename. A fan-in member is the exception, keeping its own file and branch and opening no pull request, per `## Fan-in`.
13
13
 
14
- - A `**Batch N**` sub-heading inside one file's `**Files to touch:**` shares that branch across every batch, so the first merge strands the rest
14
+ - A `**Batch N**` sub-heading inside one file's `## Files to touch` shares that branch across every batch, so the first merge strands the rest
15
15
  - Write a plan opening five batches as five files before the first line of any of them
16
16
 
17
17
  ## Dependent batches
18
18
 
19
- State a dependent batch's dependency on the ones before it in its own `**Constraints:**`, naming the earlier batch's slug and stacking rather than merging into it.
19
+ State a dependent batch's dependency on the ones before it in its own `## Constraints`, naming the earlier batch's slug and stacking rather than merging into it.
20
20
 
21
21
  A batch that builds after another and shares most of its files folds into that batch as contiguous commits on one branch. Each pull request pays a fixed cost a same-file slice cannot earn back, and the rebases between stacked slices land on the same files.
22
22
 
23
23
  ### Judged apart
24
24
 
25
- Keep a batch apart only where a reviewer or the operator would judge it apart. Write that reason as ``Judged apart from `feature-<parent>`: <reason>`` in the batch's `**Constraints:**`.
25
+ Keep a batch apart only where a reviewer or the operator would judge it apart. Write that reason as ``Judged apart from `feature-<parent>`: <reason>`` in the batch's `## Constraints`.
26
26
 
27
27
  - A contract a later batch is built against
28
28
  - A taste call the operator judges in its own sitting
@@ -61,12 +61,12 @@ Keep separate pull requests when the pieces are independent features, when one n
61
61
 
62
62
  ### Declaring the set
63
63
 
64
- Each side names the other in its `**Constraints:**`, and `canon records validate plans` reports `fan-in-unmatched` wherever the two disagree.
64
+ Each side names the other in its `## Constraints`, and `canon records validate plans` reports `fan-in-unmatched` wherever the two disagree.
65
65
 
66
66
  - A member writes ``Fan-in member of `feature-<integrator>` ``, naming one integrator
67
67
  - The integrator writes ``Fans in `feature-<a>`, `feature-<b>`, and `feature-<c>` ``, in the order it merges them
68
68
  - The task's `Plan:` line cites every member and the integrator, since the merge archives only the plans that line cites and a live integrator listing archived members reports `fan-in-unmatched`
69
- - The integrator is its own plan, since its writes, being the shared lists, the citer repoints, and the index regeneration, need a `**Files to touch:**` of their own
69
+ - The integrator is its own plan, since its writes, being the shared lists, the citer repoints, and the index regeneration, need a `## Files to touch` of their own
70
70
 
71
71
  `canon tasks plan-answers` holds a member whose integrator is missing or does not list it with a `Fan-in set` entry. It holds the integrator with a `Fan-in pending` entry until every member branch is on origin.
72
72