@erclx/canon 5.25.0 → 5.26.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 (123) hide show
  1. package/README.md +2 -1
  2. package/claude/.claude-plugin/plugin.json +1 -1
  3. package/claude/skills/canvas/SKILL.md +1 -1
  4. package/claude/skills/context-fold/REQUIREMENT.md +6 -2
  5. package/claude/skills/context-fold/SKILL.md +8 -6
  6. package/claude/skills/context-fold/references/anchor-sweep.md +2 -2
  7. package/claude/skills/design-taste/REQUIREMENT.md +1 -1
  8. package/claude/skills/design-taste/SKILL.md +4 -2
  9. package/claude/skills/design-taste/references/adopted.md +40 -0
  10. package/claude/skills/design-taste/references/kinds.md +1 -1
  11. package/claude/skills/design-taste/references/systems.md +1 -7
  12. package/claude/skills/design-taste/references/tells.md +2 -24
  13. package/claude/skills/docs-sync/REQUIREMENT.md +2 -1
  14. package/claude/skills/document-health/REQUIREMENT.md +2 -0
  15. package/claude/skills/document-health/SKILL.md +21 -0
  16. package/claude/skills/document-health/references/axes.md +12 -0
  17. package/claude/skills/draft-and-pick/SKILL.md +1 -1
  18. package/claude/skills/draft-identity/SKILL.md +1 -1
  19. package/claude/skills/draft-screencast/SKILL.md +9 -7
  20. package/claude/skills/draft-slides/REQUIREMENT.md +17 -12
  21. package/claude/skills/draft-slides/SKILL.md +31 -20
  22. package/claude/skills/git-issue/references/issue.md +10 -0
  23. package/claude/skills/git-pr/references/evidence.md +8 -0
  24. package/claude/skills/git-pr/references/labels.md +12 -0
  25. package/claude/skills/git-split/SKILL.md +19 -8
  26. package/claude/skills/markdown-propose/references/format.md +9 -0
  27. package/claude/skills/memory-review/references/later-phases.md +7 -0
  28. package/claude/skills/review-ui/references/post.md +4 -2
  29. package/claude/skills/role-orchestrator/references/orchestrator-cloud-launch.md +8 -0
  30. package/claude/skills/role-orchestrator/references/orchestrator-dispatch.md +13 -0
  31. package/claude/skills/search-craft/REQUIREMENT.md +1 -1
  32. package/claude/skills/search-craft/SKILL.md +3 -1
  33. package/claude/skills/search-craft/references/adopted.md +30 -0
  34. package/claude/skills/target-setup/references/detect.md +8 -0
  35. package/claude/skills/target-setup/references/indexes.md +13 -0
  36. package/claude/skills/target-setup/references/verify.md +8 -0
  37. package/claude/skills/test-first/SKILL.md +2 -0
  38. package/claude/skills/test-first/references/adopted.md +36 -0
  39. package/claude/skills/write-human/SKILL.md +1 -1
  40. package/claude/skills/write-human/references/machine-tells.md +13 -0
  41. package/docs/agents/canvas.md +3 -1
  42. package/docs/agents/capture.md +1 -1
  43. package/docs/agents/commands.md +3 -3
  44. package/docs/agents/index.md +2 -2
  45. package/docs/agents/records-stale.md +22 -9
  46. package/docs/agents/records.md +1 -1
  47. package/docs/agents/sandbox.md +1 -1
  48. package/docs/agents/skills-audit.md +10 -3
  49. package/docs/agents/slides.md +15 -3
  50. package/docs/workflow/ai-workflow.md +1 -1
  51. package/docs/workflow/index.md +1 -0
  52. package/docs/workflow/parallel-features.md +1 -1
  53. package/docs/workflow/skill-map-on-request.md +42 -0
  54. package/docs/workflow/skill-map.md +1 -34
  55. package/package.json +1 -1
  56. package/scripts/lib/sandbox-dispatch.sh +1 -1
  57. package/scripts/lib/sandbox-git.sh +1 -9
  58. package/scripts/lib/sandbox-path.sh +1 -1
  59. package/scripts/sandbox-hook.sh +99 -0
  60. package/src/canvas/capture.ts +1 -9
  61. package/src/canvas/client/inspector/color-field.tsx +368 -0
  62. package/src/canvas/client/inspector/fields.css +163 -22
  63. package/src/canvas/client/inspector/values.ts +123 -0
  64. package/src/canvas/client/inspector.tsx +46 -69
  65. package/src/capture/render.ts +45 -7
  66. package/src/capture/sources.ts +43 -0
  67. package/src/census/count.ts +1 -1
  68. package/src/claude/cases/workflow.ts +5 -0
  69. package/src/claude/seeds.ts +1 -1
  70. package/src/claude/skills-audit.ts +68 -14
  71. package/src/client-commands.ts +1 -1
  72. package/src/commands/claude.ts +27 -2
  73. package/src/commands/feedback.ts +3 -3
  74. package/src/commands/records.ts +88 -6
  75. package/src/commands/sandbox.ts +50 -10
  76. package/src/commands/slides.ts +31 -77
  77. package/src/context/audit.ts +1 -1
  78. package/src/design/tokens.ts +2 -18
  79. package/src/docs/read.ts +1 -1
  80. package/src/{github.ts → feedback/github.ts} +1 -1
  81. package/src/gate/measures.ts +6 -4
  82. package/src/gov/citations.ts +1 -1
  83. package/src/gov/payload.ts +1 -1
  84. package/src/gov/superseded.ts +2 -2
  85. package/src/markdown/ceiling.ts +1 -1
  86. package/src/record-root.ts +1 -0
  87. package/src/records/backup.ts +1 -0
  88. package/src/records/push-guard.ts +1 -1
  89. package/src/records/stale-canonical.ts +146 -0
  90. package/src/records/stale.ts +1 -1
  91. package/src/sandbox/hooks.ts +128 -0
  92. package/src/sandbox/provision.ts +596 -0
  93. package/src/sandbox/tree.ts +103 -4
  94. package/src/secrets/marker.ts +2 -2
  95. package/src/secrets/scan.ts +1 -1
  96. package/src/shipped/references.ts +2 -2
  97. package/src/slides/convert/export.ts +2 -16
  98. package/src/slides/decks.ts +110 -0
  99. package/src/standards/read.ts +1 -1
  100. package/src/sync/seeds-report.ts +1 -1
  101. package/src/tasks/answers.ts +1 -1
  102. package/src/tasks/archive.ts +1 -1
  103. package/src/teach/nav.ts +1 -1
  104. package/src/tooling/inject.ts +1 -1
  105. package/src/web/readme-citations.ts +1 -1
  106. package/standards/architecture.md +1 -0
  107. package/standards/canvas.md +1 -1
  108. package/standards/requirements.md +2 -0
  109. package/standards/skill-practice.md +2 -1
  110. package/standards/skill.md +1 -0
  111. package/scripts/manage-sandbox.sh +0 -472
  112. package/src/slides/layouts.ts +0 -478
  113. package/src/slides/parse.ts +0 -84
  114. package/src/slides/render.ts +0 -110
  115. package/src/slides/styles.ts +0 -96
  116. /package/claude/skills/write-human/references/{source-material.md → adopted.md} +0 -0
  117. /package/src/{commands/feedback-format.ts → feedback/body.ts} +0 -0
  118. /package/src/{github-format.ts → feedback/github-format.ts} +0 -0
  119. /package/src/{frontmatter.ts → markdown/frontmatter.ts} +0 -0
  120. /package/src/{binary.ts → sweep/binary.ts} +0 -0
  121. /package/src/{exempt-marker.ts → sweep/exempt-marker.ts} +0 -0
  122. /package/src/{paths.ts → tasks/paths.ts} +0 -0
  123. /package/src/{seed-marker.ts → tooling/seed-marker.ts} +0 -0
package/README.md CHANGED
@@ -68,7 +68,7 @@ Each domain has a canonical source in this repo and a thin install or sync CLI o
68
68
  | Standards | Authoring conventions for commits, branches, plans, tasks, and markdown | Opened by name, read by name with `canon standards <name>` |
69
69
  | Tooling stacks | Golden configs, seeds, and a reference per framework | Laid down by `canon init`, reconciled by `canon tooling sync` |
70
70
  | Design system | Ships a `DESIGN.md` token format, a skill that drafts one from an existing project or from scratch, and a render command | `canon design render` |
71
- | Slides | A `SLIDES.md` source format with a layout catalog, or a folder of HTML slides rebuilt as editable shapes | `canon slides render` writes PowerPoint |
71
+ | Slides | A folder of HTML slides per deck, drawn in the project's tokens and rebuilt as editable shapes | `canon slides render` writes PowerPoint |
72
72
  | Teach | Lessons, sources, and a glossary in one workspace, rendered to a small site | `canon teach` |
73
73
  | Canvas | Pages of HTML frames on a local pan and zoom surface, each frame drawn with the project's tokens | `canon canvas serve` |
74
74
  | Transcripts | A YouTube transcript with metadata frontmatter | `canon transcripts <url>` writes it into any repo |
@@ -98,6 +98,7 @@ Working with an agent rather than reading this yourself? It loads `CLAUDE.md` at
98
98
  - [AI workflow](docs/workflow/ai-workflow.md): feature-development loop inside a toolkit-managed project
99
99
  - [Operating model](docs/workflow/operating-model.md): orchestrator, planner, and worker roles for building across parallel sessions
100
100
  - [Skill map](docs/workflow/skill-map.md): plugin skills grouped by the moment a project meets them
101
+ - [Skill map on request](docs/workflow/skill-map-on-request.md): plugin skills that serve a request rather than a moment
101
102
  - [Visual design workflow](docs/workflow/visual-design-workflow.md): tiered guide for design and wireframe authoring
102
103
  - [Target projects](docs/target/projects.md): scaffold, add a domain later, sync upstream drift
103
104
  - [Agents](docs/agents/index.md): CLI flags, exit codes, and JSON output shapes
@@ -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.25.0",
4
+ "version": "5.26.0",
5
5
  "author": {
6
6
  "name": "Eric Le",
7
7
  "url": "https://github.com/erclx"
@@ -83,7 +83,7 @@ The operator restyles elements from the inspector, and each edit lands as inline
83
83
  - Capture a whole page once its frames are finished: `canon canvas capture <page> --composite --json`. The image shows each frame clipped to its box at its layout position.
84
84
  - Capture once per finished frame or page, not after every edit. The live canvas is the working view, and a capture is the record handed on.
85
85
  - Read each `path` off the record rather than composing one.
86
- - A capture refused because a font is not installed names the family it read off the frame's `html` element. Set that element's `font-family` to a family the machine has and capture again, rather than reporting the frame as captured.
86
+ - A capture refused because a font is not installed names the family it read off the frame's text. Set that text's `font-family` to a named family the machine has, never a generic keyword such as `sans-serif`, and capture again, rather than reporting the frame as captured.
87
87
 
88
88
  ## Step 7: carry a picked direction back
89
89
 
@@ -7,7 +7,7 @@ description: What the planning-doc reconcile is for, the gaps it closes, and why
7
7
 
8
8
  ## Gap
9
9
 
10
- Without this skill, the planning docs describe the scope the session opened with. An outcome the diff shipped stays unchecked, so the board reports finished work as open and the next session re-plans it. A requirement or architecture decision that changed mid-cycle lives only in the conversation and dies with it. Plans for closed tasks accumulate in the live folder, so the folder stops indicating what is in flight.
10
+ Without this skill, the planning docs describe the scope the session opened with. An outcome the diff shipped stays unchecked, so the board reports finished work as open and the next session re-plans it. An architecture decision a plan settled mid-cycle lives only in the conversation and dies with it. Plans for closed tasks accumulate in the live folder, so the folder stops indicating what is in flight.
11
11
 
12
12
  A decision's verification anchor has the same shape of gap in the other direction. The reasoning keeps reading as current while the number it cites moves underneath, and an amendment written without an anchor leaves nothing recording which numbers were checked and which nobody has read since.
13
13
 
@@ -17,6 +17,8 @@ The receipt half of that sweep was missing entirely. A review receipt was delete
17
17
 
18
18
  The trigger side carries a gap of its own. "Sync the docs" names either corpus to the person saying it, so a description leaving its corpus to the opening clause alone competes with its public-facing sibling on nothing the routing field states, and the planning surface the request was about goes untouched.
19
19
 
20
+ The opposite gap opened from the same write. A fold allowed to touch the requirements and architecture records on every ship rewrote both one reasonable edit at a time, and nothing read either for whether it still stated the project's identity. Each ship looked correct and the sum drifted.
21
+
20
22
  This skill writes canonical docs at the end of a long build and never reviews what it wrote. An appended figure or a branch-narrated re-measurement lands unchecked the same way a session's own edits do, so what the fold produces carries the exact defect the standards it cites already ban.
21
23
 
22
24
  ## Must
@@ -28,7 +30,8 @@ This skill writes canonical docs at the end of a long build and never reviews wh
28
30
  - Write tracked docs at the current worktree root and the task board at the main root, since only the first commits with the branch
29
31
  - Count every other citation before archiving a plan, comparing resolved targets rather than raw strings or bare filenames
30
32
  - Retarget a closed task at the archived plan, so the reasoning behind finished work stays reachable
31
- - Write a decision to the domain context entry it constrains unless it fills an architecture slot, since reach admits nearly every decision to an always-loaded file
33
+ - Write a decision to the domain context entry it constrains unless a plan this run folds states it and it fills an architecture slot, since reach admits nearly every decision to an always-loaded file and a slot decision only the conversation carries was never reviewed
34
+ - Report a requirements or direction change in one line naming `document-health`, rather than writing it, so the identity record changes only when the operator reviews it
32
35
  - Merge or retire an architecture entry before adding one at the record's stated cap, and name which in the report, so the cap never turns into compressed prose or two decisions packed under one heading
33
36
  - Anchor a decision entry this run writes or amends whose reasoning cites a measured number, re-reading the number against the tree before writing the marker
34
37
  - Report an anchored decision whose cited path the diff touched, since the number was read before the branch moved what it counted
@@ -48,6 +51,7 @@ This skill writes canonical docs at the end of a long build and never reviews wh
48
51
  - Infer a new task from the diff. Only outcomes already on the board get marked.
49
52
  - Touch task files the session did not change
50
53
  - Widen what a writing step reads when the baseline is unusable. Widening a read is safe and widening a write stubs a surface for every file in the repository.
54
+ - Write the requirements record. It states identity, and a fold reads one session where a review reads the whole project.
51
55
  - Edit `CLAUDE.md` inline. Every change there goes through a diff-and-approve gate, so this skill only flags.
52
56
  - Create a context entry, or move or delete a plan. A plan is settled by the merge, and `canon tasks archive` carries it.
53
57
  - Overwrite a file a promotion block routes to. A destination that already holds a page is a merge for a person, and folding over it discards work this skill never read.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: context-fold
3
- description: Folds a session into the project's context entries, requirements, architecture, and wireframes, marks the outcomes the diff shipped `[x]` on the task board, and archives the plans those tasks cite. Use when asked to "fold the session into context", "update the context entries", "sync the planning records", when design or requirements changed mid-cycle, after a pivot, or before shipping. Do NOT use for `README.md` or `docs/`, which is `docs-sync`, or to create or archive a task file, which is `task-board`.
3
+ description: Folds a session into the project's context entries, architecture, and wireframes, marks the outcomes the diff shipped `[x]` on the task board, and archives the plans those tasks cite. Use when asked to "fold the session into context", "update the context entries", "sync the planning records", when design or requirements changed mid-cycle, after a pivot, or before shipping. Do NOT use for `README.md` or `docs/`, which is `docs-sync`, or to create or archive a task file, which is `task-board`.
4
4
  ---
5
5
 
6
6
  # Context fold
@@ -82,13 +82,15 @@ The verb resolves the board at the main worktree root in-process, which is the r
82
82
 
83
83
  Read `ok` and `reason` out of that record rather than the exit. An operator's shell profile may wrap `canon` in a function that runs the binary and then a second command and takes the second status, which flattens every non-zero exit to zero. A refusal arriving as success leaves the outcome unmarked while the chain moves on, so the board reports shipped work as open and the next session re-plans it.
84
84
 
85
- **REQUIREMENTS.md, ARCHITECTURE.md, DESIGN.md, a wireframe surface file (flat or nested)**
85
+ **ARCHITECTURE.md, DESIGN.md, a wireframe surface file (flat or nested)**
86
86
 
87
+ - Never write `canon/REQUIREMENTS.md`. Report a requirements change in After completion.
87
88
  - Update only the sections affected by session decisions.
88
89
  - Do not rewrite sections unrelated to what changed.
89
90
  - Rewrite a restated or superseded statement in place rather than appending the replacement beside it. State the fact that stands and keep the earlier reasoning only where it is the alternative that lost, per `${CLAUDE_SKILL_DIR}/../../standards/context.md` and `${CLAUDE_SKILL_DIR}/../../standards/architecture.md`.
90
91
  - Follow `${CLAUDE_SKILL_DIR}/../../standards/markdown.md` and the `write-human` skill for all edits.
91
- - Write a session decision into the `canon/context/` entry for the domain it constrains, under that entry's `## Decisions`, by default. Touch `canon/ARCHITECTURE.md` only for a decision that fills one of the slots `${CLAUDE_SKILL_DIR}/../../standards/architecture.md` names, however many domains its reasoning reaches.
92
+ - Write a session decision into the `canon/context/` entry for the domain it constrains, under that entry's `## Decisions`, by default.
93
+ - Touch `canon/ARCHITECTURE.md` only when a plan a matched task's `Plan:` line names states a decision filling a slot `${CLAUDE_SKILL_DIR}/../../standards/architecture.md` names. A slot decision no plan carries goes to the domain entry.
92
94
  - Read the entry cap the record states before adding a decision to it. At the cap, merge two decisions or retire one to the domain entry it constrains, and name which in the report. Never compress a decision's prose to fit, and never pack two decisions under one heading.
93
95
  - Close a decision entry in `canon/ARCHITECTURE.md` with its verification anchor whenever this run writes that entry or amends its reasoning and that reasoning cites a measured number. Re-read the number against the tree first, since the marker records the read rather than the edit. `${CLAUDE_SKILL_DIR}/../../standards/architecture.md` fixes the sentence.
94
96
  - Leave every decision entry this run did not write alone, anchored or not. The rule is scoped forward, so an entry written before it is dated by blame rather than by a read. Step 5 reports a stale anchor and no step writes one on an entry it did not amend.
@@ -107,9 +109,7 @@ Skip silently when the filter leaves nothing, which is every branch touching no
107
109
 
108
110
  Skip this step silently when `canon/ARCHITECTURE.md` does not exist at `pwd` or carries no decision entry with a verification anchor. A record written before the rule holds none, and a project is not told on every ship that nothing has been checked when the standard calls that state correct. When the baseline is unusable, scope the sweep to the working tree and untracked files, and skip it only when that set is empty, reporting `⚠ No diff to scope against. Skipped the anchor sweep.`
109
111
 
110
- This step reports and never writes. The record carries no frontmatter, so an anchor is a sentence sharing a paragraph with the claim it marks, and a pass editing prose to mark prose has no structural guard against editing the claim beside it. A surface whose marker sits in YAML gets that separation for free and this one cannot.
111
-
112
- Step 3 holds the writer, and the two never meet. Anchoring fires when this run amends a decision, and this sweep fires when the diff moves a path under one, so a single step covering both would gate the anchor obligation on a signal that has nothing to do with it.
112
+ This step reports and never writes. An anchor is a sentence sharing a paragraph with the claim it marks rather than a frontmatter field, and a pass editing prose to mark prose has no structural guard against editing the claim beside it. A surface whose marker sits in YAML gets that separation for free and this one cannot.
113
113
 
114
114
  Follow `${CLAUDE_SKILL_DIR}/../../standards/architecture.md` for the anchor sentence this step matches on.
115
115
 
@@ -153,6 +153,8 @@ When Step 3 met the architecture record's cap, add one line naming what it did t
153
153
 
154
154
  `↪ Architecture at cap: merged <heading> into <heading>` or `↪ Architecture at cap: retired <heading> to <context entry>`
155
155
 
156
+ When Step 2 noted a requirements change: `↪ Direction changed this session: run document-health on canon/REQUIREMENTS.md`
157
+
156
158
  Step 10 adds its own lines when it applied or reported a finding, in the exact shape `${CLAUDE_SKILL_DIR}/references/classify.md` gives them under its own Report section. Do not shorten or paraphrase those lines here or in the reply, since the quote and the reason are what a reader checks the finding against.
157
159
 
158
160
  If no files were updated and nothing was swept, output:
@@ -43,11 +43,11 @@ What this misses is a claim whose number moved with no matching citation in the
43
43
 
44
44
  ## What the sweep never does
45
45
 
46
- - Write into the entry. The record carries no frontmatter, so the marker and the claim share one paragraph and an edit reaching one reaches the other.
46
+ - Write into the entry. The anchor is a sentence rather than a frontmatter field, so the marker and the claim share one paragraph and an edit reaching one reaches the other.
47
47
  - Refresh an anchor. Re-reading the number is the act the marker records, so a date written by a pass that measured nothing is the false confidence the marker exists to prevent.
48
48
  - Flag an unanchored entry. The standard scopes the rule forward, and an entry written before it is dated by blame rather than by a read.
49
49
 
50
- The session amending a decision writes its anchor, which Step 3 already requires.
50
+ The session amending a decision writes its anchor, which Step 3 already requires. Step 3 holds the writer, and the two never meet. Anchoring fires when this run amends a decision, and this sweep fires when the diff moves a path under one, so a single step covering both would gate the anchor obligation on a signal that has nothing to do with it.
51
51
 
52
52
  ## Output
53
53
 
@@ -46,7 +46,7 @@ A rule belongs in this skill only when all four hold. Three of the four reject m
46
46
  3. **It is judgment rather than a threshold.** A contrast ratio has a number and belongs to the floor. Whether a palette reads cheap has no number and belongs here.
47
47
  4. **One line states it, and something could violate that line.** "Use whitespace intentionally" fails, since nothing could break it. "No three consecutive image-and-text splits" passes, since it can be counted.
48
48
 
49
- A rule failing any of the four is recorded as considered and declined rather than argued again, in the reference where it would have gone.
49
+ A rule failing any of the four is recorded as considered and declined rather than argued again, in `references/adopted.md`, under the reference where it would have gone.
50
50
 
51
51
  ## Must not
52
52
 
@@ -115,9 +115,11 @@ It states no values. A value belongs to the project's own design document.
115
115
 
116
116
  ## The rest of the catalog
117
117
 
118
- Read `${CLAUDE_SKILL_DIR}/references/tells.md` before handing over anything a model drafted, and whenever output satisfies every rule here and still reads generic. The ten above are the common cases. It holds the rest, plus the countable composition limits, the first-screen budget, and the record of which external items were adopted, which declined, and why.
118
+ Read `${CLAUDE_SKILL_DIR}/references/tells.md` before handing over anything a model drafted, and whenever output satisfies every rule here and still reads generic. The ten above are the common cases. It holds the rest, plus the countable composition limits and the first-screen budget.
119
119
 
120
- Skip it on a small change to a surface with a settled direction. The catalog is a diagnostic and costs a read on every invocation that does not need one.
120
+ Skip `tells.md` on a small change to a surface with a settled direction. The catalog is a diagnostic and costs a read on every invocation that does not need one.
121
+
122
+ Read `${CLAUDE_SKILL_DIR}/references/adopted.md` only when extending this guidance or arguing against a rule in it. It records which external catalog items were adopted, which declined, and why.
121
123
 
122
124
  ## When it reads almost right
123
125
 
@@ -0,0 +1,40 @@
1
+ ---
2
+ title: Adopted and declined
3
+ description: Which external design catalogs this skill adopted from, which items it declined, and why, so a later session extends the position instead of re-deriving it
4
+ ---
5
+
6
+ # Adopted and declined
7
+
8
+ External catalogs were read and filtered rather than imported. This file is the record, and a later session extends it rather than re-deriving it.
9
+
10
+ ## Adopted
11
+
12
+ **Adopted with no change.** The three equal cards, the centered hero over a wash, enumerated eyebrows, scroll cues, decorative status dots, atmospheric strips, the fake screenshot built from boxes, filler verbs, and placeholder that reads as placeholder. Each names a shape, each carries a replacement, and none depends on a stack.
13
+
14
+ **Adopted with the stack removed.** Source items naming an icon set, a component library, a font by name, or an animation package were rewritten to state what the rule is about. "Do not use Inter" became one family doing every job, since the defensible claim is about pairing and role separation rather than about one typeface.
15
+
16
+ ## Declined from the catalogs
17
+
18
+ **Banned fonts by name.** A font ban is a value ban, and a value belongs to the project's own design document rather than to a skill that loads everywhere. A project that wants a typeface ruled out rules it out there.
19
+
20
+ **Numeric intensity dials.** Every external source carries a 1-to-10 scale for variance, motion and density. A session picks a middle value and reports compliance. That satisfies the rule, decides nothing, and leaves no trace a later reader could check it by. The declared read carries the same information in a sentence somebody can argue with.
21
+
22
+ **The em dash ban as a design rule.** One source bans the character on a page as a visual tell. The markdown standard already bans it for prose reasons and `canon markdown audit` gates that from package data, so restating it here would put a second copy of an enforced rule behind an unenforced pointer.
23
+
24
+ **The official-package map.** A table routing a brief to Fluent, Material, Carbon, Polaris, Primer or a government design system. It is real advice and it is a stack decision a project takes once, so it belongs in that project's own records rather than in a skill that loads on every design round.
25
+
26
+ **Scoping out application UI.** The largest source covers landing pages, portfolios and redesigns, and excludes dashboards, data tables and multi-step product UI. Those exclusions are most of what software projects actually build, so the kinds reference carries application UI as a first-class kind.
27
+
28
+ ## Declined from the systems reference
29
+
30
+ Each failed the test in `REQUIREMENT.md`. Recorded so they are not argued again.
31
+
32
+ - **Control sizing and proportion.** An unguided model produces reasonable controls without instruction, so it fails the first question.
33
+ - **Specific ratios for a type scale**, such as a named musical interval. Falsifiable and arbitrary, and a project picking a different ratio is not wrong.
34
+ - **Named palettes or banned hues.** A value ban, which belongs to the project's design document. This is where every external catalog of this kind ends up, and it is why theirs cannot be imported.
35
+ - **A minimum contrast figure.** A threshold with a number, which the accessibility rules own.
36
+ - **Imagery as a system.** There is no scale to establish. What a model gets wrong about images is using fake ones, which `tells.md` already covers, so the layer stays thin on purpose rather than by oversight.
37
+
38
+ ## Carried as a caution
39
+
40
+ **Greeking.** Placeholder text is correct while judging space and wrong once an arm is judged on content, since real copy length is what breaks a composition. State which of the two a set is doing.
@@ -46,7 +46,7 @@ Documentation, articles, reference pages, learning material. The reader arrived
46
46
  ## Kinds this file does not cover
47
47
 
48
48
  - **Transactional flows** such as checkout, sign-up and settings are read as application UI. Their distinctive rules are state coverage and error recovery, which the `ui` governance rules already carry.
49
- - **Presentation surfaces** such as slide decks are governed by `${CLAUDE_SKILL_DIR}/../../standards/slides.md` and drafted by `draft-slides`. Take the layer ordering and the floor from the body and the rest from there.
49
+ - **Presentation surfaces** such as slide decks are drafted by `draft-slides`, which carries the deck's own design rules. Take the layer ordering and the floor from the body and the rest from that skill.
50
50
  - **Terminal and text-mode surfaces** have no layout engine and their own color rules, stated where the writing surface is decided rather than here.
51
51
 
52
52
  A read naming any of the three above takes the body's rules and says it has no per-kind guidance, naming the surface that governs it. A read naming a kind this file does not list at all says so rather than borrowing the nearest section.
@@ -40,10 +40,4 @@ The layer a model is worst at, and the layer where rules are hardest to make fal
40
40
 
41
41
  ## Considered and declined
42
42
 
43
- Each failed the test in `REQUIREMENT.md`. Recorded so they are not argued again.
44
-
45
- - **Control sizing and proportion.** An unguided model produces reasonable controls without instruction, so it fails the first question.
46
- - **Specific ratios for a type scale**, such as a named musical interval. Falsifiable and arbitrary, and a project picking a different ratio is not wrong.
47
- - **Named palettes or banned hues.** A value ban, which belongs to the project's design document. This is where every external catalog of this kind ends up, and it is why theirs cannot be imported.
48
- - **A minimum contrast figure.** A threshold with a number, which the accessibility rules own.
49
- - **Imagery as a system.** There is no scale to establish. What a model gets wrong about images is using fake ones, which `tells.md` already covers, so the layer stays thin on purpose rather than by oversight.
43
+ The items considered for this reference and declined sit in `adopted.md` beside this file, recorded so they are not argued again.
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  title: Machine tells in design
3
- description: The visual defaults a model reaches for when nothing states a direction, each with what to do instead, plus the record of which external items were adopted, which were declined, and why
3
+ description: The visual defaults a model reaches for when nothing states a direction, each with what to do instead, plus the countable composition limits and the first-screen budget
4
4
  ---
5
5
 
6
6
  # Machine tells in design
@@ -76,26 +76,4 @@ These are the rules with numbers, so they are checked by counting rather than by
76
76
 
77
77
  ## Adopted, declined, and why
78
78
 
79
- External catalogs were read and filtered rather than imported. This section is the record, and a later session extends it rather than re-deriving it.
80
-
81
- ### Adopted
82
-
83
- **Adopted with no change.** The three equal cards, the centered hero over a wash, enumerated eyebrows, scroll cues, decorative status dots, atmospheric strips, the fake screenshot built from boxes, filler verbs, and placeholder that reads as placeholder. Each names a shape, each carries a replacement, and none depends on a stack.
84
-
85
- **Adopted with the stack removed.** Source items naming an icon set, a component library, a font by name, or an animation package were rewritten to state what the rule is about. "Do not use Inter" became one family doing every job, since the defensible claim is about pairing and role separation rather than about one typeface.
86
-
87
- ### Declined
88
-
89
- **Banned fonts by name.** A font ban is a value ban, and a value belongs to the project's own design document rather than to a skill that loads everywhere. A project that wants a typeface ruled out rules it out there.
90
-
91
- **Numeric intensity dials.** Every external source carries a 1-to-10 scale for variance, motion and density. A session picks a middle value and reports compliance. That satisfies the rule, decides nothing, and leaves no trace a later reader could check it by. The declared read carries the same information in a sentence somebody can argue with.
92
-
93
- **The em dash ban as a design rule.** One source bans the character on a page as a visual tell. The markdown standard already bans it for prose reasons and `canon markdown audit` gates that from package data, so restating it here would put a second copy of an enforced rule behind an unenforced pointer.
94
-
95
- **The official-package map.** A table routing a brief to Fluent, Material, Carbon, Polaris, Primer or a government design system. It is real advice and it is a stack decision a project takes once, so it belongs in that project's own records rather than in a skill that loads on every design round.
96
-
97
- **Scoping out application UI.** The largest source covers landing pages, portfolios and redesigns, and excludes dashboards, data tables and multi-step product UI. Those exclusions are most of what software projects actually build, so the kinds reference carries application UI as a first-class kind.
98
-
99
- ### Carried as a caution
100
-
101
- **Greeking.** Placeholder text is correct while judging space and wrong once an arm is judged on content, since real copy length is what breaks a composition. State which of the two a set is doing.
79
+ The record of which external catalog items were adopted, which declined, and why sits in `adopted.md` beside this file.
@@ -35,7 +35,8 @@ The quiet one is the baseline. A diff resolved against a bare local ref equals H
35
35
 
36
36
  ## Out of scope
37
37
 
38
- - The context entries, requirements, architecture, wireframes, and task board: `context-fold`, which runs immediately before this skill in the ship chain and resolves the same baseline. The split is by audience, so a file's location decides which skill owns it rather than its subject.
38
+ - The context entries, architecture, wireframes, and task board: `context-fold`, which runs immediately before this skill in the ship chain and resolves the same baseline. The split is by audience, so a file's location decides which skill owns it rather than its subject.
39
+ - The requirements record: `document-health` reads it when asked, and `markdown-propose` rewrites it from the answers
39
40
  - `CLAUDE.md` and the installed seed docs: `seed-sync`, which reconciles them per section against the toolkit source
40
41
  - Changelog entries, which release tooling generates from commit messages
41
42
  - Whether the prose conforms to its standards. `canon markdown audit` reports violations and fixes none, and this skill writes prose it does not audit.
@@ -23,6 +23,7 @@ The third is silence on an unread axis. Both measured verbs resolve their folder
23
23
  - Say which layer answered the classifier sweep, since its model layer being off narrows the read without refusing it
24
24
  - Take every checkpoint from the record the verb returns rather than from a number written into the skill
25
25
  - Run standalone, and stay callable from the structural check rather than reachable only through it
26
+ - Read the requirements and architecture records for identity drift when the scope reaches them, and print one reminder line per doc from `canon records stale canonical`, since the fold no longer writes the first and only writes the second for a planned slot decision, so nothing else reads either whole
26
27
 
27
28
  ## Must not
28
29
 
@@ -30,6 +31,7 @@ The third is silence on an unread axis. Both measured verbs resolve their folder
30
31
  - Emit a verdict across the three axes, or a score across the documents. Two axes answer from verbs and one answers from a reading, so any roll-up is a figure that lies about the third.
31
32
  - Report a finding against a file nobody hand-authors. A generated index, a gitignored file, and a copied reference each name a file an author cannot fix.
32
33
  - Answer an axis by file inspection where a verb answers it. The verb is the surface under test and a hand-rolled read of the same files is not.
34
+ - Trigger itself, or ask a hook, a gate stage, or CI to trigger the canonical review. The operator settled that it runs only when asked.
33
35
  - Read a document's modification time as its staleness. A file untouched beside code untouched is current, and the timestamp answers a different question.
34
36
 
35
37
  ## Guards
@@ -59,6 +59,18 @@ No verb answers whether a document still describes the tree it was written about
59
59
 
60
60
  Mark every staleness finding as a reading. It is this session's judgment rather than a measurement, and a report that sets it beside two verb-backed axes without marking it implies evidence the axis does not carry.
61
61
 
62
+ ### The requirements and architecture records
63
+
64
+ When the scope reaches `canon/REQUIREMENTS.md` or `canon/ARCHITECTURE.md`, read each for identity drift as well as for stale paths, and take the review point from the verb:
65
+
66
+ ```bash
67
+ CANON_NON_INTERACTIVE=1 canon records stale canonical --json
68
+ ```
69
+
70
+ Each doc in the record carries `reviewed` and `releasesSince`. `${CLAUDE_SKILL_DIR}/references/axes.md` holds the identity claim shapes to test and how the record reads. Skip both the read and the verb when the scope excludes the two docs.
71
+
72
+ Nothing triggers this review but a request. A finished review routes to `markdown-propose` for the rewrite, and its last edit sets `reviewed:` in the doc's frontmatter to the day the operator's answers landed. This run writes neither.
73
+
62
74
  ## Step 4: report per document
63
75
 
64
76
  Give each document its three axes, and give each axis three things: the state, the evidence class, and the command or skill that repairs it. Naming the repair is not running it.
@@ -85,4 +97,13 @@ Document health: `<scope>`, <n> documents read.
85
97
  Length and placement are measured. Staleness is a reading.
86
98
  ```
87
99
 
100
+ When Step 3 read the canonical records, add one reminder line per doc the verb returned, under the evidence line:
101
+
102
+ ```markdown
103
+ `canon/REQUIREMENTS.md`: reviewed <date>, <n> releases since.
104
+ `canon/ARCHITECTURE.md`: never reviewed.
105
+ ```
106
+
107
+ Write `reviewed value is not a date: <value>` for a doc carrying `invalidReviewed`, and `no release tags to count` in place of the count when `tagged` is false. Name the unread cause instead when the verb refused or the binary carries no `canonical` kind.
108
+
88
109
  Keep the evidence line under the table on every run. A table read without it flattens a judgment into a measurement, which is the one shape the three classes exist to prevent.
@@ -67,6 +67,18 @@ Read each document against the surfaces it names. Four claim shapes are testable
67
67
 
68
68
  A claim resting on none of the four is unverifiable from here. Report it as unread rather than as passing, which is the same rule the measured axes take when a verb refuses.
69
69
 
70
+ ### Identity drift in the requirements and architecture records
71
+
72
+ These two records state what the project is and why it is built the way it is, so they go stale by the project changing direction as well as by the tree moving. Test these claim shapes beside the four above:
73
+
74
+ - A goal nobody pursues, read against the task board and the recent history
75
+ - A non-goal the project has since shipped
76
+ - A constraint the tree contradicts
77
+ - A decision whose revisit sentence has fired
78
+ - A risk or open question already fixed
79
+
80
+ Each is a `read`. The review point beside them is `measured`: `canon records stale canonical --json` returns per doc the `reviewed` date from its frontmatter and `releasesSince`, the release tags merged into HEAD after that day. A null `releasesSince` means the doc was never reviewed, and `tagged: false` means no release tag exists to count, so a zero there measured nothing. The count is a reminder of how far the project has moved since someone last read the record whole, never a threshold.
81
+
70
82
  **Routes to:** the skill that rewrites a stale claim against an answer, rather than a direct edit from here. A document health run reports and never repairs.
71
83
 
72
84
  **Caveat:** a reading is the weakest evidence in the report and the most consequential finding in it, which is the tension this axis ships with. Marking the class is what keeps the two facts together in the reader's hands.
@@ -35,7 +35,7 @@ Write every arm side by side on one self-contained HTML page at `<dest>/candidat
35
35
  - Hand over the per-arm file addresses beside the combined page where the declared layer is composition, layout or space, and say that an arm is judged at a width by opening its own file in the browser's device toolbar. The combined page cannot answer that question at all: every arm sits in a column there while the media queries answer to the whole window, so each one renders its widest layout in a narrow space no matter how the window is sized. Build no width control of your own, since the browser already has one.
36
36
  - Take the live-app branch instead when the surface under decision is a running app: lift the rendered markup and link a copy of the built stylesheet rather than inlining, per `${CLAUDE_SKILL_DIR}/references/live-arms.md`.
37
37
  - On the default path, inline every style, script, and asset the page needs. The render reads the file off disk, so a page reaching for a build step or a network font renders without it and the arms differ by something nobody chose.
38
- - On the default path, declare a font stack the machine resolves, such as `system-ui` behind a generic fallback. The render refuses a page that would rewrap against a substitute rather than shipping a false comparison, so a page naming no font at all is refused on whatever the default resolves to.
38
+ - On the default path, name a real font first in the stack, one the machine has or the page embeds, such as the project's own family from its design tokens. A generic keyword such as `system-ui` or `sans-serif` is refused, since it resolves to a different font on each machine. The render refuses a page that would rewrap against a substitute rather than shipping a false comparison, so a page naming no font at all is refused on whatever the default resolves to.
39
39
 
40
40
  ### What varies
41
41
 
@@ -72,7 +72,7 @@ Follow `${CLAUDE_SKILL_DIR}/../draft-and-pick/SKILL.md` Steps 2 through 5 agains
72
72
  This step and Step 7 replace `draft-and-pick`'s own Step 6, since the pick here produces several final files rather than one applied surface.
73
73
 
74
74
  1. Extract the picked arm's `.mark` markup as the final vector source. Write it to `<write-folder>/favicon.svg`.
75
- 2. Under `<dest>/render/`, write one `icon-<w>x<h>.html` page per Step 2 size, carrying the picked `.mark` markup. Give every page's captured element the shared class `.render`, so one capture call renders the whole batch regardless of the size spread. `canon capture` opens every page at a fixed 2x device scale factor and screenshots the element at that scale, so declare each `.render` element at half its target dimension, `<w>/2` by `<h>/2`, to land the captured PNG on the literal target size rather than double it. Declare a machine-resolved font stack (`system-ui` behind a generic fallback) on each, since `canon capture` refuses a page naming no font at all.
75
+ 2. Under `<dest>/render/`, write one `icon-<w>x<h>.html` page per Step 2 size, carrying the picked `.mark` markup. Give every page's captured element the shared class `.render`, so one capture call renders the whole batch regardless of the size spread. `canon capture` opens every page at a fixed 2x device scale factor and screenshots the element at that scale, so declare each `.render` element at half its target dimension, `<w>/2` by `<h>/2`, to land the captured PNG on the literal target size rather than double it. Declare no font on them, since each holds the mark alone and `canon capture` skips the font check on an element with no text. A generic family such as `system-ui` would be refused if text ever sat inside one.
76
76
  3. Render the batch:
77
77
 
78
78
  ```bash
@@ -45,6 +45,8 @@ Create `demos/<slug>/beats.md` at the project root, creating the folder if it do
45
45
 
46
46
  Write all nine sections. Pre-seed every section with concrete content so the draft is shippable as-is. The user edits down rather than fills blanks.
47
47
 
48
+ Load `canon:video-craft` for every zoom and caption value the draft names, and report it rather than proceeding silently when it does not resolve. The template below states none, since each number there traces to a source that skill records.
49
+
48
50
  ```markdown
49
51
  # Screencast: <short title>
50
52
 
@@ -72,7 +74,7 @@ Five beats. Each uses five fields. Add a sixth `Transition out` only when non-de
72
74
  - On screen: <derived from hero moment>
73
75
  - Action: <one verb, derived>
74
76
  - Watch for:
75
- - Emphasis: zoom 1.4x
77
+ - Emphasis: zoom onto the action, scale and speed per `canon:video-craft`
76
78
  - Caption:
77
79
 
78
80
  ### Beat 2: Setup
@@ -104,7 +106,7 @@ Five beats. Each uses five fields. Add a sixth `Transition out` only when non-de
104
106
  - On screen:
105
107
  - Action:
106
108
  - Watch for:
107
- - Emphasis: zoom 1.2x out
109
+ - Emphasis: zoom out to full frame
108
110
  - Caption:
109
111
 
110
112
  ## 4. Sequencing notes
@@ -119,14 +121,14 @@ Five beats. Each uses five fields. Add a sixth `Transition out` only when non-de
119
121
  - Resolution: 1920x1080
120
122
  - Frame rate: 30fps
121
123
  - Container: mp4 H.264
122
- - Zoom: max 1.8x with always-zoom-out before cut
124
+ - Zoom: only on an action too small to read at full frame, scale, speed, and dwell per `canon:video-craft`, zoomed out before every cut
123
125
  - Highlight overlay: ~1.5s soft glow
124
126
 
125
- ## 6. Caption typography
127
+ ## 6. Captions
126
128
 
127
- - White text on dark scrim at ~60% opacity
128
- - ~200ms fade in and out
129
- - One line max per caption, split across beats if needed
129
+ - Each caption names what its beat's frame shows, at most two lines of 42 characters, per `canon:video-craft`
130
+ - Hold and reading rate per `canon:video-craft`, splitting a caption across beats rather than shortening its hold
131
+ - Placed off the element the beat acts on
130
132
 
131
133
  ## 7. Distribution
132
134
 
@@ -1,39 +1,44 @@
1
1
  ---
2
2
  name: draft-slides
3
- description: Why the skill owns deck content and the CLI owns layout, and why one render is read back before the deck is called done
3
+ description: Why the skill draws a deck as HTML in the project's tokens inside its own folder, why the CLI owns the conversion, and why one render is read back before the deck is called done
4
4
  ---
5
5
 
6
6
  # Draft slides requirement
7
7
 
8
8
  ## Gap
9
9
 
10
- Without this skill, a deck request turns into hand-built layout. The session invents layout names the renderer does not have, so the render falls back or fails, and it writes centered body text and bullet lines that overflow the slide because nothing told it the type scale is fixed. Every slide comes out as a title over bullets, which is the shape that needs no decision and reads as a document rather than a deck.
10
+ Without this skill, a deck request turns into hand-built output. The session writes a deck into whatever path occurs to it, so a second deck overwrites the first and nothing lists either. It writes pptxgenjs code or hex colors per deck, so the deck takes neither the project's design nor any other deck's, and it invents attributes the converter does not read, so a section, a chart, or an entrance silently goes missing. Every slide comes out as a title over bullets, which is the shape that needs no decision and reads as a document rather than a deck.
11
11
 
12
- Reimplementing spacing and palette logic is the failure that survives the session. The CLI already owns both, so a deck that styles itself drifts from every other deck and stops being recognizable. And a first render shipped unread hands the audience the overlap and the overflow, since a source that looks correct says nothing about the picture it produces.
12
+ A first render shipped unread hands the audience the overlap, the overflow, and every element the converter fell back to a picture for, since markup that looks correct says nothing about the file it produces.
13
13
 
14
14
  ## Must
15
15
 
16
- - Read the layout catalog from the CLI before drafting and pick only from what it returns
17
- - Match the content shape to the layout, since each one parses a different body
18
- - Vary layouts across the deck rather than repeating one
19
- - Size content to fit the fixed type scale, keeping titles short and bullet lines tight
16
+ - Read the existing decks and the slide format from the CLI before drawing, and pick a deck name no listed deck carries unless the request names one
17
+ - Write each deck into its own folder under the slides record folder, one HTML file per slide in filename order
18
+ - Draw with the project's custom properties so the deck takes the project's design
19
+ - Vary the composition across the deck rather than repeating one shape
20
+ - Size content to fit the slide frame, keeping titles short and lines tight
20
21
  - Shell out to the render command for the deck itself
21
- - Run one QA pass over the rendered images and fix what it reports
22
+ - Read every fallback and refusal the render reports, run one QA pass over the rendered images, and fix what both report
22
23
 
23
24
  ## Must not
24
25
 
25
- - Hardcode a layout name, which goes stale the moment the catalog changes
26
- - Reimplement layout, palette, or type scale, which the CLI owns
26
+ - Hardcode a deck name, an attribute, or a chart type, which goes stale the moment the CLI changes
27
+ - Reimplement the conversion, the master, or the packaging, which the CLI owns
28
+ - Write a deck into the shared layouts folder, which is never listed as a deck
29
+ - Invent token values when the project has no token stylesheet
27
30
  - Write centered body text or content that overflows a slide
28
31
  - Loop on aesthetics past a single fix pass
29
32
 
30
33
  ## Guards
31
34
 
35
+ - No token stylesheet: draw the deck anyway and say it renders unstyled.
32
36
  - Image conversion tools missing: skip the image pass and say so. Do not fail the render over a verification step.
33
37
 
34
38
  ## Out of scope
35
39
 
36
- - Rendering, which the CLI owns end to end
37
- - The palette and the type scale, which live in the CLI rather than in the source
40
+ - Converting HTML to PowerPoint, which the CLI owns end to end
41
+ - The project's palette and faces, which live in its token stylesheet rather than in the slides
38
42
  - Writing the content the deck is about, which the caller brings
43
+ - Drafting a deck as a canvas page, which waits on a measurement of that authoring surface
39
44
  - Recording a demo, which `draft-screencast` owns
@@ -1,49 +1,59 @@
1
1
  ---
2
2
  name: draft-slides
3
- description: Drafts a `.claude/SLIDES.md` source from a topic, picks a layout per slide, then renders it to PowerPoint via `canon slides render`. Use when asked to "draft slides", "make a deck", "build a presentation", "turn this into slides", or "render a SLIDES.md". Holds the deck design rules. Do NOT reimplement render logic. The CLI owns layout and styling. Assumes the `canon` CLI is on PATH.
3
+ description: Draws a deck as HTML slides in the project's own design, one folder under `.canon/slides/` per deck, then renders it to an editable PowerPoint file via `canon slides render`. Use when asked to "draft slides", "make a deck", "build a presentation", "turn this into slides", or "render the deck". Holds the deck design rules. Do NOT reimplement the conversion. The CLI owns layout into PowerPoint shapes, the master, and packaging. Assumes the `canon` CLI is on PATH.
4
4
  ---
5
5
 
6
6
  # Draft slides
7
7
 
8
- Author a `SLIDES.md` source, then shell out to `canon slides render`. The CLI owns all layout and styling. This skill owns content and the design choices encoded in the source.
8
+ Draw each slide as an HTML file in a deck folder, then shell out to `canon slides render`. The CLI lays every slide out in a browser and rebuilds it as editable PowerPoint shapes. This skill owns the content, the slide markup, and the design choices the markup encodes.
9
9
 
10
- ## Read the catalog
10
+ ## Read the decks and the format
11
11
 
12
- Run this first to load the available layouts. Never hardcode layout names. The catalog is the source of truth.
12
+ Run both first. Never hardcode a deck name, an attribute, or a chart type. The CLI is the source of truth for each.
13
13
 
14
14
  ```bash
15
15
  canon slides list --json 2>/dev/null
16
+ canon docs slides
16
17
  ```
17
18
 
18
- ## Draft the source
19
+ The list returns one row per deck, carrying its `name`, `title`, slide count, and `path`. When the request names a deck the list holds, edit that folder. Otherwise pick a new kebab-case name no row carries.
19
20
 
20
- Write the deck to `.claude/SLIDES.md` from the project root. Structure:
21
+ The docs page states what `deck.json` holds, what each slide declares on its `<body>`, the motion attributes, speaker notes, charts, and what each refusal reports.
21
22
 
22
- - Deck frontmatter between `---` delimiters: `title`, optional `subtitle`, `palette`, and `variant` (light or dark).
23
- - One slide per section, separated by a `---` rule. Each slide opens with a `# Title` and a `layout:` line naming a layout from the catalog, followed by its content.
23
+ ## Draw the deck
24
24
 
25
- Match content shape to the layout: bullet lists for list layouts, `## Heading` blocks for columns, `- value : caption` pairs for stats and cards, a quote with a `- attribution` line for quotes.
25
+ A deck folder sits at `.canon/slides/<deck>/` from the project root, and holds:
26
26
 
27
- For a deck with chapters, add a `toc` slide near the front and mark each chapter opener with the `section` layout. The render fills the contents links and the per-slide footer automatically from the section slides. Leave the `toc` slide body empty.
27
+ - One `.html` file per slide, rendered in filename order. Number them with a zero-padded prefix, such as `01-cover.html`, so a slide inserted later sorts where it belongs.
28
+ - `deck.json`, optional, for the title, the header and footer bands, slide numbers, the mark, and embedded faces.
29
+ - `assets/` for images the slides reference by a relative path.
30
+
31
+ Never write a slide into `.canon/slides/layouts/`. That folder holds the project's shared layouts and is never listed as a deck.
32
+
33
+ Each slide is a full HTML document laid out at 1280 by 720 CSS pixels. Position its blocks absolutely or with a flex or grid container sized to that frame, and keep every element inside it.
28
34
 
29
35
  ## Design rules
30
36
 
31
- The palette and type scale live in the CLI. Own the choices the source controls.
37
+ The render injects the project's token stylesheet ahead of each slide's own styles, so the deck takes the project's design rather than the toolkit's.
32
38
 
33
- - Pick the variant that fits the topic. Light is a paper background, dark is near black. Both carry the same rust accent.
34
- - Vary the layout across slides. Never repeat title-and-bullets on every slide. Reach for columns, stat callouts, grids, and section dividers.
35
- - The CLI enforces the type scale, so size content to fit rather than overflow. Keep titles short and bullet lines tight.
36
- - Never write centered body text or content that overflows a slide. Let the layouts place the elements.
39
+ - Use the project's custom properties, such as `var(--color-accent)`, for every color, face, and spacing value the stylesheet defines. Read the names from `.claude/design/base.css` and any overrides under `.claude/design/project/`. When neither exists, say the deck renders unstyled rather than inventing values to cover it.
40
+ - Leave the `--color-*` roles to the stylesheet rather than redefining them in a slide. The master reads its colors off the first slide's `<html>`, and a slide body computing its own `--color-text` is reported, since the bands keep the master's colors.
41
+ - Vary the composition across slides. Never repeat a title over bullets on every slide. Reach for columns, a row of large numbers, a grid of cards, a chart, a pull quote, and section dividers.
42
+ - Keep titles short and lines tight, so text fits its box at the size the design sets rather than overflowing the frame.
43
+ - Never write centered body text.
44
+ - Prefer CSS the converter maps to native shapes. An element computing a property it cannot map is drawn as a picture of itself and reported on stderr, so a slide full of gradients and filters stops being editable.
37
45
 
38
46
  ## Render
39
47
 
40
48
  Shell out to the CLI. It writes the deck and reports the path.
41
49
 
42
50
  ```bash
43
- canon slides render --source .claude/SLIDES.md --out .canon/tmp/render/slides
51
+ canon slides render <deck>
44
52
  ```
45
53
 
46
- Pass `--variant light` or `--variant dark` to override the source variant for a one-off render. Pass `--open` to open the deck, and `--mirror <dir>` (or set `CANON_SLIDES_MIRROR`) to copy it into a synced folder.
54
+ With one deck in the project the name can be left out. The render refuses with the deck list when there are several. Pass `--open` to open the deck, and `--mirror <dir>`, or set `CANON_SLIDES_MIRROR`, to copy it into a synced folder.
55
+
56
+ Read every `✗` line the render prints. A picture fallback, a refused link, chart, or effect, and a missing token each leave the deck written with that piece degraded or left out.
47
57
 
48
58
  ## QA loop
49
59
 
@@ -51,12 +61,13 @@ Run this once after the first render, then stop.
51
61
 
52
62
  1. Convert the deck to images: `soffice --headless --convert-to pdf <deck>.pptx` then `pdftoppm -r 90 -png <deck>.pdf slide`. If `soffice` or `pdftoppm` is missing, skip the image pass and say so. Do not fail the render.
53
63
  2. Open and inspect every rendered image in this session, checking each slide for overlap, overflow, low contrast, and empty regions.
54
- 3. Fix the reported issues in `SLIDES.md` once, re-render, and stop. Do not loop indefinitely on aesthetics.
64
+ 3. Fix the reported issues and the `✗` lines in the slide files once, re-render, and stop. Do not loop indefinitely on aesthetics.
55
65
 
56
66
  ## Response
57
67
 
58
68
  After rendering, report:
59
69
 
60
- - Slide count and the deck path
61
- - The palette and variant used
70
+ - The deck folder, the slide count, and the written `.pptx` path
71
+ - Whether the project's token stylesheet was found
72
+ - Each `✗` line the final render printed, or that it printed none
62
73
  - Any QA issues found and what changed, or that the deck passed clean