@erclx/canon 5.68.0 → 5.70.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 (125) hide show
  1. package/CHANGELOG.md +36 -0
  2. package/README.md +33 -159
  3. package/assets/brand/mark.svg +17 -9
  4. package/claude/.claude-plugin/plugin.json +1 -1
  5. package/claude/skills/app-drive/REQUIREMENT.md +5 -5
  6. package/claude/skills/app-drive/SKILL.md +17 -6
  7. package/claude/skills/app-drive/references/drive-record.md +61 -8
  8. package/claude/skills/app-drive/references/isolate.md +1 -1
  9. package/claude/skills/canon-cli/SKILL.md +2 -2
  10. package/claude/skills/canon-feedback/REQUIREMENT.md +1 -1
  11. package/claude/skills/canon-feedback/SKILL.md +1 -1
  12. package/claude/skills/design-identity/REQUIREMENT.md +4 -4
  13. package/claude/skills/design-identity/SKILL.md +7 -7
  14. package/claude/skills/{pick-by-eye → design-pick}/REQUIREMENT.md +6 -6
  15. package/claude/skills/{pick-by-eye → design-pick}/SKILL.md +19 -10
  16. package/claude/skills/{pick-by-eye → design-pick}/references/board.md +17 -11
  17. package/claude/skills/design-pick/references/design-config.md +33 -0
  18. package/claude/skills/design-record/REQUIREMENT.md +2 -2
  19. package/claude/skills/design-record/SKILL.md +1 -1
  20. package/claude/skills/design-taste/REQUIREMENT.md +2 -2
  21. package/claude/skills/design-taste/SKILL.md +3 -3
  22. package/claude/skills/design-taste/references/preflight.md +1 -1
  23. package/claude/skills/git-issue/REQUIREMENT.md +1 -1
  24. package/claude/skills/git-issue/references/issue.md +1 -1
  25. package/claude/skills/plan-feature/SKILL.md +1 -1
  26. package/claude/skills/plan-feature/references/plan.md +21 -6
  27. package/claude/skills/plan-groundwork/SKILL.md +1 -1
  28. package/claude/skills/pr-evidence/references/evidence.md +2 -2
  29. package/claude/skills/role-orchestrator/references/orchestrator-launch.md +3 -3
  30. package/claude/skills/role-orchestrator/references/orchestrator-parked.md +1 -1
  31. package/claude/skills/role-orchestrator/references/orchestrator-planning-wait.md +24 -0
  32. package/claude/skills/role-planner/SKILL.md +4 -2
  33. package/claude/skills/role-worker/SKILL.md +5 -6
  34. package/claude/skills/task-board/references/tasks.md +1 -1
  35. package/claude/skills/task-complete/references/receipt-sweep.md +1 -1
  36. package/claude/skills/{ux-audit → ui-audit}/REQUIREMENT.md +3 -3
  37. package/claude/skills/{ux-audit → ui-audit}/SKILL.md +7 -7
  38. package/claude/skills/ui-checklist/REQUIREMENT.md +1 -1
  39. package/claude/skills/ui-craft/SKILL.md +1 -1
  40. package/claude/skills/ui-craft/references/copy.md +4 -1
  41. package/claude/skills/{ui-record → ui-film}/REQUIREMENT.md +6 -4
  42. package/claude/skills/{ui-record → ui-film}/SKILL.md +26 -13
  43. package/claude/skills/ui-film/references/compose-craft.md +81 -0
  44. package/claude/skills/{ui-record → ui-film}/references/config.md +9 -4
  45. package/claude/skills/{ui-record → ui-film}/references/handoff.md +17 -7
  46. package/claude/skills/{ui-record → ui-film}/references/pr-clip.md +5 -5
  47. package/claude/skills/{ui-record → ui-film}/references/take-craft.md +28 -2
  48. package/claude/skills/{ux-measure → ui-measure}/REQUIREMENT.md +3 -3
  49. package/claude/skills/{ux-measure → ui-measure}/SKILL.md +6 -6
  50. package/docs/agents/audits.md +1 -1
  51. package/docs/agents/migrate.md +13 -13
  52. package/docs/index.md +1 -0
  53. package/docs/migrations/by-hand.md +107 -0
  54. package/docs/migrations/by-verb.md +118 -0
  55. package/docs/migrations/index.md +14 -0
  56. package/docs/target/index.md +1 -2
  57. package/docs/target/projects.md +3 -3
  58. package/docs/target/sync.md +23 -3
  59. package/docs/workflow/ai-workflow.md +1 -1
  60. package/docs/workflow/skill-map-on-request.md +1 -2
  61. package/docs/workflow/skill-map.md +9 -10
  62. package/docs/workflow/visual-design-workflow.md +6 -1
  63. package/governance/ledger/claude/background.md +26 -0
  64. package/governance/ledger/skills/ui-craft/copy.md +8 -4
  65. package/governance/rules/claude/background.md +19 -0
  66. package/governance/stacks/base.toml +1 -0
  67. package/package.json +6 -4
  68. package/scripts/ci/install-playwright-deps.sh +52 -0
  69. package/scripts/core/design-sync.ts +204 -0
  70. package/scripts/core/regen-web-favicon.ts +27 -12
  71. package/scripts/core/regen-web-previews.ts +8 -1
  72. package/scripts/core/render-film.ts +179 -0
  73. package/src/capture/frame-values.ts +12 -12
  74. package/src/claude/cases/authoring.ts +2 -2
  75. package/src/claude/cases/misc.ts +1 -1
  76. package/src/claude/cases/setup.ts +0 -5
  77. package/src/claude/cases/workflow.ts +6 -6
  78. package/src/commands/fixtures/gh.sh +64 -0
  79. package/src/commands/gov.ts +33 -3
  80. package/src/commands/migrate.ts +12 -2
  81. package/src/commands/records.ts +3 -2
  82. package/src/commands/sandbox.ts +9 -2
  83. package/src/commands/take.ts +159 -11
  84. package/src/commands/tasks.ts +183 -0
  85. package/src/design/favicon.ts +85 -13
  86. package/src/design/reference.ts +98 -0
  87. package/src/design/render.ts +16 -14
  88. package/src/design/tokens.ts +4 -3
  89. package/src/gate/stages.ts +8 -2
  90. package/src/gov/audit.ts +48 -11
  91. package/src/gov/detect.ts +1 -1
  92. package/src/init/steps.ts +2 -2
  93. package/src/markdown/scope.ts +9 -14
  94. package/src/migrate/record-layout.ts +5 -3
  95. package/src/migrate/skill-names.ts +21 -4
  96. package/src/migrate/status.ts +3 -3
  97. package/src/records/validate.ts +15 -2
  98. package/src/sandbox/expect.ts +32 -0
  99. package/src/sandbox/headless/dispatch-shim.sh +15 -0
  100. package/src/sandbox/headless/dispatch.ts +12 -14
  101. package/src/sandbox/headless/run.ts +6 -3
  102. package/src/sandbox/stub-gh.sh +26 -0
  103. package/src/sandbox/stub-remote.ts +8 -29
  104. package/src/sync/engine.ts +1 -1
  105. package/src/take/camera.ts +100 -11
  106. package/src/take/film.ts +55 -4
  107. package/src/take/fixtures/input.html +138 -0
  108. package/src/take/keys.ts +193 -0
  109. package/src/take/log.ts +94 -1
  110. package/src/take/perform.ts +165 -10
  111. package/src/take/plan.ts +101 -6
  112. package/src/take/pointer.ts +2 -1
  113. package/src/take/screencast.ts +28 -3
  114. package/src/take/stepper.ts +141 -23
  115. package/src/take/zoom/NOTICE.md +1 -1
  116. package/src/tasks/launch-wait.ts +160 -0
  117. package/tooling/claude/reference.md +1 -1
  118. package/claude/skills/canon-feedback-triage/REQUIREMENT.md +0 -34
  119. package/claude/skills/canon-feedback-triage/SKILL.md +0 -98
  120. package/claude/skills/plan-ready/REQUIREMENT.md +0 -35
  121. package/claude/skills/plan-ready/SKILL.md +0 -136
  122. package/claude/skills/plan-ready/references/assembly.md +0 -75
  123. package/claude/skills/plan-ready/references/ready.md +0 -128
  124. package/docs/target/migrations.md +0 -203
  125. /package/claude/skills/{pick-by-eye → design-pick}/references/live-arms.md +0 -0
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: design-identity
3
- description: Drafts a project's logo mark through pick-by-eye's render-and-pick loop, then composes the picked mark into an icon sequence and a 1200x630 social card. Use when asked to "make a logo", "design a logo mark", "create a favicon", "build the icon set", "generate a social card", "make an og:image", or "draft the logo and social card together". Do NOT use to mutate an existing logo file directly, which is a plain edit, or to record the mark's construction rules in DESIGN.md, which is out of scope.
3
+ description: Drafts a project's logo mark through design-pick's render-and-pick loop, then composes the picked mark into an icon sequence and a 1200x630 social card. Use when asked to "make a logo", "design a logo mark", "create a favicon", "build the icon set", "generate a social card", "make an og:image", or "draft the logo and social card together". Do NOT use to mutate an existing logo file directly, which is a plain edit, or to record the mark's construction rules in DESIGN.md, which is out of scope.
4
4
  metadata:
5
5
  family: generate
6
6
  ---
@@ -60,7 +60,7 @@ Announce which tier decided, naming the tier rather than the path alone, so the
60
60
 
61
61
  ## Step 4: name the decision and the arms
62
62
 
63
- Follow `${CLAUDE_SKILL_DIR}/../pick-by-eye/SKILL.md` Step 1, with the decision fixed rather than derived: "the project's logo mark and its composition into the social card." Vary the mark's shape or style across arms, keeping the card's type and layout fixed, per that skill's one-property rule.
63
+ Follow `${CLAUDE_SKILL_DIR}/../design-pick/SKILL.md` Step 1, with the decision fixed rather than derived: "the project's logo mark and its composition into the social card." Vary the mark's shape or style across arms, keeping the card's type and layout fixed, per that skill's one-property rule.
64
64
 
65
65
  - Draft each arm inside the 1200x630 card frame, mark and type together, and add it with `frameboard frame add <page>/arm-<id> --width 1200 --height 630`, so one pick settles shape and composition
66
66
  - Arm 0 is the current mark when the Step 3 folder already holds a logo file (`favicon.svg`, `favicon.ico`, `logo.svg`, or similar). Arms start at 1 otherwise.
@@ -68,13 +68,13 @@ Follow `${CLAUDE_SKILL_DIR}/../pick-by-eye/SKILL.md` Step 1, with the decision f
68
68
 
69
69
  ## Step 5: draft, render, pick, and loop
70
70
 
71
- Follow `${CLAUDE_SKILL_DIR}/../pick-by-eye/SKILL.md` Steps 2 through 5 against the arms from Step 4: draft the arms as frames on a Frameboard page, render and hand off, take the pick, and loop on it.
71
+ Follow `${CLAUDE_SKILL_DIR}/../design-pick/SKILL.md` Steps 2 through 5 against the arms from Step 4: draft the arms as frames on a Frameboard page, render and hand off, take the pick, and loop on it.
72
72
 
73
- The final icon and card renders below are not arms, so they stay off the board. Call the folder they render from `<dest>`, being `.canon/tmp/<slug>/` under the slug `pick-by-eye` Step 1 derived, which is where this project puts every temporary write.
73
+ The final icon and card renders below are not arms, so they stay off the board. Call the folder they render from `<dest>`, being `.canon/tmp/<slug>/` under the slug `design-pick` Step 1 derived, which is where this project puts every temporary write.
74
74
 
75
75
  ## Step 6: finalize the mark and the icons
76
76
 
77
- This step and Step 7 replace `pick-by-eye`'s own Step 6 items 1 and 2, since the pick here produces several final files rather than one applied surface. Its archive capture, its page delete, and its server stop still run, after Step 7.
77
+ This step and Step 7 replace `design-pick`'s own Step 6 items 1 and 2, since the pick here produces several final files rather than one applied surface. Its archive capture, its page delete, and its server stop still run, after Step 7.
78
78
 
79
79
  1. Extract the picked arm's `.mark` markup as the final vector source. Write it to `<write-folder>/favicon.svg`.
80
80
  2. Under `<dest>/render/`, write one `icon-<w>x<h>.html` page per Step 2 size, carrying the picked `.mark` markup in an element with the shared class `.render`.
@@ -112,7 +112,7 @@ It takes its own call because Step 6's batch is already captured by the time thi
112
112
 
113
113
  ### Closing the scratch folder and the board
114
114
 
115
- Delete `<dest>` once both captures land, then close the board through `pick-by-eye` Step 6 items 3 to 8, which archive every arm and delete the pages the run added. The route is not a leftover variant, since it holds the arm the operator picked.
115
+ Delete `<dest>` once both captures land, then close the board through `design-pick` Step 6 items 3 to 8, which archive every arm and delete the pages the run added. The route is not a leftover variant, since it holds the arm the operator picked.
116
116
 
117
117
  A project whose card was generated before this route existed keeps its PNG. Say so rather than regenerating it, since the pick loop spends attention on a file nobody complained about, and the next real edit picks up the route.
118
118
 
@@ -132,7 +132,7 @@ Card source: <the route, captured through the card server|a scratch page, since
132
132
 
133
133
  Cite these rather than restating them.
134
134
 
135
- - `pick-by-eye` owns Steps 1 through 5 of the render-and-pick loop, cited above
135
+ - `design-pick` owns Steps 1 through 5 of the render-and-pick loop, cited above
136
136
  - `canon:design-record` carries a picked direction into `canon/DESIGN.md`. This skill only reads it.
137
137
  - `canon capture` owns the render mechanics, its font refusal, its fixed 2x scale, and its reported dimensions. It reads an `http(s)://` source, where `--out` names the PNG.
138
138
  - The `astro` tooling stack owns the card route's scaffold, its second config, and the exclusion check, read with `canon tooling reference astro`. This skill writes into the route and never reshapes it.
@@ -1,15 +1,15 @@
1
1
  ---
2
- name: pick-by-eye
2
+ name: design-pick
3
3
  description: Why a decision settled by looking needs its own surface, and where its boundary against the planning, audit, measurement, and recording skills falls
4
4
  ---
5
5
 
6
- # Pick by eye requirement
6
+ # Design pick requirement
7
7
 
8
8
  ## Gap
9
9
 
10
10
  Without this skill, a session facing a decision settled by looking describes the options in prose or ships one answer to a taste call. The operator never sees what they chose between. A drafted set varies several properties or the wrong layer, sits in the real surface, and mixes themes and widths, so no pick names what decided it.
11
11
 
12
- The evidence fails as well. Arms get reported without being rendered or judged, a driver finding reads as a verdict, and the pick question arrives with no address to look at. Renders land in scratch, each round overwrites the last, and the losing arms vanish with the run's pages.
12
+ The evidence fails as well. Arms get reported unrendered or unjudged, a driver finding reads as a verdict, and the pick question arrives with no address to look at. Renders land in scratch, each round overwrites the last, and the losing arms vanish with the run's pages. Rounds drafted off the synced board need redrawing.
13
13
 
14
14
  ## Must
15
15
 
@@ -17,7 +17,7 @@ The evidence fails as well. Arms get reported without being rendered or judged,
17
17
  - Each round is one Frameboard page of frames at their judged widths, themed by the board toggle and captured once as a composite, with the link ahead of the first pick question
18
18
  - Every arm is rendered and judged against a stated bar before handover, and a missing browser or a board that will not start is reported as a refusal
19
19
  - The pick comes through the structured question surface with the recommendation first and every option's cost, and the winner lands in one change
20
- - Every round stays openable on its own page until the pick, and the picked round's arms are captured into the citing record at the main root before the run's pages go
20
+ - Rounds sit on the board the design config names, each openable until the pick, and the picked arms are archived at the main root before the run's pages go
21
21
 
22
22
  ## Must not
23
23
 
@@ -30,6 +30,6 @@ The evidence fails as well. Arms get reported without being rendered or judged,
30
30
  ## Out of scope
31
31
 
32
32
  - Planning the work once the answer is settled, which `plan-feature` owns
33
- - Finding roughness by reading source, which `ux-audit` owns
34
- - Measuring what a running interface costs to paint, which `ux-measure` owns
33
+ - Finding roughness by reading source, which `ui-audit` owns
34
+ - Measuring what a running interface costs to paint, which `ui-measure` owns
35
35
  - Listing what to look at on a change already made, which `ui-checklist` owns
@@ -1,15 +1,15 @@
1
1
  ---
2
- name: pick-by-eye
3
- description: Drafts several candidates for a decision judged by looking, lays them out side by side as frames on one Frameboard page, hands the operator the address, takes the pick through the structured question surface, and loops on the pick until they stop. Use when asked to "draft some options", "show me a few versions", "try a few variations", "mock up alternatives", "give me candidates for X", or when a choice is taste rather than correctness. Do NOT use when the request already names the answer and asks for it to be built, which is `plan-feature`. Do NOT use to read source for roughness, which is `ux-audit`, to measure what a running interface costs to paint, which is `ux-measure`, or to write what to look at on a change already made, which is `ui-checklist`.
2
+ name: design-pick
3
+ description: Drafts several candidates for a decision judged by looking, lays them out side by side as frames on one Frameboard page, hands the operator the address, takes the pick through the structured question surface, and loops on the pick until they stop. Use when asked to "draft some options", "show me a few versions", "try a few variations", "mock up alternatives", "give me candidates for X", or when a choice is taste rather than correctness. Do NOT use when the request already names the answer and asks for it to be built, which is `plan-feature`. Do NOT use to read source for roughness, which is `ui-audit`, to measure what a running interface costs to paint, which is `ui-measure`, or to write what to look at on a change already made, which is `ui-checklist`.
4
4
  metadata:
5
5
  family: decide
6
6
  ---
7
7
 
8
- # Pick by eye
8
+ # Design pick
9
9
 
10
10
  Some decisions are settled by looking rather than by reasoning, and no draft is wrong until one is picked. Every step here puts several candidates in front of the operator and keeps the real surface untouched until they have chosen.
11
11
 
12
- The candidates live on a Frameboard board at `.canon/canvas/`, in a project named `picks` so rounds never mix with an operator's project. Read `${CLAUDE_SKILL_DIR}/references/board.md` before the first `frameboard` verb, for the flags every verb carries and how a selection resolves.
12
+ The candidates live on the Frameboard board the project names, in a project of their own so rounds never mix with the operator's frames. Read `${CLAUDE_SKILL_DIR}/references/board.md` before the first `frameboard` verb, for how `<board>` and `<project>` resolve, the flags every verb carries, and how a selection resolves.
13
13
 
14
14
  ## Guards
15
15
 
@@ -34,7 +34,7 @@ Inside a live `plan-groundwork` track, renders land in the track's own `evidence
34
34
  Every arm of a round sits as one frame on one board page, side by side. The operator judges that page, never a set of separate images compared from memory.
35
35
 
36
36
  1. Start the board the way `references/board.md` states, unless this run already has. Note whether this run started the server, read off `reused`, since Step 6 ends only a server this run started.
37
- 2. Read `frameboard list --root <board> --json` with no `--project`, so it lists every project. Run `frameboard project add picks --root <board> --json` when it lists no `picks`.
37
+ 2. Read `frameboard list --root <board> --json` with no `--project`, so it lists every project. Run `frameboard project add <project> --root <board> --json` when it lists no `<project>`.
38
38
  3. Add the round's page with `frameboard page add <page>` and record its `ref` on the run's list of pages. A `name-taken` refusal means the name is somebody else's, so take the next free suffix.
39
39
  4. Add each arm with `frameboard frame add <page>/arm-<id> --width <px> --height <px> --x <px> --y <px>`, placing the frames in one row in arm order. Step 6's archive keys on the `arm-<id>` names.
40
40
  5. Write each arm's whole document to the `path` the add verb reported. From a linked worktree, take the heredoc route `session-worktree` gives for a main-root write.
@@ -48,6 +48,7 @@ Each frame carries its own label and follows the board theme, so the set reads a
48
48
  - Label each arm inside its frame with its id and its cost, since the composite capture draws no captions
49
49
  - Theme every arm off the `data-theme` attribute the board sets on each frame's root, so the theme toggle sets the whole set at once. A set spanning both themes cannot be compared.
50
50
  - Give no arm a script that stores a theme and reapplies it on load. It overwrites the toggle, and a fresh browser profile hides the fault.
51
+ - Write each frame's headings, labels, and captions by `${CLAUDE_SKILL_DIR}/../ui-craft/references/copy.md`, since a candidate's copy is often the first draft of the shipped page's
51
52
 
52
53
  ### Default path and live app
53
54
 
@@ -72,7 +73,7 @@ Vary one property across the arms, since a pick cannot say which of three differ
72
73
  Render the page and look at what came back before handing anything over:
73
74
 
74
75
  ```bash
75
- frameboard capture --page <page> --composite --root <board> --project picks --json
76
+ frameboard capture --page <page> --composite --root <board> --project <project> --json
76
77
  ```
77
78
 
78
79
  - Point `--out` at `evidence/<slug>/renders/` inside a live track, and leave the board's default elsewhere. Step 6 archives the picked round alone.
@@ -118,15 +119,23 @@ Read the selection when the answer points at the board, such as "the selected on
118
119
  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.
119
120
  3. Hand the winning frame's ref to `canon:design-record`, which lands it in the project's design record. Report it rather than proceeding silently when that skill does not resolve.
120
121
  4. Capture the picked round's frames with `frameboard capture --page <page> --out <canon-dir>`, keeping the losing arms as a revert record. Report each image's `path` off the record.
121
- 5. Resolve `<canon-dir>` as `.canon/` against the main worktree root, since shared session scratch resolves there. Frameboard appends the project and page, so the archive lands at `.canon/picks/<page>/`.
122
- 6. Delete every page on the run's list with `frameboard page delete <page>`. Touch no page the run did not add, whatever its name, and never remove a page folder by hand.
122
+ 5. Resolve `<canon-dir>` as `.canon/` against the main worktree root, where shared session scratch resolves. Frameboard appends the project and page, so the archive lands at `.canon/<project>/<page>/`.
123
+ 6. Delete every page on the run's list with `frameboard page delete <page>`, except a picked page on a named board. Touch no page the run did not add, and never remove a page folder by hand.
123
124
  7. End the serve command if this run started it, since Frameboard carries no stop verb. Leave a server the operator started running.
124
125
  8. Leave the renders in a live track's `evidence/<slug>/renders/`, since `plan-groundwork` treats evidence as durable.
125
- 9. Report each page whose delete is refused, naming its `ref` and the `error.code`. The pick is applied either way.
126
+ 9. Report each page or frame whose delete is refused, naming its `ref` and the `error.code`. The pick is applied either way.
126
127
  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.
127
128
 
128
129
  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 board is a second design nobody maintains.
129
130
 
131
+ ### On a named board
132
+
133
+ A board `canon/config/design.toml` names is the one the project's design sync reads, and once `design-record` lands the pick, the sync's mapping points at the winning frame. Deleting that page leaves a later redraw nothing to read.
134
+
135
+ - Keep the picked round's page and its winning frame
136
+ - Delete each losing arm on it with `frameboard frame delete <page>/arm-<id>`, after item 4's capture has archived it
137
+ - Delete every other page on the run's list as item 6 states
138
+
130
139
  ## Reading a measurement
131
140
 
132
141
  A capture proves appearance and a measurement proves a relationship, so reach for the second whenever the claim is a number, such as a contrast ratio, a column width, or a tap target. `canon drive` runs the probes and ships the failure modes each one carries.
@@ -142,7 +151,7 @@ A capture proves appearance and a measurement proves a relationship, so reach fo
142
151
  Cite these rather than restating them. A step reimplemented here rots against the skill that owns it.
143
152
 
144
153
  - `plan-feature` plans the work once the pick is made, and declares the pull request boundary that plan carries
145
- - `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
154
+ - `design-record` lands the winning frame in the reference folder and its values in the design document, and runs before item 4's capture and item 6's deletes, which keep the picked page on named boards
146
155
  - `design-taste` carries the layer catalog, the ordering, grey-boxing, and the defaults an arm should reach past
147
156
  - `write-human` carries the voice for any copy an arm puts in front of a reader
148
157
 
@@ -1,12 +1,18 @@
1
1
  # The Frameboard board
2
2
 
3
- Read before the first `frameboard` verb a `pick-by-eye` run sends. It carries where the board sits, how the verbs are reached, how the server starts, and how a selection resolves to an answer.
3
+ Read before the first `frameboard` verb a `design-pick` run sends. It carries where the board sits, how the verbs are reached, how the server starts, and how a selection resolves to an answer.
4
4
 
5
5
  ## Reaching the board
6
6
 
7
- Resolve `<board>` as `.canon/canvas/` against the main worktree root, the way `session-worktree` resolves it, since a linked worktree holds no copy of the gitignored folder.
7
+ Resolve `<board>` and `<project>` from the `board` and `project` keys of `canon/config/design.toml`, read at the main worktree root per `${CLAUDE_SKILL_DIR}/references/design-config.md`. A missing file or key falls back to `.canon/board/` and `picks`.
8
8
 
9
- - Pass `--root <board> --project picks --json` to every verb unless the step says otherwise, so no verb relies on the only-project default
9
+ - Stop before starting a board when `<board>` came from that fallback, `.canon/board/` is absent, and `.canon/canvas/` exists
10
+ - Report `❌ The board is still at .canon/canvas/. Run canon migrate record-layout --write, then re-run.` on that stop
11
+ - A board started there drafts on an empty page set and leaves the migration a standing collision
12
+
13
+ Resolve `<board>` against the main worktree root, the way `session-worktree` resolves it, since a linked worktree holds no copy of the gitignored folder.
14
+
15
+ - Pass `--root <board> --project <project> --json` to every verb unless the step says otherwise, so no verb relies on the only-project default
10
16
  - Where `frameboard` is not on PATH, run every verb as `bunx -y frameboard@0.6 <verb>`. Say so once and keep that form for the run.
11
17
  - The pin holds the minor, since record shapes move across a pre-1.0 minor
12
18
 
@@ -30,13 +36,13 @@ frameboard serve --root <board> --no-open --tokens <stylesheet> --json
30
36
 
31
37
  Read `frameboard selection --root <board> --json` when the operator's answer points at the board, such as "the selected one". Resolve it against the record's `project` and `page` as well as its `frames`, since every round reuses the `arm-<id>` names.
32
38
 
33
- | Selection | Reading |
34
- | ------------------------------------------------------------- | -------------------------------------------------------- |
35
- | One frame in `frames`, on the current round's page in `picks` | The pick |
36
- | One frame in `frames`, on an earlier round's page | A revert, so name the round back before acting |
37
- | An `element` inside a picked frame | A correction the loop carries by its `index` and `hash` |
38
- | Several entries in `frames` | Ask which one rather than taking the first |
39
- | Empty `frames`, another project, or a page the run never made | No answer, so ask again rather than guess |
40
- | `tabs: 0`, or a `server-not-running` refusal | No board is open, so hand the address over and ask again |
39
+ | Selection | Reading |
40
+ | ----------------------------------------------------------------- | -------------------------------------------------------- |
41
+ | One frame in `frames`, on the current round's page in `<project>` | The pick |
42
+ | One frame in `frames`, on an earlier round's page | A revert, so name the round back before acting |
43
+ | An `element` inside a picked frame | A correction the loop carries by its `index` and `hash` |
44
+ | Several entries in `frames` | Ask which one rather than taking the first |
45
+ | Empty `frames`, another project, or a page the run never made | No answer, so ask again rather than guess |
46
+ | `tabs: 0`, or a `server-not-running` refusal | No board is open, so hand the address over and ask again |
41
47
 
42
48
  Pass the element's `hash` to `frameboard edit --hash` with its `index`. A frame rewritten since the operator picked refuses with `stale-address` rather than landing on another element, so ask for the pick again on that refusal.
@@ -0,0 +1,33 @@
1
+ ---
2
+ title: Design config
3
+ description: The canon/config/design.toml keys board and project, their defaults, and how a design-pick run resolves the board it drafts on
4
+ ---
5
+
6
+ # Design config
7
+
8
+ Read before the first `frameboard` verb a `design-pick` run sends. A project names the Frameboard board its design sync reads in `canon/config/design.toml` at the main worktree root, and the run reads that file and never writes it.
9
+
10
+ ```toml
11
+ board = ".canon/board"
12
+ project = "picks"
13
+ ```
14
+
15
+ ## Keys
16
+
17
+ | Key | Holds | Default |
18
+ | --------- | ------------------------------------------------------- | --------------- |
19
+ | `board` | The board folder a round drafts on, under the main root | `.canon/board/` |
20
+ | `project` | The Frameboard project a round's pages go in | `picks` |
21
+
22
+ Each key falls back on its own, so a file naming `board` alone moves the board and keeps the project at `picks`.
23
+
24
+ - Resolve `board` against the main worktree root even when the run sits in a linked worktree, since the board folder is gitignored and a linked worktree holds no copy of it
25
+ - Leave `project` at `picks` on a named board unless the operator wants otherwise, so rounds sit on the board the sync reads and stay apart from the accepted frames
26
+ - Stop on a file that does not parse or a key that is not a string, naming the file's path. Falling back there would draft the round where the sync never looks.
27
+ - The archive lands at `.canon/<project>/<page>/`, so it follows `project`. Stop on a `project` naming a `.canon/` folder another record owns, such as `plans` or `tasks`.
28
+
29
+ ## When the file is absent
30
+
31
+ The run drafts on `.canon/board/` in `picks`, the folder Frameboard keeps its design board in, and asks nothing.
32
+
33
+ Set the file when the project's design sync reads a board other than `.canon/board/`. A round drafted there lands through `design-record` without a redraw, and Step 6 of the skill body keeps the winning page for the sync's mapping.
@@ -24,10 +24,10 @@ Each project invents its own grouping, and its index restates the file tree rath
24
24
  - Write, copy, or delete a reference file by hand, or capture frames in place of a missing sync
25
25
  - Land a candidate the operator has not picked
26
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 `pick-by-eye` should hand off to it
27
+ - Be reached only by the author typing its name, since a pick from `design-pick` should hand off to it
28
28
 
29
29
  ## Out of scope
30
30
 
31
- - Drafting candidates and taking the pick, which `pick-by-eye` owns
31
+ - Drafting candidates and taking the pick, which `design-pick` owns
32
32
  - Drawing, selecting, and capturing frames on a board, which Frameboard owns
33
33
  - Judging whether a design is good, which `design-taste` owns
@@ -1,6 +1,6 @@
1
1
  ---
2
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 a board, which is Frameboard, or to judge a design, which is `design-taste`.
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 `design-pick`, to draw frames on a board, which is Frameboard, or to judge a design, which is `design-taste`.
4
4
  metadata:
5
5
  family: ship
6
6
  ---
@@ -25,12 +25,12 @@ The output has no standard of quality either. A model with no stated direction d
25
25
  - Admit a rule an unguided model already gets right, another surface owns, a threshold settles, or no single line could violate
26
26
  - Restate the correctness floor or the banned characters, or trade accessibility and the state set against an aesthetic preference
27
27
  - Express intensity as a numeric scale, or claim a round follows these rules when nothing measures it
28
- - Be reached only by an author typing its name, since `pick-by-eye`'s declared read is the intended caller
28
+ - Be reached only by an author typing its name, since `design-pick`'s declared read is the intended caller
29
29
 
30
30
  ## Out of scope
31
31
 
32
32
  - Accessibility, keyboard interaction, state coverage, forms, and rendered copy, which `ui-craft` owns
33
33
  - The focus ring's floors, which `ui-craft` owns, though its weight is this skill's
34
- - The candidate loop and the pick, which `pick-by-eye` owns
34
+ - The candidate loop and the pick, which `design-pick` owns
35
35
  - The shape of the project's design document, which `design-record`'s design reference governs
36
36
  - Prose on the surface being designed, which `write-human` and `markdown-craft` own
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: design-taste
3
- description: Carries the layer model that decides which design decision settles first, the rules that keep a surface coherent across sections, and the catalog of defaults a model reaches for when nothing states a direction. Use when drafting or judging an interface, a page, or any rendered surface, when output reads generic or templated, when redesigning something that already exists, or when asked to "make this look designed", "why does this look like AI made it", "give it taste", "what layer is this decision at", or "grey-box this first". Do NOT use for accessibility, forms, or state coverage, which `ui-craft` carries, for the shape of the project's design document, which `design.md` governs, or to run the candidate loop, which is `pick-by-eye`.
3
+ description: Carries the layer model that decides which design decision settles first, the rules that keep a surface coherent across sections, and the catalog of defaults a model reaches for when nothing states a direction. Use when drafting or judging an interface, a page, or any rendered surface, when output reads generic or templated, when redesigning something that already exists, or when asked to "make this look designed", "why does this look like AI made it", "give it taste", "what layer is this decision at", or "grey-box this first". Do NOT use for accessibility, forms, or state coverage, which `ui-craft` carries, for the shape of the project's design document, which `design.md` governs, or to run the candidate loop, which is `design-pick`.
4
4
  metadata:
5
5
  family: build
6
6
  ---
@@ -157,8 +157,8 @@ Run `${CLAUDE_SKILL_DIR}/references/preflight.md` against the output. It is the
157
157
 
158
158
  Five neighbors own the rest.
159
159
 
160
- - The candidate loop, the arm set, the render, and the pick: `pick-by-eye`
160
+ - The candidate loop, the arm set, the render, and the pick: `design-pick`
161
161
  - The shape of the project's design document and where its values live: `${CLAUDE_SKILL_DIR}/../design-record/references/design.md`
162
162
  - The folder holding the accepted designs and how a reference lands in it: `${CLAUDE_SKILL_DIR}/../design-record/references/folder.md`
163
- - Reading source for roughness: `ux-audit`. Measuring what a running interface costs to paint: `ux-measure`
163
+ - Reading source for roughness: `ui-audit`. Measuring what a running interface costs to paint: `ui-measure`
164
164
  - Prose on the surface being designed: the `write-human` skill
@@ -101,5 +101,5 @@ Every word on the surface states what is true of it.
101
101
 
102
102
  ## Handover
103
103
 
104
- - [ ] The weakest thing on the surface is named out loud, per `pick-by-eye` Step 3, and fixed where naming it would embarrass the work
104
+ - [ ] The weakest thing on the surface is named out loud, per `design-pick` Step 3, and fixed where naming it would embarrass the work
105
105
  - [ ] The floor the `ui-craft` skill carries has been applied, not assumed
@@ -28,5 +28,5 @@ Prose bans hold on files the hook watches and not on text leaving through `gh`,
28
28
  ## Out of scope
29
29
 
30
30
  - Reporting a toolkit defect from a target project, which `canon-feedback` owns
31
- - Triaging issues already filed, which `canon-feedback-triage` owns
31
+ - Triaging the toolkit's feedback issues, which its maintainers do in its own repository
32
32
  - Opening a pull request, which `git-pr` owns
@@ -97,7 +97,7 @@ Fix the feedback CLI so it applies the `feedback` label.
97
97
 
98
98
  ## Details
99
99
 
100
- `canon feedback` opens an issue with no label, so `canon-feedback-triage` never lists it.
100
+ `canon feedback` opens an issue with no label, so the toolkit's triage never lists it.
101
101
 
102
102
  ## Context
103
103
 
@@ -85,7 +85,7 @@ Every `- Suggested:` line takes senior judgment, picking the best option in one
85
85
 
86
86
  - Suggest a real default when best practice, the codebase, or prior context points to one
87
87
  - Before `## Files to touch`, load `canon:codebase-layout` for a new path (its reason) and `canon:api-design` for a changed verb, flag, output, record shape, or endpoint. Report either if missing.
88
- - 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
88
+ - Fill `## Design references` with the `canon/design/<surface>/` folder per rendered surface, or `None identified.`, and `## Reference images` with each untracked image that shaped the plan
89
89
  - Write `## Verification` as one bullet per outcome naming the test or command that proves it, with a grep bullet per `## Verbatim` block of settled wording
90
90
  - Write `## Review focus` as the inputs or states that would break the change, carrying the risk you understood to the executor and the reviewer
91
91
 
@@ -75,8 +75,9 @@ The document opens with `# Feature: <short title>` and one paragraph stating wha
75
75
  | `## Current behavior` | each command run against the thing being changed and what it showed | When the change touches something that runs |
76
76
  | `## Constraints` | durable rules the work must respect | When supplied |
77
77
  | `## Files to touch` | each file with a one-line reason | Always |
78
- | `## Verbatim` | settled wording that lands unchanged in an existing file, one H3 per block | When wording is settled |
78
+ | `## Verbatim` | settled wording that lands unchanged in a file, one H3 per block | When wording is settled |
79
79
  | `## Design references` | the tracked design folders the change builds against, each with its surface | When Files to touch names a rendered-surface file |
80
+ | `## Reference images` | the untracked images the plan was shaped against, each from the main root | When an image shaped the plan |
80
81
  | `## Verification` | the test or command that proves each outcome | Always |
81
82
  | `## Risks` | conflicts, coupling, and the tricky spots | Always |
82
83
  | `## Review focus` | the inputs or states that would break the change, for the reviewer | Always |
@@ -166,22 +167,24 @@ Re-test a stamped constraint before honoring it, fetching and scoping the log in
166
167
  git fetch origin main --quiet && git log <commit>..origin/main --oneline -- <the paths the constraint names>
167
168
  ```
168
169
 
169
- ### Fan-in and ready constraints
170
+ ### Fan-in constraints
170
171
 
171
172
  A batch in a fan-in set declares its side in a constraint bullet, ``Fan-in member of `feature-<integrator>` `` on a member and ``Fans in `feature-<a>`, `feature-<b>` `` on the integrator. `batches.md` holds when to fan in, and `canon records validate plans` reports `fan-in-unmatched` for a set whose two sides disagree.
172
173
 
173
- A constraint naming a `.canon/ready/` folder is a third shape beside the hold and the shared path. It makes that folder's files the verbatim source for the paths this plan's `## Files to touch` lists, per `ready.md`, so the executing session copies those paths rather than authoring them.
174
-
175
174
  ### Verbatim
176
175
 
177
- A `## Verbatim` section carries wording someone settled, landing in an existing file exactly as written. Wording the planner only proposes stays a `- Suggested:` question, and a whole new file goes in the ready folder per `ready.md`, so the two never describe the same file.
176
+ A `## Verbatim` section carries wording someone settled, landing in a file exactly as written. Wording the planner only proposes stays a `- Suggested:` question, so the two never describe the same file.
178
177
 
179
178
  - Give each block an H3 naming it, then a lead sentence with the action, the full path, and the anchor, then a fenced `text` block holding the wording
180
- - Name the action as Add, Insert, or Replace. A Replace quotes the old line in the lead's code span.
179
+ - Name the action as Add, Insert, Replace, or Create. A Replace quotes the old line in the lead's code span.
181
180
  - Write the block as the project's formatter leaves it, since a formatter that re-pads a table row or rewraps a line makes the grep fail on correct text
182
181
  - Name the outcome in a grep bullet and put a command past 200 characters in a fenced `bash` block under it, since `S4` reports a longer bullet
183
182
  - Give each block one `## Verification` bullet running `grep -cF -e` on its whole first line against its file, so a reworded line fails a check the reviewer already runs.
184
183
 
184
+ A Create block makes a new file, so its lead names a path that does not exist yet and no anchor. Its grep bullet takes the first distinctive line, such as the `title:` line or the H1, since a markdown file opens on `---` and that line matches any file with frontmatter.
185
+
186
+ Keep a Create block to 80 lines. A longer new file goes in `## Files to touch` for the executing session to write, since a plan carrying a whole skill body costs every session that reads it.
187
+
185
188
  ### Design references
186
189
 
187
190
  A plan whose `## Files to touch` names a rendered-surface file (`.tsx`, `.jsx`, `.astro`, `.vue`, `.svelte`, `.html`, or `.css`) carries this section. It tells the building session which accepted design to open before it writes a line.
@@ -191,6 +194,14 @@ A plan whose `## Files to touch` names a rendered-surface file (`.tsx`, `.jsx`,
191
194
  - Cite a tracked folder only, since the building session opens its light and dark images and its frame HTML from the working tree
192
195
  - `canon records validate plans` reports `section-missing` for a plan that names a rendered-surface file and omits the section
193
196
 
197
+ ### Reference images
198
+
199
+ A plan shaped against an image no tracked folder holds carries this section, such as drive evidence, an image in an intake item, or a design board frame. It tells the building session which images to open before its first edit, and it stays apart from `## Design references`, which cites tracked folders alone.
200
+
201
+ - Give each entry an image path and what the image shows, as one bullet
202
+ - Write each path from the main worktree root, since these images are gitignored and a linked worktree holds no copy. A path relative to a linked worktree resolves nowhere.
203
+ - Leave the section out when no image shaped the plan. It is optional, and `canon records validate plans` reports nothing on a plan without it.
204
+
194
205
  ### Verification
195
206
 
196
207
  Every outcome reaches the review with its proof named.
@@ -325,6 +336,10 @@ Add as <where> in `<path/to/file>`, after <anchor>.
325
336
 
326
337
  - `canon/design/<surface>/`: <the surface it governs>
327
338
 
339
+ ## Reference images
340
+
341
+ - `.canon/intake/<nn>-<slug>/evidence/<name>.png`: <what the image shows>
342
+
328
343
  ## Verification
329
344
 
330
345
  ### <Outcome group>
@@ -37,7 +37,7 @@ Write only inside `.canon/groundwork/<nn>-<slug>/`. A feature plan, source chang
37
37
 
38
38
  What a spike produces stays inside the track, under `.canon/groundwork/<nn>-<slug>/evidence/`, which the first rule already permits. Mode detection matches only top-level entries, so a nested folder cannot be mistaken for a track, and scratch holds only what can be deleted without loss.
39
39
 
40
- A `pick-by-eye` run invoked from inside a live track follows its own branch for this. It writes its renders to `evidence/` here, and drafts its candidates as pages on the Frameboard board at `.canon/canvas/` that its close deletes.
40
+ A `design-pick` run invoked from inside a live track follows its own branch for this. It writes its renders to `evidence/` here, and drafts its candidates as pages on the Frameboard board `design-pick` resolves, where its close removes the round. On a board `canon/config/design.toml` names, the close keeps the picked page.
41
41
 
42
42
  ### Reading and backing
43
43
 
@@ -63,9 +63,9 @@ canon pr evidence <number> --check --json
63
63
  - Skip filming when the record's `reel.head` is a prefix of the `tip` that `canon pr head <number> --json` reports, since the posted reel already shows this head
64
64
  - With no checklist from either source, skip silently, since nothing names an interaction to film
65
65
 
66
- Invoke `canon:ui-record` in pull request mode, passing the number, the local `url`, and the checklist. It films, checks each beat's closing still, pushes the reel to `canon/frames`, and hands back a `link` or a skip reason.
66
+ Invoke `canon:ui-film` in pull request mode, passing the number, the local `url`, and the checklist. It films, checks each beat's closing still, pushes the reel to `canon/frames`, and hands back a `link` or a skip reason.
67
67
 
68
- Report it rather than proceeding silently when `canon:ui-record` does not resolve, and post the evidence without a reel.
68
+ Report it rather than proceeding silently when `canon:ui-film` does not resolve, and post the evidence without a reel.
69
69
 
70
70
  - Hold a `link` for the evidence step, which embeds it under the addresses
71
71
  - Hold a skip's reason and message for the closing report. A skip never stops the chain, and a reel already on the comment carries forward under the older head it names.
@@ -117,7 +117,7 @@ No branch and no worktree exist here and none is created. A planner writes one g
117
117
  claude --bg --model <model> -n "planner-<project>-<slug>" "Run /canon:role-planner, then /canon:plan-feature <task>. Your controller is the session whose sessionId is <dispatcher-id>. Resolve its current name from that id through canon sessions list --json, which carries sessionId per row, at the moment you send, and never resolve an addressee by name prefix. Message it when the plan lands, carrying the path and what the task file got wrong, and message it again if you stop on a question."
118
118
  ```
119
119
 
120
- `<task>` is the row's task file path and `<slug>` the slug its plan will take, resolved off the row. `<dispatcher-id>`, `<model>`, and `<project>` resolve as above, and the prefix reads `planner-` because it marks the role of the session it names.
120
+ `<task>` is the row's task file path and `<slug>` the slug its plan will take, resolved off the row. `<dispatcher-id>`, `<model>`, and `<project>` resolve as above, and the prefix reads `planner-` because it marks the role of the session it names. Then wait per `orchestrator-planning-wait.md`.
121
121
 
122
122
  ### Which checks bind
123
123
 
@@ -131,9 +131,9 @@ What a planning dispatch owes instead is the reverse reading, since a row planne
131
131
 
132
132
  ### One row per dispatch
133
133
 
134
- A session reused across a batch pays the context load once and ages its picture of the tree while it works, which is why the in-flight read sits on the task rather than the batch. One that compacts mid-batch loses the reasoning behind its earlier plans with nothing reporting it.
134
+ A reused session pays the context load once and ages its picture of the tree, which is why the in-flight read sits on each row. One that compacts loses the reasoning behind its earlier plans unreported, so `role-planner` stops it when the operator ends it or a compaction nears.
135
135
 
136
- Cap a reused session where the saving is worth it and say what the cap was.
136
+ Hold all planning of a row any talk session has said by message it is planning, a drive session included, whether by a launch or by `plan-feature` here, unless the operator asks for a cold planner. That session holds what the operator said about the row, and plans a filed row only once it is named back to it.
137
137
 
138
138
  ## Dispatch a talk session
139
139
 
@@ -95,7 +95,7 @@ A local formatter removing the shape on contact says nothing about a target runn
95
95
 
96
96
  ## The plan half
97
97
 
98
- Plan what the pass clears, and any `## Needs a plan` row whose only blocker is the missing plan. This pass runs while workers build and the session is idle, when planning costs the critical path nothing, and a row cleared with no plan is looked at again next pass.
98
+ Plan what the pass clears, and any `## Needs a plan` row whose only blocker is the missing plan, skipping a row a talk session holds per `orchestrator-launch.md`. This pass runs while workers build and the session is idle, when planning costs the critical path nothing, and a row cleared with no plan is looked at again next pass.
99
99
 
100
100
  - Run `plan-feature` for each, carrying the constraint per in-flight track that `## The loop` in `role-orchestrator` requires
101
101
  - Verify each plan against the tree the way that step does, since several branches are already changing it
@@ -0,0 +1,24 @@
1
+ ---
2
+ title: Orchestrator planning wait
3
+ description: How the orchestrator waits in the background on a row whose plan a planner is still writing, through canon tasks launchable, and how it branches on the record the wait ends on
4
+ ---
5
+
6
+ A row whose plan a planner is still writing has nothing to dispatch yet. Run the wait in the background rather than grepping the task file on a loop, and act on the wake:
7
+
8
+ ```bash
9
+ canon tasks launchable <task> --wait --json
10
+ ```
11
+
12
+ The verb resolves the task's `Plan:` line and runs the `plan-answers` gate on the plan it names, re-reading every 30 seconds for up to 1800 seconds by default. It keys on the line rather than the plan file. A planner links a plan only after it validates, so a half-written plan never wakes the loop.
13
+
14
+ ## Branch on the record
15
+
16
+ Branch on the record's `reason` rather than on the exit code, which a shell function wrapping `canon` can flatten to zero.
17
+
18
+ - `launchable`: the plan waits on nobody, so run `${CLAUDE_SKILL_DIR}/references/orchestrator-dispatch.md` from the candidate on, since the wait never reads the branch or the conflict check
19
+ - `timeout`: read `plan` and `open` off the last reading, then act on which one held the row
20
+ - No `plan` means nothing was linked in time, so check the planner is still live and re-arm the wait
21
+ - A non-empty `open` names the questions holding the row, so report each label and reason to the operator, then re-arm the wait
22
+ - A refusal such as `several-plans`, `archived`, or `no-match` means the row cannot launch as it stands, so name the reason and fall back to the human
23
+
24
+ A one-shot read without `--wait` reports `reason: unlinked`, `open`, or `launchable` at once. It suits a pass that only needs the row's state now.
@@ -86,10 +86,11 @@ Each finding in that file opens with the bold source-and-date label that `${CLAU
86
86
 
87
87
  ## The channel
88
88
 
89
- The controlling session cannot watch this one read, so two messages are owed and nothing else.
89
+ The controlling session cannot watch this one read, so the messages below are owed and nothing else.
90
90
 
91
91
  - Announce the record as the file lands, carrying its path and what the task file got wrong. Write no summary beside it, which is a second account of a document the reader is about to open.
92
92
  - Send a block out as a message before it becomes an interactive prompt.
93
+ - Name the handed rows still unplanned when a reused session stops under `## Lifetime`
93
94
  - Send nothing on progress, which rebuilds on this side the poll the announcement retires on the other
94
95
 
95
96
  ### Addressing
@@ -120,5 +121,6 @@ The operator being present is an assumption the launch carries. A talk planner w
120
121
  ## Lifetime
121
122
 
122
123
  - The role runs from the launch to the record landing, and the operator closes a talk session. A session handed a second row works it under the same role and reads the tree again for it.
123
- - A reused session's picture of the tree ages, and it nears a compaction that silently drops the reasoning behind its earlier records. Cap a reused session rather than letting it run the board.
124
+ - A reused session's picture of the tree ages, and a compaction silently drops the reasoning behind its earlier records
125
+ - Run the in-flight read again before each handed row, and stop when the operator ends the session or a compaction nears, telling the controller which rows are still unplanned
124
126
  - Treat this body as possibly older than the branch under it. A plugin skill loads from the marketplace cache rather than from the working tree.
@@ -18,17 +18,16 @@ This body states the role, the boundaries, and the channel, and starts no step o
18
18
 
19
19
  ## Where the session stands
20
20
 
21
- - Resolve `.canon/plans/`, `.canon/tasks/`, `.canon/review/`, and `.canon/ready/` at the main worktree root, never the linked worktree. Being gitignored, they are absent there rather than empty.
21
+ - Resolve `.canon/plans/`, `.canon/tasks/`, and `.canon/review/` at the main worktree root, never the linked worktree. Being gitignored, they are absent there rather than empty.
22
22
  - Report a plan that fails to resolve as unreadable from here, naming the main-root path. Reporting the task as having no plan is wrong about the world, and a reader cannot tell the two apart.
23
23
  - Build the plan the launch named. Never write a second one when the path fails to resolve, since a row citing a plan already has one.
24
24
  - Load `ui-craft` before editing a rendered surface, pointer rule or not
25
25
  - Keep a task list from launch, one item per slice, and tick each as its slice lands. Skip it on a host that offers no list tool, since the list is for the operator watching and not a gate.
26
26
 
27
- ### Ready folders and the draft mark
27
+ ### The draft mark
28
28
 
29
- A ready folder and the draft mark each carry work another session already did, so this one preserves both.
29
+ The draft mark holds the merge until the reviews close, so this session preserves it.
30
30
 
31
- - Copy a ready folder's files verbatim to the paths its plan's `**Constraints:**` block names, editing only what the gate or the overview's list requires, since a rewrite discards the handoff
32
31
  - The ship chain marks the pull request a draft, and only `canon pr lift` or the operator un-marks it
33
32
  - Report a flag reading ready once and leave it. It passed every gate the verb reads or a person readied it, which GitHub requires before a merge, so re-drafting fights them.
34
33
  - Leave the lift to the reviewers, who run `canon pr lift` on their close, with the controlling session as fallback
@@ -53,9 +52,9 @@ Run `canon pr drive-copy --json` before starting `dev`. On `copied`, start it wi
53
52
 
54
53
  A hand-run `git-ship` or `git-pr` starts no server, since only a worker has a lifetime to own one.
55
54
 
56
- ### Building against a design reference
55
+ ### Building against design references and images
57
56
 
58
- A plan carrying a `**Design references:**` section names the accepted design for the surface it changes. Open it before building, since the build matches it and a worker that reads the dark image alone ships a light theme nobody saw.
57
+ A plan's `## Design references` names the accepted design per surface, and `## Reference images` names images it was shaped against by main-root path. Either can appear alone. Open both before building, since a worker reading the dark image alone ships a light theme nobody saw.
59
58
 
60
59
  - Open each cited folder's light and dark images and its frame HTML before the first edit to that surface
61
60
  - Take sizes, spacing, and colors from the frame HTML rather than from the image
@@ -141,7 +141,7 @@ A task with no origin is lost context or work nobody decided to do. The reverse
141
141
 
142
142
  - Write the path relative to `.canon/tasks/`, as `../plans/`, `../groundwork/`, and `../intake/`. A path from the project root resolves to nothing in an editor rooted there.
143
143
  - `Issue:` stays a bare `#NNN`, since a full URL writes the remote into a gitignored file. Several issues list comma-separated, each getting a `git-pr` closing line.
144
- - `Ready:` links `../ready/<nn>-<slug>/`, the folder the plan copies from, only when it exists. `canon tasks archive` reads it to move the folder, falling back to a path in the plan.
144
+ - `Ready:` is a line older tasks carry, linking `../ready/<nn>-<slug>/`. No new task gains one, and `canon tasks archive` still reads it to move and retarget the folder.
145
145
 
146
146
  ### The `Plan:` line
147
147
 
@@ -37,7 +37,7 @@ A branch report is read once, by the session addressing it. The durable record i
37
37
 
38
38
  ### What stays
39
39
 
40
- Do not sweep `ux-audit-*.md` or `ux-measure-*.md`, which are standalone deliverables. They sit at `.canon/review/` itself rather than under a producer folder, so the glob never reaches them.
40
+ Do not sweep `ui-audit-*.md` or `ui-measure-*.md`, which are standalone deliverables. They sit at `.canon/review/` itself rather than under a producer folder, so the glob never reaches them.
41
41
 
42
42
  Output one line per file swept:
43
43