@taloswork/ose-shared 0.1.9 → 0.1.11

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 (62) hide show
  1. package/mcp/gen/mcp.json +2 -2
  2. package/package.json +3 -3
  3. package/skills/diagram-design/SKILL.md +1 -1
  4. package/skills/document/SKILL.md +63 -75
  5. package/skills/document/bin/deck-build.cjs +51 -1
  6. package/skills/document/bin/deck-qa.cjs +18745 -279
  7. package/skills/document/bin/doc-convert.cjs +9280 -76489
  8. package/skills/document/bin/doc-fill.cjs +0 -0
  9. package/skills/document/bin/doc-gen.cjs +3043 -46825
  10. package/skills/document/bin/doc-run.cjs +65095 -1967
  11. package/skills/document/bin/doc-scan.cjs +0 -0
  12. package/skills/document/bin/doc-text.cjs +0 -0
  13. package/skills/document/bin/doc-validate.cjs +18067 -226
  14. package/skills/document/bin/doc-xml.cjs +1 -1
  15. package/skills/document/bin/docx-annotate.cjs +0 -0
  16. package/skills/document/bin/html2pptx.cjs +32498 -145280
  17. package/skills/document/bin/ocr-worker.cjs +0 -0
  18. package/skills/document/bin/ocr.cjs +0 -0
  19. package/skills/document/bin/pdf-form.cjs +0 -0
  20. package/skills/document/bin/pdf-images.cjs +0 -0
  21. package/skills/document/bin/pdf-ops.cjs +0 -0
  22. package/skills/document/bin/pdf-render.cjs +11 -9
  23. package/skills/document/bin/pdf-tables.cjs +0 -0
  24. package/skills/document/bin/pptx-clone.cjs +21 -25
  25. package/skills/document/bin/pptx-embed-fonts.cjs +8 -6
  26. package/skills/document/bin/pptx-set-image.cjs +0 -0
  27. package/skills/document/bin/pptx-slide.cjs +22 -32
  28. package/skills/document/bin/pptx-theme.cjs +1 -20
  29. package/skills/document/bin/pptx-tokenize.cjs +1 -1
  30. package/skills/document/bin/xlsx-query.cjs +0 -0
  31. package/skills/document/bin/xlsx-recalc.cjs +0 -0
  32. package/skills/document/bin-reference.md +35 -0
  33. package/skills/document/content-pipeline.md +19 -18
  34. package/skills/document/deck-design.md +110 -211
  35. package/skills/document/layouts/README.md +4 -33
  36. package/skills/document/motion/README.md +4 -2
  37. package/skills/document/office.md +5 -1
  38. package/skills/document/rewrite.md +43 -99
  39. package/skills/document/styles/README.md +0 -7
  40. package/skills/document/theme-system.md +1 -0
  41. package/skills/document/themes/README.md +5 -5
  42. package/skills/document/themes/anthropic-clay.json +1 -7
  43. package/skills/document/themes/apple-keynote.json +1 -7
  44. package/skills/document/themes/black-gold.json +1 -2
  45. package/skills/document/themes/cinereel.json +1 -2
  46. package/skills/document/themes/cool-tech.json +1 -2
  47. package/skills/document/themes/hand-drawn.json +1 -2
  48. package/skills/document/themes/ivory-gold.json +1 -2
  49. package/skills/document/themes/magazine-ink.json +1 -2
  50. package/skills/document/themes/mckinsey-consulting.json +1 -7
  51. package/skills/document/themes/mono.json +1 -2
  52. package/skills/document/themes/swiss-grid.json +1 -2
  53. package/skills/document/themes/warm-editorial.json +1 -2
  54. package/skills/image-layout/SKILL.md +1 -1
  55. package/skills/image-layout/bin/html2img.cjs +0 -0
  56. package/skills/cozy-static-svg/SKILL.md +0 -76
  57. package/skills/cozy-static-svg/references/approved-preview.png +0 -0
  58. package/skills/cozy-static-svg/references/cross-platform.md +0 -73
  59. package/skills/cozy-static-svg/references/moon_keeps_watch.svg +0 -229
  60. package/skills/cozy-static-svg/references/style-anchor.md +0 -271
  61. package/skills/cozy-static-svg/scripts/artkit.py +0 -321
  62. package/skills/cozy-static-svg/scripts/to_png.py +0 -333
package/mcp/gen/mcp.json CHANGED
@@ -12,9 +12,9 @@
12
12
  "TALOS_API_KEY": "${TALOS_GATEWAY_API_KEY}",
13
13
  "TALOS_GATEWAY_BASE_URL": "${TALOS_GATEWAY_BASE_URL}"
14
14
  },
15
- "timeoutMs": 600000,
15
+ "timeoutMs": 720000,
16
16
  "connectTimeoutMs": 30000,
17
- "supportsParallelToolCalls": false,
17
+ "supportsParallelToolCalls": true,
18
18
  "metadata": {
19
19
  "provides": "talos/gen",
20
20
  "title": "文生图/视频 · Talos 计费",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@taloswork/ose-shared",
3
- "version": "0.1.9",
3
+ "version": "0.1.11",
4
4
  "description": "Talos cross-OSE shared library — skills + MCP servers auto-loaded into every OSE (P93 2026-07-27).",
5
5
  "type": "module",
6
6
  "files": [
@@ -10,6 +10,6 @@
10
10
  "publishConfig": {
11
11
  "access": "public"
12
12
  },
13
- "_talosPublishHash": "sha256-G225GKl7MFuGzmHVNTAmkcBmcOohJvs3RLcQOy4ffEo",
14
- "_talosPublishedAt": "2026-09-21T07:29:20.819Z"
13
+ "_talosPublishHash": "sha256-JzD-VeYh0UJfwZYHueL8DpxlsjlDOEJGiSdOaX70yIg",
14
+ "_talosPublishedAt": "2026-09-28T08:42:12.912Z"
15
15
  }
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: diagram-design
3
- description: Create branded architecture, IT current-state, flowchart, sequence, state machine, ER/data model, timeline, swimlane, quadrant, radar/spider, loop/flywheel, nested, tree, org chart, layer stack, Venn, pyramid/funnel, bar, line, Gantt and scatter charts, high-level, process, medallion, data flow, DP integration, or DP security matrix diagrams as standalone HTML/SVG/PNG. Redraw .drawio/.drawio.png/.drawio.svg or Mermaid .mmd sources at a chosen size/detail; onboard brand tokens from a website; add semantic patterns, callouts, accessible motion, or sketchy/hand-drawn styling.
3
+ description: Create branded architecture, data flow, flowchart, sequence, state machine, ER/data model, timeline, swimlane, quadrant, radar, flywheel, tree, org chart, layer stack, Venn, pyramid/funnel, and bar/line/Gantt/scatter diagrams as standalone HTML/SVG/PNG. Also redraws .drawio or Mermaid sources, onboards brand tokens from a website, and adds callouts, motion or hand-drawn styling.
4
4
  license: MIT
5
5
  metadata:
6
6
  version: "2.3"
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  name: document
3
- description: "Use this skill whenever a document attachment (PDF, .docx, .pptx, or .xlsx) is the input and the user wants it read, summarized, translated, searched, or its tables/formulas/figures interpreted — OR whenever the user asks to CREATE/GENERATE a document FILE (PDF, Word, PowerPoint, Excel) from scratch, edit an existing one, or CONVERT a document to another format (转成/转换/导出 PDF, .docx/.pptx → PDF, convert/export to PDF). For generating any document file ALWAYS use this skill's doc-gen script, and for docx/pptx→PDF conversion ALWAYS use its doc-convert script — never hand-write a python / ReportLab / LibreOffice / textutil / headless-browser pipeline for document output. Talos routes most inbound documents to local text extraction by default; reach for this skill's scripts for page rendering (formulas/scanned/figures), spreadsheet computation, document generation, or format conversion. Do NOT trigger for images (handled natively) or plain .txt/.md/.csv already inlined as text."
3
+ description: "Use for document FILES. Reading: a PDF, .docx, .pptx or .xlsx attachment to read, summarize, translate or search when its pages must be rendered (formulas, scans, figures) or a sheet computed — others arrive as extracted text. Writing: any request to create or edit a Word, PowerPoint, Excel or PDF file, or convert one (转成/导出 PDF, .docx/.pptx → PDF). ALWAYS use its scripts — doc-gen (docs), html2pptx (decks, and a deck made here to PDF), doc-convert (an existing file to PDF); never hand-write a python/ReportLab/LibreOffice/browser pipeline. Do NOT trigger for images or plain .txt/.md/.csv."
4
4
  license: Proprietary. LICENSE.txt has complete terms
5
5
  ---
6
6
 
@@ -26,6 +26,14 @@ script only when:
26
26
  exact (don't do the arithmetic yourself).
27
27
  - **Formula / figure / scanned / exact layout matters** AND you can see images
28
28
  → read **vision.md**; `bin/pdf-render` a page, then look.
29
+ - **A deck you built here, as PDF**(PPT 要 PDF / 导出 PDF / deck as PDF)→ print
30
+ its `deck.html` with the same STYLE flags you rendered the .pptx with (leave out
31
+ `--editable` / `--rasterize` / `--notes-doc`, which are .pptx-only):
32
+ `bin/html2pptx.cjs deck.html out.pdf --style <id> [--theme-v2 …] [--backdrop …]`.
33
+ One 16:9 page per slide, vector text (selectable, searchable), links clickable.
34
+ Do not route it through `doc-convert` (that re-lays out the .pptx) and never
35
+ assemble slide PNGs into a PDF (image pages: no text, no links). If the result
36
+ reports `pages` ≠ `slides`, a slide overflows its canvas — fix it and print again.
29
37
  - **Convert** a .docx/.pptx/.xlsx to PDF(转成/转换/导出 PDF / convert to PDF)→
30
38
  `bin/doc-convert.cjs <in.docx|pptx|xlsx> <out.pdf>`. This is FAITHFUL conversion —
31
39
  the source's content, structure and images with neutral print styling; do not
@@ -39,6 +47,10 @@ script only when:
39
47
  template) → read **rewrite.md**, use `doc-gen` / `doc-fill`. **Always** produce
40
48
  document files via these scripts — never hand-write a python / ReportLab /
41
49
  LibreOffice script for document output.
50
+ **A length limit** (正文 1000 字以内 / under 800 words) is kept in the spec,
51
+ before generating: after a PDF, `doc-gen` prints `textChars` (spaces and URLs
52
+ not counted) — over the limit, shorten the spec and generate once more. Do not
53
+ extract text from the output to count it.
42
54
  **Any deck/presentation(路演/汇报/评审/宣讲/pitch/roadshow/介绍 PPT)**:
43
55
  **CLARIFY FIRST — HARD GATE (applies to EVERY deck).** Before authoring, collect
44
56
  three brief fields: **(1) content source** (提供材料 / 联网调研 / 自由创作);
@@ -117,53 +129,28 @@ script only when:
117
129
  Then render a cover+content sample of the result and confirm (same image-card step as
118
130
  a normal pick) before authoring; save the resulting preference to memory.
119
131
 
120
- **THE deck method — html2pptx HYBRID with catalog-governed V1/V2 composition.**
121
- Modern entries compose **Theme + component profile + media style + art direction +
122
- content-selected layouts**; frozen `classic-v1` entries keep family paint only:
123
- 1. **Read deck-design.md** (⭐ PREFERRED workflow) + **`layouts/README.md`**
124
- (every layout tagged role · structure · density · has-image; that index is
125
- the source of truth for which layouts exist).
126
- 2. **Plan pages, pick layouts** from `layouts/profiles.json` by intent, then by
127
- **P1/P2/P3** (structure → density → **≤2 dedup**;
128
- `html2pptx` warns on repeats). Paste each `layouts/<id>.tpl` into `deck.html`
129
- (they carry `data-layout`), fill REAL content — **never hardcode a brand hex**
130
- (leave color to the skin; `html2pptx` warns on hardcoded colors). 8 roles:
131
- cover/title/toc/section/transition/content/ending + special charts
132
- (gantt/radar/funnel/ring/org-tree/map/data-table/stats-chart).
133
- **A layout with a `{{#rows}}` block (gantt · radar · ring-progress ·
134
- map-distribution · team-row · brand-values · color-palette · steps-vertical ·
135
- toc-panel) must go through `deck-build`** — it repeats the block per row AND
136
- computes the geometry (bar spans, ring arcs, pin positions, the radar chart)
137
- from your numbers. Hand-pasting one leaves `{{#…}}` markers in the deck, or a
138
- drawing that contradicts its own labels.
139
- For Theme V2, keep each slide's semantic `intent`: `deck-build` uses it to derive
140
- the `hero/content/data/media/closing` art scene and balance low/medium/high decoration
141
- across the deck. Do not hand-assign every scene; override `scene` or `decorDensity`
142
- only for a deliberate exception. `decorRhythm:"steady"` disables auto balancing.
143
- For `classic-v1`, choose only pre-V2 layouts and omit scene/decor controls.
144
- 3. **Render:** modern entry → `bin/html2pptx.cjs deck.html out.pptx --style <id>
145
- --theme-v2 [--media-style <id>] [--backdrop <variant>]`; frozen classic entry →
146
- `bin/html2pptx.cjs deck.html out.pptx --style <id> [--backdrop <variant>]`.
147
- DEFAULT hybrid (no `--editable`/`--rasterize`): pixel-perfect
148
- visuals baked into a backdrop + native EDITABLE text and native `data-chart`
149
- on top. Theme V2 injects the compatible V1 family paint plus semantic component,
150
- media and art-direction layers; it never chooses a layout. Chromium gives the full CSS toolbox (Tailwind
151
- + a `size="1".."7"` scale, gradients, shadows, per-element SVG, `<img>`
152
- auto-inline, speaker notes) → NATIVE editable pptx.
153
- **For a substantive deck, first read content-pipeline.md** (premium-deck method:
154
- clarify + persist brief → research → narrative structure → one outline gate → author from
155
- `layouts/` → fast HTML preview → final PPTX QA; premium density = rich VISUAL + sparse TEXT, details to
156
- speaker notes). **Do NOT build a deck with `doc-gen pptx` archetypes or `doc-run`
157
- PptxGenJS — those deck paths are OFF.** (html2pptx needs a browser: the app's
158
- Chromium service or bundled Playwright; if neither, say so and stop — never
159
- silently fall back to a lesser deck.) End with the mandatory hostile-review loop
160
- (deck-design.md). *(The legacy `themes/*.json` + `--theme` recolor path is for
161
- doc-gen DOCUMENTS; for decks use `--style` + `layouts/`.)*
162
- - **After ANY generated/edited file** (doc-gen / doc-fill / docx-annotate /
163
- pptx-clone / doc-xml pack / hand-written scripts): run
164
- `bin/doc-validate.cjs <file>` — exit 1 means fix it before delivering. Then
165
- **render-and-look** at the output before delivery (see "Verify generated
166
- output" below) — `doc-validate` proves well-formed, not good-looking.
132
+ **Then build it — the method lives in deck-design.md.** For a substantive deck read
133
+ **content-pipeline.md** first (brief → research → narrative → one outline gate), then
134
+ **deck-design.md** (workflow and delivery sign-off) and **`layouts/README.md`** (the
135
+ layout index and fill rules). In short: pick layouts from `layouts/profiles.json` by
136
+ slide intent; fill them with `deck-build` (required for any layout with a `{{#rows}}`
137
+ block — it computes the geometry; put the confirmed scenario in its spec as
138
+ `"scenario"` — read decks such as 内审/报告/培训 then get no animation); render with `bin/html2pptx.cjs deck.html out.pptx
139
+ --style <id>` (+ `--theme-v2` for modern entries, never for `classic-v1`) — DEFAULT
140
+ hybrid: baked visuals, native editable text. `doc-gen` makes no decks and the doc-run
141
+ PptxGenJS deck path is OFF. html2pptx needs a browser (the app's Chromium or bundled
142
+ Playwright); without one, say so and stop — never fall back to a lesser deck.
143
+ - **Generators check their own output.** `doc-gen` and `html2pptx` report
144
+ validity in the step that wrote the file — `valid: false` exits 1, fix before
145
+ delivering; never re-run `doc-validate` on their output. `doc-gen pdf` prints
146
+ `{valid, pages, textChars, cjkChars, previews}` (a ≈72dpi PNG per page — read
147
+ those, do not re-render or count characters yourself); `doc-gen docx` prints
148
+ `{valid, textChars, cjkChars}`, `xlsx` `{valid}`; `html2pptx` adds `valid` and
149
+ `qa` (deck-qa's findings) to its result. **After any other edit** (doc-fill /
150
+ docx-annotate / pptx-clone / pptx-slide / doc-xml pack / hand-written scripts)
151
+ run `bin/doc-validate.cjs <file>` yourself — exit 1 means fix it. Valid is not
152
+ good-looking: **render-and-look** before delivery (see "Verify generated
153
+ output" below; decks sign off with `deck-qa --final`).
167
154
  - **Raw XML edit** (when no targeted tool fits): `doc-xml unpack` → edit →
168
155
  `doc-xml pack` → `doc-validate` (see rewrite.md "Raw XML editing").
169
156
  - **PDF** whose inlined text is garbled/missing where the answer should be →
@@ -204,39 +191,40 @@ Fidelity-decision self-correct, but pointed at your OWN output:
204
191
  blank CJK** (a missing-font symptom, not a content bug); colliding
205
192
  headers/footers; leftover `{{tokens}}` / "lorem" / "undefined".
206
193
  3. **Fix → re-render the affected pages.** One fix often creates another; repeat
207
- until a clean pass. Scale rigor to the artifact: a one-page memo = one look; a
194
+ until a clean pass. Fix what is broken — clipped, overlapping, unreadable, tofu —
195
+ not how full a page looks: unless the user asked for a page count, never
196
+ resize fonts, line height or margins to fill a short last page or squeeze onto
197
+ fewer pages. Page breaks already keep a heading with its text and never strand
198
+ a single line, so a heading near a page edge is not something to fix. Layout and styling taste gets at most
199
+ TWO fix rounds: after the second, deliver and name what is still imperfect instead
200
+ of regenerating again. Scale rigor to the artifact: a one-page memo = one look; a
208
201
  multi-page report/deck = every page, ideally a sub-agent for fresh eyes.
209
202
  4. **Vision unavailable**: say so and rely on `doc-validate` + a text re-extract
210
203
  (`doc-text`) as a weaker proxy — never claim the layout is verified.
211
204
 
212
205
  ## Scripts (run via bash; output returns to context, the script itself does not)
213
206
 
214
- - `bin/doc-scan.cjs <file.pdf>` — per-page signals as JSON.
215
- - `bin/doc-text.cjs <file.pdf>` — extract a PDF's text layer.
216
- - `bin/pdf-render.cjs <file.pdf> <pages|all> [scale]` — render pages to PNG for vision (`pages` = `3` | `2-5` | `all`). `scale` (default `2` ≈ 144dpi) trades resolution for vision tokens: pass `1` (≈72dpi, ¼ the pixels ≈ ¼ the tokens) for slide-composition/layout QA; keep `2` when fine print must stay legible (formulas/tables). Reading previews is the priciest step in the deck loop — render cheap + read only what changed.
217
- - `bin/pdf-images.cjs <file.pdf> [pages]` — extract EMBEDDED images at native resolution with page placement (`pages` = `N` | `N-M` | `all`, default all). Prints a JSON manifest (page/index/bbox/size/path). Use this — not a full-page `pdf-render` — when you need the original figures/photos as their own files (e.g. rebuilding a deck). Vector/text-only pages yield nothing → fall back to `pdf-render`.
218
- - `bin/pdf-tables.cjs <file.pdf> [page] [minCols]` — recover text-layer tables as rows (ruled/scanned tables need render + vision instead).
219
- - `bin/ocr.cjs <image.png|jpg> [lang]` — read text off a scanned image (tesseract.js). For a scanned PDF, `pdf-render` a page first, then OCR the PNG. Language data downloads on first use / set `$TALOS_TESSDATA` for offline. **Prefer vision** when a vision model is available; OCR is the text-only fallback.
220
- - `bin/xlsx-query.cjs <file> [--summary | --agg <sheet> <col> <op> | --sample <sheet> [n]]` — spreadsheet compute.
221
- - `bin/doc-gen.cjs <docx|xlsx|pptx|pdf> <out> <spec.json> [--theme <theme.json>] [--topic <subject> | --palette <id>] [--design native|html]` — generate documents from scratch. DOCX/PDF body fields are exactly `paragraphs` and/or `blocks` (never `sections`); unknown fields and empty bodies fail with `DOC_SPEC_INVALID` before any output is written (`allowCoverOnly:true` is the explicit title-only opt-in). Correct the reported JSON path and rerun. `--theme` applies a presentation theme (colors/fonts/cover/header/footer/pptx master — see rewrite.md "Themes"; built-ins in `themes/`). **`--topic <subject>` (pptx, when no `--theme`) picks a topic-adaptive palette** so the deck is designed-for-subject instead of template-flat, and turns on richness (motif + gradient wash + depth). `--palette <id>` forces a specific palette (`doc-gen --list-palettes` prints them). **`--accent <#hex>` / `--style <skin>` (docx/pdf)**: white-paper-black-text base with ONE brand color on H1/H2 + a faint table-header tint — the practical doc shape (a document is read/printed/edited, not projected, so body text stays near-black). `--accent` takes a literal hex; `--style <skin>` pulls just the `--accent` from `styles/<skin>/skin.css` (the deck skin's full palette is NOT carried onto paper). Precedence: `--theme` > spec `"theme"` > `--accent`/`--style` > `--palette`/`--topic` > default. `--design html` (pptx only, in-app) renders eligible slides through designed HTML templates for a magazine look — richer but a flat collage (no master structure); auto-falls back to native when headless or a slide has no template. Default `native` (structured, editable, charts, headless-safe).
222
- - `bin/doc-convert.cjs <in.docx|pptx|xlsx> <out.pdf> [--cache-dir <dir>]` — faithful docx/pptx/xlsx → PDF conversion. Engine precedence (best fidelity first, each downgrade tagged on stdout `[pdf (…)]` + warned on stderr): (1) **LibreOffice** if a system `soffice` is found — true layout render (page geometry, headers/footers, text-box positions, native charts), offline; (2) **LibreOffice sidecar** if `TALOS_OFFICE_URL` is set — same true-layout fidelity via a remote converter (e.g. Gotenberg), needs network; (3) **Chromium** (in-app) — reconstructed HTML, content/structure/images preserved but in-document layout is not (pptx = one page per slide); (4) **pdf-lib text-only** headless last resort — images/tables flatten. `--cache-dir` (or `TALOS_OFFICE_CACHE_DIR`) reuses a content-hashed local LibreOffice result for the exact same immutable artifact; caching is opt-in so document bytes are not retained by default. Surface the resulting `[pdf (engine)]` caveat to the user. NOTE: spreadsheets (xlsx/xls/ods) render ONLY via tiers 1–2 (real LibreOffice); tiers 3–4 do not rebuild spreadsheets, so with no LibreOffice available the command errors (never a degraded text-only sheet).
223
- - `bin/doc-validate.cjs <file.docx|pptx|xlsx> [--strict] [--design-lint]` — structural OOXML validation gate (zip/parts/rels/Content_Types/XML well-formedness); run after every generation or edit; exit 1 = broken, fix before delivering. `--strict` adds full ECMA-376 schema (XSD) validation of every recognised part — REQUIRED after custom-code (doc-run/html2pptx) or raw-XML output; a strict failure means the file is non-standard even if Office opens it. `--design-lint` (pptx only) adds an ADVISORY design pass — flags `text-only-slide` (a wall of text with no visual anchor), `low-contrast-text`, `placeholder-text` (a layout pasted but never filled — 替换为…/占位/Lorem still in the slide), `font-mismatch` (CJK text set in a Latin-only font → 豆腐; expected language defaults to the system locale, override with `TALOS_DECK_LANG`), `off-canvas`, `tiny-font`, `shape-overlap`; findings are warnings (never change the exit code) but are real design bugs — fix them. See deck-design.md "Design principles".
224
- - `bin/deck-qa.cjs <file.pptx> [--json]` — MECHANICAL design QA (deterministic, token-free): reads slide XML and flags `off-canvas` (content clipped past the edge), `tiny-font` (<10pt), `shape-overlap` (colliding text), plus `text-only-slide` / `low-contrast-text` / `placeholder-text` / `font-mismatch` (CJK text in a Latin-only font → 豆腐). Advisory (exit 0 even with findings). `--json` → `{ok,findings:[{slide,code,message}]}` for the visual-QA loop. It is the CHEAP GATE before spending vision tokens — run it every QA round and fix all findings first; then do the vision critic + per-slide regeneration (deck-design.md "Verify before delivering").
225
- - `bin/doc-xml.cjs unpack <file> <dir>` / `pack <dir> <out>` — raw-XML escape hatch (pretty-printed unpack → edit → repack); always doc-validate afterwards. `replace <in.docx> <out.docx> <find> <replacement>` — cross-run character-offset replace (finds text even when Word split it over runs, preserves formatting; covers body + headers/footers) — try this FIRST for plain text edits before unpacking. `merge-runs <in.docx> <out.docx>` repairs run fragmentation when you do need manual XML edits.
226
- - `bin/pptx-clone.cjs <template.pptx> <slideNo> <out.pptx> [replacements.json]` — clone a styled template slide once per data item, replacing `{{tokens}}` in the clone only (tokens split across runs are still found); `pptx-clone remove <in> <slideNo> <out>` drops a slide (e.g. the leftover token template). CAPACITY warnings on stderr mean the text likely overflows its slot — shorten the wording, never shrink the font. See rewrite.md.
227
- - `bin/pptx-slide.cjs add <in.pptx> <out.pptx> [--layout N]` / `dup <in> <slideNo> <out>` / `remove <in> <slideNo> <out>` / `reorder <in> <order> <out>` — slide-lifecycle surgery on an EXISTING deck WITHOUT a `{{token}}` template: append a blank slide bound to a layout (inherits the deck's master/theme), duplicate or drop a slide, or permute deck order (`pptx-slide reorder in.pptx 3,1,2 out.pptx` — comma-list of current 1-based positions in the new sequence). Lossless & structural — parts/rels/Content_Types are bookkept for you, but in-slide TEXT/content edits still go through doc-xml. Always doc-validate.
228
- - `bin/pptx-embed-fonts.cjs <in.pptx> <out.pptx> --font "<Typeface>=<path.ttf>" [--bold …] [--italic …]` — EMBED fonts into a deck (OOXML font embedding) so it looks identical on a machine lacking the font. Full-font embed → use for SMALL custom/brand fonts; NOT big CJK fonts (openers have system CJK, and the file would balloon). `<Typeface>` must match the deck's text-run font name. doc-validate after.
229
- - `bin/pptx-theme.cjs <ref.pptx> [out.json]` — extract a theme.json (palette/fonts/sizes) from an existing deck, then `doc-gen --theme` it: new content in that deck's look. Palette only — reusing actual layouts is pptx-clone/doc-fill territory.
230
- - `bin/doc-fill.cjs <template.docx|pptx|xlsx> <values.json> <out>` — fill `{{placeholders}}` in an existing template, preserving its styling (see rewrite.md).
231
- - `bin/pptx-tokenize.cjs <user.pptx> <template.pptx> [schema.json]` — turn a user's UPLOADED deck into a reusable `{{token}}` template: keeps its exact layouts/master/brand, replaces each content slot's text with a clean single-run token, and emits a `schema.json` cataloging every token (slide/role/type/multiline/original/capacity). Plain text boxes (no `<p:ph>`) are tokenized too. Then `doc-fill` it — fill EVERY token (pass `original` for slots you keep, else they blank). The B2 "reuse their layout" path; see rewrite.md.
232
- - `bin/pptx-set-image.cjs <in.pptx> <slideNo> <rId> <image> <out.pptx>` — swap the picture behind a slide's `rId` (from pptx-tokenize's image tokens) with a new image, keeping the frame (position/size) put. add-and-repoint (old media orphaned). Aspect-mismatch STRETCHES — pre-crop to the slot ratio. Always doc-validate.
233
- - `bin/docx-annotate.cjs comment <in.docx> <out.docx> <comments.json>` / `suggest <in.docx> <out.docx> <author> <text>` / `accept <in.docx> <out.docx>` / `redline-check <original.docx> <edited.docx>` — add Word comments (paragraph-anchored, threaded replies via `replyTo`), a tracked insertion (reviewer suggestion), accept ALL tracked changes, or PROVE an edited file changed nothing outside tracked changes (run after every redline edit; non-zero exit = an untracked content change slipped in).
234
- - `bin/pdf-form.cjs list <in.pdf>` / `fill <in.pdf> <values.json> <out.pdf> [--flatten]` / `overlay <filled.pdf> <out.pdf>` — inspect/fill PDF forms; `overlay` boxes every field in red for a render-and-look fill check (see pdf.md).
235
- - `bin/pdf-ops.cjs merge <out> <in…>` / `split <in> <from-to> <out>` / `rotate <in> <deg> <out> [pages]` / `watermark <in> <text> <out>` / `encrypt <in> <out> <user-pw> [owner-pw]` / `decrypt <in> <pw> <out>` — PDF page ops + AES-256 password protection.
236
- - `bin/xlsx-recalc.cjs <in.xlsx> <out.xlsx>` — re-evaluate all formulas (HyperFormula) and cache the results, keeping the formulas. Use when a spreadsheet's formula cells show stale/blank values.
237
- - `bin/doc-run.cjs <script.js> [args…]` — run a custom Node script with the engine's libraries bundled in (`require("pptxgenjs"|"docx"|"xlsx"|"pdf-lib"|"jszip"|"pizzip"|"hyperformula")` guaranteed on any machine; `--list` prints the registry). The long-tail escape hatch when no verb fits — see rewrite.md "Custom scripts"; ALWAYS doc-validate the output.
238
- - `bin/html2pptx.cjs <deck.html|snapshot.layout.json> [out.pptx] [--style <id>] [--theme-v2] [--media-style <id>] [--backdrop <variant>] [--editable] [--rasterize] [--preview-dir <dir>] [--preview-pages <all|N,N-M>]` — **THE deck path**: write slide HTML (`<section class="slide" data-layout="…">` on a 1280×720 canvas), Chromium lays it out → NATIVE editable pptx. `--preview-dir` is a preview-only fast path that writes slide PNGs directly from the styled HTML and skips PPTX/LibreOffice; use all pages once, then `--preview-pages` for changed pages. `--theme-v2` composes the selected family's existing paint with its semantic component profile, default media style and bound art direction; `--media-style` overrides only the media treatment. Entries in a `classic-v1` catalog collection reject both flags; omit them for the frozen V1 path. `--backdrop <variant>` picks a signature backdrop. **DEFAULT = hybrid**: each slide's visuals bake into a full-fidelity raster backdrop with native EDITABLE text on top; auto-falls back to plain native if backdrop capture is unavailable. `--editable` = plain native only (effects flatten). `--rasterize` = full image slides (ZERO editability — tell the user). Advisory warnings on hardcoded brand colors + repeated layouts (P3). Runs in the app's Chromium OR bundled headless Chromium (Playwright) — works off-app (CI/cloud); layout JSON works anywhere. **Tailwind + `size="1".."7"` scale available** (vendored offline). See theme-system.md + deck-design.md + layouts/README.md. `[--theme <theme.json>]` is a separate legacy document recolor path.
239
- - `bin/deck-build.cjs <spec.json> <deck.html>` — **THE FAST deck path** for catalog slides: emit a COMPACT spec with `style`, independent `layoutPack`, and per-slide `intent` + `layout` + content. Modern entries add `themeVersion:2` plus optional `mediaStyle`/`decorRhythm`; frozen `classic-v1` entries must omit those fields and use only pre-V2 layouts. Use `layouts/profiles.json` to match content intent before selecting geometry; under V2 the same intent derives the art scene and deck-level decoration rhythm. The CLI warns on an intent/layout mismatch and errors on an unknown intent. `layoutPack:"none"` forces shared layouts; omitting `layoutPack` preserves the old behavior where a `kind:"pack"` style implicitly uses its same-name layouts. `slots`, `rows`, and `chart` are still validated against `layouts/slots.json`; any unknown layout/slot/field or missing figure input exits 1 and writes nothing. See theme-system.md for the full schema and compatibility contract.
207
+ One line each — **read a bin's entry in `bin-reference.md` before its first use**
208
+ (flags, output shape, exit codes, gotchas). Do not read, grep or open `bin/*.cjs`
209
+ themselves — they are bundled builds; the answer is in `bin-reference.md`.
210
+
211
+ - Read: `bin/doc-scan.cjs <file.pdf>` page signals · `bin/doc-text.cjs <file.pdf>` text layer ·
212
+ `bin/pdf-render.cjs <file.pdf> <N|N-M|3,7-8|all> [scale]` pages → PNG (scale `1` ≈72dpi for layout) ·
213
+ `bin/pdf-images.cjs` embedded images · `bin/pdf-tables.cjs` text-layer tables ·
214
+ `bin/ocr.cjs <image> [lang]` · `bin/xlsx-query.cjs <file> --summary|--agg|--sample` exact spreadsheet compute.
215
+ - Generate: `bin/doc-gen.cjs <docx|xlsx|pdf> <out> <spec.json>` (self-checks) ·
216
+ `bin/doc-run.cjs <script.js>` custom script with the bundled libraries ·
217
+ `bin/doc-convert.cjs <in.docx|pptx|xlsx> <out.pdf>` faithful → PDF.
218
+ - Decks: `bin/deck-build.cjs <spec.json> <deck.html>` catalog slides from a compact spec ·
219
+ `bin/html2pptx.cjs <deck.html> <out.pptx> --style <id> …` THE deck path (self-checks; `--preview-dir` for fast previews) ·
220
+ `bin/deck-qa.cjs <deck.pptx> [--json | --final]` lint, and the one-call delivery sign-off.
221
+ - Edit: `bin/doc-fill.cjs` fill `{{tokens}}` · `bin/doc-xml.cjs unpack|pack|replace|merge-runs` raw XML ·
222
+ `bin/pptx-slide.cjs add|dup|remove|reorder` · `bin/pptx-clone.cjs` clone a template slide per item ·
223
+ `bin/pptx-tokenize.cjs` uploaded deck → template · `bin/pptx-set-image.cjs` · `bin/pptx-theme.cjs` palette from a deck ·
224
+ `bin/pptx-embed-fonts.cjs` · `bin/docx-annotate.cjs comment|suggest|accept|redline-check` ·
225
+ `bin/xlsx-recalc.cjs` recompute formulas.
226
+ - Validate: `bin/doc-validate.cjs <file.docx|pptx|xlsx|pdf> [--strict]` — for anything a generator did not already check.
227
+ - PDF: `bin/pdf-form.cjs list|fill|overlay` · `bin/pdf-ops.cjs merge|split|rotate|watermark|stamp|encrypt|decrypt`.
240
228
 
241
229
  All scripts are Node and print a machine-readable result plus a human note. On a
242
230
  missing dependency or unreadable file they exit non-zero with a clear message —
@@ -686,6 +686,52 @@ function applyMotion(html, layoutId, preset) {
686
686
  }
687
687
  return out;
688
688
  }
689
+ var STAGE_SCENARIOS = [
690
+ "pitch",
691
+ "\u8DEF\u6F14",
692
+ "\u53D1\u5E03\u4F1A",
693
+ "launch",
694
+ "keynote",
695
+ "\u4E3B\u9898\u6F14\u8BB2",
696
+ "\u5927\u4F1A",
697
+ "conference",
698
+ "\u8BB2\u5EA7",
699
+ "lecture",
700
+ "talk",
701
+ "\u9500\u552E",
702
+ "sales"
703
+ ];
704
+ var READ_SCENARIOS = [
705
+ "\u5185\u5BA1",
706
+ "\u8BC4\u5BA1",
707
+ "review",
708
+ "\u62A5\u544A",
709
+ "\u6C47\u62A5",
710
+ "report",
711
+ "\u8BB2\u4E49",
712
+ "handout",
713
+ "\u57F9\u8BAD",
714
+ "training",
715
+ "\u8FF0\u804C",
716
+ "\u5468\u62A5",
717
+ "\u6708\u62A5"
718
+ ];
719
+ function motionForDeck(spec) {
720
+ if (typeof spec.motion === "boolean") {
721
+ return { on: spec.motion, reason: `motion: ${spec.motion} in the spec` };
722
+ }
723
+ const scenario = typeof spec.scenario === "string" ? spec.scenario.trim() : "";
724
+ if (!scenario)
725
+ return { on: true, reason: "no scenario in the spec \u2014 the family preset applies" };
726
+ const s = scenario.toLowerCase();
727
+ const read = READ_SCENARIOS.find((k) => s.includes(k));
728
+ if (read)
729
+ return { on: false, reason: `scenario "${scenario}" is read, not watched \u2014 the family preset is off` };
730
+ const stage = STAGE_SCENARIOS.find((k) => s.includes(k));
731
+ if (stage)
732
+ return { on: true, reason: `scenario "${scenario}" is presented \u2014 the family preset applies` };
733
+ return { on: true, reason: `scenario "${scenario}" is not one motion knows \u2014 the family preset applies; set motion:false to drop it` };
734
+ }
689
735
 
690
736
  // apps/admin/data/skills.lib/document/bin-src/deck-build.mjs
691
737
  function die(msg, code = 1) {
@@ -711,6 +757,8 @@ async function main() {
711
757
  die("mediaStyle must be a string and requires themeVersion: 2", 64);
712
758
  }
713
759
  if (spec?.layoutPack !== void 0 && typeof spec.layoutPack !== "string") die('layoutPack must be a pack id or "none"', 64);
760
+ if (spec?.scenario !== void 0 && typeof spec.scenario !== "string") die('scenario must be a string (the confirmed scenario, e.g. "\u5185\u5BA1" or "\u53D1\u5E03\u4F1A")', 64);
761
+ if (spec?.motion !== void 0 && typeof spec.motion !== "boolean") die("motion must be true or false", 64);
714
762
  if (spec?.decorRhythm !== void 0 && (spec.themeVersion !== 2 || !["auto", "steady"].includes(spec.decorRhythm))) {
715
763
  die("decorRhythm must be auto|steady and requires themeVersion: 2", 64);
716
764
  }
@@ -816,8 +864,9 @@ async function main() {
816
864
  );
817
865
  }
818
866
  }
867
+ const motion = motionForDeck(spec);
819
868
  let motionPreset = null;
820
- if (catalogEntry?.motion) {
869
+ if (catalogEntry?.motion && motion.on) {
821
870
  const mp = (0, import_node_path.join)(skillDir, catalogEntry.motion);
822
871
  if (!(0, import_node_fs.existsSync)(mp)) die(`motion preset not found: ${catalogEntry.motion}`, 66);
823
872
  let raw;
@@ -848,6 +897,7 @@ async function main() {
848
897
  out: outPath,
849
898
  slides: Array.isArray(spec?.slides) ? spec.slides.length : 0,
850
899
  warnings,
900
+ motion: catalogEntry?.motion ? motion : { on: false, reason: "the family has no motion preset" },
851
901
  next: `html2pptx ${outPath} out.pptx${styleId ? ` --style ${styleId}` : " --style <skin>"}${spec?.themeVersion === 2 ? " --theme-v2" : ""}${spec?.mediaStyle ? ` --media-style ${spec.mediaStyle}` : ""}`
852
902
  }, null, 1) + "\n");
853
903
  }