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
package/README.md CHANGED
@@ -298,6 +298,9 @@ slidemind new <name> Scaffold ./decks/<name>/ (auto-binds to the ope
298
298
  slidemind plan <deck> Plan sign-off gate on <deck>/plan.md; blocks for approve/comments (offline)
299
299
  slidemind review <deck> Spatial preview review; blocks for approve/comments (offline)
300
300
  slidemind build-pptx <deck> Render a native .pptx via the add-in (host required)
301
+ A deck connected to SharePoint (the file you opened, or a folder you
302
+ connected in the workspace) is saved there right after the build;
303
+ --no-publish keeps a build local
301
304
  --pack <dir> for an explicit fill-template pack
302
305
  slidemind inspect-template-deck <deck> Emit a normalized template-deck model for pack validation
303
306
  --pack <dir> --json [--allow-unrendered-freeform]
@@ -317,10 +320,61 @@ slidemind add-slide [opts] Fold slide(s) into a deck as native .pptx — f
317
320
  --from <file.pptx> --pick <n[,n,...]> --deck <deck> [--at <N>] (local file; host-free; not with --search)
318
321
  slidemind download-result [opts] Download image/icon result(s) into a deck's assets/ (host required)
319
322
  --search <id> --pick <n[,n,...]> --deck <deck> --to <presId> [--icon-color <hex[,hex,...]>]
323
+ slidemind assets <sub> The deck's registry of images you supplied. Importing records the bytes;
324
+ what the picture is FOR is approved in the plan, not here
325
+ import <deck> <file> copy a file in and identify it by its own digest
326
+ (file paths only — never a URL)
327
+ list <deck> what this deck has registered
328
+ --json on both
320
329
  slidemind adopt <file.pptx> Rebuild a deck workspace from a .pptx — slidemind-authored slides come back
321
330
  as their original jsx, foreign ones are converted to editable jsx where the
322
331
  add-in offers it, the rest fold in native
323
332
  --deck <slug> --brand <presFP> --no-convert
333
+ --slides 2,7 | 2-4 | all hydrate only those slides to editable jsx;
334
+ every other slide stays a lossless native slide with its notes, comments,
335
+ animations and embeddings intact. Re-running is safe: the same file again
336
+ changes nothing, a wider --slides hydrates just the new slides, and a
337
+ different file is reconciled onto the deck
338
+ slidemind revision <sub> <deck> Ownership and acceptance for an adopted deck
339
+ begin take the deck for a whole edit session; export the printed token
340
+ as SLIDEMIND_OWNER so every command under it re-enters
341
+ status accepted base, generation, changed slides, candidates, conflicts
342
+ accept --candidate <id> — make a build the deck's new accepted base
343
+ finish release the session (your work and candidates are kept)
344
+ slidemind rebase <deck> Move an adopted deck onto a newer copy of the same .pptx — their changes
345
+ apply, your unpublished edits stay yours, and anything both sides touched
346
+ stops for you to decide (nothing is applied until you do)
347
+ --incoming <file.pptx|revisionId> [--dry-run] [--json]
348
+ --resolve <resolution.json> apply the skeleton a conflict wrote for you
349
+ slidemind open <link|file.pptx> Open a SharePoint presentation as a deck: the LINK picks the file, one
350
+ consistent snapshot is adopted, and the deck is bound to that item.
351
+ A local path adopts only — it never guesses where to publish
352
+ --deck <slug> --slides 2,7|all
353
+ --rebind point an already-bound deck at this item instead
354
+ --keep | --detach local file, on a deck that is already bound
355
+ slidemind pull <deck> Check the bound file and every linked input it names. Unchanged costs one
356
+ metadata call and downloads nothing. A newer save is kept aside until your
357
+ own work is published, then applied
358
+ --check report freshness only (never stages, never changes anything)
359
+ slidemind publish <deck> Save the deck back to the file you opened. It pulls and reconciles first,
360
+ runs every required check on the bytes it is actually about to upload, and
361
+ replaces the file only if nobody saved in the meantime — if somebody did,
362
+ their save is kept and yours is not lost. build-pptx does this for you;
363
+ run it to retry a save that did not go through
364
+ --candidate <id> --manual --shared-workbook --json
365
+ slidemind rename <deck> --name <file> Rename the file you are bound to. Same file, nothing re-rendered
366
+ slidemind record <sub> Share ONE JSON file so several people and their agents can edit it at
367
+ once; the backend merges, so different fields combine instead of
368
+ overwriting. The CLI never reads what is in the file
369
+ create <deck> --folder <link> --name <file.json> --file <path>
370
+ share it and print the permanent link
371
+ open <link> --deck <slug> --file <path>
372
+ fetch a shared record into a (new) deck
373
+ sync <deck> --file <path> [--approval] [--resolve <file>]
374
+ send yours, get everyone's back merged; a same-field
375
+ clash writes state/record-conflicts.json and exits 3
376
+ status <deck> current | behind (v…) | local edits
377
+ --json on every subcommand
324
378
  slidemind download-bundle [deck] Materialize the active corporate design locally (host required; lower-level — `ready` covers this)
325
379
  slidemind read [presId|file.pptx] Read an open presentation (presId; host required) or a local .pptx on disk (file path; host-free)
326
380
  --mode summary|raw (default raw) [--to <presId>] [--json]
@@ -328,7 +382,8 @@ slidemind setup <claim> One-command onboarding: connect + global instal
328
382
  --for <target> --no-install --no-ready --json
329
383
  slidemind login [--backend <e>] Sign in to Microsoft 365 (opens your browser) so SharePoint-backed
330
384
  downloads and slide extractions work without an open PowerPoint window
331
- slidemind whoami Show connected environment(s) and their Microsoft 365 sign-in state
385
+ slidemind whoami [--json] Show connected environment(s) and their Microsoft 365 sign-in state,
386
+ named as the account that signed in
332
387
  slidemind logout [url|env] Unpair an environment (--all unpairs every one; drops its Microsoft 365 sign-in too)
333
388
  slidemind init --for <target> Install the skill into a harness (clears the bundle cache)
334
389
  <target> = claude | codex | opencode | all | auto (every harness found here)
@@ -345,19 +400,67 @@ slidemind --version Print version
345
400
 
346
401
  | Command | Output | When to use |
347
402
  |---|---|---|
348
- | `slidemind view-draft <deck>` | `decks/<deck>/.draft-preview/*.png` (+ `presentation.html`) | Look at each slide before anyone else does (offline) |
403
+ | `slidemind view-draft <deck>` | `decks/<deck>/.slidemind/preview/draft/*.png` (+ `preview/presentation.html`) | Look at each slide before anyone else does (offline) |
349
404
  | `slidemind build-pptx <deck>` | `decks/<deck>/<deck>.pptx` | An editable native PowerPoint file |
350
405
  | `slidemind push <deck>` | (streamed via the add-in) | Live insertion into an open PowerPoint window |
351
406
 
407
+ ### What a deck directory looks like
408
+
409
+ A deck keeps the two halves apart. The root holds what you asked for; everything
410
+ the CLI works with sits in a hidden `.slidemind/` beside it:
411
+
412
+ ```
413
+ decks/my-deck/
414
+ ├── my-deck.pptx the built deck
415
+ ├── plan.html the saved plan page (open it any time; `slidemind plan my-deck` to edit)
416
+ └── .slidemind/
417
+ ├── plan.md the plan record
418
+ ├── slides/ one .jsx per slide (filename order IS slide order)
419
+ ├── assets/ images and icons this deck downloaded
420
+ ├── conversions/ identity records for adopted PowerPoint slides
421
+ ├── concepts/ the concept mockups
422
+ ├── state/ gate decisions, slide identity, the design binding
423
+ └── preview/ presentation.html, fonts/, draft/, build/ — all regenerable
424
+ ```
425
+
426
+ You never need to name `.slidemind/` — every command takes the deck directory and
427
+ finds it. One command manages the directory itself:
428
+
429
+ ```bash
430
+ slidemind clean <deck> # drop preview/ and abandoned downloads; a build recreates them
431
+ ```
432
+
433
+ `clean` touches nothing a build cannot reproduce: gate decisions, concepts and a
434
+ download still in flight all stay.
435
+
436
+ `plan.html` has one owner, recorded in `.slidemind/state/plan-owner.json`. The CLI
437
+ renders it from `plan.md`; an extension pack renders
438
+ its own from its own record. Whoever does not own it leaves it alone and names the
439
+ command that opens it, so a pack deck's plan page survives a generic `slidemind
440
+ plan` or `build` untouched.
441
+
352
442
  ### Reviewing before you export
353
443
 
354
- `slidemind review <deck>` opens the HTML preview in your browser with a comment overlay and **waits** until you decide:
444
+ Your agent asks you to review in the **slidemind workspace** — a page on your computer (`127.0.0.1`) that `slidemind setup` starts and keeps running from every login. The agent ends its turn with a link; click it. In the Codex app it opens in Codex's own browser pane, next to the chat; elsewhere in your browser.
445
+
446
+ - **Plan:** read and edit the storyline, comment on any slide (press Enter to add each comment), then **Send** your comments or **Approve plan**. Approve is off while a comment is waiting to be sent.
447
+ - **Preview:** click any element on a slide to pin a comment to that spot — each is anchored to the exact slide source (`slides/<file>.jsx:line:col`) — then **Send** your comments or **Approve**. On the next round your earlier notes come back as faded "ghost" pins so you can confirm each was addressed.
448
+ - **Then paste.** Your answer is saved and a message is copied to your clipboard. Paste it into the chat with your agent and send it. That is the one thing to do after every answer: nothing can reach an agent whose turn has ended, so the message — which names the deck and the command that receives your answer — brings it back, in the same chat or a new one.
449
+
450
+ It runs entirely offline (no open PowerPoint needed) — review happens *before* the native render.
355
451
 
356
- - **Click any element** on a slide to leave a comment pinned to that spot. Each comment is anchored to the exact slide source (`slides/<file>.jsx:line:col`), so your agent knows precisely what to change.
357
- - **Approve & continue** when it looks right — the command unblocks and your agent proceeds to the export you asked for (`push` / `build-pptx`).
358
- - **Send comments** to hand your notes back to the agent; it edits the cited files and re-runs `review`, where your previous notes appear as faded "ghost" pins so you can confirm each was addressed.
452
+ ### The workspace
359
453
 
360
- It runs entirely offline (no open PowerPoint needed) — review happens *before* the native render. There's no copy-paste: the moment you approve or send comments in the browser, your coding agent picks up where it left off.
454
+ One page for everything you answer: a library of your decks, the plan editor, the preview, and an inbox of what your agents asked you to decide. Close the browser — the page and the questions stay; it restarts by itself after a reboot.
455
+
456
+ - **Add a folder** (or `slidemind workspace add <path>` / `discover <root>`) to see a deck. Nothing is rendered or uploaded because you looked at it.
457
+ - **Paste a SharePoint link** (or `slidemind workspace open-remote <url>`) to open a presentation, a shared plan, or a folder; a folder shows its children and you pick.
458
+ - **Local vs remote saving.** Every edit is saved locally at once. A plan that is shared on SharePoint syncs in the background afterwards; the status reads *Saved → Saving to SharePoint… → Saved to SharePoint*, and *Action needed* when the backend refused, you are signed out, or writes are disabled. Selecting a folder with `connect` only records a destination; the plan is *shared* once it actually exists there.
459
+ - **Conflicts** are shown as mine / theirs / merged with the exact fields; nothing is sent until you resolve them.
460
+ - **Access** is per person: the page uses your own Microsoft 365 sign-in for remote work, and the daemon answers only this machine's browser.
461
+ - **Running it yourself.** `slidemind workspace` prints its link (and opens it in a terminal); `slidemind workspace stop` ends it and keeps everything queued. `SLIDEMIND_WORKSPACE=0` brings back the old standalone review pages.
462
+
463
+ Both commands are documented in `slidemind --help`; the design is in `docs/slidemind-cli-connect/21-persistent-workspace.md`.
361
464
 
362
465
  ---
363
466
 
@@ -449,3 +552,95 @@ So an open PowerPoint host with the slidemind add-in and an active corporate des
449
552
  ---
450
553
 
451
554
  slidemind is published by **statworx**. Source lives in a private repository; the npm tarball is the install artifact. License: `UNLICENSED` (publicly installable, proprietary).
555
+
556
+
557
+ ### Concept-based authoring and existing-slide edits
558
+
559
+ After plan approval, run `slidemind concepts <deck>` then `slidemind transcribe <deck>`.
560
+ Concepts are read into compact specifications; transcription creates editable JSX, settles
561
+ initial geometry and fetches requested assets. Compare the concept and draft images, repair
562
+ `slides/*.jsx`, then run the usual draft, review and delivery commands. Missing assets stay
563
+ explicit. `SLIDEMIND_SPEC_SCHEMA=legacy` supports an older reader deployment.
564
+
565
+ Existing-slide edits patch current JSX directly. Imported PowerPoint slides retain the
566
+ PPTX → JSX conversion and native-object preservation workflow; they do not need concepts.
567
+ `transcribe --only NN` can settle a generated slide during reconstruction, but may move
568
+ neighbouring content. Do not use it as an automatic step for a small edit or converted slide.
569
+
570
+ Existing-slide edits are not limited to changing words: adding elements and restructuring
571
+ them is supported. What is protected is what the slide promised to keep.
572
+
573
+ If a generated slide is right in substance but slightly off in layout, `slidemind transcribe
574
+ <deck> --repair` nudges it back rather than rebuilding it. It runs inside a scope you open first
575
+ (`slidemind revision begin <deck> --operation repair --slides <sel>`), and that scope is what
576
+ authorizes it — the file's own contents never do. What you are agreeing to is bounded and
577
+ measured from the original slide, not from the previous attempt: at most three passes, at most a
578
+ few slot-pixels of movement and a ten-percent size change per element, and **no** change to text,
579
+ images, the number of elements, or what a connector joins. It refuses an imported slide, a slide
580
+ it has no transcription record for, and a slide it cannot parse — each before touching anything.
581
+
582
+ **Edits cannot quietly drop things.** A deck rebuilt from a PowerPoint file (`slidemind adopt`)
583
+ records, per slide, the elements that have to survive an edit — connectors and what they join,
584
+ images and the file each points at, tables, and preserved native objects. If an edit loses one,
585
+ `slidemind view-draft` names it:
586
+
587
+ ```
588
+ [preserve:warn] 04-pricing — #conn-tier-a-tier-b: missing — is required on this slide and is
589
+ not in the evidence — restore it in slides/04-pricing.jsx, or supersede the obligation
590
+ explicitly (`slidemind revision begin pricing --operation targeted-edit`); a final
591
+ replacement refuses while it stands.
592
+ ```
593
+
594
+ `view-draft` only reports it; `slidemind build-pptx` and `slidemind push` refuse until it is
595
+ resolved. You do **not** have to start a session for this — an adopted deck is protected from
596
+ the moment it is adopted, and a deck you authored from scratch is never gated by it. If you
597
+ meant to remove the element, say so once with
598
+ `slidemind revision begin <deck> --operation targeted-edit --slides <sel>`; that scope is what
599
+ authorizes the removal.
600
+
601
+ Evidence a draft cannot give is *unknown*, never a pass, and whether it stops the build
602
+ depends on the slide — one deck can hold both kinds:
603
+
604
+ - **A slide that came from a PowerPoint file** can be checked against that file. Things like a
605
+ connector's endpoints and a native object's embedded package normally resolve and the build goes
606
+ ahead. If one of them could have been checked and was not, the build **stops**, the same as for a
607
+ `[preserve:warn]`.
608
+ - **A slide you authored from scratch** has no original file to check against, so some obligations
609
+ cannot be proved either way. Those **ship**, with one line naming exactly what was not proved.
610
+ Stopping there would demand evidence that cannot exist.
611
+
612
+ The build also stops if you changed a slide and have not run `slidemind view-draft` since, because
613
+ then nothing has checked the bytes you are about to ship.
614
+
615
+ Both places you can use slidemind follow the same rule — proof is demanded where proof is possible —
616
+ and on most decks they behave identically. A deck you authored has no original file on either side,
617
+ so the same slides ship with the same note whether you build from the command line or the PowerPoint
618
+ add-in. They differ on one case only: a slide that came from a PowerPoint file, which the command
619
+ line can check and the add-in currently cannot. So the add-in is not a way around a refusal — if the
620
+ command line stopped on such a slide, that slide has something to fix.
621
+
622
+ ### Images you supply
623
+
624
+ An image you hand the agent — a screenshot, a diagram, a photo — is kept as itself. Two steps,
625
+ deliberately separate:
626
+
627
+ 1. **Import the bytes.** `slidemind assets import <deck> <file>` copies the file into the deck and
628
+ identifies it by its own digest. It takes file paths, never URLs, and it promises nothing about
629
+ where the picture goes.
630
+ 2. **Approve what it is for.** The agent records a *use* on a slide in `plan.md`, and you see it on
631
+ that slide's card at the plan gate: `original` (place exactly this file), `reconstruct` (rebuild
632
+ it as editable slide content — the whole slide, or one element inside it), or `reference` (it
633
+ guides the look; no picture required). One file can have several uses, on several slides.
634
+
635
+ An `original` is never searched for, regenerated, recoloured or swapped for something similar. If
636
+ its file goes missing or its bytes change, `slidemind view-draft` says so per slide, and
637
+ `slidemind build-pptx` / `slidemind push` refuse until it is restored — including when the add-in
638
+ returned no verdict at all, because a skipped check is not a pass.
639
+
640
+ This needs a slidemind add-in that supports image intent. On an older deployment a deck with
641
+ approved image uses stops **before** anything is generated, names the capability, and leaves your
642
+ plan and your files exactly as they were. Decks with no image uses are unaffected.
643
+
644
+ What the checks prove is structural: the right bytes, on the right slide, once, inside the slide,
645
+ not hidden. They cannot prove the picture is visible — something drawn over it would still pass —
646
+ so the draft preview and the review gate remain the place that is caught.
package/bin/slidemind.mjs CHANGED
@@ -30,19 +30,27 @@ import fs from "node:fs";
30
30
  import { register as registerSecret, scrub } from "../src/bridge/secrets.mjs";
31
31
  import { announceUpdate } from "../src/update-check.mjs";
32
32
  import { readPackageJson, fail } from "../src/cli/common.mjs";
33
+ import { cmdAssets } from "../src/cli/assets.mjs";
33
34
  import { cmdConceptImages } from "../src/cli/concepts.mjs";
35
+ import { cmdTranscribe } from "../src/cli/transcribe.mjs";
34
36
  import { cmdPlan, cmdReview, cmdImagen, cmdInspectTemplateDeck, cmdBuildPptx, cmdViewDraft } from "../src/cli/deck.mjs";
35
37
  import { cmdDownloadBundle } from "../src/cli/download-bundle.mjs";
36
38
  import { cmdViewSlide, cmdReadSource, cmdDownloadResult } from "../src/cli/engine-results.mjs";
37
39
  import { printHelp } from "../src/cli/help.mjs";
38
40
  import { cmdInstall, cmdUninstall, cmdUpdate } from "../src/cli/install.mjs";
41
+ import { cmdClean } from "../src/cli/maintenance.mjs";
39
42
  import { cmdRead } from "../src/cli/read.mjs";
43
+ import { cmdRecord } from "../src/cli/record.mjs";
40
44
  import { cmdReady } from "../src/cli/ready.mjs";
41
45
  import { cmdSearch, cmdLs } from "../src/cli/search.mjs";
42
46
  import { cmdLogin, cmdWhoami, cmdLogout } from "../src/cli/session.mjs";
43
47
  import { cmdSetup } from "../src/cli/setup.mjs";
44
48
  import { cmdInsertSlide, cmdAddSlide } from "../src/cli/slide-reuse.mjs";
45
49
  import { cmdAdopt, cmdPush, cmdNew } from "../src/cli/workspace.mjs";
50
+ import { cmdWorkspace } from "../src/cli/workspace-ui.mjs";
51
+ import { cmdTasks } from "../src/cli/tasks.mjs";
52
+ import { cmdRebase, cmdRevision } from "../src/cli/revision.mjs";
53
+ import { cmdOpen, cmdPull, cmdPublish, cmdRename } from "../src/cli/remote.mjs";
46
54
 
47
55
  // Pull a global `--backend <url|env>` out of argv (it may appear anywhere) and
48
56
  // expose it as SLIDEMIND_BACKEND, which scopes the fan-out across paired
@@ -182,9 +190,15 @@ async function main(rawArgv) {
182
190
  case "download-result":
183
191
  await cmdDownloadResult(rest);
184
192
  return 0;
193
+ case "assets":
194
+ await cmdAssets(rest);
195
+ return 0;
185
196
  case "concepts":
186
197
  await cmdConceptImages(rest);
187
198
  return 0;
199
+ case "transcribe":
200
+ await cmdTranscribe(rest);
201
+ return 0;
188
202
  case "download-bundle":
189
203
  await cmdDownloadBundle(rest);
190
204
  return 0;
@@ -209,12 +223,45 @@ async function main(rawArgv) {
209
223
  case "read":
210
224
  await cmdRead(rest);
211
225
  return 0;
226
+ case "record":
227
+ await cmdRecord(rest);
228
+ return 0;
212
229
  case "adopt":
213
230
  await cmdAdopt(rest);
214
231
  return 0;
232
+ case "workspace":
233
+ // The persistent local workspace (src/cli/workspace-ui.mjs); sets its own
234
+ // exit code (0/1/2/3) on process.exitCode instead of throwing.
235
+ await cmdWorkspace(rest);
236
+ return 0;
237
+ case "tasks":
238
+ // Durable tasks (src/cli/tasks.mjs); exit code on process.exitCode like `workspace`.
239
+ await cmdTasks(rest);
240
+ return 0;
241
+ case "revision":
242
+ await cmdRevision(rest);
243
+ return 0;
244
+ case "rebase":
245
+ await cmdRebase(rest);
246
+ return 0;
247
+ case "open":
248
+ await cmdOpen(rest);
249
+ return 0;
250
+ case "pull":
251
+ await cmdPull(rest);
252
+ return 0;
253
+ case "publish":
254
+ await cmdPublish(rest);
255
+ return 0;
256
+ case "rename":
257
+ await cmdRename(rest);
258
+ return 0;
215
259
  case "push":
216
260
  await cmdPush(rest);
217
- return 0;
261
+ break;
262
+ case "clean":
263
+ await cmdClean(rest);
264
+ break;
218
265
  case "init":
219
266
  case "install":
220
267
  // Set slidemind up in a coding harness (deploy the skill).
@@ -255,6 +302,7 @@ main(rawArgv)
255
302
  });
256
303
  if (err) {
257
304
  process.stderr.write(`slidemind: ${err.message || err}\n`);
258
- process.exit(1);
305
+ // a script that ran under us keeps its exit code (runNode): 2 = blocked
306
+ process.exit(Number.isInteger(err.exitCode) && err.exitCode > 0 ? err.exitCode : 1);
259
307
  }
260
308
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "slidemind",
3
- "version": "0.3.20",
3
+ "version": "0.4.0",
4
4
  "description": "Connect Claude Code, Codex & opencode to the slidemind PowerPoint add-in — let your coding agent build and edit native, on-brand PowerPoint decks against your active corporate design, from the terminal.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -32,7 +32,7 @@
32
32
  "build-pptx": "node bin/slidemind.mjs build-pptx",
33
33
  "lint:parity": "node scripts/check-skill-parity.mjs",
34
34
  "release": "node scripts/release.mjs",
35
- "test": "node --test"
35
+ "test": "node --test --import ./test/support/isolate-config.mjs 'test/*.test.mjs'"
36
36
  },
37
37
  "dependencies": {
38
38
  "@clack/prompts": "^1.3.0",