@erclx/canon 5.51.0 → 5.53.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 (142) hide show
  1. package/CHANGELOG.md +20 -0
  2. package/README.md +1 -4
  3. package/claude/.claude-plugin/plugin.json +1 -1
  4. package/claude/skills/canon-cli/SKILL.md +0 -3
  5. package/claude/skills/context-fold/REQUIREMENT.md +0 -1
  6. package/claude/skills/design-taste/references/kinds.md +0 -1
  7. package/claude/skills/draw-figure/REQUIREMENT.md +2 -3
  8. package/claude/skills/draw-figure/SKILL.md +4 -5
  9. package/claude/skills/draw-figure/references/figures.md +0 -1
  10. package/claude/skills/draw-figure/references/hand-drawn.md +1 -1
  11. package/claude/skills/git-pr/references/pr.md +1 -1
  12. package/claude/skills/pick-by-eye/REQUIREMENT.md +0 -1
  13. package/claude/skills/pick-by-eye/SKILL.md +1 -1
  14. package/claude/skills/review-address/SKILL.md +1 -1
  15. package/claude/skills/review-address/references/post-review-findings.md +1 -1
  16. package/claude/skills/review-pr/references/post.md +2 -2
  17. package/claude/skills/target-check/SKILL.md +2 -0
  18. package/claude/skills/target-setup/SKILL.md +1 -1
  19. package/claude/skills/target-update/REQUIREMENT.md +33 -0
  20. package/claude/skills/target-update/SKILL.md +136 -0
  21. package/claude/skills/teach-craft/REQUIREMENT.md +30 -0
  22. package/claude/skills/teach-craft/SKILL.md +39 -0
  23. package/claude/skills/teach-craft/references/lesson-craft.md +52 -0
  24. package/claude/skills/{teach-workspace → teach-craft}/references/pedagogy.md +12 -4
  25. package/docs/agents/audits.md +0 -1
  26. package/docs/agents/migrate.md +2 -1
  27. package/docs/target/migrations.md +12 -1
  28. package/docs/target/projects.md +1 -1
  29. package/docs/target/sync.md +1 -1
  30. package/docs/workflow/parallel-features.md +1 -1
  31. package/docs/workflow/skill-map-on-request.md +10 -22
  32. package/docs/workflow/skill-map.md +13 -14
  33. package/package.json +1 -4
  34. package/scripts/core/regen-web-previews.ts +2 -67
  35. package/src/audits/catalog.ts +0 -1
  36. package/src/browser/engine.ts +3 -6
  37. package/src/capture/render.ts +1 -1
  38. package/src/claude/cases/authoring.ts +0 -12
  39. package/src/claude/cases/misc.ts +0 -17
  40. package/src/claude/cases/setup.ts +7 -0
  41. package/src/claude/cases/workflow.ts +2 -38
  42. package/src/claude/skills-audit.ts +0 -1
  43. package/src/cli/help.ts +0 -7
  44. package/src/cli.ts +0 -6
  45. package/src/commands/labels.ts +9 -7
  46. package/src/commands/records.ts +0 -1
  47. package/src/commands/serve.ts +2 -2
  48. package/src/design/components.ts +8 -1514
  49. package/src/design/css.ts +5 -6
  50. package/src/design/fonts.ts +3 -5
  51. package/src/driver/drive.ts +3 -4
  52. package/src/driver/steps.ts +2 -5
  53. package/src/inventory/walk.ts +1 -1
  54. package/src/markdown/scope.ts +4 -31
  55. package/src/migrate/status.ts +5 -1
  56. package/src/records/validate.ts +4 -176
  57. package/src/sandbox/equivalence.ts +0 -5
  58. package/tooling/claude/seeds/.claude/hooks/review-post-scan.sh +1 -1
  59. package/claude/skills/draft-and-pick/REQUIREMENT.md +0 -26
  60. package/claude/skills/draft-and-pick/SKILL.md +0 -11
  61. package/claude/skills/draft-doc/REQUIREMENT.md +0 -26
  62. package/claude/skills/draft-doc/SKILL.md +0 -11
  63. package/claude/skills/draft-figure/REQUIREMENT.md +0 -26
  64. package/claude/skills/draft-figure/SKILL.md +0 -11
  65. package/claude/skills/draft-identity/REQUIREMENT.md +0 -26
  66. package/claude/skills/draft-identity/SKILL.md +0 -11
  67. package/claude/skills/draft-ready/REQUIREMENT.md +0 -26
  68. package/claude/skills/draft-ready/SKILL.md +0 -11
  69. package/claude/skills/draft-screencast/REQUIREMENT.md +0 -26
  70. package/claude/skills/draft-screencast/SKILL.md +0 -11
  71. package/claude/skills/draft-slides/REQUIREMENT.md +0 -26
  72. package/claude/skills/draft-slides/SKILL.md +0 -11
  73. package/claude/skills/make-deck/REQUIREMENT.md +0 -36
  74. package/claude/skills/make-deck/SKILL.md +0 -80
  75. package/claude/skills/make-deck/references/deck.md +0 -183
  76. package/claude/skills/read-frames/REQUIREMENT.md +0 -30
  77. package/claude/skills/read-frames/SKILL.md +0 -55
  78. package/claude/skills/record-screencast/REQUIREMENT.md +0 -35
  79. package/claude/skills/record-screencast/SKILL.md +0 -99
  80. package/claude/skills/script-screencast/REQUIREMENT.md +0 -34
  81. package/claude/skills/script-screencast/SKILL.md +0 -70
  82. package/claude/skills/script-screencast/references/beats-template.md +0 -119
  83. package/claude/skills/teach-workspace/REQUIREMENT.md +0 -34
  84. package/claude/skills/teach-workspace/SKILL.md +0 -196
  85. package/claude/skills/teach-workspace/references/glossary.md +0 -90
  86. package/claude/skills/teach-workspace/references/lesson-build.md +0 -106
  87. package/claude/skills/teach-workspace/references/lesson-craft.md +0 -135
  88. package/claude/skills/teach-workspace/references/promotion-fold.md +0 -35
  89. package/claude/skills/teach-workspace/references/promotion.md +0 -116
  90. package/claude/skills/teach-workspace/references/revisit.md +0 -28
  91. package/claude/skills/teach-workspace/references/teach.md +0 -211
  92. package/claude/skills/video-craft/REQUIREMENT.md +0 -35
  93. package/claude/skills/video-craft/SKILL.md +0 -96
  94. package/claude/skills/video-craft/references/adopted.md +0 -110
  95. package/src/commands/demo.ts +0 -542
  96. package/src/commands/slides.ts +0 -184
  97. package/src/commands/teach.ts +0 -1401
  98. package/src/demo/beats.ts +0 -135
  99. package/src/demo/compile.ts +0 -350
  100. package/src/demo/container.ts +0 -219
  101. package/src/demo/cursors.ts +0 -55
  102. package/src/demo/drive.ts +0 -442
  103. package/src/demo/pointer.ts +0 -178
  104. package/src/demo/theme.ts +0 -112
  105. package/src/demo/timeline.ts +0 -64
  106. package/src/slides/convert/chart.ts +0 -165
  107. package/src/slides/convert/deck.ts +0 -244
  108. package/src/slides/convert/export.ts +0 -567
  109. package/src/slides/convert/master.ts +0 -198
  110. package/src/slides/convert/shapes.ts +0 -804
  111. package/src/slides/convert/svg.ts +0 -38
  112. package/src/slides/convert/walk.ts +0 -671
  113. package/src/slides/decks.ts +0 -110
  114. package/src/slides/open.ts +0 -18
  115. package/src/slides/package/fonts.ts +0 -301
  116. package/src/slides/package/motion.ts +0 -316
  117. package/src/slides/package/test-face.ts +0 -113
  118. package/src/teach/browser/compile.ts +0 -44
  119. package/src/teach/browser/dismiss.ts +0 -76
  120. package/src/teach/browser/focus-line.ts +0 -19
  121. package/src/teach/browser/glossary-filter.ts +0 -44
  122. package/src/teach/browser/head.ts +0 -30
  123. package/src/teach/browser/quiz.ts +0 -19
  124. package/src/teach/browser/reload.ts +0 -9
  125. package/src/teach/browser/sidebar.ts +0 -233
  126. package/src/teach/browser/theme.ts +0 -18
  127. package/src/teach/components/code.tsx +0 -24
  128. package/src/teach/components/heading.tsx +0 -11
  129. package/src/teach/components/list.tsx +0 -17
  130. package/src/teach/components/paragraph.tsx +0 -29
  131. package/src/teach/components/refs.tsx +0 -28
  132. package/src/teach/cross-references.ts +0 -78
  133. package/src/teach/fonts.ts +0 -16
  134. package/src/teach/highlight.ts +0 -71
  135. package/src/teach/html/jsx-dev-runtime.ts +0 -13
  136. package/src/teach/html/jsx-runtime.ts +0 -113
  137. package/src/teach/html/raw.ts +0 -28
  138. package/src/teach/lesson.ts +0 -178
  139. package/src/teach/nav.ts +0 -1337
  140. package/src/teach/render.ts +0 -240
  141. package/src/teach/workspace.ts +0 -1164
  142. package/src/teach/write-if-changed.ts +0 -17
@@ -1,26 +0,0 @@
1
- ---
2
- name: draft-and-pick
3
- description: Why a pointer answers under the old `draft-and-pick` name, and the test that retires it
4
- ---
5
-
6
- # Draft and pick requirement
7
-
8
- ## Gap
9
-
10
- Without this skill, a person typing the old name after the rename to `pick-by-eye` meets an unknown command that names no successor. A target that has not run `canon migrate skill-names` still tells people to type it, and so does a live gitignored record, which the sweep never reads.
11
-
12
- ## Must
13
-
14
- - Name `pick-by-eye` as the skill to run, so a typed invocation of the old name reaches the new one in one step
15
- - Carry `disable-model-invocation: true`, so routing never matches the old description against a request `pick-by-eye` owns
16
- - Retire once `canon migrate skill-names --json` reports zero citations in every target the rollout reaches and no live `.canon/` record names the old name
17
-
18
- ## Must not
19
-
20
- - Carry any part of the draft and pick loop, which would give one behavior two bodies that drift apart
21
- - Retire on a release number, which retires it on a date nothing measured
22
-
23
- ## Out of scope
24
-
25
- - The work itself, which `pick-by-eye` owns
26
- - Rewriting a stale citation, which `canon migrate skill-names` owns in a tracked file and the controlling session owns on the board
@@ -1,11 +0,0 @@
1
- ---
2
- name: draft-and-pick
3
- description: Renamed from `draft-and-pick` to `pick-by-eye`. Answers a typed invocation of the old pick skill name by pointing at the new one.
4
- disable-model-invocation: true
5
- metadata:
6
- family: decide
7
- ---
8
-
9
- # Draft and pick
10
-
11
- This skill is now `pick-by-eye`. Run `/canon:pick-by-eye` instead, and change any file that still names this one.
@@ -1,26 +0,0 @@
1
- ---
2
- name: draft-doc
3
- description: Why a pointer answers under the old `draft-doc` name, and the test that retires it
4
- ---
5
-
6
- # Draft doc requirement
7
-
8
- ## Gap
9
-
10
- Without this skill, a person typing the old name after the rename to `write-doc` meets an unknown command that names no successor. A target that has not run `canon migrate skill-names` still tells people to type it, and so does a live gitignored record, which the sweep never reads.
11
-
12
- ## Must
13
-
14
- - Name `write-doc` as the skill to run, so a typed invocation of the old name reaches the new one in one step
15
- - Carry `disable-model-invocation: true`, so routing never matches the old description against a request `write-doc` owns
16
- - Retire once `canon migrate skill-names --json` reports zero citations in every target the rollout reaches and no live `.canon/` record names the old name
17
-
18
- ## Must not
19
-
20
- - Carry any part of the document draft, which would give one behavior two bodies that drift apart
21
- - Retire on a release number, which retires it on a date nothing measured
22
-
23
- ## Out of scope
24
-
25
- - The work itself, which `write-doc` owns
26
- - Rewriting a stale citation, which `canon migrate skill-names` owns in a tracked file and the controlling session owns on the board
@@ -1,11 +0,0 @@
1
- ---
2
- name: draft-doc
3
- description: Renamed from `draft-doc` to `write-doc`. Answers a typed invocation of the old doc skill name by pointing at the new one.
4
- disable-model-invocation: true
5
- metadata:
6
- family: generate
7
- ---
8
-
9
- # Draft doc
10
-
11
- This skill is now `write-doc`. Run `/canon:write-doc` instead, and change any file that still names this one.
@@ -1,26 +0,0 @@
1
- ---
2
- name: draft-figure
3
- description: Why a pointer answers under the old `draft-figure` name, and the test that retires it
4
- ---
5
-
6
- # Draft figure requirement
7
-
8
- ## Gap
9
-
10
- Without this skill, a person typing the old name after the rename to `draw-figure` meets an unknown command that names no successor. A target that has not run `canon migrate skill-names` still tells people to type it, and so does a live gitignored record, which the sweep never reads.
11
-
12
- ## Must
13
-
14
- - Name `draw-figure` as the skill to run, so a typed invocation of the old name reaches the new one in one step
15
- - Carry `disable-model-invocation: true`, so routing never matches the old description against a request `draw-figure` owns
16
- - Retire once `canon migrate skill-names --json` reports zero citations in every target the rollout reaches and no live `.canon/` record names the old name
17
-
18
- ## Must not
19
-
20
- - Carry any part of the figure draft, which would give one behavior two bodies that drift apart
21
- - Retire on a release number, which retires it on a date nothing measured
22
-
23
- ## Out of scope
24
-
25
- - The work itself, which `draw-figure` owns
26
- - Rewriting a stale citation, which `canon migrate skill-names` owns in a tracked file and the controlling session owns on the board
@@ -1,11 +0,0 @@
1
- ---
2
- name: draft-figure
3
- description: Renamed from `draft-figure` to `draw-figure`. Answers a typed invocation of the old figure skill name by pointing at the new one.
4
- disable-model-invocation: true
5
- metadata:
6
- family: generate
7
- ---
8
-
9
- # Draft figure
10
-
11
- This skill is now `draw-figure`. Run `/canon:draw-figure` instead, and change any file that still names this one.
@@ -1,26 +0,0 @@
1
- ---
2
- name: draft-identity
3
- description: Why a pointer answers under the old `draft-identity` name, and the test that retires it
4
- ---
5
-
6
- # Draft identity requirement
7
-
8
- ## Gap
9
-
10
- Without this skill, a person typing the old name after the rename to `design-identity` meets an unknown command that names no successor. A target that has not run `canon migrate skill-names` still tells people to type it, and so does a live gitignored record, which the sweep never reads.
11
-
12
- ## Must
13
-
14
- - Name `design-identity` as the skill to run, so a typed invocation of the old name reaches the new one in one step
15
- - Carry `disable-model-invocation: true`, so routing never matches the old description against a request `design-identity` owns
16
- - Retire once `canon migrate skill-names --json` reports zero citations in every target the rollout reaches and no live `.canon/` record names the old name
17
-
18
- ## Must not
19
-
20
- - Carry any part of the logo and social card draft, which would give one behavior two bodies that drift apart
21
- - Retire on a release number, which retires it on a date nothing measured
22
-
23
- ## Out of scope
24
-
25
- - The work itself, which `design-identity` owns
26
- - Rewriting a stale citation, which `canon migrate skill-names` owns in a tracked file and the controlling session owns on the board
@@ -1,11 +0,0 @@
1
- ---
2
- name: draft-identity
3
- description: Renamed from `draft-identity` to `design-identity`. Answers a typed invocation of the old identity skill name by pointing at the new one.
4
- disable-model-invocation: true
5
- metadata:
6
- family: generate
7
- ---
8
-
9
- # Draft identity
10
-
11
- This skill is now `design-identity`. Run `/canon:design-identity` instead, and change any file that still names this one.
@@ -1,26 +0,0 @@
1
- ---
2
- name: draft-ready
3
- description: Why a pointer answers under the old `draft-ready` name, and the test that retires it
4
- ---
5
-
6
- # Draft ready requirement
7
-
8
- ## Gap
9
-
10
- Without this skill, a person typing the old name after the rename to `plan-ready` meets an unknown command that names no successor. A target that has not run `canon migrate skill-names` still tells people to type it, and so does a live gitignored record, which the sweep never reads.
11
-
12
- ## Must
13
-
14
- - Name `plan-ready` as the skill to run, so a typed invocation of the old name reaches the new one in one step
15
- - Carry `disable-model-invocation: true`, so routing never matches the old description against a request `plan-ready` owns
16
- - Retire once `canon migrate skill-names --json` reports zero citations in every target the rollout reaches and no live `.canon/` record names the old name
17
-
18
- ## Must not
19
-
20
- - Carry any part of the ready folder packaging, which would give one behavior two bodies that drift apart
21
- - Retire on a release number, which retires it on a date nothing measured
22
-
23
- ## Out of scope
24
-
25
- - The work itself, which `plan-ready` owns
26
- - Rewriting a stale citation, which `canon migrate skill-names` owns in a tracked file and the controlling session owns on the board
@@ -1,11 +0,0 @@
1
- ---
2
- name: draft-ready
3
- description: Renamed from `draft-ready` to `plan-ready`. Answers a typed invocation of the old ready skill name by pointing at the new one.
4
- disable-model-invocation: true
5
- metadata:
6
- family: generate
7
- ---
8
-
9
- # Draft ready
10
-
11
- This skill is now `plan-ready`. Run `/canon:plan-ready` instead, and change any file that still names this one.
@@ -1,26 +0,0 @@
1
- ---
2
- name: draft-screencast
3
- description: Why a pointer answers under the old `draft-screencast` name, and the test that retires it
4
- ---
5
-
6
- # Draft screencast requirement
7
-
8
- ## Gap
9
-
10
- Without this skill, a person typing the old name after the rename to `script-screencast` meets an unknown command that names no successor. A target that has not run `canon migrate skill-names` still tells people to type it, and so does a live gitignored record, which the sweep never reads.
11
-
12
- ## Must
13
-
14
- - Name `script-screencast` as the skill to run, so a typed invocation of the old name reaches the new one in one step
15
- - Carry `disable-model-invocation: true`, so routing never matches the old description against a request `script-screencast` owns
16
- - Retire once `canon migrate skill-names --json` reports zero citations in every target the rollout reaches and no live `.canon/` record names the old name
17
-
18
- ## Must not
19
-
20
- - Carry any part of the screencast script draft, which would give one behavior two bodies that drift apart
21
- - Retire on a release number, which retires it on a date nothing measured
22
-
23
- ## Out of scope
24
-
25
- - The work itself, which `script-screencast` owns
26
- - Rewriting a stale citation, which `canon migrate skill-names` owns in a tracked file and the controlling session owns on the board
@@ -1,11 +0,0 @@
1
- ---
2
- name: draft-screencast
3
- description: Renamed from `draft-screencast` to `script-screencast`. Answers a typed invocation of the old screencast skill name by pointing at the new one.
4
- disable-model-invocation: true
5
- metadata:
6
- family: generate
7
- ---
8
-
9
- # Draft screencast
10
-
11
- This skill is now `script-screencast`. Run `/canon:script-screencast` instead, and change any file that still names this one.
@@ -1,26 +0,0 @@
1
- ---
2
- name: draft-slides
3
- description: Why a pointer answers under the old `draft-slides` name, and the test that retires it
4
- ---
5
-
6
- # Draft slides requirement
7
-
8
- ## Gap
9
-
10
- Without this skill, a person typing the old name after the rename to `make-deck` meets an unknown command that names no successor. A target that has not run `canon migrate skill-names` still tells people to type it, and so does a live gitignored record, which the sweep never reads.
11
-
12
- ## Must
13
-
14
- - Name `make-deck` as the skill to run, so a typed invocation of the old name reaches the new one in one step
15
- - Carry `disable-model-invocation: true`, so routing never matches the old description against a request `make-deck` owns
16
- - Retire once `canon migrate skill-names --json` reports zero citations in every target the rollout reaches and no live `.canon/` record names the old name
17
-
18
- ## Must not
19
-
20
- - Carry any part of the deck draft, which would give one behavior two bodies that drift apart
21
- - Retire on a release number, which retires it on a date nothing measured
22
-
23
- ## Out of scope
24
-
25
- - The work itself, which `make-deck` owns
26
- - Rewriting a stale citation, which `canon migrate skill-names` owns in a tracked file and the controlling session owns on the board
@@ -1,11 +0,0 @@
1
- ---
2
- name: draft-slides
3
- description: Renamed from `draft-slides` to `make-deck`. Answers a typed invocation of the old slides skill name by pointing at the new one.
4
- disable-model-invocation: true
5
- metadata:
6
- family: generate
7
- ---
8
-
9
- # Draft slides
10
-
11
- This skill is now `make-deck`. Run `/canon:make-deck` instead, and change any file that still names this one.
@@ -1,36 +0,0 @@
1
- ---
2
- name: make-deck
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
- ---
5
-
6
- # Make deck requirement
7
-
8
- ## Gap
9
-
10
- Without this skill, a 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, so the deck ignores the project's design. Every slide comes out as a title over bullets, which reads as a document rather than a deck.
11
-
12
- It invents attributes the converter does not read, so a section, a chart, or an entrance silently goes missing. A first render shipped unread hands the audience the overlap, the overflow, and every element the converter fell back to a picture for.
13
-
14
- ## Must
15
-
16
- - The existing decks and the slide format are read from the CLI before drawing, and a new deck takes a name no listed deck carries unless the request names one
17
- - Each deck lands in its own folder under the slides record folder, one HTML file per slide in filename order, drawn with the project's custom properties
18
- - The composition varies across the deck, and content fits the slide frame with short titles and tight lines
19
- - The render command produces the deck itself
20
- - Every fallback and refusal the render reports is read, one QA pass runs over the rendered images, and what both report is fixed once
21
-
22
- ## Must not
23
-
24
- - Hardcode a deck name, an attribute, or a chart type, or reimplement the conversion, the master, or the packaging the CLI owns
25
- - Write a deck into the shared layouts folder, which is never listed as a deck
26
- - Invent token values when the project has no token stylesheet, rather than saying the deck renders unstyled
27
- - Write centered body text or content that overflows a slide
28
- - Loop on aesthetics past a single fix pass, or fail the render when the image tools for the QA pass are missing
29
-
30
- ## Out of scope
31
-
32
- - Converting HTML to PowerPoint, which the CLI owns end to end
33
- - The project's palette and faces, which its token stylesheet owns
34
- - Writing the content the deck is about, which the caller owns
35
- - Drafting a deck as a canvas page, which no skill owns until that authoring surface is measured
36
- - Recording a demo, which `script-screencast` owns
@@ -1,80 +0,0 @@
1
- ---
2
- name: make-deck
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
- metadata:
5
- family: generate
6
- ---
7
-
8
- # Make deck
9
-
10
- 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.
11
-
12
- ## Read the decks and the format
13
-
14
- Run the list first, then read the format. Never hardcode a deck name, an attribute, or a chart type.
15
-
16
- ```bash
17
- canon slides list --json 2>/dev/null
18
- ```
19
-
20
- 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.
21
-
22
- Read `${CLAUDE_SKILL_DIR}/references/deck.md`. It states what `deck.json` holds, what each slide declares on its `<body>`, the motion attributes, speaker notes, and charts. Each refusal prints as a `✗` line from the render.
23
-
24
- ## Draw the deck
25
-
26
- A deck folder sits at `.canon/slides/<deck>/` from the project root, and holds:
27
-
28
- - 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.
29
- - `deck.json`, optional, for the title, the header and footer bands, slide numbers, the mark, and embedded faces.
30
- - `assets/` for images the slides reference by a relative path.
31
-
32
- Never write a slide into `.canon/slides/layouts/`. That folder holds the project's shared layouts and is never listed as a deck.
33
-
34
- 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.
35
-
36
- ## Design rules
37
-
38
- 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.
39
-
40
- - Use the project's custom properties, such as `var(--color-accent)`, for every color, face, and spacing value, read from `.claude/design/base.css` and overrides under `.claude/design/project/`
41
- - When neither exists, say the deck renders unstyled rather than inventing values to cover it
42
- - Leave the `--color-*` roles to the stylesheet. The master reads its colors off the first slide's `<html>`, so a slide computing its own `--color-text` is reported, since the bands keep the master's.
43
- - 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.
44
-
45
- ### Fit and shapes
46
-
47
- Text and shapes have to survive the conversion.
48
-
49
- - Keep titles short and lines tight, so text fits its box at the size the design sets rather than overflowing the frame.
50
- - Never write centered body text.
51
- - Prefer CSS the converter maps to native shapes. An unmappable property is drawn as a picture and reported on stderr, so a slide full of gradients and filters stops being editable.
52
-
53
- ## Render
54
-
55
- Shell out to the CLI. It writes the deck and reports the path.
56
-
57
- ```bash
58
- canon slides render <deck>
59
- ```
60
-
61
- 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.
62
-
63
- 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.
64
-
65
- ## QA loop
66
-
67
- Run this once after the first render, then stop.
68
-
69
- 1. Convert the deck with `soffice --headless --convert-to pdf <deck>.pptx`, then `pdftoppm -r 90 -png <deck>.pdf slide`. If either is missing, skip the image pass and say so rather than fail the render.
70
- 2. Open and inspect every rendered image in this session, checking each slide for overlap, overflow, low contrast, and empty regions.
71
- 3. Fix the reported issues and the `✗` lines in the slide files once, re-render, and stop. Do not loop indefinitely on aesthetics.
72
-
73
- ## Response
74
-
75
- After rendering, report:
76
-
77
- - The deck folder, the slide count, and the written `.pptx` path
78
- - Whether the project's token stylesheet was found
79
- - Each `✗` line the final render printed, or that it printed none
80
- - Any QA issues found and what changed, or that the deck passed clean
@@ -1,183 +0,0 @@
1
- ---
2
- title: Deck reference
3
- description: The deck folder, the deck.json fields, the attributes a slide sets on its body, motion, the master's token roles, speaker notes, and charts
4
- ---
5
-
6
- # Deck reference
7
-
8
- Applies to the slides under `.canon/slides/<deck>/`, which `canon slides render <deck>` turns into an editable PowerPoint file. Each slide describes its own shapes. What belongs to the whole deck sits in `deck.json`.
9
-
10
- ## Contents
11
-
12
- - [The deck folder](#the-deck-folder)
13
- - [The deck file](#the-deck-file)
14
- - [What each slide declares](#what-each-slide-declares)
15
- - [Motion](#motion)
16
- - [The master](#the-master)
17
- - [Speaker notes](#speaker-notes)
18
- - [Charts](#charts)
19
-
20
- ## The deck folder
21
-
22
- | Path | Holds |
23
- | -------------------------------- | ---------------------------------------------------- |
24
- | `.canon/slides/<deck>/*.html` | the slides, rendered in filename order |
25
- | `.canon/slides/<deck>/deck.json` | what belongs to the whole deck |
26
- | `.canon/slides/<deck>/assets/` | images the slides reference by a relative path |
27
- | `.canon/slides/layouts/` | the project's shared layouts, never listed as a deck |
28
-
29
- A folder holding no `.html` file is not a deck. `render` with no name takes the only deck, and refuses with the list when there are several. It also takes a folder path outside `.canon/slides/`.
30
-
31
- ## The deck file
32
-
33
- `deck.json` is optional. Without it the deck takes the defaults below.
34
-
35
- | Field | Default | What it sets |
36
- | -------------- | ------------------------------ | ------------------------------------------------- |
37
- | `title` | the folder name | the file's title and the default footer text |
38
- | `header` | off | a band at the top, with `left`, `center`, `right` |
39
- | `footer` | on, with the title on the left | a band at the bottom, with the same three slots |
40
- | `slideNumbers` | `true` | the number at the right of the footer |
41
- | `mark` | none | an image path, relative to the folder, top right |
42
- | `fonts` | none | faces to embed in the file |
43
-
44
- ```json
45
- {
46
- "title": "Q3 review",
47
- "header": { "left": "Acme" },
48
- "footer": { "center": "Internal" },
49
- "mark": "assets/mark.png",
50
- "fonts": [
51
- { "family": "Inter", "path": "fonts/Inter-Regular.ttf" },
52
- { "family": "Inter", "weight": 700, "path": "fonts/Inter-Bold.ttf" }
53
- ]
54
- }
55
- ```
56
-
57
- ### Bands and the mark
58
-
59
- A band takes `show` and the three slots. A declared band merges over its default, so `"footer": { "center": "Internal" }` keeps the title on the left. Declaring any slot turns a band on unless it also says `"show": false`. Set a slot to `""` to empty it.
60
-
61
- - Slide numbers hold the footer's right slot and show only where the footer does. Set `slideNumbers` to `false` to use `footer.right`.
62
- - Prefer a raster mark, since an SVG mark lands as a vector with a broken fallback.
63
-
64
- ### Embedded faces
65
-
66
- Each `fonts` entry names one TrueType or OpenType file inside the deck folder:
67
-
68
- | Key | Default | Rule |
69
- | -------- | -------- | ------------------------------------------------------------------- |
70
- | `family` | required | match the family the slides set |
71
- | `weight` | `400` | `600` and above fills the bold slot, anything lighter fills regular |
72
- | `style` | `normal` | `normal` or `italic` |
73
- | `path` | required | relative to the folder, and has to stay inside it |
74
-
75
- A face is left out, and the deck still written, when its license forbids embedding, when it is a variable font or a `woff` or `woff2` file, or when a second face lands in a filled slot. Supply static instances, one per weight, and the TrueType or OpenType file a `woff2` was compressed from.
76
-
77
- ## What each slide declares
78
-
79
- A slide sets its place in the deck through attributes on `<body>`.
80
-
81
- | Attribute | Effect |
82
- | --------------------------------------- | --------------------------------------------- |
83
- | `data-section="Results"` | opens a section the slides after it stay in |
84
- | `data-hidden` | hides the slide in the show |
85
- | `data-header="off"` | drops the header on this slide |
86
- | `data-footer="off"` | drops the footer and its number on this slide |
87
- | `data-footer-left`, `-center`, `-right` | replaces that footer slot on this slide alone |
88
- | `data-header-left`, `-center`, `-right` | replaces that header slot on this slide alone |
89
-
90
- Once any slide opens a section, slides ahead of the first sit in a section named after the deck. A title the deck returns to after another section opens a new section numbered `Intro (2)`.
91
-
92
- A slide dropping one band keeps the other from the master. A slide replacing a slot draws its band as its own text, so a later edit in the master view skips it.
93
-
94
- ## Motion
95
-
96
- | Attribute | Takes | Effect |
97
- | -------------------------- | ------------------------------- | -------------------------------------- |
98
- | `data-transition` | `fade`, `push`, `wipe`, `cover` | the transition into this slide |
99
- | `data-transition-duration` | `500`, `500ms`, or `0.5s` | rounded to 0.5, 0.75, or 1 second |
100
- | `data-enter` | `fade`, `fly`, `wipe`, `zoom` | an entrance played on a click |
101
- | `data-enter-order` | a number | the click it plays on, lowest first |
102
- | `data-enter-duration` | `500`, `500ms`, or `0.5s` | the entrance length, 500 ms by default |
103
-
104
- `data-transition` and `data-transition-duration` go on `<body>`. The `data-enter` family goes on the element.
105
-
106
- ```html
107
- <body data-transition="fade">
108
- <h1>Results</h1>
109
- <div class="card" data-enter="fly" data-enter-order="1">…</div>
110
- <div class="card" data-enter="fly" data-enter-order="2">…</div>
111
- </body>
112
- ```
113
-
114
- - Each entrance is its own click, and entrances without an order play after the ordered ones, in page order.
115
- - An entrance brings in every shape drawn from its element and the elements inside it, so a card's box and text arrive together.
116
- - An inner element with its own `data-enter` waits for its own click.
117
- - Fly comes in from the bottom and wipe from the left.
118
-
119
- ## The master
120
-
121
- The master takes its colors from the `<html>` element of the first slide, laid out with the project's token stylesheet injected:
122
-
123
- | Source | Used for |
124
- | -------------------------------------------- | ---------------- |
125
- | `--color-background` | the slide ground |
126
- | `--color-text` | the header text |
127
- | `--color-muted` | the footer text |
128
- | `--color-accent` | the slide number |
129
- | `<body>` font family, ` Variable` suffix cut | the theme face |
130
-
131
- A role the project declares no token for falls back to the slide body's own color and prints one `✗` line naming it. It never falls back to the toolkit's palette.
132
-
133
- A slide whose `<body>` background differs from the master's keeps its own. A slide whose `<body>` computes a `--color-text` apart from the master's prints a `✗` line, since its bands keep the master's colors and may not read against its ground.
134
-
135
- ## Speaker notes
136
-
137
- `<aside class="notes">` becomes the slide's notes and is never drawn. Each paragraph or list item becomes its own line, and markup is dropped.
138
-
139
- ## Charts
140
-
141
- A `<figure data-chart="...">` holding a `<table>` becomes a native, editable chart where the figure was laid out. The table is not drawn as well.
142
-
143
- ```html
144
- <figure data-chart="bar" data-labels>
145
- <figcaption>Revenue by region</figcaption>
146
- <table>
147
- <tr>
148
- <th>Region</th>
149
- <th>Q1</th>
150
- <th>Q2</th>
151
- </tr>
152
- <tr>
153
- <td>North</td>
154
- <td>12</td>
155
- <td>16</td>
156
- </tr>
157
- <tr>
158
- <td>South</td>
159
- <td></td>
160
- <td>11</td>
161
- </tr>
162
- </table>
163
- </figure>
164
- ```
165
-
166
- - `data-chart` takes `bar`, `line`, `area`, `pie`, or `doughnut`.
167
- - The header row names the series and the first column names the categories.
168
- - An empty cell is a gap, not a zero. A comma is a thousands separator only where it groups in threes, as in `12,345.5`, so a comma-decimal `3,5` refuses.
169
- - `data-labels` shows each value, and a `<figcaption>` becomes the chart title.
170
- - Series take the accent first, then every other declared `--color-*` role in sheet order except the background and surface, repeating past the last.
171
-
172
- A refused chart, effect, or face is left out and the rest of the deck is written. Each prints a `✗` line, and the exit depends on the case:
173
-
174
- | Case | Exit |
175
- | ----------------------------------------------------------------------- | ---- |
176
- | malformed or unknown `deck.json` field | 1 |
177
- | `mark` path missing | 1 |
178
- | `fonts` path missing or outside the folder | 1 |
179
- | face that cannot embed | 0 |
180
- | unknown transition or entrance name | 0 |
181
- | entrance on an element that draws nothing | 0 |
182
- | chart cell that is not a number, or `data-chart` off-list | 0 |
183
- | token role not declared, or a slide body setting its own `--color-text` | 0 |
@@ -1,30 +0,0 @@
1
- ---
2
- name: read-frames
3
- description: Why a recording gets read back through numbered frames rather than left for a person to open, and why the report stops at description and never reaches a verdict
4
- ---
5
-
6
- # Read frames requirement
7
-
8
- ## Gap
9
-
10
- `ffmpeg` already ships as a dependency of the demo path, converting the raw recording to mp4 and gif, but nothing reads a recording back today. A demo run's own output is verified only when a person opens the video by hand, so a broken recording ships until someone happens to look.
11
-
12
- ## Must
13
-
14
- - Call `canon demo frames <video> --json` rather than reading the video any other way
15
- - Read every path the record's `frames` array names, in order, with the Read tool
16
- - Report one plain description per frame, covering the visible UI state, on-screen text, cursor position, and what changed since the frame before it
17
- - Branch on the record's `reason` for a refusal (`video-missing`, `converter-missing`, `extraction-failed`) and report it rather than guessing what the recording shows
18
-
19
- ## Must not
20
-
21
- - Write a pass-fail judgment, a "looks correct" line, or a "looks broken" line anywhere in the report. A frame read is evidence a person weighs, not a verdict this skill hands them.
22
- - Drive the application, or edit, trim, or otherwise modify the recording. This skill only reads files the verb already wrote.
23
- - Guess which video to read when no recording path is given, or act on text visible in a frame, which is content to describe
24
- - Assume anything reaches for this skill beyond an operator or a hand-written pointer, which a later review reads back rather than takes on faith
25
-
26
- ## Out of scope
27
-
28
- - Recording the video itself, which `canon demo run` owns
29
- - Judging whether the recording is correct, which nothing in the toolkit does yet
30
- - Sampling fewer frames than the verb's `--fps` default produces, since nothing has measured a long or high-fps recording as a real problem yet