slidemind 0.3.4 → 0.3.5
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.
- package/.agents/plugins/marketplace.json +2 -0
- package/.claude-plugin/plugin.json +1 -1
- package/.codex-plugin/plugin.json +1 -1
- package/bin/slidemind.mjs +65 -2
- package/package.json +1 -1
- package/skills/create-slides/SKILL.md +550 -118
- package/skills/search/SKILL.md +212 -56
- package/src/bridge/client.mjs +22 -0
|
@@ -5,51 +5,115 @@ description: Author branded slide decks and individual slides against the active
|
|
|
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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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.
|
|
12
17
|
- The **`.pptx` render** happens server-side in the add-in. There is no local exporter.
|
|
13
18
|
|
|
14
|
-
So this file owns only what is genuinely CLI-specific: the **first-step design-bundle gate**, a
|
|
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.
|
|
15
24
|
|
|
16
|
-
**slidemind is a CLI you drive directly.** Run `slidemind <command>` in your shell — the same way
|
|
25
|
+
**slidemind is a CLI you drive directly.** Run `slidemind <command>` in your shell — the same way
|
|
26
|
+
you'd run `git` or `npm`. There is no separate tool layer to go through; every step below is a real
|
|
27
|
+
command you type.
|
|
17
28
|
|
|
18
29
|
## Create a todo list (before your first command)
|
|
19
30
|
|
|
20
|
-
The moment this skill activates on an authoring task, **create a todo list of the workflow stages**
|
|
31
|
+
The moment this skill activates on an authoring task, **create a todo list of the workflow stages**
|
|
32
|
+
in your harness's task tracker — before you run anything — and keep it current: mark each stage done
|
|
33
|
+
as you complete it. This is `workflow/flow.md` → *track the stages*; the list is what keeps the
|
|
34
|
+
later stages (above all the review gate) from being skipped. The stages, as they run over the CLI:
|
|
21
35
|
|
|
22
36
|
1. `slidemind ready` — session preflight (*First step* below)
|
|
23
|
-
2. Clarify with the user — the content **and the output target** (*Intake → plan* below; needs no
|
|
37
|
+
2. Clarify with the user — the content **and the output target** (*Intake → plan* below; needs no
|
|
38
|
+
host, so it can run while `ready` executes)
|
|
24
39
|
3. Plan sign-off — `slidemind plan <deck>` (decks; single slides stay in chat)
|
|
25
|
-
4. Concept mockups — `slidemind concepts <deck>`, then
|
|
40
|
+
4. Concept mockups — `slidemind concepts <deck>`, then immediately inspect every mockup to drive
|
|
41
|
+
image/content search (a deck authored from an approved plan; see *The create flow* below)
|
|
26
42
|
5. Author the slides
|
|
27
43
|
6. Draft check — `slidemind view-draft`
|
|
28
44
|
7. Review gate — `slidemind review`, the moment the deck builds clean
|
|
29
45
|
8. Deliver — `slidemind push` or `slidemind build-pptx`, whichever target was locked in stage 2
|
|
30
46
|
|
|
31
|
-
**Deliver is the last todo — the task ends when the slides are delivered.** Don't add a "sanity
|
|
32
|
-
|
|
33
|
-
|
|
47
|
+
**Deliver is the last todo — the task ends when the slides are delivered.** Don't add a "sanity
|
|
48
|
+
pass" or "report back" step after it: the visual QA already happened at the draft check and the user
|
|
49
|
+
already approved at the review gate, so on approval you push/build directly and stop. Each stage's
|
|
50
|
+
full definition and the ordering invariants live in the bundle's `workflow/flow.md` — read it right
|
|
51
|
+
after `ready` succeeds.
|
|
52
|
+
|
|
53
|
+
**Concept mockups (stage 4) are a mandatory deck stage, not an optional aid.** After plan sign-off,
|
|
54
|
+
for a deck authored from an approved plan, you **always** run `slidemind concepts <deck>` and
|
|
55
|
+
**immediately Read every generated `concept-slide-NN.png` at full detail**. Use this first,
|
|
56
|
+
deck-wide viewing pass to inventory the imagery, pictograms, factual/content checks, and other
|
|
57
|
+
searches each slide needs; do those searches before authoring. This discovery read does **not**
|
|
58
|
+
replace the fresh per-batch concept read immediately before JSX creation in *The create flow*.
|
|
59
|
+
The durable visual anchors are the repo-relative files under
|
|
60
|
+
`decks/<slug>/concepts/concept-slide-NN.png`, never an earlier chat image or temporary attachment;
|
|
61
|
+
after any continuation, re-list that directory and reopen the files from those paths.
|
|
62
|
+
Rebuild each mockup toward its target — this is the local-harness equivalent of the in-app manager's
|
|
63
|
+
*unconditional* concept pass on every full-deck delegation (`generateConceptImages` fires for
|
|
64
|
+
`approvedPlan && !targetSlideScope`). It degrades benignly: if it returns no mockups (exit 0 — the
|
|
65
|
+
add-in can't generate them) you author from the storyboards alone, but the *attempt* is not optional.
|
|
66
|
+
Skip it only where the add-in's `!targetSlideScope` gate would — a single slide, a tiny in-chat set,
|
|
67
|
+
or a targeted rework of existing slides.
|
|
34
68
|
|
|
35
69
|
Two gate invariants you must never break — one per gate, equally binding:
|
|
36
70
|
|
|
37
|
-
- **Never jump from clarify to authoring for a deck** — the plan sign-off gate (`slidemind plan
|
|
38
|
-
|
|
71
|
+
- **Never jump from clarify to authoring for a deck** — the plan sign-off gate (`slidemind plan
|
|
72
|
+
<deck>`, stage 3) always sits between. Writing `decks/<slug>/slides/*.jsx` before that gate has
|
|
73
|
+
returned `DECISION: approved` is the single most common way this workflow goes wrong — it means
|
|
74
|
+
the user never actually signed off on the story. The only exception is a single slide or a tiny
|
|
75
|
+
set genuinely handled in-chat (*Intake → plan* below) — that's a real design choice, not a
|
|
76
|
+
shortcut to take when a deck-sized request feels obvious.
|
|
77
|
+
- **Never jump from authoring to deliver** — the draft check and an approved review gate always sit
|
|
78
|
+
between.
|
|
39
79
|
|
|
40
80
|
## Bootstrap (set yourself up — don't make the user do it)
|
|
41
81
|
|
|
42
|
-
**The first step of every session is `slidemind ready`** (continuing an existing deck: `slidemind
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
- **
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
82
|
+
**The first step of every session is `slidemind ready`** (continuing an existing deck: `slidemind
|
|
83
|
+
ready <deck>`). In one call it verifies authorization, connection, and CLI version; resolves the
|
|
84
|
+
design the add-in has open; downloads or refreshes that design's bundle; and — given a deck arg —
|
|
85
|
+
binds the deck to it.
|
|
86
|
+
|
|
87
|
+
- **Exit 0** → you're fully set up. Read `workflow/flow.md` (the stage spine) and `design.md` from
|
|
88
|
+
the reported `bundleDir` and start planning.
|
|
89
|
+
- **Non-zero** → the CLI names exactly one blocker and one `nextAction`; do what it says. (The two
|
|
90
|
+
blockers that ever need the user are handled in *First step* below.)
|
|
91
|
+
|
|
92
|
+
`ready` drives the `slidemind` CLI, which reaches PowerPoint through the add-in's **cloud relay** —
|
|
93
|
+
no local server. Patch a missing CLI yourself; **connecting** needs the user once (they hold the
|
|
94
|
+
add-in's identity):
|
|
95
|
+
|
|
96
|
+
- **CLI missing** (`slidemind` not on `PATH`): `npm install -g slidemind` — that alone is the fix.
|
|
97
|
+
Only run `slidemind init --for <claude|codex|opencode|all>` ((re)deploys this skill) when this
|
|
98
|
+
skill did **not** come from a plugin: if the `SKILL.md` you are reading sits under a harness
|
|
99
|
+
plugin cache (`~/.claude/plugins/…`, `~/.codex/plugins/…`), the plugin already supplies it and
|
|
100
|
+
`init` would plant a second copy that drifts on the next plugin update. `npx slidemind <command>`
|
|
101
|
+
runs one-off without a global install; `slidemind --version` confirms PATH; `slidemind update`
|
|
102
|
+
upgrades (`--ref <version>` to pin) — unless the CLI itself came from a plugin, in which case
|
|
103
|
+
update it there.
|
|
104
|
+
- **Not connected:** `ready` exits with `not_connected` — the CLI cannot start a connection by
|
|
105
|
+
itself, because the claim that carries the deployment's address is minted in the add-in. Ask the
|
|
106
|
+
user to open PowerPoint → slidemind → **Settings → General → Connect CLI**, press the **link
|
|
107
|
+
button**, and copy the command shown (press **CLI already installed?** for the short `slidemind
|
|
108
|
+
setup …` form). Have them paste it to you and run it **verbatim** — it connects, refreshes the
|
|
109
|
+
skills, and runs `ready` itself. Add `--no-install --for none` only if their install must not be
|
|
110
|
+
touched. `slidemind whoami` lists connected environments.
|
|
111
|
+
|
|
112
|
+
The CLI is **multi-environment**: connect once per backend (local / dev / prod) and every command
|
|
113
|
+
fans out across all of them, tags each open window with its `env`, and routes to the right backend
|
|
114
|
+
automatically — no manual switching. (Scope first-use authorization with `--backend <url>`; scope
|
|
115
|
+
later calls with `--backend <url|env>`.) A normal user connects to the baked-in production backend
|
|
116
|
+
only.
|
|
53
117
|
|
|
54
118
|
## Connecting the CLI (one-time; you guide the user)
|
|
55
119
|
|
|
@@ -58,63 +122,210 @@ PowerPoint — not here. Every organization runs its own slidemind backend, so a
|
|
|
58
122
|
unconnected CLI has no address to reach and nothing to discover it from; the
|
|
59
123
|
authenticated add-in knows both, and mints a one-time claim carrying its address.
|
|
60
124
|
|
|
61
|
-
**1 — Ask for the command.** Tell the user to open the **slidemind add-in** task pane → **Settings**
|
|
125
|
+
**1 — Ask for the command.** Tell the user to open the **slidemind add-in** task pane → **Settings**
|
|
126
|
+
→ **General** → **Connect CLI**, press the **link button**, and press **Copy command**. If they
|
|
127
|
+
already have the CLI, **CLI already installed?** swaps it to the shorter `slidemind setup …` form;
|
|
128
|
+
either works.
|
|
62
129
|
|
|
63
|
-
**2 — Run it verbatim.** Paste it exactly as given. It redeems the claim, saves the session,
|
|
130
|
+
**2 — Run it verbatim.** Paste it exactly as given. It redeems the claim, saves the session,
|
|
131
|
+
installs the CLI globally if needed, deploys the skills into every coding agent on the machine, and
|
|
132
|
+
finishes by running `ready` — so no `init` and no add-in restart belong to this flow.
|
|
64
133
|
|
|
65
|
-
**3 — If it fails.** A claim works once and expires in ~10 minutes; on *already used or expired*,
|
|
134
|
+
**3 — If it fails.** A claim works once and expires in ~10 minutes; on *already used or expired*,
|
|
135
|
+
ask for a fresh one. The pane flips to **Connected** by itself once the claim is spent.
|
|
66
136
|
|
|
67
137
|
## First step — `slidemind ready` (before anything else, every time)
|
|
68
138
|
|
|
69
|
-
Everything about how a deck is authored, styled, and rendered is shaped by the corporate design
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
**
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
139
|
+
Everything about how a deck is authored, styled, and rendered is shaped by the corporate design
|
|
140
|
+
**the add-in has open**, and every brand rule you follow is read from that design's **materialized
|
|
141
|
+
bundle**. `slidemind ready` gets you there in one call: it walks the connection ladder (a saved
|
|
142
|
+
session → reachable backend → CLI version → an open render-ready window), resolves which open design
|
|
143
|
+
to build against, downloads or refreshes that design's bundle (incremental — unchanged files cost
|
|
144
|
+
nothing), and — when you pass a deck — binds the deck to it by writing `<deck>/.bundle-ref.json`.
|
|
145
|
+
|
|
146
|
+
- **New work:** `slidemind ready` — resolves + materializes the open design's bundle so you can read
|
|
147
|
+
its `design.md` while planning.
|
|
148
|
+
- **Continuing a deck:** `slidemind ready <deck>` — same, and (re)binds the deck to whatever design
|
|
149
|
+
is open.
|
|
150
|
+
|
|
151
|
+
**The open add-in is the source of truth.** `ready` binds to whatever design is open *now*; a deck's
|
|
152
|
+
`.bundle-ref.json` records the last-resolved design for the render-time etag contract and host-free
|
|
153
|
+
bundle reads — it is **not** a pinned design preference. So you never "start a session with design
|
|
154
|
+
A" from a deck ref; you start it from what the add-in has open.
|
|
155
|
+
|
|
156
|
+
**On exit 0** the JSON reports `presId`, `presFP`, `designName`, `bundleDir`, `bundleEtag`, `bound`,
|
|
157
|
+
`paneSuspended`, and `engines` (`{available, envs}` — whether engine search reaches the corpus
|
|
158
|
+
without a window), with `nextAction: "Ready."`. Read `workflow/flow.md` and `design.md` from
|
|
159
|
+
`bundleDir` (cached at `${XDG_CACHE_HOME:-~/.cache}/slidemind/bundles/<presFP>/`, alongside
|
|
160
|
+
`corporate-design.css`, `layouts/*.jsx`, `layouts/layouts.css`, `assets/`, `samples/`, and the rest
|
|
161
|
+
of the add-in-owned `workflow/*.md`) and start planning. A render-ready window whose pane is
|
|
162
|
+
suspended still exits 0 with `paneSuspended: true` — the pane ops wait for a pane click on their
|
|
163
|
+
own; **don't treat it as a blocker.**
|
|
164
|
+
|
|
165
|
+
**A bound deck readies with NO window at all — that is the normal case, not a degraded one.**
|
|
166
|
+
`slidemind ready <deck>` for a deck that was bound once before exits 0 with `windowless: true` even
|
|
167
|
+
when PowerPoint is closed: the design identity lives in the deck's `.bundle-ref.json` and the bundle
|
|
168
|
+
syncs over a pane-free route, so its ladder is *session → bundle freshness → engine reachability*,
|
|
169
|
+
with **no pane precondition** — the pane is reported, never required. In that state authoring,
|
|
170
|
+
`view-draft`, `build`, `review`, `build-pptx`, and (where `engines.available` is true) engine search
|
|
171
|
+
and download all work end-to-end; only `push`'s insert, `insert-slide`, and `read <presId>` of an
|
|
172
|
+
open presentation need a window — the `nextAction` says exactly that. Don't ask the user to open
|
|
173
|
+
PowerPoint until one of those is actually next.
|
|
174
|
+
|
|
175
|
+
**Microsoft 365 sign-in — automatic on first need; just let it happen.** The engine surface — corpus
|
|
176
|
+
search, brand-imagery downloads, slide extraction — runs **as the user**. `ready` reports the state
|
|
177
|
+
(JSON: `m365.signedIn`, `m365.degradation`) so you know it's coming, but you never initiate it: the
|
|
178
|
+
first engine command opens the user's browser ITSELF, prints `Microsoft 365 sign-in needed — opening
|
|
179
|
+
your browser…`, and **blocks until the human finishes**. When that line appears, tell the user to
|
|
180
|
+
complete the sign-in in the browser (you cannot) and keep waiting — don't kill or re-run the
|
|
181
|
+
command. One sign-in lasts ~90 days. Rendering, bundles, and already-materialized assets never need
|
|
182
|
+
it, so a pure author→render session runs signed-out without ever seeing this.
|
|
183
|
+
|
|
184
|
+
For a deck that was **never** bound and no window is open, `ready` asks the backend which corporate
|
|
185
|
+
designs the user may build against: exactly one binds automatically, several stop with
|
|
186
|
+
`ambiguous_brand` (below).
|
|
187
|
+
|
|
188
|
+
**On non-zero** the CLI names exactly one blocker `{code, actor, message}` and one `nextAction`.
|
|
189
|
+
**The CLI owns the remediation text — relay `nextAction`, don't restate it.** These are the ones
|
|
190
|
+
that need the user:
|
|
191
|
+
|
|
192
|
+
- **`ambiguous_design`** — several windows with **different** corporate designs are open, so `ready`
|
|
193
|
+
can't choose. The CLI lists the candidates (each with its `env` and window `title`/`fileName`,
|
|
194
|
+
plus a design fingerprint); if the deck was last built against one of them it's marked
|
|
195
|
+
`suggested`. **Ask the user which design to build against, naming the windows by
|
|
196
|
+
`title`/`fileName` (and `env`) — never by raw id** — and mention the suggested one if present
|
|
197
|
+
("this deck was last built against X — continue with it?"). Then re-run `slidemind ready --to
|
|
198
|
+
<presId>` for the window they pick.
|
|
199
|
+
- **`ambiguous_brand`** — the same question with no window to ask it from: the backend offers
|
|
200
|
+
several designs (`brands[]`, each with a `name` and `env`). Ask the user by **name**, then re-run
|
|
201
|
+
`slidemind ready [deck] --brand <presFP>`.
|
|
202
|
+
- **`login_required`** — the automatic browser sign-in was refused or abandoned, so **corpus search
|
|
203
|
+
and engine downloads** stop until the user runs `slidemind login` (browser step, whenever they're
|
|
204
|
+
ready). It never blocks authoring, rendering, or the bundle — relay the line, keep working, and
|
|
205
|
+
re-run the search after they've signed in. When a slidemind pane is already open the CLI says so
|
|
206
|
+
and routes the search through that window instead: follow what it printed.
|
|
207
|
+
- **Connection blockers** (`not_connected`, `all_unreachable`, `cli_update_required`, `no_window`,
|
|
208
|
+
`not_render_ready`) — relay the CLI's `nextAction` verbatim (copy the setup command / open
|
|
209
|
+
PowerPoint / click the pane / run `slidemind update`). Connecting is walked through above.
|
|
210
|
+
(`no_window` only ever surfaces for a deck that is neither bound nor bindable from the backend's
|
|
211
|
+
design list — a bound deck rides the pane-free rung above instead.)
|
|
212
|
+
|
|
213
|
+
**The session spine** (= the stage todos you created up front): `slidemind ready` → read
|
|
214
|
+
`workflow/flow.md` + `design.md` from `bundleDir` → intake/plan (below) → `slidemind new <slug>`
|
|
215
|
+
(scaffolds **and** auto-binds the deck to the open design — zero extra download, because `ready`
|
|
216
|
+
already materialized it) → `slidemind plan <slug>` (plan sign-off gate for decks; single slides stay
|
|
217
|
+
in chat) → `slidemind concepts <slug>` (mandatory concept-mockup pass for a deck, then rebuild
|
|
218
|
+
toward each) → author → `view-draft` → `review` (mandatory, the moment the deck builds clean) →
|
|
219
|
+
deliver (`push` / `build-pptx`). `slidemind new` best-effort binds when the open design is
|
|
220
|
+
unambiguous and the bundle is already materialized; if it can't (ambiguous, or no host), it
|
|
221
|
+
scaffolds anyway and hints to run `slidemind ready <slug>`.
|
|
222
|
+
|
|
223
|
+
**Backgrounded — or closed — PowerPoint is expected to work.** Do not pre-emptively ask the user to
|
|
224
|
+
focus PowerPoint or the task pane, and never ask them to keep it foregrounded while something runs.
|
|
225
|
+
**The whole authoring loop is host-free for a bound deck** — intake → plan → concepts → author →
|
|
226
|
+
`view-draft` → `review` → `slidemind build-pptx <deck> [--out <file>]` — because the render captures
|
|
227
|
+
the slides with a local headless browser and assembles the `.pptx` server-side over the pane-free
|
|
228
|
+
brand route (streaming its own `rendering slide n/m…` progress), and engine discovery, search,
|
|
229
|
+
downloads, and slide reuse run off the connection wherever the add-in serves them
|
|
230
|
+
(`engines.available` in `ready`'s payload; older add-ins relay them through a pane instead). Exactly
|
|
231
|
+
three things need a live PowerPoint: **`push`'s insert**, **`insert-slide`**, and **`read
|
|
232
|
+
<presId>`** of an open presentation. Where a pane *is* involved, the CLI handles the wait itself: up
|
|
233
|
+
to ~2 min, one *"click the slidemind pane"* line when user help is genuinely needed, then a safe
|
|
234
|
+
retry. If you see that line, relay it once and keep waiting — do not rebuild, re-plan, or babysit.
|
|
235
|
+
If a `push` can't deliver (pane never woke, or no window at all), the rendered `.pptx` was saved
|
|
236
|
+
next to the deck (`paneSuspended` + `fallbackFile` in the result) — nothing is lost; re-run the push
|
|
237
|
+
once a window exists. Reserve the full "open PowerPoint…" instruction for when a command actually
|
|
238
|
+
reports it as the blocker.
|
|
239
|
+
|
|
240
|
+
`slidemind build`, `review`, and `view-draft` run offline, but only against a **previously
|
|
241
|
+
materialized** bundle — so `ready` (or a prior `ready`) must have succeeded at least once.
|
|
242
|
+
`build-pptx` additionally needs the backend reachable (the OOXML assembly is server-side), but no
|
|
243
|
+
PowerPoint window for a bound deck — so *"a `.pptx` file to send around"* is deliverable end-to-end
|
|
244
|
+
with PowerPoint closed.
|
|
96
245
|
|
|
97
246
|
## Two UX rules (gates + host)
|
|
98
247
|
|
|
99
|
-
- **Announce every gate, with a clickable link.** The moment `slidemind plan` or `slidemind review`
|
|
100
|
-
|
|
248
|
+
- **Announce every gate, with a clickable link.** The moment `slidemind plan` or `slidemind review`
|
|
249
|
+
starts it prints `ready at <url>` and a `BROWSER:` status line. Immediately tell the user in chat
|
|
250
|
+
whether a browser tab opened (new tab / reused tab / failed to open) and give the gate URL as a
|
|
251
|
+
clickable link — every round, and again whenever you report that you're still waiting on their
|
|
252
|
+
decision.
|
|
253
|
+
- **Add-in unreachable → block and name the tab.** When a genuinely host-required command (`push`'s
|
|
254
|
+
insert, `insert-slide`, `read <presId>`) can't reach the add-in (a connection blocker, a pane that
|
|
255
|
+
never wakes, the *click the slidemind pane* line with no effect), **stop the workflow** — don't
|
|
256
|
+
skip the step, work around it, or retry silently. Ask the user to go back into the PowerPoint tab
|
|
257
|
+
of presentation **<title/fileName>** (name it from the command output or `slidemind presentations`
|
|
258
|
+
— never a raw id), then re-run the failed command once they have. Everything before delivery keeps
|
|
259
|
+
running meanwhile — never park the whole task on a window it doesn't need.
|
|
101
260
|
|
|
102
261
|
## Intake → plan (you own this; do it in chat)
|
|
103
262
|
|
|
104
|
-
This is your mapping of `workflow/flow.md` stages 1–2 (*clarify* + *plan sign-off*). In-app, a
|
|
105
|
-
|
|
106
|
-
-
|
|
107
|
-
|
|
108
|
-
- **
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
263
|
+
This is your mapping of `workflow/flow.md` stages 1–2 (*clarify* + *plan sign-off*). In-app, a
|
|
264
|
+
manager runs these; over the CLI the manager role collapses onto **you**, so you run the interview
|
|
265
|
+
and the sign-off directly with the user. Don't write slide JSX until the plan is agreed.
|
|
266
|
+
|
|
267
|
+
- **Read scope from the wording**, don't ask redundantly: single slide ("make a slide about X"),
|
|
268
|
+
small set ("add three slides on Y"), or whole deck ("a deck for Friday"). Only ask "one slide, a
|
|
269
|
+
small set, or a full deck?" when truly ambiguous.
|
|
270
|
+
- **Interview just enough** to pin: audience/goal, the content and its sources (none / pasted /
|
|
271
|
+
local files / existing deck / web research — a source that's already a local `.pptx` you read
|
|
272
|
+
host-free with `slidemind read <file.pptx>`), and the slide outline (each slide's role + a layout
|
|
273
|
+
*job* like cover/agenda/section/quote/closing/body — the concrete brand layout is chosen later
|
|
274
|
+
against the bundle). If the content source resolves to "none", don't silently plan from generic
|
|
275
|
+
knowledge — say so, and either interview the user for the substance (their claims, numbers,
|
|
276
|
+
examples) or offer web research before writing storyboards.
|
|
277
|
+
- **Lock the output target — it decides your deliver command.** Into the open PowerPoint (`slidemind
|
|
278
|
+
push`), or a `.pptx` file (`slidemind build-pptx`) — or an HTML preview / a mix. Infer it when the
|
|
279
|
+
wording is clear ("add a slide to this deck" → push; "make me a deck I can send around" → a file)
|
|
280
|
+
and ask only when genuinely ambiguous — but **always confirm the concrete target before
|
|
281
|
+
delivering** (which window, or which output path).
|
|
282
|
+
- **Replay and get sign-off.** Single slides / tiny sets → a compact in-chat plan (no gate). Decks →
|
|
283
|
+
persist a **story-focused plan with body storyboards** in `decks/<slug>/plan.md`, two top-level
|
|
284
|
+
sections in order:
|
|
285
|
+
- `## Red thread` — one presentation **move** per slide, as bullets or one arrow-separated line.
|
|
286
|
+
The number of moves MUST equal the number of `### Slide N` sections: when the user names a slide
|
|
287
|
+
count, write exactly that many moves and sections — never expand the narrative arc beyond the
|
|
288
|
+
requested count. Name the *teaching function* of each slide — short verb+noun labels for what
|
|
289
|
+
the audience is doing cognitively at that step — never its content: no claims, facts, metrics,
|
|
290
|
+
client-specific terms, slide copy, generic section names, or wording copied from these
|
|
291
|
+
instructions.
|
|
292
|
+
- `## Per-slide storyboards` — one `### Slide N: <role>` subsection per slide, each a one-sentence
|
|
293
|
+
`Core message:` followed by **exactly one** fenced `storyboard-canvas` JSON block.
|
|
294
|
+
|
|
295
|
+
The `storyboard-canvas` is a **body-only spatial sketch**, not final slide design: it plans the
|
|
296
|
+
body region only and never the template title/header/footer/logo/slide-number areas. Blocks live
|
|
297
|
+
in a 1600 × 900 coordinate space, kept inside the body-safe area (roughly x 80–1520, y 110–780);
|
|
298
|
+
position, size, and proximity must express the slide's meaning — hierarchy, sequence, causality,
|
|
299
|
+
contrast, grouping, flow direction, or the main focus — not random placement. Each block shows
|
|
300
|
+
only two visible text fields: `designElement` (the visual mechanism in up to 5 words — e.g.
|
|
301
|
+
"hub-spoke visual", "loop diagram", "timeline", "matrix", "before/after contrast", "scorecard")
|
|
302
|
+
and `content` (a 1–2 word label), plus `emphasis` ("primary"/"secondary"/"tertiary") for
|
|
303
|
+
hierarchy. `keyMessage` is the slide's **story beat**: one plain sentence naming what this slide
|
|
304
|
+
does to move the story forward, stated abstractly — NOT the headline or copy that will appear on
|
|
305
|
+
the slide, and not the red-thread move restated. `contentNotes` is the **content draft** that
|
|
306
|
+
delivers that beat — facts, claims, examples, source points, caveats, draft copy, proof points —
|
|
307
|
+
and carries no design, layout, tone, or authoring-process instructions. It is the slide's full
|
|
308
|
+
content budget: the create stage and the concept-mockup generator build from `contentNotes` alone
|
|
309
|
+
and never add substance, so anything not in the notes will not be on the slide. Write them so the
|
|
310
|
+
slide body could be authored from them without inventing anything — every claim spelled out
|
|
311
|
+
concretely, with the numbers, named examples, or proof points that make it land. Two or three
|
|
312
|
+
abstract topic bullets ("X is expensive", "Y improves") is an unfinished draft, not a storyboard.
|
|
313
|
+
|
|
314
|
+
Judge whether two or more slides form a genuine visual series — for example a continuation,
|
|
315
|
+
progressive reveal, repeated comparison, phased journey, or recurring framework. When they do,
|
|
316
|
+
give those storyboard objects the same short, stable `visualFamily` identifier. Do not group
|
|
317
|
+
slides merely because they share a topic, and do not ask the user to make this design judgment. A
|
|
318
|
+
family tells concept generation to establish one recognizable visual system and adapt it to every
|
|
319
|
+
member's own `keyMessage`, `contentNotes`, role, and structure. It never permits copying another
|
|
320
|
+
slide's text, claims, data, or exact geometry, and it never permits dropping approved content to
|
|
321
|
+
fit the shared concept. Omit `visualFamily` for independent slides.
|
|
322
|
+
|
|
323
|
+
Choose the block count from the slide's meaning and **never default to three** (1 for a hero idea,
|
|
324
|
+
2 for a contrast or paired tension, 3 only for three genuinely distinct beats, 4–5 only for a true
|
|
325
|
+
sequence or comparison set), and vary the spatial composition across slides — avoid repeating the
|
|
326
|
+
same left/right/bottom alignment. Ban style micromanagement only — no colours, fonts, exact layout
|
|
327
|
+
names, or final box/card counts: **the create stage owns realisation** of the approved body
|
|
328
|
+
storyboard in the corporate design. Use this exact JSON shape:
|
|
118
329
|
|
|
119
330
|
```storyboard-canvas
|
|
120
331
|
{
|
|
@@ -141,77 +352,284 @@ This is your mapping of `workflow/flow.md` stages 1–2 (*clarify* + *plan sign-
|
|
|
141
352
|
}
|
|
142
353
|
```
|
|
143
354
|
|
|
144
|
-
Make the connection to the current deck explicit in the red thread, core messages, `keyMessage`,
|
|
145
|
-
|
|
146
|
-
|
|
355
|
+
Make the connection to the current deck explicit in the red thread, core messages, `keyMessage`,
|
|
356
|
+
or `contentNotes` whenever the work extends the open presentation, and fold in any content
|
|
357
|
+
findings from slides/files you inspected. Then run `slidemind plan <deck>`: it opens the plan as
|
|
358
|
+
**editable storyboards** — the user reorders/renames/inserts/removes slides on the red-thread
|
|
359
|
+
strip, drags/resizes/edits blocks and the content draft directly on each slide's canvas, and/or
|
|
360
|
+
leaves comments anchored to a slide or to the whole story — and it **blocks until the user
|
|
361
|
+
decides** — announce it per *Two UX rules* (browser opened? + the clickable gate URL) and give the
|
|
362
|
+
shell call a **generous timeout** (the gate waits up to 30 min; if your harness kills the call
|
|
363
|
+
early, just re-run it — the user's open tab reconnects). Outcomes: `DECISION: approved` → proceed
|
|
364
|
+
to author; `DECISION: comments` → apply the comments to `plan.md` — each is **slide-anchored** (`-
|
|
365
|
+
[Slide 3: "<beat>"] …`) or whole-story, and the batch may include a **generated story-iteration
|
|
366
|
+
instruction** (when the user restructured the red thread by adding or renaming slides, the gate
|
|
367
|
+
asks you to build storyboards and content for exactly those moves while keeping the other slides
|
|
368
|
+
intact) — (the round is persisted verbatim in `<deck>/plan-review.json` if your capture of the
|
|
369
|
+
output was truncated). Change only what the comments require and keep unaffected slides verbatim
|
|
370
|
+
(that is what makes the reviewer's per-slide "updated" badges meaningful), then **re-run the gate
|
|
371
|
+
in the same turn**. **Expect several consecutive `DECISION: comments` rounds — that is the normal
|
|
372
|
+
shape of a review, not an error.** The reviewer's tab stays live while you revise, so they keep
|
|
373
|
+
reading and keep queueing comments; those queued comments are delivered by your next run, which
|
|
374
|
+
then returns *immediately* with them (a drain round) instead of waiting. So never end your turn on
|
|
375
|
+
a comments round, never claim to be "polling", and never send the user back to the browser between
|
|
376
|
+
rounds — nothing reaches them until the gate runs again. Only `DECISION: approved` or `DECISION:
|
|
377
|
+
pending` ends the loop; `DECISION: pending` → the gate timed out with no answer — not approval,
|
|
378
|
+
not rejection: don't author; wrap up telling the user the plan still awaits their sign-off and
|
|
379
|
+
re-run `slidemind plan <deck>` on their go-ahead. Loop until approved. A `plan.md` **approved in a
|
|
380
|
+
prior gate round and unchanged since** counts as approved (skip straight to authoring); any new or
|
|
381
|
+
revised plan must pass the gate. When the gate reports the user edited `plan.md` directly, re-read
|
|
382
|
+
it — the edited storyboards **are** the approved plan; author from them.
|
|
383
|
+
|
|
384
|
+
Keep planning about intent and content. The bundle is already materialized by `slidemind ready`, so
|
|
385
|
+
`design.md` is there if you need to sanity-check feasibility — but **don't dive into
|
|
386
|
+
brand/layout/composition detail until create/edit.**
|
|
147
387
|
|
|
148
388
|
## The create flow
|
|
149
389
|
|
|
150
|
-
`slidemind ready` already resolved the design source and materialized its bundle; the deck was bound
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
`
|
|
163
|
-
|
|
164
|
-
|
|
390
|
+
`slidemind ready` already resolved the design source and materialized its bundle; the deck was bound
|
|
391
|
+
to it by `slidemind ready <deck>` (continuing) or by `slidemind new <slug>`'s auto-bind (new work).
|
|
392
|
+
From here:
|
|
393
|
+
|
|
394
|
+
1. **Study brand samples (before composing).** The materialized bundle's `samples/` dir holds the
|
|
395
|
+
brand's own reference slides. If it's non-empty, pick **3 at random** and **Read** each (the Read
|
|
396
|
+
tool renders images) *before* writing any JSX — this is the local-harness stand-in for the in-app
|
|
397
|
+
persona's reference thumbnails, and it is what keeps a deck looking on-brand rather than merely
|
|
398
|
+
compliant. Study them for whitespace rhythm, shape density, hierarchy, accent use, and layering,
|
|
399
|
+
then compose in that spirit (never copy a sample 1:1). This is `composition.md`'s samples
|
|
400
|
+
discipline; skip only when `samples/` is empty.
|
|
401
|
+
2. **Load create context, then inspect the concepts.** Read the create-stage references together —
|
|
402
|
+
`workflow/create.md` (the procedure), `workflow/composition.md` (the composition baseline),
|
|
403
|
+
`workflow/layouts.md` (palette + working area), and `workflow/authoring.md` (the substrate rules)
|
|
404
|
+
— plus the deck's `design.md` and the specific `layouts/*.jsx` the plan uses. (That is the read
|
|
405
|
+
set `workflow/create.md` → Context loading prescribes; follow it as written — `workflow/flow.md`
|
|
406
|
+
you already read after `ready`.) The approved `plan.md` is a **content contract, not a rendering
|
|
407
|
+
spec** — you drew its storyboards yourself, but approval covered the story and content, not the
|
|
408
|
+
sketch's geometry; how to interpret the `storyboard-canvas` blocks at author time (design
|
|
409
|
+
hypothesis: reinterpret freely, never transcribe coordinates, block geometry, or block labels)
|
|
410
|
+
is owned by `workflow/create.md` → Preconditions. **Generate concept mockups first — mandatory
|
|
411
|
+
for a deck (stage 4).** Before
|
|
412
|
+
authoring a deck from an approved plan, run `slidemind concepts <deck>` — the local-harness
|
|
413
|
+
equivalent of the in-app manager's *unconditional* concept pass (`generateConceptImages` fires
|
|
414
|
+
for every `approvedPlan && !targetSlideScope` delegation). **Immediately after generation, Read
|
|
415
|
+
every `decks/<slug>/concepts/concept-slide-NN.png` at full detail, before any engine or content
|
|
416
|
+
search.** First list the directory and keep the literal repo-relative mapping in the task context:
|
|
417
|
+
concept `NN` maps to `decks/<slug>/concepts/concept-slide-NN.png` and later to the `NN-*.jsx`
|
|
418
|
+
slide. These workspace files are the durable source of truth across turns and compaction — never
|
|
419
|
+
rely on an earlier rendered attachment. Inventory what each mockup requires — imagery, distinct
|
|
420
|
+
pictograms, factual/content verification, annotations, and other visible organisms — and use
|
|
421
|
+
that inventory to drive step 3. This first pass is deliberately deck-wide and search-oriented;
|
|
422
|
+
it is not the fresh authoring read required in step 4. Rebuild each mockup under your constraints
|
|
423
|
+
— the rebuild rule is owned by
|
|
424
|
+
`workflow/create.md` → Preconditions (reproduce the mockup's composition, hierarchy, graphic
|
|
425
|
+
mechanism, AND granularity — its organism count, badges, satellites, and annotation layers are
|
|
426
|
+
part of the target, and restraint is a colour budget, never an element budget; texts follow the
|
|
427
|
+
story). It never hard-fails: if it produces no mockups (exit 0 — the add-in can't generate them)
|
|
428
|
+
author from the storyboards alone. Skip it only where the add-in's `!targetSlideScope` gate would
|
|
429
|
+
— a single slide, a tiny in-chat set, or a targeted rework of existing slides.
|
|
430
|
+
When storyboard objects share a `visualFamily`, rebuild those mockups as one recognizable visual
|
|
431
|
+
series. The lowest-numbered member is the anchor. Preserve its shape vocabulary, framing,
|
|
432
|
+
hierarchy, annotation style, illustration treatment, and spatial rhythm across the family, but
|
|
433
|
+
adapt every member's element count, sizing, arrangement, labels, emphasis, and connections to its
|
|
434
|
+
own complete `keyMessage`, `contentNotes`, role, and structure. Never copy another member's text,
|
|
435
|
+
claims, or data, never force its exact geometry, and never omit approved content because it does
|
|
436
|
+
not fit the anchor composition.
|
|
437
|
+
3. **Search and fetch from the concept inventory.** Resolve the image and content needs identified
|
|
438
|
+
in the immediate post-generation concept pass. Discover the available image engines by listing
|
|
439
|
+
them — `slidemind ls engines --subtype image` (the local-harness equivalent of the in-app design
|
|
440
|
+
agent's
|
|
441
|
+
`list_engines` tool; no PowerPoint window needed where the add-in serves the pane-free engine
|
|
442
|
+
routes) — judge which engine fits from its label and description, then search it and place
|
|
443
|
+
results. (`slidemind search` without `--engine` picks an image engine the same way.) The engine
|
|
444
|
+
search/reuse mechanics live in **`slidemind-search`** — use it to find and fetch imagery; the
|
|
445
|
+
create-only detail — sizing a fetched asset's box and recolouring an icon — is in *Placing engine
|
|
446
|
+
imagery* below. To pull in an **existing whole slide** (not just an image), use
|
|
447
|
+
`slidemind-search`'s `add-slide` — it folds the slide into `decks/<slug>/slides/` as a native
|
|
448
|
+
`.pptx` that coexists with your JSX in play order and survives re-push. The slide can come from
|
|
449
|
+
an engine search **or** from a local `.pptx` on disk (`add-slide --from <file.pptx> --pick <n>
|
|
450
|
+
--deck <slug>`, host-free); both fold in identically — see `slidemind-search`.
|
|
451
|
+
4. **Reopen the concepts, then author in small batches.** Once the searches and asset downloads are
|
|
452
|
+
complete, split a concept-seeded deck into batches of at most **3 slides**. For each batch, first
|
|
453
|
+
Read its matching anchored `decks/<slug>/concepts/concept-slide-NN.png` files together at full
|
|
454
|
+
detail; as the **very next tool action**, create those slides'
|
|
455
|
+
`decks/<slug>/slides/NN-<topic>.jsx` files. Put no search, command, reference read, user exchange,
|
|
456
|
+
or unrelated work between the concept images and the JSX write.
|
|
457
|
+
The deck-wide discovery read in step 2 never counts as this authoring read. A user interruption,
|
|
458
|
+
resumed turn, compaction, long wait, or unrelated tool work invalidates an earlier authoring read:
|
|
459
|
+
re-list `decks/<slug>/concepts/` if needed and reopen the affected anchored files before writing.
|
|
460
|
+
This batching is a local-harness context discipline, not a second create pass: the whole deck
|
|
461
|
+
remains one create pass and every slide file is created exactly once. Use a zero-padded numeric
|
|
462
|
+
prefix from the first file on (play order is filename order here; see the slide-file row in the
|
|
463
|
+
command mapping), one default export per slide, and one bundle layout (Mode A) or blank-content
|
|
464
|
+
layout with freeform children (Mode B), exactly as the bundle docs prescribe.
|
|
465
|
+
5. **Look at your own draft first (you, the agent).** This is the **draft check** in
|
|
466
|
+
`workflow/build-and-export.md` — your pre-check, *before* any human sees the deck. Run `slidemind
|
|
467
|
+
view-draft <deck>`: it renders each authored `slides/*.jsx` to a per-slide PNG and hands the
|
|
468
|
+
images back to you — **nothing is pushed, no `.pptx` is written, no review gate opens**. For
|
|
469
|
+
every concept-seeded slide, Read its anchored
|
|
470
|
+
`decks/<slug>/concepts/concept-slide-NN.png` and matching
|
|
471
|
+
`decks/<slug>/.draft-preview/<slide-basename>.png` **together in the same visual inspection**, in
|
|
472
|
+
batches of at most 3 pairs. Diff each pair organism by organism; a draft-only inspection does not
|
|
473
|
+
satisfy this check. Fix anything visibly wrong **in the JSX** (re-express, never delete), render
|
|
474
|
+
again, and reopen the affected anchored concept/draft pairs until each slide is sound. One round
|
|
475
|
+
usually suffices. It runs
|
|
476
|
+
locally against the materialized bundle, so it needs no awake pane and no open host once the
|
|
477
|
+
bundle has been downloaded once. Two faithful limits to know: a slide on a **purpose-built (Mode
|
|
478
|
+
A) layout** (cover/divider/agenda) and a **reused native `.pptx`** slide have no freeform region
|
|
479
|
+
to capture, so they come back as a status line, not an image — judge those at the full-deck
|
|
480
|
+
`review`/`build` step below. Do this self-check before the human review gate; don't push a draft
|
|
481
|
+
you haven't looked at.
|
|
482
|
+
6. **The review gate — the moment the deck builds clean.** This is the **review gate** in
|
|
483
|
+
`workflow/build-and-export.md`; the CLI's gate command is `slidemind review <deck>`. Run it the
|
|
484
|
+
instant the authored set builds clean — before any deliver, without asking whether the user wants
|
|
485
|
+
a review. It builds the HTML preview first (the same lint the render enforces, so a gate that
|
|
486
|
+
*opens* is a clean build; while lint errors remain it exits non-zero — fix and re-run), then
|
|
487
|
+
opens the browser with a spatial comment overlay and **blocks until the user decides** (host-free
|
|
488
|
+
— no open PowerPoint needed for the gate). Announce it per *Two UX rules*: tell the user the
|
|
489
|
+
browser opened and give the clickable gate URL. **Blocking is the point: give the shell call a
|
|
490
|
+
generous timeout (the gate waits up to 30 min) and let it sit — a long quiet wait means the user
|
|
491
|
+
is reviewing, not that something hung. Never cancel it; if your harness kills the call early,
|
|
492
|
+
just re-run it (the user's open tab reconnects).** The verdict prints to stdout:
|
|
493
|
+
- `DECISION: approved` → proceed to the deliver the user chose at intake: `slidemind push <deck>`
|
|
494
|
+
(into PowerPoint) or `slidemind build-pptx <deck>` (to a file).
|
|
495
|
+
- `DECISION: comments` → the user left spatially-anchored notes, each citing a
|
|
496
|
+
`slides/<file>.jsx:line:col`, the source line, the click position, and a **round tag** (`[2,
|
|
497
|
+
round 1] …`) — plus a readonly-layout note where the click landed on a layout slot. A pin
|
|
498
|
+
carrying an *older* round was dropped on the previous render, so read the file before you edit
|
|
499
|
+
it rather than trusting the cited line blindly. **Edit the cited files in place at the given
|
|
500
|
+
line and re-run `slidemind review <deck>` in the same turn.** **Expect several consecutive
|
|
501
|
+
`DECISION: comments` rounds — that is the normal shape of a review, not an error.** The user's
|
|
502
|
+
tab stays live while you fix: they keep browsing the preview and keep dropping pins, and those
|
|
503
|
+
queued pins are delivered by your next run, which then returns *immediately* with them (a drain
|
|
504
|
+
round) instead of waiting. So never end your turn on a comments round, never claim to be
|
|
505
|
+
"polling", and never send the user back to the browser between rounds — nothing reaches them
|
|
506
|
+
until the gate runs again. Addressed pins come back as read-only ghost pins so the user can
|
|
507
|
+
confirm each note was worked in. Only `DECISION: approved` or `DECISION: pending` ends the
|
|
508
|
+
loop. Nothing is exported on a comments round. **Every round is persisted verbatim in
|
|
509
|
+
`<deck>/review.json`** — if your shell capture of the gate's output was truncated or lost
|
|
510
|
+
(backgrounded command, clipped scrollback), read that file for the complete comment list; never
|
|
511
|
+
guess at missing comments or ask the user to re-type them.
|
|
512
|
+
- `DECISION: pending` → the gate timed out with no answer (the user stepped away). Not approval,
|
|
513
|
+
not rejection — **do not deliver**. Wrap up your turn: tell the user the preview is still
|
|
514
|
+
waiting for their review and that on their go-ahead you'll re-run `slidemind review <deck>`
|
|
515
|
+
(their tab reconnects).
|
|
516
|
+
|
|
517
|
+
`slidemind review` is the only step that pauses; `push`/`build-pptx` never pause — they render
|
|
518
|
+
pane-free (local capture + server-side assembly, with live per-slide progress). **CLI exports
|
|
519
|
+
happen out of the user's sight, so the flow invariant — *the user sees every change before the
|
|
520
|
+
task is done* — makes re-review mandatory here: every deliver is preceded by an approved review
|
|
521
|
+
of exactly what it delivers. After any later slide change, the deck re-enters `slidemind review`
|
|
522
|
+
before it can be pushed or exported again — never deliver an unreviewed change.** If several
|
|
523
|
+
presentations are open, confirm **which one to push into** first (it can differ from the design
|
|
524
|
+
source `slidemind ready` locked in). After approval, run the push without asking; it works while
|
|
525
|
+
PowerPoint is backgrounded, and the CLI itself waits + retries if the pane is needed (see *First
|
|
526
|
+
step* above). If a push still times out, the rendered `.pptx` is saved next to the deck — re-run
|
|
527
|
+
`push` after the user clicks the pane, without rebuilding.
|
|
528
|
+
|
|
529
|
+
**On a clean approve + deliver, the task is done.** Report what landed (slide count + target) and
|
|
530
|
+
stop — no sanity pass, no re-verification. The visual QA already happened at the draft check
|
|
531
|
+
(step 4) and the user signed off at the review gate.
|
|
165
532
|
|
|
166
533
|
## Manual PowerPoint edits (the reconcile loop)
|
|
167
534
|
|
|
168
|
-
The user may have edited the deck directly in PowerPoint since your last deliver — moved a shape,
|
|
535
|
+
The user may have edited the deck directly in PowerPoint since your last deliver — moved a shape,
|
|
536
|
+
retyped a line, recoloured a box. Those edits live only in that file or that window; the deck's jsx
|
|
537
|
+
knows nothing about them. `slidemind build-pptx` and `slidemind push --replace` therefore check
|
|
538
|
+
before they write, and play the changes back to you:
|
|
169
539
|
|
|
170
|
-
- **Plain text edits are already folded into your jsx** — the command prints `note: folded N manual
|
|
171
|
-
|
|
540
|
+
- **Plain text edits are already folded into your jsx** — the command prints `note: folded N manual
|
|
541
|
+
text edit(s) … into slides/<file>` and the fold is now the source of truth on disk. **Re-read that
|
|
542
|
+
file before your next edit** or you will write over it from a stale copy.
|
|
543
|
+
- **Everything else refuses the deliver** with a `RECONCILE REQUIRED` report per slide (geometry in
|
|
544
|
+
EMU, style changes, added/removed shapes) and exit code non-zero. Nothing was written or pushed.
|
|
172
545
|
|
|
173
546
|
On a `RECONCILE REQUIRED`:
|
|
174
547
|
|
|
175
|
-
1. **Fold every listed change into the slide's jsx** — the user made them on purpose; losing them is
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
548
|
+
1. **Fold every listed change into the slide's jsx** — the user made them on purpose; losing them is
|
|
549
|
+
unacceptable. Translate geometry deltas into **layout intent** (spacing, order, relative sizing,
|
|
550
|
+
which region a thing sits in) — never literal offsets, absolute coordinates, or
|
|
551
|
+
transform/translate hacks bolted onto a working composition. Recreate added shapes as jsx
|
|
552
|
+
elements; drop deleted ones. If a folded position genuinely cannot fit the content area,
|
|
553
|
+
re-express its intent (reflow, reorder, resize) rather than discarding it.
|
|
554
|
+
2. Lines marked `[preserved]` are foreign add-in content (e.g. an embedded chart) — do **not**
|
|
555
|
+
recreate them; they are spliced back into the rendered slide automatically.
|
|
556
|
+
3. **Re-run the same command.** The re-run proceeds: the report was acknowledged
|
|
557
|
+
(`decks/<slug>/.reconcile-ack.json`), and only a NEW manual edit re-arms the check. The deck
|
|
558
|
+
changed, so the flow invariant applies — re-run `slidemind review <deck>` before delivering
|
|
559
|
+
again.
|
|
560
|
+
4. **Do this silently.** Reconcile is bookkeeping, not a deliverable: never explain the report, the
|
|
561
|
+
baseline, or your folding steps, and never ask the user about it. Fold and carry on with their
|
|
562
|
+
actual request in the same turn. At most one short clause in your final answer ("kept your manual
|
|
563
|
+
layout change").
|
|
564
|
+
|
|
565
|
+
`--force` on either command **discards the user's manual edits** and writes anyway. It is a last
|
|
566
|
+
resort, only on the user's explicit say-so — never reach for it to get past a report you could fold.
|
|
181
567
|
|
|
182
568
|
Three refusals are not foldable and need the user, not a retry:
|
|
183
569
|
|
|
184
|
-
- `the live deck contains N slide(s) not in this deck` — a whole-deck replace would delete slides
|
|
185
|
-
|
|
186
|
-
|
|
570
|
+
- `the live deck contains N slide(s) not in this deck` — a whole-deck replace would delete slides
|
|
571
|
+
someone added by hand or with another tool. Push **without** `--replace` to insert instead, or ask
|
|
572
|
+
the user what should happen to them.
|
|
573
|
+
- `<file> was edited in PowerPoint …` naming slides with no jsx behind them (a reused native slide,
|
|
574
|
+
or one pushed by another deck) — build to a different target with `--out <other file>` so their
|
|
575
|
+
edits survive, or ask.
|
|
576
|
+
- `backend does not support manual-edit reconcile` / `the live deck could not be inspected` — the
|
|
577
|
+
add-in is older than this contract, or its PowerPoint build cannot export slides. Tell the user to
|
|
578
|
+
update the slidemind add-in. Do not paper over it with `--force`.
|
|
187
579
|
|
|
188
580
|
## Placing engine imagery (create-authoring specifics)
|
|
189
581
|
|
|
190
|
-
Finding and fetching engine imagery is `slidemind-search`'s job (`slidemind search` → `slidemind
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
582
|
+
Finding and fetching engine imagery is `slidemind-search`'s job (`slidemind search` → `slidemind
|
|
583
|
+
download-result`). What follows is **create-only**: how to size and colour a fetched asset so it
|
|
584
|
+
reads on-brand in your JSX, honoured in both the `slidemind build` preview and the render.
|
|
585
|
+
|
|
586
|
+
Engine results land as files referenced with `<img src="./assets/<file>">`. These facts are specific
|
|
587
|
+
to the local harness (the bundle's `workflow/*.md` stay harness-neutral):
|
|
588
|
+
|
|
589
|
+
- **Size the box from the asset's own dimensions.** Both `slidemind search` (from the engine index,
|
|
590
|
+
before any fetch) and `slidemind download-result` (measured from the delivered bytes) print each
|
|
591
|
+
image's intrinsic `width×height`. **Use it.** A plain `<img>` is stretched to whatever box you
|
|
592
|
+
write, so a box whose aspect ratio disagrees with the asset ships a distorted picture. Derive one
|
|
593
|
+
side from your layout and compute the other from the printed ratio. `object-fit: contain`/`cover`
|
|
594
|
+
is honoured in the render as well as the preview, but it is a *fallback*, not a substitute: it
|
|
595
|
+
converts a wrong ratio into letterboxing or a crop, both of which you chose blind. When the size
|
|
596
|
+
prints as `(size unknown)`, the format carried no readable header — give the asset a square-ish
|
|
597
|
+
box and check it at the draft check.
|
|
598
|
+
- **Never open the SVG to find out whether it recolours.** `slidemind download-result` prints a
|
|
599
|
+
`recolor` descriptor for each asset — `{ recolorable, mode, applied, note }`, where `mode` is
|
|
600
|
+
`currentColor`, `mono`, `multicolor`, or `raster`. Read it; that *is* the answer.
|
|
196
601
|
- **Two ways to colour an icon, both honoured in the `slidemind build` preview *and* the render:**
|
|
197
|
-
- **Bake it in (prefer this):** pass `--icon-color <hex>` — a hex you resolve from a token in the
|
|
198
|
-
|
|
199
|
-
|
|
602
|
+
- **Bake it in (prefer this):** pass `--icon-color <hex>` — a hex you resolve from a token in the
|
|
603
|
+
bundle's `corporate-design.css` — to `slidemind download-result`. Works for any `recolorable`
|
|
604
|
+
glyph and the colour is in the saved file, so preview and render always agree. The tint is
|
|
605
|
+
applied by the add-in, so on the window-free path it can be **refused**: the asset is then saved
|
|
606
|
+
in its original colours and the `recolor` note says so. Believe the note over your request — to
|
|
607
|
+
actually bake the colour in, re-run the search and the download with `--to <presId>` against an
|
|
608
|
+
open PowerPoint window.
|
|
609
|
+
- **Tint via CSS:** set `color` to a token on the `<img>`. This works only for `mode:
|
|
610
|
+
"currentColor"` icons (the preview inlines the SVG so `color` resolves, and the render
|
|
611
|
+
substitutes `currentColor`). A `mono` icon will not respond to CSS colour — bake it instead.
|
|
612
|
+
- **Batch the fetch.** Pull every icon a slide needs in one call — `slidemind download-result
|
|
613
|
+
--search <id> --pick <n,n,…> --deck <deck> [--icon-color <hex,hex,…>]` (one colour applies to all
|
|
614
|
+
picks, or give one per pick; add `--to <presId>` only on an add-in that still relays the fetch
|
|
615
|
+
through a pane, which the `search` output names) — the downloads run concurrently. Don't run
|
|
616
|
+
`download-result` once per icon.
|
|
200
617
|
|
|
201
618
|
## Command mapping (the workflow vocabulary ⇄ your CLI)
|
|
202
619
|
|
|
203
|
-
The bundle's `workflow/*.md` speak the harness-neutral verbs defined in `workflow/flow.md` →
|
|
620
|
+
The bundle's `workflow/*.md` speak the harness-neutral verbs defined in `workflow/flow.md` →
|
|
621
|
+
Vocabulary. You are the local harness — this is your mapping:
|
|
204
622
|
|
|
205
623
|
| Verb (`workflow/flow.md`) | Your equivalent (local harness) |
|
|
206
624
|
|---|---|
|
|
207
625
|
| (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 |
|
|
208
626
|
| **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) |
|
|
209
627
|
| **clarify** / **plan sign-off** | intake stays in chat with the user (above); for decks, 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, some returning instantly with comments queued while you revised; loop until approved) |
|
|
210
|
-
| concept mockups (mandatory deck stage, after plan sign-off) | `slidemind concepts <deck>` — renders one image mockup per approved-plan slide into `decks/<slug>/concepts/concept-slide-NN.png`;
|
|
628
|
+
| concept mockups (mandatory deck stage, 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 a deck you always run it. Skip only where the add-in's `!targetSlideScope` gate would — a single slide, a tiny in-chat set, or a targeted rework of existing slides |
|
|
211
629
|
| **read** / **list** the workspace | read the files from the materialized bundle dir (`<bundle>/…`) and your `decks/<slug>/` |
|
|
212
|
-
| **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 |
|
|
630
|
+
| **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 |
|
|
213
631
|
| brand reference samples (studied before composing) | **Read** 3 random images from the materialized bundle's `samples/` dir — the Read tool renders them (see *The create flow* step 1) |
|
|
214
|
-
| **draft check** | `slidemind view-draft <deck>` — renders each `slides/*.jsx` to
|
|
632
|
+
| **draft check** | `slidemind view-draft <deck>` — renders each `slides/*.jsx` to `decks/<slug>/.draft-preview/<slide-basename>.png` 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. A draft-only inspection does not count. 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 |
|
|
215
633
|
| **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 |
|
|
216
634
|
| **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); expect several comment rounds, some returning instantly with pins the user queued while you were fixing. 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. |
|
|
217
635
|
| **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 |
|
|
@@ -219,15 +637,26 @@ The bundle's `workflow/*.md` speak the harness-neutral verbs defined in `workflo
|
|
|
219
637
|
| **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 |
|
|
220
638
|
| **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 |
|
|
221
639
|
|
|
222
|
-
Everything else in `workflow/*.md` — the composition craft, the substrate/authoring rules, the
|
|
640
|
+
Everything else in `workflow/*.md` — the composition craft, the substrate/authoring rules, the
|
|
641
|
+
layout discovery and slot/working-area rules, the visual quality bar (applied at the draft check) —
|
|
642
|
+
applies to you unchanged.
|
|
223
643
|
|
|
224
644
|
## The brand and the workflow both live in the bundle, not here
|
|
225
645
|
|
|
226
|
-
Do not restate brand values (colour, type scale, spacing, layout names, accent discipline) or
|
|
646
|
+
Do not restate brand values (colour, type scale, spacing, layout names, accent discipline) or
|
|
647
|
+
re-derive the authoring/composition craft in this file or in slide files — they are in the bundle's
|
|
648
|
+
`design.md` and `workflow/*.md`. Read them and follow them. Don't load external UI/design-taste
|
|
649
|
+
plugins during slide work; compose against the bundle's layouts and tokens. If the corporate design
|
|
650
|
+
moves mid-task (`bundle_etag_stale`), the CLI self-heals: it refreshes the bundle and retries the
|
|
651
|
+
render on its own — afterwards re-read the bundle's `design.md` before authoring anything new, since
|
|
652
|
+
the rules may have changed.
|
|
227
653
|
|
|
228
654
|
## Failure modes the render lint can't catch
|
|
229
655
|
|
|
230
|
-
Render-time lint rejects contract violations (unsupported CSS, bad imports, remote `<img>` URLs —
|
|
656
|
+
Render-time lint rejects contract violations (unsupported CSS, bad imports, remote `<img>` URLs —
|
|
657
|
+
the add-in's capability-table engine; `slidemind build` runs the same engine locally from the
|
|
658
|
+
bundle). It can't catch content-shaped failures; check for these **at the draft check** (step 4,
|
|
659
|
+
before the review gate) — not after delivery:
|
|
231
660
|
|
|
232
661
|
- Layout-default / placeholder text leaking through an unfilled prop.
|
|
233
662
|
- A bullet list standing in for a structured idea (process, comparison, timeline).
|
|
@@ -239,4 +668,7 @@ Render-time lint rejects contract violations (unsupported CSS, bad imports, remo
|
|
|
239
668
|
|
|
240
669
|
## Where the deck lives
|
|
241
670
|
|
|
242
|
-
`decks/<slug>/` is created in the **current working directory** (the shell's pwd when the skill was
|
|
671
|
+
`decks/<slug>/` is created in the **current working directory** (the shell's pwd when the skill was
|
|
672
|
+
invoked). Every `slidemind` command and `mkdir` resolves `decks/` against that cwd — don't `cd` into
|
|
673
|
+
the skill's install directory. The materialized bundle lives in the cache dir above, not under the
|
|
674
|
+
deck.
|