@taloswork/ose-shared 0.1.12 → 0.1.14

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 (71) hide show
  1. package/package.json +3 -3
  2. package/skills/document/SKILL.md +33 -45
  3. package/skills/document/bin/deck-build.cjs +10482 -272
  4. package/skills/document/bin/deck-chart.cjs +21 -12
  5. package/skills/document/bin/deck-plan.cjs +11654 -42
  6. package/skills/document/bin/deck-qa.cjs +107 -23
  7. package/skills/document/bin/deck-scenario.cjs +20 -3
  8. package/skills/document/bin/deck-styles.cjs +1604 -0
  9. package/skills/document/bin/doc-convert.cjs +200 -260
  10. package/skills/document/bin/doc-fill.cjs +140 -19
  11. package/skills/document/bin/doc-gen.cjs +1909 -282
  12. package/skills/document/bin/doc-scan.cjs +6 -1
  13. package/skills/document/bin/doc-text.cjs +6 -1
  14. package/skills/document/bin/doc-validate.cjs +139 -54
  15. package/skills/document/bin/docx-defaults.cjs +9907 -0
  16. package/skills/document/bin/html2pptx.cjs +35960 -31973
  17. package/skills/document/bin/pdf-form.cjs +14 -1
  18. package/skills/document/bin/pdf-images.cjs +6 -1
  19. package/skills/document/bin/pdf-ops.cjs +14 -1
  20. package/skills/document/bin/pdf-render.cjs +6 -1
  21. package/skills/document/bin/pdf-tables.cjs +6 -1
  22. package/skills/document/bin/pptx-notes.cjs +10038 -0
  23. package/skills/document/bin/pptx-tokenize.cjs +19 -4
  24. package/skills/document/bin/template-skin.cjs +10915 -0
  25. package/skills/document/bin-reference.md +15 -10
  26. package/skills/document/catalog.json +33 -32
  27. package/skills/document/content-pipeline.md +79 -44
  28. package/skills/document/deck-design.md +55 -32
  29. package/skills/document/generated-visuals.md +99 -0
  30. package/skills/document/layouts/MAINTAINERS.md +33 -0
  31. package/skills/document/layouts/README.md +20 -20
  32. package/skills/document/layouts/big-stat.tpl +1 -1
  33. package/skills/document/layouts/capacity.json +1 -1
  34. package/skills/document/layouts/cards-3.tpl +1 -1
  35. package/skills/document/layouts/chart-full.tpl +1 -1
  36. package/skills/document/layouts/chart-kpi.tpl +1 -1
  37. package/skills/document/layouts/comparison.tpl +1 -1
  38. package/skills/document/layouts/data-table.tpl +1 -1
  39. package/skills/document/layouts/funnel.tpl +1 -1
  40. package/skills/document/layouts/gantt.tpl +1 -1
  41. package/skills/document/layouts/hub-flow.tpl +4 -0
  42. package/skills/document/layouts/icon-row.tpl +1 -1
  43. package/skills/document/layouts/image-grid.tpl +1 -1
  44. package/skills/document/layouts/matrix-2x2.tpl +1 -1
  45. package/skills/document/layouts/mock-qa.tpl +4 -0
  46. package/skills/document/layouts/profiles.json +2 -2
  47. package/skills/document/layouts/pyramid.tpl +1 -1
  48. package/skills/document/layouts/radar.tpl +1 -1
  49. package/skills/document/layouts/ring-progress.tpl +1 -1
  50. package/skills/document/layouts/slots.json +1 -1
  51. package/skills/document/layouts/steps-vertical.tpl +1 -1
  52. package/skills/document/layouts/steps.tpl +1 -1
  53. package/skills/document/layouts/three-kpi.tpl +1 -1
  54. package/skills/document/layouts/timeline.tpl +1 -1
  55. package/skills/document/layouts/toc-panel.tpl +1 -1
  56. package/skills/document/layouts/two-kpi.tpl +2 -2
  57. package/skills/document/layouts/versus.tpl +1 -1
  58. package/skills/document/packs/README.md +1 -1
  59. package/skills/document/pdf.md +13 -0
  60. package/skills/document/rewrite.md +23 -8
  61. package/skills/document/scenarios.json +19 -2
  62. package/skills/document/scenarios.schema.json +1 -0
  63. package/skills/document/styles/_backdrops/rimlight.html +3 -2
  64. package/skills/document/styles/_contract-defaults.css +6 -1
  65. package/skills/document/styles/_samples/_groups/biz-premium.webp +0 -0
  66. package/skills/document/styles/_samples/mckinsey.webp +0 -0
  67. package/skills/document/styles/mckinsey/backdrop.html +7 -5
  68. package/skills/grill-me/SKILL.md +6 -0
  69. package/skills/grill-me/agents/openai.yaml +5 -0
  70. package/skills/grilling/SKILL.md +28 -0
  71. package/skills/grilling/agents/openai.yaml +3 -0
@@ -7,9 +7,9 @@ unreadable file · `69` a required engine is unavailable · `75` transient, retr
7
7
 
8
8
  - **Read** (lines 14–22) — doc-scan · doc-text · pdf-render · pdf-images · pdf-tables · ocr · xlsx-query
9
9
  - **Generate** (lines 24–28) — doc-gen · doc-run · xlsx-recalc
10
- - **Fill and edit** (lines 30–42) — doc-fill · doc-xml · docx-annotate · pptx-clone · pptx-slide · pptx-tokenize · pptx-set-image · pptx-theme · pptx-embed-fonts · pdf-form · pdf-ops
11
- - **Decks** (lines 44–53) — deck-scenario · deck-plan · deck-build · deck-chart · html2pptx · deck-qa
12
- - **Validate and convert** (lines 55–58) — doc-validate · doc-convert
10
+ - **Fill and edit** (lines 30–44) — doc-fill · doc-xml · docx-annotate · docx-defaults · pptx-clone · pptx-slide · pptx-tokenize · pptx-set-image · pptx-notes · pptx-theme · pptx-embed-fonts · pdf-form · pdf-ops
11
+ - **Decks** (lines 46–58) — deck-scenario · deck-styles · deck-plan · deck-build · deck-chart · html2pptx · deck-qa · template-skin
12
+ - **Validate and convert** (lines 60–63) — doc-validate · doc-convert
13
13
 
14
14
  ## Read
15
15
 
@@ -32,10 +32,12 @@ unreadable file · `69` a required engine is unavailable · `75` transient, retr
32
32
  - `bin/doc-fill.cjs <template.docx|pptx|xlsx> <values.json> <out>` — fill `{{placeholders}}` in an existing template, preserving its styling; prints `{ok, out, unfilled}`. A malformed or unclosed tag exits 1 and writes nothing. Syntax: rewrite.md "Fill a template".
33
33
  - `bin/doc-xml.cjs replace <in.docx> <out.docx> <find> <replacement>` — cross-run text replace (finds text even when Word split it over runs, keeps formatting; matched within one paragraph; body incl. tables + headers/footers + footnotes/endnotes, not comments); prints `{replaced}` — `0` means the text is not there as written. Try this FIRST for plain text edits. `unpack <file> <dir>` / `pack <dir> <out>` — the raw-XML escape hatch (pretty-printed unpack → edit → repack); always `doc-validate --strict` afterwards. `merge-runs <in.docx> <out.docx>` coalesces fragmented runs before a manual XML edit.
34
34
  - `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>` — Word review: comments, a tracked insertion, accept ALL tracked changes, and the proof that an edited file changed nothing outside tracked changes (exit 1 + `firstDivergence`). JSON shapes and caveats: rewrite.md "Review".
35
+ - `bin/docx-defaults.cjs <in.docx> <out.docx>` — add the default paragraph style a script-written (docx.js) .docx lacks; without it Pages lays body text out like the heading before it.
35
36
  - `bin/pptx-clone.cjs <template.pptx> <slideNo> <out.pptx> [replacements.json]` — clone a styled template slide once per data item (appended at the end), replacing `{{tokens}}` in the clone only (tokens split across runs are still found); prints `{newSlideNumber, replaced, missing, warnings}`. `pptx-clone remove <in> <slideNo> <out>` drops a slide. CAPACITY warnings on stderr mean the text likely overflows its slot — shorten the wording, never shrink the font. See rewrite.md "Template decks".
36
37
  - `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 (default: the last slide's), duplicate (appended) or drop a slide, or permute deck order (`reorder in.pptx 3,1,2 out.pptx` — current 1-based positions in the new sequence). Lossless; in-slide TEXT still goes through doc-fill / doc-xml.
37
- - `bin/pptx-tokenize.cjs <user.pptx> <template.pptx> [schema.json]` — turn an UPLOADED deck into a reusable `{{token}}` template that keeps its exact layouts/master/brand, and write `schema.json` cataloging every token. Then `doc-fill` it — fill EVERY token (pass `original` for slots you keep, else they blank). See rewrite.md "Reuse an uploaded deck".
38
+ - `bin/pptx-tokenize.cjs <user.pptx> <template.pptx> [schema.json]` — UPLOADED deck → `{{token}}` template keeping its layouts/master/brand, and write `schema.json` of every token. Then `doc-fill` it — fill EVERY token (`original` for slots you keep, else they blank). `leadStyle:true` = lead + body: fill `lead\nbody`. See rewrite.md "Reuse an uploaded deck".
38
39
  - `bin/pptx-set-image.cjs <in.pptx> <slideNo> <rId> <image> <out.pptx>` — swap the picture behind a slide's `rId` (pptx-tokenize's image tokens carry it as `rel`), keeping the frame (position/size); prints `{newMedia, oldMedia}`. A different aspect ratio STRETCHES — pre-crop to the slot ratio.
40
+ - `bin/pptx-notes.cjs <in.pptx> <notes.json|{}> <out.pptx>` — speaker notes on an existing deck (`{"1": "…"}` by slide); repairs notes Keynote refuses (`{}`). **Never hand-write notesSlide XML.**
39
41
  - `bin/pptx-theme.cjs <ref.pptx> [out.json]` — extract a theme.json (palette/fonts) from an existing deck (printed when no `out.json`). For documents, `doc-gen --theme` it. For a deck, copy its colours into a user skin's tokens (deck-design.md "Custom skins") — `html2pptx --theme` does not repaint a `--style` deck. Palette only, never layouts.
40
42
  - `bin/pptx-embed-fonts.cjs <in.pptx> <out.pptx> --font "<Typeface>=<path.ttf>" [--bold …] [--italic …] [--bold-italic …]` — EMBED fonts (OOXML font embedding) so a deck looks the same where the font is missing. `<Typeface>` must match the runs' font name. Full-font embed: SMALL custom/brand fonts only, never big CJK fonts.
41
43
  - `bin/pdf-form.cjs list <in.pdf>` / `fill <in.pdf> <values.json> <out.pdf> [--flatten]` / `overlay <filled.pdf> <out.pdf>` — PDF AcroForms: `list` → `{fields:[{name, type}]}`; `fill` takes `{"<text or dropdown field>": "value", "<checkbox>": true}` → `{filled, skipped}` (unknown names are skipped, not errors); `overlay` boxes every field in red for the render-and-look check (pdf.md). Chinese values are drawn in the bundled Noto Sans SC (`--flatten` too); a character it lacks (emoji, rare extension hanzi) exits 1 naming its code point.
@@ -46,13 +48,16 @@ unreadable file · `69` a required engine is unavailable · `75` transient, retr
46
48
  Flags and outputs only; the workflow is deck-design.md.
47
49
 
48
50
  - `bin/deck-scenario.cjs "<scenario>"` — the ONE matrix row the clarify gate picked: `{ok, scenario:{id, tone, density, pages, narrative, flows, sections:[{label, key, content}], researchFocus}}`. `content` = what that section must contain (elements, evidence; `;宜` a recommended shape) — it is in no md table. Matches the id, else the longest alias in the text; no match exits 1 with the ids (map to the nearest and rerun).
49
- - `bin/deck-plan.cjs <plan.json> [spec.json]` — **content-first layout selection, run BEFORE deck-build.** The plan is the deck spec's top-level fields (`style`, `themeVersion`, `layoutPack`, `scenario`, `footer`, `chartRender`, …) plus per slide its CONTENT: `role` (cover · toc · section · content · ending; default content), optional `intent` (layouts/profiles.json) / `shape` / `layout` (pin), and `title` · `subtitle` · `eyebrow` · `meta` · `index` · `points` (`[{title, body, date?, label?}]` or strings) · `stats` (`[{value, unit, label, note}]`) · `chart` · `quote` (`{text, source}` or a string) · `table` (`{columns, rows}`) · `image: true` · `slots` / `rows` (explicit values, override the draft). Prints `{ok, slides:[{slide, pick, warnings, blanks, alternatives, rejected:[{layout, why}]}], next}`. Fit = the layout's item count (a 3-card layout takes exactly 3 points; rows layouts take 1..their measured ceiling, at least the count the README density column names) + every drafted string within the layout's capacity measured under your `style` (`layouts/capacity.json`; an unknown style uses the tightest skin). Picks under P1/P2/P3 (layouts/README.md). With `spec.json` it writes the drafted deck-build spec (chart slides get `chartRender:"svg"`) — only when EVERY slide got a pick; otherwise exit 1, nothing written: fix the content the `why` names and re-plan. `blanks` = slots the content had nothing for (left empty, not demo text) — fill them or accept.
50
- - `bin/deck-build.cjs <spec.json> <deck.html>` — fills catalog layouts from a COMPACT spec (normally the one `deck-plan` drafted): top-level `style`, `layoutPack`, `scenario`, `chartRender`, `capacityCheck`, `motion`, Theme V2 fields (theme-system.md), and per slide `intent` + `layout` + `slots` / `rows` / `chart` (layouts/README.md "How to fill"). An unknown layout/slot/field, an unknown intent, a missing figure input, or a chart layout without `chart` / with a chart that has nothing to plot (it would ship the demo chart or a blank box) exits 1 and writes nothing; an intent/layout mismatch warns. **Capacity check** (`layouts/capacity.json`, measured per layout × style): a slot wider than the layout holds, a number that would wrap, or more rows than fit exits 1 naming the slot and the cut; an un-filled NUMBERED slot (`card3_title` — it ships demo copy), a one-line slot that wraps, or an un-filled unnumbered slot (renders its template text; pass `""` to blank it) warns — treat those warnings as defects. `"capacityCheck":"strict"` makes the un-filled numbered slot fatal too; `"warn"|"off"` downgrades/disables it. **Charts:** `"chartRender":"svg"` (or a chart's own `"render":"svg"`) draws each layout chart from its data as an inline SVG sized to the layout's chart box (see deck-chart above); default `native` keeps the editable `c:chart`. `scenario` decides whether the family's motion preset applies (`motion: true|false` overrides; deck-design.md "Motion"). Prints `{ok, out, slides, warnings, capacity:{checked, mode}, motion:{on, reason}, next}` — `next` is the matching html2pptx command.
51
+ - `bin/deck-styles.cjs --scenario "<scenario>"` — the style picker's first round: `{scenario, source, options}`; pass `options` to the picker as printed (SKILL.md "STYLE PICKER"). `source` `mixed`/`fallback` = the scenario claimed under six styles and the default group topped it up.
52
+ - `bin/deck-plan.cjs --layouts --style <id>` — before plan.json: the layouts this style renders and the plan fields each takes (`stats×N` = exactly N, `unit?` optional, `slots.<name>` = pass it, `source ✓` = footer).
53
+ - `bin/deck-plan.cjs <plan.json> [spec.json]` — **content-first layout selection, run BEFORE deck-build.** The plan is the deck spec's top-level fields (`style`, `themeVersion`, `layoutPack`, `scenario`, `density` (read · talk; default from scenario), `footer`, `chartRender`, …) plus per slide its CONTENT: `role` (cover · toc · section · content · ending; default content), optional `intent` (layouts/profiles.json) / `shape` / `layout` (pin), and `title` · `subtitle` (口径 line) · `takeaway` (启示 line) · `eyebrow` · `meta` · `index` · `points` (`[{title, body, date?, label?}]` or strings) · `stats` (`[{value, unit, label, note}]`) · `chart` · `quote` (`{text, source}` or a string) · `table` (`{columns, rows}`) · `image: true` · `source` (one short source line, "IDC,2026" → the footer; dropped with a warning on a layout without one) · `notes` (speaker notes) · `narrative` (outline only) · `file` (a bespoke slide: one `<section class="slide">` in that file, taken as is, `pick:"bespoke"`) · `slots` / `rows` (explicit values, override the draft). A `\n` in any text is a line break. `--outline <slide-outline.md>` also writes the readable outline (one block per slide + its pick) — the approval gate's document, rendered from the plan, never hand-written. Prints `{ok, slides:[{slide, pick, warnings, blanks, alternatives, rejected:[{layout, why}]}], next}`. Fit = the layout's item count (a 3-card layout takes exactly 3 points; rows layouts take 1..their measured ceiling, at least the count the README density column names) + every drafted string within the layout's capacity measured under your `style` (`layouts/capacity.json`; an unknown style uses the tightest skin). Picks under P1/P2/P3 (layouts/README.md). With `spec.json` it writes the drafted deck-build spec (chart slides get `chartRender:"svg"`) — only when EVERY slide got a pick; otherwise exit 1, nothing written: fix the content the `why` names and re-plan. `blanks` = slots the content had nothing for (left empty, not demo text) — fill them or accept. A layout rejected for leaving slots empty names where each one is filled from (`kpi1_desc ← each stat's note`).
54
+ - `bin/deck-build.cjs <spec.json> <deck.html>` — fills catalog layouts from a COMPACT spec (normally the one `deck-plan` drafted): top-level `style`, `layoutPack`, `scenario`, `chartRender`, `capacityCheck`, `motion`, Theme V2 fields (theme-system.md), and per slide `intent` + `layout` + `slots` / `rows` / `chart` / `source` / `notes` (layouts/README.md "How to fill"), or `file` + `notes` for a bespoke slide (relative to the spec, exactly one `<section class="slide">`); a `\n` in a slot is a line break, a typed `<br>` stays text. An unknown layout/slot/field, an unknown intent, a missing figure input, or a chart layout without `chart` / with a chart that has nothing to plot (it would ship the demo chart or a blank box) exits 1 and writes nothing; an intent/layout mismatch warns. **Capacity check** (`layouts/capacity.json`, measured per layout × style): a slot wider than the layout holds, a number that would wrap, more rows than fit, or text longer than its font size may carry (deck-qa's `tiny-font` floor: ≥10pt past 24 characters, ≥8pt up to 24 — a ~9pt footer takes a ≤24-character source line) exits 1 naming the slot and the cut; an un-filled NUMBERED slot (`card3_title` — it ships demo copy), a one-line slot that wraps, or an un-filled unnumbered slot (renders its template text; pass `""` to blank it) warns — treat those warnings as defects. `"capacityCheck":"strict"` makes the un-filled numbered slot fatal too; `"warn"|"off"` downgrades/disables it. **Charts:** `"chartRender":"svg"` (or a chart's own `"render":"svg"`) draws each layout chart from its data as an inline SVG sized to the layout's chart box (see deck-chart above); default `native` keeps the editable `c:chart`. `scenario` decides whether the family's motion preset applies (`motion: true|false` overrides; deck-design.md "Motion"). Prints `{ok, out, slides, warnings, capacity:{checked, mode}, motion:{on, reason}, next}` — `next` is the matching html2pptx command.
51
55
  - `bin/deck-chart.cjs <chart.json> [out.svg] --width <px> --height <px>` — a chart drawn from data as an inline `<svg>` for a BESPOKE slide (catalog chart layouts use `chartRender:"svg"` in deck-build instead). `chart.json` = `{type: bar|barH|line|area|pie|doughnut|radar|scatter, labels, series:[{name, values}], stacked?, unit?, highlight?, showValues?, centerLabel?, zeroBaseline?}` (line: axis from 0 instead of zoomed to the data); radar = 3–8 labels, ≤3 series, `max?` (out-of-range clamps + warns); scatter = `series:[{name, points:[[x,y,label?]|{x,y,label}]}]`, `xLabel?`, `yLabel?`, `xUnit?`. Painted only with the skin's CSS variables (re-skins with `--style`); ≤4 series (more exits 1), a 5th+ pie slice folds into 其他; data mismatches warn like the native chart. Without `out.svg` prints the SVG; paste it into a box of exactly W×H px.
52
- - `bin/html2pptx.cjs <deck.html|snapshot.layout.json> [out.pptx|out.pdf] [--style <id>] [--theme-v2] [--media-style <id>] [--backdrop <variant>] [--line <name|none>] [--editable | --mode native] [--rasterize] [--notes-doc <out.md>] [--preview-dir <dir>] [--preview-pages <all|N,N-M>] [--preview-density <1..4>]` — **THE deck path** (modes, slide contract: deck-design.md). Prints `{ok, out, engine, slides, backdrop, warnings, valid, qa}`; `valid:false` exits 1. An `out.pdf` prints the same styled deck instead: one 16:9 vector page per slide, text selectable, links clickable (HTML input only; not with `--editable`/`--rasterize`/`--notes-doc`). `--preview-dir` (no output file) writes slide PNGs straight from the styled HTML, skipping PPTX/LibreOffice — all pages once, then `--preview-pages` for changed ones — read each image once. `--style` resolves a catalog id, then a user style in `$TALOS_DOC_STYLES_DIR/styles/<name>/`, or an explicit directory. `--theme-v2` / `--media-style`: theme-system.md (rejected for `classic-v1` entries). `--backdrop <variant>` picks a signature backdrop (the skin's `backdrop-<variant>.html`, else `styles/_backdrops/<variant>.html`; `default` = the skin's own); the result reports the one used as `backdrop` — pass it back on later renders of the same deck so an edit cannot switch variants. `--line` swaps the skin's line motif (`styles/_lines/`). `--backdrop-cache <dir>` (services re-rendering many decks) reuses unchanged hybrid backdrops; `--backdrop-cache-verify` captures anyway and fails on any difference. Advisory warnings: hardcoded brand colours, repeated layouts (P3), and a `data-chart` with nothing to plot — drawn as a dashed "图表占位" box (qa flags it as placeholder text). `[--theme <theme.json>]` is the legacy document-recolor path; a `--style` skin overrides it (a warning says so).
53
- - `bin/deck-qa.cjs <file.pptx> [--json] [--rendered <office.pdf> | --final [--cache-dir <dir>] [--require-office]]` — MECHANICAL design QA (deterministic, token-free; the authoritative list of lint codes): `off-canvas` (content past the edge), `tiny-font` (<10pt), `shape-overlap` (colliding text), `text-only-slide` (a wall of text with no visual anchor), `low-contrast-text`, `placeholder-text` (a layout never filled — 替换为…/占位/在这里写/Lorem), `font-mismatch` (CJK in a Latin-only font → 豆腐; expected language defaults to the system locale, override with `TALOS_DECK_LANG`). Advisory: exit 0 even with findings. `--json` → `{ok,findings:[{slide,code,message}]}`. `html2pptx` already prints this lint as `qa` after every build. **`--final` is the deck's delivery sign-off in one call**: strict XSD validation (failure exits 1), the lint, an Office render through `doc-convert` (cached in `.office-cache/` beside the deck, or `--cache-dir` / `$TALOS_OFFICE_CACHE_DIR`), `render-overflow` / `render-collision` where Office re-laid the native text past its box, `render-type3-font` + `office.type3Fonts` when the render draws with a Type 3 font (LibreOffice's empty CJK fallback — that text is blank), and `review` + `previews` — the only slides to look at again, at ≈72dpi (deck-design.md "Verify before delivering"). `--rendered <pdf>` runs the same render check against a PDF you converted yourself; a page count that differs from the deck exits 1.
56
+ - `bin/html2pptx.cjs <deck.html|snapshot.layout.json> [out.pptx] [--style <id>] [--theme-v2] [--media-style <id>] [--backdrop <variant>] [--line <name|none>] [--editable | --mode native] [--rasterize] [--notes-doc <out.md>] [--preview-dir <dir>] [--preview-pages <all|N,N-M>] [--preview-density <1..4>]` — **THE deck path** (modes, slide contract: deck-design.md). Prints `{ok, out, engine, slides, backdrop, warnings, valid, qa}`; `valid:false` exits 1. Hybrid text a skin bakes into the backdrop (`--talos-bake`) that came out blank there is written native in its place (`healedText`, a warning each — the face may be a fallback); only text it cannot write fails: `ok:false` + `missingText`, exits 1 — never deliver that. `.pdf` output is retired (exit 64): convert the final PPTX with `doc-convert`. `--preview-dir` (no output file) writes slide PNGs straight from the styled HTML, skipping PPTX/LibreOffice — all pages once, then `--preview-pages` for changed ones — read each image once; 1280×720 by default (`--preview-density 2` only for fine print), plus `sheet.png` (all rendered slides as 640×360 tiles — read it first). `--style` resolves a catalog id, then a user style in `$TALOS_DOC_STYLES_DIR/styles/<name>/`, or an explicit directory. `--theme-v2` / `--media-style`: theme-system.md (rejected for `classic-v1` entries). `--backdrop <variant>` picks a signature backdrop (the skin's `backdrop-<variant>.html`, else `styles/_backdrops/<variant>.html`; `default` = the skin's own); without it the deck's variant is picked once at random and remembered beside the HTML (`.html2pptx-backdrop.json`, per style), so every later preview and build of that deck — edited or renamed — keeps it; the result reports it as `backdrop`. `--line` swaps the skin's line motif (`styles/_lines/`). `--backdrop-cache <dir>` (services re-rendering many decks) reuses unchanged hybrid backdrops; `--backdrop-cache-verify` captures anyway and fails on any difference. Advisory warnings: hardcoded brand colours, repeated layouts (P3), and a `data-chart` with nothing to plot — drawn as a dashed "图表占位" box (qa flags it as placeholder text). `[--theme <theme.json>]` is the legacy document-recolor path; a `--style` skin overrides it (a warning says so).
57
+ - `bin/deck-qa.cjs <file.pptx> [--json] [--rendered <office.pdf> | --final [--cache-dir <dir>] [--require-office]]` — MECHANICAL design QA (deterministic, token-free; the authoritative list of lint codes): `off-canvas` (content past the edge), `tiny-font` (<10pt), `shape-overlap` (colliding text), `text-only-slide` (a wall of text with no visual anchor), `low-contrast-text`, `placeholder-text` (a layout never filled — 替换为…/占位/在这里写/Lorem), `font-mismatch` (CJK in a Latin-only font → 豆腐; expected language defaults to the system locale, override with `TALOS_DECK_LANG`). Advisory: exit 0 even with findings. `--json` → `{ok,findings:[{slide,code,message}]}`. `html2pptx` already prints this lint as `qa` after every build. **`--final` is the deck's delivery sign-off in one call**: strict XSD validation (failure exits 1), the lint, an Office render through `doc-convert` (cached in `.office-cache/` beside the deck, or `--cache-dir` / `$TALOS_OFFICE_CACHE_DIR`), `render-overflow` / `render-collision` where Office re-laid the native text past its box, `render-type3-font` + `office.type3Fonts` when the render draws with a Type 3 font (LibreOffice's empty CJK fallback — that text is blank), and `review` + `previews` — PPTX review slides at ≈72dpi (PDF delivery checks every final PDF page; deck-design.md "Verify before delivering"). `--rendered <pdf>` runs the same render check against a PDF you converted yourself; a page count that differs from the deck exits 1.
58
+ - `bin/template-skin.cjs <template.pptx> <name> [--label <显示名>] [--content-page N] [--exclude <key>,…] [--include <key>,…]` — a pptx template → the user's style `$TALOS_DOC_STYLES_DIR/styles/<name>/`. Prints `{style, samples, uncertain, kept, warnings, replaced}`; each `kept` element carries a `hint` (its text, or a picture's corner — "a logo?") for `--exclude <key>`; `--label` = the name the picker shows ("我的风格 · <label>", default the file name); not a catalog id.
54
59
 
55
60
  ## Validate and convert
56
61
 
57
- - `bin/doc-validate.cjs <file.docx|pptx|xlsx|pdf> [--strict] [--design-lint]` — structural validation gate: OOXML zip/parts/rels/Content_Types/XML well-formedness; a PDF must parse, open without a password (`pdf-encrypted` error: validate before `pdf-ops encrypt`) and hold at least one page (reports `pages` and a `pdf-parse-only` warning — how it looks is render-and-look's job). Exit 1 = broken, fix before delivering. `--strict` (OOXML only; on a PDF it just adds a `strict-not-applicable` warning) adds full ECMA-376 schema (XSD) validation of every recognised part — REQUIRED after custom-code (doc-run) or raw-XML output; a strict failure means the file is non-standard even if Office opens it. `--design-lint` (pptx only) adds deck-qa's lint as advisory warnings (never changes the exit code; codes under deck-qa in Decks) — real design bugs, fix them.
58
- - `bin/doc-convert.cjs <in.docx|pptx|xlsx> <out.pdf> [--cache-dir <dir>] [--require-office]` — 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** — reconstructed HTML, content/structure/images preserved but in-document layout is not (pptx = one page per slide): the app's service in-app, else a headless Chromium; with none of these it exits 69 — say the PDF could not be made. `--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. `--require-office` never falls to (3): a LibreOffice that ran and failed exits 75 (retry — usually a timeout under load), none at all exits 69. NOTE: spreadsheets (xlsx/xls/ods) render ONLY via (1)–(2), a real LibreOffice; Chromium does not rebuild spreadsheets, so with no LibreOffice available the command errors (never a degraded text-only sheet).
62
+ - `bin/doc-validate.cjs <file.docx|pptx|xlsx|pdf> [--strict] [--design-lint]` — structural validation gate: OOXML zip/parts/rels/Content_Types/XML well-formedness, plus pptx `notes-keynote` (→ `pptx-notes <in> {} <out>`) and docx `docx-default-style` (→ `docx-defaults`); a PDF must parse, open without a password (`pdf-encrypted` error: validate before `pdf-ops encrypt`) and hold at least one page (reports `pages` and a `pdf-parse-only` warning — how it looks is render-and-look's job). Exit 1 = broken, fix before delivering. `--strict` (OOXML only; on a PDF it just adds a `strict-not-applicable` warning) adds full ECMA-376 schema (XSD) validation of every recognised part — REQUIRED after custom-code (doc-run) or raw-XML output; a strict failure means the file is non-standard even if Office opens it. `--design-lint` (pptx only) adds deck-qa's lint as advisory warnings (never changes the exit code; codes under deck-qa in Decks) — real design bugs, fix them.
63
+ - `bin/doc-convert.cjs <in.docx|pptx|xlsx> <out.pdf> [--cache-dir <dir>] [--require-office]` — Office → PDF. **PPTX requires Office**: local `soffice`, then `TALOS_OFFICE_URL` sidecar. Missing Office exits 69; failed Office exits 75. Never rebuild a deck as browser HTML. Spreadsheets also require Office. DOCX can fall back to reconstructed HTML via the app's Chromium or headless Chromium (content retained, layout lost); `--require-office` blocks this fallback. Report the `[pdf (engine)]` result and any caveat. `--cache-dir` (or `TALOS_OFFICE_CACHE_DIR`) reuses the local Office result for identical source bytes; after any PPTX edit, convert again. Fonts come from the Office environment, which must have the required faces for faithful typography.
@@ -16,39 +16,40 @@
16
16
  "entryIds": ["cool", "swiss-grid", "black-gold", "olive-gold", "mckinsey", "apple", "mono", "ivory-gold", "magazine-ink", "anthropic", "hand-drawn", "cinereel", "branding"]
17
17
  }
18
18
  ],
19
+ "fallbackEntryIds": ["mckinsey", "swiss-grid", "cool", "board-brief"],
19
20
  "entries": [
20
- {"id":"cool","kind":"skin","group":"tech-future","name_cn":"酷炫深色","oneliner":"深蓝辉光 · 科技发布","scenarios":["科技","发布","pitch","主题演讲"],"mode":"dark","sample":"styles/_samples/cool.webp","motion":"motion/cool.json"},
21
- {"id":"neon-cyber","kind":"skin","group":"tech-future","name_cn":"霓虹赛博","oneliner":"霓虹品红 · 赛博夜场","scenarios":["科技","游戏","Web3","夜场发布"],"mode":"dark","sample":"styles/_samples/neon-cyber.webp","motion":"motion/neon-cyber.json"},
22
- {"id":"prismatic-3d","kind":"pack","group":"tech-future","name_cn":"棱镜空间","oneliner":"紫黑棱镜 · 立体发布","scenarios":["科技发布","AI 产品","创意提案","未来趋势"],"mode":"dark","sample":"styles/_samples/prismatic-3d.webp","motion":"motion/prismatic-3d.json"},
23
- {"id":"swiss-grid","kind":"skin","group":"tech-future","name_cn":"瑞士国际","oneliner":"克莱因蓝白 · 瑞士国际","scenarios":["科技产品","数据汇报","设计","年度总结"],"mode":"light","sample":"styles/_samples/swiss-grid.webp","motion":"motion/swiss-grid.json"},
24
- {"id":"black-gold","kind":"skin","group":"biz-premium","name_cn":"黑金","oneliner":"纯黑金辉 · 高端商务","scenarios":["金融","年报","路演","奢侈品"],"mode":"dark","sample":"styles/_samples/black-gold.webp","motion":"motion/black-gold.json"},
25
- {"id":"olive-gold","kind":"skin","group":"biz-premium","name_cn":"橄榄金","oneliner":"橄榄亮金 · 高端招商","scenarios":["高端","证书","招商","品牌"],"mode":"dark","sample":"styles/_samples/olive-gold.webp","motion":"motion/olive-gold.json"},
26
- {"id":"mckinsey","kind":"skin","group":"biz-premium","name_cn":"白底咨询","oneliner":"白底藏青 · 咨询评审","scenarios":["咨询","战略汇报","评审","董事会"],"mode":"light","sample":"styles/_samples/mckinsey.webp","motion":"motion/mckinsey.json"},
27
- {"id":"mckinsey-photo","kind":"pack","group":"biz-premium","name_cn":"咨询影像","oneliner":"藏青影像 · 企业叙事","scenarios":["咨询","企业战略","案例研究","年度回顾"],"mode":"light","sample":"styles/_samples/mckinsey-photo.webp","motion":"motion/mckinsey-photo.json"},
28
- {"id":"apple","kind":"skin","group":"minimal","name_cn":"纯黑极简","oneliner":"纯黑极简 · 产品发布","scenarios":["产品发布","主题演讲","极简演示"],"mode":"dark","sample":"styles/_samples/apple.webp","motion":"motion/apple.json"},
29
- {"id":"mono","kind":"skin","group":"minimal","name_cn":"纯白黑灰","oneliner":"纯白黑灰 · 极简设计","scenarios":["极简","高端","设计","单色报告"],"mode":"light","sample":"styles/_samples/mono.webp","motion":"motion/mono.json"},
30
- {"id":"ivory-gold","kind":"skin","group":"minimal","name_cn":"奶油青铜","oneliner":"奶油青铜 · 奢华极简","scenarios":["奢华极简","品牌手册","路演","高端零售"],"mode":"light","sample":"styles/_samples/ivory-gold.webp","motion":"motion/ivory-gold.json"},
31
- {"id":"magazine-ink","kind":"skin","group":"editorial","name_cn":"杂志墨","oneliner":"瓷白靛蓝 · 杂志人文","scenarios":["人文分享","行业观察","商业发布"],"mode":"light","sample":"styles/_samples/magazine-ink.webp","motion":"motion/magazine-ink.json"},
32
- {"id":"anthropic","kind":"skin","group":"editorial","name_cn":"奶油珊瑚","oneliner":"奶油珊瑚 · AI 研究","scenarios":["AI","产品","研究分享","人文品牌"],"mode":"light","sample":"styles/_samples/anthropic.webp","motion":"motion/anthropic.json"},
33
- {"id":"hand-drawn","kind":"skin","group":"creative","name_cn":"纸感手绘","oneliner":"纸感手绘 · 创意教学","scenarios":["创意","头脑风暴","教学","工作坊"],"mode":"light","sample":"styles/_samples/hand-drawn.webp","motion":"motion/hand-drawn.json"},
34
- {"id":"cinereel","kind":"skin","group":"creative","name_cn":"黑白胶片","oneliner":"黑白胶片 · 影视创意","scenarios":["影视","创意作品集","音乐","传媒"],"mode":"dark","sample":"styles/_samples/cinereel.webp","motion":"motion/cinereel.json"},
35
- {"id":"branding","kind":"skin","group":"natural","name_cn":"暖米绿意","oneliner":"暖米绿意 · 品牌手册","scenarios":["品牌手册","可持续","美妆","零售","极简"],"mode":"light","sample":"styles/_samples/branding.webp","motion":"motion/branding.json"},
36
- {"id":"dark-glass","kind":"skin","group":"tech-future","name_cn":"暗色玻璃","oneliner":"石墨冰蓝 · 产品评审","scenarios":["产品评审","技术方案","路线图","内部汇报"],"mode":"dark","sample":"styles/_samples/dark-glass.webp","motion":"motion/dark-glass.json"},
37
- {"id":"grid-tech","kind":"skin","group":"tech-future","name_cn":"硬核网格","oneliner":"近黑荧绿 · 工程评审","scenarios":["工程","基础设施","数据平台","技术大会"],"mode":"dark","sample":"styles/_samples/grid-tech.webp","motion":"motion/grid-tech.json"},
38
- {"id":"pastel-saas","kind":"skin","group":"minimal","name_cn":"柔和粉彩","oneliner":"薰衣草白 · SaaS 提案","scenarios":["SaaS","产品提案","增长复盘","客户成功"],"mode":"light","sample":"styles/_samples/pastel-saas.webp","motion":"motion/pastel-saas.json"},
39
- {"id":"memphis","kind":"skin","group":"creative","name_cn":"几何孟菲斯","oneliner":"米白撞色 · 创意提案","scenarios":["创意提案","品牌活动","校园分享","工作坊"],"mode":"light","sample":"styles/_samples/memphis.webp","motion":"motion/memphis.json"},
40
- {"id":"retro-press","kind":"skin","group":"editorial","name_cn":"复古印刷","oneliner":"旧纸砖红 · 文化叙事","scenarios":["文化","书业","展览","品牌故事"],"mode":"light","sample":"styles/_samples/retro-press.webp","motion":"motion/retro-press.json"},
41
- {"id":"bold-clash","kind":"skin","group":"creative","name_cn":"大胆撞色","oneliner":"亮黄墨黑 · 发布造势","scenarios":["发布造势","营销campaign","潮牌","音乐节"],"mode":"light","sample":"styles/_samples/bold-clash.webp","motion":"motion/bold-clash.json"},
42
- {"id":"organic-earth","kind":"skin","group":"natural","name_cn":"自然有机","oneliner":"苔绿陶土 · 可持续","scenarios":["可持续","农业食品","户外","ESG 报告"],"mode":"light","sample":"styles/_samples/organic-earth.webp","motion":"motion/organic-earth.json"},
43
- {"id":"press-room","kind":"pack","group":"editorial","name_cn":"报刊头版","oneliner":"报纸墨黑 · 发布头版","scenarios":["发布会","媒体沟通","行业观察","年度特刊"],"mode":"light","sample":"styles/_samples/press-room.webp","motion":"motion/press-room.json"},
44
- {"id":"board-brief","kind":"pack","group":"biz-premium","name_cn":"董事会简报","oneliner":"冷灰藏青 · 董事会","scenarios":["董事会","季度经营","投委会","内部治理"],"mode":"light","sample":"styles/_samples/board-brief.webp","motion":"motion/board-brief.json"},
45
- {"id":"campus-teal","kind":"skin","group":"creative","name_cn":"课堂青","oneliner":"浅青板书 · 教学课件","scenarios":["教学","课件","培训","校园"],"mode":"light","sample":"styles/_samples/campus-teal.webp","motion":"motion/campus-teal.json"},
46
- {"id":"clinic-care","kind":"skin","group":"minimal","name_cn":"诊疗蓝","oneliner":"洁净浅蓝 · 医疗健康","scenarios":["医疗","健康科普","器械","公共卫生"],"mode":"light","sample":"styles/_samples/clinic-care.webp","motion":"motion/clinic-care.json"},
21
+ {"id":"cool","kind":"skin","group":"tech-future","name_cn":"酷炫深色","oneliner":"深蓝辉光 · 科技发布","scenarios":["科技","发布","pitch","主题演讲"],"mode":"dark","sample":"styles/_samples/cool.webp","motion":"motion/cool.json","use_cases":["pitch","发布会","大会","公司/产品介绍"]},
22
+ {"id":"neon-cyber","kind":"skin","group":"tech-future","name_cn":"霓虹赛博","oneliner":"霓虹品红 · 赛博夜场","scenarios":["科技","游戏","Web3","夜场发布"],"mode":"dark","sample":"styles/_samples/neon-cyber.webp","motion":"motion/neon-cyber.json","use_cases":["发布会","大会","年度总结/年会"]},
23
+ {"id":"prismatic-3d","kind":"pack","group":"tech-future","name_cn":"棱镜空间","oneliner":"紫黑棱镜 · 立体发布","scenarios":["科技发布","AI 产品","创意提案","未来趋势"],"mode":"dark","sample":"styles/_samples/prismatic-3d.webp","motion":"motion/prismatic-3d.json","use_cases":["发布会","pitch","公司/产品介绍"]},
24
+ {"id":"swiss-grid","kind":"skin","group":"tech-future","name_cn":"瑞士国际","oneliner":"克莱因蓝白 · 瑞士国际","scenarios":["科技产品","数据汇报","设计","年度总结"],"mode":"light","sample":"styles/_samples/swiss-grid.webp","motion":"motion/swiss-grid.json","use_cases":["工作汇报","数据分析","项目立项/评审","产品调研","讲座"]},
25
+ {"id":"black-gold","kind":"skin","group":"biz-premium","name_cn":"黑金","oneliner":"纯黑金辉 · 高端商务","scenarios":["金融","年报","路演","奢侈品"],"mode":"dark","sample":"styles/_samples/black-gold.webp","motion":"motion/black-gold.json","use_cases":["pitch","商业计划书","年度总结/年会","公司/产品介绍","发布会","大会"]},
26
+ {"id":"olive-gold","kind":"skin","group":"biz-premium","name_cn":"橄榄金","oneliner":"橄榄亮金 · 高端招商","scenarios":["高端","证书","招商","品牌"],"mode":"dark","sample":"styles/_samples/olive-gold.webp","motion":"motion/olive-gold.json","use_cases":["商业计划书","公司/产品介绍","销售","pitch"]},
27
+ {"id":"mckinsey","kind":"skin","group":"biz-premium","name_cn":"白底咨询","oneliner":"白底藏青 · 咨询评审","scenarios":["咨询","战略汇报","评审","董事会"],"mode":"light","sample":"styles/_samples/mckinsey.webp","motion":"motion/mckinsey.json","use_cases":["内审","项目立项/评审","产品调研","数据分析","工作汇报","销售"]},
28
+ {"id":"mckinsey-photo","kind":"pack","group":"biz-premium","name_cn":"咨询影像","oneliner":"藏青影像 · 企业叙事","scenarios":["咨询","企业战略","案例研究","年度回顾"],"mode":"light","sample":"styles/_samples/mckinsey-photo.webp","motion":"motion/mckinsey-photo.json","use_cases":["公司/产品介绍","项目立项/评审","年度总结/年会","投标"]},
29
+ {"id":"apple","kind":"skin","group":"minimal","name_cn":"纯黑极简","oneliner":"纯黑极简 · 产品发布","scenarios":["产品发布","主题演讲","极简演示"],"mode":"dark","sample":"styles/_samples/apple.webp","motion":"motion/apple.json","use_cases":["发布会","公司/产品介绍","pitch","大会"]},
30
+ {"id":"mono","kind":"skin","group":"minimal","name_cn":"纯白黑灰","oneliner":"纯白黑灰 · 极简设计","scenarios":["极简","高端","设计","单色报告"],"mode":"light","sample":"styles/_samples/mono.webp","motion":"motion/mono.json","use_cases":["讲座","会议纪要","数据分析","大会"]},
31
+ {"id":"ivory-gold","kind":"skin","group":"minimal","name_cn":"奶油青铜","oneliner":"奶油青铜 · 奢华极简","scenarios":["奢华极简","品牌手册","路演","高端零售"],"mode":"light","sample":"styles/_samples/ivory-gold.webp","motion":"motion/ivory-gold.json","use_cases":["公司/产品介绍","pitch","年度总结/年会"]},
32
+ {"id":"magazine-ink","kind":"skin","group":"editorial","name_cn":"杂志墨","oneliner":"瓷白靛蓝 · 杂志人文","scenarios":["人文分享","行业观察","商业发布"],"mode":"light","sample":"styles/_samples/magazine-ink.webp","motion":"motion/magazine-ink.json","use_cases":["大会","讲座","产品调研"]},
33
+ {"id":"anthropic","kind":"skin","group":"editorial","name_cn":"奶油珊瑚","oneliner":"奶油珊瑚 · AI 研究","scenarios":["AI","产品","研究分享","人文品牌"],"mode":"light","sample":"styles/_samples/anthropic.webp","motion":"motion/anthropic.json","use_cases":["讲座","产品调研","大会"]},
34
+ {"id":"hand-drawn","kind":"skin","group":"creative","name_cn":"纸感手绘","oneliner":"纸感手绘 · 创意教学","scenarios":["创意","头脑风暴","教学","工作坊"],"mode":"light","sample":"styles/_samples/hand-drawn.webp","motion":"motion/hand-drawn.json","use_cases":["培训","讲座","会议纪要"]},
35
+ {"id":"cinereel","kind":"skin","group":"creative","name_cn":"黑白胶片","oneliner":"黑白胶片 · 影视创意","scenarios":["影视","创意作品集","音乐","传媒"],"mode":"dark","sample":"styles/_samples/cinereel.webp","motion":"motion/cinereel.json","use_cases":["发布会","年度总结/年会","大会"]},
36
+ {"id":"branding","kind":"skin","group":"natural","name_cn":"暖米绿意","oneliner":"暖米绿意 · 品牌手册","scenarios":["品牌手册","可持续","美妆","零售","极简"],"mode":"light","sample":"styles/_samples/branding.webp","motion":"motion/branding.json","use_cases":["公司/产品介绍","销售","培训"]},
37
+ {"id":"dark-glass","kind":"skin","group":"tech-future","name_cn":"暗色玻璃","oneliner":"石墨冰蓝 · 产品评审","scenarios":["产品评审","技术方案","路线图","内部汇报"],"mode":"dark","sample":"styles/_samples/dark-glass.webp","motion":"motion/dark-glass.json","use_cases":["项目立项/评审","内审","产品调研"]},
38
+ {"id":"grid-tech","kind":"skin","group":"tech-future","name_cn":"硬核网格","oneliner":"近黑荧绿 · 工程评审","scenarios":["工程","基础设施","数据平台","技术大会"],"mode":"dark","sample":"styles/_samples/grid-tech.webp","motion":"motion/grid-tech.json","use_cases":["项目立项/评审","内审","数据分析"]},
39
+ {"id":"pastel-saas","kind":"skin","group":"minimal","name_cn":"柔和粉彩","oneliner":"薰衣草白 · SaaS 提案","scenarios":["SaaS","产品提案","增长复盘","客户成功"],"mode":"light","sample":"styles/_samples/pastel-saas.webp","motion":"motion/pastel-saas.json","use_cases":["销售","pitch","数据分析","公司/产品介绍"]},
40
+ {"id":"memphis","kind":"skin","group":"creative","name_cn":"几何孟菲斯","oneliner":"米白撞色 · 创意提案","scenarios":["创意提案","品牌活动","校园分享","工作坊"],"mode":"light","sample":"styles/_samples/memphis.webp","motion":"motion/memphis.json","use_cases":["大会","培训","公司/产品介绍"]},
41
+ {"id":"retro-press","kind":"skin","group":"editorial","name_cn":"复古印刷","oneliner":"旧纸砖红 · 文化叙事","scenarios":["文化","书业","展览","品牌故事"],"mode":"light","sample":"styles/_samples/retro-press.webp","motion":"motion/retro-press.json","use_cases":["大会","讲座","年度总结/年会"]},
42
+ {"id":"bold-clash","kind":"skin","group":"creative","name_cn":"大胆撞色","oneliner":"亮黄墨黑 · 发布造势","scenarios":["发布造势","营销campaign","潮牌","音乐节"],"mode":"light","sample":"styles/_samples/bold-clash.webp","motion":"motion/bold-clash.json","use_cases":["发布会","大会","年度总结/年会"]},
43
+ {"id":"organic-earth","kind":"skin","group":"natural","name_cn":"自然有机","oneliner":"苔绿陶土 · 可持续","scenarios":["可持续","农业食品","户外","ESG 报告"],"mode":"light","sample":"styles/_samples/organic-earth.webp","motion":"motion/organic-earth.json","use_cases":["年度总结/年会","公司/产品介绍","投标"]},
44
+ {"id":"press-room","kind":"pack","group":"editorial","name_cn":"报刊头版","oneliner":"报纸墨黑 · 发布头版","scenarios":["发布会","媒体沟通","行业观察","年度特刊"],"mode":"light","sample":"styles/_samples/press-room.webp","motion":"motion/press-room.json","use_cases":["发布会","年度总结/年会","公司/产品介绍"]},
45
+ {"id":"board-brief","kind":"pack","group":"biz-premium","name_cn":"董事会简报","oneliner":"冷灰藏青 · 董事会","scenarios":["董事会","季度经营","投委会","内部治理"],"mode":"light","sample":"styles/_samples/board-brief.webp","motion":"motion/board-brief.json","use_cases":["内审","工作汇报","述职/晋升","数据分析","会议纪要"]},
46
+ {"id":"campus-teal","kind":"skin","group":"creative","name_cn":"课堂青","oneliner":"浅青板书 · 教学课件","scenarios":["教学","课件","培训","校园"],"mode":"light","sample":"styles/_samples/campus-teal.webp","motion":"motion/campus-teal.json","use_cases":["培训","讲座","会议纪要"]},
47
+ {"id":"clinic-care","kind":"skin","group":"minimal","name_cn":"诊疗蓝","oneliner":"洁净浅蓝 · 医疗健康","scenarios":["医疗","健康科普","器械","公共卫生"],"mode":"light","sample":"styles/_samples/clinic-care.webp","motion":"motion/clinic-care.json","use_cases":["培训","公司/产品介绍","投标"]},
47
48
  {"id":"wedding-blush","kind":"skin","group":"creative","name_cn":"婚礼胭脂","oneliner":"胭脂米白 · 婚礼请柬","scenarios":["婚礼","请柬","纪念册","私人典礼"],"mode":"light","sample":"styles/_samples/wedding-blush.webp","motion":"motion/wedding-blush.json"},
48
- {"id":"portfolio-noir","kind":"skin","group":"minimal","name_cn":"炭黑作品集","oneliner":"炭黑铜金 · 作品集","scenarios":["作品集","个人品牌","摄影","设计评审"],"mode":"dark","sample":"styles/_samples/portfolio-noir.webp","motion":"motion/portfolio-noir.json"},
49
- {"id":"bistro-warm","kind":"skin","group":"natural","name_cn":"餐酒暖木","oneliner":"奶油辣椒红 · 餐饮门店","scenarios":["餐饮","门店","食品品牌","菜单发布"],"mode":"light","sample":"styles/_samples/bistro-warm.webp","motion":"motion/bistro-warm.json"},
50
- {"id":"gov-brief","kind":"skin","group":"biz-premium","name_cn":"政务简报","oneliner":"素白藏蓝 · 政务汇报","scenarios":["政务","公共事务","工作汇报","会议材料"],"mode":"light","sample":"styles/_samples/gov-brief.webp","motion":"motion/gov-brief.json"},
51
- {"id":"sport-arena","kind":"skin","group":"creative","name_cn":"赛场竞技","oneliner":"夜场亮橙 · 赛事发布","scenarios":["赛事","体育","战报","俱乐部"],"mode":"dark","sample":"styles/_samples/sport-arena.webp","motion":"motion/sport-arena.json"},
52
- {"id":"legal-slate","kind":"skin","group":"biz-premium","name_cn":"法务石板","oneliner":"石板墨绿 · 法务合规","scenarios":["法务","合规","尽调","风险评估"],"mode":"light","sample":"styles/_samples/legal-slate.webp","motion":"motion/legal-slate.json"}
49
+ {"id":"portfolio-noir","kind":"skin","group":"minimal","name_cn":"炭黑作品集","oneliner":"炭黑铜金 · 作品集","scenarios":["作品集","个人品牌","摄影","设计评审"],"mode":"dark","sample":"styles/_samples/portfolio-noir.webp","motion":"motion/portfolio-noir.json","use_cases":["述职/晋升","公司/产品介绍","大会"]},
50
+ {"id":"bistro-warm","kind":"skin","group":"natural","name_cn":"餐酒暖木","oneliner":"奶油辣椒红 · 餐饮门店","scenarios":["餐饮","门店","食品品牌","菜单发布"],"mode":"light","sample":"styles/_samples/bistro-warm.webp","motion":"motion/bistro-warm.json","use_cases":["公司/产品介绍","销售"]},
51
+ {"id":"gov-brief","kind":"skin","group":"biz-premium","name_cn":"政务简报","oneliner":"素白藏蓝 · 政务汇报","scenarios":["政务","公共事务","工作汇报","会议材料"],"mode":"light","sample":"styles/_samples/gov-brief.webp","motion":"motion/gov-brief.json","use_cases":["政务/党政汇报","工作汇报","项目立项/评审","投标"]},
52
+ {"id":"sport-arena","kind":"skin","group":"creative","name_cn":"赛场竞技","oneliner":"夜场亮橙 · 赛事发布","scenarios":["赛事","体育","战报","俱乐部"],"mode":"dark","sample":"styles/_samples/sport-arena.webp","motion":"motion/sport-arena.json","use_cases":["发布会","年度总结/年会"]},
53
+ {"id":"legal-slate","kind":"skin","group":"biz-premium","name_cn":"法务石板","oneliner":"石板墨绿 · 法务合规","scenarios":["法务","合规","尽调","风险评估"],"mode":"light","sample":"styles/_samples/legal-slate.webp","motion":"motion/legal-slate.json","use_cases":["投标","内审","政务/党政汇报","项目立项/评审"]}
53
54
  ]
54
55
  }
@@ -5,9 +5,9 @@ quick 3-slide summary. It is the single source for HOW to source, structure and
5
5
  out deck content; deck-design.md renders it. You run these phases yourself (web search,
6
6
  reasoning, AskUserQuestion) — there is no research script.
7
7
 
8
- **Design target = a premium presentation, not a document**: sparse punchy text on the
9
- slide, the substance in visuals, data and speaker notes (Phase 4). A wall of text is not
10
- "substantive".
8
+ **Design target = a premium presentation that explains itself**: a visual + data on every
9
+ slide, and each point says why in one line (Phase 4). A wall of text is not "substantive";
10
+ neither is a board of 2-word labels.
11
11
 
12
12
  ## Execution discipline (whole pipeline)
13
13
 
@@ -20,6 +20,8 @@ slide, the substance in visuals, data and speaker notes (Phase 4). A wall of tex
20
20
  citation, a palette). Missing → halt and get it.
21
21
  4. **No silent skips**: if you skip a step (e.g. Research for "organize my material"),
22
22
  say so and why.
23
+ 5. **Batch independent reads, searches and checks in ONE turn of parallel calls.**
24
+ Update the task plan only when a phase changes.
23
25
 
24
26
  Two entry modes: **open-ended** ("做一份关于 X 的 PPT") → every phase from Research;
25
27
  **organize existing material** (user gave a doc/notes) → skip Phase 1 and in Phase 4
@@ -33,7 +35,9 @@ The clarify gate and the style picker are defined once, in SKILL.md: ask only fo
33
35
  missing values among content source, scenario and slide count, in ONE AskUserQuestion
34
36
  call with at most
35
37
  THREE questions; the scenario-ranked image-card style picker is a separate call after
36
- the scenario is known. What each answer means here:
38
+ the scenario is known. Run `bin/deck-styles.cjs` and pass its `options` unchanged;
39
+ the app expands the full-gallery option. The manual fallback is defined in SKILL.md.
40
+ What each answer means here:
37
41
 
38
42
  1. **Content source** — 提供材料 / 联网调研 / 自由创作 (offline / no web tool → say so;
39
43
  only the first and last). Provided → request the materials now; when you ask for a FILE, set
@@ -73,7 +77,7 @@ the user:
73
77
  <!-- generated:scenario-matrix · source: scenarios.json · regenerate: node scripts/deck/gen-scenarios.mjs — do not edit by hand -->
74
78
  | 场景 | 语气 | 密度 | 必备章节(required roles — default; user overrides win) | 叙事(Phase 2) | 默认页数 |
75
79
  |---|---|---|---|---|---|
76
- | **pitch** 融资/路演 | 自信 · 有张力 · 故事驱动 | 稀疏 · 大数字 | Problem/问题 · Solution/解决方案 · Market/市场 · Product/Traction/产品/进展 · Team/团队 · **Ask/融资需求** | SCQA / 问题-方案 | 10–12 |
80
+ | **pitch** 融资/路演 | 自信 · 有张力 · 故事驱动 | 中 · 大数字+一句解释 | Problem/问题 · Solution/解决方案 · Market/市场 · Product/Traction/产品/进展 · Team/团队 · **Ask/融资需求** | SCQA / 问题-方案 | 10–12 |
77
81
  | **内审** | 客观 · 直接 · 结论先行 | 略密(容明细/数据) | 结论/进展 · 关键指标 · 问题与风险 · 下一步/决策项 | 结论先行 | 6–8 |
78
82
  | **销售** | 利益驱动 · 客户中心 · 说服 | 中 · 重价值与佐证 | 痛点 · 方案/价值主张 · 差异化 · 客户案例 · ROI/定价 · **CTA/行动号召** | 问题-方案 | 8–12 |
79
83
  | **讲座** 学术 | 讲解 · 循序渐进 | 中 · 概念+例子 | 学习目标 · 背景/基础 · 核心概念 · 案例/推导 · 小结 | 由浅入深 | 10–15 |
@@ -98,7 +102,9 @@ Tone also biases the catalog style ranking: 张力/情绪(pitch·发布会·大
98
102
  <!-- /generated:scenario-style-bias -->
99
103
 
100
104
  **Persist `deck-brief.md`**: Topic · Scenario · Source · Style (entry id + 2–3 sentences
101
- on palette/type/motif) · Template style · Slide Count · Overrides (if any) · (assumptions). Persist it and
105
+ on palette/type/motif) · Template style · Slide Count · Overrides (if any) · (assumptions) —
106
+ ≤10 lines of DECISIONS. Research findings, numbers, chart data and citations do not go
107
+ here: they are written once, in `plan.json`. Persist it and
102
108
  continue — do not ask the user to approve what they just supplied. If the brief adds a
103
109
  material assumption that changes scope, show only that assumption and pause.
104
110
 
@@ -108,7 +114,9 @@ material assumption that changes scope, show only that assumption and pause.
108
114
 
109
115
  Run 8–12 queries **in parallel** (many searches at once, or a sub-agent per dimension —
110
116
  breadth beats depth-first), then organize into 概述 / 背景 / 关键信息 / 证据(案例·数据) /
111
- 分析 / 展望.
117
+ 分析 / 展望. Research with search and fetch only — **do not open the browser** for it (it
118
+ pops a panel in the user's app): a page that blocks fetch (403, timeout, paywall) → use
119
+ its search snippet or another source. Open it only when the user asks for that page.
112
120
 
113
121
  | Layer | Query pattern |
114
122
  |---|---|
@@ -151,8 +159,12 @@ breadth beats depth-first), then organize into 概述 / 背景 / 关键信息 /
151
159
  **Cite everything:** every data point (number / percent / year / quote) carries its
152
160
  source in a `{claim → URL}` list; a stat without one is dropped. **Quality gate: ≥3
153
161
  authoritative sources, ≥5 distinct domains; drop anything >5 years old or unverified.**
154
- The source list goes on a "参考来源" ending slide AND into speaker notes. Generate
155
- figures/photos with the media-generation tool into local files at the same time.
162
+ The source list goes on a "参考来源" ending slide AND into speaker notes. On the slide
163
+ itself: at most ONE short line, publisher + year — the slide's `source` in the plan
164
+ (「来源:IDC,2026」) — the data period,
165
+ scope caveats and URL go to notes and 参考来源, never a footnote sentence. The user's
166
+ own figures carry no source line. Plan generated visuals in Phase 3; generate after
167
+ the outline and style are confirmed (generated-visuals.md).
156
168
 
157
169
  ---
158
170
 
@@ -178,60 +190,81 @@ it is merged or omitted per the brief's Overrides.
178
190
 
179
191
  ## Phase 3 — Outline artifact (MANDATORY gate)
180
192
 
181
- Materialize the plan into `slide-outline.md` — the single source of truth for Phase 4–5;
182
- do not re-decide count or roles later. One full block per slide, splitting what goes ON
183
- the canvas (sparse) from what moves to speaker notes (detail). The fields map straight
184
- onto `deck-plan`'s plan.json:
185
-
186
- ```markdown
187
- # Slide Outline
188
- ## Meta — from deck-brief.md (Topic/Scenario/Source/Style/Template style/Count/Overrides)
189
- ## Source Materials — provided summary · {claim→URL} list · or "N/A — topic knowledge"
190
- ## Slide-by-Slide (one BLOCK per slide)
191
-
192
- ### S1 — Cover
193
- - Role: cover | toc | section | content | ending (deck-plan `role`)
194
- - Takeaway: <the TITLE stated as a CONCLUSION, not the topic>
195
- - Shape: parallel · process · timeline · compare · hierarchy · matrix · list · metrics · quote · table · agenda (deck-plan `shape`; optional `intent` from layouts/profiles.json)
196
- - On-slide (sparse): <only what shows on the canvas — 3–5 points / numbers, phrase-level>
197
- - Data points {claim→URL}: <n1 (src) · n2 (src) · …> (drop any stat with no source)
198
- - Chart: <type + data> or none · Image: yes/no
199
- - → Notes: <detail / caveat / context / citations — speaker notes, never the slide>
200
- - Narrative role: <how this page advances the ONE core message>
201
-
202
- ### S2 — Agenda
203
- - … (same fields; one block for ALL N slides)
204
-
205
- ## Visual Rhythm
206
- - Dark-accent slides at: <e.g. 1, 7, N> (≥1–2 where the style offers dark pages)
207
- - Chart-bearing slides at: <e.g. 4, 6, 9>
193
+ First see what the chosen style's layouts take — one call, before writing anything:
194
+
195
+ ```
196
+ node <skill>/bin/deck-plan.cjs --layouts --style <style id>
197
+ ```
198
+
199
+ One line per layout this style renders, with the plan fields it takes
200
+ (bin-reference.md). Write each slide's content to the layout you mean it for.
201
+
202
+ Write the outline ONCE, as `plan.json` — `deck-plan`'s input and the single source of
203
+ truth for Phase 4–5 (do not re-decide count or roles later). Per slide: `role` · `title`
204
+ (the takeaway, stated as a CONCLUSION) · `shape` / `intent` · what goes ON the canvas,
205
+ (`subtitle` · `points` · `stats` · `quote` · `table` · `chart` · `image` · `takeaway`) ·
206
+ `source` (one short line) · `notes` (what to say + the one caveat that matters, 2–3
207
+ sentences, ≲120 字 — never on the slide; cite as "见来源 1": the full citation — title,
208
+ date, URL — is written ONCE, in the 参考来源 slide's notes, never re-quoted per slide or
209
+ in the original language) · `narrative` (how it advances the ONE core message) · `file` for a bespoke slide
210
+ (deck-design.md). Write `plan.json` itself with the file tool and edit it in place on a
211
+ revision — no script that generates or patches it. Render the outline from it;
212
+ never write it by hand:
213
+
208
214
  ```
215
+ node <skill>/bin/deck-plan.cjs plan.json spec.json --outline slide-outline.md
216
+ ```
217
+
218
+ One block per slide (Takeaway · Shape · On-slide · Chart · Source · Notes · Narrative
219
+ role) plus the layout each slide got. A slide that fits no layout says so in its block —
220
+ fix its content before asking. Keep ≥1–2 dark-accent and the chart pages spread through
221
+ the deck (visual rhythm).
209
222
 
210
223
  A required section's block covers its `content` (deck-scenario) — the elements on the
211
224
  slide or in the data points, the evidence with a source — unless the user's words say
212
225
  otherwise. An element with no source → say so in Notes; never invent the number.
213
226
 
214
- Then **GATE**: show the outline, AskUserQuestion approve/revise, advance only on approval.
227
+ A ~9pt footer carries ≤24 characters (deck-plan rejects longer): `source` is the
228
+ publisher and year ("Maximize Market Research,2026"); URL and caveats go in `notes`.
229
+
230
+ Assess where generated visuals improve the story: typically 2–3 pages, not a quota.
231
+ Count them within the total; mark purpose and image/text mode in `narrative`, reserve
232
+ `file` paths before HTML exists, and follow generated-visuals.md.
233
+
234
+ Then **GATE**, in this order — never ask before the outline exists:
235
+ 1. `plan.json` written and `slide-outline.md` rendered by the command above;
236
+ 2. `read` `slide-outline.md` — the outline shows in the timeline;
237
+ 3. AskUserQuestion, ONE sentence ("是否按这份 12 页大纲制作?"), `confirmation` with
238
+ `options: ["按此制作", "调整大纲"]` — never the outline in the question.
239
+
240
+ Advance only on approval. A revision edits `plan.json` and re-runs the same command — the outline and the
241
+ spec move together.
215
242
 
216
243
  ---
217
244
 
218
245
  ## Phase 4 — Author
219
246
 
220
247
  Announce the on-canvas language in one line (default = the user's prompt language;
221
- respect an explicit "用英文/use English"), e.g. `本次幻灯片内容将使用中文生成`. Then turn
222
- the approved outline into plan.json and follow deck-design.md "Workflow"
223
- (`deck-plan` → `deck-build` → bespoke slides only where no layout fits). Layout
224
- selection rules (P1/P2/P3) live in layouts/README.md and are applied by `deck-plan`.
248
+ respect an explicit "用英文/use English"). Generate the approved visuals, then author
249
+ their `file` slides and follow deck-design.md "Workflow" with the approved plan.
250
+ Layout selection rules (P1/P2/P3) live in layouts/README.md.
225
251
 
226
252
  Content density — what each slide carries:
227
253
 
228
254
  - **One message per slide**; the title states the takeaway.
229
- - **Phrases, not sentences; no paragraphs.** Every detail, caveat and citation goes to
230
- speaker notes (`talos-notes`, deck-design.md).
255
+ - **Read deck** (default; `deck-plan` reads it off the scenario — 发布会/大会/年会 are
256
+ talk decks): each point = a label + ONE explanatory sentence (`body`; stats: `note`),
257
+ plus `subtitle` (口径 / why it matters) and `takeaway` (启示) — 120–300 字 per slide;
258
+ `content-thin` flags less. **Talk deck**: phrases only. Either way no paragraphs;
259
+ citations and long caveats go to the notes.
231
260
  - **Substance = visual + data.** Each content slide carries ≥1 chart / diagram / big
232
261
  number / visual plus 3–5 concrete data points, with its story in one line. A
233
262
  bullets-only slide is the last resort for genuinely list-like content.
234
- - **Cover and ending are statements** — strong visual, few powerful words.
263
+ - **Cover and ending are statements** — strong visual, few powerful words. On the
264
+ cover the title is by far the largest text; besides it only the brand/eyebrow once
265
+ (brand, event or date — never a chapter name like 现状), a subtitle and at most one
266
+ key line. No running header or chapter nav, no stat row,
267
+ no source line — the key numbers open slide 2.
235
268
  - Doesn't fit → split or cut; never shrink the type (visual rules: deck-design.md
236
269
  "Design principles").
237
270
 
@@ -244,3 +277,5 @@ previews (`html2pptx.cjs deck.html --preview-dir <dir>`, then `--preview-pages`
244
277
  changed slides), build the PPTX and fix its `qa` findings, then sign off once with
245
278
  `deck-qa deck.pptx --final` and look only at its `previews`. Never use PPTX→PDF as the
246
279
  authoring preview. Finish only after one clean structural, mechanical and visual pass.
280
+ For PDF delivery, follow deck-design.md: convert the final PPTX through Office and
281
+ inspect that PDF, reusing final QA output only while the PPTX is unchanged.