zcbot/skills/ppt/references/executor-base.md

42 KiB
Raw Blame History

Executor Common Guidelines

Narrative skeleton and visual aesthetic come from this deck's locked files under modes/ and visual-styles/. Technical constraints are in shared-standards.md.


1. Template Adherence Rules

1.0 Pre-generation Batch Read

Hard rule: Before the first SVG page, batch-read every template SVG this deck will reference. Read once up front, never re-read during generation.

Source list Read path
Chosen template's design_spec.md (read frontmatter to detect replication_mode) templates/design_spec.md
Every distinct <basename> in spec_lock.md page_layouts templates/<basename>.svg
Every distinct chart name in spec_lock.md page_charts templates/charts/<chart_name>.svg
Chart types in design_spec.md §VII not covered above templates/charts/<chart_name>.svg

Default — read each template once; re-read only on the mid-deck exception below:

  • Layout SVG already loaded in this batch
  • Chart SVG already loaded in this batch

spec_lock.md is the only file re-read per page (§2.1).

Exception: user mid-deck adds pages or swaps templates introducing a basename/chart absent from the original batch → read the new file once, continue.

Note: batched prefix reads stay in the cached prompt prefix; per-page spec_lock.md re-reads append below and benefit from that cache. Scattered on-demand reads of layout/chart SVGs would invalidate downstream cache and sit in the compression-vulnerable mid-context region.

Resolve the per-page template SVG via spec_lock.md page_layouts (authoritative). The legacy page-type table below is a last-resort fallback for legacy decks where page_layouts is missing.

Resolution order (per page):

  1. Mirror-mode template (template's design_spec.md frontmatter has replication_mode: mirror) → see §1.1 below. The page is consumed as a visual reference, not as a placeholder shell.
  2. spec_lock.md page_layouts has P<NN>: <basename> for this page → inherit the structure of templates/<basename>.svg (already in context from §1.0).
  3. page_layouts exists but no entry for this page → free design, no template inheritance.
  4. page_layouts section absent (legacy deck) and templates/ directory exists → fall back to the page-type table below, matching by SVG filename keyword (cover/chapter/content/ending/toc). Read the matched file at first use if §1.0 batch did not cover it.
  5. No template at all → free design.

Note: page_layouts disambiguates the multiple content variants modern templates ship (e.g., graduation_defense has 8); the legacy table cannot.

Templates supply structure, not skin (non-mirror): a chart or layout template's gradients, drop-shadows, palette, and font sizes are placeholder. Inherit its geometry, label / legend placement, and series-encoding logic; re-skin every fill / stroke to the deck's visual_style + spec_lock.colors — flat styles strip the gradients and shadows, gradient / glass styles repaint their own. Forbidden — shipping a template's default <linearGradient> / cardShadow / Tailwind fills unchanged. Mirror templates are the exception: §1.1 preserves their visuals verbatim.

Font size is skin, not geometry (non-mirror). A chart / layout template's hardcoded font-size values (often 1116px, sized for the template's own dense placeholder text) are NOT inherited — classify each text into its spec_lock.md role and use that role's locked size, exactly as you re-skin color. Structural roles (page title / body / subtitle / annotation / footnote) hold their one deck-wide size on every page — the template's placeholder px never overrides it; same-role text drifting page to page is what makes a deck look unprofessional.

Typography execution order (mandatory):

  1. Build a per-page text inventory from design_spec.md §IX + the current notes/<NN>_*.md.
  2. Classify each text item before drawing. Structural roles (title, subtitle / lead, body, annotation, footnote / page_number) must map to their declared spec_lock.typography slot. A one-off feature element (a single hero number, an isolated emphasis label) may take an in-ramp intermediate value — the ramp is anchored on body, not a closed menu — but a feature size that recurs must be promoted to a declared slot. The failure mode this guards against is structural text silently inheriting the template's compact px, not legitimate feature sizing.
  3. Copy the role's locked px value into font-size verbatim. Do this before placing the text; never start from a template font-size and then "adjust".
  4. Layout from those locked sizes: compute line-height, wrapped line count, child y / dy, card padding, card height, column gaps, and available image/chart area from the chosen px values.
  5. Only after this reflow may you inspect fit. If fit fails, move / resize containers or simplify local geometry first; do not reduce the role size merely because the inherited template slot was smaller.

Geometry adapts to the type, never the reverse: when the locked size is larger than the template's placeholder text, widen / heighten the card, open spacing, and recompute child y / dy to make room — do not shrink the font to fit the inherited container. A font-size change is a layout change: revise line-height and every downstream vertical coordinate that depends on it. For wrapped text, allocate at least the wrapped line count × line-height plus top / bottom padding; fixed y stacks copied from a smaller template are invalid once the locked role size is applied. The Executor renders the page it was given; page count and per-page density are the Strategist's call, fixed at confirmation — do not re-paginate, split the page, or drop authored content to cope with size here. Only when a single block still cannot fit after the geometry is fully reflowed may you shrink that block as a bounded last resort — and only body text is ever shrunk this way. Title, subtitle, annotation / caption, footnote and page number are locked once set and never adjusted to fit — their values hold across the whole deck. Step the overflowing body block's font-size down by 2px at a time, and only if it still overflows step it down again, up to a cumulative floor of 4px below the locked body size (e.g. 24 → no smaller than 20). This is a local, single-block reduction — the deck-wide locked body size is unchanged on every other block and page. (The Executor works in unitless px throughout — spec_lock and SVG carry no pt.) If the block still overflows at the floor, surface a warning: rather than silently restructure the page. (Mirror templates are the exception: §1.1 preserves their sizes verbatim — there the source deck's typography is the spec.)

1.1 Mirror-mode templates — reference-style consumption

When the project's chosen template is a mirror template (design_spec.md frontmatter declares replication_mode: mirror), Executor switches to a reference-style consumption path that bypasses placeholder substitution:

  1. Per-page reference selection — Strategist selects one mirror page per project page via spec_lock.md page_layouts (e.g., P04: 015_content). The basename is the mirror filename without extension; Strategist made this choice by reading design_spec.md §V Page Roster descriptions, not by guessing.
  2. Copy, don't fill — open the referenced mirror SVG (already in context from §1.0). Copy it as the starting point for the project page, then edit text elements in place to express the project's content for P<NN>. Preserve every non-text element verbatim: backgrounds, decorative shapes, sprite-cropped images, charts, icon usage, color values, font families, geometry, sprite <svg viewBox> wrappers, and which image each <image> points at.
  3. What you may edit — the visible text content of <text> / <tspan> elements that express slide-specific content (title, body, captions, KPI labels, dates, page numbers). Replace the source deck's example text with the project's text for this page from design_spec.md §IX and notes/<NN>_*.md.
  4. What you must not touch — element positions, sizes, fonts, colors, fills, strokes, gradients, which image each <image> points at, <g> grouping, sprite-sheet <svg viewBox> wrappers, decorative <rect> / <path> / <circle> / <polygon> shapes, <use data-icon="..."> markers, embedded chart data structures. Mirror's value is preserving the source deck's visual identity — any geometric / decorative drift defeats the purpose. The href path is not the image: normalizing a bare href="cover_bg.png" to href="../images/<name>" (when Step 3 relocated the asset to images/) points at the same image and changes nothing visual — that is an allowed path fix, not a fidelity edit. Leaving the bare href as-is is also fine; the exporter and live preview resolve bare hrefs against images/ either way.
  5. Content fit — the mirror page was chosen by Strategist because its layout matches the content slot. If the project's content for P<NN> legitimately needs more / fewer items than the mirror page provides (e.g. mirror shows 3 KPI cards, project has 4 metrics), keep the mirror page's visual rhythm and either drop one metric to fit or split across two pages — do not restructure the mirror page's grid. If neither works, surface a warning: P<NN> content does not fit mirror reference <basename>; suggest different reference page and proceed with the closest-fit edit.
  6. No {{}} substitution — mirror SVGs do not contain placeholder markers. Do not search for {{TITLE}} / {{CONTENT_AREA}} etc.; do not invent placeholders. The whole mirror contract is "verbatim source + in-place text edit".
  7. Output filename — follow the standard project SVG naming convention (<NN>_<page_name>.svg where <NN> matches the project page index, not the mirror source index). The mirror filename is the reference, not the output.

Detecting mirror mode: read the chosen template's design_spec.md frontmatter once during §1.0 batch read. If replication_mode: mirror, every page that hits page_layouts follows §1.1 above; pages without a page_layouts entry still fall through to free design (resolution rule 3 above).

Mirror + chart pages: chart structures inside a mirror SVG are already drawn (axis, series, labels). Treat them as visual references — replace the data labels and series text content to match the project's chart spec, but do not redraw the chart from a templates/charts/<name>.svg baseline. A mirror template's page_charts entries are normally absent for this reason.

Legacy fallback table (used only when page_layouts is absent):

Page Type Corresponding Template Adherence Rules
Cover 01_cover.svg Inherit background, decorative elements, layout structure; replace placeholder content
Chapter 02_chapter.svg Inherit numbering style, title position, decorative elements
Content 03_content.svg Inherit header/footer styles; content area may be freely laid out
Ending 04_ending.svg Inherit background, thank-you message position, contact info layout
TOC 02_toc.svg Optional: Inherit TOC title, list styles

Page-Template Mapping Declaration (Required Output)

Before generating each page, output which template is used:

📝 **Template mapping**: `templates/03a_content_image_text.svg` (or "None (free design)")
🎯 **Adherence rules / layout strategy**: [specific description]
  • Content pages: template defines only header/footer; content area is free
  • No template: generate entirely per the Design Spec

2. Design Parameter Confirmation (Mandatory Step)

Before the first SVG page, output a confirmation listing: canvas dimensions, body font size, color scheme (primary/secondary/accent HEX), font plan. Prevents spec/execution drift.

2.1 Per-page spec_lock re-read (Mandatory)

Long decks drift off the declared palette/icons mid-deck due to context compression. spec_lock.md is the canonical execution reference — re-read it per page to bypass model memory.

Hard rule: Before generating each SVG page, read_file <project_path>/spec_lock.md. Use only values from this file, not from memory. If context was auto-compacted, also read_file <project_path>/design_spec.md for the current page's §IX brief.

Per-block expression: render each design_spec.md §IX Content block in its written texture — a full-sentence block as wrapped prose, a fragment/label block as bullets/keywords. Never split a full-sentence block into a bullet list — splitting loses the information that the block was continuous reasoning, not a set of parallel points; not because a bullet lays out easier, and not because an inherited template slot is shaped as a list. If a block carries no clear texture, infer the mode from its wording and the page layout.

  • Prose render recipe: one <text> per paragraph; wrap lines with sibling <tspan> that reset x to the block's left edge and advance dy by the font size × a line-height factor. Default — line-height by density (may override per content fit): ~1.41.5× for dense / small-body blocks (CLReq comfortable minimum), 1.62.0× for large-type, sparse, or breathing blocks. Fit about width ÷ font-size CJK glyphs per line (Latin fits roughly twice that); the last line runs short. Use the body ramp size, not a new one.
  • Template precedence: when an inherited template slot is a bullet list but the §IX block is prose, the prose wins — widen or reflow the container to hold the paragraph, or drop that card; do not pour the sentence back into the list slot.
  • Mode precedence: the locked mode shapes voice / register, not §IX's authored titles or page order. When a §IX title is a user-authored topic label, keep it — do not upgrade it to an assertion just because the mode (e.g. pyramid) favors them; mode title-tendencies apply only to AI-drafted titles.

Note: block-level phrasing, applied within the page's page_rhythm density (below), not against it.

If spec_lock.md is missing: emit warning: spec_lock.md missing — generating without execution lock once, then proceed using design_spec.md values. Expected only for legacy projects; new projects MUST have it (see strategist.md §6 step 4).

Forbidden — values outside the lock:

  • Colors (fill / stroke / stop-color) MUST come from colors
  • Icons MUST come from icons.inventory; library MUST equal icons.library
  • Font family from typography: use role override (title_family / body_family / emphasis_family / code_family) if declared, else fall back to font_family
  • Font sizes follow a ramp anchored on typography.body, not a closed menu. Structural roles — page title, body, subtitle, annotation / caption, footnote / page number — render at one consistent size deck-wide, taken from their spec_lock slot; never re-pick a structural role's size page by page or carry a template's placeholder px. This locks the role, not every glyph: a page may still carry deliberate typographic hierarchy — a lead-in sentence, an inline emphasis figure, a pull-quote, a kicker, a hero number — but each of those is its own role / feature element with its own size, applied consistently deck-wide (declare a recurring one as its own spec_lock slot). In-band intermediate sizes are for exactly these feature elements. What is banned is the same role drifting size to fit a container or by page whim — that scatter is what reads as unprofessional. Sizes outside every band require extending the lock first.
  • The page's core message is primary — render it ≥ body. The one-idea / key-claim / key-takeaway line a page is built around is its most important text; map it to the locked lead or subtitle slot (≥ body), never to a sub-body size. Demoting it below body while data callouts or labels sit larger inverts the hierarchy — the failure this prevents. If no lead / subtitle slot is locked for a recurring core-message line, surface it (per below) instead of improvising a smaller one. A footnote / page number / source credit uses the locked footnote (or annotation) slot — never an invented sub-annotation size; and the body-shrink last resort (§1.0) bottoms out at body 4px, a hard floor never crossed.
  • Write the locked px verbatim; at most 2 decimals. font-size MUST be the exact px from spec_lock.typography — if body is 24, write 24; never substitute a "rounder" or PowerPoint-familiar number (20 / 18 / 36). The system is px-only — there is no pt to convert, and a remembered pt-style value written as px renders the whole deck the wrong size. Prefer whole numbers (sizes are clean even px); keep a decimal only for a slot that genuinely carries one in spec_lock. Never emit long tails like 20.8026: the exporter rounds the final size to 1 decimal pt, so extra px precision is wasted noise.
  • Images MUST reference files listed under images; no invented filenames
  • Formula PNGs are images with Acquire Via: formula / Status: Rendered; place them only from the listed file path and never recreate the formula as text.

If a page needs a value not in spec_lock.md, surface it — do not silently invent one.

Per-page layout rhythm — page_rhythm section:

Before drawing each page, look up its entry in page_rhythm (key format P<NN> matching the page index in §IX of design_spec.md) and apply the corresponding layout discipline:

Tag Layout discipline
anchor Structural page (cover / chapter / TOC / ending). With a template, follow the matching template verbatim. In free design (no template), realize the page's §IX intent — for the cover deliver its Cover impact and for a closing page its Closing impact (the committed hook / takeaway + composition), never a default centered title + subtitle or a generic "Thank you" sign-off.
dense Information-heavy. Card grids, multi-column layouts, KPI dashboards, tables, and charts are all permitted. This is the baseline behavior.
breathing Low-density impact page. Avoid multi-card grid layouts — do not organize content as multiple parallel rounded containers (3-card row, 4-card KPI grid, 2×2 matrix rendered as cards). Use naked text blocks, dividers, whitespace, or full-bleed imagery as the content structure. Single rounded visual elements (hero image corners, callouts, tags, one emphasis block) are fine — the rule is about grid structure, not about the rx attribute. Proportions follow information weight (not a preset ratio). Typical forms: hero quote, single large number with one-line interpretation, full-bleed image with floating caption, section transition.

Without rhythm variation, every page defaults to card grids (the "AI-generated" look). page_rhythm is the only narrative lever that survives context compression.

Missing page_rhythm section → emit warning: spec_lock.md missing page_rhythm — defaulting all pages to dense once, fall back to dense for all pages.

Tag not found for current page → emit warning: spec_lock.md page_rhythm tag not found for P<NN> — falling back to dense once per deck (aggregate; do not repeat per page), fall back to dense. Do not invent a tag.

Per-page template lookup — page_layouts section:

Before drawing each page, look up its entry in page_layouts to decide which basename to inherit (the SVG itself was loaded in §1.0):

  • Entry present (e.g., P04: 03a_content_image_text) → inherit the corresponding SVG already in context. The basename must match an actual file in the chosen template directory; if it doesn't, emit warning: page_layouts P<NN> references missing file <basename>.svg — falling back to free design and proceed.
  • No entry for this page → free design, no inheritance. Not an error — Strategist intentionally left this page free.
  • Whole section absent → see §1 fallback (legacy page-type matching).

Do not invent a layout entry, and do not assume a template just because templates/ exists — if page_layouts is present but silent for this page, that silence is the instruction.

Per-page chart reference — page_charts section:

Before drawing each page, look up its entry in page_charts to decide which chart structure applies (the SVG itself was loaded in §1.0):

  • Entry present (e.g., P09: timeline_horizontal) → adapt the corresponding chart SVG already in context. Apply project colors/typography/density; do not copy verbatim. Cross-reference templates/charts/charts_index.json for the chart's purpose summary if needed.
  • No entry for this page → either no chart on this page, or a chart that didn't match any catalog template (Strategist's no-template-match fallback). Design the visualization from scratch using design_spec.md §VII for guidance.
  • Whole section absent → no chart pages in this deck.

3. Execution Guidelines

  • Proximity: group related elements with tight spacing; separate unrelated groups
  • Spec adherence: follow color, layout, canvas format, and typography in the spec
  • Template structure: if templates exist, inherit the visual framework
  • Main-agent ownership: SVG generation must run in the main agent (not sub-agents) — pages share upstream context for cross-page visual continuity
  • Generation rhythm: lock global design context first, then generate pages sequentially in one continuous context. No batched groups (e.g., 5 at a time).
  • Phased batch generation (recommended):
    1. Visual Construction Phase: generate all SVG pages sequentially for visual consistency. Use layout judgment for chart marks during the draft. MUST embed plot-area markers per §3.1 below on every chart page — coordinate calibration is a post-generation step (see workflows/verify-charts.md) that depends on these markers.
    2. Quality Check Gate: run python3 scripts/svg_quality_checker.py <project_path> on svg_output/. Any error (banned features, viewBox mismatch, spec_lock drift, non-PPT-safe font, etc.) MUST be fixed on the offending page before proceeding — regenerate and re-check. Address warnings when straightforward. Do NOT defer to after finalize_svg.py — finalize rewrites SVG and masks some violations.
    3. Logic Construction Phase: after SVGs pass the quality check, batch-generate speaker notes for narrative continuity.

3.1 Chart Plot-Area Marker (MANDATORY on every chart page)

The verify-charts workflow enumerates chart pages from design_spec.md §VII, then reads each page's plot-area marker to feed svg_position_calculator.py. Missing marker → verify-charts has to re-derive the plot area from axis lines, paying the cost on every run.

Hard rule: every SVG page that contains a data visualization chart includes a plot-area marker inside <g id="chartArea">, placed after axis lines and before the first data element (bar, line, area, point).

Rectangular plot area (bar / horizontal_bar / grouped_bar / stacked_bar / line / area / stacked_area / scatter / waterfall / pareto / butterfly):

<!-- chart-plot-area: x_min,y_min,x_max,y_max -->

Radial charts (pie / donut / radar):

<!-- chart-plot-area: pie | center: cx,cy | radius: r -->
<!-- chart-plot-area: donut | center: cx,cy | outer-radius: r1 | inner-radius: r2 -->
<!-- chart-plot-area: radar | center: cx,cy | radius: r -->

How to determine coordinate values:

Value Derivation
x_min X coordinate of the Y-axis line (leftmost data boundary)
y_min Y coordinate of the topmost grid line (highest data boundary)
x_max X coordinate of the rightmost axis endpoint or grid line
y_max Y coordinate of the X-axis baseline
cx, cy Center point of pie/donut/radar (accounting for transform="translate()")
r Outer radius of the chart

Per-page verification — after writing each chart SVG, confirm the marker exists:

grep "chart-plot-area" <project_path>/svg_output/<current_page>.svg

All chart templates in templates/charts/ include this marker as a reference. If you are drawing a chart and the marker is absent, you have a bug.

  • Technical specs: see shared-standards.md for SVG/PPT constraints
  • Card containers — use the documented patterns: when a content page needs section cards (4 quadrants, parallel aspects, capability blocks, info cards), use the patterns codified in templates/charts/CHART_STYLE_GUIDE.md §11 — half-rounded section tab (§11.1), nested card border without stroke (§11.2), card-grid skeletons (§11.3), diagonal dashed connector for cross-quadrant relationships (§11.5), ground-anchor ellipse as a non-filter depth marker (§11.6), bidirectional interaction arrows for paired protocols (§11.7). Do not reinvent the "tinted full-rounded rect + white cover-rect to hide the bottom corners" hack; it survives in older templates but breaks SVG→PPTX color editing. Reference templates: labeled_card.svg, quadrant_text_bullets.svg, kpi_cards.svg, matrix_2x2.svg, team_roster.svg, client_server_flow.svg.
  • Reference — prefer semantic shapes over preset stacks (not a constraint): when a slide needs to express "ascending / converging / breaking through / stacking" — i.e., a relationship that goes beyond a generic arrow — prefer a single custom <polygon> or <path> that encodes the semantics geometrically, rather than stacking multiple preset arrows. A converging-tip path or a podium polygon reads faster than three arrows pointing at a label. Examples of this technique appear in many imported corporate decks; see projects/01_template_import/svg_output/slide_01.svg shape-158 for a reference (gradient-filled inward-pointing arrow). Do not codify these as templates — they are page-specific; the rule is just "consider polygon before stacking presets."
  • Reference — visual depth through restraint (not a constraint): layered depth comes from rhythm (flat vs lifted, dense vs spacious), not from shadows everywhere. Shadow typically suits 2-3 genuinely floating elements per page (cards on photos, primary CTA, overlays); keep peer-grid cards, dividers, body containers flat. Reach for typography weight, spacing, accent bars, subtle tints before shadow. Full rules in shared-standards.md §6.

SVG File Naming Convention

Format: <NN>_<page_name>.svg (two-digit number from 01; name matches the deck's language and the page title in the Design Spec).

Examples: 01_封面.svg / 02_目录.svg / 03_核心优势.svg; 01_cover.svg / 02_agenda.svg / 03_key_benefits.svg.


4. Icon Usage

Strategist chooses the library and inventory; Executor only implements. Library details and one-library rule: ../templates/icons/README.md. This section defines placeholder syntax.

🚧 MANDATE — icons are not optional in free-design mode. When spec_lock.md declares an icons.library + non-empty inventory, every content page MUST place icons from that inventory — they are part of the design, not garnish. In free-design mode there is no mirror template to copy icons from, so the only way icons reach the deck is you authoring <use data-icon> on each page. Concretely:

  • Content pages (KPI cards, lists, process / flow steps, comparison columns, feature grids, section dividers with a concept) → place 13 inventory icons that label the content (one per card / step / list item is the common pattern). A dense content page with zero icons reads flat and is a quality regression.
  • Legitimately icon-less (do NOT force icons): the cover, a pure-typography section break, a single-number / single-quote breathing page, and the closing/thanks page.
  • The strategist already validated each inventory name exists (via icon_sync.py); use those names verbatim — do not invent new ones.
  • Enforcement: svg_quality_checker.py fails the deck (hard error, non-zero exit) when an inventory is locked but the deck authors zero <use data-icon> across all pages, and warns per page that references none. Don't ship past it by deleting the icon lock — place the icons.

Resolution is project-first. Strategist copied the chosen icons into <project_path>/icons/<lib>/ (via icon_sync.py); finalize_svg.py embed-icons embeds from there, falling back to the global library per-icon. Custom icons: drop an .svg into <project_path>/icons/<lib>/ (any <lib>, e.g. custom/) and reference it as data-icon="<lib>/<name>" — it embeds like any other. Reference only icons in the spec_lock.md inventory.

Built-in icons — Placeholder method (recommended):

<!-- chunk-filled (straight-line geometry, sharp corners, structured) -->
<use data-icon="chunk-filled/home" x="100" y="200" width="48" height="48" fill="#005587"/>

<!-- tabler-filled (bezier-curve forms, smooth & rounded contours) -->
<use data-icon="tabler-filled/home" x="100" y="200" width="48" height="48" fill="#005587"/>

<!-- tabler-outline (light, line-art style — screen-only decks) -->
<use data-icon="tabler-outline/home" x="100" y="200" width="48" height="48" fill="#005587"/>

<!-- phosphor-duotone (single color + 20% backplate — soft depth without solid weight) -->
<use data-icon="phosphor-duotone/house" x="100" y="200" width="48" height="48" fill="#005587"/>

<!-- simple-icons (brand logos — used alongside the deck's primary library, only for real company/product marks) -->
<use data-icon="simple-icons/github" x="100" y="200" width="48" height="48" fill="#181717"/>

<!-- tabler-outline with thin / bold stroke (stroke-style libraries only) -->
<use data-icon="tabler-outline/home" x="100" y="200" width="48" height="48" fill="#005587" stroke-width="1.5"/>
<use data-icon="tabler-outline/home" x="100" y="200" width="48" height="48" fill="#005587" stroke-width="3"/>

⚠️ Color: ALWAYS use fill="#HEX" on <use data-icon="...">. NEVER use stroke or fill="none", even for stroke-style libraries.

stroke-width (stroke-style libraries only, currently tabler-outline): allowed values {1.5, 2, 3}. If spec_lock.md icons.stroke_width is declared, all placeholders MUST use that value deck-wide. Default 2 if absent (legacy). Ignored on non-stroke libraries.

Icons are auto-embedded by finalize_svg.py — no need to run embed_icons.py manually.

Searching for icons — use terminal, zero token cost:

ls skills/ppt/templates/icons/chunk-filled/ | grep home
ls skills/ppt/templates/icons/tabler-filled/ | grep home
ls skills/ppt/templates/icons/tabler-outline/ | grep chart
ls skills/ppt/templates/icons/phosphor-duotone/ | grep house
ls skills/ppt/templates/icons/simple-icons/ | grep github

Abstract concept → icon name (names for chunk-filled; tabler libraries use their own equivalents — verify with ls | grep):

Concept chunk-filled tabler-filled / tabler-outline
Growth / Increase arrow-trend-up same
Decline / Decrease arrow-trend-down same
Success / Complete circle-checkmark circle-check
Warning / Risk triangle-exclamation alert-triangle
Innovation / Idea lightbulb bulb
Strategy / Goal target same
Efficiency / Speed bolt same
Collaboration / Team users same
Settings / Config cog settings
Security / Trust shield same
Money / Finance dollar currency-dollar
Time / Deadline clock same
Location / Region map-pin same
Communication comment message
Analysis / Data chart-bar same
Process / Flow arrows-rotate-clockwise refresh
Global / World globe world
Excellence / Award star same
Expand / Scale maximize same
Problem / Issue bug same

For self-evident names (home, user, file, search, arrow, etc.) — just grep chunk-filled/ directly without consulting the table.

⚠️ Icon validation: only use icons from the Design Spec's approved inventory. Verify each via ls | grep before use. Mixing libraries within one deck is FORBIDDEN.


5. Visualization Reference

Chart SVGs referenced in VII. Visualization Reference List are loaded once via the §1.0 batch read. This section governs adaptation only.

Hard rule: adapt the loaded chart SVG; do not improvise from memory and do not replicate verbatim. Apply project colors, typography, content; preserve visualization type.

Adaptation rules:

  • Preserve: visualization type (bar/line/pie/timeline/process/framework…) as specified
  • Adapt: data, labels, colors (project scheme), dimensions
  • Freely adjust: composition, axis ranges, grid, legend, spacing, decoration — as long as the chart stays accurate and readable
  • Forbidden: changing visualization type without spec justification; omitting data points or structural elements from the outline

Templates: templates/charts/ (70 types). Index: templates/charts/charts_index.json

5.1 Chart Coordinate Calibration

Coordinate calibration runs as a standalone post-generation workflow, not inside the executor pipeline. After SVG generation completes, if the deck contains data charts, run workflows/verify-charts.md before post-processing.

The executor's only obligation here is upstream: embed the <!-- chart-plot-area ... --> marker on every chart page during initial draft (§3.1). Verify-charts enumerates chart pages from design_spec.md §VII (authoritative deck plan) and uses the marker to feed svg_position_calculator.py.

Do NOT run svg_position_calculator.py during the initial draft. The calculator calibrates already-generated SVGs against their declared plot areas; running it before the SVG exists has nothing to compare against.


6. Image Handling

Handle images by their status in the Design Spec's Image Resource List. Status enum and lifecycle: svg-image-embedding.md.

Status Source Handling
Existing User-provided Reference images directly from ../images/ directory
Generated Generated by Image_Generator Reference images directly from ../images/ directory
Sourced Web-acquired by Image_Searcher Reference from ../images/. Read image_sources.json to decide attribution — see §6.1 below.
Rendered Deterministic formula PNG Reference from ../images/; use preserveAspectRatio="xMidYMid meet"
Needs-Manual Acquisition failed and file is absent Use dashed border placeholder unless the expected file exists
Placeholder Not yet prepared Use dashed border placeholder

Reference syntax: see svg-image-embedding.md.

Template-bundled images: when a template (deck / layout / brand) is applied, its bitmaps are copied into the project's images/ alongside every other runtime image (SKILL.md Step 3). Reference them the same way — ../images/<name> — and do not reproduce a template SVG's bare sibling href (e.g. href="cover_bg.png"): the template SVG is reference material, the rendered page lives in svg_output/ and must point at ../images/. Mirror templates (§1.1) are the one exception — they copy hrefs verbatim, and the exporter resolves those bare hrefs against images/.

Placeholder: Dashed border <rect stroke-dasharray="8,4" .../> + description text

no-crop images: when a spec_lock.md images entry ends with | no-crop, size the container to the image's native ratio (from analyze_images.py or file dims) and use preserveAspectRatio="xMidYMid meet". Untagged entries are croppable — default to slice.

Formula images: rows with Acquire Via: formula or Type: Latex Formula MUST be treated as no-crop even if a legacy spec_lock.md forgot the flag. Use the dimensions from design_spec.md §VIII, analysis/image_analysis.csv, or images/formula_manifest.json; do not normalize all formulas to one height unless the spec explicitly states that layout choice.

6.1 Inline Attribution for Sourced Images (web path)

Whenever the slide uses an image with Status: Sourced, look up the corresponding entry in project/images/image_sources.json and act on license_tier:

license_tier Action on this slide
no-attribution Embed the <image> element only. No credit element needed.
attribution-required Embed the <image> element plus a small inline <text> credit element per the visual spec in image-searcher.md §7.

The credit text is not rendered by post-processing or export — it must be present in the SVG you produce. The shape of the credit element (size, position, color, multi-image source line, hero gradient overlay) is specified in image-searcher.md §7. Do not invent a different style.

Use attribution_text from the manifest entry as the starting point, then compress for the small-text constraint (drop URL, drop filename, keep "via Provider / License"). For CC0/PD images that landed in the attribution-required tier only because of upstream metadata quirks (rare), credits are still safe to render.

svg_quality_checker.py treats missing CC BY / CC BY-SA inline attribution as an error. Fix the offending SVG before post-processing.

The manifest is the single source of truth for credits. Do not duplicate license info into speaker notes or any other artifact.


7. Font Usage

Source of truth: spec_lock.md typography. Use font_family as default; override per role with title_family / body_family / emphasis_family / code_family if declared. LaTeX formulas that Strategist rendered are PNG images, not a code_family text role.

If spec_lock.md is absent, consult strategist.md §g — do not invent a stack.

Hard rule: every SVG font-family stack MUST end with a pre-installed family (Microsoft YaHei / SimHei / SimSun / Arial / Calibri / Segoe UI / Times New Roman / Georgia / Consolas / Courier New / Impact / Arial Black). PPTX has no runtime fallback — missing fonts degrade to Calibri.


8. Speaker Notes Generation Framework

Task 1. Generate Complete Speaker Notes Document

After all SVG pages are finalized, enter Logic Construction Phase and write the full notes to notes/total.md. Batch-writing (not per-page) lets transitions plan coherently.

Pure spoken narration: notes are read aloud verbatim by notes_to_audio.py (TTS). Write only what should be spoken. No visible markers, no labeled meta-lines, no enumerated key-point lists, no duration annotations — anything you write outside the heading will be vocalized.

Per-page structure: # <number>_<page_title> heading (the # heading line is the only thing stripped before TTS), pages separated by ---. Body is 25 natural sentences carrying the page's core message. Page-to-page transitions live inside the opening sentence as natural prose ("接下来……" / "Having framed X, let's turn to Y") — no bracketed [过渡] / [Transition] tags.

Concrete examples — same shape applies to any language; just write naturally in that language.

中文 deck

# 02_市场格局

在明确了行业背景之后,我们来看具体的市场格局。当前线上零售集中度持续上升,前三大平台合计份额已经达到百分之六十八,腰部玩家正在被快速挤压,留给新进入者的窗口期不超过十八个月。这意味着我们的策略必须聚焦,而不是铺开。

英文 deck

# 02_market_landscape

Having framed the industry backdrop, let's look at the actual market landscape. Online retail concentration keeps rising — the top three platforms now hold sixty-eight percent of combined share, mid-tier players are being squeezed fast, and the window for new entrants is under eighteen months. This means our strategy has to focus, not spread.

日本語 / 한국어 / 其他语言:照搬同样的结构,用对应语言自然书写即可。

Number readability: TTS reads digits and symbols literally. Prefer fully-spelled forms in the language being spoken when literal pronunciation would be awkward (e.g. Chinese "百分之六十八" reads better than "68%"; "1-2分钟" reads as "一减二分钟"). Plain integers and percentages in English are fine as-is.

Common mistakes to avoid:

  • Leaving any bracketed stage marker ([过渡] / [Transition] / [Pause] / [Data] / [Scan Room] / [Interactive] / [Benchmark] etc.) in the text — they will be read aloud literally.
  • Adding 要点:① … / Key points: (1) … / 时长2分钟 / Duration: 2 minutes / Flex: … lines — TTS will speak "要点 一 …".
  • Mixing languages within one deck's notes.

Task 2. Split Into Per-Page Note Files

Auto-split notes/total.md into per-page files in notes/.

Naming: match SVG names (01_cover.svgnotes/01_cover.md); slide01.md also supported (legacy).


9. Next Steps After Completion

Auto-continuation: After Visual Construction Phase (all SVG pages) and Logic Construction Phase (all notes) are complete, the Executor proceeds directly to the post-processing pipeline.

Post-processing & Export (same canonical pipeline as shared-standards.md §5):

# 1. Split speaker notes
python3 scripts/total_md_split.py <project_path>

# 2. SVG post-processing (auto-embed icons, images, etc.)
python3 scripts/finalize_svg.py <project_path>

# 3. Export PPTX
python3 scripts/svg_to_pptx.py <project_path>
# Output (default-flow mode):
#   exports/<project_name>_<timestamp>.pptx           ← native pptx (canonical output)
#   backup/<timestamp>/svg_output/                    ← Executor SVG source backup (always written)
#
# Add --svg-snapshot to additionally emit:
#   exports/<project_name>_<timestamp>_svg.pptx      ← SVG snapshot pptx (sibling of native pptx)