@liustack/pptfast 0.6.0 → 0.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -58,6 +58,28 @@ installNodePlatform()
58
58
  const bytes = await generatePptx(ir) // Uint8Array, ready to write to a .pptx
59
59
  ```
60
60
 
61
+ ## Browser
62
+
63
+ The default `@liustack/pptfast` entry is browser-safe by construction — its whole dependency closure has no `fs`, no `commander`, no Node-only API (`docs/architecture.md`'s platform seam). Which subpath to import depends on how your page loads code:
64
+
65
+ - **Bundler** (Vite, webpack, esbuild, Next.js, …) — the default entry, unchanged: `import { generatePptx, validateIr } from "@liustack/pptfast"`. `react`/`react-dom`/`zod`/`jszip`/`dagre`/`pptxgenjs` stay external, resolved from your own `node_modules` and deduped against whatever else you already depend on.
66
+ - **Bare `<script type="module">`, no build step** — `@liustack/pptfast/browser` instead. Every dependency is bundled in (react + react-dom/server + zod + jszip + dagre + pptxgenjs, ~1.7 MB raw / ~455 KB gzip), so it loads with nothing else on the page and no import map:
67
+
68
+ ```html
69
+ <script type="module">
70
+ import { validateIr, generatePptx } from "https://esm.sh/@liustack/pptfast/browser"
71
+ const { ok, ir, errors } = validateIr(deckJson)
72
+ if (!ok) throw new Error(errors.map((e) => e.message).join("\n"))
73
+ const bytes = await generatePptx(ir) // Uint8Array — new Blob([bytes]) to download
74
+ </script>
75
+ ```
76
+
77
+ - **Embedding just the validator** — a page that checks pasted/edited IR JSON and shows errors has no reason to carry the render/export chain at all. `@liustack/pptfast/validate` exports `validateIr`, `formatIssues`/`formatWarnings`, `irJsonSchema`/`styleJsonSchema`, `listThemes`, and the IR/style zod schemas — `react`, `react-dom/server`, `pptxgenjs`, `jszip`, and `dagre` are all absent from its closure by construction, not just unused at runtime, landing at a fraction of `/browser`'s size (~730 KB raw / ~155 KB gzip).
78
+
79
+ No `installPlatform()` call is needed in a browser — DOM parsing and (for `--pixels`-equivalent audits) SVG rasterization both default to the real browser globals (`DOMParser`, `OffscreenCanvas`) automatically, unlike `installNodePlatform()` (Quick start above), which is a Node-only requirement. Two honest caveats, not bugs: an image asset needs to already be a `data:` URI, or an `http(s)` URL the browser's own `fetch` can read cross-origin (the host needs permissive CORS headers — reading raw bytes to inline needs more than an `<img>` tag ever does) — `generatePptx` fetches such a URL for you at export time, but `auditDeck`'s pixel path (`{ pixels: true }`) refuses a remote `http(s)` image reference outright, the same "never a surprise network request" rule the Node/Sharp path also follows. `--pixels`-equivalent auditing needs `OffscreenCanvas`, which every evergreen browser has, while Node needs the optional `sharp` dependency instead (see Auditing below).
80
+
81
+ `pptfast preview --html` (see For AI agents below) is the project's most mature "ships to a browser" artifact today: a self-contained review page a Node CLI run generates once, with zero further dependencies or network calls once it's open in a tab — distinct from importing the SDK live into your own page, but worth knowing about if "zero-dependency browser artifact" is what you actually need.
82
+
61
83
  ## CLI
62
84
 
63
85
  | Command | Does |
@@ -80,9 +102,9 @@ const bytes = await generatePptx(ir) // Uint8Array, ready to write to a .pptx
80
102
 
81
103
  Run `node dist/cli.js schema` for the full JSON Schema — feed it to a model before asking it to write IR. A deck (`PptxIR`) has `version` (currently `"4"`, and now the default when omitted), `filename`, an optional `narrative` (a preset id string or a partial axes object — see Narratives below), `theme` (`id` plus optional `style`/`brand` overrides), `meta`, and `assets` — all optional with sane defaults — plus a separate optional `brand` (logo placement) and a required ordered list of `slides`. Each slide has a `type` (`cover`, `chapter`, `content`, `ending`), an optional `layout` (an explicit page-layout id that always wins over auto-selection — omit it and pptfast auto-selects one, see Layout selection below), an optional `arrangement` (how a content slide's body is laid out, e.g. `two_column`, `kpi_focus`), and a list of typed `components` (`bullets`, `kpi_cards`, `image`, `chart`, …). `assets` is `{ images: { [id]: { src, alt? } } }` — components reference images by `asset_id`, so the same image can be reused across slides without duplication.
82
104
 
83
- A deck also carries an optional `seed` (an integer that keeps auto-selected layouts stable across revisions — see Layout selection below for how it's derived when omitted). Any slide may set a stable `id` (what spec pages and validation error messages reference it by), `placeholder: true` (a slide with no content yet — injected by `assemble` for a spec page nobody has filled in, skipped by the content-quality checks, and blocking `render` unless `--draft`), and an optional `notes` (aliases `note`/`speaker_notes`/`speakerNotes`) that exports as a native PowerPoint speaker note — content for the presenter's own view, never drawn onto the slide canvas and never counted toward any layout capacity. Field names that commonly drift between a model's output and the schema (40 synonym pairs across component types, e.g. kpi `title`→`label`, quote `content`→`text`, swot `strength`→`strengths`, bmc `partners`→`key_partners`) are silently normalized to the canonical name at validate time — `validate`/`render`/`preview` print a note listing what changed, never a hard error. That rescue is scoped to weak-model synonym drift only — it does not cover pre-v4 vocabulary. A v4-labeled document that writes `scenario` instead of `narrative`, `mode`/`delivery` instead of `strategy`/`pacing`, or the old `narrative`/`text`/`presentation` axis values hard-rejects, listing the current names/values, exactly like any other unrecognized field or value. An explicit `version: "3"` (or `"2"`) also hard-rejects, with a migration pointer — see `pptfast migrate` below, the only supported path for old-vocabulary input.
105
+ A deck also carries an optional `seed` (an integer that keeps auto-selected layouts stable across revisions — see Layout selection below for how it's derived when omitted). Any slide may set a stable `id` (what spec pages and validation error messages reference it by), `placeholder: true` (a slide with no content yet — injected by `assemble` for a spec page nobody has filled in, skipped by the content-quality checks, and blocking `render` unless `--draft`), and an optional `notes` (aliases `note`/`speaker_notes`/`speakerNotes`) that exports as a native PowerPoint speaker note — content for the presenter's own view, never drawn onto the slide canvas and never counted toward any layout capacity. Field names that commonly drift between a model's output and the schema (53 synonym pairs across component types, e.g. kpi `title`→`label`, quote `content`→`text`, swot `strength`→`strengths`, bmc `partners`→`key_partners`) are silently normalized to the canonical name at validate time — `validate`/`render`/`preview` print a note listing what changed, never a hard error. That rescue is scoped to weak-model synonym drift only — it does not cover pre-v4 vocabulary. A v4-labeled document that writes `scenario` instead of `narrative`, `mode`/`delivery` instead of `strategy`/`pacing`, or the old `narrative`/`text`/`presentation` axis values hard-rejects, listing the current names/values, exactly like any other unrecognized field or value. An explicit `version: "3"` (or `"2"`) also hard-rejects, with a migration pointer — see `pptfast migrate` below, the only supported path for old-vocabulary input.
84
106
 
85
- Four component types are *full-body*: `swot` (strengths/weaknesses/opportunities/threats), `bmc` (the nine-block Business Model Canvas), `waterfall` (a running-total bridge chart), and `gantt` (dated bars on a shared numeric axis). Each fills a slide's entire content rect and must be the only component on its slide — mixing one in with anything else fails `validate` instead of silently dropping the sibling.
107
+ Eight component types are *full-body*: `swot` (strengths/weaknesses/opportunities/threats), `bmc` (the nine-block Business Model Canvas), `waterfall` (a running-total bridge chart), `gantt` (dated bars on a shared numeric axis), `pest` (a political/economic/social/technological macro-environment scan), `five_forces` (Porter's competitive-forces hub-and-spoke), `heatmap` (a value-driven color grid), and `sankey` (a layered, quantity-proportional flow diagram — shipped as native editable vectors, not the rasterized image the type gets elsewhere). Each fills a slide's entire content rect and must be the only component on its slide — mixing one in with anything else fails `validate` instead of silently dropping the sibling.
86
108
 
87
109
  The v4 IR schema is frozen as of 0.4.0 — future evolution is additive only (new optional fields, new enum members), and any breaking change ships under a new top-level `version` value with the same hard-reject-and-migration treatment v3 got. `pptfast migrate <v3-file.json> -o <out.json>` deterministically converts a v3 file to v4 (field renames only — same theme, layout selection, content budgets, and visual output) — see Deck projects below for the sibling `deck.plan.json` → `deck.spec.json` conversion.
88
110
 
@@ -180,7 +202,7 @@ pptfast audit examples/basic.json
180
202
 
181
203
  ## For AI agents
182
204
 
183
- The recommended loop for an agent generating a deck: read `pptfast schema` to learn the vocabulary, write an IR JSON, run `pptfast validate` and fix whatever it reports (errors carry a page number and a fixable-in-place message — the point is to close this loop without a human), then `pptfast audit` for the same kind of fixable-in-place feedback on what a *valid* deck can still get wrong at render time (overflow, low-contrast, overlap — exit code alone says whether it's clean), then `pptfast render`. `pptfast preview` gives the agent SVG files it can look at to self-check layout before committing to a render. Add `--html` to also write a self-contained `preview.html` for a human to review (keyboard nav, placeholder badges — a remote-URL image asset stays remote, the one self-containment gap). When every page is filled, that `preview.html` also overlays the same `audit` findings (per-page badges plus a findings panel, click to jump to the page) so a human reviewer sees them without a terminal — a deck with any placeholder page shows a one-line "audit skipped" notice instead. The reviewer can leave free-text per-page annotations right in `preview.html` and export them as a `revision-request.json` (a Blob download, no network or file write — preview stays read-only) for the agent to route back through `pages/*.json`. The Claude Code plugin above wraps this loop as a skill ([`skills/pptfast/SKILL.md`](./skills/pptfast/SKILL.md)). This exact loop is exercised by an internal, model-agnostic benchmark (`tests/bench/`, not published to npm) that mechanically scores how well a model follows the skill on a fixed question bank — see `tests/bench/README.md`.
205
+ The recommended loop for an agent generating a deck: read `pptfast schema` to learn the vocabulary, write an IR JSON, run `pptfast validate` and fix whatever it reports (errors carry a page number and a fixable-in-place message — the point is to close this loop without a human), then `pptfast audit` for the same kind of fixable-in-place feedback on what a *valid* deck can still get wrong at render time (overflow, low-contrast, overlap — exit code alone says whether it's clean), then `pptfast render`. `pptfast preview` gives the agent SVG files it can look at to self-check layout before committing to a render. Add `--html` to also write a self-contained `preview.html` for a human to review (keyboard nav, placeholder badges — a remote-URL image asset stays remote, the one self-containment gap) — zero network calls and zero further dependencies once it's open in a tab, the project's most mature zero-dependency browser artifact today (see Browser above). When every page is filled, that `preview.html` also overlays the same `audit` findings (per-page badges plus a findings panel, click to jump to the page) so a human reviewer sees them without a terminal — a deck with any placeholder page shows a one-line "audit skipped" notice instead. The reviewer can leave free-text per-page annotations right in `preview.html` and export them as a `revision-request.json` (a Blob download, no network or file write — preview stays read-only) for the agent to route back through `pages/*.json`. The Claude Code plugin above wraps this loop as a skill ([`skills/pptfast/SKILL.md`](./skills/pptfast/SKILL.md)). This exact loop is exercised by an internal, model-agnostic benchmark (`tests/bench/`, not published to npm) that mechanically scores how well a model follows the skill on a fixed question bank — see `tests/bench/README.md`.
184
206
 
185
207
  ## Roadmap
186
208
 
package/README.zh-CN.md CHANGED
@@ -56,6 +56,28 @@ installNodePlatform()
56
56
  const bytes = await generatePptx(ir) // Uint8Array,可直接写成 .pptx 文件
57
57
  ```
58
58
 
59
+ ## 浏览器
60
+
61
+ `@liustack/pptfast` 默认入口天生浏览器安全——它的整个依赖闭包不含 `fs`、不含 `commander`、不含任何 Node-only API(见 `docs/architecture.md` 的 platform seam 一节)。具体该 import 哪个子路径,取决于页面怎么加载代码:
62
+
63
+ - **打包器场景**(Vite、webpack、esbuild、Next.js 等)——默认入口,写法不变:`import { generatePptx, validateIr } from "@liustack/pptfast"`。`react`/`react-dom`/`zod`/`jszip`/`dagre`/`pptxgenjs` 依旧是 external,从你自己的 `node_modules` 解析,和你项目里其他依赖一起去重。
64
+ - **裸 `<script type="module">`,零构建**——改用 `@liustack/pptfast/browser`。每个依赖都已打包进去(react + react-dom/server + zod + jszip + dagre + pptxgenjs,约 1.7MB 原始 / 约 455KB gzip),页面上不需要任何 import map 或额外脚本就能加载:
65
+
66
+ ```html
67
+ <script type="module">
68
+ import { validateIr, generatePptx } from "https://esm.sh/@liustack/pptfast/browser"
69
+ const { ok, ir, errors } = validateIr(deckJson)
70
+ if (!ok) throw new Error(errors.map((e) => e.message).join("\n"))
71
+ const bytes = await generatePptx(ir) // Uint8Array —— new Blob([bytes]) 即可触发下载
72
+ </script>
73
+ ```
74
+
75
+ - **只嵌入校验器**——一个校验用户粘贴/编辑的 IR JSON 并展示错误的页面,完全没理由带上整条渲染/导出链。`@liustack/pptfast/validate` 导出 `validateIr`、`formatIssues`/`formatWarnings`、`irJsonSchema`/`styleJsonSchema`、`listThemes`,以及 IR/style 的 zod schema——`react`、`react-dom/server`、`pptxgenjs`、`jszip`、`dagre` 从依赖闭包层面就不存在(不是「运行时用不到」,而是构建时就没打进去),体积只有 `/browser` 的一个零头(约 730KB 原始 / 约 155KB gzip)。
76
+
77
+ 浏览器里不需要调用 `installPlatform()`——DOM 解析,以及(等价于 `--pixels` 的)SVG 光栅化,都会自动 fallback 到真实的浏览器全局对象(`DOMParser`、`OffscreenCanvas`),`installNodePlatform()`(见上文快速开始)只是 Node 场景下的硬性要求。两条如实说明的限制,而非缺陷:图片资产要么已经是 `data:` URI,要么是浏览器自身 `fetch` 能跨域读取的 `http(s)` URL(宿主需要开放的 CORS 头——把原始字节读出来内联,比 `<img>` 标签单纯显示图片的要求更高)——`generatePptx` 会在导出时替你 fetch 这类 URL,但 `auditDeck` 的像素审查路径(`{ pixels: true }`)会直接拒绝还带着远程 `http(s)` 图片引用的页面,和 Node/Sharp 路径共享同一条「绝不擅自发起意外网络请求」的规则。等价于 `--pixels` 的审查需要 `OffscreenCanvas`,现代浏览器都有,Node 一侧则需要可选依赖 `sharp`(见下文审查一节)。
78
+
79
+ `pptfast preview --html`(见下文「面向 AI agent」)是这个项目目前最成熟的「产物直接跑在浏览器里」的例子:Node CLI 跑一次生成一个自包含的审阅页,打开后零网络请求、零进一步依赖——和「把 SDK 实时 import 进你自己的页面」是两回事,但如果你要的正好是「零依赖浏览器产物」,这个已经是现成答案。
80
+
59
81
  ## CLI
60
82
 
61
83
  | 命令 | 作用 |
@@ -78,9 +100,9 @@ const bytes = await generatePptx(ir) // Uint8Array,可直接写成 .pptx 文
78
100
 
79
101
  运行 `node dist/cli.js schema` 获取完整 JSON Schema——让模型写 IR 之前先读它。一份 deck(`PptxIR`)包含 `version`(现为 `"4"`,且省略时默认就是它)、`filename`、一个可选的 `narrative`(预设 id 字符串,或部分轴对象——详见下文「叙事」一节)、`theme`(`id` 加可选的 `style`/`brand` 覆盖)、`meta`、`assets`——均可省略、有默认值——另外还有一个独立的可选 `brand`(logo 位置)字段,以及必填的有序 `slides` 列表。每张 slide 有一个 `type`(`cover`、`chapter`、`content`、`ending`)、一个可选的 `layout`(显式指定页面版式 id,一经设置恒生效、优先于自动选型——省略则由 pptfast 自动选型,详见下文「版式选型」)、一个可选的 `arrangement`(content slide 正文的排布方式,如 `two_column`、`kpi_focus`),以及一组带类型的 `components`(`bullets`、`kpi_cards`、`image`、`chart` 等)。`assets` 的形状是 `{ images: { [id]: { src, alt? } } }`,component 通过 `asset_id` 引用图片,同一张图可以在多页复用而不必重复内嵌。
80
102
 
81
- 一份 deck 还可以携带一个可选的 `seed`(整数,让自动选型的版式在多次修订之间保持稳定——省略时如何生成,详见下文「版式选型」)。任意 slide 都可以设置一个稳定的 `id`(spec 的页面和校验报错都靠它引用)、`placeholder: true`(还没有内容的占位 slide——由 `assemble` 为 spec 里没人填写的页面注入,内容质量检查会跳过它,`render` 也会因它拒绝导出,除非加 `--draft`),以及一个可选的 `notes`(同义词 `note`/`speaker_notes`/`speakerNotes`),导出为原生 PowerPoint 演讲者备注——只是给主讲人自己看的内容,不会画到幻灯片画布上,也从不计入任何版式容量。模型输出里容易和 schema 对不上的字段名(跨 component 类型共 40 组同义词,例如 kpi 的 `title`→`label`、quote 的 `content`→`text`、swot 的 `strength`→`strengths`、bmc 的 `partners`→`key_partners`)会在校验时静默改写成规范名——`validate`/`render`/`preview` 会打印一条改了什么的提示,从不因此报错。这套救援机制只覆盖弱模型的同义词漂移,不覆盖 v4 之前的旧词汇。标着 v4 却仍写 `scenario`(而不是 `narrative`)、`mode`/`delivery`(而不是 `strategy`/`pacing`)、或轴值还停留在旧的 `narrative`/`text`/`presentation` 的文档,会像任何其他未识别字段或非法值一样直接硬报错,并列出当前正确的名称和取值。显式写 `version: "3"`(或 `"2"`)同样硬拒绝并给出迁移指引——见下文 `pptfast migrate`,这是旧词汇输入唯一支持的路径。
103
+ 一份 deck 还可以携带一个可选的 `seed`(整数,让自动选型的版式在多次修订之间保持稳定——省略时如何生成,详见下文「版式选型」)。任意 slide 都可以设置一个稳定的 `id`(spec 的页面和校验报错都靠它引用)、`placeholder: true`(还没有内容的占位 slide——由 `assemble` 为 spec 里没人填写的页面注入,内容质量检查会跳过它,`render` 也会因它拒绝导出,除非加 `--draft`),以及一个可选的 `notes`(同义词 `note`/`speaker_notes`/`speakerNotes`),导出为原生 PowerPoint 演讲者备注——只是给主讲人自己看的内容,不会画到幻灯片画布上,也从不计入任何版式容量。模型输出里容易和 schema 对不上的字段名(跨 component 类型共 53 组同义词,例如 kpi 的 `title`→`label`、quote 的 `content`→`text`、swot 的 `strength`→`strengths`、bmc 的 `partners`→`key_partners`)会在校验时静默改写成规范名——`validate`/`render`/`preview` 会打印一条改了什么的提示,从不因此报错。这套救援机制只覆盖弱模型的同义词漂移,不覆盖 v4 之前的旧词汇。标着 v4 却仍写 `scenario`(而不是 `narrative`)、`mode`/`delivery`(而不是 `strategy`/`pacing`)、或轴值还停留在旧的 `narrative`/`text`/`presentation` 的文档,会像任何其他未识别字段或非法值一样直接硬报错,并列出当前正确的名称和取值。显式写 `version: "3"`(或 `"2"`)同样硬拒绝并给出迁移指引——见下文 `pptfast migrate`,这是旧词汇输入唯一支持的路径。
82
104
 
83
- 四种 component 类型是「满幅」的:`swot`(strengths/weaknesses/opportunities/threats 四象限)、`bmc`(九宫格商业模式画布)、`waterfall`(运行合计瀑布图)、`gantt`(共享数轴上的甘特条形图)。各自独占整张 slide 的内容区域,必须是该 slide 唯一的 component——混入其他 component 会在校验时报错,而不是静默丢弃。
105
+ 八种 component 类型是「满幅」的:`swot`(strengths/weaknesses/opportunities/threats 四象限)、`bmc`(九宫格商业模式画布)、`waterfall`(运行合计瀑布图)、`gantt`(共享数轴上的甘特条形图)、`pest`(政治/经济/社会/技术宏观环境扫描)、`five_forces`(波特五力竞争结构轮辐图)、`heatmap`(值驱动色阶网格)、`sankey`(分层且量值成比例的流向图——导出为原生可编辑矢量,而非该图表类型在别处常见的栅格图片)。各自独占整张 slide 的内容区域,必须是该 slide 唯一的 component——混入其他 component 会在校验时报错,而不是静默丢弃。
84
106
 
85
107
  v4 IR schema 自 0.4.0 起冻结——后续演进只走加法(新增可选字段、新增枚举值),任何破坏性变更都会启用新的顶层 `version` 值,并沿用 v3 那套硬拒绝 + 迁移提示的处理方式。`pptfast migrate <v3-file.json> -o <out.json>` 能确定性地把一份 v3 文件转成 v4(只做字段改名——theme、版式选型、内容预算与视觉输出都不变)——`deck.plan.json` → `deck.spec.json` 的姊妹转换见下文「Deck 项目」。
86
108
 
@@ -172,7 +194,7 @@ pptfast audit examples/basic.json
172
194
 
173
195
  ## 面向 AI agent
174
196
 
175
- 推荐给 agent 的生成回路:先读 `pptfast schema` 学词汇表,写出 IR JSON,跑 `pptfast validate` 并根据报错自纠(错误信息带页码和可直接照抄的修正方式,目的就是让这个回路不必依赖人工介入),再跑 `pptfast audit`——同样是可直接照抄的修正反馈,只是针对一份*合法* deck 在渲染层仍可能出现的问题(溢出、低对比度、重叠——exit code 本身就说明干不干净),最后执行 `pptfast render`。`pptfast preview` 能让 agent 在正式渲染前先看一遍 SVG,自查版式是否合理。加上 `--html` 还会额外写出一个自包含的 `preview.html`,供人工审查(键盘翻页、占位页角标——远程 URL 的图片资产仍是远程链接,这是自包含性上唯一的缺口)。当所有页面都已填写时,这份 `preview.html` 还会叠加同一份 `audit` 检查结果(每页一个数量角标,加一个可点击跳转的 findings 面板),让人工审查者不必打开终端就能看到问题——如果 deck 里还有占位页,则显示一行「audit 已跳过」的提示代替。审查者可以直接在 `preview.html` 里给每页写自由文本批注,并导出为 `revision-request.json`(浏览器 Blob 下载,不联网也不写文件——preview 始终只读),交给 agent 通过 `pages/*.json` 回填。上文的 Claude Code 插件已把这套回路封装成 skill([`skills/pptfast/SKILL.md`](./skills/pptfast/SKILL.md))。这套回路本身由一个模型无关的内部基准测试(`tests/bench/`,不发布到 npm)机械化验证——固定题库,评估模型跟随该 skill 的表现,细节见 `tests/bench/README.md`。
197
+ 推荐给 agent 的生成回路:先读 `pptfast schema` 学词汇表,写出 IR JSON,跑 `pptfast validate` 并根据报错自纠(错误信息带页码和可直接照抄的修正方式,目的就是让这个回路不必依赖人工介入),再跑 `pptfast audit`——同样是可直接照抄的修正反馈,只是针对一份*合法* deck 在渲染层仍可能出现的问题(溢出、低对比度、重叠——exit code 本身就说明干不干净),最后执行 `pptfast render`。`pptfast preview` 能让 agent 在正式渲染前先看一遍 SVG,自查版式是否合理。加上 `--html` 还会额外写出一个自包含的 `preview.html`,供人工审查(键盘翻页、占位页角标——远程 URL 的图片资产仍是远程链接,这是自包含性上唯一的缺口)——打开后零网络请求、零进一步依赖,是这个项目目前最成熟的零依赖浏览器产物(见上文「浏览器」)。当所有页面都已填写时,这份 `preview.html` 还会叠加同一份 `audit` 检查结果(每页一个数量角标,加一个可点击跳转的 findings 面板),让人工审查者不必打开终端就能看到问题——如果 deck 里还有占位页,则显示一行「audit 已跳过」的提示代替。审查者可以直接在 `preview.html` 里给每页写自由文本批注,并导出为 `revision-request.json`(浏览器 Blob 下载,不联网也不写文件——preview 始终只读),交给 agent 通过 `pages/*.json` 回填。上文的 Claude Code 插件已把这套回路封装成 skill([`skills/pptfast/SKILL.md`](./skills/pptfast/SKILL.md))。这套回路本身由一个模型无关的内部基准测试(`tests/bench/`,不发布到 npm)机械化验证——固定题库,评估模型跟随该 skill 的表现,细节见 `tests/bench/README.md`。
176
198
 
177
199
  ## 路线图
178
200