Install
$ agentstack add skill-sanpingli-skills-narrative-pptx-composer ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ✓ Network access No
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Narrative PPTX Composer
Purpose
Turn content into a finished .pptx that tells a compelling, audience-aware story. Content first, design second.
Global Rules
These apply across all steps. Do not repeat-check per step.
Priority order: Content → Narrative → Design; higher pillar wins. See [design-principles.md](references/design-principles.md).
Workflow invariants:
- All nine steps run in order for every input modality. No skip-paths, no merged-step shortcuts.
- Completion gate: the workflow is incomplete until
s09-session-retrospective.jsonexists. Step 7'soutput.pptxis a draft — it is not reviewed, not delivered, and not announced to the user. Stopping after Step 7 is a workflow violation. - Large decks: when a step's total output would exceed what fits in a single coherent pass, split by acts per [references/batching-strategy.md](references/batching-strategy.md). Each step self-assesses whether to batch.
- Agenda page numbers use the em-dash placeholder
"—"(never"TBD") in Steps 4/5/6; patched in Step 7c. - Cross-slide consistency: numbers match
s04a-terminology-registry.json; onlycanonicalforms; low-confidence data points (confidence) |
| $PROFILER_SKILL/scripts/render_samples.py | Renders .pptx slides to JPEG. Mandatory for Step 8a. | | $IMAGE_SKILL/scripts/generate_images.py | Batch image generation from JSON request. See $IMAGE_SKILL/SKILL.md. |
Skill-internal scripts live in $COMPOSER_SKILL/scripts/. Each step section below invokes the relevant ones with full commands.
Workflow
Step 1: Input Registry
Step 2: Communication Brief
Step 3: Narrative Blueprint
Step 4: Content Draft & Form Specification
Step 5: Slide Visual Design
Step 6: Content–Zone Fitting & Speaker Notes
Step 7: Build PPTX ← output.pptx is DRAFT, not deliverable
Step 8: QA, Fix & Deliver ← first deliverable copy to outputs/
Step 9: Session Retrospective ← workflow complete only after this step
Step 1 — Input Registry
> Full procedure: [references/step1-input-registry.md](references/step1-input-registry.md)
Session initialization (1a, before any other command):
export SKILLS_ROOT=".claude/skills"
export COMPOSER_SKILL="$SKILLS_ROOT/narrative-pptx-composer"
export PROFILER_SKILL="$SKILLS_ROOT/pptx-profiler"
export IMAGE_SKILL="$SKILLS_ROOT/image-generator"
If unset, validators and rendering fail silently.
Four sub-tasks: (1a) session directory; (1b) classification → s01b-query-intent.json; (1c) content extraction → s01c-content-digest.json; (1d) design registration → s01d-design-config.json. 1c and 1d co-execute in one pass. Optional: 1c-pptx for .pptx docs, 1c-image for image inputs (three-track VLM).
Guard rules:
- Registry only, not analysis. No audience/purpose/formality inference (→ Step 2), no
imageryDemand(→ Step 3a), no palette/typography/style (→ Step 5b). Only inferlanguageandinputMode. inputModeset in 1b, locked. One ofgenerate/beautify/reproduce/expand.s01b.inferences[]whitelisted tolanguage+inputModeonly — validator hard-fails others.s01dresolution: user-explicit → reference-image (VLM) → deferred. Non-supplied design fields →null+deferred-step5b. Onlydimensions(16:9) andmonoFont(JetBrains Mono) getsystem-default.sourceProvenance(origin tag) mandatory per leaf:user-explicit/reference-image/system-default/deferred-step5b. Null↔deferred coupling enforced.- Media: extract images/diagrams into
mediaAssets; log conflicts inmergedSections.conflicts[]— never block.
Outputs: s01b-query-intent.json, s01c-content-digest.json, s01d-design-config.json; optionally s01c-image-style-extraction.json.
python $COMPOSER_SKILL/scripts/s01_validate_inputs.py "$SESSION"
Step 2 — Communication Brief
> Full procedure: [references/step2-comm-brief.md](references/step2-comm-brief.md)
Pure LLM reasoning — no design knowledge. Always runs (mandatory for every modality). Sparse signals → thin brief with inferences + confidence.
Guard rules:
- Consume
s01b.explicitSignalsverbatim. Step 2 owns all audience/purpose inference. - Single-pass:
presentationPurpose(∈ inform/persuade/report/propose/inspire) +purposeStatement;audience;communicationObjectives(think/feel/do);keyMessages(1–5);constraints(language, formalityLevel, optional timeMinutes). - Out of scope:
slideCountConstraint(→ Step 3c),imageryDemand(→ Step 3a). audience.decisionPowerrequired when purpose ∈ {persuade, propose, report}.- Brief-only mode: infer all unsupported fields; record in
inferenceswithconfidence. Never block to ask.
Outputs: s02-communication-brief.json
python $COMPOSER_SKILL/scripts/s02_validate_brief.py "$SESSION"
Step 3 — Narrative Blueprint
> Full procedure: [references/step3-narrative-blueprint.md](references/step3-narrative-blueprint.md) | Patterns: [references/storytelling-patterns.md](references/storytelling-patterns.md)
Pure LLM reasoning — no design knowledge. Three sub-phases: (3a) narrative architecture, (3b) structural scaffolding, (3c) per-slide blueprint.
Guard rules — 3a:
- Five sub-tasks: core argument, pattern & acts, act transitions, opening hook & closing takeaway, information hierarchy.
- Pattern paths: reuse / compose / nest / design new. Record
origin. Justify from content+audience, not the pattern table. - Core argument: falsifiable claim (not vague topic). Derive from
s02.keyMessages[rank=1]; log any departure ininferences[]. - Every
cutitem needsreason.
Guard rules — 3b:
- Decide structural slides (executive summary, agenda, dividers, recap, appendix). Executive summary ↔ opening hook mutually exclusive. Appendix excluded from
totalSlides. - Section dividers: include only when (a) each act has enough body slides to justify a structural marker (minimum depth ≥ 2 — a single-slide act makes its divider feel hollow), AND (b) the total divider count stays well below ~25 % of body slides (avoids over-scaffolding). Never asymmetric — all acts or none.
Guard rules — 3c:
- Per-slide fields:
slideId,headlineMessage,narrativeRole(story function),slideType,narrativeIntent(delivery mode),transitionIn/Out,informationDensity,contentSource,sourceRef. - Slide count is bottom-up.
slideCountConstraintclamped here (single decision point). Exactly onecover+ oneclosing. Step 5 may not insert/remove slides. - Pacing rule: every 6–8 body slides ≥ 1 with
informationDensity: "minimal". - Every body slide MUST have
headlineMessage. Structural slides may leave null. - Adjacent
transitionOut[N]/transitionIn[N+1]must be logically coherent. If incoherent: revise N+1'stransitionInto align. - Media: assign
mediaAttachmentsfroms01c.mediaAssets; each on ≤ 1 slide. - Illustration intent: single decision point for the illustration roster. Run minimum imagery check. Step 5 may not back-fill or demote. Field shape: [step3-narrative-blueprint.md § illustrationIntent](references/step3-narrative-blueprint.md).
- Document mode:
supportingPointsneedsourceRef; numbers matchpreGlossary(initial term list from content extraction).
Outputs: s03-presentation-blueprint.json (embeds architecture: core argument, pattern, acts, hooks, hierarchy, scaffold, contentDomain, imageryDemand (deck-level imagery budget), imageryDemandRationale).
python $COMPOSER_SKILL/scripts/s03_validate_blueprint.py "$SESSION"
Step 4 — Content Draft & Form Specification
> Full procedure: [references/step4-content-draft.md](references/step4-content-draft.md)
Write per-slide content (4b) and choose contentForm per slide (4c). Form is a content decision, not visual design.
Guard rules:
- 4a — Terminology registry. Seed from
s01c.preGlossary(initial term list) before 4b; finalize after. EverydataPointsentry:verificationTier(verified/common-knowledge/unverified) +confidence(0.0–1.0). Low-confidence precise numbers also getqualitativeForm. - Source rules:
document→ no fabrication;generated/hybrid→ numbers from registry. - Headlines faithfully render blueprint's
headlineMessage. - 4c —
contentForm({type, ...counts}). No spatial structure →text-narrative/bullet-list. Do not pre-name a layout. blocks[]for multi-zone types (card-grid,comparison-matrix,timeline,step-flow,stat-callout,architecture-layers,before-after,diagram-callouts,icon-list): one entry per zone withrole,headline,body. Single-zone → empty.- Content metrics auto-derived by validator. Do not hand-fill.
- 4c-illust: refine
illustrationIntent→illustrationSpecwithsource: "to-generate",subject,perImageSubject,compositionNote,contentInteraction. - 4d — Speaker-note cues only. Brief transition cue per slide (tone from
formalityLevel+audience). Full talk track → Step 6c. Required: non-emptyspeakerNotesfor every slide.
Outputs: s04-content-draft.json, s04a-terminology-registry.json.
python $COMPOSER_SKILL/scripts/s04_validate_content.py "$SESSION"
Step 5 — Slide Visual Design
> Full procedure: [references/step5-visual-design.md](references/step5-visual-design.md) | Layout: [references/layout-principles.md](references/layout-principles.md) | Tone: [references/visual-tone-mapping.md](references/visual-tone-mapping.md)
Read before this step: [design-principles.md](references/design-principles.md), [design-guardrails.md](references/design-guardrails.md).
Execution flow:
5a Fill deferred design fields (palette, fonts, contrast)
↓
5b Derive visual tone from content strategy:
- resolve register (authoritative/analytical/conversational/inspirational/instructional-rich)
- set color temperature, whitespace rhythm, imagery guidance per act
- write designThesis (one-sentence design concept + 2–4 mechanisms)
- plan compositionPalette (layout vocabulary) and titleChoreography (title treatments)
↓
5c Freeze s05b-style-policy.json — read-only from here on
↓
5d Design each slide's layoutSpec (three phases per slide):
Phase 1 — Concept: read context + review prior slides' moves →
commit aestheticMove, palette family, and focal idea
BEFORE drawing zones (→ designRationale)
Phase 2 — Execute: choose grid → size zones → add decorations → set background
Phase 3 — Verify: check geometry + confirm layout delivers the Phase 1 concept
↓
5f Generate images (if needed):
- collect all source:"generated" zones → image request file
- run generate_images.py (backgrounds: 1 variant; illustrations: 3 variants)
- VLM selects best illustration variant (best-of-3)
- patch file paths back into the plan
Guard rules:
designThesis(mandatory, frozen at 5c). Single sentence: what the design is about + 2–4 visiblemechanisms. Verified in Step 8, compared in Step 9.aestheticSignals(style preferences):designAmbition(style intensity) overrides default (default:"expressive";restrainedonly for explicit minimalism);moodKeywordsbias 5d;avoidKeywordsare hard exclusions;diversityPreference: "high"tightens quotas.- 5d — Layout from
contentForm. Design from first principles per layout-principles.md. Preserve content's spatial structure. Generic layout for structured content → justify indesignRationale.aesthetic. - Zone types:
text,shape,chart,image,icon,formula. Unknown type → validator hard-fails. Formula zones:notation: "mathtext",source: "authored",fallbackblock required. - Formula-zone mandate: when content contains math equations or symbolic expressions, create
type: "formula"zones — never embed formulas as Unicode text intype: "text"zones. Short inline symbols (σ, θ) are acceptable in prose; standalone equations must be formula zones. - Coordinate units: inches by default (bare numbers).
"%"for percent. No mixing. - Design minimums (4 quotas: layout variety, hero cadence, color-area, typographic punch): [visual-tone-design-floor.md](references/visual-tone-design-floor.md). Auto-relax with
quotaWaiver; never block. - Minimum imagery requirements: apply row for resolved
imageryDemand. Step 3 owns the illustration roster; Step 5 may not add or remove illustration slots. Waiver needs reason ≥ 20 chars. - Cover–closing consistency (recommended): cover ↔ closing share ≥ 1 decorative element in common. [step5d-slide-layout.md § Bookend](references/step5d-slide-layout.md).
- Deck-wide decorative motifs (
motifPalette, recommended): 2–5 shape/pattern variations; slides classified as motif-bearing / decoration-free / non-motif. [step5d-slide-layout.md § motifPalette](references/step5d-slide-layout.md). - Illustration zones: match
illustrationSpecforimageCount,placement. Step 5 decidesimageShapebased on layout and available space. Every generated zone MUST havefallback.
Outputs: s05-slide-visual-design.json ([schema](schemas/s05-slide-visual-design.schema.json)), s05b-style-policy.json. If 5f: s05f-image-requests.json, images/, s05f-image_generation_output.json, s05f-image-selection.json.
python $COMPOSER_SKILL/scripts/s05_validate_plan.py "$SESSION"
Step 6 — Content–Zone Fitting & Speaker Notes
> Full procedure: [references/step6-content-fitting.md](references/step6-content-fitting.md)
The only step holding both content draft and real zone geometry — owns fit end-to-end (no escape hatch to Step 4).
Guard rules:
- 6a — Map content to zones by zone
rolenames (not placeholders).blocks[]present → map by matchingrole(no splitting).blocks[]absent on multi-zone → heuristic split (informational log, not error). - Title compression (within Step 6 only): Stage 1 syntactic (drop modifiers), then Stage 2 semantic (core claim stays; dropped framing →
speakerNotes). Must always be complete statement. Validator warns at Full procedure: [references/step7-build-pptx.md](references/step7-build-pptx.md) | Template: [references/build-script-template.md](references/build-script-template.md)
Write and execute s07-build.py using python-pptx. Import helpers from $COMPOSER_SKILL/scripts/s07_slide_helpers.py.
Guard rules:
- 7a — Per-
taskIdbuilder functions. Onebuild_per slide (promote to sharedbuild_only when ≥ 2 slides share identical pattern). Disallowed: single genericbuild_slide(tid)branching internally. Helpers:add_textbox,add_card,add_accent_bar,add_rounded_rect,add_outline_capsule,add_outline_circle,add_image_safe,set_slide_bg,set_slide_bg_image,add_image_with_overlay,resolve_image_path,add_formula,render_formulas. - Images: insert ONLY via
add_image_safe()/add_image_with_overlay()/set_slide_bg_image()(aspect-ratio preserving). Never useslide.shapes.add_picture()directly. - Formulas: call
render_formulas()once at top ofmain()(renders to/formulas/-.png). Builders calladd_formula()with cached path. No$…$informulaSource; no SVG viaadd_picture(). - Illustration zones in every builder: every builder function whose slide has an
illustrationzone in the plan MUST resolve and insert it viaresolve_image_path(plan_zone, slot)+add_image_safe(). Omitting the illustration call silently drops the image — invisible until Step 8 visual QA. Audit: grep shared builders for illustration handling before dispatch.- 7c —patch_agenda_pages()inline at end ofs07-build.pybeforeprs.save(). Not a separate fil
…
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: sanpingli
- Source: sanpingli/skills
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.