返回 ppt-master
customize-animations.md
根目录 / skills / ppt-master / workflows / stages / customize-animations.md
1 ---
2 description: Optional post-processing stage for per-slide and per-object animation overrides.
3 ---
4
5 # Customize Animations Stage
6
7 > Optional Generate-PPTX post-processing stage for per-slide or per-object
8 > animation control. Run when `<project_path>/animations.json` already exists,
9 > when the user explicitly asks to customize slide-specific motion, object
10 > order, effects, timing, or reveals, or when the effective Custom Animations
11 > outcome in `design_spec.md §I` is enabled. Deck-wide transitions,
12 > auto-advance, and deck-wide per-element settings without page-specific motion
13 > or an existing sidecar use [`animations.md`](../../references/animations.md)
14 > directly and do not activate this stage. In Quick Generate, the current agent
15 > may activate either path from the request/deck in active context without a
16 > Design Spec or user interaction.
17
18 ## When to Run
19
20 | Condition | Action |
21 |---|---|
22 | Effective Custom Animations outcome in `design_spec.md §I` is enabled | Run this stage after the final SVG quality gate and any enabled speaker-note pass, before Generate Step 7; use §IX suggestions as advice |
23 | User asks for per-slide or per-object animation, reveal order, timing, or effect changes | Run this stage |
24 | `<project_path>/animations.json` already exists | Run this stage to resolve preserve/adjust/replace/suppress intent before export |
25 | §IX contains `Motion suggestion`, but no trigger above is active | Do not run; retain the suggestion as Strategist advice and keep normal export defaults |
26 | No motion request, enabled outcome, or existing sidecar; user only wants the default deck | Do not run; normal export keeps page transitions and no element builds |
27 | No existing sidecar; user only wants deck-wide page transitions, auto-advance, or one per-element object animation policy | Do not run; apply [`animations.md`](../../references/animations.md) with exporter flags such as `-a auto` or `-a emphasis_spin` |
28 | Only a page-transition sound is requested, with no object-specific motion or existing sidecar | Do not run the full stage solely for sound; resolve a sparse transition sidecar through [`animations.md`](../../references/animations.md) §2.2 at export time |
29 | An object-animation sound is requested | Run this stage because the cue must bind to a resolved animation row and real object target |
30 | `svg_output/*.svg` is missing | Complete the main Executor phase first |
31
32 **Decision precedence**: latest explicit instruction → final Stage-2 policy →
33 workflow default `false`; provenance stays in Design Spec §I, never the
34 lock. Final Stage-2 `false` blocks creation, not an existing sidecar. Existing
35 sidecars enter this stage; explicit disables follow the table without deletion.
36
37 ---
38
39 ## 1. Resolve Intent and Read Semantic Context
40
41 **Context read**: before editing `animations.json`, read every semantic planning file below that exists.
42
43 | File | Use |
44 |---|---|
45 | `<project_path>/design_spec.md` | Understand each slide's content intent, narrative role, and visual emphasis |
46 | `<project_path>/spec_lock.md` | Confirm page rhythm, layout role, chart/template constraints, and execution contract |
47 | `<project_path>/notes/total.md` or `<project_path>/notes/*.md` | Use speaker flow to tune reveal order, delays, and emphasis |
48
49 **Existing sidecar intent gate**:
50
51 | User intent | Action |
52 |---|---|
53 | Explicit Custom Animations disable | Preserve and validate the sidecar; return `-a none` |
54 | Explicit all-motion disable | Preserve and bypass the sidecar; return `--no-animations` |
55 | Explicit regeneration / rewrite / replacement | Rebuild the semantic grouping plan and replace `animations.json`; the previous choreography is not a constraint |
56 | Explicit adjustment / tuning / repair | Validate first, preserve the existing choreography where its semantic units remain valid, and migrate affected group references after any required regrouping |
57 | Stage activated with an existing sidecar and new §IX suggestions but no user replacement request | Validate first; preserve valid existing choreography and adjust only the affected semantic units |
58 | Existing sidecar with no new motion instruction | Validate and preserve it unchanged; if invalid, repair the owning sidecar/group reference before export |
59 | Ambiguous generation request | Default Generate asks whether to regenerate or modify; Quick Generate decides from the request, visible SVG, and existing sidecar, then continues |
60
61 Unless explicit all-motion disable bypasses it, validate an existing sidecar
62 before deciding to preserve, modify, or suppress object motion:
63
64 ```bash
65 python3 skills/ppt-master/scripts/animation_config.py validate <project_path>
66 ```
67
68 **Hard rule**: semantic files determine both animation intent and animation
69 unit boundaries. The current `svg_output/*.svg` supplies visible content and
70 implementation structure, but its existing `<g>` hierarchy is not accepted as
71 the animation plan merely because it already exists.
72
73 **Optional-context fallback**: these semantic files inform this supporting stage but are not its gate artifacts. If any are absent, state what is missing and proceed with every remaining file plus visible SVG content. If all three context inputs are absent, use only explicit user instructions, visible SVG content, and the resolution rules in [`animations.md`](../../references/animations.md); do not infer detailed choreography beyond what the page itself expresses.
74
75 **Decision ownership — understand, then design**: A §IX `Motion suggestion`
76 expresses the Strategist's communication job and semantic relationship; it
77 neither activates this stage nor locks implementation. Once active, understand
78 that intent, then develop the motion brief from the final SVG's semantic units,
79 visible states, composition, and speaker flow. Do not mechanically map it to
80 groups, effects, order, or timing. Executor may preserve, adapt, simplify,
81 decline, or choose `none`; an unchanged realization is valid and requires no
82 novelty. Explicit user motion requirements bind. Never change page
83 content merely to justify animation.
84
85 **Hard rule — existing visible-layer boundary**: This stage may regroup existing content only under §2 visual equivalence; it MUST NOT create or modify a crop, comparison layer, scrim, lens, hotspot, annotation, or other visible image state to satisfy motion intent. When a required state is missing and ordinary Slide-local authoring can supply it, return to Generate Step 6, rerun the final SVG gate and regenerate notes only when speaker notes are enabled, then resume here. If a structural boundary prevents that repair, simplify a non-binding suggestion to legal existing units, a page transition, or `none`; an explicit requirement follows failure recovery instead of changing structure.
86
87 **No-op is complete**: Evaluate suggestions before regrouping SVG content. If
88 no `animations.json` exists, every page should retain the normal `fade`
89 transition and no object builds, and no explicit user requirement remains
90 unmet, change no SVG, create no sidecar, and return to Generate Step 7. Never
91 author motion merely to expose a capability.
92
93 ---
94
95 ## 2. Rebuild Semantic Motion Units When Needed, Then List IDs
96
97 **Mandatory when object-targeted motion is in scope — content-first grouping
98 audit**: inspect each affected slide's visible content against its communication
99 job and speaker flow before treating any top-level `<g>` as an animation
100 anchor. The affected set is the page named by an adopted suggestion or explicit
101 object-motion request, plus both endpoints of each deterministic Morph pair.
102 Untouched pages need no animation audit. Existing groups are implementation
103 evidence only. Keep a current group unchanged only after confirming that it
104 already represents exactly one audience-facing motion unit or one continuing
105 Morph object. A page-transition-only plan without explicit Morph pairs skips
106 regrouping and group listing.
107
108 | Content condition | Required grouping action |
109 |---|---|
110 | One current group contains several independently narrated rows, cards, steps, claims, or stages | Split it into descriptive direct-root sibling groups, one per motion unit |
111 | One motion unit is scattered across groups or root primitives | Merge or wrap its background, icon, label, value, and supporting text into one direct-root group |
112 | A connector or arrow explains entry into a node or stage | Keep it with the relationship or target unit that makes the connection intelligible |
113 | A hero visual, overview graphic, takeaway, or warning has its own communication role | Give it its own semantic group |
114 | The same semantic object continues across adjacent Morph pages | Isolate each endpoint as one direct-root group and keep both endpoints as compatible object kinds |
115 | Several atoms express one inseparable idea | Keep them together; do not animate the atoms separately |
116 | Page chrome, structural layers, or static framing | Preserve their structure and exclude them from ordinary animation targets |
117
118 **Hard rule — visual equivalence**: regrouping changes object boundaries only.
119 Preserve all visible content, paint order, coordinates, transforms, inherited
120 paint, opacity, clipping, filters, references, and native metadata. Keep
121 rendering-bearing implementation wrappers nested inside the new semantic group
122 when flattening or distributing their attributes could change appearance.
123
124 **Hard rule — structural boundary**: never split or merge across
125 `data-pptx-layer`, `data-pptx-placeholder`, native chart/table carrier, native
126 preset, or imported logical-object boundaries. Structural/static objects remain
127 non-animatable. Ordinary Slide-local content groups follow
128 [`shared-standards-core.md`](../../references/shared-standards-core.md) §4.3:
129 every visible direct-root group has a descriptive unique `id` and positive
130 root-coordinate `data-pptx-bounds`; nested implementation groups carry no
131 bounds.
132
133 **Forbidden — group-list-first choreography**:
134
135 - Choosing effects or order from the pre-existing `list-groups` output before the content-first audit
136 - Keeping a coarse wrapper only because it already has an `id`
137 - Splitting one semantic idea into individual shapes or text lines to increase animation count
138 - Merging unrelated ideas to reduce animation count
139 - Adding animation-specific `data-*` attributes to SVG
140
141 There is no target group count. Granularity follows the page's actual claims,
142 comparisons, sequence, causality, and narration beats.
143
144 After any regrouping, rerun the final SVG quality gate because `svg_output/`
145 changed. Use the owning route's checker form; Quick Generate must add its
146 lockless profile flag:
147
148 ```bash
149 python3 skills/ppt-master/scripts/svg_quality_checker.py <project_path> --stage final --json
150 # Quick Generate: insert --quick-generate before --stage.
151 ```
152
153 Then list the **post-regroup** anchors:
154
155 ```bash
156 python3 skills/ppt-master/scripts/animation_config.py list-groups <project_path>
157 ```
158
159 Output is one line per slide: `<slide_basename>: id1, id2, id3`. Default chrome
160 groups (`bg` / `*-header` / `*-footer` / `*-decor` / `nav` / `watermark` /
161 `logo` / `pagenumber`) are excluded. This post-regroup list is the source of
162 truth when planning §3 and editing §4; never invent a slide or group key.
163
164 An explicit sidecar entry may override only the marker-free legacy id-name
165 heuristic. A group carrying `data-pptx-layer` or an explicit static
166 role/placeholder marker can never animate, even when it is named explicitly.
167
168 If `animations.json` does not exist and a starting file is useful, scaffold
169 only after semantic regrouping:
170
171 ```bash
172 python3 skills/ppt-master/scripts/animation_config.py scaffold <project_path>
173 ```
174
175 The scaffold is neutral: its default object effect is `none`, and listed groups
176 may remain empty `{}` placeholders until adopted. Creating it does not select
177 generic entrance animation. Do not read the full scaffold unless it is needed
178 as an editing starting point.
179
180 ---
181
182 ## 3. Plan Slide and Object Motion
183
184 **Mandatory**: plan the requested motion layers for each affected slide before
185 editing `animations.json`. A local object-animation request does not require a
186 deck-wide transition review.
187
188 | Layer | Config path | Use |
189 |---|---|---|
190 | Page transition | `defaults.transition` or `slides.<slide>.transition` | Control how one slide enters from the previous slide |
191 | Deterministic Morph pair | `slides.<destination>.morph` | Bind one real source group to one real destination group when semantic identity continues across adjacent slides |
192 | Page animation defaults | `defaults.animation` or `slides.<slide>.animation` | Control the default object-animation behavior for animated groups on a slide |
193 | Object lifecycle | `slides.<slide>.groups.<group_id>` | Assign one legacy effect row or an ordered `effects[]` sequence to a real SVG motion unit |
194
195 **Per-affected-page motion brief**: classify the communication job—including
196 none—and each unit's lifecycle. Choose only the required transition, effect,
197 order, timing, and one dominant Start rhythm; mix modes or add emphasis and
198 exit only for a distinct job with a restrained, fitting effect. Read
199 `design_spec.md`, `spec_lock.md`, speaker notes, and SVG group ids for role,
200 rhythm, order, and target validity.
201
202 **Mandatory — select from meaning, not catalog coverage**: run the
203 page-relationship and lifecycle selection playbooks in
204 [`animations.md`](../../references/animations.md) §3 and §4 before choosing any
205 specific effect. Their candidates are recall aids, not coverage targets; this
206 stage binds the selected duties to real targets.
207
208 **Title motion decision**: when a title participates, classify its lifecycle,
209 then choose immediate, delayed, synchronized, post-hero, or narration-cued
210 timing from slide intent. Use the sidecar override for a marker-free legacy
211 chrome-like id; repair an incorrect explicit structural/static marker before
212 animating it.
213
214 **Default — inherit unaffected motion layers (may override when the page's
215 communication job requires it)**: a custom object-animation pass may leave the
216 page transition and every untouched page on exporter or sidecar defaults. Add a
217 slide-specific `transition` only when the affected page needs one; never add
218 variation for coverage.
219
220 **Timing guidance**: use shorter motion for dense/repeated scan content and
221 longer motion for conceptual pivots, hero diagrams, section boundaries, and
222 final takeaways. Uniform timing is valid when it fits the requested style.
223
224 **Reference — not a constraint: motion judgment.** Decide the communication
225 job, lifecycle, tone, audience order, and whether direction carries meaning
226 before using geometry. If motion adds no clarity or intended feeling, classify
227 the unit `static`; use `none`, `entrance_appear`, or `entrance_fade` only when
228 that result matches the lifecycle. Layout direction alone does not require
229 special motion; variation follows a real content/tone change, never a quota.
230
231 ### 3.1 Supported Page Transitions
232
233 Use one of the 48 canonical native effects from the complete shared registry in
234 [`animations.md`](../../references/animations.md) §3. It covers all current
235 PowerPoint Subtle, Exciting, and Dynamic Content gallery effects. The eight old
236 names are readable only as compatibility inputs; do not write them in new
237 plans or sidecars. They normalize to a canonical effect plus native
238 `effect_options` before writing. `none` removes the visual page transition
239 while allowing timed advance to remain.
240
241 **Transition fields**:
242
243 | Field | Behavior |
244 |---|---|
245 | `effect` | One supported page transition effect; `none` removes only the visual effect |
246 | `effect_options` | Optional object containing only the selected native effect's PowerPoint Effect Options; requires an explicit `effect` |
247 | `duration` | Finite transition duration in seconds; must be greater than zero |
248 | `auto_advance` | Optional finite non-negative seconds before automatic slide advance; click remains enabled, and this field is valid with `effect: none` |
249 | `sound` | Optional project-relative `.wav` cue; select and sync it only after the transition solution is resolved |
250
251 Run
252 `python3 skills/ppt-master/scripts/pptx_animations.py --describe-transition <effect>`
253 before authoring Effect Options. Never infer that one effect accepts another
254 effect's direction, shape, pattern, or boolean fields.
255
256 For a cross-slide object continuation that must not depend on PowerPoint's
257 automatic matching, put one explicit `morph` block on the destination slide.
258 Its `from` slide must be the immediately preceding exported SVG; each stable
259 pair key binds one source direct-root group id to one destination direct-root
260 group id. The exporter supplies PowerPoint's `!!` prefix. Use Morph by object;
261 word/character Morph does not accept this object-pair contract.
262
263 ### 3.2 Supported In-Slide Animations
264
265 Use the 203 canonical PowerPoint-native keys: 53 `entrance_*`, 33
266 `emphasis_*`, 64 `path_*`, and 53 `exit_*`. Run
267 `python3 skills/ppt-master/scripts/pptx_animations.py --list` for the exact
268 categorized names. Each key preserves PowerPoint's complete authored behavior
269 tree. Media-only commands remain in the audio/video workflows.
270
271 | Choice | Behavior |
272 |---|---|
273 | `entrance_*` / `emphasis_*` / `path_*` / `exit_*` | Select one explicit canonical PowerPoint object effect |
274 | `auto` | Generic `enter` only: map content roles to canonical entrances; image-like ids use a richer canonical pool |
275 | `mixed` | Generic `enter` only: cycle 16 canonical entrance presets by group order |
276 | `random` | Generic `enter` only: select deterministically from the same canonical entrance pool |
277 | `none` | Exclude the object or slide from in-slide animation |
278
279 The 29 old short names remain readable only as compatibility inputs; do not use
280 them in new plans or sidecars. All Fly direction names normalize to
281 `entrance_fly`, all Wipe direction names normalize to `entrance_wipe`, and the
282 other old names normalize to their matching `entrance_*` preset. `cut`
283 normalizes to `entrance_appear`. Compatibility Fly/Wipe aliases preserve their
284 direction as `effect_options.direction`; legacy `wheel` preserves its historical
285 four-spoke amount.
286
287 `auto`, `mixed`, and `random` never choose emphasis, motion-path, or exit
288 effects implicitly. Use them only after classifying a unit as a generic
289 `enter`; select an explicit canonical key for every adopted `emphasize`,
290 `move`, or `exit` duty.
291
292 **Hard rule — explicit semantic choreography**: When an adopted plan depends
293 on a specific lifecycle, relationship, or order, target its real groups with
294 explicit canonical effects and order; do not delegate those material decisions
295 to `auto`, `mixed`, or `random`. Those modes remain valid only when generic
296 entrance treatment is sufficient.
297
298 **Start modes**:
299
300 | Trigger | Behavior |
301 |---|---|
302 | `after-previous` | Default click-free cascade |
303 | `with-previous` | One coordinated beat together |
304 | `on-click` | Controlled semantic reveal |
305
306 ### 3.3 Optional Sound Pass
307
308 Run this pass only after the visual transition, object lifecycle, effect,
309 order, and timing decisions above are complete. Sound selection is
310 post-processing state: do not recover it from or write it back to
311 `design_spec.md` / `spec_lock.md`, and do not treat it as a pre-SVG resource.
312
313 | Need | Action |
314 |---|---|
315 | No resolved cue needs sound | Omit every `sound` field; do not create `<project_path>/sounds/` |
316 | A bundled cue fits one resolved transition or animation row | Read the complete [`sound-vocabulary.md`](../../templates/sounds/sound-vocabulary.md), choose from the resolved auditory job, then sync only the selected namespaced id(s) into the project |
317 | The project already contains user-provided audio | Use its project-relative path when its format is valid; no library sync is required |
318
319 ```bash
320 # Optional exact filtering after reviewing the complete vocabulary
321 python3 skills/ppt-master/scripts/sound_sync.py list --query <term>
322 python3 skills/ppt-master/scripts/sound_sync.py \
323 <project_path> <namespace>/<sound_id> [<namespace>/<sound_id> ...]
324 ```
325
326 Use the corresponding `sounds/<namespace>/<file>.wav` path in
327 `transition.sound`, `animation.sound`, or the selected group/effect row. Never
328 reference `skills/ppt-master/templates/sounds/` from `animations.json`. The
329 global library is a selection source, not an exporter fallback.
330
331 This pass owns only native PPTX cue selection and configuration. When direct
332 narrated MP4 delivery is active, leave gain, limiting, and video mixing to
333 [`generate-audio`](./generate-audio.md) after the final narrated export; do not
334 write those post-production values into `animations.json`.
335
336 ---
337
338 ## 4. Edit `animations.json`
339
340 **Hard rule — sparse overrides reference real targets**: write only affected
341 slides and only fields that differ from exporter or sidecar defaults. An
342 unlisted SVG inherits the resolved deck-wide settings; a listed slide may
343 contain only `transition`, `animation`, `groups`, or `morph` fields that it
344 actually overrides. `defaults` is optional and belongs only to intentional
345 deck-wide settings. Group-level overrides remain opt-in. Chrome groups stay out
346 (the exporter pins them to `none` by default). Name a legacy chrome-like id only
347 when the user explicitly wants that content animated and the SVG has no
348 explicit structural layer, role, or placeholder marker.
349
350 **Forbidden**:
351
352 - Referencing a slide that does not exist in `svg_output/`
353 - Referencing a missing, ambiguous, or structural group
354 - Enumerating every content group in a slide just to restate the slide-level default effect
355 - Listing a group with `data-pptx-layer` or an explicit static role/placeholder marker
356 - Listing a legacy chrome-like id without an explicit, reviewed intent to override the name heuristic
357
358 | Field | Behavior |
359 |---|---|
360 | `transition.effect` | Slide-specific page transition effect |
361 | `transition.effect_options` | Effect-specific native PowerPoint options; requires an explicit slide-specific `transition.effect` |
362 | `transition.duration` | Slide-specific page transition duration |
363 | `transition.sound` | Optional project-relative `.wav` cue copied during §3.3; valid with `effect: none`; set a slide override to `null` to clear an inherited default sound |
364 | `morph.from` | Immediately preceding SVG stem for an explicit deterministic Morph transition |
365 | `morph.pairs.<key>.from` / `.to` | Unique source/destination direct-root group ids that receive the shared PowerPoint name `!!<key>` |
366 | `animation.effect` | Slide-specific default object animation effect |
367 | `animation.duration` | Slide-specific default object schedule duration |
368 | `animation.stagger` | Slide-specific delay between object animation rows |
369 | `animation.trigger` | Slide-specific start mode |
370 | `groups.<id>.effects` | Non-empty ordered array for a multi-duty lifecycle; every row explicitly names `effect`, and `effects` cannot coexist with legacy single-effect fields in the same group block |
371 | `groups.<id>.effect` | Backward-compatible single-row form: one canonical native effect, `auto`, `mixed`, `random`, or `none`; old names are read-only compatibility inputs |
372 | `effects[].trigger` / legacy `trigger` | Row-specific Start mode; omitted values inherit `animation.trigger` |
373 | `order` | Page-wide order for ordinary rows; ties retain SVG group order and then `effects[]` index. `trigger_shape` rows keep relative order in separate interactive sequences; SVG layer order never changes |
374 | `delay` | Row-specific seconds added to the resolved Start or shape trigger |
375 | `duration` | Per-row schedule duration in seconds; scalable native behavior trees keep their internal timing ratios, while `entrance_appear` and instantaneous native presets retain their PowerPoint-authored duration and use this value for subsequent `after-previous` spacing |
376 | `effect_options` | Effect-specific PowerPoint parameters; requires an explicit canonical `effect` in the same legacy block or `effects[]` row |
377 | `trigger_shape` | Different top-level group id for native **On Click of**; row-only and not inherited. It implies `on-click`; an explicit row `trigger` may accompany it only when also `on-click` |
378 | `repeat_count` / `repeat_duration` | Repeat count or total repeat span; mutually exclusive |
379 | `auto_reverse`, `rewind` | Reverse each cycle and/or restore the pre-animation state |
380 | `accelerate`, `decelerate`, `bounce_end` | `0..1` timing ratios; acceleration plus deceleration must not exceed `1`; bounce requires an interpolated effect and cannot combine with deceleration |
381 | `restart` | `always`, `when-not-active`, or `never` |
382 | `after_effect` | `none`, `dim` with `color`, `hide`, or `hide-on-next-click` |
383 | `sound` | Object-animation cue. Existing low-level inputs accept project-relative or absolute `.m4a`, `.mp3`, or `.wav`; bundled selections use the synced project-relative `.wav` path from §3.3 |
384
385 **Hard rule — one group representation**: A populated
386 `groups.<id>` object uses either the backward-compatible single-effect fields
387 or `effects[]`, never both. `effects[]` must contain at least one object, and
388 every row explicitly names `effect`. An untouched scaffold `{}` is a neutral
389 placeholder. Omitted row duration, Start, timing/completion controls, and sound
390 inherit the resolved slide animation values exactly as the legacy form does.
391
392 `effect_options` may contain `direction`, `amount`, `color`, `font_name`,
393 `relative`, or `size`, but validation permits only fields supported by the
394 selected effect. Before writing a parameterized effect, run
395 `python3 skills/ppt-master/scripts/pptx_animations.py --describe
396 <canonical_effect>` and use the returned values exactly. `duration` owns
397 PowerPoint Speed; `accelerate`/`decelerate` own smooth start/end, so do not
398 invent duplicate fields. Change Font's `font_name` is one concrete
399 target-installed PowerPoint face, never a CSS font stack.
400
401 Use the coherent multi-category `effects[]` example in
402 [`animations.md`](../../references/animations.md) §2. Its static frame stays
403 unlisted while one real unit runs enter → move → emphasize → exit. Keep the
404 legacy object for one-row overrides; never convert old sidecars mechanically.
405
406 Use the complete two-slide deterministic Morph example in
407 [`animations.md`](../../references/animations.md) §2.1; do not copy the source
408 group into the destination slide's `groups` block merely to establish identity.
409
410 **Forbidden — SVG pollution**: do not add `data-*` animation attributes to SVG files. Animation customization belongs in `animations.json`.
411
412 ---
413
414 ## 5. Validate and Return to Generate Export
415
416 When `animations.json` was newly created or changed after the §1 validation,
417 run:
418
419 ```bash
420 python3 skills/ppt-master/scripts/animation_config.py validate <project_path>
421 ```
422
423 After validation succeeds, return to the owning export path:
424
425 - Default Generate → [`generate-pptx.md`](../generate-pptx.md) Step 7.1, which
426 owns note splitting, `finalize_svg.py`, native export, and the published
427 postflight receipt.
428 - Quick Generate → [`quick-generate.md`](../profiles/quick-generate.md) §4,
429 which skips finalization and exports with `--quick-generate`.
430
431 Both exporters read `<project_path>/animations.json` automatically. If §2
432 changed `svg_output/`, complete the owning route's required final SVG quality
433 rerun before returning. Do not finalize or export independently from this
434 stage.
435
436 **Validation**: The later native export must reflect the per-slide and
437 per-object overrides. `--animation none` still disables all per-element
438 animation and overrides `animations.json`. Unknown animation
439 effects/modes/triggers; unsupported effect options; incompatible, boolean,
440 non-finite, or out-of-range timing parameters; non-positive durations; negative
441 delay/stagger; invalid order; missing slides/groups; and structural-layer
442 targets fail validation. Transition validation remains strict. None of these
443 failures substitutes a fallback effect or silently drops a requested target.
444 Deterministic Morph also rejects non-adjacent source slides, missing or
445 ambiguous direct-root groups, conflicting or undeclared shared keys, non-object
446 Morph, and any target that does not remain one compatible Slide-local object
447 after structure processing.
448
449 **Validation boundary**: a passing sidecar, timing-tree read-back, and sound
450 relationship check proves the PPTX configuration only. It does not prove the
451 PowerPoint-exported MP4 audio track contains those cues.
452
453 Generate Step 7 export reads back row order, including repeated rows targeting
454 one shape, trigger, target, resolved effect, duration, offset, timing placement,
455 IDs, and shape references. Narration
456 preserves these rows. Direct-PPTX routes fingerprint and preserve source object
457 animation; they never author it. See
458 [`pptx-animations.md`](../../scripts/docs/pptx-animations.md).
459
460 ### 5.1 Optional Video Motion Handoff
461
462 When a downstream video renderer will enhance the deck, have Generate Step 7.3
463 append `--conversion-trace`. After that final export succeeds, derive the motion
464 plan from its resolved trace:
465
466 ```bash
467 python3 skills/ppt-master/scripts/video_motion_plan.py \
468 <project_path>/validation/<output_stem>.trace.json \
469 -o <project_path>/validation/video_motion_plan.json \
470 --style adaptive \
471 --force
472 ```
473
474 For narrated output, use the final `--recorded-narration` trace. When resolved
475 sound cues exist and the native-export mix branch is selected, that same final
476 trace and the final narrated PPTX feed `video_sound_mix.py`; never infer cue
477 timing from the raw sidecar or filenames. An explicit slideshow capture already
478 records PowerPoint's native cue playback and does not use the trace for sound
479 mixing. The video plan locks identity, effect, direction, order, bounds, and
480 timing; it may refine renderer parameters but cannot replace the source effect.
481 See
482 [`video-motion-plan.md`](../../scripts/docs/video-motion-plan.md).
483
484 ---
485
486 ## ✅ Customize Animations Complete
487
488 - [x] Applicable semantic context and motion intent were resolved
489 - [x] Adopted object targets use real post-regroup SVG ids when object motion is in scope
490 - [x] Sparse `animations.json` overrides are valid when present; a no-op path creates none
491 - [x] Any regrouped SVG passed the final quality gate
492 - [x] Control returned to Generate Step 7 for preview, export, read-back, and package validation
493 - [x] Any requested video plan waits for the final resolved conversion trace
494
494 lines MARKDOWN