@taloswork/ose-shared 0.1.10 → 0.1.12

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 (126) hide show
  1. package/package.json +3 -3
  2. package/skills/document/SKILL.md +143 -215
  3. package/skills/document/art-directions/base.css +27 -2
  4. package/skills/document/art-directions/cinematic-depth.css +3 -1
  5. package/skills/document/art-directions/collage-paper.css +5 -1
  6. package/skills/document/art-directions/editorial-cut.css +5 -1
  7. package/skills/document/art-directions/geometric-pop.css +6 -0
  8. package/skills/document/art-directions/gradient-mesh.css +5 -1
  9. package/skills/document/art-directions/illustrated-doodle.css +5 -0
  10. package/skills/document/art-directions/luxury-ornament.css +4 -1
  11. package/skills/document/art-directions/maximalist-blocks.css +6 -0
  12. package/skills/document/art-directions/technical-grid.css +4 -0
  13. package/skills/document/assets/fonts/fonts.json +2 -2
  14. package/skills/document/assets/pdf-fonts/NotoSansSC-PDF-Bold.ttf +0 -0
  15. package/skills/document/assets/pdf-fonts/NotoSansSC-PDF-Regular.ttf +0 -0
  16. package/skills/document/assets/pdf-fonts/OFL.txt +93 -0
  17. package/skills/document/assets/pdf-fonts/README.md +35 -0
  18. package/skills/document/assets/tessdata/LICENSE-Apache-2.0.txt +202 -0
  19. package/skills/document/assets/tessdata/README.md +21 -0
  20. package/skills/document/assets/tessdata/chi_sim.traineddata.gz +0 -0
  21. package/skills/document/assets/tessdata/eng.traineddata.gz +0 -0
  22. package/skills/document/bin/deck-build.cjs +2311 -41
  23. package/skills/document/bin/deck-chart.cjs +762 -0
  24. package/skills/document/bin/deck-plan.cjs +802 -0
  25. package/skills/document/bin/deck-qa.cjs +984 -249
  26. package/skills/document/bin/deck-scenario.cjs +1346 -0
  27. package/skills/document/bin/doc-convert.cjs +130 -39
  28. package/skills/document/bin/doc-fill.cjs +73121 -170
  29. package/skills/document/bin/doc-gen.cjs +625 -68
  30. package/skills/document/bin/doc-run.cjs +162 -24
  31. package/skills/document/bin/doc-scan.cjs +13 -0
  32. package/skills/document/bin/doc-text.cjs +13 -0
  33. package/skills/document/bin/doc-validate.cjs +718 -23
  34. package/skills/document/bin/doc-xml.cjs +9 -5
  35. package/skills/document/bin/docx-annotate.cjs +95 -19
  36. package/skills/document/bin/fontkit.cjs +1 -0
  37. package/skills/document/bin/html2pptx.cjs +1372 -121
  38. package/skills/document/bin/ocr-worker.cjs +1 -0
  39. package/skills/document/bin/ocr.cjs +131 -40
  40. package/skills/document/bin/pdf-form.cjs +674 -177
  41. package/skills/document/bin/pdf-images.cjs +13 -0
  42. package/skills/document/bin/pdf-ops.cjs +634 -199
  43. package/skills/document/bin/pdf-render.cjs +19 -3
  44. package/skills/document/bin/pdf-tables.cjs +13 -0
  45. package/skills/document/bin/pptx-clone.cjs +3 -3
  46. package/skills/document/bin/pptx-slide.cjs +3 -3
  47. package/skills/document/bin/xlsx-query.cjs +192 -61
  48. package/skills/document/bin-reference.md +56 -33
  49. package/skills/document/content-pipeline.md +129 -242
  50. package/skills/document/deck-design.md +355 -638
  51. package/skills/document/layouts/README.md +46 -33
  52. package/skills/document/layouts/capacity.json +1 -0
  53. package/skills/document/layouts/slots.json +1 -1
  54. package/skills/document/layouts/toc-panel.tpl +1 -1
  55. package/skills/document/motion/README.md +3 -2
  56. package/skills/document/office.md +3 -3
  57. package/skills/document/packs/board-brief/backdrop.html +2 -0
  58. package/skills/document/packs/board-brief/pack.css +2 -1
  59. package/skills/document/packs/mckinsey-photo/backdrop.html +2 -0
  60. package/skills/document/packs/mckinsey-photo/pack.css +2 -1
  61. package/skills/document/packs/press-room/backdrop.html +2 -0
  62. package/skills/document/packs/press-room/pack.css +2 -1
  63. package/skills/document/packs/prismatic-3d/backdrop.html +2 -0
  64. package/skills/document/packs/prismatic-3d/pack.css +4 -1
  65. package/skills/document/pdf.md +53 -49
  66. package/skills/document/rewrite.md +241 -308
  67. package/skills/document/scenarios.json +1290 -0
  68. package/skills/document/scenarios.schema.json +103 -0
  69. package/skills/document/styles/README.md +15 -25
  70. package/skills/document/styles/_contract-defaults.css +25 -1
  71. package/skills/document/styles/anthropic/skin.css +6 -3
  72. package/skills/document/styles/apple/skin.css +4 -3
  73. package/skills/document/styles/bistro-warm/backdrop.html +2 -0
  74. package/skills/document/styles/bistro-warm/skin.css +4 -1
  75. package/skills/document/styles/black-gold/skin.css +6 -5
  76. package/skills/document/styles/bold-clash/backdrop.html +2 -0
  77. package/skills/document/styles/bold-clash/skin.css +2 -1
  78. package/skills/document/styles/branding/skin.css +4 -4
  79. package/skills/document/styles/campus-teal/backdrop.html +2 -0
  80. package/skills/document/styles/campus-teal/skin.css +2 -1
  81. package/skills/document/styles/cinereel/skin.css +7 -3
  82. package/skills/document/styles/clinic-care/backdrop.html +2 -0
  83. package/skills/document/styles/clinic-care/skin.css +2 -1
  84. package/skills/document/styles/cool/skin.css +6 -5
  85. package/skills/document/styles/dark-glass/backdrop.html +2 -0
  86. package/skills/document/styles/dark-glass/skin.css +2 -1
  87. package/skills/document/styles/gov-brief/backdrop.html +2 -0
  88. package/skills/document/styles/gov-brief/skin.css +2 -1
  89. package/skills/document/styles/grid-tech/backdrop.html +2 -0
  90. package/skills/document/styles/grid-tech/skin.css +2 -1
  91. package/skills/document/styles/hand-drawn/skin.css +3 -3
  92. package/skills/document/styles/ivory-gold/skin.css +7 -6
  93. package/skills/document/styles/legal-slate/backdrop.html +2 -0
  94. package/skills/document/styles/legal-slate/skin.css +2 -1
  95. package/skills/document/styles/magazine-ink/skin.css +4 -3
  96. package/skills/document/styles/mckinsey/skin.css +2 -1
  97. package/skills/document/styles/memphis/backdrop.html +2 -0
  98. package/skills/document/styles/memphis/skin.css +2 -1
  99. package/skills/document/styles/mono/skin.css +6 -2
  100. package/skills/document/styles/neon-cyber/backdrop.html +2 -0
  101. package/skills/document/styles/neon-cyber/skin.css +2 -1
  102. package/skills/document/styles/olive-gold/skin.css +7 -6
  103. package/skills/document/styles/organic-earth/backdrop.html +2 -0
  104. package/skills/document/styles/organic-earth/skin.css +2 -1
  105. package/skills/document/styles/pastel-saas/backdrop.html +2 -0
  106. package/skills/document/styles/pastel-saas/skin.css +2 -1
  107. package/skills/document/styles/portfolio-noir/backdrop.html +2 -0
  108. package/skills/document/styles/portfolio-noir/skin.css +2 -1
  109. package/skills/document/styles/retro-press/backdrop.html +2 -0
  110. package/skills/document/styles/retro-press/skin.css +2 -1
  111. package/skills/document/styles/sport-arena/backdrop.html +2 -0
  112. package/skills/document/styles/sport-arena/skin.css +4 -1
  113. package/skills/document/styles/swiss-grid/skin.css +10 -5
  114. package/skills/document/styles/wedding-blush/backdrop.html +2 -0
  115. package/skills/document/styles/wedding-blush/skin.css +4 -1
  116. package/skills/document/theme-system.md +85 -77
  117. package/skills/document/themes/README.md +7 -5
  118. package/skills/document/vision.md +8 -5
  119. package/skills/document/xlsx.md +15 -25
  120. package/skills/cozy-static-svg/SKILL.md +0 -76
  121. package/skills/cozy-static-svg/references/approved-preview.png +0 -0
  122. package/skills/cozy-static-svg/references/cross-platform.md +0 -73
  123. package/skills/cozy-static-svg/references/moon_keeps_watch.svg +0 -229
  124. package/skills/cozy-static-svg/references/style-anchor.md +0 -271
  125. package/skills/cozy-static-svg/scripts/artkit.py +0 -321
  126. package/skills/cozy-static-svg/scripts/to_png.py +0 -333
@@ -1,35 +1,58 @@
1
1
  # Script reference (L3)
2
2
 
3
- Every bin in `bin/`, with its full contract. SKILL.md lists them one line each;
4
- read the entry here before the first call of a bin you have not used in this task.
5
-
6
- - `bin/doc-scan.cjs <file.pdf>` — per-page signals as JSON.
7
- - `bin/doc-text.cjs <file.pdf>` — extract a PDF's text layer.
8
- - `bin/pdf-render.cjs <file.pdf> <pages|all> [scale]` — render pages to PNG for vision (`pages` = `3` | `2-5` | `3,7-8` | `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 (a deck's final Office pass hands you its images: `deck-qa --final`).
9
- - `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`.
10
- - `bin/pdf-tables.cjs <file.pdf> [page] [minCols]` — recover text-layer tables as rows (ruled/scanned tables need render + vision instead).
11
- - `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.
12
- - `bin/xlsx-query.cjs <file> [--summary | --agg <sheet> <col> <op> | --sample <sheet> [n]]` — spreadsheet compute.
13
- - `bin/doc-gen.cjs <docx|xlsx|pdf> <out> <spec.json> [--theme <theme.json>] [--topic <subject> | --palette <id>] [--no-preview]` — generate documents from scratch. DOCX/PDF body fields are exactly `paragraphs` and/or `blocks` (never `sections`); in a PDF, any http(s) URL written in body text, list items or table cells becomes a clickable link and wraps inside the page on its own — never split a URL by hand (there is no other link syntax); 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 — see rewrite.md "Themes"; built-ins in `themes/`). **`--topic <subject>` (when no `--theme`) picks a topic-adaptive palette** instead of the same default every time. `doc-gen pptx` exits 64: decks are built with html2pptx. `--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.
14
- - `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** — 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. 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).
15
- - `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 and hold at least one page (reports `pages` and a `pdf-parse-only` warning — how it looks is render-and-look's job; `--strict` / `--design-lint` are OOXML-only; `--strict` on a PDF adds a `strict-not-applicable` warning). 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".
16
- - `bin/deck-qa.cjs <file.pptx> [--json] [--rendered <office.pdf> | --final [--cache-dir <dir>]]` — 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"). `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), `render-overflow` / `render-collision` where Office re-laid the native text past its box, and `review` + `previews` — the only slides (findings + native charts) to look at again, already rendered at ≈72dpi (deck-design.md "Verify before delivering"). `--rendered <pdf>` is the same render check against a PDF you converted yourself; a page count that differs from the deck exits 1.
17
- - `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.
18
- - `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.
19
- - `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.
20
- - `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.
21
- - `bin/pptx-theme.cjs <ref.pptx> [out.json]` — extract a theme.json (palette/fonts) from an existing deck, then `html2pptx --theme` (or `doc-gen --theme` for a matching docx/pdf) it: new content in that deck's look. Palette only — reusing actual layouts is pptx-clone/doc-fill territory.
22
- - `bin/doc-fill.cjs <template.docx|pptx|xlsx> <values.json> <out>` — fill `{{placeholders}}` in an existing template, preserving its styling (see rewrite.md).
23
- - `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.
24
- - `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.
25
- - `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).
26
- - `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).
27
- - `bin/pdf-ops.cjs merge <out> <in…>` / `split <in> <from-to> <out>` / `rotate <in> <deg> <out> [pages]` / `watermark <in> <text> <out>` / `stamp <in.pdf> <stamps.json> <out.pdf>` / `encrypt <in> <out> <user-pw> [owner-pw]` / `decrypt <in> <pw> <out>` — PDF page ops, coordinate text stamping onto a flat (non-form) PDF (see pdf.md), and AES-256 password protection.
28
- - `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.
29
- - `bin/doc-run.cjs <script.js> [args…]` — run a custom Node script with the engine's libraries bundled in (`require("pptxgenjs"|"docx"|"xlsx"|"exceljs"|"pdf-lib"|"jszip"|"pizzip"|"hyperformula")` guaranteed on any machine; `--list` prints the registry; nothing else is installed). For a **formatted workbook** (fills, font colors, borders, merged cells) use `exceljs` — `xlsx` (SheetJS community) writes no cell styles at all and drops them without an error; `doc-gen xlsx` covers only a bold header, column widths, number formats and formulas. The long-tail escape hatch when no verb fits — see rewrite.md "Custom scripts"; ALWAYS doc-validate the output.
30
- - `bin/html2pptx.cjs <deck.html|snapshot.layout.json> [out.pptx|out.pdf] [--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. 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` 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.
31
- - `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. `scenario` (the confirmed scenario) decides whether the family's motion preset is applied — read decks (内审/报告/培训…) get none, `motion: true|false` overrides, and the result JSON reports `motion: {on, reason}` (deck-design.md "Motion"). `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.
32
-
33
- All scripts are Node and print a machine-readable result plus a human note. On a
34
- missing dependency or unreadable file they exit non-zero with a clear message —
35
- report that to the user, do not fabricate content.
3
+ Every bin in `bin/`, grouped by task. **Read only your task's section** — Read this
4
+ file with the offset/limit of the line range below; another section only when you call
5
+ a bin from it. Exit codes are shared: `64` bad usage · `65` invalid input · `66`
6
+ unreadable file · `69` a required engine is unavailable · `75` transient, retry · `1` failure.
7
+
8
+ - **Read** (lines 14–22) — doc-scan · doc-text · pdf-render · pdf-images · pdf-tables · ocr · xlsx-query
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
13
+
14
+ ## Read
15
+
16
+ - `bin/doc-scan.cjs <file.pdf>` — per-page signals: `{file, pages:[{page, textChars, imageCoverage, mathHint, tableHint, scanned, …}]}`. PDF only. Every PDF reader here (doc-scan, doc-text, pdf-render, pdf-images, pdf-tables) exits 1 on a password-protected PDF — see pdf.md.
17
+ - `bin/doc-text.cjs <file.pdf>` — the PDF's text layer, `[page N]`-delimited. A .docx/.pptx/.xlsx exits 64 (read the sidecar / use xlsx-query).
18
+ - `bin/pdf-render.cjs <file.pdf> <pages|all> [scale]` — render pages to PNG for vision, written beside the PDF as `<stem>_p<N>.png` (prints `{rendered:[{page, path}]}`); `pages` = `3` | `2-5` | `3,7-8` | `all`. `scale` 0.5–4 (default `2` ≈ 144dpi) trades resolution for vision tokens: `1` (≈72dpi, ¼ the tokens) for layout QA; keep `2` when fine print must stay legible (formulas/tables).
19
+ - `bin/pdf-images.cjs <file.pdf> [pages]` — EMBEDDED images at native resolution, written beside the PDF as `<stem>_p<page>_i<index>.png`, plus a manifest `{images:[{page, index, bbox, width, height, path}], skipped}` (`pages` = `N` | `N-M` | `all`, default all). Use this — not a full-page `pdf-render` — when you need the original figures as their own files (e.g. rebuilding a deck). Vector/text-only pages yield nothing → `pdf-render`.
20
+ - `bin/pdf-tables.cjs <file.pdf> [page] [minCols]` — text-layer tables as `{tables:[{page, rows}]}` (`minCols` default 2; rows may carry empty spacer cells). Nothing found, or a ruled/scanned table → render + vision.
21
+ - `bin/ocr.cjs <image> [lang]` — text off a png/jpg/webp/bmp image → `{text, confidence}`; for a scanned PDF `pdf-render` the page first. `lang` is a tesseract code, default `eng`; `chi_sim` = simplified Chinese, `chi_tra` traditional, `+` combines (`chi_sim+eng` for mixed text). `eng` and `chi_sim` ship with the skill and work offline; others download once into `$TALOS_TESSDATA` (no network → exit 1 `OCR failed: …`); `$TALOS_TESSDATA_LANGPATH` names a dir holding every `<lang>.traineddata.gz`. **Prefer vision** when a vision model is available; OCR is the text-only fallback.
22
+ - `bin/xlsx-query.cjs <file> [--summary | --agg <sheet> <col> <op> | --sample <sheet> [n]] [--header-row N] [--include-totals]` — exact spreadsheet compute; no mode = `--summary` (sheet names, row/column counts, `headerRow`, headers). `<op>` = `sum` | `avg` | `min` | `max` | `count` | `count-nonempty` (anything else exits 64 listing these); `<col>` is a header label or a 1-based index. The header row is detected (a title row is skipped; `--header-row N` overrides). `--agg` excludes total rows (合计/总计/小计/Total/Subtotal/Sum, or a SUM over the column) and reports them in `excludedRows` (`--include-totals` keeps them), and lists non-numeric cells it skipped in `skippedCells`. `15%` text is 0.15; `¥`/`元` amounts parse. An unknown sheet exits 1 naming the sheets; a column it cannot find returns `value: null, colIdx: -1` — run `--summary` for the exact names. `--sample` prints up to `n` (default 20) rows keyed by header. Caveats: xlsx.md.
23
+
24
+ ## Generate
25
+
26
+ - `bin/doc-gen.cjs <docx|xlsx|pdf> <out> <spec.json> [--theme <theme.json|name>] [--topic <subject> | --palette <id>] [--accent <#rrggbb> | --style <id>] [--no-preview]` — generate documents from scratch; spec shapes in rewrite.md "Generate". DOCX/PDF body fields are exactly `paragraphs` and/or `blocks` (never `sections`); in a PDF, any http(s) URL written in body text, list items or table cells becomes a clickable link and wraps inside the page on its own — never split a URL by hand (there is no other link syntax). Unknown fields and empty bodies exit 65 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. Prints `wrote <out>` (a PDF adds its engine) then one JSON line — the self-check in SKILL.md "After writing a file"; PDF previews land beside it as `<stem>_p<N>.png` (`--no-preview` skips them). A PDF prints in Chromium — the app's service, else a headless Chromium; with neither it exits 69. `doc-gen pptx` exits 64: decks are built with html2pptx. **Look flags** (docx/pdf): `--theme` = a theme file (built-ins `<skill>/themes/<id>.json`) or the name of one the user saved in `$TALOS_DOC_STYLES_DIR/themes`; `--topic <subject>` picks a topic-adaptive palette, `--palette <id>` forces one (`doc-gen --list-palettes`); `--accent <#rrggbb>` / `--style <id>` keep white paper and near-black text with ONE brand colour on H1/H2 + a faint table-header tint — `--style` takes it from a catalog skin or pack (the deck picker's ids; the deck's full palette is NOT carried onto paper); an accent that is not 6-digit hex falls back to black-on-white with a warning. Precedence: `--theme` > spec `"theme"` > `--accent`/`--style` > `--palette`/`--topic` > default.
27
+ - `bin/doc-run.cjs <script.js> [args…]` — run a custom Node script with the engine's libraries bundled in (`require("pptxgenjs"|"docx"|"xlsx"|"exceljs"|"pdf-lib"|"jszip"|"pizzip"|"hyperformula")` guaranteed on any machine; `--list` prints the registry; nothing else is installed, and an unbundled `require` fails naming the bundled alternative). For a **formatted workbook** (fills, font colors, borders, merged cells) use `exceljs` — `xlsx` (SheetJS community) writes no cell styles at all and drops them without an error; `doc-gen xlsx` covers only a bold header, column widths, number formats and formulas. The long-tail escape hatch when no verb fits — see rewrite.md "Custom scripts"; ALWAYS `doc-validate --strict` the output.
28
+ - `bin/xlsx-recalc.cjs <in.xlsx> <out.xlsx>` — re-evaluate every formula (HyperFormula) and cache the results, keeping the formulas (`out` may equal `in`). Prints `{ok, out, recomputed, errors:[{sheet, cell, error}], sample}`; it exits 0 even with formula errors, so `errors` must be read — rewrite.md "Formulas".
29
+
30
+ ## Fill and edit
31
+
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
+ - `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
+ - `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/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
+ - `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-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.
39
+ - `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
+ - `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
+ - `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.
42
+ - `bin/pdf-ops.cjs merge <out> <in…>` / `split <in> <from-to> <out>` / `rotate <in> <deg> <out> [pages]` / `watermark <in> <text> <out>` / `stamp <in.pdf> <stamps.json> <out.pdf>` / `encrypt <in> <out> <user-pw> [owner-pw]` / `decrypt <in> <pw> <out>` — page ops that keep every page verbatim (`rotate` pages like `1,3-5`), text stamping onto a flat (non-form) PDF — `stamps.json` = `[{page, x, y, text, size?, grey?}]` in points from the bottom-left (size 11, grey 0 = black, by default) — and AES-256 password protection (a wrong password exits 1). `watermark`/`stamp` draw Helvetica, or the bundled Noto Sans SC when the text has Chinese (same missing-character rule). An encrypted input exits 1 naming `decrypt`; `decrypt <in> "" <out>` handles an owner-password-only PDF.
43
+
44
+ ## Decks
45
+
46
+ Flags and outputs only; the workflow is deck-design.md.
47
+
48
+ - `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-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.
54
+
55
+ ## Validate and convert
56
+
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).