| 1 | --- |
| 2 | description: Native enhancement platform for existing PPTX files, with delivery checks and scoped OOXML updates without SVG conversion |
| 3 | --- |
| 4 | |
| 5 | # Enhance Native PPTX Route |
| 6 | |
| 7 | > Top-level route for enhancing an existing PowerPoint deck without regenerating it. The current write scope is speaker notes, narration audio, slide auto-advance timings, and global or per-slide page transitions; read-only delivery checks always run. |
| 8 | |
| 9 | This route treats a `.pptx` as the artifact to preserve. It archives the source file into a lightweight project, uses `ppt_to_md.py` only to understand slide content, then patches the archived PPTX package directly through OOXML zip operations. |
| 10 | |
| 11 | --- |
| 12 | |
| 13 | ## 1. Platform Contract |
| 14 | |
| 15 | | Rule | Contract | |
| 16 | |---|---| |
| 17 | | Source file | If already under `projects/`, move it into the enhancement project; otherwise copy it | |
| 18 | | Visible slides | Do not rewrite existing text, shapes, images, charts, tables, masters, or layouts | |
| 19 | | Route | Direct PPTX package patching; no SVG conversion | |
| 20 | | Output | A new `.pptx` under `<project>/exports/` | |
| 21 | | Project kind | `native_pptx_enhancement` | |
| 22 | |
| 23 | **Hard rule**: Native enhancement is append-oriented. It may add notes, media, timings, transitions, relationships, and content-type records. It must not regenerate slides. |
| 24 | |
| 25 | **Forbidden — SVG pipeline**: |
| 26 | - Do not run `pptx_template_import.py` |
| 27 | - Do not create `svg_output/` |
| 28 | - Do not run `finalize_svg.py` |
| 29 | - Do not run `svg_to_pptx.py` |
| 30 | |
| 31 | **Hard rule — public entrypoint**: Route and document all new work through |
| 32 | `native_enhance_pptx.py`. The legacy `native_narration_pptx.py` command remains |
| 33 | only as a thin CLI compatibility shim; it is not a separate route. The core |
| 34 | continues to accept the legacy `native_narration_pptx_project.v1` project schema. |
| 35 | |
| 36 | **OOXML execution model**: |
| 37 | |
| 38 | ```text |
| 39 | source.pptx |
| 40 | → unzip to temporary work directory |
| 41 | → patch only required package parts |
| 42 | → rezip to exports/<source>_enhanced.pptx |
| 43 | ``` |
| 44 | |
| 45 | --- |
| 46 | |
| 47 | ## 2. Module Scope |
| 48 | |
| 49 | | Module | V1 status | Behavior | |
| 50 | |---|---:|---| |
| 51 | | `narration.notes` | Enabled | Add or replace speaker notes generated from slide content | |
| 52 | | `narration.audio` | Enabled | Embed one audio file per slide | |
| 53 | | `narration.timings` | Enabled | Set narrated slides to auto-advance by audio duration | |
| 54 | | `narration.transitions` | Enabled | Add page-level transitions for narrated/selected slides | |
| 55 | | `delivery.check` | Enabled | Read-only package/font/media/hidden-slide/file-size and existing-motion audit | |
| 56 | | `media` | Planned | Background music, video, media compression | |
| 57 | | `presenter` | Planned | Q&A notes, speaker cues, rehearsal artifacts | |
| 58 | | `animation` | Planned | Explicit object-level animation only | |
| 59 | | `visible-stamp` | Planned | Watermark/footer/logo; requires explicit confirmation | |
| 60 | |
| 61 | **Default — current write scope only**: Do not implement planned write modules inside this route yet. Keep mutations limited to notes, narration audio, timings, and page transitions. |
| 62 | |
| 63 | **Object animation boundary**: `delivery.check` reports existing object-animation presence, and apply proves its fingerprint is unchanged. It does not author or edit object animations. The shared animation writer builds a complete timing tree for generated slides and is not safe to append to an arbitrary native slide. |
| 64 | |
| 65 | --- |
| 66 | |
| 67 | ## 3. When to Run |
| 68 | |
| 69 | | Condition | Action | |
| 70 | |---|---| |
| 71 | | Existing `.pptx` + wants notes / narration / voiceover / auto-play / page transitions while keeping format stable | Run this route | |
| 72 | | Existing `.pptx` + asks to optimize it but says not to change existing content or layout | Run this route only for V1 narration enhancements; clarify any visible-slide request | |
| 73 | | Existing `.pptx` + asks to beautify or re-layout | Enter Generate PPTX with the [`beautify-pptx`](./profiles/beautify-pptx.md) profile | |
| 74 | | Existing `.pptx` + asks to fill new content into the design | Use [`template-fill-pptx`](./template-fill-pptx.md) | |
| 75 | | PPT Master generated project with `svg_output/` | Stay in Generate PPTX and run the shared [`generate-audio`](./stages/generate-audio.md) stage | |
| 76 | |
| 77 | --- |
| 78 | |
| 79 | ## 4. Create the Project and Draft Plan |
| 80 | |
| 81 | 🚧 **GATE**: User provided an existing `.pptx`. |
| 82 | |
| 83 | Run: |
| 84 | |
| 85 | ```bash |
| 86 | python3 skills/ppt-master/scripts/native_enhance_pptx.py init "<source.pptx>" --name "<project_slug>" |
| 87 | ``` |
| 88 | |
| 89 | Project layout: |
| 90 | |
| 91 | | Path | Purpose | |
| 92 | |---|---| |
| 93 | | `<project>/project.json` | Project schema, kind, enabled modules, source paths, defaults | |
| 94 | | `<project>/sources/<source>.pptx` | Archived source PPTX used for package patching | |
| 95 | | `<project>/sources/<source>.md` | `ppt_to_md.py` output for slide understanding | |
| 96 | | `<project>/analysis/slide_index.json` | Slide order and PPTX slide part mapping | |
| 97 | | `<project>/notes/` | Per-slide spoken notes, named `001.md`, `002.md`, ... | |
| 98 | | `<project>/audio/` | Per-slide narration media, named `001.mp3`, `002.mp3`, ... | |
| 99 | | `<project>/exports/` | Enhanced PPTX copies | |
| 100 | | `<project>/validation/` | Delivery checks, readiness reports, and read-back artifacts | |
| 101 | |
| 102 | **Validation**: `project.json` contains `schema: native_pptx_enhancement_project.v1`, `kind: native_pptx_enhancement`, and `modules` containing `notes`, `audio`, `timings`, `transitions`, and `delivery.check`. |
| 103 | |
| 104 | `init` records the archived source SHA-256 and ordered slide-part roster, then writes the intake audit to `<project>/validation/report.json`. Package-integrity, OPC part/content-type/relationship, XML, slide-inventory, transition, or object-animation errors stop before a project-local source is moved. The only retained historical structural baseline is the narrowly recognized legacy notes-slide relationship to a missing notes master; it remains visible in the report and apply may not add any new structural error. |
| 105 | |
| 106 | **Source import rule**: When `<source.pptx>` is inside the repo's `projects/` tree, `init` moves it into `<project>/sources/`. When it is outside `projects/`, `init` copies it into `<project>/sources/`. The mode is recorded in `project.json` as `source_import.mode`. |
| 107 | |
| 108 | The `init` command also writes: |
| 109 | |
| 110 | ```text |
| 111 | <project>/analysis/enhancement_plan.json |
| 112 | ``` |
| 113 | |
| 114 | **Hard rule**: Treat this draft plan as the first user-facing artifact. Do not generate notes, list voices, generate audio, or apply package patches before the user confirms which enhancements to add. |
| 115 | |
| 116 | --- |
| 117 | |
| 118 | ## 5. Enhancement Plan Confirmation |
| 119 | |
| 120 | 🚧 **GATE**: Step 4 complete; `<project>/analysis/enhancement_plan.json` exists. |
| 121 | |
| 122 | If the project already existed or notes/audio coverage changed, refresh the draft: |
| 123 | |
| 124 | ```bash |
| 125 | python3 skills/ppt-master/scripts/native_enhance_pptx.py plan "<project>" |
| 126 | ``` |
| 127 | |
| 128 | `plan` preserves module settings, refreshes coverage, and emits a |
| 129 | reconfirmation `draft`. It changes `audio.enabled: true` / |
| 130 | `notes.enabled: false` to `notes.enabled: true`; `validate`/`apply` reject the |
| 131 | old state. Audio remains unchecked until `validate` runs ffprobe. Supplied CLI |
| 132 | flags override. |
| 133 | |
| 134 | Present the plan to the user before generating notes or audio: |
| 135 | |
| 136 | | Module | Recommended default | Confirmation question | |
| 137 | |---|---|---| |
| 138 | | `notes` | Enabled; required whenever audio is enabled | Add/replace speaker notes generated from slide content? | |
| 139 | | `audio` | Enabled when user wants narration/video/autoplay | After notes are complete, generate one narration audio file per slide? | |
| 140 | | `timings` | Enabled with audio | Set slide auto-advance from audio duration? | |
| 141 | | `transitions` | Enabled, `fade` 0.5s | Add page transitions? Which canonical native effect, Effect Options, and duration? | |
| 142 | | `delivery.check` | Always on, read-only | No confirmation required; review errors and advisories | |
| 143 | |
| 144 | **⛔ BLOCKING**: Stop here and wait for explicit user confirmation. Do not generate notes, generate audio, or patch the PPTX until the user confirms the module plan. |
| 145 | |
| 146 | **Hard dependency — notes before audio**: Confirming `audio.enabled: true` |
| 147 | also requires `notes.enabled: true`. If complete per-slide notes do not already |
| 148 | exist, run Step 6 and generate them before entering audio configuration or |
| 149 | audio generation. Never generate narration directly from slide text or bypass |
| 150 | the notes artifact. |
| 151 | |
| 152 | **Transition/timing ownership**: |
| 153 | |
| 154 | | Confirmed state | Enter transition | Slide advance | |
| 155 | |---|---|---| |
| 156 | | Transitions enabled with an effect | Replace with that exact effect and duration | Preserve unless timings is enabled | |
| 157 | | Transitions disabled with a non-`none` configured effect | Preserve the source effect, including unknown `AlternateContent` | Preserve unless timings is enabled | |
| 158 | | Explicit `none` | Remove the visual effect | Preserve, or write timing-only advance when timings is enabled | |
| 159 | | Timings enabled with audio | Keep the resolved enter policy | Use audio duration plus narration padding; click disabled | |
| 160 | | Timings disabled | Apply the confirmed enter policy only | Audio readiness may probe decodability; do not use duration or add/change `advTm` or `useTimings` | |
| 161 | |
| 162 | The confirmed `modules.transitions` object may include `effect_options` beside |
| 163 | an explicit canonical `effect`. Use |
| 164 | `pptx_animations.py --describe-transition <effect>` for its exact fields. |
| 165 | Old names remain accepted only when reading compatibility input; a newly |
| 166 | written plan stores the canonical effect and any implied options. |
| 167 | |
| 168 | For explicit page selection or page-specific settings, add `slides` keyed by |
| 169 | the 1-based `index` in `analysis/slide_index.json`: |
| 170 | |
| 171 | ```json |
| 172 | { |
| 173 | "modules": { |
| 174 | "transitions": { |
| 175 | "enabled": false, |
| 176 | "effect": "fade", |
| 177 | "duration": 0.5, |
| 178 | "apply_without_audio": false, |
| 179 | "slides": { |
| 180 | "2": {}, |
| 181 | "3": {"duration": 0.8}, |
| 182 | "4": { |
| 183 | "effect": "push", |
| 184 | "effect_options": {"direction": "left"} |
| 185 | }, |
| 186 | "5": {"effect": "none"}, |
| 187 | "6": {"effect": "preserve"} |
| 188 | } |
| 189 | } |
| 190 | } |
| 191 | } |
| 192 | ``` |
| 193 | |
| 194 | | Per-slide entry | Behavior | |
| 195 | |---|---| |
| 196 | | `{}` | Select the page and inherit the global effect/options/duration | |
| 197 | | Partial object | Inherit omitted global fields; a new explicit effect uses its own default options | |
| 198 | | `effect: none` | Remove the visual transition; timings remain independently owned | |
| 199 | | `effect: preserve` | Preserve the source visual transition; narration timing may still update advance | |
| 200 | |
| 201 | A `slides` entry always selects that page. Without audio, enabled global effects |
| 202 | and explicit global `none` apply deck-wide; `apply_without_audio` is ignored. |
| 203 | With audio, the flag extends the global policy from narrated to all pages. |
| 204 | Disabled non-`none` effects preserve unlisted pages. Morph uses PowerPoint |
| 205 | automatic matching; this route does not rename native objects for deterministic |
| 206 | pairs. |
| 207 | |
| 208 | **Hard rule — no silent downgrade**: a requested native effect must be written with its complete validated Effect Options. Unknown effects or inapplicable options fail; unknown source effects are preserved when the transition module is disabled. |
| 209 | |
| 210 | After confirmation, update `<project>/analysis/enhancement_plan.json`: |
| 211 | |
| 212 | ```json |
| 213 | { |
| 214 | "status": "confirmed" |
| 215 | } |
| 216 | ``` |
| 217 | |
| 218 | Also set each confirmed module's `enabled` value. Disabled modules must stay in the file with `enabled: false`, not be deleted. |
| 219 | |
| 220 | --- |
| 221 | |
| 222 | ## 6. Generate Notes From Existing Slides |
| 223 | |
| 224 | 🚧 **GATE**: Step 5 confirmed; `notes.enabled` is true; `<project>/sources/<source>.md` exists. |
| 225 | |
| 226 | Read: |
| 227 | |
| 228 | | File | Use | |
| 229 | |---|---| |
| 230 | | `<project>/sources/<source>.md` | Visible slide text, tables, extracted notes, image references | |
| 231 | | `<project>/analysis/slide_index.json` | Exact slide count and target note filenames | |
| 232 | |
| 233 | Write: |
| 234 | |
| 235 | ```text |
| 236 | <project>/notes/001.md |
| 237 | <project>/notes/002.md |
| 238 | ... |
| 239 | ``` |
| 240 | |
| 241 | **Hard rule**: Notes are spoken narration only. Do not include stage directions, implementation comments, timing labels, markdown tables, or visible-slide rewrite instructions. |
| 242 | |
| 243 | **Hard rule**: Notes must be faithful to the slide. They may explain visible content, but must not add unsupported facts. |
| 244 | |
| 245 | | Slide type | Notes length | |
| 246 | |---|---| |
| 247 | | Cover / section divider | 1-2 short sentences | |
| 248 | | Dense content page | 2-4 sentences | |
| 249 | | Chart / table page | Explain the reading path, then state the takeaway | |
| 250 | | Ending page | One concise close | |
| 251 | |
| 252 | Run coverage check: |
| 253 | |
| 254 | ```bash |
| 255 | python3 skills/ppt-master/scripts/native_enhance_pptx.py validate "<project>" --materials notes |
| 256 | ``` |
| 257 | |
| 258 | > Note: This keeps source/plan/transition/carrier checks but does not require |
| 259 | > audio. Missing/invalid notes return `2`; structural/semantic errors return |
| 260 | > `1`. Step 8 runs full validation after audio. |
| 261 | |
| 262 | --- |
| 263 | |
| 264 | ## 7. Shared Audio Configuration |
| 265 | |
| 266 | 🚧 **GATE**: Step 6 complete; `audio.enabled` is true. |
| 267 | |
| 268 | Run [`generate-audio`](./stages/generate-audio.md) Steps 1–3. That shared stage exclusively owns language selection, provider/voice catalog lookup, recommendation rules, and the one-shot confirmation. Do not repeat or fork those rules here. |
| 269 | |
| 270 | Record the confirmed config into `project.json`: |
| 271 | |
| 272 | ```json |
| 273 | { |
| 274 | "audio": { |
| 275 | "provider": "edge", |
| 276 | "voice": "zh-CN-YunjianNeural", |
| 277 | "rate": "+0%" |
| 278 | } |
| 279 | } |
| 280 | ``` |
| 281 | |
| 282 | --- |
| 283 | |
| 284 | ## 8. Run the Shared Audio Stage |
| 285 | |
| 286 | 🚧 **GATE**: Step 7 confirmed; complete non-empty notes files exist under |
| 287 | `<project>/notes/` for every slide. |
| 288 | |
| 289 | Run [`generate-audio`](./stages/generate-audio.md) Step 4 with `<project>` and the confirmed values. Stop after audio generation; do not run its Generate-PPTX-only `svg_to_pptx.py --recorded-narration` integration. This route integrates audio through Step 9 instead. |
| 290 | |
| 291 | **Naming contract**: Audio stems match note stems: `001.md` → `001.mp3`. |
| 292 | |
| 293 | Validate: |
| 294 | |
| 295 | ```bash |
| 296 | python3 skills/ppt-master/scripts/native_enhance_pptx.py validate "<project>" |
| 297 | ``` |
| 298 | |
| 299 | --- |
| 300 | |
| 301 | ## 9. Apply V1 Enhancements |
| 302 | |
| 303 | 🚧 **GATE**: Enhancement plan is confirmed; notes are ready if requested; audio is ready if requested. |
| 304 | |
| 305 | Run: |
| 306 | |
| 307 | ```bash |
| 308 | python3 skills/ppt-master/scripts/native_enhance_pptx.py apply "<project>" |
| 309 | ``` |
| 310 | |
| 311 | Optional: |
| 312 | |
| 313 | ```bash |
| 314 | python3 skills/ppt-master/scripts/native_enhance_pptx.py apply "<project>" \ |
| 315 | --transition fade \ |
| 316 | --transition-duration 0.5 \ |
| 317 | --narration-padding 0.4 \ |
| 318 | --apply-transition-without-audio \ |
| 319 | --overwrite |
| 320 | ``` |
| 321 | |
| 322 | `--apply-transition-without-audio` matters only with audio enabled: it extends |
| 323 | the global enter policy from narrated slides to all slides. Explicit slide |
| 324 | entries always opt in. Without audio, enabled transitions apply to every slide. |
| 325 | |
| 326 | `apply` reruns the same source/readiness/plan checks as `validate`. Enabling |
| 327 | audio always requires every selected file to be decodable by ffprobe; enabling |
| 328 | timings additionally consumes that duration for `advTm`. It refuses |
| 329 | partial requested material, a changed source hash/slide roster, or a source |
| 330 | that already contains a `native_enhance_audio_*` carrier. New audio/poster |
| 331 | parts use collision-free names; an existing poster is reused only when its |
| 332 | bytes match the tool marker exactly. Output must be a new `.pptx` under |
| 333 | `exports/` or an external location; apply never overwrites either source or |
| 334 | writes into project control directories. Every apply attempt invalidates the |
| 335 | previous validation receipt, and a failed preflight records its current errors |
| 336 | instead of leaving stale passed evidence. |
| 337 | |
| 338 | Patch scope: |
| 339 | |
| 340 | | Package area | Append/update | |
| 341 | |---|---| |
| 342 | | `ppt/notesSlides/` | Notes slide parts | |
| 343 | | `ppt/notesMasters/` | Notes master only when needed | |
| 344 | | `ppt/slides/_rels/slideN.xml.rels` | Relationships for notes/audio/media/poster | |
| 345 | | `ppt/media/` | Narration audio and transparent poster | |
| 346 | | `ppt/slides/slideN.xml` | Hidden autoplay audio shape and page timing | |
| 347 | | `ppt/presProps.xml` | `showPr useTimings=1` only when this run writes automatic slide advance | |
| 348 | | `[Content_Types].xml` | Required content types | |
| 349 | |
| 350 | **Hard rule**: Do not modify existing slide shapes, text bodies, images, chart data, master/layout parts, or existing non-target relationships. |
| 351 | |
| 352 | Before publishing the candidate, apply validates transitions, timing/object |
| 353 | animation structure, ZIP integrity, unique parts, internal relationships, |
| 354 | slide count, and hidden-slide state. The narrowly allowed legacy missing |
| 355 | notes-master finding may remain exactly equivalent, but the candidate must not |
| 356 | introduce any structural error. Apply then writes both audits and the |
| 357 | introduced-error delta to `<project>/validation/report.json`. |
| 358 | |
| 359 | --- |
| 360 | |
| 361 | ## 10. Validate Output |
| 362 | |
| 363 | Run read-back: |
| 364 | |
| 365 | ```bash |
| 366 | python3 skills/ppt-master/scripts/source_to_md/ppt_to_md.py \ |
| 367 | "<project>/exports/<source>_enhanced.pptx" \ |
| 368 | -o "<project>/validation/readback.md" |
| 369 | ``` |
| 370 | |
| 371 | Check: |
| 372 | |
| 373 | | Check | Expected | |
| 374 | |---|---| |
| 375 | | Slide count | Same as source | |
| 376 | | Visible content | No intentional changes | |
| 377 | | Notes | Present on intended slides | |
| 378 | | Audio media | Present under `ppt/media/` when generated | |
| 379 | | Auto-play | Narrated slides advance by audio duration | |
| 380 | | Transition | Requested effect remains exact; preserved `AlternateContent` keeps its primary and fallback branches | |
| 381 | | Timings disabled | Source `advTm` and package `useTimings` are not changed | |
| 382 | | Delivery check | No newly introduced structural errors; source baseline and font/media/hidden-slide advisories reviewed | |
| 383 | |
| 384 | ```markdown |
| 385 | ## ✅ Native PPTX Enhancement V1 Complete |
| 386 | |
| 387 | - [x] Project initialized at `<project>` |
| 388 | - [x] Source PPTX archived into `<project>/sources/` |
| 389 | - [x] Confirmed native enhancement modules applied |
| 390 | - [x] Enhanced PPTX exported to `<project>/exports/<file>.pptx` |
| 391 | - [x] Delivery postflight written to `<project>/validation/report.json` |
| 392 | - [x] Read-back validation written to `<project>/validation/readback.md` |
| 393 | ``` |
| 394 |