@erclx/canon 5.53.0 → 5.54.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 (94) hide show
  1. package/CHANGELOG.md +10 -0
  2. package/README.md +10 -9
  3. package/claude/.claude-plugin/plugin.json +1 -1
  4. package/claude/skills/canon-cli/SKILL.md +5 -5
  5. package/claude/skills/design-identity/REQUIREMENT.md +2 -2
  6. package/claude/skills/design-identity/SKILL.md +6 -6
  7. package/claude/skills/design-record/REQUIREMENT.md +2 -2
  8. package/claude/skills/design-record/SKILL.md +4 -4
  9. package/claude/skills/design-record/references/folder.md +1 -1
  10. package/claude/skills/design-taste/REQUIREMENT.md +1 -1
  11. package/claude/skills/draw-figure/REQUIREMENT.md +1 -1
  12. package/claude/skills/draw-figure/SKILL.md +1 -1
  13. package/claude/skills/pick-by-eye/REQUIREMENT.md +4 -4
  14. package/claude/skills/pick-by-eye/SKILL.md +34 -41
  15. package/claude/skills/pick-by-eye/references/board.md +42 -0
  16. package/claude/skills/pick-by-eye/references/live-arms.md +3 -3
  17. package/claude/skills/plan-groundwork/SKILL.md +1 -1
  18. package/claude/skills/teach-craft/REQUIREMENT.md +1 -1
  19. package/claude/skills/teach-craft/SKILL.md +32 -1
  20. package/claude/skills/teach-craft/references/adopted.md +113 -0
  21. package/claude/skills/teach-craft/references/lesson-craft.md +10 -2
  22. package/claude/skills/teach-craft/references/pedagogy.md +29 -2
  23. package/docs/agents/install-and-sync.md +0 -8
  24. package/docs/target/migrations.md +8 -3
  25. package/docs/target/projects.md +1 -1
  26. package/docs/workflow/skill-map.md +0 -1
  27. package/docs/workflow/visual-design-workflow.md +1 -4
  28. package/governance/detect.toml +1 -6
  29. package/governance/renames.toml +0 -1
  30. package/package.json +2 -5
  31. package/src/claude/cases/misc.ts +0 -5
  32. package/src/claude/skills-audit.ts +1 -0
  33. package/src/cli/help.ts +0 -3
  34. package/src/cli.ts +0 -2
  35. package/src/commands/design.ts +16 -315
  36. package/src/commands/sync.ts +4 -5
  37. package/src/design/regen.ts +5 -32
  38. package/src/design/render.ts +1 -1
  39. package/src/design/tokens.ts +3 -2
  40. package/src/gate/stages.ts +4 -10
  41. package/src/gov/audit.ts +1 -6
  42. package/src/markdown/scope.ts +2 -4
  43. package/src/shipped/references.ts +1 -2
  44. package/src/sync/check.ts +4 -29
  45. package/src/sync/stamp.ts +6 -6
  46. package/src/sync/target.ts +1 -4
  47. package/tooling/claude/reference.md +1 -1
  48. package/tooling/claude/seeds/canon/DESIGN.md +1 -1
  49. package/claude/skills/canvas-board/REQUIREMENT.md +0 -35
  50. package/claude/skills/canvas-board/SKILL.md +0 -143
  51. package/claude/skills/canvas-board/references/canvas.md +0 -170
  52. package/governance/rules/ui/canvas.md +0 -13
  53. package/src/canvas/address.ts +0 -227
  54. package/src/canvas/arrange.ts +0 -66
  55. package/src/canvas/capture.ts +0 -391
  56. package/src/canvas/client/app.tsx +0 -188
  57. package/src/canvas/client/inspector/align-grid.tsx +0 -162
  58. package/src/canvas/client/inspector/color-field.tsx +0 -398
  59. package/src/canvas/client/inspector/color-inputs.tsx +0 -139
  60. package/src/canvas/client/inspector/color-picker.tsx +0 -668
  61. package/src/canvas/client/inspector/color-space.ts +0 -240
  62. package/src/canvas/client/inspector/field.tsx +0 -263
  63. package/src/canvas/client/inspector/fields.css +0 -763
  64. package/src/canvas/client/inspector/section.tsx +0 -27
  65. package/src/canvas/client/inspector/size-field.tsx +0 -69
  66. package/src/canvas/client/inspector/token-select.tsx +0 -109
  67. package/src/canvas/client/inspector/values.ts +0 -297
  68. package/src/canvas/client/inspector.tsx +0 -692
  69. package/src/canvas/client/keys.ts +0 -71
  70. package/src/canvas/client/layers.tsx +0 -118
  71. package/src/canvas/client/main.tsx +0 -71
  72. package/src/canvas/client/pages-panel.tsx +0 -212
  73. package/src/canvas/client/panel-handle.tsx +0 -90
  74. package/src/canvas/client/selection.tsx +0 -199
  75. package/src/canvas/client/shell.css +0 -762
  76. package/src/canvas/client/state.ts +0 -792
  77. package/src/canvas/client/surface.tsx +0 -803
  78. package/src/canvas/client/theme-panel.tsx +0 -55
  79. package/src/canvas/client/tools.tsx +0 -153
  80. package/src/canvas/content.ts +0 -781
  81. package/src/canvas/edit.ts +0 -575
  82. package/src/canvas/editing.ts +0 -203
  83. package/src/canvas/fit.ts +0 -238
  84. package/src/canvas/global.d.ts +0 -15
  85. package/src/canvas/history.ts +0 -116
  86. package/src/canvas/index.html +0 -20
  87. package/src/canvas/server.ts +0 -766
  88. package/src/canvas/tokens.ts +0 -221
  89. package/src/commands/canvas.ts +0 -1097
  90. package/src/design/adapter.ts +0 -59
  91. package/src/design/base.css +0 -203
  92. package/src/design/brand-favicon.ts +0 -18
  93. package/src/design/neutral.ts +0 -127
  94. package/src/design/project-fonts.ts +0 -392
package/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Changelog
2
2
 
3
+ ## [5.54.0](https://github.com/erclx/canon/compare/v5.53.0...v5.54.0) (2026-10-21)
4
+
5
+
6
+ ### Features
7
+
8
+ * **canvas:** move the design board to Frameboard and retire the canvas ([#2593](https://github.com/erclx/canon/issues/2593)) ([19e0d4f](https://github.com/erclx/canon/commit/19e0d4f4c0022f02bdc94253a743ef757ec44bcc))
9
+ * **ci:** prove canon on macOS with the stock bash ([#2591](https://github.com/erclx/canon/issues/2591)) ([0220169](https://github.com/erclx/canon/commit/0220169cf6f10fb45ff07ffba7fb58a708ade5e2))
10
+ * **design:** retire the canvas-only design verbs and sync domain ([#2598](https://github.com/erclx/canon/issues/2598)) ([ed15567](https://github.com/erclx/canon/commit/ed1556768df49a015b8c9a921df41382e2d19e89))
11
+ * **skills:** give teach-craft a cited source ledger ([#2592](https://github.com/erclx/canon/issues/2592)) ([d67d18c](https://github.com/erclx/canon/commit/d67d18ccf6de3a04963fc20c0ff0624ea7b479f4))
12
+
3
13
  ## [5.53.0](https://github.com/erclx/canon/compare/v5.52.0...v5.53.0) (2026-10-21)
4
14
 
5
15
 
package/README.md CHANGED
@@ -66,15 +66,16 @@ Each domain has a canonical source in this repo and a thin install or sync CLI o
66
66
 
67
67
  ### Domain catalog
68
68
 
69
- | Domain | What it is | How it reaches you |
70
- | -------------- | ----------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
71
- | Plugin skills | Skills that plan a feature, review a diff, sync the planning docs, and run the ship chain | Loaded live from the plugin, never copied |
72
- | Governance | Coding and authoring rules that load into a Claude session when a matching path is edited | Installed per project by `canon gov install`, refreshed by sync |
73
- | Tooling stacks | Golden configs, seeds, and a reference per framework | Laid down by `canon init`, reconciled by `canon tooling sync` |
74
- | Design system | Ships a `DESIGN.md` intent format pointing at your stylesheet for values, a skill that drafts one, and a render command | `canon design render` |
75
- | Canvas | Pages of HTML frames on a local pan and zoom surface, each frame drawn with the project's tokens | `canon canvas serve` |
76
- | Transcripts | A YouTube transcript with metadata frontmatter | `canon transcripts <url>` writes it into any repo |
77
- | Sandbox | Scenario scaffolds that provision an isolated project state for verifying each domain flow | `canon sandbox` |
69
+ | Domain | What it is | How it reaches you |
70
+ | -------------- | ----------------------------------------------------------------------------------------------------- | --------------------------------------------------------------- |
71
+ | Plugin skills | Skills that plan a feature, review a diff, sync the planning docs, and run the ship chain | Loaded live from the plugin, never copied |
72
+ | Governance | Coding and authoring rules that load into a Claude session when a matching path is edited | Installed per project by `canon gov install`, refreshed by sync |
73
+ | Tooling stacks | Golden configs, seeds, and a reference per framework | Laid down by `canon init`, reconciled by `canon tooling sync` |
74
+ | Design system | Ships a `DESIGN.md` intent format pointing at your stylesheet for values, and a skill that drafts one | `canon:design-record` drafts it in your repo |
75
+ | Transcripts | A YouTube transcript with metadata frontmatter | `canon transcripts <url>` writes it into any repo |
76
+ | Sandbox | Scenario scaffolds that provision an isolated project state for verifying each domain flow | `canon sandbox` |
77
+
78
+ The design board lives outside canon in [Frameboard](https://www.npmjs.com/package/frameboard), which `canon:pick-by-eye` drives for each round of candidates.
78
79
 
79
80
  ### How domains reach you
80
81
 
@@ -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.53.0",
4
+ "version": "5.54.0",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: canon-cli
3
- description: Routes a job to the `canon` verb that does it, and warns which verbs can lose a project's edits before one runs. Use when asked "which canon command does X", "is there a verb for X", "which command tells me if X", "will this overwrite my changes", or before running `canon sync`, `canon gov sync`, `canon tooling sync`, `canon design sync`, `canon migrate`, or `canon indexes regen`. Do NOT use to execute a verb, only to pick one and know what it costs.
3
+ description: Routes a job to the `canon` verb that does it, and warns which verbs can lose a project's edits before one runs. Use when asked "which canon command does X", "is there a verb for X", "which command tells me if X", "will this overwrite my changes", or before running `canon sync`, `canon gov sync`, `canon tooling sync`, `canon migrate`, or `canon indexes regen`. Do NOT use to execute a verb, only to pick one and know what it costs.
4
4
  metadata:
5
5
  family: answer
6
6
  ---
@@ -50,7 +50,8 @@ Each verb here has a skill that owns the job. Load the skill rather than driving
50
50
  | Report one computed property across routes | `canon inventory` | `canon:target-check` |
51
51
  | Walk a page through interactions and measure | `canon drive` | `canon:ux-measure` |
52
52
  | Fetch a YouTube transcript | `canon transcripts` | `canon:youtube-transcripts` |
53
- | Work on the local canvas | `canon canvas` | `canon:canvas-board` |
53
+
54
+ The design board is Frameboard, a separate CLI outside canon, so a board job runs a `frameboard` verb rather than a `canon` one.
54
55
 
55
56
  ## Session and ship
56
57
 
@@ -84,11 +85,10 @@ Read the doc each line names before running one of these. `canon docs install-an
84
85
  - `canon gov sync` replaces a rule you edited and deletes a rule the toolkit retired, edited or not.
85
86
  - `canon tooling sync --write` replaces every golden config a stack ships. Seeds are copy-once. Nothing writes without the flag. See `canon docs sync`.
86
87
 
87
- ### Design, migrate, and indexes
88
+ ### Migrate and indexes
88
89
 
89
- Three more verbs rewrite files in place.
90
+ Two more verbs rewrite files in place.
90
91
 
91
- - `canon design sync` replaces the shipped design files and leaves `.claude/design/project/` alone.
92
92
  - `canon migrate --write` rewrites files that cite a retired name or layout. It reports and writes nothing without the flag. See `canon docs migrate`.
93
93
  - `canon indexes regen` rewrites each generated `index.md` from the folder's current state, so a hand edit there is lost. See `canon docs indexes`.
94
94
 
@@ -23,12 +23,12 @@ A session building this alone restates the render-and-pick loop from scratch, wh
23
23
 
24
24
  - Draft a mark the operator did not ask for, or mutate an existing logo file, which is a plain edit
25
25
  - Add a logo section to the design document's fixed section set, which its parser reads as a fixed key set
26
- - Modify `pick-by-eye`, `canon capture`, or `canon design render`, which this skill composes
26
+ - Modify `pick-by-eye` or `canon capture`, which this skill composes
27
27
  - Be taken as reached by more than an operator typing its name, which a later review reads back rather than assumes
28
28
 
29
29
  ## Out of scope
30
30
 
31
31
  - The render, hand-off, pick, and loop mechanics, which `pick-by-eye` owns
32
- - Carrying a picked direction into the design document, which `canvas-board` owns
32
+ - Carrying a picked direction into the design document, which `design-record` owns
33
33
  - Auditing an implemented UI against its tokens, which `ux-audit` owns
34
34
  - Wiring the produced files into the project's head or manifest, which the operator owns
@@ -62,15 +62,15 @@ Announce which tier decided, naming the tier rather than the path alone, so the
62
62
 
63
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.
64
64
 
65
- - Draft each arm inside the full 1200x630 card frame, mark and type together, and add its canvas frame at `--width 1200 --height 630`, so one pick settles shape and composition
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.
67
67
  - Structure every arm as a `.mark` element, the inline SVG alone, nested inside a `.card` element, the full composition, so Step 6 can address either
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 canvas page, render and hand off, take the pick, and loop on it.
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.
72
72
 
73
- The final icon and card renders below are not arms, so they stay off the canvas. 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 `pick-by-eye` 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
 
@@ -110,9 +110,9 @@ canon capture <dest>/render/og-image.html --selector .render --out <write-folder
110
110
 
111
111
  It takes its own call because Step 6's batch is already captured by the time this step picks a path. Say that the card shipped as a PNG with no source, and that the project gains one when it grows a route to hold the composition.
112
112
 
113
- ### Closing the scratch folder and the canvas
113
+ ### Closing the scratch folder and the board
114
114
 
115
- Delete `<dest>` once both captures land, then close the canvas 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 `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.
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
 
@@ -133,6 +133,6 @@ Card source: <the route, captured through the card server|a scratch page, since
133
133
  Cite these rather than restating them.
134
134
 
135
135
  - `pick-by-eye` owns Steps 1 through 5 of the render-and-pick loop, cited above
136
- - `canon:canvas-board` carries a picked direction into `canon/DESIGN.md`. This skill only reads it.
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.
@@ -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 the picking or canvas skill should hand off to it
27
+ - Be reached only by the author typing its name, since a pick from `pick-by-eye` should hand off to it
28
28
 
29
29
  ## Out of scope
30
30
 
31
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
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 the canvas, which is `canvas-board`, 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 `pick-by-eye`, 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
  ---
@@ -19,7 +19,7 @@ The document holds the rules and each role's intent, and the folder holds the pi
19
19
  ## Guards
20
20
 
21
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.
22
+ - Never land a candidate the operator has not picked. The folder holds accepted designs, and a draft lives on the board.
23
23
 
24
24
  ## Step 1: read the record
25
25
 
@@ -66,10 +66,10 @@ Retire a reference in the change that removes its surface from the app.
66
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
67
 
68
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
69
+ - A project with no stylesheet yet writes one of its own for the values, and the lead names its path
70
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
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.
72
+ Never cite a board frame path from the document or the index. The board folder is gitignored, so the citation resolves on one machine alone.
73
73
 
74
74
  ## Output
75
75
 
@@ -15,7 +15,7 @@ Does not govern:
15
15
 
16
16
  - The design document at `canon/DESIGN.md`, which `design.md` beside this file governs
17
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
18
+ - The content format a frame is drawn in, which Frameboard owns and `frameboard docs --json` prints
19
19
 
20
20
  ## What a working folder looks like
21
21
 
@@ -31,5 +31,5 @@ The output has no standard of quality either. A model with no stated direction d
31
31
 
32
32
  - Accessibility, keyboard interaction, state coverage, forms, and rendered copy, which the `a11y`, `keyboard`, `ux-completeness`, `forms`, and `copy` rules own
33
33
  - The candidate loop and the pick, which `pick-by-eye` owns
34
- - The shape of the project's design document, which `canvas-board`'s design reference governs
34
+ - The shape of the project's design document, which `design-record`'s design reference governs
35
35
  - Prose on the surface being designed, which `write-human` and `markdown-craft` own
@@ -30,5 +30,5 @@ Asked to refresh one architecture view, it redraws every view beside it. It judg
30
30
  ## Out of scope
31
31
 
32
32
  - Mermaid's layout, budgets, and label rules inside the fence, which the mermaid standard owns
33
- - A UI screen mockup, and design tokens or the visual system, which `canvas-board` owns
33
+ - A UI screen mockup, which belongs on a Frameboard board, and design tokens or the visual system, which `design-record` owns
34
34
  - Implementation detail behind an architecture view, which the context entry the caption points at owns
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: draw-figure
3
- description: Drafts one hand-drawn figure for a document, deciding whether the subject is Mermaid-shaped, an architecture view, or needs freehand SVG, then draws it. Renders the Mermaid path through Mermaid's own hand-drawn look, reads the render back, and fixes what it exposes. Wraps every path in the figure standard's caption, color, and accessibility rules. Use when asked to "draw a figure", "add a hand-drawn diagram", "draft a figure for this doc", "draw this relationship as a figure", "draw the architecture", "diagram the system", or "show the components". Do NOT use for a UI screen mockup, which is `canvas-board`.
3
+ description: Drafts one hand-drawn figure for a document, deciding whether the subject is Mermaid-shaped, an architecture view, or needs freehand SVG, then draws it. Renders the Mermaid path through Mermaid's own hand-drawn look, reads the render back, and fixes what it exposes. Wraps every path in the figure standard's caption, color, and accessibility rules. Use when asked to "draw a figure", "add a hand-drawn diagram", "draft a figure for this doc", "draw this relationship as a figure", "draw the architecture", "diagram the system", or "show the components". Do NOT use for a UI screen mockup, which belongs on a Frameboard board.
4
4
  metadata:
5
5
  family: generate
6
6
  ---
@@ -14,8 +14,8 @@ The evidence fails as well. Arms get reported without being rendered or judged,
14
14
  ## Must
15
15
 
16
16
  - Three to five arms, the shipping state among them, each carry an id, a label, and a cost, and vary only at a layer named from the `design-taste` catalog
17
- - Each round is one canvas page of frames at their judged widths, themed by the canvas toggle and captured once as a composite, with the link ahead of the first pick question
18
- - Every arm is rendered and judged against a stated bar before handover, and a missing browser or a canvas that will not start is reported as a refusal
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
+ - 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
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
21
21
 
@@ -24,8 +24,8 @@ The evidence fails as well. Arms get reported without being rendered or judged,
24
24
  - Take the pick where two arms are defensible and the difference is taste
25
25
  - Draft candidates for a decision the operator has not asked to make, or for a request that already names one answer
26
26
  - Write into the real surface before the pick is final
27
- - Restate the mechanics `canon canvas` and `canon drive` own, or read a drive finding as a gate over the arms
28
- - Delete a canvas page or stop a server the run did not start
27
+ - Restate the mechanics Frameboard and `canon drive` own, or read a drive finding as a gate over the arms
28
+ - Delete a board page or stop a server the run did not start, or remove a page by any route but a `frameboard` verb
29
29
 
30
30
  ## Out of scope
31
31
 
@@ -1,6 +1,6 @@
1
1
  ---
2
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 canvas 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`.
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`.
4
4
  metadata:
5
5
  family: decide
6
6
  ---
@@ -9,13 +9,14 @@ metadata:
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 the local design canvas, the surface `canon:canvas-board` drives. Every verb below is `canon canvas`, and `${CLAUDE_SKILL_DIR}/../canvas-board/references/canvas.md` fixes the content format a frame takes. Read that reference before writing the first frame.
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.
13
13
 
14
14
  ## Guards
15
15
 
16
16
  - If the request names one answer and asks for it to be built, stop: `❌ This names one answer, so there is nothing to pick between. Use /canon:plan-feature.`
17
17
  - If the decision has no visible form, stop: `❌ Nothing to look at. Drafting candidates needs a decision a render can show.`
18
18
  - Draft no candidate for a decision the operator has not asked to make, since options everywhere spend their attention rather than saving it
19
+ - If neither `frameboard` nor `bunx` is on PATH, stop: `❌ Frameboard not found. Install frameboard or bun and re-run.`
19
20
 
20
21
  ## Step 1: name the decision and the arms
21
22
 
@@ -28,26 +29,24 @@ The candidates live on the local design canvas, the surface `canon:canvas-board`
28
29
 
29
30
  Inside a live `plan-groundwork` track, renders land in the track's own `evidence/<slug>/renders/`, since a candidate render is evidence its decision file cites. Everywhere else they land in session scratch.
30
31
 
31
- ## Step 2: draft the arms as frames on one canvas page
32
+ ## Step 2: draft the arms as frames on one page
32
33
 
33
- Every arm of a round sits as one frame on one canvas page, side by side. The operator judges that page, never a set of separate images compared from memory.
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.
34
35
 
35
- 1. Start the canvas the way `canon:canvas-board` Step 1 states, unless this run already has. Note whether this run started the server, since Step 6 stops only a server this run started.
36
- 2. Add the round's page with `canon canvas page add <page> --json` and record it on the run's list of pages. A name `canvas list` already shows is somebody else's, so take the next free suffix.
37
- 3. Add each arm with `canon canvas frame add <page> arm-<id> --width <px> --height <px> --json`. Step 6's archive keys on the `arm-<id>` names.
38
- 4. Write each arm's whole document to the `path` the add verb reported. From a linked worktree, take the heredoc route `canon:canvas-board` Step 3 gives for a main-root write.
39
- 5. Lay the frames out in one row, in arm order, with `canon canvas frame move <page> arm-<id> --x <px> --y <px> --json`.
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`.
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
+ 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
+ 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.
40
41
 
41
- The `canvas-board` start reads `canon canvas list --json`, serves with `canon canvas serve --json` in the background unless the operator named an address that answers, and checks the shell's body holds a `<script` tag. A refused serve or a blank shell stops the run with its `reason`, and no file stands in for a canvas.
42
-
43
- Set each frame's width to the one the arm is judged at. A frame renders at its own layout width on the canvas and in a capture alike, so a layout decision needs no device toolbar.
42
+ Set each frame's width to the one the arm is judged at. A frame renders at its own layout width on the board and in a capture alike, so a layout decision needs no device toolbar.
44
43
 
45
44
  ### What every frame carries
46
45
 
47
- Each frame carries its own label and follows the canvas theme, so the set reads as one comparison.
46
+ Each frame carries its own label and follows the board theme, so the set reads as one comparison.
48
47
 
49
48
  - Label each arm inside its frame with its id and its cost, since the composite capture draws no captions
50
- - Theme every arm off the `data-theme` attribute the canvas sets on each frame's root, so the theme toggle sets the whole set at once. A set spanning both themes cannot be compared.
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.
51
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.
52
51
 
53
52
  ### Default path and live app
@@ -55,8 +54,8 @@ Each frame carries its own label and follows the canvas theme, so the set reads
55
54
  A running app under decision takes the live-app branch, and every other decision takes the default path.
56
55
 
57
56
  - Live app: lift the rendered markup and link a copy of the built stylesheet rather than inlining, per `${CLAUDE_SKILL_DIR}/references/live-arms.md`
58
- - Default path: inline every style, script, and asset. A frame resolves nothing outside its own page folder, so a build step or network font silently drops out.
59
- - Default path: name a real font first in the stack, one the machine has or the frame embeds, such as the project's own family. A generic keyword such as `system-ui` resolves differently per machine.
57
+ - Default path: inline every style, script, and asset. A frame resolves nothing outside its page folder and its project's `assets/`, so a build step or network font silently drops out.
58
+ - Default path: name a real font first in the stack, one the board serves, the machine has, or the frame embeds. A generic keyword such as `system-ui` resolves differently per machine.
60
59
 
61
60
  The capture refuses a frame that would rewrap against a substitute font rather than ship a false comparison. A frame naming no font is refused on whatever the default resolves to.
62
61
 
@@ -73,18 +72,18 @@ Vary one property across the arms, since a pick cannot say which of three differ
73
72
  Render the page and look at what came back before handing anything over:
74
73
 
75
74
  ```bash
76
- canon canvas capture <page> --composite --json
75
+ frameboard capture --page <page> --composite --root <board> --project picks --json
77
76
  ```
78
77
 
79
- - Point `--out` at `evidence/<slug>/renders/<page>.png` inside a live track, and leave the scratch default elsewhere. Step 6 archives the picked round alone.
80
- - Read the PNG's `path` off the record. The composite shows each frame in its default theme, so check the other theme on the live canvas.
81
- - A capture refusing on a font names the family it read. Take the repair `canon:canvas-board` Step 6 gives and capture again.
78
+ - Point `--out` at `evidence/<slug>/renders/` inside a live track, and leave the board's default elsewhere. Step 6 archives the picked round alone.
79
+ - Read each image's `path` off the record's `images`. The composite lands once per theme, so look at both.
80
+ - A `font-missing` refusal names the family it read. Set that text's `font-family` to a named family the board serves or the machine has, never a generic keyword, and capture again.
82
81
 
83
- When `canon canvas capture` refuses for a missing browser binary, report it and name `bunx playwright install chromium` as the repair. Stop the canvas server if this run started it, then stop rather than describe an arm nobody has seen.
82
+ When the capture refuses with `browser-not-found`, report it and name `bunx playwright install chromium` as the repair. End the serve command if this run started it, then stop rather than describe an arm nobody has seen.
84
83
 
85
84
  ### Handing over
86
85
 
87
- Hand over the address rather than a description. Emit the canvas link first on its own line, naming the page, then the PNG path on its own line.
86
+ Hand over the address rather than a description. Emit the board link first on its own line, naming the page, then each PNG path on its own line.
88
87
 
89
88
  - A still answers how a thing looks and none of a hover, a scroll-linked position, or a pace, which the live frame does
90
89
  - Never report a visual result you have not looked at, since a claim about appearance with no render behind it is a guess
@@ -103,14 +102,7 @@ Put the choice to the operator through the structured question surface, since a
103
102
 
104
103
  Take no pick on the operator's behalf when two arms are both defensible and the difference is taste. That call is theirs, and a silent one is the failure this skill exists to prevent.
105
104
 
106
- Read `canon canvas selection --json` when the answer points at the canvas, such as "the selected one". Resolve it against the record's `page` as well as its `frame`, since every round reuses the `arm-<id>` names.
107
-
108
- | Selection | Reading |
109
- | ---------------------------------------------------------------- | ---------------------------------------------- |
110
- | A frame on the current round's page | The pick |
111
- | A frame on an earlier round's page | A revert, so name the round back before acting |
112
- | A fresh element inside a picked frame | A correction Step 5 carries by its `index` |
113
- | `selection: null`, a page this run did not add, or `stale: true` | No answer, so ask again rather than guess |
105
+ Read the selection when the answer points at the board, such as "the selected one". `references/board.md` maps each record to a pick, a revert, a correction, or no answer.
114
106
 
115
107
  ## Step 5: loop on the pick
116
108
 
@@ -118,22 +110,22 @@ Read `canon canvas selection --json` when the answer points at the canvas, such
118
110
  2. Write fresh arms off the pick and return to Step 2 where the correction opens a new question. Revise the one arm's frame where it does not.
119
111
  3. Re-render, hand off again, and take the next answer.
120
112
  4. Repeat until the operator says it is right. A run stopping because the arms stopped differing has stopped early.
121
- 5. Hold the real surface untouched across every iteration. Nothing outside the run's own canvas pages changes until the pick is final.
113
+ 5. Hold the real surface untouched across every iteration. Nothing outside the run's own board pages changes until the pick is final.
122
114
 
123
115
  ## Step 6: close
124
116
 
125
117
  1. Apply the winning arm to the real surface, in one change.
126
118
  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. 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.
119
+ 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
+ 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.
123
+ 7. End the serve command if this run started it, since Frameboard carries no stop verb. Leave a server the operator started running.
132
124
  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.
125
+ 9. Report each page whose delete is refused, naming its `ref` and the `error.code`. The pick is applied either way.
134
126
  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.
135
127
 
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.
128
+ 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.
137
129
 
138
130
  ## Reading a measurement
139
131
 
@@ -154,10 +146,11 @@ Cite these rather than restating them. A step reimplemented here rots against th
154
146
  - `design-taste` carries the layer catalog, the ordering, grey-boxing, and the defaults an arm should reach past
155
147
  - `write-human` carries the voice for any copy an arm puts in front of a reader
156
148
 
157
- ### Git and review
149
+ ### Git, review, and the board
158
150
 
159
- Commits, review, and the canvas mechanics each have an owner.
151
+ Commits, review, and the board mechanics each have an owner.
160
152
 
161
153
  - `git-stage`, `git-pr`, and `git-followup` carry the commits and the pull request
162
154
  - `review-pr` and `review-address` run the review pass
163
- - `canon:canvas-board` carries the canvas start-and-check sequence, the main-root write route for a frame, and the selection and capture refusals
155
+ - `session-worktree` carries the main-root write route for a frame written from a linked worktree
156
+ - Frameboard carries the board itself, and `frameboard docs --json` prints its verbs, record shapes, content format, and refusals
@@ -0,0 +1,42 @@
1
+ # The Frameboard board
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.
4
+
5
+ ## Reaching the board
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.
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
10
+ - 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
+ - The pin holds the minor, since record shapes move across a pre-1.0 minor
12
+
13
+ Run `frameboard docs --json` before writing the first frame. Its `contentFormat` fixes what a frame may hold and link, and its `exitCodes` name every refusal a verb can return.
14
+
15
+ ## Starting the board
16
+
17
+ Serve in the background unless the operator named an address that answers, since the server runs until its command ends:
18
+
19
+ ```bash
20
+ frameboard serve --root <board> --no-open --tokens <stylesheet> --json
21
+ ```
22
+
23
+ - Take `<stylesheet>` from the lead of `canon/DESIGN.md`, which names it in a hand-written record
24
+ - A lead naming a module, or no design document at all, means serving without `--tokens`. Say the frames render on the board's own tokens.
25
+ - Read `url` and `reused` off the record rather than composing an address
26
+ - `reused: true` means a server was already up, so this run did not start it and its close leaves it running
27
+ - Report a refusal's `error.code` and stop, since no file stands in for a board
28
+
29
+ ## Reading the selection
30
+
31
+ 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
+
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 |
41
+
42
+ 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.
@@ -5,7 +5,7 @@ Read when the surface under decision is a running app rather than a static mocku
5
5
  ## Lift from the app
6
6
 
7
7
  - Dump the rendered markup of the surface under decision from the built page, after it has loaded, into a scratch file the run reads from. Strip scripts from the dump.
8
- - Copy the built stylesheet and fonts to the canvas page folder at the path each frame links, since a frame resolves only its own page. Each arm then differs from the shipped page only in what it names.
8
+ - Copy the built stylesheet and fonts into the page folder or the project's `assets/`, since a frame resolves nothing else. Each arm then differs from the shipped page only in what it names.
9
9
  - Trim a large dump to the part the decision needs, and keep the wrapper classes intact so layout rules keyed to them still resolve.
10
10
  - Set each frame's `--width` to the content width the decision names rather than the window width, since a container query reads the frame.
11
11
  - Write copy an arm introduces with `write-human`, and take every other word from the dump.
@@ -13,7 +13,7 @@ Read when the surface under decision is a running app rather than a static mocku
13
13
  ## The frames
14
14
 
15
15
  - Generate the frames with a short script, one per round, so a shared change is one edit and a rerun.
16
- - Leave the theme to the canvas toggle, which sets the app's own `data-theme` switch on every frame's root. Name the attribute the stylesheet reads where it differs, as the toggle sets that one alone.
16
+ - Leave the theme to the board toggle, which sets the app's own `data-theme` switch on every frame's root. Name the attribute the stylesheet reads where it differs, as the toggle sets that one alone.
17
17
  - Print each frame's measurement under it from a script in the frame, so the numbers the operator reads are the browser's.
18
18
  - Draw an arm that is a whole page or a route as one frame at that page's width, so it still sits beside the other arms on the round's page.
19
- - Name anything the canvas cannot reproduce, such as an asset whose colors follow the browser rather than the frame's theme, rather than fixing the frame around it.
19
+ - Name anything the board cannot reproduce, such as an asset whose colors follow the browser rather than the frame's theme, rather than fixing the frame around it.
@@ -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 canvas pages under `.canon/canvas/` that its close deletes.
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.
41
41
 
42
42
  ### Reading and backing
43
43
 
@@ -17,6 +17,7 @@ Its quizzes leak the answer through option length or position, and nothing tests
17
17
  - Ask the learner's starting point and read the subject from sources, saying which claims rest on recall
18
18
  - State quiz design that leaks no answer, and pair a quiz with a teach-back
19
19
  - Hold that the wrong answer itself is what the next session places from
20
+ - Cite an opened source in the ledger for every kept rule, or label it house judgment with the reason it stays, then close on excuses, red flags, and a checklist
20
21
 
21
22
  ## Must not
22
23
 
@@ -27,4 +28,3 @@ Its quizzes leak the answer through option length or position, and nothing tests
27
28
  ## Out of scope
28
29
 
29
30
  - Where a lesson is stored or how it renders, which belongs to whatever surface the session writes to
30
- - A cited source ledger for the practice family, which is a follow-on task
@@ -7,7 +7,7 @@ metadata:
7
7
 
8
8
  # Teach craft
9
9
 
10
- A session asked to teach explains, and a smooth explanation reads as a lesson learned. It is fluency, which decays within days. This skill carries what turns teaching into retention: test before telling, space the returns, and grade only what the learner produced unaided.
10
+ A session asked to teach explains, and a smooth explanation reads as a lesson learned. It is fluency, which does not survive a delay. This skill carries what turns teaching into retention: test before telling, space the returns, and grade only what the learner produced unaided.
11
11
 
12
12
  It produces nothing of its own. The lesson lands wherever the session already writes, being the conversation, a file, or a page.
13
13
 
@@ -18,6 +18,8 @@ It produces nothing of its own. The lesson lands wherever the session already wr
18
18
 
19
19
  Read `pedagogy.md` before picking what to teach next, and `lesson-craft.md` before writing a quiz or a lesson.
20
20
 
21
+ Read `${CLAUDE_SKILL_DIR}/references/adopted.md` only when extending this guidance or arguing against a rule in it. It records the research each rule rests on, the passage relied on, and which rules stand as house judgment.
22
+
21
23
  ## Before teaching
22
24
 
23
25
  - Ask what the learner already knows rather than assuming it. Difficulty with no floor under it teaches nobody.
@@ -37,3 +39,32 @@ Read `pedagogy.md` before picking what to teach next, and `lesson-craft.md` befo
37
39
  | They followed the explanation, so move on | Following is fluency. Advance on a retrieval the learner passed unaided. |
38
40
  | Review the last lesson before testing it | Review rebuilds the fluency the test would have measured. Test first, then fill what missed. |
39
41
  | The answer is obvious from the options | Then the distractors are not misconceptions anyone holds. Rewrite them. |
42
+
43
+ ## Red flags
44
+
45
+ - You are about to explain a topic and the learner has not yet tried to answer anything on it.
46
+ - The learner said it makes sense and you are moving to the next topic.
47
+ - A returning learner's session opens on new material.
48
+
49
+ ### Quizzes and records
50
+
51
+ These flags fire on what the session has written.
52
+
53
+ - The correct options in a quiz are the longest ones, or sit in the same slot.
54
+ - You are writing a claim about the subject with no source open.
55
+ - The learning record you are about to write holds a score and no wrong answer.
56
+
57
+ ## Before handing over
58
+
59
+ Check each line against the lesson and the record the session produced.
60
+
61
+ - Every advance followed a retrieval the learner passed unaided, not a smooth explanation.
62
+ - The lesson carries a quiz and a teach-back with a named audience.
63
+ - Every quiz keeps its options to one length and rotates the correct slot by question number.
64
+ - Every claim names the source it was read from, or says it rests on recall.
65
+ - The learning record names each wrong answer and the next revisit from the ladder.
66
+
67
+ ## What this delegates
68
+
69
+ - Finding and opening the sources a lesson is read from: `search-craft`
70
+ - Where a lesson is stored and how it renders, which belongs to the surface the session writes to