skilldrop-cli 0.12.0 → 0.12.2
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 +1 -1
- package/bin/skilldrop.js +38 -1
- package/model-routing.json +1 -1
- package/package.json +1 -1
- package/skills/deck-builder/SKILL.md +160 -93
- package/skills/deck-builder/evals/eval_queries.json +12 -32
- package/skills/deck-builder/evals/evals.json +23 -0
- package/skills/deck-builder/examples/templated-brand-deck.md +148 -0
- package/skills/deck-builder/manifest.json +5 -5
- package/skills/deck-builder/reference.md +88 -0
- package/skills/deck-builder/scripts/build_deck.py +863 -140
- package/skills/deck-builder/templates/deck-spec.json +69 -1
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 +
|
|
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). |
|
package/bin/skilldrop.js
CHANGED
|
@@ -55,6 +55,8 @@ Usage:
|
|
|
55
55
|
skilldrop scan [<skill...>] [--from <src>] supply-chain scan — flag network/exec/credential
|
|
56
56
|
patterns in scripts and injection-shaped instructions
|
|
57
57
|
in SKILL.md before you trust a catalog (RFC-0022)
|
|
58
|
+
skilldrop bootstrap add the skilldrop marketplace to ~/.claude/settings.json
|
|
59
|
+
(idempotent — safe to run in onboarding scripts)
|
|
58
60
|
|
|
59
61
|
Catalogs:
|
|
60
62
|
(default) the catalog bundled with this package
|
|
@@ -1153,9 +1155,44 @@ function validateCmd(args) {
|
|
|
1153
1155
|
console.log(`OK: ${names.length} skills in catalog '${cat.source}' pass the structural check.`);
|
|
1154
1156
|
}
|
|
1155
1157
|
|
|
1158
|
+
/* ---------- bootstrap (enterprise distribution) ----------
|
|
1159
|
+
Writes the skilldrop marketplace into ~/.claude/settings.json so every Claude Code
|
|
1160
|
+
session on this machine discovers the catalogue without any per-session /plugin command.
|
|
1161
|
+
Idempotent: safe to run in a provisioning script or onboarding runbook. */
|
|
1162
|
+
const BOOTSTRAP_MARKETPLACE_KEY = "skilldrop";
|
|
1163
|
+
const BOOTSTRAP_GITHUB_OWNER = "sananthanarayan";
|
|
1164
|
+
const BOOTSTRAP_GITHUB_REPO = "skilldrop";
|
|
1165
|
+
|
|
1166
|
+
function bootstrap() {
|
|
1167
|
+
const settingsPath = path.join(os.homedir(), ".claude", "settings.json");
|
|
1168
|
+
let data = {};
|
|
1169
|
+
const raw = readIfPresent(settingsPath, null);
|
|
1170
|
+
if (raw !== null) {
|
|
1171
|
+
try { data = JSON.parse(raw); }
|
|
1172
|
+
catch (e) { die(`${settingsPath} is not valid JSON — fix it first, then re-run bootstrap`); }
|
|
1173
|
+
}
|
|
1174
|
+
data.extraKnownMarketplaces = data.extraKnownMarketplaces || {};
|
|
1175
|
+
const entry = { source: { source: "github", owner: BOOTSTRAP_GITHUB_OWNER, repo: BOOTSTRAP_GITHUB_REPO } };
|
|
1176
|
+
const existing = data.extraKnownMarketplaces[BOOTSTRAP_MARKETPLACE_KEY];
|
|
1177
|
+
if (existing && JSON.stringify(existing) === JSON.stringify(entry)) {
|
|
1178
|
+
console.log(`already configured: ${BOOTSTRAP_MARKETPLACE_KEY} -> github:${BOOTSTRAP_GITHUB_OWNER}/${BOOTSTRAP_GITHUB_REPO}`);
|
|
1179
|
+
console.log(`\nIn any Claude Code session:\n /plugin install <pack>@${BOOTSTRAP_MARKETPLACE_KEY}`);
|
|
1180
|
+
return;
|
|
1181
|
+
}
|
|
1182
|
+
data.extraKnownMarketplaces[BOOTSTRAP_MARKETPLACE_KEY] = entry;
|
|
1183
|
+
fs.mkdirSync(path.dirname(settingsPath), { recursive: true });
|
|
1184
|
+
fs.writeFileSync(settingsPath, JSON.stringify(data, null, 2) + "\n");
|
|
1185
|
+
console.log(`configured ${settingsPath}:`);
|
|
1186
|
+
console.log(` extraKnownMarketplaces.${BOOTSTRAP_MARKETPLACE_KEY} -> github:${BOOTSTRAP_GITHUB_OWNER}/${BOOTSTRAP_GITHUB_REPO}`);
|
|
1187
|
+
console.log(`\nIn any Claude Code session, install a role pack:\n /plugin install solution-architect@${BOOTSTRAP_MARKETPLACE_KEY}`);
|
|
1188
|
+
console.log(` /plugin install dev-team@${BOOTSTRAP_MARKETPLACE_KEY}`);
|
|
1189
|
+
console.log(` /plugin install ai-engineering@${BOOTSTRAP_MARKETPLACE_KEY}`);
|
|
1190
|
+
console.log(`\nOr install the full catalogue:\n /plugin install ${BOOTSTRAP_MARKETPLACE_KEY}@${BOOTSTRAP_MARKETPLACE_KEY}`);
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1156
1193
|
const args = parseArgs(process.argv.slice(2));
|
|
1157
1194
|
const cmd = args._.shift();
|
|
1158
|
-
const commands = { list, info, packs: listPacks, agents: listAgents, loops: listLoops, install, update, outdated, uninstall, validate: validateCmd, scan };
|
|
1195
|
+
const commands = { list, info, packs: listPacks, agents: listAgents, loops: listLoops, install, update, outdated, uninstall, validate: validateCmd, scan, bootstrap };
|
|
1159
1196
|
if (!cmd || cmd === "help" || args.flags.help) console.log(HELP);
|
|
1160
1197
|
else if (commands[cmd]) commands[cmd](args);
|
|
1161
1198
|
else die(`unknown command '${cmd}' — run: skilldrop help`);
|
package/model-routing.json
CHANGED
|
@@ -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": "
|
|
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.12.
|
|
3
|
+
"version": "0.12.2",
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
11
|
-
- **[`audience-profile`](../audience-profile/SKILL.md)** — decides how dense
|
|
12
|
-
- **[`slide-outliner`](../slide-outliner/SKILL.md)** — drafts
|
|
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,
|
|
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.
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
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) —
|
|
92
|
-
- [`templates/deck-spec.json`](templates/deck-spec.json) —
|
|
93
|
-
- [`templates/palettes.json`](templates/palettes.json) —
|
|
94
|
-
- [`examples/exec-board-update.md`](examples/exec-board-update.md) —
|
|
95
|
-
- [`
|
|
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
|
-
- **
|
|
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
|
-
- **
|
|
102
|
-
- **
|
|
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
|
-
- ❌
|
|
110
|
-
- ❌
|
|
111
|
-
- ❌
|
|
112
|
-
- ❌
|
|
113
|
-
- ❌
|
|
114
|
-
- ❌
|
|
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.
|
|
@@ -1,34 +1,14 @@
|
|
|
1
1
|
[
|
|
2
|
-
{
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
},
|
|
6
|
-
{
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
},
|
|
10
|
-
{
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
}
|
|
14
|
-
{
|
|
15
|
-
"query": "I need a real deck file, not an outline",
|
|
16
|
-
"should_trigger": true
|
|
17
|
-
},
|
|
18
|
-
{
|
|
19
|
-
"query": "Just outline the slides — I'll build the deck myself",
|
|
20
|
-
"should_trigger": false
|
|
21
|
-
},
|
|
22
|
-
{
|
|
23
|
-
"query": "Write a one-page summary for executives",
|
|
24
|
-
"should_trigger": false
|
|
25
|
-
},
|
|
26
|
-
{
|
|
27
|
-
"query": "Which audience archetype should I target and what are its rules?",
|
|
28
|
-
"should_trigger": false
|
|
29
|
-
},
|
|
30
|
-
{
|
|
31
|
-
"query": "Critique the deck I already made",
|
|
32
|
-
"should_trigger": false
|
|
33
|
-
}
|
|
2
|
+
{ "query": "Build me a PowerPoint from this content", "should_trigger": true },
|
|
3
|
+
{ "query": "Generate a .pptx deck for this exec presentation", "should_trigger": true },
|
|
4
|
+
{ "query": "Turn this into actual slides I can present, with our brand colors", "should_trigger": true },
|
|
5
|
+
{ "query": "I need a real deck file, not an outline", "should_trigger": true },
|
|
6
|
+
{ "query": "Build the deck on our corporate template — marketing rejects anything else", "should_trigger": true },
|
|
7
|
+
{ "query": "Use our .potx master for this QBR deck", "should_trigger": true },
|
|
8
|
+
{ "query": "Put these quarterly numbers on a slide as a chart", "should_trigger": true },
|
|
9
|
+
{ "query": "Just outline the slides — I'll build the deck myself", "should_trigger": false },
|
|
10
|
+
{ "query": "Write a one-page summary for executives", "should_trigger": false },
|
|
11
|
+
{ "query": "Which audience archetype should I target and what are its rules?", "should_trigger": false },
|
|
12
|
+
{ "query": "Critique the deck I already made", "should_trigger": false },
|
|
13
|
+
{ "query": "Extract the text out of this existing .pptx so I can email it", "should_trigger": false }
|
|
34
14
|
]
|
|
@@ -6,12 +6,35 @@
|
|
|
6
6
|
"prompt": "Build a .pptx from this content for an exec audience, using our brand palette (navy/white).",
|
|
7
7
|
"assertions": [
|
|
8
8
|
"A real .pptx file is produced, not an outline",
|
|
9
|
+
"Audience, format and design are confirmed in a single setup block rather than as a trickle of separate questions",
|
|
9
10
|
"The title slide carries a real title, subtitle, presenter, and date — never left blank",
|
|
10
11
|
"Section dividers appear sparingly, at most one every 4-5 content slides",
|
|
11
12
|
"Big-number layouts use only numbers the user supplied; no statistic is invented for emphasis",
|
|
12
13
|
"Bullet density matches the stated audience rather than a fixed default",
|
|
13
14
|
"The requested palette is applied rather than the default theme"
|
|
14
15
|
]
|
|
16
|
+
},
|
|
17
|
+
{
|
|
18
|
+
"id": 2,
|
|
19
|
+
"prompt": "Build the Q3 QBR deck on our corporate template at ~/brand/acme-master.potx — 25 minutes, live, partner audience.",
|
|
20
|
+
"assertions": [
|
|
21
|
+
"The template's layouts are listed with --list-layouts before the spec is written, rather than layout names being guessed",
|
|
22
|
+
"The spec sets `template` and a `layout_map` covering at least title, section, content and closing",
|
|
23
|
+
"A palette is still collected, because the template does not colour charts, tables or big numbers",
|
|
24
|
+
"`aspect` is not fought with — the template's own slide size is accepted and stated",
|
|
25
|
+
"Slide count is derived from the 25-minute budget at roughly 2 minutes per slide"
|
|
26
|
+
]
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": 3,
|
|
30
|
+
"prompt": "Here are our renewal rates for the last three quarters (88%, 91%, 94%) and the SLA table from the contract. Put them in the deck.",
|
|
31
|
+
"assertions": [
|
|
32
|
+
"The three comparable figures become a `chart` slide, not a bullet list",
|
|
33
|
+
"The chart carries a `takeaway` sentence and a `source`",
|
|
34
|
+
"The SLA data becomes a `table` slide rather than aligned bullets",
|
|
35
|
+
"No figure appears that the user did not supply",
|
|
36
|
+
"Any build warning (missing image, short series) is reported to the user with its path rather than left in the file"
|
|
37
|
+
]
|
|
15
38
|
}
|
|
16
39
|
]
|
|
17
40
|
}
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
# Example: Q3 partner QBR on the company's own PowerPoint template
|
|
2
|
+
|
|
3
|
+
**Prompt the user gave:** *"Make the Q3 QBR deck for Northwind. Use our corporate template at
|
|
4
|
+
`~/brand/acme-master.potx` — it's mandatory, marketing rejects anything else. 25 minutes, live,
|
|
5
|
+
with the partner's CTO and two of their architects in the room. Renewal rate went 88 → 91 → 94%
|
|
6
|
+
over the last three quarters, ticket volume is down 31%, and we want to land the co-sell
|
|
7
|
+
expansion ask. Brand colours are #0B3D6B and #E8A33D."*
|
|
8
|
+
|
|
9
|
+
## Step 1 — Setup block, answered in one pass
|
|
10
|
+
|
|
11
|
+
| Input | Value | How it was resolved |
|
|
12
|
+
|---|---|---|
|
|
13
|
+
| Content | Renewal trend, ticket volume, expansion ask | Supplied |
|
|
14
|
+
| Audience | `partner` | Stated ("partner's CTO and architects") |
|
|
15
|
+
| Format | Live, 25 min → 12–14 slides | Stated; slide count derived at ~2 min/slide |
|
|
16
|
+
| Aspect | From the template | `aspect` ignored — the `.potx` is 16:9 |
|
|
17
|
+
| Design | `~/brand/acme-master.potx` + brand hexes | Template for chrome, palette for charts |
|
|
18
|
+
| Embeds | Renewal trend (chart), SLA table | Three comparable figures ⇒ chart, not bullets |
|
|
19
|
+
|
|
20
|
+
The palette is still collected: the template does not colour charts, tables or big numbers.
|
|
21
|
+
`primary: #0B3D6B`, `accent: #E8A33D`; `secondary`, `background` and `text` derived per
|
|
22
|
+
[`reference.md`](../reference.md#color-palette-principles) and called out to the user.
|
|
23
|
+
|
|
24
|
+
## Step 2 — Read the template's layouts before writing the spec
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
python3 "${CLAUDE_SKILL_DIR}/scripts/build_deck.py" --list-layouts ~/brand/acme-master.potx
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
acme-master.potx — slide size 13.33in x 7.50in
|
|
32
|
+
[0] Acme Cover
|
|
33
|
+
[1] Acme Section Break
|
|
34
|
+
[2] Acme Title and Body
|
|
35
|
+
[3] Acme Two Column
|
|
36
|
+
[4] Acme Statement
|
|
37
|
+
[5] Acme Full Bleed Image
|
|
38
|
+
[6] Blank
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
The names are the template's, not PowerPoint's defaults — which is exactly why the map is read
|
|
42
|
+
from the file rather than guessed.
|
|
43
|
+
|
|
44
|
+
## Step 3 — The deck spec
|
|
45
|
+
|
|
46
|
+
```json
|
|
47
|
+
{
|
|
48
|
+
"title": "Northwind QBR — Q3 FY26",
|
|
49
|
+
"audience": "partner",
|
|
50
|
+
"template": "~/brand/acme-master.potx",
|
|
51
|
+
"layout_map": {
|
|
52
|
+
"title": "Acme Cover",
|
|
53
|
+
"section": "Acme Section Break",
|
|
54
|
+
"content": "Acme Title and Body",
|
|
55
|
+
"two_column": "Acme Two Column",
|
|
56
|
+
"big_number": "Acme Statement",
|
|
57
|
+
"quote": "Acme Statement",
|
|
58
|
+
"chart": "Acme Statement",
|
|
59
|
+
"table": "Acme Statement",
|
|
60
|
+
"image": "Acme Full Bleed Image",
|
|
61
|
+
"closing": "Acme Statement"
|
|
62
|
+
},
|
|
63
|
+
"palette": {
|
|
64
|
+
"primary": "#0B3D6B",
|
|
65
|
+
"secondary": "#4A6E94",
|
|
66
|
+
"accent": "#E8A33D",
|
|
67
|
+
"background": "#FFFFFF",
|
|
68
|
+
"text": "#222222"
|
|
69
|
+
},
|
|
70
|
+
"slides": [
|
|
71
|
+
{
|
|
72
|
+
"layout": "title",
|
|
73
|
+
"title": "Northwind × Acme — Q3 business review",
|
|
74
|
+
"subtitle": "Renewals, service quality, and the FY27 co-sell ask",
|
|
75
|
+
"presenter": "Jane Roe, Partner Director",
|
|
76
|
+
"date": "2026-09-30",
|
|
77
|
+
"notes": "Thank them for the quarter before the first slide. Name the ask now so it isn't a surprise at slide 12."
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
"layout": "chart",
|
|
81
|
+
"title": "Renewal rate has climbed every quarter this year",
|
|
82
|
+
"takeaway": "Three consecutive quarters of improvement — the joint success plan is what changed.",
|
|
83
|
+
"chart": {
|
|
84
|
+
"type": "line",
|
|
85
|
+
"categories": ["Q1 FY26", "Q2 FY26", "Q3 FY26"],
|
|
86
|
+
"series": [{ "name": "Renewal rate (%)", "values": [88, 91, 94] }],
|
|
87
|
+
"number_format": "0\"%\""
|
|
88
|
+
},
|
|
89
|
+
"source": "Northwind CS dashboard, 30 Sep 2026",
|
|
90
|
+
"notes": "Let them claim the win — ask their CTO what drove Q2. The answer is usually the thing to double down on in FY27."
|
|
91
|
+
},
|
|
92
|
+
{
|
|
93
|
+
"layout": "big_number",
|
|
94
|
+
"title": "Support load is down as adoption is up",
|
|
95
|
+
"number": "-31%",
|
|
96
|
+
"caption": "Ticket volume vs. Q3 FY25, on 2.4× the seat count",
|
|
97
|
+
"notes": "The pairing is the point: more users, fewer tickets. Pause after saying it."
|
|
98
|
+
},
|
|
99
|
+
{
|
|
100
|
+
"layout": "table",
|
|
101
|
+
"title": "SLA performance against contract",
|
|
102
|
+
"columns": ["Metric", "Contracted", "Q3 actual", "Status"],
|
|
103
|
+
"rows": [
|
|
104
|
+
["Availability", "99.9%", "99.97%", "Met"],
|
|
105
|
+
["P1 response", "15 min", "9 min", "Met"],
|
|
106
|
+
["P1 resolution", "4 hrs", "3h 10m", "Met"],
|
|
107
|
+
["Change failure", "< 5%", "6.2%", "Missed"]
|
|
108
|
+
],
|
|
109
|
+
"caption": "Change-failure remediation plan on the next slide.",
|
|
110
|
+
"notes": "Do not skip the missed row. Naming it before they do is what makes the other three credible."
|
|
111
|
+
},
|
|
112
|
+
{
|
|
113
|
+
"layout": "closing",
|
|
114
|
+
"title": "Ask: co-sell motion for FY27, two named accounts each",
|
|
115
|
+
"subtitle": "Kick-off 15 Oct, joint pipeline review monthly",
|
|
116
|
+
"notes": "Land on the ask. Get the kick-off date agreed in the room, not in follow-up email."
|
|
117
|
+
}
|
|
118
|
+
]
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
*(Abridged — the full deck is 13 slides; the four above are the ones that show the new layouts.)*
|
|
123
|
+
|
|
124
|
+
## Step 4 — Build
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
python3 "${CLAUDE_SKILL_DIR}/scripts/build_deck.py" /tmp/northwind-qbr.json -o ./out/northwind-qbr.pptx
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
```
|
|
131
|
+
template: dropped 2 sample slide(s), kept masters and layouts
|
|
132
|
+
wrote ./out/northwind-qbr.pptx (13 slides, template)
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
No warnings, so nothing to report. Had the SLA table's diagram been an `.svg`, the build would
|
|
136
|
+
have drawn a placeholder box and warned — which gets reported to the user with the path, not
|
|
137
|
+
quietly shipped.
|
|
138
|
+
|
|
139
|
+
## What the template bought
|
|
140
|
+
|
|
141
|
+
| Without the template | With it |
|
|
142
|
+
|---|---|
|
|
143
|
+
| Calibri, generated-looking cover | Acme's typeface, cover, and logo on every slide |
|
|
144
|
+
| Palette-coloured title bars | The master's own chrome |
|
|
145
|
+
| Marketing sends it back | Passes brand review unchanged |
|
|
146
|
+
|
|
147
|
+
The palette still did real work: the line chart, the `-31%`, and the table header are brand
|
|
148
|
+
colours because `palette` was collected *alongside* the template, not instead of it.
|