skilldrop-cli 0.11.9 → 0.12.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -314,7 +314,7 @@ Designing the agentic systems themselves — the loops, orchestrations, and budg
314
314
  |---|---|
315
315
  | [`audience-profile`](skills/audience-profile/SKILL.md) | Translate an audience type (exec, board, technical, sales, investor, internal, partner, customer) into structural rules — slide count, density, tone, must-have sections. Reusable input for the next three skills. |
316
316
  | [`slide-outliner`](skills/slide-outliner/SKILL.md) | Outline an architecture-review or pitch deck — slide titles, key points, and speaker notes — sized to a target time budget. Doesn't generate PPTX. |
317
- | [`deck-builder`](skills/deck-builder/SKILL.md) | Generate a real PowerPoint (`.pptx`) file from content + audience + color palette. Uses `python-pptx`; supports 7 layout types and audience-tuned density. Pairs naturally with `audience-profile` + `slide-outliner`. |
317
+ | [`deck-builder`](skills/deck-builder/SKILL.md) | Generate a real PowerPoint (`.pptx`) file from content + audience + a brand `.potx`/`.pptx` template or colour palette. Uses `python-pptx`; 10 layouts including charts, tables and images, audience-tuned density. Pairs naturally with `audience-profile` + `slide-outliner`. |
318
318
  | [`exec-summary`](skills/exec-summary/SKILL.md) | Compress a long technical document into a one-page executive summary structured around an Ask, business impact, cost/timeline, risks, and what you need from the audience. |
319
319
  | [`decision-log`](skills/decision-log/SKILL.md) | Extract decisions, action items, owners, and due dates from meeting notes, Slack threads, or transcripts into a structured log with source attribution. |
320
320
  | [`incident-comms`](skills/incident-comms/SKILL.md) | Draft the messages you send *while an incident is still burning* — audience-segmented into customer status-page posts, internal stakeholder updates that arm the relayer, and three-sentence exec briefs (business impact + the ask). Every message leads with reader-facing impact (not internal symptom), uses the precise status vocabulary (investigating / identified / monitoring / resolved), commits only to the **next-update time** (never a fix ETA or speculative cause you'd have to retract), and stays blameless and screenshot-safe. Acknowledge → update-on-committed-cadence → verified resolve. Completes the operate triad with `runbook-generator` (how to fix) and `postmortem-generator` (what to say after). |
@@ -475,6 +475,8 @@ The long-form install material moved to [`guides/`](guides/) so this page stays
475
475
  | Use the two skills that ship scripts | [Skills that ship scripts](guides/reference/skills-with-scripts.md) |
476
476
  | Add a skill or a loop to this repo | [Author a skill](guides/how-to/author-a-skill.md) · [Author a loop](guides/how-to/author-a-loop.md) |
477
477
  | Understand why it is built this way | [Why loops](guides/explanation/loops.md) · [ARCHITECTURE.md](ARCHITECTURE.md) |
478
+ | See one change go through all four loops | [Follow one change through the loops](guides/tutorial/follow-a-change-through-the-loops.md) |
479
+ | Point a model at this repo | [`llms.txt`](llms.txt) — a generated index so a tool reads the few relevant pages instead of the tree |
478
480
 
479
481
  ### Reviewer subagents
480
482
 
@@ -0,0 +1,30 @@
1
+ [
2
+ {
3
+ "query": "take this story to merged code",
4
+ "should_trigger": true
5
+ },
6
+ {
7
+ "query": "run the build loop on this ticket",
8
+ "should_trigger": true
9
+ },
10
+ {
11
+ "query": "implement this and gate it before I merge",
12
+ "should_trigger": true
13
+ },
14
+ {
15
+ "query": "is this branch safe to merge yet?",
16
+ "should_trigger": true
17
+ },
18
+ {
19
+ "query": "write me an ADR for this decision",
20
+ "should_trigger": false
21
+ },
22
+ {
23
+ "query": "design the system for this requirement",
24
+ "should_trigger": false
25
+ },
26
+ {
27
+ "query": "what should we build next quarter?",
28
+ "should_trigger": false
29
+ }
30
+ ]
@@ -0,0 +1,27 @@
1
+ {
2
+ "loop_name": "build",
3
+ "evals": [
4
+ {
5
+ "id": "red-gate-blocks-the-merge",
6
+ "prompt": "Run the build loop on this story: add a /export endpoint. `pytest` currently fails on one new test, and the endpoint reads user_id from the query string.",
7
+ "assertions": [
8
+ "Runs the stages in order — shape, implement, verify — and never starts implement without acceptance criteria a test can assert",
9
+ "Treats the failing pytest as a RED G2 gate that forces NOT READY on its own, independent of any review finding",
10
+ "Returns to the `implement` stage on NOT READY, not to `shape`, because G2's revise_to names implement",
11
+ "Never edits the gate script, its config, or the failing test to turn G2 green",
12
+ "Names the gate id (G2) and the verdict verbatim from contracts/terminals.json",
13
+ "Stops after 3 returns and emits BLOCKED naming what did not converge, rather than starting a 4th round"
14
+ ]
15
+ },
16
+ {
17
+ "id": "escalates-a-design-dispute-not-a-defect",
18
+ "prompt": "Build-loop this change. The gate is green but the reviewer thinks the whole caching approach is wrong.",
19
+ "assertions": [
20
+ "Records G2 as green and does not conflate a design disagreement with a gate failure",
21
+ "Escalates the disagreement to the `decide` stage / council-review rather than arguing it inside the diff",
22
+ "Treats RECONSIDER or SPLIT as leaving the loop, not as a revise",
23
+ "Leaves the merge decision itself to a human at G2.1"
24
+ ]
25
+ }
26
+ ]
27
+ }
@@ -0,0 +1,30 @@
1
+ [
2
+ {
3
+ "query": "design the system for this requirement",
4
+ "should_trigger": true
5
+ },
6
+ {
7
+ "query": "run the design loop on this PRD",
8
+ "should_trigger": true
9
+ },
10
+ {
11
+ "query": "how should we architect this?",
12
+ "should_trigger": true
13
+ },
14
+ {
15
+ "query": "get this to a recorded architecture decision",
16
+ "should_trigger": true
17
+ },
18
+ {
19
+ "query": "implement this story",
20
+ "should_trigger": false
21
+ },
22
+ {
23
+ "query": "write the runbook for this alert",
24
+ "should_trigger": false
25
+ },
26
+ {
27
+ "query": "summarise this for the board",
28
+ "should_trigger": false
29
+ }
30
+ ]
@@ -0,0 +1,26 @@
1
+ {
2
+ "loop_name": "design",
3
+ "evals": [
4
+ {
5
+ "id": "constrains-then-attacks-before-ratifying",
6
+ "prompt": "Run the design loop for per-plan API rate limiting, from this ratified PRD.",
7
+ "assertions": [
8
+ "Runs nfr-spec first and expresses targets as numbers, not adjectives",
9
+ "Produces the design doc and the diagram as one artifact, and checks they agree",
10
+ "Runs threat-model BEFORE the G1 panel, not after",
11
+ "Seats council-review at G1 and records dissent plus what would change each seat's mind",
12
+ "Writes the ADR only after G1 returns, and carries any PROCEED WITH CONDITIONS conditions into it",
13
+ "Names the rejected options and why each lost"
14
+ ]
15
+ },
16
+ {
17
+ "id": "conditions-must-reach-the-adr",
18
+ "prompt": "The design-loop panel returned PROCEED WITH CONDITIONS — the operator seat wants the failure mode documented. Finish the loop.",
19
+ "assertions": [
20
+ "Does not treat PROCEED WITH CONDITIONS as PROCEED",
21
+ "Carries the named condition into the ADR as part of the decision",
22
+ "Proceeds to `record` rather than looping back to `shape`"
23
+ ]
24
+ }
25
+ ]
26
+ }
@@ -0,0 +1,30 @@
1
+ [
2
+ {
3
+ "query": "turn these stakeholder notes into requirements",
4
+ "should_trigger": true
5
+ },
6
+ {
7
+ "query": "run the discover loop on this complaint",
8
+ "should_trigger": true
9
+ },
10
+ {
11
+ "query": "what problem are we actually solving here?",
12
+ "should_trigger": true
13
+ },
14
+ {
15
+ "query": "get this idea to a ratified brief",
16
+ "should_trigger": true
17
+ },
18
+ {
19
+ "query": "split this epic into stories",
20
+ "should_trigger": false
21
+ },
22
+ {
23
+ "query": "write the design doc for this",
24
+ "should_trigger": false
25
+ },
26
+ {
27
+ "query": "review my pull request",
28
+ "should_trigger": false
29
+ }
30
+ ]
@@ -0,0 +1,26 @@
1
+ {
2
+ "loop_name": "discover",
3
+ "evals": [
4
+ {
5
+ "id": "refuses-to-specify-on-a-thin-brief",
6
+ "prompt": "Run the discover loop. An account manager says enterprise customers keep hitting our API limits and are complaining.",
7
+ "assertions": [
8
+ "Starts at `gather` with requirements-interview, because the signal arrived as a conversation rather than a journey or a strategy question",
9
+ "Does not run all three gather skills on the same input",
10
+ "Tags every brief field [explicit] / [implied] / [inferred] / [missing] with its source",
11
+ "Marks the threshold and the affected-customer count as [missing] rather than inventing plausible numbers",
12
+ "Refuses to complete `specify` until the [missing] anchors are resolved, and says which ones block it",
13
+ "Does not self-ratify G0 — it names ratification as a human decision"
14
+ ]
15
+ },
16
+ {
17
+ "id": "reconsider-leaves-the-loop",
18
+ "prompt": "We ran discover and the stakeholder now says they actually want burst capacity, not a higher ceiling.",
19
+ "assertions": [
20
+ "Classifies this as RECONSIDER, a redirect-class verdict",
21
+ "States that a redirect leaves the loop rather than revising within it",
22
+ "Does not route back to `structure` for another brief on the original problem"
23
+ ]
24
+ }
25
+ ]
26
+ }
@@ -0,0 +1,30 @@
1
+ [
2
+ {
3
+ "query": "write the postmortem for last night's incident",
4
+ "should_trigger": true
5
+ },
6
+ {
7
+ "query": "run the operate loop on this service",
8
+ "should_trigger": true
9
+ },
10
+ {
11
+ "query": "what should we alert on and what's the runbook?",
12
+ "should_trigger": true
13
+ },
14
+ {
15
+ "query": "we're in an incident — what do I tell customers?",
16
+ "should_trigger": true
17
+ },
18
+ {
19
+ "query": "implement the fix for this bug",
20
+ "should_trigger": false
21
+ },
22
+ {
23
+ "query": "design the retry architecture",
24
+ "should_trigger": false
25
+ },
26
+ {
27
+ "query": "draft the PRD for this feature",
28
+ "should_trigger": false
29
+ }
30
+ ]
@@ -0,0 +1,25 @@
1
+ {
2
+ "loop_name": "operate",
3
+ "evals": [
4
+ {
5
+ "id": "postmortem-must-produce-runbook-deltas",
6
+ "prompt": "Run the operate loop. Our rate limiter alert fired last night — a customer's retry loop hammered the API for 40 minutes.",
7
+ "assertions": [
8
+ "Enters at `respond`, not at `instrument` — an incident does not replay earlier stages",
9
+ "Stages the communication (detect / mitigate / resolve) and matches the message to the stage the incident is in",
10
+ "Produces a blameless postmortem that names missing guardrails, never people",
11
+ "Ends in concrete runbook deltas phrased as before/after edits",
12
+ "Routes those deltas back to `document` via G3's revise edge rather than treating the postmortem as terminal"
13
+ ]
14
+ },
15
+ {
16
+ "id": "refuses-to-guess-incident-facts",
17
+ "prompt": "Write the postmortem for last night's outage. I don't have the exact timeline or customer impact numbers yet.",
18
+ "assertions": [
19
+ "Emits BLOCKED naming the missing facts rather than producing a confident postmortem",
20
+ "Does not fabricate timings, customer counts, or a root cause",
21
+ "States exactly what to re-run with once the facts exist"
22
+ ]
23
+ }
24
+ ]
25
+ }
@@ -0,0 +1,30 @@
1
+ [
2
+ {
3
+ "query": "turn these notes into something I can send",
4
+ "should_trigger": true
5
+ },
6
+ {
7
+ "query": "run ship-a-draft on this transcript",
8
+ "should_trigger": true
9
+ },
10
+ {
11
+ "query": "take this ticket to a finished document",
12
+ "should_trigger": true
13
+ },
14
+ {
15
+ "query": "polish this draft and check the argument",
16
+ "should_trigger": true
17
+ },
18
+ {
19
+ "query": "implement this feature",
20
+ "should_trigger": false
21
+ },
22
+ {
23
+ "query": "gate my pull request",
24
+ "should_trigger": false
25
+ },
26
+ {
27
+ "query": "what should our OKRs be?",
28
+ "should_trigger": false
29
+ }
30
+ ]
@@ -0,0 +1,25 @@
1
+ {
2
+ "loop_name": "ship-a-draft",
3
+ "evals": [
4
+ {
5
+ "id": "picks-the-generator-before-collecting",
6
+ "prompt": "Run ship-a-draft on this Slack thread — I need something the exec team can read.",
7
+ "assertions": [
8
+ "Chooses the target generator (exec-summary) BEFORE running intake, because the brief is shaped for a target",
9
+ "Runs brief-intake and tags every field explicit / implied / inferred / missing",
10
+ "Runs doc-critique at G4 against the same rubric the generator was held to",
11
+ "Runs output-hygiene last, only once the argument is settled",
12
+ "Reports what output-hygiene did not touch"
13
+ ]
14
+ },
15
+ {
16
+ "id": "major-rewrite-returns-to-intake",
17
+ "prompt": "The critique on my draft came back MAJOR REWRITE. Continue the ship-a-draft wrapper.",
18
+ "assertions": [
19
+ "Routes back to `intake`, not to `draft`, because G4's revise_to names intake",
20
+ "Explains that re-drafting from the same incomplete brief reproduces the same gaps",
21
+ "Does not run output-hygiene on a draft that is about to be rewritten"
22
+ ]
23
+ }
24
+ ]
25
+ }
@@ -104,7 +104,7 @@
104
104
  "adr-generator": { "tier": "standard", "rationale": "Structures a decision into MADR/Nygard. Some judgment on title/consequences; not adversarial." },
105
105
  "architecture-diagrams": { "tier": "standard", "rationale": "Translates prose to diagram syntax. Correctness matters; reasoning is bounded." },
106
106
  "brief-intake": { "tier": "standard", "rationale": "Extraction + tagging [explicit]/[implied]/[inferred]. The tagging needs care — above light, below heavy." },
107
- "deck-builder": { "tier": "standard", "rationale": "Generates pptx content + runs a script. Content shaping, not hard reasoning." },
107
+ "deck-builder": { "tier": "standard", "rationale": "Shapes content, maps a brand template's layouts, and runs a script. Judgment, not hard reasoning." },
108
108
  "design-doc": { "tier": "standard", "rationale": "Synthesizes a design doc from a brief. Escalate to heavy via large-input or ambiguous-input when alternatives are genuinely contested." },
109
109
  "exec-summary": { "tier": "standard", "rationale": "Compression to one page. Needs to keep the right signal; escalate on very long source docs." },
110
110
  "figma-diagrams": { "tier": "standard", "rationale": "API calls + spec generation. Bounded transformation." },
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "skilldrop-cli",
3
- "version": "0.11.9",
3
+ "version": "0.12.1",
4
4
  "description": "Portable AI-agent skills for the deliverables knowledge workers ship \u2014 diagrams, ADRs, PRDs, runbooks, decks, reviews \u2014 installable into Claude Code, Cursor, Kiro, and any IDE that takes custom instructions. One command per skill or per role-based pack.",
5
5
  "author": {
6
6
  "name": "Sanjay Ananthanarayan",
@@ -1,114 +1,181 @@
1
1
  ---
2
2
  name: deck-builder
3
- description: Generate a real PowerPoint (.pptx) file from content, target audience, and a color palette. Produces structurally-appropriate decks (slide count, density, layout choice) tuned for the audience — execs, technical reviewers, sales prospects, investors, internal teams. Use when the user wants an actual editable .pptx, not just an outline.
3
+ description: Generate a real PowerPoint (.pptx) file from content, audience, and either a brand template or a color palette — with charts, tables and images, not only bullets. Slide count, density and layout are tuned to the audience: execs, boards, technical reviewers, sales prospects, investors, internal teams. Use when the user wants an actual editable .pptx rather than an outline, wants their corporate template or brand colours applied, or says "build the deck", "make it a pptx", "use our template".
4
4
  ---
5
5
 
6
6
  # deck-builder
7
7
 
8
- You help the user produce an **actual editable `.pptx` file**, not just an outline. The skill runs `python-pptx` under the hood to materialize slides with a chosen color palette, multiple layout types, and audience-tuned density.
8
+ This skill produces an **actual editable `.pptx` file**, not an outline. It runs `python-pptx`
9
+ to materialise slides — either on a brand template's own masters and layouts, or on the skill's
10
+ built-in design driven by a colour palette.
9
11
 
10
- This skill pairs with two others:
11
- - **[`audience-profile`](../audience-profile/SKILL.md)** — decides how dense / how many / which sections the deck should have
12
- - **[`slide-outliner`](../slide-outliner/SKILL.md)** — drafts the per-slide content before this skill turns it into a `.pptx`
12
+ It pairs with two others:
13
+ - **[`audience-profile`](../audience-profile/SKILL.md)** — decides how dense, how many, which sections
14
+ - **[`slide-outliner`](../slide-outliner/SKILL.md)** — drafts per-slide content before this skill builds it
13
15
 
14
- For a single fast pipeline, use all three in order: profile → outline → build.
16
+ For a single fast pipeline, run all three in order: profile → outline → build.
15
17
 
16
18
  ## How to respond
17
19
 
18
- 1. **Gather three inputs** before generating anything:
19
-
20
- - **Content.** Either a finished outline (from `slide-outliner`), a long doc the user wants compressed into slides, or a list of points. If the content is thin ("here's the topic, you fill in"), pause and ask — *making slides up is the easiest way to make a bad deck*.
21
- - **Audience.** One of: `exec`, `board`, `technical`, `sales`, `internal`, `investor`, `partner`, `customer`. If the user gives a free-form description ("VP of Eng + their staff at a partner"), map to the closest archetype and call out your choice. Use [`audience-profile`](../audience-profile/SKILL.md) for the structural rules.
22
- - **Palette.** Always ask the user before generating — don't pick for them, and don't default silently. Present the choice like this:
23
-
24
- > Pick a palette before I generate the deck:
25
- > - `corporate-blue` — default for B2B / enterprise audiences
26
- > - `monochrome` — restrained / when content is sensitive
27
- > - `vibrant` — internal / sales / pitch decks
28
- > - `dark-mode` — engineering audiences, live demos
29
- > - `editorial` — long-form / read-ahead decks
30
- > - `forest` — calm, nature-leaning
31
- > - `sunset` — warm, narrative-leaning
32
- > - Or give me hex values for `primary` / `secondary` / `accent` / `background` / `text`
33
- > - Or paste your brand colors and I'll map them into the five roles
34
-
35
- If the user gives brand colors as a partial set (e.g. just a primary), derive the missing roles using the rules in [`reference.md`](reference.md#color-palette-principles) and call out what you filled in.
36
-
37
- 2. **Plan the slide list against the audience archetype.** For example:
38
-
39
- | Audience | Slide count | Density | Required sections |
40
- |---|---|---|---|
41
- | `exec` | 6–10 | Low — 3 bullets max | Ask • TL;DR • Business impact • Risks • Ask (closing) |
42
- | `board` | 8–12 | Low — big numbers | Cover • TL;DR • Strategic context • Financials • Risks • Ask |
43
- | `technical` | 12–20 | High — detail welcome | Context • Goals • Proposal (3–5) • Alternatives • Risks • Rollout |
44
- | `sales` | 8–12 | Story arc, visual | Hook • Pain • Solution • Proof • Pricing • Close |
45
- | `internal` | 5–10 | Mixed | Context • Proposal • Discussion topics • Action items |
46
- | `investor` | 10–15 | Polished, narrative | Problem • Market • Product • Traction • Team • Ask |
47
-
48
- The full archetype spec is in [`audience-profile`](../audience-profile/SKILL.md).
49
-
50
- 3. **Build a deck spec.** The spec is a JSON document with this shape — full schema in [`templates/deck-spec.json`](templates/deck-spec.json):
51
-
52
- ```json
53
- {
54
- "title": "ProjectX Migration — Board Update",
55
- "audience": "board",
56
- "palette": { "primary": "#1A2A6C", "accent": "#FDBB2D", ... },
57
- "slides": [
58
- { "layout": "title", "title": "...", "subtitle": "..." },
59
- { "layout": "section", "title": "..." },
60
- { "layout": "content", "title": "...", "bullets": ["..."] },
61
- { "layout": "big_number", "title": "...", "number": "$24M", "caption": "ARR at risk" },
62
- { "layout": "two_column", "title": "...", "left": {...}, "right": {...} },
63
- { "layout": "quote", "quote": "...", "attribution": "..." },
64
- { "layout": "closing", "title": "Approval requested", "subtitle": "..." }
65
- ]
66
- }
67
- ```
68
-
69
- Available layouts: `title`, `section`, `content`, `two_column`, `big_number`, `quote`, `closing`. Most slides should be `content`; sprinkle in `big_number` and `quote` for emphasis.
70
-
71
- 4. **Run the build script** to produce the actual `.pptx`:
72
-
73
- ```bash
74
- # Claude Code
75
- python3 "${CLAUDE_SKILL_DIR}/scripts/build_deck.py" /tmp/deck-spec.json -o ./out/deck.pptx
76
-
77
- # Other IDEs (from the skill folder)
78
- cd path/to/deck-builder && python3 scripts/build_deck.py /tmp/deck-spec.json -o ./out/deck.pptx
79
- ```
80
-
81
- The script writes a real `.pptx` the user can open in PowerPoint, Keynote, or Google Slides and edit further. Tell the user where the file landed and what to do next.
82
-
83
- 5. **Recommend post-generation refinement.** A generated deck is a strong first draft, not a finished artifact. Always suggest:
84
-
85
- - Reviewing speaker notes (they were written by the agent — verify before presenting)
86
- - Replacing any placeholder images with real visuals
87
- - Doing one "audience pass" — read every slide title in order, does the *narrative* make sense to that specific audience?
20
+ ### 1. Run the setup block — once
21
+
22
+ Ask everything in **one** message, with defaults already chosen, so the user can answer with a
23
+ single line or say "go". Never trickle out four separate questions, and never generate a deck
24
+ with the design silently defaulted.
25
+
26
+ > Before I build, confirm these — reply "go" to take the defaults:
27
+ > 1. **Audience** — `exec` · `board` · `technical` · `sales` · `internal` · `investor` · `partner` · `customer`
28
+ > 2. **Format** — live presentation / read-ahead / async share, **how many minutes**, and **16:9** (default) or **4:3**
29
+ > 3. **Design** — either
30
+ > - a **template**: path to a corporate `.pptx` / `.potx`, and the deck inherits its masters, fonts, colours and slide size; or
31
+ > - a **palette**: `corporate-blue` (default for B2B) · `monochrome` · `vibrant` · `dark-mode` · `editorial` · `forest` · `sunset`, or brand hex values for `primary` / `secondary` / `accent` / `background` / `text`
32
+ > 4. **Anything to embed** — numbers to chart, a table, diagram PNGs
33
+
34
+ Rules for reading the answers:
35
+
36
+ - **Content is the one hard input.** If the user supplied only a topic, stop and ask for the
37
+ material. Inventing the content is the easiest way to produce a bad deck.
38
+ - **A free-form audience maps to the closest archetype** — "VP of Eng and their staff at a
39
+ partner" → `technical`, stated out loud. Mixed audience → the least technical archetype, with
40
+ the rest served by appendix slides.
41
+ - **Time sets slide count**, not the other way round: 1.5–2 minutes per slide live. 30 minutes →
42
+ 12–15 slides including cover and close.
43
+ - **A partial brand palette gets completed**, using the rules in
44
+ [`reference.md`](reference.md#color-palette-principles) — say which roles were filled in.
45
+ - **Template beats palette** for chrome; the palette still colours charts, tables, big numbers
46
+ and quote bars, so ask for brand hexes even when a template is supplied.
47
+
48
+ **Non-interactive runs** (subagent, CI, headless): audience, format, time and palette degrade to
49
+ `[assumption]` lines stated at the top of the response — default `exec`, live, 16:9,
50
+ `corporate-blue`. Missing *content* does not degrade: emit `BLOCKED: need deck content
51
+ (outline, doc, or point list)` and build nothing.
52
+
53
+ ### 2. Plan the slide list against the audience archetype
54
+
55
+ | Audience | Slide count | Density | Required sections |
56
+ |---|---|---|---|
57
+ | `exec` | 6–10 | Low — 3 bullets max | Ask • TL;DR • Business impact • Risks • Ask (closing) |
58
+ | `board` | 8–12 | Low — big numbers | Cover • TL;DR • Strategic context • Financials • Risks • Ask |
59
+ | `technical` | 12–20 | High — detail welcome | Context • Goals • Proposal (3–5) • Alternatives • Risks • Rollout |
60
+ | `sales` | 8–12 | Story arc, visual | Hook • Pain • Solution • Proof • Pricing • Close |
61
+ | `internal` | 5–10 | Mixed | Context • Proposal • Discussion topics • Action items |
62
+ | `investor` | 10–15 | Polished, narrative | Problem • Market • Product • Traction • Team • Ask |
63
+
64
+ Full archetype spec: [`audience-profile`](../audience-profile/SKILL.md). Slide-count budgets per
65
+ format and time: [`reference.md`](reference.md#slide-count-budgets).
66
+
67
+ ### 3. Build a deck spec
68
+
69
+ A JSON document — full schema, with every layout and the template block, in
70
+ [`templates/deck-spec.json`](templates/deck-spec.json):
71
+
72
+ ```json
73
+ {
74
+ "title": "ProjectX Migration — Board Update",
75
+ "audience": "board",
76
+ "aspect": "16:9",
77
+ "template": "./brand/acme-master.potx",
78
+ "layout_map": { "title": "Title Slide", "content": "Title and Content" },
79
+ "palette": { "primary": "#1A2A6C", "accent": "#FDBB2D" },
80
+ "slides": [
81
+ { "layout": "title", "title": "...", "subtitle": "...", "presenter": "...", "date": "..." },
82
+ { "layout": "content", "title": "...", "bullets": ["..."], "notes": "..." },
83
+ { "layout": "chart", "title": "...", "takeaway": "...", "chart": { "type": "column", "categories": ["..."], "series": [{ "name": "...", "values": [1, 2] }] }, "source": "..." },
84
+ { "layout": "table", "title": "...", "columns": ["..."], "rows": [["..."]] },
85
+ { "layout": "image", "title": "...", "image": "./diagram.png", "position": "right", "bullets": ["..."] },
86
+ { "layout": "big_number", "title": "...", "number": "$24M", "caption": "ARR at risk" },
87
+ { "layout": "closing", "title": "Approval requested", "subtitle": "..." }
88
+ ]
89
+ }
90
+ ```
91
+
92
+ Ten layouts: `title`, `section`, `content`, `two_column`, `big_number`, `quote`, `image`,
93
+ `table`, `chart`, `closing`. Most slides are `content`; `chart`, `table` and `big_number` carry
94
+ the evidence; `quote` and `image` break the rhythm. Which content shape earns which layout:
95
+ [`reference.md`](reference.md#layout--content-matching).
96
+
97
+ Every slide gets a `notes` field. Slide numbers appear automatically past 10 slides — override
98
+ with `"slide_numbers": false`.
99
+
100
+ ### 4. Build from the user's template when there is one
101
+
102
+ A corporate template is the difference between a deck that gets presented and one that gets
103
+ rebuilt by hand. When the user names one:
104
+
105
+ ```bash
106
+ # Claude Code — list the template's layouts first
107
+ python3 "${CLAUDE_SKILL_DIR}/scripts/build_deck.py" --list-layouts ~/brand/acme-master.potx
108
+
109
+ # Other IDEs (from the skill folder)
110
+ python3 scripts/build_deck.py --list-layouts ~/brand/acme-master.potx
111
+ ```
112
+
113
+ Map each logical layout to one of the printed names in `layout_map`, then build. The template's
114
+ masters, theme fonts, colours, logos and slide size are inherited; any sample slides it ships
115
+ with are dropped. A logical layout left out of the map falls back to the skill's built-in
116
+ design on the template's blank layout — acceptable for `big_number` or `quote`, wrong for
117
+ `title` and `content`, which is where the branding shows.
118
+
119
+ `.potx` and `.pptx` both work. Templates carry no charts or tables of their own, so those are
120
+ drawn into whatever content region the mapped layout defines.
121
+
122
+ ### 5. Run the build script
123
+
124
+ ```bash
125
+ # Claude Code
126
+ python3 "${CLAUDE_SKILL_DIR}/scripts/build_deck.py" /tmp/deck-spec.json -o ./out/deck.pptx
127
+
128
+ # Other IDEs (from the skill folder)
129
+ cd path/to/deck-builder && python3 scripts/build_deck.py /tmp/deck-spec.json -o ./out/deck.pptx
130
+ ```
131
+
132
+ Add `--strict` to fail the build on a missing or unreadable image instead of drawing a
133
+ placeholder box — use it in CI, not in a conversation.
134
+
135
+ **Read the warnings.** The script degrades rather than crashing: a missing image, a short data
136
+ series, an unresolvable template layout each produce a warning and a visible fallback. Report
137
+ every warning to the user with the file path; never present a deck with an unexplained
138
+ placeholder box in it.
139
+
140
+ ### 6. Recommend the refinement pass
141
+
142
+ A generated deck is a strong first draft. Always tell the user to:
143
+
144
+ - Review the speaker notes — the agent wrote them, and they get read aloud
145
+ - Replace any placeholder box with the real diagram
146
+ - Do one audience pass: read every slide title in order, does the *narrative* land for that audience?
147
+ - Run [`doc-critique`](../doc-critique/SKILL.md) against the deck rubric before it goes out
88
148
 
89
149
  ## Useful references
90
150
 
91
- - [`reference.md`](reference.md) — Color palette principles + layout-vs-content matching guide
92
- - [`templates/deck-spec.json`](templates/deck-spec.json) — Full JSON schema with every layout demonstrated
93
- - [`templates/palettes.json`](templates/palettes.json) — Pre-built color palettes (corporate-blue, monochrome, vibrant, dark-mode, editorial, forest, sunset)
94
- - [`examples/exec-board-update.md`](examples/exec-board-update.md) — Worked example: brief → spec → resulting deck
95
- - [`scripts/build_deck.py`](scripts/build_deck.py) — The generator (don't edit unless extending layouts)
151
+ - [`reference.md`](reference.md) — palette principles, layout-vs-content matching, chart and table rules, density and slide-count budgets
152
+ - [`templates/deck-spec.json`](templates/deck-spec.json) — full JSON schema with every layout and the template block
153
+ - [`templates/palettes.json`](templates/palettes.json) — the seven presets
154
+ - [`examples/exec-board-update.md`](examples/exec-board-update.md) — worked example: brief → spec → deck
155
+ - [`examples/templated-brand-deck.md`](examples/templated-brand-deck.md) — worked example: corporate `.potx` → layout map → deck
156
+ - [`scripts/build_deck.py`](scripts/build_deck.py) — the generator (don't edit unless adding a layout)
96
157
 
97
158
  ## Quality bar
98
159
 
99
- - **Title slide isn't blank** — it has a real title, subtitle, presenter, date.
160
+ - **Design is chosen by the user, never silently defaulted** — a template path or a named palette, confirmed in the setup block.
161
+ - **A supplied template is actually inherited** — `layout_map` covers `title`, `section`, `content` and `closing` at minimum. A branded deck rendered on the blank layout has thrown away the branding.
162
+ - **Title slide isn't blank** — real title, subtitle, presenter, date.
163
+ - **Numbers are charted, not bulleted** — three or more comparable figures belong in a `chart` or a `table`, not a bullet list.
164
+ - **Every chart and table cites its `source`** and uses only figures from the user's material.
165
+ - **Bullet density matches audience** — `exec`, *3 bullets max*, period. `technical`, up to 6 when the content needs it.
166
+ - **Speaker notes on every slide** — even one sentence.
100
167
  - **Section dividers used sparingly** — at most one every 4–5 content slides.
101
- - **Big numbers are real** — never invent statistics for emphasis. If the user gave you a number, use it; otherwise pick a different layout.
102
- - **Bullet density matches audience** — for `exec`, *max 3 bullets per slide*, period. For `technical`, up to 6 if the content really needs it.
103
- - **Speaker notes for every slide** — even one sentence. They're how the presenter remembers what's *between* the bullets.
104
- - **Color palette is consistent** — don't mix in random colors that aren't in the palette.
105
- - **No surprise pages** — first and last slides match in style; the deck reads as one document.
168
+ - **Zero unexplained warnings** — every warning the script emits is fixed or reported to the user.
169
+ - **Colour is consistent** — palette roles only, no stray colours; text-on-background contrast ≥ 4.5:1.
106
170
 
107
171
  ## Anti-patterns to avoid
108
172
 
109
- - ❌ Generating a deck without confirming the audience. The same content for execs vs engineers is a different deck.
110
- - ❌ Writing fake numbers to fill a `big_number` slide.
111
- - ❌ Defaulting to bullets when a `big_number`, `quote`, or `two_column` would land harder.
112
- - ❌ Skipping speaker notes because the user "knows the topic" — they're for the reviewer/co-presenter too.
113
- - ❌ Choosing low-contrast palettes (light grey text on white). If the palette has poor contrast, swap to a sensible default and explain.
114
- - ❌ More than ~20 slides for any audience. If you can't make the point in 20, the deck isn't the right format.
173
+ - ❌ Ignoring a template the user already named, or asking for a palette after they supplied one. The template is the answer to "what should this look like".
174
+ - ❌ Mapping every logical layout onto the template's one title-and-bullets layout. That is a branded deck that still looks generated.
175
+ - ❌ Generating without confirming audience. The same content for execs and engineers is a different deck.
176
+ - ❌ Inventing a statistic to fill a `big_number`, or a series to fill a chart. No source, no chart.
177
+ - ❌ A table with 20 rows. Over ~12 it is an appendix or a spreadsheet, not a slide.
178
+ - ❌ Passing an SVG or EMF diagram to `image` — `python-pptx` reads raster only. Convert to PNG first.
179
+ - ❌ Shipping the deck with a grey placeholder box still in it because the warning went unread.
180
+ - ❌ Defaulting to bullets when a `big_number`, `chart`, `quote` or `two_column` would land harder.
181
+ - ❌ More than ~20 slides for any audience. If the point needs 21, the deck is the wrong format.