---
name: PPT Standard Pipeline
slug: ppt-standard-pipeline
category: Automation
description: PPT Standard Pipeline generates PowerPoint decks through a deterministic staged CLI that wraps all LLM, VLM, and text-to-image calls. It supports fast and standard modes, taking task_pack.json/info_pack.json and producing PPTX or PDF.
github: "https://github.com/OpenSenseNova/SenseNova-Skills/tree/main/skills/sn-ppt-standard"
language: JavaScript
stars: 4873
forks: 364
install: "npx degit https://github.com/OpenSenseNova/SenseNova-Skills/tree/main/skills/sn-ppt-standard ~/.claude/skills/sn-ppt-standard"
installs_to: ~/.claude/skills/sn-ppt-standard
source_path: skills/sn-ppt-standard/SKILL.md
collection_size: 25
category_size: 1523
collection_url: "https://dirskills.com/collections/OpenSenseNova/SenseNova-Skills"
added: 2026-08-16T07:01:06.514Z
last_synced: 2026-08-16T07:01:06.514Z
canonical_url: "https://dirskills.com/skills/ppt-standard-pipeline"
---

# PPT Standard Pipeline

PPT Standard Pipeline generates PowerPoint decks through a deterministic staged CLI that wraps all LLM, VLM, and text-to-image calls. It supports fast and standard modes, taking task_pack.json/info_pack.json and producing PPTX or PDF.

**Install:**

```bash
npx degit https://github.com/OpenSenseNova/SenseNova-Skills/tree/main/skills/sn-ppt-standard ~/.claude/skills/sn-ppt-standard
```

## README

# sn-ppt-standard

> **⚠️ This skill must be invoked through `/skill sn-ppt-entry`.** Never start here directly — the entry skill collects parameters, parses uploaded files, and writes `task_pack.json` + `info_pack.json` that this skill requires. If you arrived here without those files, stop and tell the user to enter via `/skill sn-ppt-entry` or "生成 PPT".

This skill is **self-contained** — no dependency on `sn-image-base` for LLM/VLM (T2I still goes through `sn-image-base`). Generation logic stays in `$SKILL_DIR/scripts/run_stage.py`; use `run_stage_with_progress.py` only as a WebUI progress wrapper. Every subcommand is deterministic: one input set → one output artifact → one-line JSON status.

## Preconditions

- `<deck_dir>/task_pack.json` exists and `ppt_mode in {"standard", "fast"}`
- `<deck_dir>/info_pack.json` exists

Any missing → stop and tell user to enter via `/skill sn-ppt-entry`.

When `ppt_mode == "fast"`: **build first, then iterate.** Make decisions autonomously — do not ask the user about colors, fonts, page count, or layout preferences. Infer reasonable defaults from the query and start building immediately. Skip optional web search and image search. Run the full pipeline including PPTX export. **Data**: use uploaded documents first; if none, use mock data labeled `[Sample Data]` and tell the user in chat which data needs replacement. **Images**: AI generation for decorative images, ECharts for charts — no questions asked.

### Post-generation (fast mode only)

After the PPTX is generated, do NOT just say "done, any feedback?" Instead, provide a **structured set of refinement suggestions** based on the actual content you generated. This helps the user understand what changed between your fast draft and what a polished standard-mode version would look like.

**1. Quick wins (3-5 specific suggestions):** Point to concrete things the user could improve with one-line instructions. Tie each suggestion to a specific slide or element. Examples:
- "Slide 3: replace the mock revenue numbers with your actual Q4 data"
- "Slide 5: swap the generic team photo placeholder with your real team picture"
- "Cover slide: try a darker background for more impact — I can switch it to deep navy"
- "Slide 7: the bar chart is using sample data — give me your real numbers and I'll regenerate it"

**2. Standard-mode comparison (2-3 gaps):** Explain what would have been different in standard mode, so the user knows what they're trading off. Examples:
- "In standard mode, I would have searched the web for competitor benchmarks to include on slide 4 — right now those numbers are estimates labeled [Sample Data]"
- "Standard mode includes a three-sample deck preview checkpoint where you would compare three concatenated deck images and a preview URL before I built all 12 slides"
- "With image search enabled, slides 2 and 8 could use real product photos instead of the AI-generated decorative images"

**3. Suggested next actions (3-4 paths):** Offer concrete directions the user can take:
- "Replace mock data: tell me which slides need real numbers and I'll update them"
- "Adjust style: I can change the color palette, fonts, or layout density across all slides at once"
- "Add a section: if you need a financial projections or risk analysis section, I can insert new slides"
- "Promote to standard: if this draft is close to what you need, I can re-run it in standard mode with full research and image search for a delivery-ready version"

When the user responds with a change request, apply it immediately and re-present the updated suggestions.

When `ppt_mode == "standard"`: **plan thoroughly first, then build.** Do thorough research and image search. Generate three visual deck samples for the user to choose from before creating the outline. Each sample includes one concatenated deck image and one HTML preview deck; also provide a single preview URL that shows all three decks. Produce the selected final format from `task_pack.params.output_format` (`"pptx"` or `"pdf"`). **Data**: documents first, web search second, ask user as last resort. Never fabricate numbers.

## 🚫 Hard rules (the main agent MUST NOT)

1. **Do NOT write Python scripts that loop over pages or slots** in a single exec. Use the batch subcommands, or per-item execs in the agent's own loop of tool_calls.
2. **Do NOT fake image generation.** If `gen-image` and its image-search fallback both fail, don't write a placeholder PNG — the HTML stage will redesign around the missing slot.
3. **Do NOT construct LLM prompts yourself.** `run_stage.py` is the only place that builds payloads.
4. **Do NOT add `timing` / logging / retry layers.** The skill is intentionally thin.
5. **Do NOT go silent between execs.** Echo a one-line Chinese progress message after each exec before issuing the next.
6. **Do NOT use python-pptx, pptxgenjs, libreoffice, or any alternative converter.** `run_stage.py export` is the ONLY way to produce the final PPTX/PDF file. Never write Python scripts that import `pptx`, Node scripts that import `pptxgenjs`, or ad hoc PDF conversion scripts. If export fails or is skipped, the HTML pages are the final deliverable.
7. **Do NOT re-run a failing stage more than twice.** If the same `run_stage.py` subcommand fails with the same error on two consecutive attempts, treat it as a permanent failure. Echo the failure, record the skipped stage, and move on. Partial output is better than a stuck retry loop.
8. **Language integrity.** All user-visible text MUST match the user's query language. If the query is Chinese, every title, bullet, caption, label, and footnote MUST be in Chinese — even if source documents are in English. A single English title in a Chinese deck is a regression.
9. **Image integration.** All images used in slides MUST be saved under `<deck_dir>/images/` and referenced via relative paths from HTML (e.g., `../images/photo.jpg`). Never leave remote URLs in final HTML. Never use colored rectangles as image placeholders. If a searched/downloaded image exists on disk, it MUST appear in the corresponding page HTML.
10. **Do NOT fabricate data.** All numbers, statistics, and factual claims MUST come from the user's uploaded documents or from web search results. If no data source is available, use qualitative descriptions instead of invented numbers.
11. **Wait for `ask_user` responses.** When you ask the user a question (e.g., to clarify parameters, choose a style sample, or choose output format), do NOT proceed until the user replies. Never continue with assumed/default values without explicit confirmation.
12. **Multi-round edits: regenerate, do not patch.** When the user requests changes to an existing deck, re-run the affected pipeline stages from scratch. Do NOT edit files in-place with sed/perl/Python string manipulation — the artifact schemas are machine-generated and easy to corrupt.
13. **Validate paths before writing.** All output goes under `<deck_dir>/` — the absolute path written in `task_pack.json`. Before writing any file, verify the parent directory exists. Never write to `/workspace/`, `/tmp/`, `~/`, `./`, or any path not rooted at `<deck_dir>`. If a command's `--output` or `--save-path` argument doesn't start with `<deck_dir>/`, it's wrong.

## Visual quality standards

- The style_spec MUST NOT default to safe/bland choices (e.g., white background + blue accents + black text). Actively prefer distinctive, themed styles.
- Each page HTML MUST have visual density: use color blocks, decorative elements, background gradients, and layout variety. A page that looks like a Word document (white background, title + bullet list, no decoration) is a FAILURE.
- Avoid low-contrast text. All body text must have at least 4.5:1 contrast ratio against its background.

## Image sourcing

The user's `image_source` preference (from `task_pack.params`) determines how images are obtained:

**`web-search`**: Search the web for real images via the `sn-search-image` skill. Each result includes the image URL, source page, title, and domain — easy to trace and attribute. Save downloaded images under `<deck_dir>/images/` and reference them with relative paths in HTML. Web search is ideal for real product photos, landmark shots, or anything AI can't draw accurately.

**`ai-gen`**: Use AI image generation via `gen-image` / `sn-image-base`. Asset priority for standard image slots: **searched image first**, **generated image second**, **authored SVG/CSS illustration last**. Do not mention the image-search provider name in prompts, progress, visible slide text, or user-facing summaries.

**`none`**: No raster images — use text, tables, charts, and CSS visuals only.

### Infographic slots (U1-generated diagrams)

For flowcharts, process diagrams, organizational charts, and complex data visualizations, the pipeline creates `infographic` slots (slot_kind=`infographic`). These are **always AI-generated via U1** — web search is not used for infographics because they visualize content-specific data.

When `gen-image` processes an infographic slot, U1 generates a clean, professionally styled diagram. If U1 generation fails, fall back to ECharts, CSS, or text tables.

### Image search as fallback

When `image_source` is `ai-gen` and generation fails for a slot, use web search as a backup (if `SERPER_API_KEY` is set).

### No junk — hard constraint

Never use: grey boxes, 1×1 transparent PNGs, "image pending" labels, broken-image icons, fake thumbnails, empty reserved frames, or colored rectangles as image placeholders. If no good image turns up for a slot — from any source — rework the page completely. Different layout, different approach. The user must never see that awkward hole where a picture should be.

## External research

- Always use the web search skills (`sn-search-web`) for facts, research, and knowledge grounding.

## Pipeline

Use `python3` on Linux/macOS, `python` on Windows (where `python3` is often absent).
All commands below use `python3` — substitute `python` on Windows.

```bash
W="python3 $SKILL_DIR/scripts/run_stage_with_progress.py"
D="<deck_dir>"

$W preflight     --deck-dir $D              # validate + stage assets, publish progress

# sn-ppt-entry should already have started the generation progress WebUI after
# task_pack.json / info_pack.json were written. Run this only as an idempotent
# reuse/fallback check for resumed or direct-invocation sessions.
python3 $SKILL_DIR/scripts/launch_workbench.py --deck-dir $D --source-session-id "${HERMES_SESSION_KEY:-}" --agent-managed 1 --agent-provider "${WORKBENCH_AGENT_PROVIDER:-hermes}"

$W style-samples --deck-dir $D             # standard only -> style_samples.json + deck preview images/URL
$W style         --deck-dir $D --sample A   # standard -> style_spec.json from selected sample
$W style         --deck-dir $D              # fast -> style_spec.json (one autonomous style)
$W outline       --deck-dir $D              # -> outline.json
$W asset-plan    --deck-dir $D              # -> asset_plan.json

# Per-item forms — one progress line per item. PREFERRED for visibility:
# each exec returns quickly with status, keeping the user informed.
$W gen-image     --deck-dir $D --page N --slot SLOT_ID
$W page-html     --deck-dir $D --page N

# Batch (concurrent) equivalents. Use when individual execs would exceed
# time budget. Batch commands block until ALL items complete.
# Concurrency for batch-page-html: 1 (≤4 pages), 2 (5-8 pages), 4 (9+ pages).
# Concurrency for batch-gen-image: default 4.
$W batch-gen-image  --deck-dir $D [--concurrency 4]
$W batch-page-html  --deck-dir $D --concurrency N [--start-page S --end-page E]

# For large decks, split into ranges to stay within the 300s execution limit:
$W batch-page-html  --deck-dir $D --concurrency 4 --start-page 1 --end-page 8
$W batch-page-html  --deck-dir $D --concurrency 4 --start-page 9 --end-page 16

$W export        --deck-dir $D              # -> <deck_id>.pptx or <deck_id>.pdf from task_pack.params.output_format
```

### Three-sample deck preview checkpoint (standard mode only)

When `ppt_mode == "standard"`: after preflight, run `style-samples`, then **pause for user selection** before proceeding to `style` and `outline`:

1. Make sure the workbench has already been launched after preflight. It will show the style chooser automatically when `style_samples.json` appears.
2. Run `$W style-samples --deck-dir $D`. This writes:
   - `style_samples.json`
   - `style_samples/style_samples.html` and `style_samples/index.html` (same all-samples preview)
   - `style_samples/sample_A_deck.svg`, `sample_B_deck.svg`, `sample_C_deck.svg` (one concatenated deck image per style)
   - `style_samples/sample_A_deck.html`, `sample_B_deck.html`, `sample_C_deck.html` (one HTML preview deck per style)
3. Parse the command JSON. It includes `preview_url`, `preview_images`, and `preview_decks`.
4. Send or attach all three `preview_images` to the user before asking them to choose. Each image is a vertically concatenated mini deck, not a single style card.
5. Provide the `preview_url` or the workbench URL so the user can compare all three decks. If the client cannot attach local images, provide each image URL/path plus the `preview_url`.
6. Present samples (`A`, `B`, `C`) with their label, design style, tone, primary color, and rationale.
7. Ask the user to choose `A`, `B`, or `C`, and wait. If the user selects in the WebUI, read `$D/.workbench/style-selection.json` and use its `sampleId`.
8. Run `$W style --deck-dir $D --sample <A|B|C>` to promote the selected sample into `style_spec.json`.
9. Only proceed to outline after `style_spec.json` exists.

Progress echo after samples: `[1] style_samples.json ✓ 3 个 deck 预览图 + URL，等待选择`.
Progress echo after selection: `[1] style_spec.json ✓ selected sample <A|B|C>`.

When `ppt_mode == "fast"`: **skip this checkpoint.** Proceed directly through all stages without pausing.

`batch-gen-image` serializes writes to `asset_plan.json` under a process-local lock so concurrent workers don't clobber each other.

**Split decks into small ranges.** Hermes defaults to a 180s foreground timeout. The SN API can take 60-90s per page for HTML generation, so conservative batching is essential:

- Concurrency 2: 3 pages max per batch (3×90s/2 ≈ 135s)
- Concurrency 4: 6 pages max per batch (6×90s/4 ≈ 135s)
- For 10 pages: `--start-page 1 --end-page 3`, `--start-page 4 --end-page 6`, `--start-page 7 --end-page 9`, then page 10 solo.
- If even 3-page batches time out, the SN API backend is slow — skip directly to manual fallback rather than splitting further.
- Batch commands block until ALL items complete; a single slow page stalls the whole batch.

### Generation progress WebUI launch

`sn-ppt-entry` starts the generation progress WebUI immediately after the first JSON files exist. In this skill, run the same helper only as an idempotent reuse/fallback check after `preflight` and before `style-samples`, `style`, `outline`, or HTML generation:

```bash
python3 $SKILL_DIR/scripts/launch_workbench.py --deck-dir $D --source-session-id "${HERMES_SESSION_KEY:-}" --agent-managed 1 --agent-provider "${WORKBENCH_AGENT_PROVIDER:-hermes}"
```

On native Windows Hermes installs where `python3` is unavailable, run the same helper with `python`.

**⚠️ MSYS path conversion pitfall (Windows + git-bash/MSYS):** When running under MSYS/git-bash on Windows, the shell auto-converts arguments that look like POSIX paths (e.g., `/progress`) to Windows-style paths. This breaks `--progress-route` and any other argument starting with `/`. **Fix:** prefix the command with `MSYS_NO_PATHCONV=1`:

```bash
MSYS_NO_PATHCONV=1 python $SKILL_DIR/scripts/launch_workbench.py --deck-dir $D --progress-route /progress --agent-managed 1 --host 0.0.0.0
MSYS_NO_PATHCONV=1 python $SKILL_DIR/scripts/progress_event.py --deck-dir $D --stage entry --status ok ...
```

This applies to BOTH `launch_workbench.py` and `progress_event.py` when slash-prefixed arguments are used.

Before starting the server, the helper checks NodeJS. If it returns `{"status":"skipped","reason":"nodejs_missing",...}`, ask the user whether to install NodeJS/dependencies. If they decline, say generation will continue without the WebUI and proceed. If they agree, first use any approved dependency-install skill/tool exposed by the active environment; otherwise use platform install means only after explicit dangerous-operation confirmation.

When launched from an agent, keep `--agent-managed 1`. Managed mode hides BYOK/model configuration in the PPT workbench and lets the Node server relay bottom-chat turns to a deck-scoped companion session. For Hermes, keep passing the active generation session only as `--source-session-id` so the companion can read the original generation prompt and related context; do not expose WebUI, Gateway, REST, ACP commands, or API keys to the browser.

Interactive provider configuration is structured-only:

- Hermes: `--agent-provider hermes --agent-transport webui|gateway` plus `--webui-base-url` or `--gateway-base-url`.
- OpenClaw: `--agent-provider openclaw --agent-transport rest --agent-base-url <url> --agent-api-key <key>`.
- Codex: `--agent-provider codex --agent-transport acp --acp-command <codex-acp command>`.
- Claude Code: `--agent-provider claude-code --agent-transport acp --acp-command <claude ACP command>`.
- WorkBuddy: `--agent-provider workbuddy` only marks provider identity. Tell the user that WorkBuddy has no supported API or ACP interface for use as an interactive workbench bridge, so bottom-chat modification turns cannot be sent back to WorkBuddy.

Never parse provider CLI/TUI output for the WebUI companion bridge.

If the helper returns `{"status":"ok", ...}`, echo the returned `generation_url` to the user. The returned `generation_url` is the progress page at `/progress`; the editor remains available through `editor_url` at `/editor`.

`生成进度工作台已启动：<url>`

If the helper returns `{"status":"skipped", ...}`, echo a short skip reason and continue generating HTML. WebUI startup must never block PPT generation.

The helper locates the local `sensenova-ppt-workbench` launcher from `SENSENOVA_PPT_WORKBENCH_CLI`, `PPT_WORKBENCH_CLI`, or common `~/Repository/ppt-editor/src/ppt-editor` paths, with the legacy root layout kept as a fallback. It builds the workbench once if `dist/index.html` is missing, starts a lightweight server, and reuses an existing healthy server for the same deck.

**Bridge mode** — the workbench auto-detects its bridge type:
- **Writable companion bridge**: When a supported WebUI, Gateway/REST, or ACP bridge is configured, the workbench creates/reuses one companion session for the deck and writes bottom-chat turns there.
- **Source-only mode**: When no writable bridge is configured, the workbench still shows all pages, tools, and export, but bottom chat cannot write to an agent companion session. This does NOT block PPT preview or export.

Remote access behavior:
- Prefer Hermes/canvas/port-forward URLs from `WORKBENCH_PUBLIC_URL`, `HERMES_WORKBENCH_PUBLIC_URL`, `HERMES_CANVAS_URL`, `HERMES_PORT_FORWARD_URL`, `CANVAS_URL`, `PORT_FORWARD_URL`, `TUNNEL_URL`, Codespaces, or Gitpod.
- If a forwarded/canvas URL exists, the helper binds the WebUI to localhost and reports the forwarded generation URL.
- If no forwarded/canvas URL exists, native hosts bind to localhost by default.
- Docker/WSL bind to `0.0.0.0` by default and report a LAN URL based on the machine's non-loopback IPv4 address.
- If the reported URL is not reachable from the user's device, ask for a reachable forward/canvas URL or explicit host/IP and rerun the helper with `--public-url <url>` or `--host <host>`.

### How `page-html` works (two LLM calls per page)

1. **Rewrite** — `prompts/page_html_rewrite.md` converts the structured outline + style_spec + inherited content into a natural-language user prompt (content, layout, palette, inherited material).
2. **Generate** — `prompts/page_html.md` is a hard-contract 
