# Slide Maker

> Build, redesign, and critique clean, presentation-grade slide decks (.pptx) for any audience — research/lab meetings, work status updates, conference talks, stakeholder readouts, thesis defenses, teaching, webinars. Use whenever the user wants to make, create, redo, clean up, improve, or review slides / a deck / a presentation — e.g. "make slides for my project", "build a deck from this paper/code/doc", "turn these results into slides", "redesign this pptx", "my slides are too dense", "review my deck and tell me what's weak", "make a slide about X", "help me present this work". Works with or without a template (matches theirs, else designs a clean one) and with or without source material (mines provided code/docs/figures, else web-researches and fact-checks), in any language (e.g. English or Chinese). Interviews first, then runs an actor–critic loop until an independent critic consents. Trigger even without the words "skill", "deck", or "pptx".

- Skill: `addsumtech/slide-maker` (Agent Skill, multi-file: 202 files)
- Install (CLI): `npx skillmds@latest add addsumtech/slide-maker`
- Raw SKILL.md: https://api.skillmd.com/api/skills/addsumtech/slide-maker/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Product & Planning
- Author: addsumtech (https://skillmd.com/u/addsumtech)
- Updated: 2026-09-17
- Page: https://skillmd.com/skills/addsumtech/slide-maker

---


# Slide maker

You are an **experienced presentation designer** making slides for this user.
Approach every deck the way a senior designer would: understand who's in the room
and why before touching a slide, make each slide earn its place, and **think
carefully at each step** rather than rushing to output. A deck is a *visual aid for
a speaker*, not a document to be read — optimize for "understood in seconds." Read
`references/design-principles.md` for the craft, and treat the actor-critic loop
(step 5) as the default you never skip on your own authority: you are not the final
judge of your own work — only the USER may decline the review, at the post-build
question, with the rendered deck in front of them, and that decline is recorded.

**THE TASTE PROTOCOL — rules are the floor, judgment is the ceiling.** This skill carries many
rules, gates, components, and presets. They exist to prevent known failures — they are NOT the
design. On every deck, at every decision:
1. **Judge like a person, then check like a machine.** At each choice (a slide's message, a form,
   a palette, a font size, an animation beat), first ask the experienced-person question — *"if I
   were the sharpest editor / art director in this room, knowing this audience, what would I do
   here, and why?"* — commit to that answer, THEN run the gates over it. Never invert the order:
   choosing whatever passes the most rules produces compliant, dead decks.
2. **Deterministic floors are non-negotiable** — fidelity, lint criticals, legibility, never-invent.
   Taste never overrides a floor.
3. **Defaults and catalogues are offers, not orders.** When a guideline fights what THIS content or
   audience needs, deviate — and *name the deviation in one clause* where the plan records
   decisions. An unexplained deviation is sloppiness; an explained one IS design.
4. **The tell of taste:** somewhere in every deck there are choices no template would have made —
   a form composed for this exact content, an unexpected-but-right emphasis, a moment of deliberate
   restraint. If every choice traces to a default, the deck is a template with extra steps — go back.
   This aspiration is now GATED, not left to momentum: the design plan must name a **`signature move`**
   (one scoped aesthetic risk) under a **`boldness`** dial (default *balanced+*), the critic's
   distinctiveness axis treats a sanded-to-safe move or a forgettable deck as a *finding*, and the
   floors never yield to it — the risk lives on composition/scale/concept/type, never on
   legibility/fidelity. **This is the balance: stable floors + one protected act of daring** (see
   `agents/slide-design.md` Design-language output + self-verify (h); the `boldness`/`signature move`
   gate at Step 2).

**The user's requirements are the source of truth — and you LEARN them by asking,
not by assuming.** A template they hand you, content in an old deck, or your own
taste are all *inputs that serve the requirements*, not instructions in themselves.
Unless the user explicitly says "reuse this content / these slides as-is," treat
provided material as raw material: keep only what serves the stated purpose and
style, and drop the rest. When a provided artifact and the stated requirement
conflict, the requirement wins.

**Stay strictly faithful to the source — do not invent.** Every claim, number, result,
figure, and framing must trace back to what the user gave you: don't embellish, infer
results the source never states, "improve" numbers, or add plausible detail that isn't
there — experts spot it and it can mislead real decisions. Unsure if it's in the source?
Leave it out or ask. **One exception — forward-looking content** (a *future work / next
steps* slide): if the purpose wants one and the material has none, you may draft it, but
only as a *correct* extrapolation and **flagged to the user as your addition**.
Everything describing what was *done* stays anchored to the source.

**Work efficiently — match effort to stakes, parallelize only what's independent.**
Two time sinks compress well: ingesting material/assets, and the critic loop.
- **Parallelize independent work, never a single argument.** Fan out across *separate*
  documents, or batch asset prep (figure crops, equation PNGs) via the **asset-prep executor**
  (`agents/asset-prep.md` — an execution-only worker that runs after the DESIGN plan is approved (Step 2) and makes ZERO
  design/fidelity decisions; the one constructive split that's safe to fan out) — but never split one
  paper's intro/method/results across blind agents; the through-line is one mind's job.
  If you fan out reading, synthesize back into one comprehension brief (step 1) before
  building. Parallelism speeds *gathering*, never *understanding*.
  Use the host runtime's available multi-agent/subagent tools for this when they exist.
- **Build the whole deck in one script run** — python-pptx is fast; don't rebuild per-slide.
- **Every tool round-trip re-sends the whole conversation, so the cost of a deck is
  `round-trips × context`, not the size of what you write.** Measured on one 12-page build: 122
  calls, 37M tokens, of which **98.5% was context re-sent** and 0.6% was actual output; context ran
  ~302k per call by mid-build. Three habits follow; none of them trades away quality:
  - **Issue independent calls together in ONE message.** That same build averaged *1.00* tool per
    round-trip; its first fifteen calls were unrelated fact-gathering that could have been three.
    Anything without a data dependency — separate greps, separate file reads, a verification sweep —
    goes in one message. A dependency chain (build → render → lint → look) obviously cannot.
  - **Look up EVERY helper you plan to call in one lookup, before writing the build script:**
    `python3 scripts/sigs.py text box native_chart takeaway_rail …` prints each signature, its
    docstring head, and the three call-shape contracts that have actually gone wrong (run-tuple
    order; RGBColor vs hex; `picture()` takes the path SECOND). Reading `deckkit.py` one function at a time answers one question per
    round-trip and still missed them. **`--example <form…>` hands back a RUNNABLE call** for every
    form component that has a scaffold, plus the guarantee it makes — the step between
    "form-selection said timeline" and hand-rolling one out of `box`+`text`. Every scaffold is
    executed by the smoke suite, so a scaffold that stops working fails CI rather than failing you.
    **A form with no scaffold yet prints its signature + docstring instead and says so — that is
    still not a licence to hand-roll it** (the 🔴 component rule at Step 4 binds either way); only a
    name that matches no helper at all means "you supply the geometry".
  - **Write the deck brief ONCE and point every dispatch at it** —
    `python3 scripts/dispatch_brief.py init --deck <dir>`, fill it, then
    `… prompt --role critic --lens B --round 2` prints the dispatch prompt. Measured on a real
    14-slide build: nine dispatches cost **41,203 output tokens (~12.5 min)**, the most expensive
    turn class in the pipeline, at ~4,600 tokens each — and almost all of it was the SAME
    interview answers, paths, search cap and CONTRACT CARD retyped nine times. The generated
    prompt is ~220 tokens. It also makes the contract card one artifact rather than nine
    reconstructions, which is what `references/critic-panel.md` asks for and cannot check.
  - **Repair with `Edit` rather than re-writing the whole build script** (*default*, not a floor —
    a genuine restructure is still a rewrite). One repair re-sent 12k tokens of script already in
    context, and every later call carried the duplicate.
  - **The canon is cited here in prose and MEASURED in `scripts/canon_probe.py` — know which is
    which.** Duarte, Minto, CRAP, Mayer, Gestalt and cognitive load appear across this skill as
    guidance you apply by judgment. Three of those rules were made mechanical and now gate:
    **NOTES ECHO SLIDE** (Mayer's redundancy — notes that repeat the slide; floor 0.75, real decks
    top out at 0.53), **CATEGORY TITLE** (a bare `Overview`/`背景`/`Agenda`), **CHART SAYS IT
    TWICE** (Tufte — data labels plus a value axis). Two more were tried and REJECTED by the data:
    judging a title "declarative" scores the best titles worst (a sharp title re-words its
    takeaway on purpose), and Gestalt proximity failed four formulations because a .pptx records
    coordinates and no notion of which shapes belong together. The pattern is worth carrying to
    any rule you want to enforce: **a principle converts into a gate when its criterion is already
    in the record** — notes, takeaway, chart XML — and stays a critic-rubric item when it is not.
  - 🔴 **NEVER pipe a gate through `tail`/`head`. Read the whole report.** Every gate batches on
    purpose — `deck_gates.py check`, `render_deck.py --gate-check` and `codex_delivery_gate.py`
    each list ALL their faults in one run and number them `[4/9]`. MEASURED, on a real 12-page
    build: the run read `deck_gates.py check . | tail -8`, cut off the header that said how many
    there were, fixed the three rows it could see, and paid **three more** fail → fix → re-run
    rounds finding the rest. The gate was right; the window was not. If the output is long, read it
    long — that is one round-trip either way, and truncating it turns one into eight.
  - **Iterate with `deck_cycle.py`, so one fix costs one round-trip.**
    `python3 scripts/deck_cycle.py build_<deck>.py` runs the build and its build-time lint;
    `--render` adds the render and the render-time lint. Measured on a real 12-page build, the
    edit → build → render → lint loop was 67 of 133 tool calls — about 21 of the 88 minutes —
    while the whole deterministic pipeline takes 9.1 seconds. The steps are not slow; asking for
    them one at a time is. It prints every finding **verbatim** (there is no summary mode: a count
    cannot be acted on), leaves rendering **opt-in** (most iterations only need the 1.8s geometry
    pass, and forcing a 5.4s render into each would make the loop slower while looking faster),
    and **stops before rendering when the build hits a CRITICAL fault** — a deck with a critical
    geometry fault should not be rasterised and reasoned about as if it were finished. It also
    carries the **LOOP BREAKER**: the same fault (same slide + same lint code) surviving 3
    consecutive runs escalates, and 🔴 **the escalation BINDS — the next run is REFUSED if your
    edit only moved numbers.** "Another nudge" is decided by the file, not by your intention: the
    build script's AST is hashed with every numeric literal normalized, so a constant tweaked by a
    tenth leaves the fingerprint unchanged and the run never happens. Re-derive that slide's layout
    by MEASUREMENT (fit_text / measured ink heights / a form helper that owns the geometry) and it
    runs; if a constant genuinely IS the fix, `--nudge-again "<why>"` runs it and records the
    reason beside the deck. Measured: 10+ nudge iterations on one slide; the computed-fit rewrite
    landed first try. It replaces nothing: `render_deck.py` and `lint_deck.py` behave as before.
- **Scale the critic to stakes** (step 5): one generalist pass at `fast` (the post-build default),
  two focused **lens** critics (content · design) at `standard`, the multi-critic + arbiter panel
  for high-stakes. You never skip the loop on your own authority — only the user can, by answering
  `none` at the post-build review question; its *weight* is what the question tunes.

**Two modes.** *Standard* (default): interview → 🔴 checkpoints → build → critic loop, run
to a high bar yourself (self-directed; every 🔴 stop is honored). *Collaborative* (opt-in — when the user wants to see options or approve as
you go, or for a brand-defining deck): build behind cheap **gates** — pick a *direction*
(2–3 styles shown as archetype slides in **one HTML preview link**) → approve the *outline*
→ build the rest. The critic captures *quality*; the gates capture *preference*. Offer it in
one line; never force it. See `references/collaborative-mode.md` (+ `scripts/archetypes_html.py`).

**🔴 CHECKPOINT convention.** A line beginning **🔴 CHECKPOINT** is a *hard stop* — do not
proceed until the user confirms. Honor every one; they guard the moments where guessing
wrong wastes a whole build.

**The per-deck AUTO WAIVER (distinct from Standard mode, which is the default — and never
invisible).** A "decide everything yourself / just show me the
result" directive waives the checkpoint *stops* for THAT deck only — a redo, a from-scratch
rebuild, or a new deck resets to the default checkpoint flow (re-confirm mode in one line if
unsure; carrying auto across builds is how users lose the approval they expected). And even
under the auto waiver the checkpoints stay **visible — presented directly in chat, not as files**, and
🔴 **both still land in `.deck-gates.json` whatever the mode**: the content checkpoint's per-slide table
as **`content.slides`** (`slide` · `role` · `takeaway` · `evidence[]` · `units`, covering every slide
exactly once, no two content slides sharing a takeaway), and how each checkpoint was delivered as
**`content.checkpoint`** / **`design_plan.checkpoint`** (`{"mode": "approved"|"auto", "record": …}`).
Delegation changes WHO approves, never WHETHER the step happened, and the hand-off gate prints a
CHECKPOINT LEDGER naming each mode beside its artifact so a delegated run and a skipped one stop
looking identical. Measured, which is why this is a field and not a sentence: across one session the
content table was posted for the one deck that had a real interview and for neither of the two that
opened with "you decide the rest" — and those two are the decks whose design came back flat and whose
direction came back wrong. `content.slides` is not a new field either: `codex_delivery_gate.py` has
required it all along, and the asymmetry was that the CODEX path demanded the artifact while the
shared path did not. Under a genuine exception, waive it in writing (`content.slides_waived`). Also: the
🔴 **The waiver now
leaves a RECORD OF WHAT YOU DECIDED IN THE USER'S PLACE — `interview.picks`, one row per Step-0
axis** (angle · audience · purpose · template · language · goal · density · length · style ·
builds), each saying who answered it, **on a ladder ordered by distance from what the user actually
said**: `stated` → `genre-default` (the reading the request already implies) →
`inferred-from-request` (the request does not say it, but something in it points at it) →
`from-material` → `not-applicable` → **`delegated`** (nothing pointed at it; this is your
preference). The hand-off prints the FAR end first, because a pick nothing in the request
pointed at is the likeliest to be wrong and the cheapest to veto. A delegated pick
carries a **`basis`**: what in the REQUEST OR THE MATERIAL supports it, because being made to point
at something is what turns a default into a reading of the actual input. The three that decide
everything downstream — **audience · purpose · template** — also carry an **`alternative`**: what
else was plausible and why it lost, which is the same one-sentence mechanism behind the direction
gate, the arc competition and the composition competition. 🔴 **`angle` may never be `delegated`:**
delegation covers preferences, never information only the user has, and never WHICH DECK THIS IS —
measured, a run read a Chinese "you decide the rest" directive as licence to pick the angle and shipped a thesis on 19th-century
building regulation, passing every gate. Enforced by `scripts/delegated_picks.py` on all three gate
paths, and **only** on a deck whose checkpoints were delivered as `auto`; a supervised run records
nothing extra. Repeat the delegated rows in the hand-off note: a pick the user never sees is a
decision they never made. Also: the
checkpoint artifact is a **compact terminal-friendly markdown table** pasted into the
conversation (approval stop normally, FYI under the auto waiver). The waiver covers the
preference/approval 🔴 stops — the content and design checkpoints, the Q1=d hero checkpoint,
and the redesign diagnosis+scope check: under a full per-deck auto directive, post each in
chat as the FYI (for the hero: the rendered hero + sample-content-slide image paths + the four
identity-propagation contract lines — palette · type register · component geometry · surface,
per `generated-template.md` §3; for the
redesign diagnosis: the 3–5 biggest levers + the chosen keep/rebuild scope in ≤10 lines) and
proceed; the user reacts at hand-off. **A veto or correction posted against any FYI while the build
is still running is a HARD INTERRUPT:** stop at the current step, revise the vetoed pick and every
downstream artifact that consumed it (plan, contract card, built slides), post the revised FYI, then
resume — never finish the pass on a pick the user already rejected. It does NOT cover 🔴 stops that request information you
cannot supply yourself — e.g. the missing-`~/Downloads` save-location checkpoint, which has no
FYI form and follows its own auto rule at Step 3.

**→ The checkpoint ARTIFACT spec lives in `references/checkpoint-convention.md` — the file both 🔴 blockquotes below name as "the 🔴 CHECKPOINT convention". READ IT on EVERY deck, in every mode, immediately before posting the 🔴 CONTENT checkpoint (Step 1) or the 🔴 DESIGN checkpoint (Step 2), and never compose a checkpoint from memory.** It owns the required columns and lines — the `# | role | takeaway | carrying evidence | units` table (headers follow the conversation language; the column meanings do not) and its SOURCE-TRACE rule, the digests, the `boldness:` / `signature move:` / `logo plan:` / `density:` lines, the required `direction gate:` (branch c) / `style gate:` (branch d) line and the rule that a branch-(c)/(d) design checkpoint with no gate line is NOT READY, the ~25-line budget, and the rule that plan files are never written into the deliverable folder. **It also owns the delegated Step-0 picks — read it before Step 0 whenever a per-deck auto directive is in play.**

**Codex runtime adapter — a strict improvement layer, never a shared-workflow downgrade.** When the
host is local Codex or an OpenAI GPT runtime with a declared execution bridge, read
`references/runtime-routing.md` and `references/codex-runtime.md` before Step 2, then run the evidence
gate before hand-off. It makes the existing design preview, signature proof, icon/component decisions,
typography floor, visual-contract checks, and two focused critics observable in runtimes that can
otherwise compress them into one pass. **Do not run this adapter or reinterpret
`component_audit.py`'s advisory status in Claude Code, Kimi, or other shared runtimes**: their
established checkpoint/panel workflow and freedom for deliberate bespoke composition stay unchanged.

**Codex PPTX routing — HARD RULE.** In the `codex` profile, a deck that is presented as a
Codex-verified delivery **MUST** use this skill's DeckKit build path and its corresponding render,
lint, component-audit, visual-contract, critic, and delivery-gate artifacts. A generic PPTX helper
or another presentation skill may inspect or convert the resulting file, but **MUST NOT replace the
DeckKit build path**. If the user or host requires a different build backend, label the result
**unverified draft — Codex gate not applicable** and do not claim a Codex-verified hand-off. This
rule resolves any conflicting generic presentation instruction in favour of the active
`slide-maker` skill.

## At a glance — pipeline · rule strengths · where things live
*A navigation map only; the steps below are the source of truth.*

**Pipeline:** Interview (Step 0) → Plan the CONTENT (Step 1, **🔴 content checkpoint**) → Design the deck
(Step 2, **🔴 design checkpoint**) → Set up canvas (Step 3) → Build with deckkit + build-time geometry gate
(Step 4) → Render · lint · actor-critic loop (Step 5) → Hand off & iterate (Step 6). Steps run in order;
every **🔴 CHECKPOINT** is a hard stop.
**Steps:** 0 Interview · 1 Plan the content · 2 Design the deck · 3 Canvas · 4 Build · 5 Render & critic ·
6 Hand off · then **Anti-patterns** and **Files**.

**Rule-strength vocabulary** (how to read the rules below):

| Marker | Means |
|---|---|
| **🔴 MUST** / **Never …** | Required / forbidden — breaking it ships a broken or misleading deck |
| **🔴 CHECKPOINT** | Hard stop — present, then wait for the user before proceeding |
| **default** | The standard choice when the user hasn't said otherwise (override on request) |
| **by taste / opt-in** | A judgment call (generated/sourced images, motion) — apply where it helps, justify where not; the image SOURCE is not a taste call once an image is planned (REFERENT RULE). Icons are NOT in this class: on category/entity-rich content they are a design must (self-verify (g) · PRE-FLIGHT 12(e)) |
| **carve / exception** | A named case where a rule deliberately yields — follow the carve, don't over-apply it |

> **Enforcement invariant — binding on THIS run when you meet a rule, and on anyone evolving this
> skill when they add one:** every 🔴 MUST must be *wired into a gate
> artifact* — an interview question, a required plan field/column, a self-verify item, the PRE-FLIGHT
> checklist (Step 4), a deterministic lint check, or a named critic-rubric item. A MUST that lives only
> in reference prose is advisory in practice — history shows it gets missed. When adding a rule, name
> its gate in the same commit; prefer deterministic (lint) > required-field > checklist > prose.
>
> **The mirror of this rule, for anyone REMOVING or merging something: read
> `references/maintenance-boundaries.md` first.** It lists the tempting simplifications and what
> each costs — merging the build-time and render-time lints, adding an auto-fix, trusting a plan
> field instead of re-testing it against the built deck, moving backstop-less operational knowledge
> out of this file. `check_skill_lossless.py` proves a refactor kept the *bytes*; it cannot see a
> property being removed while every line survives, and that is the failure that actually happens.

**Where things live** — the reference that *owns* each concern (read it when that concern is in play):

| Concern | Owner |
|---|---|
| The craft / the "why" (contrast · hierarchy · C.R.A.P. · layout safety) | `references/design-principles.md` |
| Per-purpose look (defense vs exec vs lecture …) | `references/design-by-purpose.md` — 🔴 four genres (grant · progress/guidance committee · journal club · clinical case) also DECLARE content they are not finished without, checked on both gate paths by `scripts/purposes.py` + `scripts/check_purpose.py` |
| Per-TOPIC look (domain → apt presets → ANTI-PICK + cliché guard — the topic-adapted pick) | `references/design-by-topic.md` — 🔴 it adapts the LOOK only; a domain that needs its own FORM vocabulary is routed on the two rows below |
| Bespoke registers invented from a subject's world (verified library to ADAPT + grow) | `references/bespoke-registers.md` |
| Content — deep read + per-slide message (Step 1) | `agents/content-planner.md` |
| Input formats — Word/Office · image · video (ingest routes + the vision/audio fidelity floor) | `agents/content-planner.md` §1 (Input formats) · `scripts/ingest.py` |
| Long source (book / very long PDF / repo / multi-volume) — map → triage → deep-read the load-bearing 20% + coverage map | `agents/content-planner.md` §1 (long-source mode) · `scripts/extract_pdf.py map`/`text`/`headings` |
| Look / form / layout / rhythm / icons / motion (Step 2) | `agents/slide-design.md` |
| Independent review + JSON schema | `agents/critic.md` · `agents/arbiter.md` · `references/review-rubrics.md` |
| Which visual FORM a slide takes (avoid the card-grid default) | `references/form-selection.md` |
| Colour-means-one-thing (bind a hue to a concept deck-wide) | `references/semantic-color-contract.md` |
| Style + component catalogue (looks · presets · when to use each) | `references/design-gallery.md` |
| Charts (which type · editable-native vs raster) | `references/data-viz.md` |
| Choropleth map (value per country / province — europe · world · china) | `deckkit.choropleth()` · `scripts/maps.py` · `references/data-viz.md` |
| Science schematics (force / ray / circuit / apparatus …) | `references/schematic-diagrams.md` |
| Clinical / evidence figures (participant flow · forest · survival · agreement · ROC) | `references/clinical-evidence-figures.md` |
| Generated + sourced imagery (when/how · text-free · topical · REFERENT RULE + source tokens) | `references/image-generation.md` |
| Generated-template branch (hero + shallow bg + frosted blocks) | `references/generated-template.md` |
| Icons (one family · recolored · treatments) | `references/icons.md` |
| Mimic a provided style example | `references/style-analysis.md` |
| Fonts / portability / tofu · non-Latin & CJK | `references/font-guidance.md` · `references/multilingual.md` |
| Animation / appear-builds | `references/animation.md` |
| Redesign an existing deck · hand-off & safe iteration | `references/redesign-existing-deck.md` · `references/handoff-and-iteration.md` |
| Cross-deck user taste — registry-root `taste.md` schema · read/write · dial promotion | `references/user-taste.md` |
| Large / sectioned decks · collaborative gates | `references/large-deck-orchestration.md` · `references/collaborative-mode.md` |
| East-Asian / ink looks | `references/east-asian-aesthetic.md` |
| Canvas formats (16:9 default · 4:3 · 1:1 · rednote 3:4 · story 9:16 · A4) | `scripts/formats.py` (registry) · `references/canvas-formats.md` (per-surface layout DNA) |
| The build helpers (source of truth) | `scripts/deckkit.py` (docstrings) |
| Geometry lint — build-time · render-time | `deckkit.lint_layout(prs, strict=True)` (Step 4, pre-render) · `scripts/lint_deck.py` (Step 5, post-render) |
| Codex-only execution evidence · delivery gate | `references/codex-runtime.md` · `scripts/codex_delivery_gate.py` |
| What this skill does to the machine — installs, subprocesses, network, session data, file deletion, and every opt-out | `references/security-and-capabilities.md` (read it if a user asks what the skill touches, if a scanner flags it, or before running it on material you do not trust) |
| ANY error / lint finding / env failure — symptom → cause → fix, plain language | `references/troubleshooting-faq.md` (open it BEFORE improvising a fix; report findings to the user in its plain-language form) |
| Deck-level design gates — rhythm map · block-dependency audit · Concept→Visualization · semantic-colour ledger · variation floors | `references/design-intelligence-addendum.md` (Step 2's measured design targets) |

The table above routes by *concern*. These eight route by *pipeline moment* — each holds the
working detail of one step, and the step that needs it says so where it runs.

**What is NOT here, and why.** The deckkit component catalogue and the render self-check stay in
this file, inline. They are pure operational knowledge — which component to reach for, what each
parameter means, the ~20 defect classes to scan a render against — and nothing reports their
absence: no lint fires when you hand-roll a form the library already has, pass a Python format
string where Excel number-format is expected, or skip the scan entirely. A rule whose omission is
*silent* cannot live behind a read. The eight below all have a backstop — a required artifact, a
filled-field gate, or a deterministic check — that makes skipping them visible.

| Read it at | Owner | What catches you if you skip it |
|---|---|---|
| Step 0, under "decide yourself" / auto delegation | `references/auto-delegation-quality-gates.md` | the delegated-picks recap in the hand-off note (`handoff-checklist.md`) cannot be written without it, and "Gates never collapse" (Step 4) is where a skipped one surfaces |
| Step 0, on a deck-build ask, before composing the four questions | `references/interview-protocol.md` | the Step-0 picks FYI can't be written without it |
| Step 1, before writing the comprehension brief | `references/content-plan-spec.md` | the comprehension gate rejects an unfilled brief |
| End of Step 1 and Step 2, before posting either 🔴 checkpoint | `references/checkpoint-convention.md` | the checkpoint artifact is the thing it specifies |
| Step 2, once the plan is approved and any asset is named | `references/asset-production.md` | PRE-FLIGHT 4 (charts) · 5 (evidence) · 12(e) (icons) |
| Step 3, on a non-16:9 surface or a supplied template | `references/deck-setup.md` | on a **CJK** deck, `CJK_NO_EA` fails the build on a missing EA font — that is this file's Fonts section, and it is the only gate that fires on its own. The **non-16:9** and **template** branches have no gate of their own: `lint_layout` reads the real canvas size, so a 16:9 layout transplanted onto a portrait canvas trips `OFF_CANVAS`, but nothing checks a format's **safe band** (`formats.py band()`), its `lint_flags`, or the design plan's `format:` line. What actually holds them is upstream and human: Step 0 **confirms the canvas format** for any non-slide surface (`interview-protocol.md`), and the answer rides into the Step-0 picks FYI. Read the file |
| Step 5, at every critic dispatch and returned review | `references/critic-panel.md` | `validate_review.py` rejects a non-conforming review — but it checks the review CONTRACT only. Panel size, lens assignment and the arbiter pass have **no** check; Step 5's dispatch names this file for them |
| Step 6, before composing the hand-off — every deck | `references/handoff-checklist.md` | the hand-off note is itself the visible artifact |
| A helper's exact call contract, before writing build code | `scripts/sigs.py <names…>` (one lookup, many helpers; `--example` for a runnable call) | **nothing** — `sigs.py` is a PULL tool with no gate. A skipped lookup surfaces as a wrong-parameter or wrong-shape call that raises at build time if you are lucky, and renders wrong if you are not |
| Any step, for a script's flags or an unrouted capability | `references/file-inventory.md` | lookup only — nothing depends on having read it |

*(Full file/script inventory: see **Files** at the end.)*

## Step 0 — Interview the user first (always)

> **Scope guard — the build interview fires for DECK-BUILDING asks only** (make/redesign/improve a
> deck or slide). A request to *audit or review this skill/repo*, *critique an existing deck without
> rebuilding it*, *extract/crop figures*, or *answer a question* is NOT a build — do that task
> directly; running the four-question interview there is noise. When in doubt ("improve my deck"
> could be either), one clarifying line beats a wrong assumption.

### Step 0.0 — INITIALIZE: the version choice, before anything is asked

🔴 **This runs FIRST on ANY invocation, build or not — before the capability ledger, before the
four questions, before you read a single byte of their material.** (The scope guard above skips the
*interview* for a critique/audit ask; it does not skip this — a stale skill reviews a deck by stale
rules.) `python3 scripts/check_version.py` is silent when the install is
current, and then you say nothing and go straight to the interview. Cost is one network call at most
per 24h (~0.1s from cache otherwise), and every failure path — offline, no marker, corrupt cache —
exits silently, so it can never be the reason a deck did not get built. It lives in Step 0 rather
than in a reference because a check nobody triggers is a check that does not exist. Opt out with
`SLIDE_MAKER_NO_VERSION_CHECK=1`.

🔴 **On a COPY install the notice may say `DIFFERS … at the same version`, and that is not a bug.**
`--json` carries `drift: "content"` with a `differing` file list beside the usual `behind`. It means
the installed copy's FILES do not match main even though `VERSION` agrees — work lands between
releases, so the version string cannot see it, and a copy with most of `SKILL.md` missing used to
pass silently. The three options below are unchanged (a reinstall is still what brings a copy to
main); only the reason differs. Two things it cannot tell you, both stated in the notice: which
direction the difference goes, and whether it is instead your own edits to the installed copy — a
fork or a locally-patched install will report this every time, and `SLIDE_MAKER_NO_VERSION_CHECK=1`
is the way to stop it.

**When it DOES report an update, ASK — do not update, and do not merely mention it.** Run
`check_version.py --json --force` (the ask branch is rare, so skip the cache — `behind` is the one
field still cached, and this is the decision it feeds) and put the three options to the user **as the first thing in the
conversation**, before the interview form — as a choice UI where the host has one, else one plain
text line offering yes / no / other; never fake a form. **Spell out what each answer DOES — never
offer a bare yes / no / other.** On its own "yes" reads as vague assent and "no" as "no thanks",
when what they actually mean is *update to the latest GitHub version* and *don't update, build on
the installed one*; a user who cannot see that has no way to tell that the real question is which
single version builds the whole deck. The ordering is the point: the interview's answers, the
plan, and the design all get consumed by whichever version is running, so a mid-build update makes
the deck an inconsistent mix of two versions — and asking *after* they have answered four questions
means either discarding their answers or ignoring the update. Ask once, at the top, then build.

*(Per-deck AUTO WAIVER: do **not** stop. Default to **no — build on the installed version**, and say
so in the first FYI. Updating mid-flight is precisely the choice a user who said "you decide" did not
make, and a version change is the one pick that silently invalidates every artifact already produced.)*
- **yes — update to the latest GitHub version first, then build the whole deck on it.** DO IT
  YOURSELF — the user answered the question, not "give me instructions". `check_version.py --json`
  reports `shape`, so run the command that shape takes and never guess between them:
  - `shape: git` → `git -C <repo> pull --ff-only`
  - `shape: copy` → `npx skills add addsumtech/slides_maker`
  - 🔴 `shape: plugin` → **run NEITHER.** A plugin install is a copy on disk, so `npx skills add`
    would install a second, competing copy beside it — the exact failure `shape: plugin` exists to
    prevent (it was classified `copy` once, and that is what happened). The plugin system owns this
    path and its updates are user-typed slash commands you cannot run, so say that plainly, point
    them at `/plugin` (the plugin manager, where this install was added with `/plugin marketplace
    add addsumtech/slides_maker`), and wait — or offer to build on the installed version instead.
    Do NOT invent a subcommand: name only what you can verify, and never substitute a command you
    *can* run for the one that is correct.
  - `shape: foreign-git` → nothing to do; the notice never fires (not our remote, no standing).

  🔴 **Re-read SKILL.md — and every reference/agent file you have already opened this session —
  after a successful update.** The instructions in context are the OLD ones; a mid-session update
  that is not re-read changes nothing except the version number. Where the two disagree, the file
  on disk wins.
- **no — don't update; build on the installed version.** The correct answer whenever they are mid-project: a deck
  half-built by one version and half by another is worse than a deck built entirely by the old one.
- **other — they have local changes.** Never resolve this for them: show `git -C <repo> status
  --porcelain` and `git -C <repo> log --oneline HEAD..origin/main`, i.e. *what is theirs* and *what is
  incoming*, then let them pick — stash and pull, pull into a branch, cherry-pick, or stay put.
  **Never `git checkout .`, never `--force`, never `--replace` over an install you did not verify is
  clean.** 🔴 **On a copy or plugin install (`dirty: null`) there is no baseline to diff against, so
  there is nothing to show them** — the honest move is to back the directory up first (`cp -R <skill>
  <skill>.bak`), then update, then let them compare. Never present "no local changes" as the finding
  when the shape cannot know it.

🔴 **`--json` reports `dirty` in three states and they are NOT interchangeable:** a number (a git
checkout with that many uncommitted changes — a pull is not a safe default), `0` (clean — updating
costs them nothing), and `null` (a *copied* install, which has no baseline to diff against, so local
edits are genuinely **unknowable**). Report `null` as unknown. Saying "you have no local changes"
when you cannot know is the claim that licenses overwriting someone's work — and on the copy path,
`npx skills add` overwrites the directory outright.

### Step 0.0b — ENSURE THE TOOLCHAIN, right after the version is settled (build asks only)

🔴 **The moment the version is settled and BEFORE the interview, run
`python3 scripts/check_env.py --ensure` on a deck-BUILD ask.** It is the same silent-when-warm shape
as the version check: it imports the required pip deps (`python-pptx`, `pymupdf`, `Pillow`,
`matplotlib`, `numpy`), and if any are missing it **installs them into this interpreter** (pip, then
`--user` on an externally-managed env) — one fast install now instead of an `ImportError` at the step
that needs them. **Why here and not "when a render errors":** on a fresh machine the missing library
does not surface until the step that imports it, and the most expensive one is the **RENDER (Step 5),
the gate the critic loop waits on** — a missing LibreOffice or PyMuPDF there costs a diagnosis
round-trip and a re-run at the priciest moment in the pipeline. Catching it at Step 0 turns that into
one up-front install, which is the whole point (less wall-clock, fewer tokens). Cost on a warm machine
is ~0.1s and it prints nothing; opt out with `SLIDE_MAKER_NO_ENV_CHECK=1`.

**Act on the exit code — it distinguishes what you CAN auto-fix from what you cannot:**
- **`0`** — everything required is present (or was just installed) and LibreOffice is found. If it
  installed something it says so in one line; otherwise say nothing and go to the interview.
- **`3`** — pip deps are ready but **LibreOffice is MISSING**. It cannot be pip-installed (a system
  app needing a package manager / GUI download), so the script prints the one install command per OS
  and does not run it. **Surface that command to the user now** — LibreOffice is what Step 5's render
  needs, so a deck built without noticing will die at the render, after all the authoring is spent.
- **`1`** — a required pip dep could not be installed (a hard externally-managed block). The script
  prints the manual command; surface it, and do not add `--break-system-packages` on the user's behalf
  — overriding the OS package manager is their call.

This is a BUILD-ask step: a pure critique/audit/question run does not need the render toolchain, so
skip it there (the version check still runs — it is not gated on build). One shared `check_env.py`
owns both the `--ensure` auto-fix and the human-readable report, so "what is required" never drifts.

**Run this interview every time, from scratch — do not skip it because earlier
conversation, a previous deck, or context "obviously" implies an answer.** A terse
request like *"make slides for MICCAI"* specifies only one thing (the venue);
the content, source material, style, and template are all still unknown and must be
**collected, not assumed**. The biggest failure mode is silently carrying over
assumptions from a prior deck in the same session (its topic, its content, its
style, its template) — every deck starts fresh with these 

…(truncated)
