返回 ppt-master
template-fill-pptx.md
根目录 / skills / ppt-master / workflows / template-fill-pptx.md
1 ---
2 description: Fill Native PPTX route — use a native PowerPoint template deck, select fitting pages, and fill new material back without SVG conversion
3 ---
4
5 # Fill Native PPTX Route
6
7 > Run when the user provides a raw `.pptx` template plus new content / a new topic and asks to generate a `.pptx` from that template. Typical requests include "use this PPT template to generate a PPTX", "fill this deck with the new content", "fill this back into the template", "replace the copy in this PowerPoint", or "keep the original PowerPoint pages and swap in this material". This route treats the existing `.pptx` as a native slide library and produces a new `.pptx` by selecting, cloning, and patching source slides.
8
9 This route is **independent** from the SVG generation pipeline. It treats the source PPTX as a native template / slide library, keeps the original PowerPoint design intact, and writes a new `.pptx` by cloning selected source slides and replacing text directly in OOXML.
10
11 **Boundary against template-based generation**: run this route for raw PPTX template + generated PPTX requests. Skip this route only when the user explicitly wants a reusable template workspace or an SVG-generated deck that can freely select / repeat / skip / adapt template pages. In that case, they must run [`create-template.md`](./create-template.md) first and then provide the generated workspace root to Generate PPTX.
12
13 | User wants | Route |
14 |---|---|
15 | Generate a PPTX from a raw PPTX template | This route |
16 | Directly edit / fill cloned PPTX slides | This route |
17 | Create a reusable design asset from the PPTX | `create-template` |
18 | Generate a new PPT from a reusable template package | Main pipeline Step 3 with the explicit template directory path |
19 | Generate through the SVG pipeline directly from a raw PPTX "template" | Not allowed; create the template package first |
20
21 ## When to Run
22
23 Recognize requests that combine an existing PowerPoint template with new content or a topic and ask for a generated `.pptx` without explicitly requesting the reusable SVG/template-package route:
24
25 | Pattern | Example |
26 |---|---|
27 | Existing `.pptx` + "fill back" intent | "Use this deck and fill in the attached material" |
28 | Raw PPTX template + generated PPTX | "Use this PowerPoint template to generate a PPTX about this topic" |
29 | Existing `.pptx` + selective reuse | "Do not keep every page; only use the slides that fit" |
30 | Existing `.pptx` + copywriting replacement | "Keep the original design and replace the copy with this text" |
31 | Native PPT template fill | "Use this PowerPoint template for this content and fill the slides directly" |
32 | Direct wording | "Fill this deck with the new content" |
33
34 **Hard rule**: Do not run `pptx_to_svg.py`, `pptx_template_import.py`, `finalize_svg.py`, or `svg_to_pptx.py` for this route. SVG conversion is for presentation generation / template creation; this route is direct PowerPoint editing.
35
36 **Deterministic routing rule**: do not ask a route-choice question for raw PPTX template + generated PPTX requests; route them here. If the user asks for SVG/template-workspace generation from a raw PPTX, state that `create-template` must run first and stop this route until they provide the generated workspace root.
37
38 ---
39
40 ## Step 1: Inputs
41
42 🚧 **GATE**: The user has provided:
43
44 | Input | Required | Notes |
45 |---|---:|---|
46 | Source PPTX | Yes | Original design deck to reuse as a slide library |
47 | Content material | Yes | User text, Markdown, document, URL-derived source, or a clear topic brief |
48 | Target output intent | Optional | Audience, page count, tone, must-keep pages, must-drop pages |
49
50 If the content material is only a topic with no supporting facts, gather or ask for source material first. Do not invent detailed factual content.
51
52 ---
53
54 ## Step 2: Create the Project Workspace
55
56 Create a dedicated project directory under `projects/`. Do not write outputs directly into `projects/` root. Reuse the standard project manager so source import rules stay consistent with the rest of the repository:
57
58 ```bash
59 python3 skills/ppt-master/scripts/project_manager.py init "<project_name>" --format ppt169
60 python3 skills/ppt-master/scripts/project_manager.py import-sources "<project_dir>" "<source.pptx>" "<material...>"
61 ```
62
63 **Source import rule**: `project_manager.py import-sources` moves only sources under repository `projects/` and copies all others. `--copy` preserves a projects-local input; `--move` never widens that scope. Reuse this path.
64
65 Use this fixed layout:
66
67 | Path | Required content |
68 |---|---|
69 | `<project_dir>/sources/` | Source PPTX and user-provided text / Markdown / converted materials |
70 | `<project_dir>/analysis/` | Slide library JSON, page-selection reasoning, and final fill plan |
71 | `<project_dir>/exports/` | Final generated PPTX only |
72 | `<project_dir>/validation/` | Read-back Markdown, extracted validation assets, and validation notes |
73
74 **Hard rule**: A template-fill project is a project, not a loose output file. The final answer must point to `<project_dir>/exports/<name>.pptx`, and all intermediate artifacts must remain inside `<project_dir>`.
75
76 ---
77
78 ## Step 3: Extract the PPTX Intake Bundle
79
80 `project_manager.py import-sources` automatically runs the standard PPTX intake for imported PowerPoint files and writes `<stem>.slide_library.json` into `<project_dir>/analysis/`. If you are working from a manually assembled project that does not have the intake artifact, run the template-fill analyzer directly:
81
82 ```bash
83 python3 skills/ppt-master/scripts/template_fill_pptx.py analyze "<project_dir>/sources/<source.pptx>" -o "<project_dir>/analysis/<stem>.slide_library.json"
84 ```
85
86 Read `<project_dir>/analysis/<stem>.slide_library.json` (intake prefixes per-deck artifacts by the template deck's file stem) and identify:
87
88 | Field | Use |
89 |---|---|
90 | `slides[].page_type` | Cover / chapter / content / ending candidate |
91 | `slides[].text_summary` | Current semantic purpose of the source page |
92 | `slides[].slots[]` | Replaceable text slots with `slot_id`, `role`, `geometry`, paragraph count, and old text |
93 | `slides[].slots[].role` | Title / body / label candidate hint |
94 | `slides[].tables[]` | Native PowerPoint tables with `table_id`, row / column counts, per-cell coordinates/text, and merge anchor/slave topology |
95 | `slides[].charts[]` | Native PowerPoint charts with `chart_id` and an `edit_capability` safety result derived from the actual chart XML |
96 | `slides[].diagrams[]` | SmartArt layout, semantic nodes, hierarchy/connections, geometry, and extraction status; inventory-only |
97
98 **Selection rule**: Pick pages by content fitness, not by source order alone. A source page is useful only if its visible structure can carry the target message without heavy redesign.
99
100 A page's layout already encodes a rhetorical shape — a single hero statement, a lead-then-detail split, a 2×2 comparison, a stepwise progression, a metric row. Match the source material's own logic to a page whose structure expresses that same logic; do not pour unrelated content into a slot just because it is empty. When no selected page fits a piece of content well, drop that page or that content rather than forcing it — a forced fill reads as stiff. It is fine to use fewer pages than the source deck has.
101
102 **Layout-first planning**: Treat `<stem>.slide_library.json` as a layout inventory, not as an ordered deck outline. Before writing `fill_plan.json`, infer each reusable source page's affordance from JSON fields:
103
104 | JSON signal | Layout planning use |
105 |---|---|
106 | `slides[].page_type` | Identify cover / TOC / chapter / ending candidates, but do not preserve their original order by default |
107 | `slots[].role` counts | Infer whether the page is a hero statement, comparison, multi-card list, timeline, metric row, or dense explanation |
108 | `slots[].geometry` | Estimate whether each text slot is a short label, medium title, body block, caption, or decorative number |
109 | `slots[].text_metrics.font_size_px` | Estimate text capacity together with geometry; larger type means fewer safe characters |
110 | `slots[].text_summary` | Read the source page's original rhetorical pattern, not its literal placeholder wording |
111 | `diagrams[].layout` + `nodes` | Understand the SmartArt's source meaning; template-fill preserves it unchanged and cannot map new text into it |
112
113 **SmartArt boundary**: A selected source slide keeps its original native SmartArt parts. `check-plan` warns because the fill plan cannot replace SmartArt node text; choose another layout unless the original diagram content is intentionally retained, or explicitly accept the warning.
114
115 **Hard rule**: The target story controls output order. Source slides may move forward, move backward, be omitted, or be reused several times when their layout matches multiple target messages. Never treat source slide order as a default outline unless the user explicitly asks to preserve it.
116
117 **Required mapping pass**: Record a concise page-to-layout rationale in each planned slide before finalizing the plan. Use the per-slide `layout_rationale` object in `fill_plan.json` with `layout_pattern`, `why_fit`, and `risk`. This is human-review evidence that selection came from template structure rather than sequential replacement; it is not a mechanical checker gate.
118
119 ---
120
121 ## Step 4: Build the Fill Plan
122
123 Create a scaffold:
124
125 ```bash
126 python3 skills/ppt-master/scripts/template_fill_pptx.py scaffold "<project_dir>/analysis/<stem>.slide_library.json" -o "<project_dir>/analysis/fill_plan.json" --slides "1,3,4"
127 ```
128
129 Then edit `<project_dir>/analysis/fill_plan.json` by hand from the source material. The plan is the single execution contract.
130
131 **Pages are reusable**: the output is the ordered `slides` list, not a one-to-one copy of the source deck. A source page is not single-use — list the same `source_slide` as many times as you need, each entry with its own `replacements`, to drive several output slides from one good layout (e.g., reuse a single content layout for five content pages). Likewise you may omit source pages entirely and put the selected ones in any order.
132
133 **Scaffold boundary**: `scaffold --slides` is only a convenience starter. If the final plan needs repeated source pages or a story order that differs from the template order, duplicate / reorder entries in `fill_plan.json` manually or generate the plan from `<stem>.slide_library.json`; do not let scaffold output constrain the deck structure.
134
135 The plan structure:
136
137 ```json
138 {
139 "schema": "template_fill_pptx_plan.v1",
140 "status": "draft",
141 "source_pptx": "projects/source.pptx",
142 "accepted_warnings": [
143 {
144 "plan_slide": 3,
145 "slot_id": "s03_sh5",
146 "code": "text_capacity",
147 "reason": "User accepted dense wording"
148 }
149 ],
150 "slides": [
151 {
152 "source_slide": 1,
153 "purpose": "cover",
154 "layout_rationale": {
155 "layout_pattern": "hero cover",
156 "why_fit": "Large title and subtitle slots fit the opening message without redesign.",
157 "risk": "Subtitle must stay short."
158 },
159 "notes": "Speaker notes for this filled slide.",
160 "transition": "fade",
161 "replacements": [
162 {
163 "slot_id": "s01_sh4",
164 "text": "New title"
165 }
166 ],
167 "table_edits": [
168 {
169 "table_id": "s01_tbl3",
170 "cells": [
171 {"row": 0, "col": 0, "text": "Metric"},
172 {"row": 0, "col": 1, "text": "Value"}
173 ]
174 }
175 ],
176 "chart_edits": [
177 {
178 "chart_id": "s01_ch4",
179 "categories": ["A", "B"],
180 "series": [
181 {"name": "Series 1", "values": [10, 20]}
182 ]
183 }
184 ]
185 }
186 ]
187 }
188 ```
189
190 **Per-slide plan discipline**:
191
192 | Decision | Rule |
193 |---|---|
194 | `status` | Keep `"draft"` until the user has reviewed the page sequence / reuse / deletion decisions. Set to `"confirmed"` only after approval. |
195 | `source_slide` | Repeat the same value across multiple entries to reuse one source layout for several output slides; order is free and must follow the target story rather than source deck order |
196 | `layout_rationale` | Human review aid for page selection. Include `layout_pattern`, `why_fit`, and `risk`; it is not a mechanical checker gate. |
197 | `accepted_warnings` | Optional audit trail for warnings the user or agent explicitly accepts. `check-plan` warnings remain non-blocking; errors must be fixed. |
198 | `notes` | Optional spoken speaker notes for the filled slide — see **Speaker notes** below; write prose, not a copy of the on-slide text |
199 | `transition` | Optional per-slide page transition; overrides the `apply --transition` default. New plans use one canonical native gallery effect from [`animations.md`](../references/animations.md) §3; old names remain read-compatible. Accepts `none` to remove the visual effect, `keep` to preserve the source, or an object containing only `effect`, `effect_options`, `duration`, and `advance_after`, such as `{ "effect": "push", "effect_options": { "direction": "left" }, "duration": 0.6, "advance_after": 5 }`. `check-plan` and `apply` reject unknown object fields. |
200 | `replacements` | Target by `slot_id` whenever possible; `shape_id` and `shape_name` are fallback selectors |
201 | `table_edits` | Optional native table cell edits; target by `table_id` whenever possible and use zero-based `row` / `col` |
202 | `chart_edits` | Optional native chart data edits; target by `chart_id`, set `categories`, and provide one or more `series` |
203 | Short text | For labels / chapter names / directory items, fit the slot's visual capacity from geometry and font size; do not rely on old placeholder length alone |
204 | Body text | May be moderately freer than the original, but keep paragraph count, visual width, and information density near the slot's geometry capacity |
205 | Empty slots | Use `scaffold --include-empty` only when a real placeholder is empty in the source deck |
206 | Native tables | Keep the original table row and column count; edit ordinary cells or a merge anchor only. A merge slave is not visible and is rejected by both `check-plan` and `apply`. This route never changes table structure. |
207 | Native charts | Each series `values` list must match the category count. Single-plot classic charts whose every series uses `c:cat/c:val` are editable; analyzer/checker preflight the structure and the runtime writer revalidates the actual chart XML before mutation. |
208 | Chart edit boundary | A single classic plot is editable when every series uses `c:cat/c:val`, including stock, 3D, surface, and other classic plot types. Date-axis and multi-level categories are accepted with a warning because replacement categories are flattened to one level. Scatter, bubble, ChartEx/unknown frames, multi-plot/combo charts, missing-series charts, and non-`c:cat/c:val` data models are rejected. Use beautify / main pipeline to redraw unsupported charts, or leave the native chart untouched. |
209 | Facts | Every substantive claim must come from the user material |
210
211 **Fit check before apply**:
212
213 - Cover pages: replace title / subtitle / author only.
214 - Chapter pages: use short section labels.
215 - Dense content pages: compress material to bullets matching the existing slot capacity.
216 - Decorative or image-heavy pages: avoid forcing long prose into label-sized slots.
217 - Repeated source pages: every repeated entry must carry a distinct purpose and replacement set; avoid visual repetition unless the repeated layout expresses the same rhetorical pattern.
218 - Reordered source pages: verify the new sequence reads as a coherent story; template page numbers, decorative section markers, and notes must be updated to match the output order.
219
220 **Speaker notes (the `notes` field)** — distilled from the main pipeline's Logic Construction Phase, scaled to one note per planned slide:
221
222 Each `notes` value is **pure spoken narration**: write only what a presenter would say aloud, so the same text also works if the deck is later sent through `notes_to_audio.py`. The note explains and connects; it must not just restate the words already on the slide.
223
224 | Rule | Detail |
225 |---|---|
226 | Length | 2–5 natural sentences carrying the page's core message; cover / chapter / ending pages can be one or two sentences |
227 | Transitions | Carry page-to-page flow in the opening sentence as natural prose ("在明确了背景之后……" / "Having framed X, let's turn to Y") — never bracketed `[过渡]` / `[Transition]` tags |
228 | Plain prose only | No `#` heading line, no `- ` bullet lists, no `要点:① …` / `Key points:` lines, no `时长:2分钟` / `Duration:` annotations — embedded notes keep them verbatim and TTS would read them aloud |
229 | Number readability | Spell out figures when literal TTS pronunciation is awkward (Chinese "百分之六十八" over "68%"; plain English integers and percentages are fine) |
230 | One language | Match the deck's language; do not mix languages inside one note |
231 | Source-bound | Every substantive claim comes from the user material, same as `replacements` |
232
233 Example `notes` value for a Chinese content slide:
234
235 ```json
236 "notes": "在看清整体市场格局之后,我们把镜头拉近到成都二手房的头部板块。当前挂牌均价同比上涨约百分之十二,但成交周期反而拉长到九十天以上,说明买方观望情绪在加重。这组数据是后面定价策略的基础,请重点留意。"
237 ```
238
239 ---
240
241 ## Step 5: Check Text Capacity
242
243 Run the data-based capacity check before applying the plan:
244
245 ```bash
246 python3 skills/ppt-master/scripts/template_fill_pptx.py check-plan "<project_dir>/analysis/<stem>.slide_library.json" "<project_dir>/analysis/fill_plan.json" -o "<project_dir>/analysis/check_report.json"
247 ```
248
249 Interpret the report:
250
251 | Warning type | Action |
252 |---|---|
253 | Short label exceeds visual width | Rewrite shorter or choose a layout with a larger label slot; do not shrink font by default |
254 | Title too long | Rewrite first; only use font-size changes as a last resort |
255 | Body much longer than source slot | Compress, split across another selected page, or choose a larger source page |
256 | SmartArt source content remains unchanged | Pick another source slide unless the original SmartArt wording is intended; otherwise record the accepted warning |
257 | Missing target | Fix `slot_id` / `shape_id`; do not apply the plan |
258
259 `check-plan` emits stable `code` fields in its JSON results so warnings can be tracked without parsing message text. Warnings are advisory and do not fail the command; record any intentionally accepted warning in `accepted_warnings` when it matters for review. Errors are blocking and must be fixed before apply.
260
261 **Default fitting policy**: Check fit against visual capacity, not raw character count. CJK characters, Latin letters, numbers, and punctuation occupy different visual widths; old placeholder text is only a weak signal. Use `capacity_visual_width` when present, together with `slots[].geometry` and `slots[].text_metrics.font_size_px`, to decide whether to rewrite, split, or choose a different source layout. Do not use per-item font shrinking as a default strategy because it breaks template consistency.
262
263 ---
264
265 ## Step 6: Apply the Plan
266
267 ⛔ **BLOCKING GATE**: The user has reviewed the planned output order, omitted pages, reused pages, and material-to-layout fit. Set `<project_dir>/analysis/fill_plan.json` top-level `status` to `"confirmed"` only after that review. `apply` rejects an unconfirmed plan by default; `--force` exists only for deliberate recovery/debug use.
268
269 Run:
270
271 ```bash
272 python3 skills/ppt-master/scripts/template_fill_pptx.py apply "<project_dir>/sources/<source.pptx>" "<project_dir>/analysis/fill_plan.json" -o "<project_dir>/exports/<output.pptx>"
273 ```
274
275 By default `apply` preserves every cloned slide's existing transition. Select
276 `--transition <effect>` to replace it with a canonical gallery effect from
277 [`animations.md`](../references/animations.md) §3, and use
278 `--transition-duration <seconds>` for the replacement duration; old names
279 remain accepted only as compatibility CLI inputs. Pass `--transition none` for
280 no visual motion. `--transition keep` states the default preservation policy
281 explicitly. A per-slide `transition` field overrides the CLI and may include
282 native `effect_options`; these require an explicit effect and are validated
283 effect-by-effect. `advance_after` keeps click advance enabled and adds timed
284 advance; it also works with `none` (timing-only transition) and `keep` (source
285 effect preserved, Choice/Fallback timing updated together).
286
287 `apply` appends a timestamp automatically. For example, `-o "<project_dir>/exports/demo.pptx"` writes `demo_YYYYMMDD_HHMMSS.pptx`. If the filename already ends with `_YYYYMMDD_HHMMSS`, it is left unchanged.
288
289 The script:
290
291 | Behavior | Result |
292 |---|---|
293 | Clones selected source slides | Original slide design, relationships, images, layouts, and animations are preserved where PowerPoint supports them |
294 | Replaces text nodes | Text frames remain editable in PowerPoint |
295 | Writes `notes` fields | Speaker notes are embedded as native PowerPoint notes slides |
296 | Applies `--transition` / per-slide `transition` | Applies the requested visual-transition and slide-advance policy; `keep` may preserve no carrier and `none` may remove it |
297 | Rebuilds presentation slide list | Output deck contains only the planned slide sequence |
298 | Adds timestamp to PPTX filename | Matches the main SVG-to-PPTX export convention |
299 | Drops orphaned source parts | Output carries only the selected pages and the layouts / media / charts they still reference (reachability prune) |
300
301 **Animation policy**: Template-fill preserves each cloned slide's existing
302 object animation XML (the SVG pipeline's generated object animation defaults
303 are not applied here). It also preserves source page transitions by default.
304 Use `apply --transition` or a per-slide `transition` field only when the user
305 requests a replacement or removal. `keep` preserves direct and
306 `mc:AlternateContent` transition effects without converting unknown effects to
307 `fade`; explicit replacement removes the old logical carrier before writing one
308 new carrier. If the user asks to change object-level animation order / timing /
309 effects, treat that as a separate direct-PPTX animation customization task.
310
311 ---
312
313 ## Step 7: Validate Output
314
315 Run a lightweight readability check:
316
317 ```bash
318 python3 skills/ppt-master/scripts/template_fill_pptx.py validate "<project_dir>"
319 ```
320
321 The validator finds the latest PPTX in `<project_dir>/exports/`, runs `ppt_to_md.py` into `<project_dir>/validation/readback.md`, and writes `<project_dir>/validation/validate_report.json`. `exports/` must contain only final deliverables.
322
323 Verify:
324
325 | Check | Expected |
326 |---|---|
327 | Output filename | Ends with `_YYYYMMDD_HHMMSS.pptx` |
328 | Slide count | Matches `len(fill_plan.slides)` |
329 | Key title text | Appears in the extracted Markdown |
330 | Native table cells | Updated values appear in the extracted Markdown table |
331 | Native chart data | Updated labels / values are readable from the extracted Markdown when `ppt_to_md.py` can surface them |
332 | Multi-line body text | Preserves intended line / paragraph breaks |
333 | Speaker notes | Read-back note count matches planned `notes` fields |
334 | Missing target errors | None from `template_fill_pptx.py apply` |
335
336 If the extracted text is correct but visual overflow is likely, reduce the text in `fill_plan.json` and re-run Step 4.
337
338 ```markdown
339 ## ✅ Template Fill Complete
340
341 - [x] Standard PPTX intake extracted from the source deck, including `<stem>.slide_library.json`
342 - [x] `fill_plan.json` selects only pages that fit the target story
343 - [x] User reviewed the story structure and `fill_plan.json` has `status: "confirmed"`
344 - [x] `check-plan` run; errors fixed; warnings reviewed / optionally recorded in `accepted_warnings`
345 - [x] Output PPTX generated through direct OOXML text replacement
346 - [x] Speaker notes embedded when `notes` fields are present
347 - [x] `template_fill_pptx.py validate` read-back check passed
348 ```
349
350 ---
351
352 ## Current Boundary
353
354 | Capability | Status |
355 |---|---|
356 | Select / reorder / repeat source slides | Supported |
357 | Replace text in existing text frames | Supported |
358 | Edit native PowerPoint table cell text | Supported for ordinary cells and merge anchors; merge slaves fail closed |
359 | Edit native PowerPoint chart categories / series data | Supported for single-plot classic `c:cat/c:val` charts; runtime XML validation remains authoritative |
360 | Read SmartArt node text / hierarchy / layout | Supported in intake and planning |
361 | Preserve existing native SmartArt unchanged | Supported by recursive private-part cloning |
362 | Preserve original visual design | Supported by cloning slide parts directly |
363 | Page-to-page transitions | Supported via `apply --transition` or per-slide `transition` |
364 | Replace images | Not in v1 |
365 | Object-level animations | Not authored in v1; entrance, emphasis, motion-path, and exit effects are preserved from source only and handled as a separate task |
366 | Edit chart formatting / axes / legend layout | Not in v1 |
367 | Edit or generate native SmartArt | Not supported; regenerated visual routes use ordinary editable shapes |
368 | Automatic visual overflow detection | Not in v1; use text-capacity judgment from the library slots |
369 | Material-divergence reshaping (§c content strategy) | Not applicable — this route fills text into existing slots, it does not author an outline from a source, so the Generate PPTX `content_divergence` free-text field has no role here |
370
370 lines MARKDOWN