slidemind 0.3.20 → 0.4.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 (185) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/.codex-plugin/plugin.json +1 -1
  3. package/AGENTS.md +591 -15
  4. package/README.md +202 -7
  5. package/bin/slidemind.mjs +50 -2
  6. package/package.json +2 -2
  7. package/skills/create-slides/SKILL.md +484 -886
  8. package/skills/search/SKILL.md +46 -23
  9. package/src/bridge/build-and-push.mjs +548 -73
  10. package/src/bridge/bundle.mjs +100 -31
  11. package/src/bridge/capture.mjs +14 -17
  12. package/src/bridge/client/brands.mjs +157 -18
  13. package/src/bridge/client/engine-routing.mjs +48 -13
  14. package/src/bridge/client/engine-search.mjs +24 -1
  15. package/src/bridge/client/render.mjs +27 -1
  16. package/src/bridge/client/transport.mjs +499 -23
  17. package/src/bridge/client.mjs +10 -0
  18. package/src/bridge/config.mjs +67 -6
  19. package/src/bridge/engine-download.mjs +0 -10
  20. package/src/bridge/graph-auth.mjs +55 -3
  21. package/src/bridge/image-intent-envelope.mjs +239 -0
  22. package/src/bridge/package-preview.mjs +67 -0
  23. package/src/bridge/sharepoint.mjs +914 -0
  24. package/src/builders/asset-fetch.mjs +203 -0
  25. package/src/builders/block-dividers.mjs +83 -0
  26. package/src/builders/build.mjs +171 -87
  27. package/src/builders/card-height.mjs +294 -0
  28. package/src/builders/chart-hole.mjs +183 -0
  29. package/src/builders/chart-jsx.mjs +410 -0
  30. package/src/builders/chart-labels.mjs +326 -0
  31. package/src/builders/concept-geometry.mjs +370 -0
  32. package/src/builders/concept-intent.mjs +200 -0
  33. package/src/builders/concept-layout.mjs +79 -0
  34. package/src/builders/concept-lines.mjs +509 -0
  35. package/src/builders/concept-lists.mjs +270 -0
  36. package/src/builders/concept-marks.mjs +84 -0
  37. package/src/builders/concept-relationships.mjs +12 -0
  38. package/src/builders/concept-spec.mjs +645 -0
  39. package/src/builders/concept-text.mjs +140 -0
  40. package/src/builders/concept-waves.mjs +57 -0
  41. package/src/builders/copy-fit.mjs +139 -0
  42. package/src/builders/design-tokens.mjs +347 -0
  43. package/src/builders/draft-check.mjs +552 -340
  44. package/src/builders/draft-lines.mjs +369 -0
  45. package/src/builders/edit-route.mjs +29 -0
  46. package/src/builders/figure-sketch.mjs +375 -0
  47. package/src/builders/fold-sets.mjs +639 -0
  48. package/src/builders/gate-server.mjs +9 -4
  49. package/src/builders/gate-session.js +273 -12
  50. package/src/builders/gate-shell.js +1494 -0
  51. package/src/builders/image-intent-check.mjs +308 -0
  52. package/src/builders/image-use-reconcile.mjs +107 -0
  53. package/src/builders/kit-helpers.mjs +121 -0
  54. package/src/builders/layout-names.mjs +32 -0
  55. package/src/builders/legacy-reference-uses.mjs +179 -0
  56. package/src/builders/line-fit.mjs +224 -0
  57. package/src/builders/line-native.mjs +895 -0
  58. package/src/builders/line-relations.mjs +230 -0
  59. package/src/builders/lint-fix.mjs +117 -9
  60. package/src/builders/lint.mjs +25 -20
  61. package/src/builders/list-jsx.mjs +88 -0
  62. package/src/builders/placement.mjs +133 -0
  63. package/src/builders/plan-checks.mjs +135 -0
  64. package/src/builders/plan-comments.mjs +19 -0
  65. package/src/builders/plan-handlers.mjs +95 -0
  66. package/src/builders/plan-markdown-edit.mjs +3 -3
  67. package/src/builders/plan-overlay.js +1530 -1608
  68. package/src/builders/plan.mjs +689 -186
  69. package/src/builders/preset-definitions.json +1 -0
  70. package/src/builders/preset-eval.mjs +244 -0
  71. package/src/builders/preview.html +51 -120
  72. package/src/builders/red-thread-backbone.mjs +135 -36
  73. package/src/builders/repair.mjs +205 -0
  74. package/src/builders/repeat-groups.mjs +540 -0
  75. package/src/builders/resolve-skill.mjs +5 -4
  76. package/src/builders/review-overlay.js +296 -293
  77. package/src/builders/review.mjs +305 -84
  78. package/src/builders/rule-shift.mjs +96 -0
  79. package/src/builders/seat.mjs +354 -0
  80. package/src/builders/settle-driver.mjs +236 -0
  81. package/src/builders/settle.mjs +1448 -0
  82. package/src/builders/slide-prep.mjs +67 -0
  83. package/src/builders/spec-assets.mjs +236 -0
  84. package/src/builders/spec-match.mjs +56 -0
  85. package/src/builders/stack.mjs +413 -0
  86. package/src/builders/storyboard-markdown.mjs +70 -27
  87. package/src/builders/storyboard-schema.mjs +54 -114
  88. package/src/builders/text-blocks.mjs +212 -0
  89. package/src/builders/text-card-fit.mjs +552 -0
  90. package/src/builders/text-stack.mjs +276 -0
  91. package/src/builders/transcribe.mjs +1069 -0
  92. package/src/cli/assets.mjs +164 -0
  93. package/src/cli/common.mjs +173 -12
  94. package/src/cli/concept-spec-support.mjs +76 -0
  95. package/src/cli/concepts.mjs +1002 -103
  96. package/src/cli/deck.mjs +401 -65
  97. package/src/cli/diagnose.mjs +4 -2
  98. package/src/cli/engine-helpers.mjs +17 -10
  99. package/src/cli/engine-results.mjs +76 -3
  100. package/src/cli/help.mjs +232 -28
  101. package/src/cli/install.mjs +9 -0
  102. package/src/cli/maintenance.mjs +104 -0
  103. package/src/cli/read.mjs +2 -1
  104. package/src/cli/ready.mjs +6 -3
  105. package/src/cli/record.mjs +522 -0
  106. package/src/cli/remote.mjs +818 -0
  107. package/src/cli/revision.mjs +686 -0
  108. package/src/cli/search.mjs +30 -11
  109. package/src/cli/session.mjs +56 -13
  110. package/src/cli/setup.mjs +46 -2
  111. package/src/cli/status.mjs +142 -33
  112. package/src/cli/tasks.mjs +246 -0
  113. package/src/cli/transcribe.mjs +854 -0
  114. package/src/cli/workspace-ui.mjs +260 -0
  115. package/src/cli/workspace.mjs +212 -34
  116. package/src/install-channel.mjs +64 -7
  117. package/src/lib/adopt.mjs +346 -25
  118. package/src/lib/concept-spec-binding.mjs +96 -0
  119. package/src/lib/conversions.mjs +70 -6
  120. package/src/lib/convert-folded.mjs +107 -0
  121. package/src/lib/deck-paths.mjs +418 -0
  122. package/src/lib/durable-ids.mjs +47 -0
  123. package/src/lib/edit-operations.mjs +316 -0
  124. package/src/lib/edit-state.mjs +1244 -0
  125. package/src/lib/edit-transitions.mjs +120 -0
  126. package/src/lib/extensions.mjs +501 -0
  127. package/src/lib/image-assets.mjs +465 -0
  128. package/src/lib/image-derivatives.mjs +234 -0
  129. package/src/lib/image-intent-fingerprint.mjs +70 -0
  130. package/src/lib/image-intent-tags.mjs +176 -0
  131. package/src/lib/image-intent.mjs +802 -0
  132. package/src/lib/image-use-overrides.mjs +279 -0
  133. package/src/lib/inline-components.mjs +613 -0
  134. package/src/lib/lint-converted.mjs +68 -4
  135. package/src/lib/merge-json.mjs +163 -0
  136. package/src/lib/overwrite-guard.mjs +3 -3
  137. package/src/lib/presentation-context.mjs +531 -0
  138. package/src/lib/preservation-tags.mjs +157 -0
  139. package/src/lib/preservation-verdict.mjs +1342 -0
  140. package/src/lib/publish.mjs +1557 -0
  141. package/src/lib/rebase.mjs +945 -0
  142. package/src/lib/reconcile-ack.mjs +4 -6
  143. package/src/lib/reconcile.mjs +62 -24
  144. package/src/lib/record-client.mjs +175 -0
  145. package/src/lib/record-state.mjs +151 -0
  146. package/src/lib/remote.mjs +661 -0
  147. package/src/lib/revision.mjs +1210 -0
  148. package/src/lib/slide-guids.mjs +4 -6
  149. package/src/lib/slide-preservation.mjs +423 -0
  150. package/src/lib/slide-selection.mjs +9 -0
  151. package/src/lib/workspace-transaction.mjs +117 -0
  152. package/src/pptx/content-digest.mjs +334 -0
  153. package/src/pptx/deck-assemble.mjs +1278 -0
  154. package/src/pptx/fill/engine.mjs +2 -3
  155. package/src/pptx/fill/freeform.mjs +6 -3
  156. package/src/pptx/ooxml.mjs +20 -0
  157. package/src/pptx/package-evidence.mjs +383 -0
  158. package/src/pptx/tags.mjs +163 -11
  159. package/src/update-check.mjs +22 -4
  160. package/src/workspace/adapters.mjs +222 -0
  161. package/src/workspace/auth.mjs +256 -0
  162. package/src/workspace/autostart.mjs +204 -0
  163. package/src/workspace/daemon.mjs +360 -0
  164. package/src/workspace/discovery.mjs +180 -0
  165. package/src/workspace/edit.mjs +167 -0
  166. package/src/workspace/events.mjs +52 -0
  167. package/src/workspace/gate-client.mjs +290 -0
  168. package/src/workspace/handback.mjs +73 -0
  169. package/src/workspace/lifecycle.mjs +635 -0
  170. package/src/workspace/operations.mjs +200 -0
  171. package/src/workspace/pick-folder.mjs +152 -0
  172. package/src/workspace/registry.mjs +359 -0
  173. package/src/workspace/remote-links.mjs +397 -0
  174. package/src/workspace/remote-status.mjs +359 -0
  175. package/src/workspace/routes.mjs +1331 -0
  176. package/src/workspace/server.mjs +159 -0
  177. package/src/workspace/sync.mjs +1119 -0
  178. package/src/workspace/task-actions.mjs +215 -0
  179. package/src/workspace/tasks.mjs +507 -0
  180. package/src/workspace/ui/app.js +1886 -0
  181. package/src/workspace/ui/index.html +141 -0
  182. package/src/workspace/ui/plan-bridge.js +120 -0
  183. package/src/workspace/ui/sharepoint.svg +59 -0
  184. package/src/workspace/ui/styles.css +423 -0
  185. package/src/builders/visual-families.mjs +0 -46
@@ -1,899 +1,497 @@
1
1
  ---
2
2
  name: slidemind-create-slides
3
- description: Author branded slide decks and individual slides against the active corporate design. Owns the user-facing intake → plan → create → edit workflow that turns per-slide .jsx files into editable .pptx (rendered server-side in PowerPoint) plus a local HTML preview. Reads the brand rules, layout palette, and authoring workflow from a materialized design bundle served by the slidemind PowerPoint add-in — it ships neither its own brand nor its own exporter. Use whenever the user asks for a slide, a deck, a presentation, a slideshow, or to convert content into one; interview them for intent and output format first, then stay on-brand by reading the bundle at every step. Skip when the user only wants to open, present, rename, search, or query an existing deck without authoring or editing slide content.
3
+ description: Author branded slide decks and individual slides against the active corporate design. Owns the user-facing intake → plan → create → edit workflow that turns per-slide .jsx files into editable .pptx (rendered server-side in PowerPoint) plus a local HTML preview. Reads the brand rules, layout palette, and authoring workflow from a materialized design bundle served by the slidemind PowerPoint add-in — it ships neither its own brand nor its own exporter. Use whenever the user asks for a slide, a deck, a presentation, a slideshow, or to convert content into one; interview them for intent first (the output is always an editable .pptx — never ask about the format), then stay on-brand by reading the bundle at every step. Skip when the user only wants to open, present, rename, search, or query an existing deck without authoring or editing slide content.
4
4
  ---
5
5
 
6
6
  # slidemind-create-slides
7
7
 
8
- This skill is **thin workflow glue for the local harness**. Everything that determines how a deck is
9
- authored, styled, and rendered lives in the **slidemind PowerPoint add-in** and reaches you through
10
- a **materialized design bundle**:
11
-
12
- - The **brand** — tokens, `corporate-design.css`, the `design.md` brand rules, the closed layout
13
- palette, brand assets — is served per corporate design.
14
- - The **authoring workflow craft** — create, edit, composition, layouts, authoring contract,
15
- build/export — is the add-in's deployment-shipped `workflow/*.md`, served on the same bundle so
16
- the local harness reads **byte-identical** guidance to the in-app design agent.
17
- - The **`.pptx` render** happens server-side in the add-in. There is no local exporter.
18
-
19
- So this file owns only what is genuinely CLI-specific: the **first-step design-bundle gate**, a
20
- compact **intake/plan**, the **create flow**, and the **command mapping** that translates the
21
- workflow vocabulary — the harness-neutral verbs defined in the bundle's `workflow/flow.md` and
22
- spoken throughout `workflow/*.md` — into your `slidemind` CLI commands. Read the workflow + brand
23
- from the bundle; never restate or duplicate them here.
24
-
25
- Brand sample slides are private inputs to the add-in's concept generator. They are not authoring
26
- references and are deliberately not materialized into the local bundle. From the concept pass
27
- onward, re-read only `decks/<slug>/concepts/concept-slide-NN.png`; when a concept is unavailable,
28
- fall back to the approved storyboard plus `design.md` and the chosen layout, never to samples.
29
-
30
- **slidemind is a CLI you drive directly.** Run `slidemind <command>` in your shell — the same way
31
- you'd run `git` or `npm`. There is no separate tool layer to go through; every step below is a real
32
- command you type.
33
-
34
- ## Create a todo list (before your first command)
35
-
36
- The moment this skill activates on an authoring task, **create a todo list of the workflow stages**
37
- in your harness's task tracker — before you run anything — and keep it current: mark each stage done
38
- as you complete it. This is `workflow/flow.md` → *track the stages*; the list is what keeps the
39
- later stages (above all the review gate) from being skipped. The stages, as they run over the CLI:
40
-
41
- 1. `slidemind ready` — session preflight (*First step* below)
42
- 2. Clarify with the user — the content **and the output target** (*Intake → plan* below; needs no
43
- host, so it can run while `ready` executes)
44
- 3. Plan sign-off — `slidemind plan <deck>` (every from-scratch request — one slide included)
45
- 4. Concept mockups — `slidemind concepts <deck>`, then immediately inspect every mockup (anything
46
- authored from an approved plan, a single slide included; see *The create flow* below). The
47
- command **always ends on one line, `CONCEPTS: <n>/<planned> <status>`** (`--json` for the
48
- payload). Generation takes 1–2 minutes; if your harness cut the command off before that line
49
- appeared, re-run it — mockups already on disk come back as the path list instantly. Only a
50
- `CONCEPTS: 0/…` line means there are no mockups; a truncated output never does. Authoring a
51
- concept-seeded deck without having Read the concept PNGs on disk is the single largest fidelity
52
- failure this workflow has.
53
- **User-provided images** go into this command, classified from the user's words: a sketch or
54
- mockup to build ("build it like this") → `--concept <file>[@N,M]` (it becomes the mockup for
55
- those slides, no generation); a look to emulate ("in this style") → `--style <file>[@N,M]`
56
- (leads the generation; repeatable; `@` omitted = all slides). A photo or logo to place on a slide
57
- is not a concept input: copy it into `decks/<slug>/assets/` and list it in `asset-plan.md`.
58
- 5. Source assets — fill the `decks/<slug>/asset-plan.md` form `slidemind concepts` seeded (regions /
59
- organisms / connectors / icons per slide, each with its share of the content area), then search + download
60
- every icon row in it (*The create flow* steps 2–3). **This stage is not optional and not mergeable
61
- into authoring**: it is done when every plan item is checked off with a filename or marked
62
- `(no result)` after its search ran. A deck with concept mockups and an empty `assets/` beyond
63
- the brand chrome means this stage was skipped, not completed.
64
- 6. Author the slides
65
- 7. Draft check — `slidemind view-draft`, until it reports `DRAFT CHECK: no measured defects` AND each
66
- concept/render pair matches region by region
67
- 8. Review gate — `slidemind review`, the moment the deck builds clean (it refuses to open while the
68
- last draft check's measured defects stand)
69
- 9. Deliver — `slidemind push` or `slidemind build-pptx`, whichever target was locked in stage 2
70
-
71
- **Changing slides that already exist runs a shorter list.** When the deck is on disk and the
72
- request targets slides in it — "make slide 13 clearer", "rescope 12 and 13", "fix the spacing",
73
- comments on a delivered deck — the stages are `ready` → edit → `view-draft` → `review` → deliver.
74
- Stages 2–5 do not run: there is nothing to plan and no mockup to render, the live slide is the
75
- starting point (the in-app equivalent is the manager's route B, `approvedPlan: null`; the design
76
- worker's small-edit fast path keeps no todo board at all). Updating `plan.md` afterwards is optional
77
- bookkeeping and never re-opens the plan gate — once a deck has passed a review, the CLI treats
78
- `plan.md` as a record, not a contract. The full route definitions are in *Intake → plan* below; new
79
- slides added to an existing deck are from-scratch work and run the full list.
80
-
81
- **Deliver is the last todo — the task ends when the slides are delivered.** Don't add a "sanity
82
- pass" or "report back" step after it: the visual QA already happened at the draft check and the user
83
- already approved at the review gate, so on approval you push/build directly and stop. Each stage's
84
- full definition and the ordering invariants live in the bundle's `workflow/flow.md` — read it right
85
- after `ready` succeeds.
86
-
87
- **Concept mockups (stage 4) are a mandatory authoring stage, not an optional aid.** After plan
88
- sign-off, for anything authored from an approved plan — one slide as much as a deck — you **always**
89
- run `slidemind concepts <deck>` and
90
- **immediately Read every generated `concept-slide-NN.png` at full detail**. Use this first,
91
- deck-wide viewing pass to inventory the imagery, pictograms, factual/content checks, and other
92
- searches each slide needs; do those searches before authoring. This discovery read does **not**
93
- replace the fresh per-batch concept read immediately before JSX creation in *The create flow*.
94
- The durable visual anchors are the repo-relative files under
95
- `decks/<slug>/concepts/concept-slide-NN.png`, never an earlier chat image or temporary attachment;
96
- after any continuation, re-list that directory and reopen the files from those paths.
97
- Rebuild each mockup toward its target — this is the local-harness equivalent of the in-app manager's
98
- *unconditional* concept pass on every from-scratch delegation (`generateConceptImages` fires for
99
- every delegation carrying an approved plan). It degrades benignly: if it returns no mockups (exit 0 —
100
- the add-in can't generate them) you author from the storyboards alone, but the *attempt* is not
101
- optional. Skip it only for targeted work on slides that **already exist** — an edit or a rework,
102
- which designs from the live slide and never had a plan to render mockups from.
103
-
104
- Two gate invariants you must never break — one per gate, equally binding:
105
-
106
- - **Never jump from clarify to authoring** — the plan sign-off gate (`slidemind plan <deck>`,
107
- stage 3) always sits between. Writing `decks/<slug>/slides/*.jsx` before that gate has
108
- returned `DECISION: approved` is the single most common way this workflow goes wrong — it means
109
- the user never actually signed off on the story. **There is no small-request exception**: one new
110
- slide runs the same gate with a one-beat plan. The only work that skips it is a change to slides
111
- that already exist.
112
- - **Never jump from authoring to deliver** — the draft check and an approved review gate always sit
113
- between.
114
-
115
- ## After a context summarization (compaction recovery)
116
-
117
- Long deck runs exceed the context window mid-task; the harness then replaces the transcript with a
118
- summary. **Everything you only held in chat — viewed concept images, search results, the asset
119
- inventory, the workflow rules you read from the bundle, this skill's own steps — is gone; the files
120
- on disk are not.** When you notice you are running from a summary (or after any interruption or
121
- continuation), do NOT improvise from the summary and do NOT restart finished work. Run
122
- `slidemind ready <deck>` first: it re-materializes and re-binds (idempotent) and ends with a
123
- **`stage:` line read from disk** (plan / concepts / asset plan / slides / draft check / review) and
124
- a **`next:` line naming the command or file that is due** (`stage` in `--json`). Resume there, after
125
- re-reading the set that stage works from:
126
-
127
- - **plan gate** → *Two UX rules* and the `slidemind plan` row below.
128
- - **concepts / sourcing** → `<bundle>/workflow/create.md` steps 1–2, `asset-plan.md`, every
129
- `concepts/concept-slide-NN.png` at full detail.
130
- - **authoring** → `<bundle>/workflow/create.md` + `authoring.md`, `design.md`,
131
- `corporate-design.css`, the `layouts/<Layout>.jsx` the plan names, `asset-plan.md`, `plan.md`;
132
- then, per batch of ≤3, the matching concept PNGs immediately before each write.
133
- - **draft check** → *The create flow* step 4; **review** → step 5 + *Two UX rules*; **deliver** →
134
- the deliver row. An **edit** to existing slides → `<bundle>/workflow/edit.md` + the cited files.
135
-
136
- Two rules bind: the stage todo list still binds after a summary — "mostly done" is never a reason
137
- to skip the remaining stages — and never author, judge, or deliver from a remembered image; reopen
138
- the PNG from its path. `<bundle>` is `bundleDir` from `slidemind ready <deck> --json`.
139
-
140
- ## Bootstrap (set yourself up — don't make the user do it)
141
-
142
- **The first step of every session is `slidemind ready`** (continuing an existing deck: `slidemind
143
- ready <deck>`). In one call it verifies authorization, connection, and CLI version; resolves the
144
- design the add-in has open; downloads or refreshes that design's bundle; and — given a deck arg —
145
- binds the deck to it.
146
-
147
- - **Exit 0** → you're fully set up. Read `workflow/flow.md` (the stage spine) and `design.md` from
148
- the reported `bundleDir` and start planning.
149
- - **Non-zero** → the CLI names exactly one blocker and one `nextAction`; do what it says. (The two
150
- blockers that ever need the user are handled in *First step* below.)
151
-
152
- `ready` drives the `slidemind` CLI, which reaches PowerPoint through the add-in's **cloud relay** —
153
- no local server. Patch a missing CLI yourself; **connecting** needs the user once (they hold the
154
- add-in's identity):
155
-
156
- - **Flags you are unsure of:** `slidemind <command> --help` prints that command's usage block; the
157
- deck commands take `--json`.
158
- - **CLI missing** (`slidemind` not on `PATH`): `npm install -g slidemind` — that alone is the fix.
159
- Only run `slidemind init --for <claude|codex|opencode|all>` ((re)deploys this skill) when this
160
- skill did **not** come from a plugin: if the `SKILL.md` you are reading sits under a harness
161
- plugin cache (`~/.claude/plugins/…`, `~/.codex/plugins/…`), the plugin already supplies it and
162
- `init` would plant a second copy that drifts on the next plugin update. `npx slidemind <command>`
163
- runs one-off without a global install; `slidemind --version` confirms PATH; `slidemind update`
164
- upgrades (`--ref <version>` to pin) — unless the CLI itself came from a plugin, in which case
165
- update it there.
166
- - **Not connected:** `ready` exits with `not_connected` — the CLI cannot start a connection by
167
- itself, because the claim that carries the deployment's address is minted in the add-in. Ask the
168
- user to open PowerPoint → slidemind → **Settings → General → Connect CLI**, press the **link
169
- button**, and copy the command shown (press **CLI already installed?** for the short `slidemind
170
- setup …` form). Have them paste it to you and run it **verbatim** — it connects, refreshes the
171
- skills, and runs `ready` itself. Add `--no-install --for none` only if their install must not be
172
- touched. `slidemind whoami` lists connected environments.
173
-
174
- The CLI is **multi-environment**: connect once per backend (local / dev / prod) and every command
175
- fans out across all of them, tags each open window with its `env`, and routes to the right backend
176
- automatically — no manual switching. (Scope first-use authorization with `--backend <url>`; scope
177
- later calls with `--backend <url|env>`.) A normal user connects to the baked-in production backend
178
- only.
179
-
180
- ## Connecting the CLI (one-time; you guide the user)
181
-
182
- Connecting is the **only** step that genuinely needs the user, and it starts in
183
- PowerPoint — not here. Every organization runs its own slidemind backend, so an
184
- unconnected CLI has no address to reach and nothing to discover it from; the
185
- authenticated add-in knows both, and mints a one-time claim carrying its address.
186
-
187
- **1 — Ask for the command.** Tell the user to open the **slidemind add-in** task pane → **Settings**
188
- → **General** → **Connect CLI**, press the **link button**, and press **Copy command**. If they
189
- already have the CLI, **CLI already installed?** swaps it to the shorter `slidemind setup …` form;
190
- either works.
191
-
192
- **2 — Run it verbatim.** Paste it exactly as given. It redeems the claim, saves the session,
193
- installs the CLI globally if needed, deploys the skills into every coding agent on the machine, and
194
- finishes by running `ready` — so no `init` and no add-in restart belong to this flow.
195
-
196
- **3 — If it fails.** A claim works once and expires in ~10 minutes; on *already used or expired*,
197
- ask for a fresh one. The pane flips to **Connected** by itself once the claim is spent.
198
-
199
- ## First step — `slidemind ready` (before anything else, every time)
200
-
201
- Everything about how a deck is authored, styled, and rendered is shaped by the corporate design
202
- **the add-in has open**, and every brand rule you follow is read from that design's **materialized
203
- bundle**. `slidemind ready` gets you there in one call: it walks the connection ladder (a saved
204
- session → reachable backend → CLI version), picks which design to build against, downloads or
205
- refreshes that design's bundle (incremental — unchanged files cost nothing), and — when you pass a
206
- deck — binds the deck to it by writing `<deck>/.bundle-ref.json`. PowerPoint does not have to be
207
- open: the designs cached on this machine are a first-class source.
208
-
209
- - **New work:** `slidemind ready` — picks + materializes a design's bundle so you can read its
210
- `design.md` while planning.
211
- - **Continuing a deck:** `slidemind ready <deck>` — same, and the deck's own binding is what it
212
- picks.
213
-
214
- **The design is the user's choice; `ready` only picks a sensible default.** Its order is: an
215
- explicit `--brand <presFP>`, else the deck's own `.bundle-ref.json`, else the one design the
216
- verified live PowerPoint windows agree on (a window whose pane is only suspended never outranks a
217
- live one), else the one design cached here, else the one design the backend lists. Anything
218
- that leaves several candidates is the `ambiguous_design` blocker (below). A live window is a
219
- suggestion, never an authority: it only decides when nothing stronger says otherwise. And whatever
220
- `ready` picked, when its `designs` list holds more than one entry the design is a Clarify question
221
- (below), and the answer is applied with `slidemind ready [deck] --brand <presFP>` before anything
222
- is planned.
223
-
224
- **On exit 0** the JSON reports `presId`, `presFP`, `designName`, `designs` (every design at hand
225
- — cached on this machine, open in a verified window, or listed by the backend — `{presFP, name,
226
- colors, current, cached, windows}`, `colors` being the master's theme colours as hex,
227
- `dk1`/`lt1`/`dk2`/`lt2`/`accent1..6`, `windows` the open PowerPoint windows on that design),
228
- `windows` (every verified open window — `{presId, env, title, fileName, presFP, paneReady}`; a
229
- window PowerPoint no longer has is pruned before anything is decided), `bundleDir`, `bundleEtag`,
230
- `bound`, `paneSuspended`, and `engines` (`{available, envs}` — whether engine search reaches the
231
- corpus without a window), with `nextAction: "Ready."`. Read `workflow/flow.md` and `design.md` from
232
- `bundleDir` (cached at `${XDG_CACHE_HOME:-~/.cache}/slidemind/bundles/<presFP>/`, alongside
233
- `corporate-design.css`, `layouts/*.jsx`, `layouts/layouts.css`, `assets/`, and the rest
234
- of the add-in-owned `workflow/*.md`) and start planning. A render-ready window whose pane is
235
- suspended still exits 0 with `paneSuspended: true` — the pane ops wait for a pane click on their
236
- own; **don't treat it as a blocker.**
237
-
238
- **A bound deck readies with NO window at all — that is the normal case, not a degraded one.**
239
- `slidemind ready <deck>` for a deck that was bound once before exits 0 with `windowless: true` even
240
- when PowerPoint is closed: the design identity lives in the deck's `.bundle-ref.json` and the bundle
241
- syncs over a pane-free route, so its ladder is *session → bundle freshness → engine reachability*,
242
- with **no pane precondition** — the pane is reported, never required. In that state authoring,
243
- `view-draft`, `build`, `review`, `build-pptx`, and (where `engines.available` is true) engine search
244
- and download all work end-to-end; only `push`'s insert, `insert-slide`, and `read <presId>` of an
245
- open presentation need a window — the `nextAction` says exactly that. Don't ask the user to open
246
- PowerPoint until one of those is actually next.
247
-
248
- **Microsoft 365 sign-in — automatic on first need; just let it happen.** The engine surface — corpus
249
- search, brand-imagery downloads, slide extraction — runs **as the user**. `ready` reports the state
250
- (JSON: `m365.signedIn`, `m365.degradation`) so you know it's coming, but you never initiate it: the
251
- first engine command opens the user's browser ITSELF, prints `Microsoft 365 sign-in needed — opening
252
- your browser…`, and **blocks until the human finishes**. When that line appears, tell the user to
253
- complete the sign-in in the browser (you cannot) and keep waiting — don't kill or re-run the
254
- command. One sign-in lasts ~90 days. Rendering, bundles, and already-materialized assets never need
255
- it, so a pure author→render session runs signed-out without ever seeing this.
256
-
257
- For a deck that was **never** bound and no window is open, the one design cached here binds
258
- automatically; with nothing cached `ready` asks the backend which corporate designs the user may
259
- build against, and exactly one binds. Several of either stop with `ambiguous_design` (below).
260
-
261
- **On non-zero** the CLI names exactly one blocker `{code, actor, message}` and one `nextAction`.
262
- **The CLI owns the remediation text — relay `nextAction`, don't restate it.** These are the ones
263
- that need the user:
264
-
265
- - **`ambiguous_design`** — several corporate designs are at hand and nothing says which: several
266
- live windows on different designs, or no live window and several designs cached / listed by the
267
- backend. The payload is the same `designs` menu as on success (name, `colors`, `cached`, and
268
- the open `windows` on each) plus `windows`; if the deck was last built against one of them its
269
- `presFP` is `suggested`. **Ask the user which design to build against exactly as the Clarify
270
- question below does — by name and colours, naming any open window on it by `title`/`fileName`,
271
- never by raw id** — and mention the suggested one if present ("this deck was last built against
272
- X — continue with it?"). Then re-run `slidemind ready [deck] --brand <presFP>` for the design
273
- they pick (`--to <presId>` also works when they named a window).
274
- - **`login_required`** — the automatic browser sign-in was refused or abandoned, so **corpus search
275
- and engine downloads** stop until the user runs `slidemind login` (browser step, whenever they're
276
- ready). It never blocks authoring, rendering, or the bundle — relay the line, keep working, and
277
- re-run the search after they've signed in. When a slidemind pane is already open the CLI says so
278
- and routes the search through that window instead: follow what it printed.
279
- - **Connection blockers** (`not_connected`, `all_unreachable`, `cli_update_required`, `no_window`,
280
- `not_render_ready`) — relay the CLI's `nextAction` verbatim (copy the setup command / open
281
- PowerPoint / click the pane / run `slidemind update`). Connecting is walked through above.
282
- (`no_window` only ever surfaces for a deck that is neither bound nor bindable from the backend's
283
- design list — a bound deck rides the pane-free rung above instead.)
284
-
285
- **The session spine** (= the stage todos you created up front): `slidemind ready` → read
286
- `workflow/flow.md` + `design.md` from `bundleDir` → intake/plan (below) → `slidemind new <slug>`
287
- (scaffolds **and** auto-binds the deck to the open design — zero extra download, because `ready`
288
- already materialized it; `--brand <presFP>` binds to the design the user chose instead) → `slidemind plan <slug>` (plan sign-off gate for every
289
- from-scratch request, one slide included) → `slidemind concepts <slug>` (mandatory concept-mockup pass for everything
290
- authored from a plan, then rebuild toward each) → author → `view-draft` → `review` (mandatory, the moment the deck builds clean) →
291
- deliver (`push` / `build-pptx`). `slidemind new` best-effort binds when the open design is
292
- unambiguous and the bundle is already materialized; if it can't (ambiguous, or no host), it
293
- scaffolds anyway and hints to run `slidemind ready <slug>`.
294
-
295
- **Backgrounded — or closed — PowerPoint is expected to work.** Do not pre-emptively ask the user to
296
- focus PowerPoint or the task pane, and never ask them to keep it foregrounded while something runs.
297
- **The whole authoring loop is host-free for a bound deck** — intake → plan → concepts → author →
298
- `view-draft` → `review` → `slidemind build-pptx <deck> [--out <file>]` — because the render captures
299
- the slides with a local headless browser and assembles the `.pptx` server-side over the pane-free
300
- brand route (streaming its own `rendering slide n/m…` progress), and engine discovery, search,
301
- downloads, and slide reuse run off the connection wherever the add-in serves them
302
- (`engines.available` in `ready`'s payload; older add-ins relay them through a pane instead). Exactly
303
- three things need a live PowerPoint: **`push`'s insert**, **`insert-slide`**, and **`read
304
- <presId>`** of an open presentation. Where a pane *is* involved, the CLI handles the wait itself: up
305
- to ~2 min, one *"click the slidemind pane"* line when user help is genuinely needed, then a safe
306
- retry. If you see that line, relay it once and keep waiting — do not rebuild, re-plan, or babysit.
307
- If a `push` can't deliver (pane never woke, or no window at all), the rendered `.pptx` was saved
308
- next to the deck (`paneSuspended` + `fallbackFile` in the result) — nothing is lost; re-run the push
309
- once a window exists. Reserve the full "open PowerPoint…" instruction for when a command actually
310
- reports it as the blocker.
311
-
312
- `view-draft` and `review` run offline, but only against a **previously
313
- materialized** bundle — so `ready` (or a prior `ready`) must have succeeded at least once.
314
- `build-pptx` additionally needs the backend reachable (the OOXML assembly is server-side), but no
315
- PowerPoint window for a bound deck — so *"a `.pptx` file to send around"* is deliverable end-to-end
316
- with PowerPoint closed.
317
-
318
- ## Two UX rules (gates + host)
319
-
320
- - **Announce every gate, with a clickable link.** The moment `slidemind plan` or `slidemind review`
321
- starts it prints `ready at <url>` and a `BROWSER:` status line. Immediately tell the user in chat
322
- whether a browser tab opened (new tab / reused tab / failed to open) and give the gate URL as a
323
- clickable link — every round, and again whenever you report that you're still waiting on their
324
- decision.
325
- - **Add-in unreachable → block and name the tab.** When a genuinely host-required command (`push`'s
326
- insert, `insert-slide`, `read <presId>`) can't reach the add-in (a connection blocker, a pane that
327
- never wakes, the *click the slidemind pane* line with no effect), **stop the workflow** — don't
328
- skip the step, work around it, or retry silently. Ask the user to go back into the PowerPoint tab
329
- of presentation **<title/fileName>** (name it from the command output or `slidemind ready --diagnose`
330
- — never a raw id), then re-run the failed command once they have. Everything before delivery keeps
331
- running meanwhile — never park the whole task on a window it doesn't need.
332
-
333
- ## Intake → plan (you own this; do it in chat)
334
-
335
- This is your mapping of `workflow/flow.md` stages 1–2 (*clarify* + *plan sign-off*). In-app, a
336
- manager runs these; over the CLI the manager role collapses onto **you**, so you run the interview
337
- and the sign-off directly with the user. Don't write slide JSX until the plan is agreed.
338
-
339
- **First read which of three things the user wants**, from their words plus what you already have —
340
- the deck you are working in, the file they pointed at, what you built for them a moment ago. Judge it
341
- yourself and ask only when the request genuinely reads both ways. **Slide count never decides the
342
- route; intent does.**
343
-
344
- - **Author something new** ("a slide about X", "a deck for Friday", "add a closing slide", filling an
345
- empty placeholder) → the full spine: plan → `slidemind plan` → `slidemind concepts` → author →
346
- `view-draft` → `review` → deliver. One slide runs every one of those stages, just smaller.
347
- - **Change slides that already exist** ("make slide 4 stronger", "fix the spacing", "retitle these
348
- three") → **no plan, no concepts**: there is nothing to plan, the live slide is the starting point.
349
- Read `workflow/edit.md`, patch that slide's own `.jsx` (adopt a foreign slide on first touch), then
350
- `view-draft` → `review` → deliver. The review gate still runs — over the CLI the deliver happens
351
- out of the user's sight, so it is the only place they see the change.
352
- - **Reuse something that already exists elsewhere** ("do we have a slide on X?", "drop in our pricing
353
- slide", "put our lighthouse icon here") → that is **`slidemind-search`**, not this create flow:
354
- `slidemind search` → `download-result` / `add-slide`. Reuse is not authoring — no plan, no
355
- concepts.
356
-
357
- A request can carry two of them ("find our pricing slide and write a summary after it") — run each
358
- part on its own route instead of forcing the whole thing onto one.
359
-
360
- - **Read scope from the wording**, don't ask redundantly: single slide ("make a slide about X"),
361
- small set ("add three slides on Y"), or whole deck ("a deck for Friday"). Only ask "one slide, a
362
- small set, or a full deck?" when truly ambiguous.
363
- **Choose layouts from evidence.** Honor explicit choices first. For an extension, read the target deck and its section/insertion context: prefer the section's suitable body layouts, then the deck's common layouts. For a new presentation use the catalog's observed brand usage. Frequency wins among layouts that can fit the content; do not force layout variety or an 80/20 quota. Names, previews, hints and content areas guide semantic choices. Preserve native names; copy the exact component name and layoutKey from the catalog. Verified dark/light counterparts can be switched, but retain the deck's established pattern (for example dark dividers with light body slides). Never assume two layouts are equivalent just because names or colors resemble each other.
364
-
365
- **Record the slide's role, not a permanent layout classification.** Every storyboard carries `role: body | frame`; frame slides also carry `frameKind: cover | agenda | divider | closing`. Also record `layoutSelection: automatic | explicit`, `layoutKey` when provided, and a short `layoutReason`. Use `sectionId` for meaningful sections. A quote is ordinarily a body slide. Choose frame layouts from the available native names, previews and slots; no stored layout job is required. Use an empty blocks array only when the layout has no authored content area. Covers can require images; agendas can require composition. No frame mockup is generated by default, but source every required image, fill every required slot, and perform the normal fit and rendered checks.
366
-
367
- **Deliverable intent is independent of delivery target.** `slides` adds only the requested slides, with no automatic frame; an explicitly requested cover or divider is still valid. `deck` adds the appropriate available frame whether delivered as a file or into PowerPoint. A deck request's count means body slides unless the user states a total limit. Show body and total counts separately. Default to available cover/closing, agenda at four body slides or two meaningful sections, dividers for multiple meaningful sections; never invent sections for these thresholds. Record an unavailable frame layout as an omission in the plan. User choices override defaults. Never overwrite a signed-off layout because usage evidence changed.
368
-
369
- For an existing target or explicit reference deck, run `slidemind read <presId|file.pptx> --mode summary --deck <deck>` before planning to bind its usage snapshot to this workspace. Refresh that read when the target changes. Standalone decks without a reference use brand usage and require no live window.
370
-
371
- - **Which corporate design — ask whenever more than one is cached.** `ready`'s `designs` list is
372
- the menu: with a single entry there is no question; with several, put the choice to the user
373
- **before planning**, even if PowerPoint has one of them open (that one is only the suggestion).
374
- Never pick silently and never default to the open window or the deck's last binding — those
375
- only chose `ready`'s `current` default, not the user's answer. Name each
376
- design **and show its colours** so the user recognises it — the `name` plus its theme hexes in a
377
- fixed order (`<name> — accent <accent1>, dark <dk1>, light <lt1>`, each a hex from `colors`; a
378
- design without `colors` is listed by name alone), mark the `current` one, and ask which to build
379
- against. Then
380
- apply the answer: `slidemind ready [deck] --brand <presFP>` for the session, and `slidemind new
381
- <slug> --brand <presFP>` when scaffolding a new deck. A design the user names that is not in the
382
- list is not cached yet — `slidemind ready --brand <presFP>` fetches it when the backend serves
383
- it; otherwise it must be opened in PowerPoint once.
384
- - **Interview just enough** to pin: audience/goal, the content and its sources (none / pasted /
385
- local files / existing deck / web research — a source that's already a local `.pptx` you read
386
- host-free with `slidemind read <file.pptx>`), and the slide outline (each slide's role + a layout
387
- *job* like cover/agenda/section/quote/closing/body — the concrete brand layout is chosen later
388
- against the bundle). If the content source resolves to "none", don't silently plan from generic
389
- knowledge — say so, and either interview the user for the substance (their claims, numbers,
390
- examples) or offer web research before writing storyboards.
391
- - **Lock the output target — it decides your deliver command.** Into the open PowerPoint (`slidemind
392
- push`), or a `.pptx` file (`slidemind build-pptx`) — or an HTML preview / a mix. Infer it when the
393
- wording is clear ("add a slide to this deck" → push; "make me a deck I can send around" → a file)
394
- and ask only when genuinely ambiguous — but **always confirm the concrete target before
395
- delivering** (which window, or which output path).
396
- - **Replay and get sign-off — always, at every size.** Persist a **story-focused plan with body
397
- storyboards** in `decks/<slug>/plan.md` and run the gate on it, whether the request is one slide or
398
- forty. A single slide gets the same document with one `### Slide N` section: shorter, never
399
- skipped. Three top-level sections in order — first `## Deliverable`, four lines:
400
- ```
401
- ## Deliverable
402
- - shape: deck # deck | slides
403
- - body slides: 3 # the count the user asked for, body only
404
- - frame: cover, closing # the frame jobs this deck ships, or none
405
- - target: file # file | push
406
- ```
407
- (`slidemind plan` prints a `[plan:warn]` line for every disagreement between this block, the
408
- storyboards' explicit roles and selected layouts — read them before the gate opens.) Then:
409
- - `## Red thread` — one presentation **move** per **body** slide, as bullets or one arrow-separated
410
- line, followed by one `Frame:` line naming the frame slides in play order (`Frame: cover ·
411
- closing`, or `Frame: none`). The number of body moves MUST equal the number of body `### Slide N`
412
- sections: use the agreed Deliverable body count, accounting for any explicit total limit or
413
- individual frame-slide request. Never expand that agreed body count. Frame slides get their own `### Slide
414
- N` sections in play order (cover = slide 1, closing = last, a divider directly before its
415
- section). Use `"blocks": []` only when the layout has no authored content region; otherwise
416
- sketch the required composition. Put the slot text in `contentNotes` and the story beat in
417
- `keyMessage`. Name the *teaching function* of each slide — short verb+noun labels for what
418
- the audience is doing cognitively at that step — never its content: no claims, facts, metrics,
419
- client-specific terms, slide copy, generic section names, or wording copied from these
420
- instructions.
421
- - `## Per-slide storyboards` — one `### Slide N: <role>` subsection per slide, each a one-sentence
422
- `Core message:` followed by **exactly one** fenced `storyboard-canvas` JSON block.
423
-
424
- The `storyboard-canvas` is a **body-only spatial sketch**, not final slide design: it plans the
425
- body region only and never the template title/header/footer/logo/slide-number areas. Blocks live
426
- in a 1600 × 900 coordinate space, kept inside the body-safe area (roughly x 80–1520, y 110–780);
427
- position, size, and proximity must express the slide's meaning — hierarchy, sequence, causality,
428
- contrast, grouping, flow direction, or the main focus — not random placement. Each block shows
429
- only two visible text fields: `designElement` (the visual mechanism in up to 5 words — e.g.
430
- "hub-spoke visual", "loop diagram", "timeline", "matrix", "before/after contrast", "scorecard")
431
- and `content` (a 1–2 word label), plus `emphasis` ("primary"/"secondary"/"tertiary") for
432
- hierarchy. A `designElement` may also name the chart family when the beat is quantitative
433
- ("waterfall revenue to EBIT", "combo: revenue bars + margin line", "column chart by quarter");
434
- that is a plan-level choice the authoring stage honours unless the data cannot be shown that
435
- way, in which case it says so at the review gate.
436
- `keyMessage` is the slide's **story beat**: one plain sentence naming what this slide
437
- does to move the story forward, stated abstractly — NOT the headline or copy that will appear on
438
- the slide, and not the red-thread move restated. `contentNotes` is the **content draft** that
439
- delivers that beat — facts, claims, examples, source points, caveats, draft copy, proof points —
440
- and carries no design, layout, tone, or authoring-process instructions. It is the slide's full
441
- content budget: the create stage and the concept-mockup generator build from `contentNotes` alone
442
- and never add substance, so anything not in the notes will not be on the slide. Write them so the
443
- slide body could be authored from them without inventing anything — every claim spelled out
444
- concretely, with the numbers, named examples, or proof points that make it land. Two or three
445
- abstract topic bullets ("X is expensive", "Y improves") is an unfinished draft, not a storyboard.
446
-
447
- Judge whether two or more slides form a genuine visual series — for example a continuation,
448
- progressive reveal, repeated comparison, phased journey, or recurring framework. When they do,
449
- give those storyboard objects the same short, stable `visualFamily` identifier. Do not group
450
- slides merely because they share a topic, and do not ask the user to make this design judgment. A
451
- family tells concept generation to establish one recognizable visual system and adapt it to every
452
- member's own `keyMessage`, `contentNotes`, role, and structure. It never permits copying another
453
- slide's text, claims, data, or exact geometry, and it never permits dropping approved content to
454
- fit the shared concept. Omit `visualFamily` for independent slides.
455
-
456
- Choose the block count from the slide's meaning and **never default to three** (1 for a hero idea,
457
- 2 for a contrast or paired tension, 3 only for three genuinely distinct beats, 4–5 only for a true
458
- sequence or comparison set), and vary the spatial composition across slides — avoid repeating the
459
- same left/right/bottom alignment. Ban style micromanagement — no colours, fonts, or final
460
- box/card counts: **the create stage owns realisation** of the approved body storyboard in the
461
- corporate design. The ONE exception is the top-level `layout` field: **choose each slide's
462
- layout at plan time** from `design.md` → Layout Catalog (a workhorse with a freeform body for
463
- content slides; a purpose-built layout for covers/quotes/agendas; match the background tone —
464
- light vs dark — to the slide's intended look) and set `"layout": "<ComponentName>"` on the
465
- storyboard block. The concept generator uses it to render the mockup INTO that layout's actual
466
- chrome and canvas, so the image you later rebuild already fits the stage it will live on. Use
467
- this exact JSON shape:
468
-
469
- ```storyboard-canvas
470
- {
471
- "version": 1,
472
- "role": "body",
473
- "layoutSelection": "automatic",
474
- "slide": 1,
475
- "layout": "<ComponentName from design.md's Layout Catalog>",
476
- "blocks": [
477
- {
478
- "id": "main-visual",
479
- "x": 420,
480
- "y": 180,
481
- "w": 680,
482
- "h": 280,
483
- "emphasis": "primary",
484
- "designElement": "Hub-spoke visual",
485
- "content": "Operating model"
486
- }
487
- ],
488
- "keyMessage": "Shift the audience from thinking about AI tools to thinking about the operating model, so the rest of the deck has a reason to land.",
489
- "contentNotes": [
490
- "The operating model has five components: intake (requests land in one queue), tool use (agents draft with approved tools), validation (a human reviews before anything ships), escalation (edge cases route to a named owner), ownership (each workflow has one accountable lead).",
491
- "Concrete example: contract review — intake via the legal inbox, agent drafts the redline, counsel validates in under 10 minutes vs. 2 hours manual.",
492
- "Decision for the audience: which single workflow do we pilot this quarter — contract review or customer response drafting?"
493
- ]
494
- }
495
- ```
496
-
497
- Make the connection to the current deck explicit in the red thread, core messages, `keyMessage`,
498
- or `contentNotes` whenever the work extends the open presentation, and fold in any content
499
- findings from slides/files you inspected. Then run `slidemind plan <deck>`: it opens the plan as
500
- **editable storyboards** — the user reorders/renames/inserts/removes slides on the red-thread
501
- strip, drags/resizes/edits blocks and the content draft directly on each slide's canvas, and/or
502
- leaves comments anchored to a slide or to the whole story — and it **blocks until the user
503
- decides** — announce it per *Two UX rules* (browser opened? + the clickable gate URL) and give the
504
- shell call a **generous timeout** (the gate waits up to 30 min; if your harness kills the call
505
- early, just re-run it — the user's open tab reconnects). Outcomes: `DECISION: approved` → proceed
506
- to author; `DECISION: comments` → apply the comments to `plan.md` — each is **slide-anchored** (`-
507
- [Slide 3: "<beat>"] …`) or whole-story, and the batch may include a **generated story-iteration
508
- instruction** (when the user restructured the red thread by adding or renaming slides, the gate
509
- asks you to build storyboards and content for exactly those moves while keeping the other slides
510
- intact) — (the round is persisted verbatim in `<deck>/plan-review.json` if your capture of the
511
- output was truncated). Change only what the comments require and keep unaffected slides verbatim
512
- (that is what makes the reviewer's per-slide "updated" badges meaningful), then **re-run the gate
513
- in the same turn**. **Expect several consecutive `DECISION: comments` rounds — that is the normal
514
- shape of a review, not an error.** The reviewer's tab waits while you revise (reading stays live,
515
- commenting is off) and refreshes with your next run, which blocks until they decide again. So
516
- never end your turn on a comments round, never claim to be "polling", and never send the user
517
- back to the browser between rounds — nothing reaches them until the gate runs again. Only `DECISION: approved` or `DECISION:
518
- pending` ends the loop; `DECISION: pending` → the gate timed out with no answer — not approval,
519
- not rejection: don't author; wrap up telling the user the plan still awaits their sign-off and
520
- re-run `slidemind plan <deck>` on their go-ahead. Loop until approved. A `plan.md` **approved in a
521
- prior gate round and unchanged since** counts as approved (skip straight to authoring); any new or
522
- revised plan must pass the gate. When the gate reports the user edited `plan.md` directly, re-read
523
- it — the edited storyboards **are** the approved plan; author from them.
524
-
525
- Keep planning about intent and content. The bundle is already materialized by `slidemind ready`, so
526
- `design.md` is there if you need to sanity-check feasibility — but **don't dive into
527
- brand/layout/composition detail until create/edit.**
8
+ This skill is the **CLI half** of slidemind authoring: it maps the shared workflow onto `slidemind`
9
+ commands and owns what only the CLI has. Read all of it — if your tool truncates its output, read
10
+ the rest by line range. Everything else comes from the **design bundle** `slidemind ready`
11
+ materializes, the same files the in-app design agent reads:
12
+
13
+ - **The brand** — `design.md`, `corporate-design.css`, `layouts/` (tokens, type ramp, the closed
14
+ layout palette).
15
+ - **The craft** — `workflow/flow.md` (stages, invariants, vocabulary), `plan.md` (the plan
16
+ contract), `create.md`, `edit.md`, `authoring.md`, `composition.md`, `layouts.md`,
17
+ `build-and-export.md`.
18
+
19
+ Read them there; never restate a brand value or a craft rule from memory, and load no external
20
+ design-taste plugins during slide work. **slidemind is a CLI you run directly**, like `git`. Every
21
+ command takes `--help`; the deck commands take `--json`.
22
+
23
+ ## Stage todo list (create it before your first command)
24
+
25
+ Create a todo list of these stages in your harness's task tracker before you run anything
26
+ (`workflow/flow.md` → *track the stages*); mark each done as you finish it:
27
+
28
+ 1. **Ready** — `slidemind ready` (*Session start*).
29
+ 2. **Clarify** the content (*Intake → plan*). Never ask about the output: it is always a `.pptx`.
30
+ 3. **Plan sign-off** — write `plan.md`, run `slidemind plan <deck>`; every from-scratch request,
31
+ one slide included. Once approved, write each body slide's `content` draft into its storyboard
32
+ (`workflow/plan.md`); `concepts` refuses a body slide without one.
33
+ 4. **Concepts** — `slidemind concepts <deck>`, then Read every mockup PNG it lists. It always ends
34
+ on `CONCEPTS: <n>/<planned> <status>`; if your harness cut it off before that line, re-run it
35
+ (mockups on disk return at once). Only `CONCEPTS: 0/…` means there are none.
36
+ 5. **Transcribe** — `slidemind transcribe <deck>`: editable JSX, settled geometry, the requested
37
+ assets. It runs for minutes and ends on one `TRANSCRIBED` line — poll it, never interrupt it.
38
+ 6. **Compare and repair** each concept/draft pair in the JSX (*The create flow*).
39
+ 7. **Draft check** — `slidemind view-draft <deck>` until `DRAFT CHECK: no measured defects` (which
40
+ lines hold: `workflow/create.md` step 6) and each render makes its concept's argument, cleaner
41
+ than the painting.
42
+ 8. **Review gate** — `slidemind review <deck>` the moment the deck builds clean.
43
+ 9. **Deliver** — `slidemind build-pptx <deck>` (`push`/`publish` too only when the user's words
44
+ asked, *Intake → plan*; a deck connected to SharePoint publishes inside the build, *Remote
45
+ decks*). The concept comparison was the draft check's (`workflow/flow.md` stage 6), so the PNGs
46
+ it renders get no second one: they are where a `<Chart>` is judged (*Charts*). A build that ends
47
+ on `PACKAGE DEFECTS:` is not ready for the user (nor published): fix each, `view-draft --only`
48
+ it, build again. Say what landed (slide count + target) and stop: deliver is the last stage.
49
+
50
+ **Changing slides that already exist** runs `ready` → edit → `view-draft` → deliver (*Editing slides
51
+ that already exist*): no plan, no concepts, no review once the deck passed one or was adopted from
52
+ the user's own `.pptx`. After that review `plan.md` is a record; updating it never re-opens the plan
53
+ gate. New slides added to an existing deck run the full list, minus a review the deck already
54
+ passed.
55
+
56
+ The CLI enforces `workflow/flow.md`'s gate invariants: **no `slides/*.jsx` for new slides before the
57
+ plan gate returned `DECISION: approved`** — no small-request exception — and **nothing delivered
58
+ that `view-draft` has not checked**: `review`, `build-pptx` and `push` refuse a slide they would
59
+ ship that was never checked, changed since its check, or still holds a measured defect. A deck you
60
+ authored passes the review gate once, before its first delivery.
61
+
62
+ ## What to read, and resuming after a summarization
63
+
64
+ `<bundle>` is `bundleDir` from `slidemind ready [deck] --json`; deck paths are under
65
+ `decks/<slug>/.slidemind/`.
66
+
67
+ | Stage | Read |
68
+ |---|---|
69
+ | after `ready` | `<bundle>/workflow/flow.md`, `<bundle>/design.md` |
70
+ | plan + content drafts | `<bundle>/workflow/plan.md`, the layout catalog in `design.md`, `plan.md` |
71
+ | concepts → repair | `<bundle>/workflow/create.md` (all of it), `corporate-design.css`, the `layouts/<Layout>.jsx` the plan names, `slides/*.jsx`, each `concepts/concept-slide-NN.png` at full detail; `workflow/authoring.md` for a `<Chart>` and for substrate, line/arrow or type-size repairs; `workflow/composition.md` + `layouts.md` for a slide with no mockup |
72
+ | edit existing slides | `<bundle>/workflow/edit.md` + the affected `slides/*.jsx` (a structural rework adds the row above) |
73
+ | reuse from an engine | the `slidemind-search` skill |
74
+
75
+ A summary replaces what you only held in chat — viewed images, search results, the rules you read;
76
+ files on disk survive. Running from a summary, after an interruption, or when the user just says
77
+ "continue": run `slidemind ready <deck>` first. Its `stage:` and `next:` lines (`stage` in `--json`)
78
+ name where the deck stands and the command or file due next — a waiting gate answer included.
79
+ Re-read that stage's row and resume there. Never restart finished work, never skip the remaining
80
+ stages, and never author, judge or deliver from a remembered image — reopen the PNG from its path.
81
+
82
+ ## Session start — `slidemind ready`
83
+
84
+ `slidemind ready` (continuing a deck: `slidemind ready <deck>`) is the first command of every
85
+ session: it checks the connection and CLI version, picks the corporate design, refreshes its bundle
86
+ and, given a deck, binds it (`state/bundle-ref.json`).
87
+
88
+ **Exit 0** → read `workflow/flow.md` and `design.md` from `bundleDir`. The JSON also carries
89
+ `designs` (`{presFP, name, colors, current, cached, windows}`; `colors` = theme hexes
90
+ `dk1`/`lt1`/`dk2`/`lt2`/`accent1..6`), `windows` (`{presId, title, fileName, presFP, paneReady}`),
91
+ `engines.available`, `paneSuspended` and `windowless`.
92
+
93
+ - **No PowerPoint window is the normal case** (`windowless: true`). Authoring, `view-draft`,
94
+ `review`, `build-pptx` and — with `engines.available` — engine search and download all run without
95
+ one. Only `push`'s insert, `insert-slide` and `read <presId>` need a live window; don't ask the
96
+ user to open, focus or click PowerPoint before one of those is next. `paneSuspended: true` is no
97
+ blocker: those commands wait (~2 min) and print one *click the slidemind pane* line when they need
98
+ help — relay it once and keep waiting.
99
+ - **The design is the user's choice.** `ready` only picks a default (`--brand`, else the deck's
100
+ binding, else the one design live windows agree on, else the one cached, else the one the backend
101
+ lists). **When `designs` has more than one entry, ask before planning** — an open window is only
102
+ the suggestion. List each as `<name> — accent <accent1>, dark <dk1>, light <lt1>`, mark the
103
+ `current` one, name open windows by `title`/`fileName` (never an id), and apply the answer with
104
+ `slidemind ready [deck] --brand <presFP>` (and `slidemind new <slug> --brand <presFP>`).
105
+ - **Microsoft 365 sign-in happens by itself:** the first engine command opens the browser, prints
106
+ `Microsoft 365 sign-in needed — opening your browser…` and blocks until the user finishes. Tell
107
+ them to complete it; don't kill or re-run the command.
108
+ - **The bundle stays fresh by itself:** deck commands re-sync the bound design and print
109
+ `design bundle updated` when it moved (a render that meets `bundle_etag_stale` refreshes and
110
+ retries on its own) — then re-read `design.md` before authoring anything new.
111
+
112
+ **Non-zero** → one blocker `{code, actor, message}` and one `nextAction`. Relay the `nextAction`.
113
+
114
+ - `ambiguous_design` — ask as above from its `designs` menu (mention `suggested`: "this deck was
115
+ last built against X — continue with it?"), then `slidemind ready [deck] --brand <presFP>`.
116
+ - `login_required` — corpus search and engine downloads wait until the user runs `slidemind login`;
117
+ keep authoring. When a slidemind pane is open, the CLI routes the search through it.
118
+ - `not_connected` — the claim that carries the deployment's address is minted in the add-in. Ask
119
+ the user to open PowerPoint → slidemind → **Settings → General → Connect CLI**, press the **link
120
+ button**, then **Copy command** (**CLI already installed?** gives the short `slidemind setup …`
121
+ form), and paste it to you. Run it **verbatim** — it connects, installs, deploys the skills and
122
+ runs `ready` (`--no-install --for none` only when their install must stay untouched). A claim
123
+ works once for ~10 minutes; on *already used or expired*, ask for a fresh one.
124
+ - `all_unreachable`, `cli_update_required`, `no_window`, `not_render_ready` — relay `nextAction`.
125
+
126
+ **CLI missing:** `npm install -g slidemind` is the whole fix.
127
+ `slidemind init --for <claude|codex|opencode|all>` only when this `SKILL.md` is not under a plugin
128
+ cache (`~/.claude/plugins/…`, `~/.codex/plugins/…`) — there it would plant a second copy.
129
+ `slidemind update` upgrades (`--ref <version>` pins), unless the CLI came from the plugin: then
130
+ update the plugin.
131
+
132
+ ## The workspace and the gates
133
+
134
+ The user answers in the **slidemind workspace**, a browser page that runs in the background. Never
135
+ ask them to open a terminal or run anything. Asked to show it:
136
+ `slidemind workspace [<deck>] --no-open --json`, then answer *Your slidemind workspace: <link>*.
137
+ Never open a browser yourself.
138
+
139
+ **How to run a gate.** `slidemind plan <deck>` (once `plan.md` is written) and
140
+ `slidemind review <deck>` (once `view-draft` is clean) are the only ways to ask for a decision. A
141
+ gate never waits.
142
+
143
+ - **Asking:** it prints `ASK: <link>`, `SAY: <line>`, `DECISION: pending`. **End your turn with the
144
+ SAY line, word for word.** Don't wait, poll, sleep or re-run; don't author or deliver meanwhile.
145
+ - **Receiving:** the user pastes a message naming the receiving command (*Plan approved. Continue:
146
+ `slidemind plan "<deck path>"`*). Run exactly that. `DECISION: approved` → do what `Next:` says.
147
+ `DECISION: comments` → change only what is asked, run the same gate again, end your turn with its
148
+ new SAY line (several rounds are normal). `DECISION: pending` → end your turn with its SAY line
149
+ again.
150
+ - Approved, unchanged content answers `approved` at once; never ask the user to repeat an answer or
151
+ type a command.
152
+ - `BLOCKED: workspace_sandboxed` → run it again outside the sandbox (Codex: escalated permissions).
153
+ `BLOCKED: deck_not_writable` → *Where the deck lives*. `BLOCKED: deck_unbound` → the
154
+ `slidemind ready <deck> --brand <presFP>` it names, with the design the user chose, then the gate
155
+ again.
156
+ - An adopted deck's session must not hold the deck while the user answers:
157
+ `slidemind revision finish <deck>` before the gate, `revision begin` again after.
158
+
159
+ **Add-in unreachable → stop and name the tab.** When `push`'s insert, `insert-slide` or
160
+ `read <presId>` cannot reach the add-in, stop that step — no skipping, workaround or silent retry.
161
+ Ask the user to go back to the PowerPoint tab of **<title or fileName>** (from the output or
162
+ `slidemind ready --diagnose`), then re-run it. Work that needs no window continues.
163
+
164
+ ## Intake → plan
165
+
166
+ `workflow/flow.md` stages 1–2; in-app a manager runs them, over the CLI you do, in chat.
167
+
168
+ **Route by intent, never by slide count** (`workflow/flow.md` → *What scales*); ask only when it
169
+ reads both ways, and run each part of a two-part request on its own route:
170
+
171
+ - **Author something new** ("a slide about X", "add a closing slide") → the full stage list.
172
+ - **Change slides that exist** ("make slide 4 stronger") → *Editing slides that already exist*.
173
+ - **Reuse what exists** ("do we have a slide on X?", "drop in our pricing slide") → the
174
+ `slidemind-search` skill (`search` → `download-result` / `add-slide`); no plan, no concepts.
175
+
176
+ **Clarify** what `workflow/flow.md` stage 1 lists (a content source included), plus the design when
177
+ `ready` reported several. `slidemind read <file.pptx>`
178
+ reads a local source host-free; for an existing target or reference deck,
179
+ `slidemind read <presId|file.pptx> --mode summary --deck <deck>` before planning binds its layout
180
+ usage (re-read when the target changes).
181
+
182
+ **The output is always a `.pptx` — never ask about format, target or path.** `build-pptx` writes
183
+ `decks/<slug>/<slug>.pptx` (`target: file` in `## Deliverable`). Only the user's own words add a
184
+ destination: a SharePoint link (`…/:f:/…` folder, `…/:p:/…` file, `/sites/…/x.pptx`) adds
185
+ `slidemind publish` (*Remote decks*) — a folder the user connects in the workspace needs nothing from
186
+ you; "put it into my open presentation" adds `slidemind push`
187
+ (`target: push`) — with several presentations open, confirm which one; after the review, push
188
+ without asking. Delivering into that window again is `push --replace`, which replaces the whole
189
+ presentation with the deck and refuses while it holds slides the deck does not own.
190
+
191
+ **Write the plan and get sign-off — at every size.**
192
+
193
+ 1. `slidemind new <slug>` scaffolds `decks/<slug>/` and binds it to the design `ready` picked
194
+ (`--brand <presFP>` for the user's choice; if it cannot bind, it says to run `ready <slug>`).
195
+ 2. Write `decks/<slug>/.slidemind/plan.md` exactly per `<bundle>/workflow/plan.md`. The scaffold
196
+ text is a placeholder; one slide is the same document with one `### Slide N`. Images the user
197
+ gave you add `assetUses` (*Images the user gives you*).
198
+ 3. `slidemind plan <deck>`. The user sees one card per slide (beat, content points, layout), can
199
+ reorder, rename, insert and remove slides, and comments per slide or on the whole story.
200
+ 4. `DECISION: comments` → each is slide-anchored (`- [Slide 3: "<beat>"] …`) or whole-story; a
201
+ batch may carry a story-iteration instruction (build exactly the slides the user added or
202
+ renamed). Keep every slide no comment touches verbatim — the page's "updated" badges depend on
203
+ it. A cut-off round is in `state/plan-review.json`. When the decision says the user edited
204
+ `plan.md`, re-read it: that is the approved plan.
205
+ 5. `DECISION: approved` → write the `content` drafts, then `slidemind concepts`. Drafts don't
206
+ re-open the gate; changed key points or story go back through `slidemind plan`.
207
+
208
+ ## Images the user gives you
209
+
210
+ A picture the user hands you is theirs, and only they know what it is for. Two records carry that:
211
+
212
+ - **The bytes are an asset:** `slidemind assets import <deck> <file>` copies it in, identifies it
213
+ by digest and records it (`slidemind assets list <deck>`). File paths only, never URLs. Importing
214
+ creates **no** obligation to place it.
215
+ - **The purpose is a use:** an `assetUses[]` entry on that slide's `storyboard-canvas`, approved at
216
+ the plan gate. One file may have several uses on several slides.
217
+
218
+ **Import before you plan** — a use names the `assetId` the import prints. Infer the purpose from the
219
+ user's words; ask once, only when it reads both ways (no role picker, no second approval). Each use
220
+ has a `useId`, the `assetId`, a free-text `instruction` and a `fidelity`:
221
+
222
+ | `fidelity` | Means |
223
+ |---|---|
224
+ | `original` | "place **this**": its saved bytes, visibly, once — with the use's `fit` (`contain` default; `cover` crops), `position`, and a `crop` only when asked for |
225
+ | `reconstruct` | "rebuild **this**" as editable content: `reconstructionScope: "slide"` = blueprint for the whole slide (replaces the mockup, bypasses composition; at most one per slide), `"element"` = one fragment inside a larger composition |
226
+ | `reference` | "look like **this**": guidance only |
227
+
228
+ `slidemind concepts --concept <file>[@N,M]` (the sketch IS those slides' mockup) and
229
+ `--style <file>[@N,M]` (it leads the look) import and record the use for you; a new use re-arms the
230
+ plan gate.
231
+
232
+ **`useId` and `assetId` are durable identity:** byte-identical in `plan.md`, the spec and the slide
233
+ element through every repair, settle and re-render. Reordering changes no id; a duplicated slide
234
+ needs **new** ids; never invent an id or move one onto other bytes; a derived version is a new
235
+ import. How a use is authored (`<img data-asset-use="<useId>" src="./assets/local/<file>">`) and
236
+ what each obligation owes: `<bundle>/workflow/create.md` → *Approved image uses*.
237
+
238
+ **If you cannot reach the bytes** (the image is only in the chat), say so and ask for a path or a
239
+ re-attachment — never screenshot, re-render, describe it to an image model, or pass off a
240
+ look-alike.
241
+
242
+ **No substitution, ever:** an `original` is its own bytes — never an engine result, a
243
+ `slidemind imagen` look-alike, a recoloured, re-cropped or re-saved copy, or a similar file in the
244
+ deck. Missing or changed bytes leave the use unresolved, and your report says so; restore or
245
+ re-import the file and rebind the use. Imagery with no use is still sourced by search.
246
+
247
+ Enforced: `concepts` refuses up front without add-in support (`image_intent_unsupported`; nothing
248
+ changes), `transcribe` resolves originals from the registry, `view-draft` reports unresolved or
249
+ unplaced uses, `build-pptx`/`push` refuse while one stands. None of that proves nothing is drawn
250
+ over the picture: look at the draft pair.
528
251
 
529
252
  ## The create flow
530
253
 
531
- Every deck command (`view-draft`, `review`, `concepts`, `build-pptx`, `push`) re-syncs the deck's
532
- bound design before it runs, so a corporate design that changes mid-session is picked up by itself —
533
- it prints `design bundle updated` when that happens, and you re-read the bundle files it names. You
534
- never have to re-run `ready` to get a fresh design.
535
-
536
- `slidemind ready` already resolved the design source and materialized its bundle; the deck was bound
537
- to it by `slidemind ready <deck>` (continuing) or by `slidemind new <slug>`'s auto-bind (new work).
538
- From here:
539
-
540
- 1. **Load create context, then inspect the concepts.** Read `workflow/create.md` (the procedure),
541
- `workflow/authoring.md` (the portability contract — **required BEFORE the first slide write**,
542
- never deferred to a lint repair: it names what CSS ports, the slide file shape, transforms,
543
- rules and dividers, painted nesting, decorative layers, the Arrow contract), the deck's
544
- `design.md`, `corporate-design.css`, and the specific `layouts/*.jsx` the plan uses. Nothing
545
- else up front: `workflow/composition.md` and `workflow/layouts.md` are for slides WITHOUT a
546
- mockup and for `[STYLE]` questions — open them when a lint message or a missing mockup sends
547
- you there, not before (the read set is what `workflow/create.md` prescribes; `workflow/flow.md`
548
- you already read after `ready`). The approved `plan.md` is a **content contract, not a rendering
549
- spec** — you drew its storyboards yourself, but approval covered the story and content, not the
550
- sketch's geometry; how to interpret the `storyboard-canvas` blocks at author time (design
551
- hypothesis: reinterpret freely, never transcribe coordinates, block geometry, or block labels)
552
- is owned by `workflow/create.md` → Preconditions. **Generate concept mockups first — mandatory
553
- for everything authored from a plan, a single slide included (stage 4).** Before
554
- authoring from an approved plan, run `slidemind concepts <deck>` — the local-harness
555
- equivalent of the in-app manager's *unconditional* concept pass (`generateConceptImages` fires
556
- for every delegation carrying an approved plan). **Immediately after generation, Read
557
- every `decks/<slug>/concepts/concept-slide-NN.png` at full detail, before any engine or content
558
- search.** First list the directory and keep the literal repo-relative mapping in the task context:
559
- concept `NN` maps to `decks/<slug>/concepts/concept-slide-NN.png` and later to the `NN-*.jsx`
560
- slide. These workspace files are the durable source of truth across turns and compaction — never
561
- rely on an earlier rendered attachment. **The mockup is painted onto the layout's own chrome:
562
- the title, section label, footer and page marks you see are chrome that travels through the
563
- layout's props; everything else is the body and belongs in the layout's `[CONTENT]` slot**
564
- (its geometry is in the layout's `PLACEHOLDERS` metadata). Note each region's share of that
565
- area in percentages as you inspect. `slidemind concepts` seeded
566
- `decks/<slug>/asset-plan.md` as a form with one section per slide (`regions:` / `organisms:` /
567
- `connectors:` / `icons:`); **fill every row the moment you finish inspecting a
568
- mockup, before any slide is written** — one bullet per region, per organism, per arrow or line
569
- (`from → to, straight|elbow|curved, arrow end|both|none, solid|dashed`), per icon (subject,
570
- prominence, one engine query). The draft check COUNTS these rows: connectors listed but not drawn,
571
- an inventory left empty, and fetched assets no slide references each come back as an
572
- `[inventory:warn]`. (If the form is missing — an older add-in — write it in that shape yourself.)
573
-
574
- Chat context is evicted when the conversation is summarized; this file is not. Every icon
575
- decision you make only in your head is lost at the next compaction — the file is the contract
576
- step 2 executes and step 3 authors from. Append the fetched filename to each icon row
577
- (`… — assets/engine-<id>-<n>.svg`) as downloads land, so the file always shows what is still
578
- missing. This first pass is
579
- deliberately deck-wide and search-oriented; it is not the fresh authoring read required in
580
- step 3. Rebuild each mockup under your constraints
581
- — the rebuild rule is owned by
582
- `workflow/create.md` → Preconditions (reproduce the mockup's composition, hierarchy, graphic
583
- mechanism, AND granularity — its organism count, badges, satellites, and annotation layers are
584
- part of the target, and restraint is a colour budget, never an element budget; texts follow the
585
- story). It never hard-fails: if it produces no mockups (exit 0 — the add-in can't generate them)
586
- author from the storyboards alone. Skip it only for targeted work on slides that **already
587
- exist** — an edit or a rework.
588
- When storyboard objects share a `visualFamily`, rebuild those mockups as one recognizable visual
589
- series. The lowest-numbered member is the anchor. Preserve its shape vocabulary, framing,
590
- hierarchy, annotation style, illustration treatment, and spatial rhythm across the family, but
591
- adapt every member's element count, sizing, arrangement, labels, emphasis, and connections to its
592
- own complete `keyMessage`, `contentNotes`, role, and structure. Never copy another member's text,
593
- claims, or data, never force its exact geometry, and never omit approved content because it does
594
- not fit the anchor composition.
595
- 2. **Execute `asset-plan.md` — search and fetch every unchecked item.** Discover the available
596
- image engines by listing them — `slidemind ls engines --subtype image` (no PowerPoint window
597
- needed where the add-in serves the pane-free engine routes) — judge which engine fits from its
598
- label and description, then run every query in `asset-plan.md` and fetch the picks.
599
- (`slidemind search` without `--engine` picks an image engine the same way.) Listing the engines
600
- is discovery, not sourcing: this step is done only when every `asset-plan.md` item is checked
601
- off with a downloaded filename or marked `(no result)` after its search actually ran. Four
602
- mechanics that waste rounds when gotten wrong:
603
- - **Icon results have no preview — the download is the preview.** Pick from the `search`
604
- output's titles/scores, `download-result` the picks (it prints each asset's size + recolor
605
- info), judge from the saved file, re-search once if it was wrong. At most two search rounds
606
- per need; two failed downloads = mark it `(no result)` and move on. (`view-slide` is for
607
- slide-library results only.)
608
- - **Batch the downloads:** one `download-result --search <id> --pick <n,n,…>` per search id —
609
- never one call per icon.
610
- - **Quote hex colors:** `--icon-color "#<hex>"` (a value resolved from a corporate-design.css token) — an unquoted `#` makes the shell drop the
611
- rest of the line.
612
- - Searches come **from the file, after the concept pass** — never from plan nouns before the
613
- concepts exist. The engine
614
- search/reuse mechanics live in **`slidemind-search`** — use it to find and fetch imagery; the
615
- create-only detail — sizing a fetched asset's box and recolouring an icon — is in *Placing engine
616
- imagery* below. To pull in an **existing whole slide** (not just an image), use
617
- `slidemind-search`'s `add-slide` — it folds the slide into `decks/<slug>/slides/` as a native
618
- `.pptx` that coexists with your JSX in play order and survives re-push. The slide can come from
619
- an engine search **or** from a local `.pptx` on disk (`add-slide --from <file.pptx> --pick <n>
620
- --deck <slug>`, host-free); both fold in identically — see `slidemind-search`.
621
- 3. **Frame slides from the plan.** A storyboard with `role: frame` gets no default concept mockup. Author its required text, images and composition according to its actual layout capabilities; source required assets even if the asset-plan section carries a frame marker. Covers go first, closing last, dividers before their sections. Run the normal fit and rendered checks.
622
- 4. **Reopen the concepts, then author in small batches.** Once the searches and asset downloads are
623
- complete, split a concept-seeded deck into batches of at most **3 slides**. For each batch, first
624
- Read its matching anchored `decks/<slug>/concepts/concept-slide-NN.png` files together at full
625
- detail; as the **very next tool action**, create those slides'
626
- `decks/<slug>/slides/NN-<topic>.jsx` files. Put no search, command, reference read, user exchange,
627
- or unrelated work between the concept images and the JSX write.
628
- The deck-wide discovery read in step 1 never counts as this authoring read. A user interruption,
629
- resumed turn, compaction, long wait, or unrelated tool work invalidates an earlier authoring read:
630
- re-list `decks/<slug>/concepts/` if needed and reopen the affected anchored files before writing.
631
- This batching is a local-harness context discipline, not a second create pass: the whole deck
632
- remains one create pass and every slide file is created exactly once. Use a zero-padded numeric
633
- prefix from the first file on (play order is filename order here; see the slide-file row in the
634
- command mapping), one default export per slide, and one bundle layout (Mode A) or blank-content
635
- layout with freeform children (Mode B), exactly as the bundle docs prescribe. **A slide whose
636
- `asset-plan.md` section lists downloaded assets is UNFINISHED until its jsx references them**
637
- (`<img src="./assets/engine-….svg">`, sized per *Placing engine imagery* below) — a concept full
638
- of pictograms rendered as bare text boxes is a failed rebuild, not a style choice.
639
- 4. **Look at your own draft first (you, the agent).** This is the **draft check** in
640
- `workflow/build-and-export.md` — your pre-check, *before* any human sees the deck. Two rules
641
- moved early on purpose — do them NOW, not at the review gate when the run is long and attention
642
- is spent: `slidemind view-draft` lints every slide before it renders, so fix every `[lint:warn]`
643
- it prints (a mechanical pass on files you just wrote — `--fix` applies the deterministic ones);
644
- and after any fix round below, one more `slidemind
645
- view-draft` over the changed slides is mandatory — the verification must appear in your command
646
- sequence, not only in prose. Run `slidemind view-draft <deck>`: it renders each authored `slides/*.jsx` to a per-slide PNG and hands the
647
- images back to you — **nothing is pushed, no `.pptx` is written, no review gate opens** — and
648
- runs the captured slides through the server's export gate (slot-fit, diagram geometry,
649
- connector endpoints) so the errors `build-pptx` would stop on surface HERE, before the review,
650
- not as a 422 after the user approved (skipped with a note when the backend is unreachable;
651
- `--lint-only` for a fast lint loop, `--json` for a payload whose `reviewCanOpen` says whether
652
- the gate will open). Two things come back, and both bind:
653
- - **Measured lines** under each slide — `[fill:warn]` (a stretched region whose organisms pool
654
- at its top, with the region and the dead band) and `[inventory:warn]` (connectors listed in
655
- `asset-plan.md` but not drawn — counted per route kind too, so five `curved` rows drawn as
656
- elbows warn even when the total matches; an empty inventory, a fetched asset no slide
657
- references) —
658
- and a closing `DRAFT CHECK: N measured defects` line. Fix every one in the JSX and re-run;
659
- the review gate refuses to open while they stand for an unchanged slide. A fill band is
660
- fixed by distributing the organisms (`grid-template-rows` with one track per organism,
661
- `justify-content: space-between`, a figure that grows), never by deleting content.
662
- - **The pair**: for every concept-seeded slide, Read its anchored
663
- `decks/<slug>/concepts/concept-slide-NN.png` and matching
664
- `decks/<slug>/.draft-preview/<slide-basename>.png` **together in the same visual inspection**,
665
- in batches of at most 3 pairs, and compare **region by region**: same organisms at the
666
- same relative positions and shares, every connector present, no region emptier than in the
667
- concept, nothing clipped, overlapping, or buried. A loop, a hub, a flywheel, a timeline in the
668
- concept that became a row of cards in the render is a failed rebuild, not a simplification —
669
- re-express the mechanism. Under the slide's section in `asset-plan.md` write `draft-check:` and
670
- then one tick line per `organisms:` row: `- [x] <organism>` when it is in the render at the
671
- concept's position and share, `- [ ] <organism> — <what differs>` when it is not. A bare
672
- `matches` is not a verdict; the review gate refuses to open while any concept-seeded slide
673
- has fewer ticks than organisms or a `[ ]` standing. A draft-only inspection does not satisfy
674
- this check. The measured lines also include `[type:warn]` — most of the text one rung below
675
- `--fs-body` next to free space; fix by raising the ramp, never by shrinking type to fit.
676
- Fix anything wrong **in the JSX** (re-express, never delete), render again, and reopen the
677
- affected concept/draft pairs until each slide matches its image and the measured line reads
678
- zero. Do not open the review gate from a summary or a memory of an earlier look. It runs
679
- locally against the materialized bundle, so it needs no awake pane and no open host once the
680
- bundle has been downloaded once. Two faithful limits to know: a slide on a **purpose-built (Mode
681
- A) layout** (cover/divider/agenda) and a **reused native `.pptx`** slide have no freeform region
682
- to capture, so they come back as a status line, not an image — judge those at the full-deck
683
- `review` step below. Do this self-check before the human review gate; don't push a draft
684
- you haven't looked at.
685
- 5. **The review gate — the moment the deck builds clean.** This is the **review gate** in
686
- `workflow/build-and-export.md`; the CLI's gate command is `slidemind review <deck>`. Run it the
687
- instant the authored set builds clean — before any deliver, without asking whether the user wants
688
- a review. It builds the HTML preview first (the same lint the render enforces, so a gate that
689
- *opens* is a clean build; while lint errors remain it exits non-zero — fix and re-run), then
690
- opens the browser with a spatial comment overlay and **blocks until the user decides** (host-free
691
- — no open PowerPoint needed for the gate). Announce it per *Two UX rules*: tell the user the
692
- browser opened and give the clickable gate URL. **Blocking is the point: give the shell call a
693
- generous timeout (the gate waits up to 30 min) and let it sit — a long quiet wait means the user
694
- is reviewing, not that something hung. Never cancel it; if your harness kills the call early,
695
- just re-run it (the user's open tab reconnects).** The verdict prints to stdout:
696
- - `DECISION: approved` → proceed to the deliver the user chose at intake: `slidemind push <deck>`
697
- (into PowerPoint) or `slidemind build-pptx <deck>` (to a file).
698
- - `DECISION: comments` → the user left spatially-anchored notes, each citing a
699
- `slides/<file>.jsx:line:col`, the source line, the click position, and a **round tag** (`[2,
700
- round 1] …`) — plus a readonly-layout note where the click landed on a layout slot. A pin
701
- carrying an *older* round was dropped on the previous render, so read the file before you edit
702
- it rather than trusting the cited line blindly. **Edit the cited files in place at the given
703
- line and re-run `slidemind review <deck>` in the same turn.** **Expect several consecutive
704
- `DECISION: comments` rounds — that is the normal shape of a review, not an error.** The user's
705
- tab waits while you fix (browsing stays live, pinning is off) and refreshes with your next run,
706
- which blocks until they send the next batch of pins or approve. So never end your turn on a
707
- comments round, never claim to be "polling", and never send the user back to the browser
708
- between rounds — nothing reaches them until the gate runs again. Addressed pins come back as read-only ghost pins so the user can
709
- confirm each note was worked in. Only `DECISION: approved` or `DECISION: pending` ends the
710
- loop. Nothing is exported on a comments round. **Every round is persisted verbatim in
711
- `<deck>/review.json`** — if your shell capture of the gate's output was truncated or lost
712
- (backgrounded command, clipped scrollback), read that file for the complete comment list; never
713
- guess at missing comments or ask the user to re-type them.
714
- - `DECISION: pending` → the gate timed out with no answer (the user stepped away). Not approval,
715
- not rejection — **do not deliver**. Wrap up your turn: tell the user the preview is still
716
- waiting for their review and that on their go-ahead you'll re-run `slidemind review <deck>`
717
- (their tab reconnects).
718
-
719
- `slidemind review` is the only step that pauses; `push`/`build-pptx` never pause — they render
720
- pane-free (local capture + server-side assembly, with live per-slide progress). **CLI exports
721
- happen out of the user's sight, so the flow invariant — *the user sees every change before the
722
- task is done* — makes re-review mandatory here: every deliver is preceded by an approved review
723
- of exactly what it delivers. After any later slide change, the deck re-enters `slidemind review`
724
- before it can be pushed or exported again — never deliver an unreviewed change.** If several
725
- presentations are open, confirm **which one to push into** first (it can differ from the design
726
- source `slidemind ready` locked in). After approval, run the push without asking; it works while
727
- PowerPoint is backgrounded, and the CLI itself waits + retries if the pane is needed (see *First
728
- step* above). If a push still times out, the rendered `.pptx` is saved next to the deck — re-run
729
- `push` after the user clicks the pane, without rebuilding.
730
-
731
- **On a clean approve + deliver, the task is done.** Report what landed (slide count + target) and
732
- stop — no sanity pass, no re-verification. The visual QA already happened at the draft check
733
- (step 4) and the user signed off at the review gate.
734
-
735
- ## Manual PowerPoint edits (the reconcile loop)
736
-
737
- The user may have edited the deck directly in PowerPoint since your last deliver — moved a shape,
738
- retyped a line, recoloured a box. Those edits live only in that file or that window; the deck's jsx
739
- knows nothing about them. `slidemind build-pptx` and `slidemind push --replace` therefore check
740
- before they write, and play the changes back to you:
741
-
742
- - **Plain text edits are already folded into your jsx** — the command prints `note: folded N manual
743
- text edit(s) … into slides/<file>` and the fold is now the source of truth on disk. **Re-read that
744
- file before your next edit** or you will write over it from a stale copy.
745
- - **Everything else refuses the deliver** with a `RECONCILE REQUIRED` report per slide (geometry in
746
- EMU, style changes, added/removed shapes) and exit code non-zero. Nothing was written or pushed.
747
-
748
- On a `RECONCILE REQUIRED`:
749
-
750
- 1. **Fold every listed change into the slide's jsx** — the user made them on purpose; losing them is
751
- unacceptable. Translate geometry deltas into **layout intent** (spacing, order, relative sizing,
752
- which region a thing sits in) — never literal offsets, absolute coordinates, or
753
- transform/translate hacks bolted onto a working composition. Recreate added shapes as jsx
754
- elements; drop deleted ones. If a folded position genuinely cannot fit the content area,
755
- re-express its intent (reflow, reorder, resize) rather than discarding it.
756
- 2. Lines marked `[preserved]` are foreign add-in content (e.g. an embedded chart) — do **not**
757
- recreate them; they are spliced back into the rendered slide automatically.
758
- 3. **Re-run the same command.** The re-run proceeds: the report was acknowledged
759
- (`decks/<slug>/.reconcile-ack.json`), and only a NEW manual edit re-arms the check. The deck
760
- changed, so the flow invariant applies — re-run `slidemind review <deck>` before delivering
761
- again.
762
- 4. **Do this silently.** Reconcile is bookkeeping, not a deliverable: never explain the report, the
763
- baseline, or your folding steps, and never ask the user about it. Fold and carry on with their
764
- actual request in the same turn. At most one short clause in your final answer ("kept your manual
765
- layout change").
766
-
767
- `--force` on either command **discards the user's manual edits** and writes anyway. It is a last
768
- resort, only on the user's explicit say-so — never reach for it to get past a report you could fold.
769
-
770
- Three refusals are not foldable and need the user, not a retry:
771
-
772
- - `the live deck contains N slide(s) not in this deck` — a whole-deck replace would delete slides
773
- someone added by hand or with another tool. Push **without** `--replace` to insert instead, or ask
774
- the user what should happen to them.
775
- - `<file> was edited in PowerPoint …` naming slides with no jsx behind them (a reused native slide,
776
- or one pushed by another deck) — build to a different target with `--out <other file>` so their
777
- edits survive, or ask.
778
- - `backend does not support manual-edit reconcile` / `the live deck could not be inspected` — the
779
- add-in is older than this contract, or its PowerPoint build cannot export slides. Tell the user to
780
- update the slidemind add-in. Do not paper over it with `--force`.
781
-
782
- ## Charts (create-authoring specifics)
783
-
784
- A real series of numbers is a `<Chart>` element in your JSX — one self-closing element that renders
785
- as a native PowerPoint chart with its own embedded workbook, so the client double-clicks it and
786
- edits the data in Excel. Never hand-draw a chart from divs, bars, lines or SVG, and never let a
787
- table stand in for one; conceptual figures (process, framework, hub, timeline with no measured
788
- values) are not charts and stay HTML/SVG. The type list, the props each type accepts, the
789
- theme-first colour rule (leave `seriesStyle` off and the brand paints it) and the kinds that are
790
- out of the model live in the bundle's `workflow/authoring.md` → Charts — read them there, don't
791
- guess; the composition rule (one chart is the hero; the accent marks ONE series or point, not six)
792
- is in `workflow/composition.md` → Charts in the composition. Three local-harness facts: numbers the
793
- user states in chat go straight into the chart's `data` prop; this harness has **no analyst
794
- subagent**, so when the numbers live in a file you do the aggregation yourself, say what you did,
795
- and put the RESULT in the props (the deck carries the numbers, never a pointer to your workspace);
796
- and both the HTML preview and `slidemind view-draft` paint a **stand-in** for a chart, not
797
- PowerPoint's render — judge a chart's final look from the pushed slide (the review gate warns the
798
- user on chart slides itself). Editing a chart later — yours, or one on a slide
799
- the deck adopted from PowerPoint — is editing its `<Chart>` props and re-rendering; an adopted
800
- chart keeps its `data-sm-source-id` and its `conversions/<stem>.slide.pptx` (never delete either:
801
- the push patches the client's own chart part through them, so its Excel data and styling
802
- survive). To see what a chart on a live slide plots, `slidemind read <presId> --mode raw` prints a
803
- data table per chart; `slidemind read <file.pptx>` (host-free) reports text only, no chart data.
804
-
805
- ## Placing engine imagery (create-authoring specifics)
806
-
807
- Finding and fetching engine imagery is `slidemind-search`'s job (`slidemind search` → `slidemind
808
- download-result`). What follows is **create-only**: how to size and colour a fetched asset so it
809
- reads on-brand in your JSX, honoured in both the local draft preview and the render.
810
-
811
- Engine results land as files referenced with `<img src="./assets/<file>">`. These facts are specific
812
- to the local harness (the bundle's `workflow/*.md` stay harness-neutral):
813
-
814
- - **Size the box from the asset's own dimensions.** Both `slidemind search` (from the engine index,
815
- before any fetch) and `slidemind download-result` (measured from the delivered bytes) print each
816
- image's intrinsic `width×height`. **Use it.** A plain `<img>` is stretched to whatever box you
817
- write, so a box whose aspect ratio disagrees with the asset ships a distorted picture. Derive one
818
- side from your layout and compute the other from the printed ratio. `object-fit: contain`/`cover`
819
- is honoured in the render as well as the preview, but it is a *fallback*, not a substitute: it
820
- converts a wrong ratio into letterboxing or a crop, both of which you chose blind. When the size
821
- prints as `(size unknown)`, the format carried no readable header — give the asset a square-ish
822
- box and check it at the draft check.
823
- - **Never open the SVG to find out whether it recolours.** `slidemind download-result` prints a
824
- `recolor` descriptor for each asset — `{ recolorable, mode, applied, note }`, where `mode` is
825
- `currentColor`, `mono`, `multicolor`, or `raster`. Read it; that *is* the answer.
826
- - **Two ways to colour an icon, both honoured in the local draft preview *and* the render:**
827
- - **Bake it in (prefer this):** pass `--icon-color <hex>` — a hex you resolve from a token in the
828
- bundle's `corporate-design.css` — to `slidemind download-result`. Works for any `recolorable`
829
- glyph and the colour is in the saved file, so preview and render always agree. The tint is
830
- applied by the add-in, so on the window-free path it can be **refused**: the asset is then saved
831
- in its original colours and the `recolor` note says so. Believe the note over your request — to
832
- actually bake the colour in, re-run the search and the download with `--to <presId>` against an
833
- open PowerPoint window.
834
- - **Tint via CSS:** set `color` to a token on the `<img>`. This works only for `mode:
835
- "currentColor"` icons (the preview inlines the SVG so `color` resolves, and the render
836
- substitutes `currentColor`). A `mono` icon will not respond to CSS colour — bake it instead.
837
- - **Batch the fetch.** Pull every icon a slide needs in one call — `slidemind download-result
838
- --search <id> --pick <n,n,…> --deck <deck> [--icon-color <hex,hex,…>]` (one colour applies to all
839
- picks, or give one per pick; add `--to <presId>` only on an add-in that still relays the fetch
840
- through a pane, which the `search` output names) — the downloads run concurrently. Don't run
841
- `download-result` once per icon.
842
-
843
- ## Command mapping (the workflow vocabulary ⇄ your CLI)
844
-
845
- The bundle's `workflow/*.md` speak the harness-neutral verbs defined in `workflow/flow.md` →
846
- Vocabulary. You are the local harness — this is your mapping:
847
-
848
- | Verb (`workflow/flow.md`) | Your equivalent (local harness) |
254
+ The procedure is `<bundle>/workflow/create.md`; this is how its steps run over the CLI.
255
+
256
+ 1. **Concepts.** `slidemind concepts <deck>`: one mockup per body slide (frame slides none by
257
+ default); existing mockups are kept (`--force` remakes); `--status` says whether a run is in
258
+ progress — never start a second. The anchors are `concepts/concept-slide-NN.png` on disk, never
259
+ an image from earlier in the chat. No mockups (exit 0: the add-in can't make them) → author from
260
+ the storyboards; for new slides the attempt is never optional.
261
+ 2. **Transcribe.** `slidemind transcribe <deck>` reads each mockup's spec (a machine intermediate
262
+ in `state/concept-specs/` — never edit it, and keep no inventory of your own), writes the JSX on
263
+ the type ramp with native line directives, settles geometry and fetches the assets the specs
264
+ name. Read every note it prints: missing specs, unresolved assets, unreadable charts, layout
265
+ fallbacks. After `[specs:warning] NO CONCEPT SPECS` from `concepts` (`--json`:
266
+ `specsUnsupported`), `transcribe` refuses (`concept_specs_unsupported`) and re-running won't
267
+ help: build each named slide from its PNG by hand — count its cards, connectors, icons, bands and
268
+ numbers first, then build every one — and say in your handover that they were not transcribed.
269
+ 3. **Resolve the rest** (`create.md` steps 2–3): unresolved assets via `slidemind-search`, charts
270
+ checked against the approved data, frame slides from their plan.
271
+ 4. **Compare and repair** (`create.md` step 4 incl. its connector checklist, *Execute, don't
272
+ trace*, *Content checks*). Run `view-draft`, open each concept PNG with its
273
+ `preview/draft/<slide>.png` in one look, and patch the smallest wrong region of the JSX — the
274
+ only editable artifact. Geometry was settled by `transcribe`: fix what you see and draft again,
275
+ never re-settle in a create. Advisories never hold but each names a difference to check;
276
+ errors and measured package defects must be fixed (`create.md` step 6 lists both), and nothing
277
+ bypasses them. Draft-check the full deck before review. Your final message names the painting defects you corrected and any concept element you
278
+ could not build.
279
+ 5. **Review** — `slidemind review <deck>` the instant the deck builds clean, without asking. It
280
+ builds the HTML preview (non-zero while lint errors remain), refuses while measured defects
281
+ stand, then asks. Comments cite `slides/<file>.jsx:line:col`, the source line, the click and a
282
+ round (`[2, round 1] …`); a pin from an older round was dropped on the previous render, so read
283
+ the file before trusting its line. Edit the cited files in place, `view-draft --only` them (review
284
+ refuses a slide edited since its last draft check), then run `review` again. Every
285
+ round is saved in `state/review.json` — read it if your capture was cut off; never guess a
286
+ comment or ask for it again.
287
+
288
+ **The review is one-time per deck** (`workflow/flow.md` → *Invariants*): edits, comments on the
289
+ delivered deck, reconcile folds, repairs and new slides go `view-draft` → deliver, never back through
290
+ `review` unless the user asks to see the preview. `build-pptx` and `push` never
291
+ pause; a `push` that finds no window saves the rendered `.pptx` next to the deck (`fallbackFile`) —
292
+ re-run it once the user clicked the pane, without rebuilding.
293
+
294
+ **Repair (the explicit settle)** — only when the user asked to fix the spacing, overlap or fit of
295
+ transcribed slides: `slidemind revision begin <deck> --operation repair --slides <sel>`,
296
+ `slidemind transcribe <deck> --repair`, `view-draft --only NN`, then look at the whole slide
297
+ (neighbours can move). The recorded scope authorizes it (a `targeted-edit` scope is refused) and it
298
+ runs the whole scope — `--only` cannot carve a subset, so scope with `--slides`. It moves elements a
299
+ few slot-px and changes no text, asset, element count or connector endpoint; it refuses converted
300
+ source and slides with no transcription record, and needs no plan.
301
+ `transcribe --force --discard-edits` throws edited source away — only for an intended reset.
302
+
303
+ ## Charts and engine imagery
304
+
305
+ **Charts** are `<Chart>` elements (`workflow/authoring.md` → Charts; `workflow/composition.md` →
306
+ Charts in the composition). Numbers the user states go straight into `data`; there is no analyst
307
+ subagent, so a figure from the user's file comes from a script you run over that file, never from
308
+ your head (`workflow/plan.md`): say what you computed and put the result in the props. The preview and `view-draft` paint a stand-in — judge a chart in the built file. An adopted
309
+ chart keeps its `data-sm-source-id` and `conversions/<stem>.slide.pptx` (never delete either;
310
+ delivery patches the client's chart through them). `slidemind read <presId> --mode raw` prints a
311
+ live chart's data; `read <file.pptx>` gives text only.
312
+
313
+ **Engine imagery** is found and fetched with the `slidemind-search` skill; sizing is
314
+ `workflow/authoring.md` → Icons and imagery. Over the CLI:
315
+
316
+ - `search` and `download-result` print each image's `width×height`; `(size unknown)` → a square-ish
317
+ `contain` box, checked at the draft check.
318
+ - `download-result` prints a `recolor` descriptor per asset (`recolorable`, `mode` — one of
319
+ `currentColor`, `mono`, `multicolor`, `raster` — `applied`, `note`): read it, never the SVG.
320
+ - Bake a colour in with `--icon-color <hex>` (a hex from a `corporate-design.css` token).
321
+ Window-free, the add-in may refuse the tint and the `note` says so — believe it; to bake it
322
+ anyway, re-run search and download with `--to <presId>` against an open window. CSS `color` on the
323
+ `<img>` tints only `mode: currentColor`.
324
+ - Fetch a slide's picks in one call:
325
+ `download-result --search <id> --pick <n,n,…> --deck <deck> [--icon-color <hex,…>]` (one colour,
326
+ or one per pick); `--to <presId>` only when `search` says the fetch relays through a pane.
327
+ - `slidemind imagen "<prompt>" --deck <deck> [--out <name.png>] [--size <size>] [--quality <tier>]`
328
+ only for a planned photograph or illustration no engine could supply — never a pictogram, never
329
+ in place of the user's image.
330
+
331
+ ## Editing slides that already exist
332
+
333
+ The rules — operations, editable slides, converted source, identity — are
334
+ `<bundle>/workflow/edit.md`. Over the CLI:
335
+
336
+ 1. **Name the slide by its file, never its position.** Slides are `slides/*.jsx` in filename order;
337
+ resolve "slide 4" to its file once. `--slides <sel>` takes a stem (`04-pricing`), number or range
338
+ and binds the durable id at once, so a reorder cannot move your scope.
339
+ 2. **Make it JSX first**, only for slides the user asked to change and before `revision begin`: a
340
+ foreign `.pptx` slide via `slidemind adopt <file.pptx> --deck <deck> --slides <n>`; a reused
341
+ `slides/NN-reused-*.pptx` via `slidemind adopt <deck>/.slidemind/slides/<NN-reused-…>.pptx --in-place`.
342
+ Slides you never name stay native, with notes, comments, animations and embeddings.
343
+ 3. **Open the operation** (`edit.md` → *What the request authorizes*):
344
+ `slidemind revision begin <deck> --operation targeted-edit|redesign|repair --slides <sel> --json`
345
+ (`--operation` always needs `--slides`). A requested redesign is authorized — don't ask again. A
346
+ removal the user asked for goes in `--scope <file.json>` (the elements and properties the edit
347
+ may touch). Changing a slide outside the scope (a `-2.jsx` sibling included) or dropping an
348
+ import's `// SLIDEMIND_DIALECT: converted` line outside a redesign is refused by the next
349
+ `view-draft`, `build-pptx` or `push`: undo it and change the target itself.
350
+ 4. **Re-read `slides/<file>.jsx` from disk, then patch it** — a manual edit may have been folded
351
+ in. Adding and restructuring supported content is allowed, not only words.
352
+ 5. **`view-draft --only <n>`, then deliver** onto the same slide (`build-pptx` re-renders only what
353
+ changed). No review gate, no confirmation question of your own.
354
+
355
+ **Preservation.** Every slide records the elements that must survive it — from its first
356
+ `view-draft` on, or earlier when `adopt`, `revision begin` or a repair captured it; it applies
357
+ without anyone opening a session.
358
+ `view-draft` prints `[preserve:warn] <slide> — <element id> …` with the repair — a measured
359
+ defect, so `review`, `build-pptx` and `push` refuse while it stands. `[preserve:error]` means
360
+ the record itself cannot be read: delivery refuses, and the file is not yours to edit — tell the user.
361
+ What no draft can answer is settled at delivery: it refuses only on a slide that can be proved (an
362
+ adopted one whose import the deck holds); a slide authored from scratch ships with that limitation
363
+ named. Fix what a warn names; never delete a record or rebuild a slide to quiet a line, and never present the add-in as a
364
+ way around a CLI refusal.
365
+
366
+ **Limits to state, not work around:** a preserved native object (SmartArt, OLE, an unmodelled chart)
367
+ moves but can't be edited inside. `export_incomplete` means the pane could only hand back the saved
368
+ file: ask the user to **save the presentation** and re-run (`--force` discards their manual edits —
369
+ only if they say those don't matter).
370
+
371
+ **An adopted deck** (`slidemind adopt` of the user's own `.pptx`) needs no plan and no review; its
372
+ edits run in a session, because its base is a real file:
373
+
374
+ 1. `slidemind revision begin <deck>` once, then `export SLIDEMIND_OWNER=<printed token>` so nested
375
+ commands and parallel lanes re-enter it. `adopt … --slides <n,m>` hydrates more slides on demand.
376
+ 2. Edit, `view-draft`, then `build-pptx`: it writes an immutable **candidate** of the changed
377
+ slides on the accepted base — building twice keeps the first edit.
378
+ 3. `slidemind revision accept <deck> --candidate <id>` makes it the accepted base, locally and
379
+ nothing more (a remote deck publishes instead). `slidemind revision finish <deck>` ends the
380
+ session.
381
+
382
+ `slidemind revision status <deck>` answers "where am I?". A **newer copy of the same file**:
383
+ `slidemind rebase <deck> --incoming <file.pptx> --dry-run` first. Their edits, adds, deletes and
384
+ moves apply, reorders combine, your unpublished edits stay; only a slide both sides changed stops
385
+ and writes a resolution file for the user. There is no force flag.
386
+
387
+ ## Remote decks (SharePoint)
388
+
389
+ The user never pulls, publishes or uploads by hand: a deck that touches SharePoint is delivered *to*
390
+ SharePoint, never as a local path. Any one signal makes it remote:
391
+
392
+ - a **file link** (`…/:p:/…`, `/sites/…/name.pptx`) → the deck IS that file:
393
+ `slidemind open <link> --deck <deck>` instead of `adopt` (a local path given to `open` adopts
394
+ only).
395
+ - a **folder link** (`…/:f:/…`) → the normal create flow, then `build-pptx` and
396
+ `slidemind publish <deck> --folder <link> --name <file>.pptx` (`<slug>.pptx` unless the user named
397
+ one — never ask). An existing name is refused; pick another.
398
+ - a **folder the user connected in the workspace** — any time, mid-build included. You need not
399
+ know: every `build-pptx` reads the deck's connection itself.
400
+ - `slidemind ready <deck>` prints a `remote:` line, or `build-pptx` prints a publish outcome.
401
+
402
+ **`build-pptx` publishes a connected deck itself**, right after the build, as `slidemind publish`
403
+ would: it pulls, reconciles, checks the final bytes and creates or replaces the file only if nobody
404
+ saved meanwhile (`revision accept` refuses a bound deck on purpose). Never follow it with a second
405
+ `publish`; `slidemind publish <deck>` only retries a build whose publish did not save (exit 2).
406
+
407
+ Every session, unprompted:
408
+
409
+ 1. `slidemind pull <deck>` before the first edit and after every pause (a gate, a summarization, a
410
+ new message). Newer saves merge in around your unpublished edits — read its `note:` lines and go
411
+ on. Only a slide you both changed stops it: show the user both versions (theirs staged, yours in
412
+ your working file), ask which to keep or what to combine, run the `slidemind rebase` it names,
413
+ fill the resolution file (`local`, `incoming`, or `merged` + your slide file) and re-run with
414
+ `--resolve`.
415
+ 2. `slidemind revision begin <deck>`, edit, `view-draft` — no review gate.
416
+ 3. `build-pptx` — it publishes; read its outcome as below.
417
+ 4. `needs_reconcile` is no error: rebuild — it publishes again (slides changed on both sides: settle
418
+ with the user first, as in step 1). Loop until `SAVED` — unless it says their save could not be
419
+ taken in (a missing pinned file, a failed check): tell the user what it names and stop.
420
+ 5. `slidemind revision finish <deck>`; hand over the SharePoint file (`webUrl` from `ready`).
421
+ `slidemind rename <deck> --name <file.pptx>` renames it without rendering.
422
+
423
+ Report publish literally, never upward: `SAVED` → in SharePoint, with the version it names;
424
+ `needs_reconcile` → someone saved first, nothing was overwritten, their changes are merged (or a
425
+ both-sides slide awaits their choice) and you rebuild; `pendingManualUpload` → **nothing was
426
+ written**, the files to upload by hand are listed; `UNKNOWN` → re-run publish, which inspects before
427
+ it writes; `not published (<reason>)` or `built, but not published` → nothing was uploaded, tell the
428
+ user why (the `.pptx` is local only). Never re-run a
429
+ publish to "make sure", and never offer to force, skip a gate or work around a missing extension.
430
+
431
+ ## Manual PowerPoint edits (reconcile)
432
+
433
+ `build-pptx` and `push --replace` check for edits the user made in PowerPoint since the last
434
+ delivery; how to fold them (layout intent, `[preserved]` lines, silently) is
435
+ `<bundle>/workflow/edit.md` → *Manual-edit reconcile*. Over the CLI:
436
+
437
+ - `note: folded N manual edit(s) (text, charts) … into slides/<file>` — already in your JSX;
438
+ re-read that file before the next edit.
439
+ - `RECONCILE REQUIRED` (non-zero; nothing written) lists geometry in EMU, style and added/removed
440
+ shapes per slide: fold each into the JSX and re-run the same command. It then proceeds
441
+ (`state/reconcile-ack.json`; only a new manual edit re-arms it), with no new review.
442
+ - `--force` discards the user's manual edits — only on their explicit say-so, never past a report
443
+ you could fold.
444
+
445
+ Four refusals need the user, not a retry: `the live deck contains N slide(s) not in this deck` →
446
+ push **without** `--replace`, or ask; `<file> was edited in PowerPoint …` for slides with no JSX
447
+ behind them → build with `--out <other file>`, or ask;
448
+ `backend does not support manual-edit reconcile` / `the live deck could not be inspected` → ask the
449
+ user to update the slidemind add-in, never `--force`; `converted slide(s) are not confirmed for
450
+ replacement` → name those slides to the user and add `--accept-conversions` only after they agree
451
+ (it overwrites their originals), or push without `--replace`.
452
+
453
+ ## Command mapping (workflow vocabulary ⇄ CLI)
454
+
455
+ The bundle's `workflow/*.md` speak the verbs of `workflow/flow.md` → Vocabulary:
456
+
457
+ | Verb | Command |
849
458
  |---|---|
850
- | (session setup — a CLI-only stage before the spine) | `slidemind ready [deck]` — the one-shot session start: connection ladder + design resolution (open window, the deck's own binding, or `--brand <presFP>`) + bundle materialize + deck bind. **Run it first, every session** (see *First step* above). `slidemind download-bundle` is the lower-level materialize-only command `ready` now covers — you rarely call it directly |
851
- | **track the stages** | your harness's task tracker — explicitly create the stage todo list before your first command and keep it current (see *Create a todo list* above) |
852
- | **clarify** / **plan sign-off** | intake stays in chat with the user (above); for every from-scratch request — one slide included — persist `decks/<slug>/plan.md` as `## Red thread` + `## Per-slide storyboards` (one `storyboard-canvas` JSON block per slide), then run `slidemind plan <deck>` — the same blocking `DECISION:` gate contract as `slidemind review`, on the plan (renders editable storyboards — red-thread strip + spatial canvases — plus slide-anchored comments; expect several comment rounds; loop until approved) |
853
- | concept mockups (mandatory for every from-scratch set, after plan sign-off) | `slidemind concepts <deck>` — renders one image mockup per approved-plan slide into the durable repo-relative path `decks/<slug>/concepts/concept-slide-NN.png`; immediately Read all of them for image/content search, then after searches reopen them in batches of at most 3 immediately before writing the matching `NN-*.jsx`. Re-list and reopen those paths after any interruption or continuation; never rely on an earlier chat image. The rebuild rule is owned by `workflow/create.md` → Preconditions. It never hard-fails: on an empty result (exit 0 — the add-in can't generate them) author from the storyboards alone, but for anything authored from a plan — one slide included — you always run it. Skip only for targeted work on slides that already exist (edit/rework) |
854
- | **read** / **list** the workspace | read the files from the materialized bundle dir (`<bundle>/…`) and your `decks/<slug>/` |
855
- | **create / update a slide file** | write `decks/<slug>/slides/NN-<topic>.jsx` on disk with a **zero-padded numeric prefix** (`01-cover.jsx`, `02-agenda.jsx`, …) — over the CLI, "the ordered set you hand to build & push" is expressed as **numeric-aware filename order**; there is no ordered-list channel, so reordering = renaming files. For a concept-seeded create or structural rewrite, the immediately preceding tool action must Read the matching anchored concept path(s) at full detail |
856
- | **draft check** | `slidemind view-draft <deck>` — lints every slide (fix each `[lint:warn]`; `--fix` applies the deterministic ones), then renders each `slides/*.jsx` to `decks/<slug>/.draft-preview/<slide-basename>.png` (clean, no overlays), prints the measured defects (`[fill:warn]`, `[inventory:warn]`, closing `DRAFT CHECK:` line) and returns the images to **you**; **no push, no `.pptx`, no review gate**. Read each concept/draft path pair together, fix the JSX, render, and pair again until the measured count is zero and the pairs match. A draft-only inspection does not count; `slidemind review` refuses to open while measured defects stand for an unchanged slide. Host-free once the bundle is materialized. Freeform slides only — purpose-built (Mode A) and reused native `.pptx` slides report as a status line (judge those at `review`/`build`). This is your self-check; `slidemind review` is the *human* gate |
857
- | **build & push** | `slidemind push <deck>` (into the open PowerPoint — the insert needs a window) · `slidemind build-pptx <deck> [--out <file>]` (to a `.pptx` file — **host-free** for a bound deck: no PowerPoint window at all) — deliver whichever target was locked at intake; both render server-side via the bridge and for a bound deck the render itself is pane-free |
858
- | **the review gate** | `slidemind review <deck>` — builds the HTML preview (lint-clean or it doesn't open), serves it with a spatial comment overlay and **blocks until the user decides**, then prints `DECISION: approved` or `DECISION: comments` (each comment cited to `slides/<file>.jsx:line:col` + the round it was dropped on). On approve → deliver (`slidemind push` / `build-pptx`); on comments → edit the cited files and re-run `slidemind review` in the same turn (addressed pins show as ghost pins); the user pins as many comments as they like and sends them as one batch (Approve is off while unsent pins exist); expect several comment rounds. CLI delivers happen out of the user's sight, so **every deliver follows an approved review of what it delivers — re-run `review` after any slide change**. `push`/`build-pptx` never pause; only `review` does. |
859
- | **inspect the deck** | `slidemind read [presId\|file.pptx] [--mode summary\|raw]` — one verb, two sources: pull the current content of an open presentation (a presId; **host-required** — it reads the live, possibly unsaved file) **or** read a local `.pptx` on disk (a file path; host-free — no PowerPoint, no pairing). Prefer the file path when the deck is saved. `summary` = per-slide outline; `raw` = each slide's plain text — to inspect what's there before editing. Plain text, not authoring markup |
860
- | **discover engines** (`list_engines`) | `slidemind ls engines [--type <collection\|search\|scope>] [--subtype <image\|slide\|template\|content>]` — the live catalog is the only engine list (the bundle carries none); pick an `id` from it, never guess one. Needs no PowerPoint window where the add-in serves the pane-free engine routes. It also lists **search scopes** for unfiltered corpus search — those belong to `slidemind-search`, not to imagery |
861
- | **engine search / fetch** | **`slidemind-search`** owns the engine search + reuse mechanics (`slidemind search` → `slidemind download-result`, plus whole-slide reuse via `add-slide`). For placing a fetched asset in your JSX, size its box from the printed `width×height`, pass `--icon-color` / batch with `--pick <n,n,…>` and colour per *Placing engine imagery* below |
862
- | **generate an image** | `slidemind imagen "<prompt>" --deck <deck> [--out <name.png>] [--size <size>] [--quality <tier>]` — use only for a planned photograph or illustration when engine sourcing returned nothing; never generate pictograms |
863
- | **see** a live slide | no CLI analog — once delivered, the user is looking at the result; your visual authority runs at the draft check and the review gate instead |
864
-
865
- Everything else in `workflow/*.md` — the composition craft, the substrate/authoring rules, the
866
- layout discovery and slot/working-area rules, the visual quality bar (applied at the draft check) —
867
- applies to you unchanged.
868
-
869
- ## The brand and the workflow both live in the bundle, not here
870
-
871
- Do not restate brand values (colour, type scale, spacing, layout names, accent discipline) or
872
- re-derive the authoring/composition craft in this file or in slide files — they are in the bundle's
873
- `design.md` and `workflow/*.md`. Read them and follow them. Don't load external UI/design-taste
874
- plugins during slide work; compose against the bundle's layouts and tokens. If the corporate design
875
- moves mid-task (`bundle_etag_stale`), the CLI self-heals: it refreshes the bundle and retries the
876
- render on its own — afterwards re-read the bundle's `design.md` before authoring anything new, since
877
- the rules may have changed.
878
-
879
- ## Failure modes the render lint can't catch
880
-
881
- Render-time lint rejects contract violations (unsupported CSS, bad imports, remote `<img>` URLs —
882
- the add-in's capability-table engine; `slidemind view-draft` runs the same engine locally from the
883
- bundle before it renders). It can't catch content-shaped failures; check for these **at the draft check** (step 4,
884
- before the review gate) — not after delivery:
885
-
886
- - Layout-default / placeholder text leaking through an unfilled prop.
887
- - A bullet list standing in for a structured idea (process, comparison, timeline).
888
- - An equal-card grid with no hero and no hierarchy.
889
- - Em dashes / curly quotes leaking from pasted source.
890
- - Hand-rolled glyphs instead of engine imagery.
891
- - Slide-local class names colliding with global token utility classes.
892
- - Internal composition vocabulary (`hero`, `focal`, …) rendered as visible text.
459
+ | (session setup, CLI-only) | `slidemind ready [deck]` — first, every session (it covers `download-bundle`) |
460
+ | **track the stages** | your harness's task tracker (*Stage todo list*) |
461
+ | **clarify** / **plan sign-off** | chat, `plan.md`, `slidemind plan <deck>` (*Intake → plan*) |
462
+ | concept mockups + preparation | `slidemind concepts <deck>` → `slidemind transcribe <deck>` |
463
+ | **read** / **list** the workspace | the files under `<bundle>/` and `decks/<slug>/.slidemind/` |
464
+ | **create / update a slide file** | write `decks/<slug>/.slidemind/slides/NN-<topic>.jsx`, zero-padded (`01-cover.jsx`, …). Play order is numeric filename order — no ordered-list channel, so reordering means renaming. For a concept-seeded create or structural rewrite, Read the concept PNG at full detail right before the write |
465
+ | **draft check** | `slidemind view-draft <deck> [--only NN]` — lint (errors block; deterministic fixes run), render to `preview/draft/`, the measured defects, the closing `DRAFT CHECK:` line. No push, no `.pptx`. Layout-only and reused native slides report a status line — judge those in the build |
466
+ | **the review gate** | `slidemind review <deck>` (*The create flow*, step 5) |
467
+ | **build & push** | `slidemind build-pptx <deck> [--out <file>]` always (it publishes a SharePoint-connected deck itself); `slidemind push <deck>` / `slidemind publish <deck>` only when asked for |
468
+ | **inspect the deck** | `slidemind read <presId\|file.pptx> [--mode summary\|raw]` — a presId reads the open (unsaved) presentation and needs its window; a saved file reads host-free (prefer it) |
469
+ | **discover image engines** | `slidemind ls engines [--type …] [--subtype image\|slide\|…]` — pick an `id` from it, never guess |
470
+ | **engine search / fetch** | the `slidemind-search` skill; placement per *Charts and engine imagery* |
471
+ | **generate an image** | `slidemind imagen` (*Charts and engine imagery*) |
472
+ | **see** a live slide | open that slide's PNG in the directory `build-pptx` prints (its line says whether the PNGs show the exported `.pptx` or the browser source) |
893
473
 
894
474
  ## Where the deck lives
895
475
 
896
- `decks/<slug>/` is created in the **current working directory** (the shell's pwd when the skill was
897
- invoked). Every `slidemind` command and `mkdir` resolves `decks/` against that cwd — don't `cd` into
898
- the skill's install directory. The materialized bundle lives in the cache dir above, not under the
899
- deck.
476
+ `decks/<slug>/` is created in the current working directory; every command resolves `decks/` there —
477
+ don't `cd` into the skill's folder. **A path the user names is input, never the deck folder:** read
478
+ a briefing, RFP or reference deck where it is and copy what the deck needs into
479
+ `.slidemind/assets/`. Your sandbox writes only under your working folder; work on a deck elsewhere
480
+ only when the user explicitly asks (expect permission prompts).
481
+
482
+ ```
483
+ decks/<slug>/
484
+ <slug>.pptx the built deck
485
+ plan.html the saved plan page (read-only; `slidemind plan <deck>` opens it to edit)
486
+ .slidemind/ plan.md · slides/ assets/ conversions/ (what the render reads) · concepts/ ·
487
+ state/ (bundle-ref, plan-review, review, draft-check, reconcile-ack, concept-specs/) ·
488
+ preview/ (regenerable)
489
+ ```
490
+
491
+ Commands take the deck **directory**; a deck without `.slidemind/` is used as it stands. Write
492
+ nothing at the deck root. `slidemind clean <slug>` drops only `preview/` and abandoned downloads.
493
+ `plan.html` has one owner (`state/plan-owner.json`): this flow re-renders it on every `plan.md`
494
+ write; on a deck an extension owns, `slidemind plan` leaves it alone and prints the command that
495
+ opens it — never hand-write it. The bundle lives in the cache
496
+ (`${XDG_CACHE_HOME:-~/.cache}/slidemind/bundles/<presFP>/`), not the deck; read
497
+ `assets/brand-images.md` from there when a workflow doc names it.