| name | strategy-map |
| description | Classify each slide's rendering strategy (full_render, full_bleed, background, backdrop, pragmatic_composition, composed) and generate image prompts via the prompt-engineer agent. |
/strategy-map
Classify rendering strategies for each slide and produce the StrategyMap contract. This is Step 3.5 in the pipeline — invoked after the SlideOutline is finalised and before image generation.
Prerequisites
./tmp/deck/outline.json (SlideOutline)
./tmp/deck/style-guide.json (StyleGuide)
./tmp/deck/brand-profile.json (BrandProfile) — optional
What It Does
-
Reads the SlideOutline and classifies each slide into a rendering strategy:
- full_render — entire slide generated as one AI image with a programmatic title overlay and footer logo on top (title, section divider, closing, sparse content)
- full_bleed — operator-opt-in only — image IS the slide, ZERO chrome: no title, no body, no footer logo (issue #88). Use for the infographic-narrative register where every slide is edge-to-edge. See "Opting into full_bleed" below.
- background — atmospheric AI background + text in template zones (5 variants: left_panel, right_panel, bottom_bar, top_band, center_float)
- backdrop — structured AI scene + vision post-analysis for text positioning (Claude Code vision-analyst agent)
- pragmatic_composition — individual AI-generated elements assembled at exact positions with text labels
- composed — standard PptxGenJS assembly (diagrams, charts, code)
backdrop_render retained for backward compatibility (maps to background with left_panel)
-
Presents the strategy map to the Speaker with rationale per slide
-
Accepts Speaker overrides for individual slides
-
Saves the approved strategy map to ./tmp/deck/strategy-map.json
Plugin Setup
PLUGIN_ROOT=$(python3 -c "
from pathlib import Path
import sys, os
if os.environ.get('JACK_TAR_DECKHAND_ROOT'):
print(os.environ['JACK_TAR_DECKHAND_ROOT']); sys.exit()
home = Path.home()
for base in [home / '.claude' / 'plugins' / 'cache']:
for p in base.rglob('jack-tar-deckhand/.claude-plugin/plugin.json'):
print(str(p.parent.parent)); sys.exit()
dev = Path.cwd() / 'plugins' / 'jack-tar-deckhand'
if dev.exists():
print(str(dev)); sys.exit()
print('NOT_FOUND')
" 2>/dev/null)
if [ -z "$PLUGIN_ROOT" ] || [ "$PLUGIN_ROOT" = "NOT_FOUND" ]; then echo "ERROR: jack-tar-deckhand not found" && exit 1; fi
Usage
PYTHONPATH="$PLUGIN_ROOT" python3 -c "
from src.slide_prompt_composer import build_strategy_map, save_strategy_map
import json
with open('./tmp/deck/outline.json') as f:
outline = json.load(f)
strategy_map = build_strategy_map(outline)
save_strategy_map('./tmp/deck', strategy_map)
print(json.dumps(strategy_map, indent=2))
"
Speaker Interaction
Present the strategy map as a table:
| Slide | Type | Strategy | Rationale |
|---|
| 1 | title | full_render | Short text, dramatic visual |
| 2 | content | background | 4 bullets — AI background + text overlay in bottom_bar zone |
| 3 | content | pragmatic_composition | 4 labeled elements in grid — independent images + precise positioning |
| 4 | diagram | composed | Precise labels require programmatic rendering |
| 5 | content | backdrop | Rich scene with vision-detected text placement |
Creative vision spend surface (#113 AC1) — MANDATORY before asking for approval
If the strategy map contains ANY slide with strategy: creative_vision, run the per-slide cost summariser BEFORE presenting the approval table. The operator sees explicit per-slide cost bands plus a deck-level totals row:
PYTHONPATH="$PLUGIN_ROOT" python3 -c "
from src.creative_vision.cost_estimator import summarise_creative_vision_spend
from src.slide_prompt_composer import load_strategy_map
import json
smap = load_strategy_map('./tmp/deck')
summary = summarise_creative_vision_spend(smap)
print(summary['summary_markdown'])
print()
print(f\"DECK SUMMARY: {summary['slide_count']} creative_vision slide(s); \"
f\"projected spend \${summary['total_min_cost_usd']:.2f} - \${summary['total_max_cost_usd']:.2f}; \"
f\"expected {summary['total_gate_band'][0]}-{summary['total_gate_band'][1]} operator gates.\")
"
Render the markdown table to the operator, then ask explicitly:
"These N creative_vision slides will absorb approximately total_gate_band operator gates and $total_min – $total_max of cloud spend. Confirm or change strategy?"
If the operator declines on cost grounds, offer fallback strategies for the over-budget slides:
- composed — no AI image cost; standard PptxGenJS assembly. Use when the slide content is genuinely about diagrams/charts/code.
- backdrop — AI background + structured text in template zones. Costs ~$0.067-$0.20 per slide via the standard render funnel (no per-iteration gate).
- full_render — single AI hero image with programmatic title overlay. Costs ~$0.067-$0.24 per slide.
Re-run build_strategy_map with the operator's per-slide overrides; the cost summary is recomputed against the new map. Continue until the operator approves.
Cost summary is also informative when the operator wants to validate the proposed allowed_ceiling for each slide — lowering a slide from pro_4k to pro_1k typically drops the worst-case spend from ~$1.50 to ~$0.40 per slide without meaningfully reducing the typical operator-gate count.
General overrides
Ask: "Would you like to override any slide strategies?"
If overrides are provided, rebuild with the overrides dict and save again. If any creative_vision slides were added, removed, or rebased to a different ceiling by the overrides, RE-RUN the creative vision spend surface above before final approval.
Strategy Selection Guidance
Pragmatic composition for grid content
When a slide has 4+ labeled elements in a grid layout, recommend pragmatic_composition over backdrop. Pragmatic composition gives precise control over element sizing and alignment since each image is independently generated and placed at exact coordinates. Backdrop relies on vision-detected positions from a single scene image, which produces inconsistent element sizes and misaligned text labels.
Opting into full_bleed (issue #88)
The full_bleed strategy is operator-opt-in only. Neither the rule-based classifier nor the outline-driven classifier will assign it automatically — the Speaker must pass it via the overrides dict to build_strategy_map or via upgrade_slide_strategy.
When to reach for it. Decks in the infographic-narrative register (see superpower-bridge infographic-narrative.md preset, related to issue #87) want every content slide rendered edge-to-edge — title and body baked into the picture itself, no template chrome, no footer logo. The image carries the entire slide's meaning. Examples: large-format conference keynote screens where each slide is a designed plate; long-scroll briefing decks; institutional reports rendered as full-image plates.
When NOT to reach for it. Avoid for slides that need post-delivery editability (the picture is fixed; speakers can't tweak words in PowerPoint), and for slides whose value is the text itself. If you want a hero image plus a programmatic title overlay, that is full_render, not full_bleed.
Override example.
strategy_map = build_strategy_map(outline, overrides={3: "full_bleed", 5: "full_bleed"})
Overrides set render_funnel to ["ollama", "cloud_low", "cloud_full"] so the slide actually gets a production-quality image rendered.
Edge case — no picture. If image generation fails for a full_bleed slide the assembler emits a slide with a solid brand-primary background (no chrome). Speakers spot the gap during review rather than seeing a misleading title placeholder.
body_layout option for background slides
Background strategy slides support body_layout: "grid_2x2" in the strategy map entry. This renders body points in a 2-column, 2-row grid using column-first reading order instead of a single bullet list. Use this when a background slide has 4 bullet points that would overflow the standard bottom_bar or panel zone.
Column-first reading order
All grid_2x2 element layouts MUST use column-first (N-pattern) reading order: TL=body_points[0], BL=body_points[1], TR=body_points[2], BR=body_points[3]. This matches natural presentation reading: audiences read down the left column before moving right. AP-30 QA check enforces this.
Element image aspect ratios
When specifying element_layout dimensions, calculate the target aspect ratio (w/h) and include it in the strategy map entry so the imagegen-bridge generates images at the correct dimensions. Don't assume square — element images should match their target placement box exactly to avoid letterboxing or cropping artefacts.
Diagram layout guidance
When classifying diagram slides, consider the slide's 16:9 aspect ratio when recommending layout in the visual_direction:
| Element count | Recommended layout | Rationale |
|---|
| 2-4 nodes | Single horizontal row | Fits comfortably in 16:9 |
| 5-8 nodes | Snake pattern (2-3 rows) | Fills the vertical space instead of a tiny horizontal line |
| 9+ nodes | Grid (3x3 or similar) | Maximises use of slide area |
| Hierarchy (1 + N) | Wide bar at top, row below | Shows orchestration clearly |
Include layout direction in the visual_direction prompt. For example: "Snake pattern: Row 1 left-to-right (Brief → Brand → Style → Narrative), curve down, Row 2 right-to-left (Images → Assembly), curve down, Row 3 left-to-right (QA → Deck)."
Resolution selection
By default every slide renders at 1K — economical, sufficient for most slides on a projector. The speaker may opt specific slides into 2K or 4K via the resolution field in the StrategyMap entry.
When to choose 4K:
- Hero opener with detailed photographic imagery
- Closing slide that will be photographed by attendees and shared on social
- Slides where text rendering at small body sizes is critical (Nano Banana Pro 4K renders text noticeably better than Flash 1K)
When to choose 2K:
- Section dividers with mid-detail imagery
- Diagrams that may be projected on very large screens (>120")
Cost implications (per slide, single Pro escalation):
1K (default): ~$0.13 (Nano Banana Pro)
2K: ~$0.13 (Nano Banana Pro — same flat rate within tier)
4K: ~$0.24 (Nano Banana Pro). Plus an optional Flash 4K pre-test at $0.151.
Mark a slide for 2K/4K by including "resolution": "4K" in its StrategyMap entry. Confirm the cost with the speaker before proceeding — a deck with three 4K hero slides is ~$2 of generation spend.
Brand-fidelity selection
Most slides don't need exact brand-color compliance — Nano Banana Pro and FLUX produce close-enough palette match. For slides where the brand colors must be hex-exact (logos, product shots, brand-led hero or closer slides with 3+ specified hexes), mark brand_fidelity: "exact" in the StrategyMap entry to route to Recraft V4 raster.
When to choose brand_fidelity: "exact":
- Logo or wordmark renderings
- Product shots where brand color is part of the identity
- Hero opener for a brand-led talk where the palette must be visually unambiguous
When to leave it default ("none" or omitted):
- Photographic backgrounds (Recraft underperforms FLUX/Nano Banana on photorealism)
- Generic illustrative imagery
- Any slide where the palette doesn't include 3+ specified hexes
Cost implications:
- 2K Recraft Pro: $0.25 (matches FAL FLUX 2 Pro 2K)
- 4K Recraft (chain: 2K + Creative Upscale): $0.50 — vs Nano Banana Pro 4K $0.24. Confirm with the speaker before marking 4K hero slides for
brand_fidelity: "exact" — three such slides represent ~$1.50 vs ~$0.72 of generation spend.
Creative vision authoring (#105)
When to assign creative_vision
Assign creative_vision when the operator describes a specific, rich vision with one or more of:
- Named entities (e.g., "SAP", "Databricks" — specific labelled things that must appear in the image)
- Extended metaphor with explicit mapping (e.g., framework components as cabins inside a man-o-war)
- Particular composition (left-to-right progression, four-way arrangement, contained-within hierarchy)
- Specific style direction ("1950s cartoon", "oil painting", "infographic plate")
Concrete examples (founding examples from issue #105):
- "Four warships SAP/Databricks/OpenAI/Anthropic engaged in a four-way naval battle on a lake. Dramatic, churning waters."
- "Frameworks shown as cabins inside an old man-o-war, Jack-Tar as Captain, 1950s cartoon style."
- "Horizontal left-to-right progression showing sun phases: protostar, main sequence, red giant, supernova, neutron star."
The renderer's job is to bring THAT exact vision to life faithfully — not to interpret it artistically.
Pairing with full_bleed assembly
The creative_vision strategy ALWAYS pairs with full_bleed assembly. The rendered image IS the slide — no chrome, no title overlay, no body bullets. This is a property of the strategy, not a choice. The producer/consumer boundary is explicit: creative_vision produces a vision-faithful image; full_bleed assembly delivers it edge-to-edge.
Operator-opt-in only
Neither the rule-based classifier nor the outline-driven classifier emits creative_vision. It must be assigned explicitly by the operator (or by Claude on the operator's behalf, with operator confirmation). The risk of cascade-spending without intent is too high to leave to heuristics.
Required block on the strategy-map entry
{
"slide_number": 3,
"strategy": "creative_vision",
"rationale": "operator-directed: four ships sea-battle metaphor",
"render_funnel": ["ollama", "cloud_low", "cloud_full"],
"speaker_override": null,
"brand_fidelity": "none",
"creative_vision": {
"vision_prose": "<free-form prose describing the vision>",
"budget_usd": 1.00,
"allowed_ceiling": "pro_4k",
"iteration_caps_override": null
}
}
Schema rule: the creative_vision block is required when strategy: creative_vision and forbidden otherwise. Only vision_prose is required inside the block; the other fields take cascade defaults.
Cost banner the skill MUST surface before recording the choice
When a slide is being assigned creative_vision, surface a cost banner before confirming:
Slide N marked creative_vision. Worst-case spend ~$X.YY per slide.
Deck currently has K creative_vision slides; deck worst-case ~$Z.ZZ.
Provide vision prose (free-form prose; describe named entities, spatial
directives, style, and any compositional progression):
The worst-case per slide is computed from budget_usd × 1.0 (the budget is the cap, so worst-case ≈ budget). For a default $1.00 budget at the default pro_4k ceiling, worst-case ≈ $1.00 per slide.
Defer-prose pattern
If the operator wants to mark a slide as creative_vision but isn't yet ready to write the prose, the skill can record the strategy with pending_vision_prose: true (a flag adjacent to the creative_vision block) and leave vision_prose empty. The pipeline halts at that slide until the prose is provided — imagegen-bridge skips it with a clear message and resumes when prose is added.
Decision tree — when to pick creative_vision vs alternatives
| Operator's intent | Strategy to pick |
|---|
| Specific rich vision with named entities / extended metaphor / particular composition | creative_vision |
| Edge-to-edge image with whatever the generic imagegen-bridge produces (no specific vision) | full_bleed |
| AI background image + programmatic title/body overlay | backdrop_render or background |
| Standard chrome (title + bullets + small hero image) | composed |
| Academic figure (Figure-N caption, equations, architecture diagram) | academic_figure |
| Editable SmartArt graphic | smartart |
Cross-references
- Spec:
docs/superpowers/specs/2026-05-21-creative-vision-renderer-design.md
- Schema:
plugins/jack-tar-deckhand/src/schemas/strategy_map.schema.json
- Pipeline implementation: imagegen-bridge SKILL.md section "Creative vision strategy (#105)"
- Founding examples: the four-ships, man-o-war, and sun-phases examples from issue #105
Output
./tmp/deck/strategy-map.json conforming to the StrategyMap schema.