Marketing Mega-Pipeline
One command produces a product's full asset suite: brand onboarding, UI polish, logo reveal, product demo, launch video with audio, social clips, and OG assets. The individual asset skills own their recipes; this skill owns sequencing, gates, and run state.
REQUIRED BACKGROUND: marketing-studio (engine-repo workflow shape and non-negotiables). All PLAYBOOK rules apply.
Production route: read docs/production-quality.md.
Require --project <product-repo> and use
<workspace> = <product>/marketing/assets/<brand>. Every generated capture, audio file,
prop, public-stage asset, render, report, matrix row, and post kit stays in that product
workspace. Engine-local out/ is not a product-run path.
Resume check — before anything else
Read <workspace>/marketing/run.json. If it exists and any asset is not delivered,
this invocation is a RESUME: load its intake and continue at the first incomplete asset.
Confirm every claimed artifact exists inside the product workspace before trusting state.
On resume, still run the Phase 1 environment checks (shared-repo guard + launch.py --check — the previous process died mid-flight), but skip brand onboarding and Phase 2 polish if the manifest marks them complete. Trust a rendered/approved status only after confirming its artifact actually exists on disk; missing or truncated artifact → demote that asset to planned.
Phase 0 — Intake: ONE batched question round, then silence
Fresh runs only. Ask everything in a single AskUserQuestion, then run without asking again (exceptions: per-asset stills gates in gated mode, final delivery):
- Product/brand — which brand and the explicit product repo used by
--project.
- UI polish before filming? Default YES: the demo films the real running app, so rough edges get rendered at 60fps forever. YES = impeccable → polish → frontend-verify on the product repo before any capture. NO = film as-is. This edits product code, so it is always the user's call — never silently skip it AND never silently do it.
- Audio — music + voiceover is the default and the only thing a film ships with; ask only WHO narrates (brand voice id vs default) and whether music leads or narration leads. "None" is not an option and music-only is a recorded exception (
--music-only), never a default: a film with no voice explaining the product is not done (CLAUDE.md, learned 2026-09-01).
- Social clips — platforms and count (default: X + LinkedIn, one each).
- Checkpoint mode — full-auto (self-check stills, user reviews the final gallery) or gated (user approves stills before each full render).
Phase 1 — Foundation
- Shared-repo guard +
python launch.py --check (marketing-studio steps 0–1), then node scripts/install-skills.mjs --check — it warns when a bundled skills/ copy and its installed ~/.claude/skills copy have drifted, so the run does not follow a stale checklist. Warn only; fix the drift or note it, then continue.
- Brand: if
brands/<id>.json is missing, onboard per PLAYBOOK. Brand-token judgment stays in the main loop — do not delegate it.
- Create
<workspace>/marketing/run.json. It stores the intake answers and one entry per planned asset. Statuses mean exactly this:
planned — not rendered yet. Gated mode: user approves pre-render stills before the render starts (that is the ONLY user gate per asset).
rendered — artifact on disk, post-render frame check pending (extract 2–3 frames from the artifact and inspect them — self-check in both modes).
approved — frame check passed; approval is recorded in the manifest the moment it happens, never inferred from chat history. A resumed session redoes the frame check for any rendered asset, showing the frames to the user first in gated mode.
delivered — copied to the product repo.
Update the manifest after every status change. Never restart a run from scratch because the session died. In executor-judge mode the judge writes rendered plus the artifact path the moment an executor returns, before judging: the truckside session died on 2026-09-05 with a finished, scored launch film on disk and a manifest that still read planned, and the resume had to be reconstructed from file timestamps.
- Infographic bridge: build the product-owned
<workspace>/marketing/infographic-style.md, then name it when an infographic is part of this run so that asset uses the approved brand tokens.
Content and direction gate. Once <workspace>/marketing/brief.json is synthesized
and passes the copy gate, generate direction, shot plan, and production plan with the
product-aware builder. Run node scripts/build-storyboard.mjs <brand> --project <product>.
Approve the grounded copy and a style frame, then build an audio-bearing animatic with
scratch voice/music and obtain named non-author approval before full rendering.
Brief synthesis rules. The zod schema (studio/src/lib/brief.ts) is the contract; fill the grounding sections, not just the copy: audience + customerLanguage + objections + switchingForces from the brief-inputs grounding, and a proofPoints entry (claim + source) for EVERY number the copy cites — an unsourced stat is fabrication, omit it instead (lint-copy WARNs on stat-shaped claims in a brief with no proofPoints). Draw hook.headline and each of the (up to two) altHeadlines from DIFFERENT hook categories per references/hook-formulas.md, record the categories in hook.strategies, and include at least one emotion-forward category (story/contrarian) against a value hook — evidence in references/campaign-evidence.md (read it before synthesis; it also lists debunked claims that must never appear in copy). Build cta with the [Action Verb] + [What They Get] formula. The storyboard renders the grounding sections so the approver can check copy against facts.
Copy council (full-auto mode). Before the main-loop judge accepts the storyboard, run a 3-judge council on the brief copy: three parallel Sonnet subagents (model: claude-sonnet-5, explicit), one per lens — positioning sharpness (would April Dunford sign it?), emotional resonance vs feature-dump, and evidence honesty (every claim traced to a proofPoint) — with the third judge additionally instructed to argue AGAINST shipping the copy (mandatory dissenter; kills the echo chamber). Issues raised by 2+ judges go back to synthesis; single-judge nits are noted, not blocking. In gated mode the human storyboard review replaces the council — offer it only if the user asks for a copy critique. (Pattern adapted from Corey Haines' marketing-council skill, MIT.)
Phase 2 — UI polish (only if opted in)
In the PRODUCT repo: impeccable → polish → frontend-verify. Must fully complete before Phase 3 — re-shooting every asset because the UI changed after capture doubles the run. Commit product-repo polish separately from asset delivery.
Phase 3 — Asset pipeline: STRICTLY SEQUENTIAL
The engine repo is shared mutable state (props builders, registries, render queue). Two asset skills at once collide and renders saturate the CPU. One asset at a time, in this order. (One blessed exception: /logo-reveal touches only the engine repo and captures nothing, so it may run concurrently with Phase 2 polish, which touches only the product repo — zero shared state, real wall-clock savings.)
Per asset, inspect inexpensive representative stills before a full render. For the hero
film, generate hash-bound start/middle/end samples for every planned shot from the exact
final render with contact-sheet.mjs --project <product> --plan ... --render ....
Footage caches also live in the product workspace; --force re-captures only when needed.
Render budget: one full-resolution render per asset. The renderer is not where a
two-hour run goes; correction rounds are. Measured 2026-09-01 on the 24-core box: a
full-res LaunchVideo render is ~9 minutes and --x264-preset barely moves it (Chrome
frame rendering is the bottleneck, not encoding), while --scale=0.5 renders 3.3x
faster. So: judge every round from the contact sheet, and when a round needs motion,
render the preview at --scale=0.5 as launch-vN-preview.mp4. The full-res render
happens ONCE, after the stills pass. The postflop launch step rendered three full
passes (27 minutes of the step's 48); this rule makes that one. A product bug found
mid-capture is a note in run.json judgeNotes for the user, not a fix inside the
run (postflop's demo step spent 64 minutes that way).
Budget the VO before you dispatch #4, not after. Picture-lock (#3) and audio (#4) are separate steps, and the trap between them is that measured VO word timings DERIVE act lengths, so scoring a locked film can push it past the 30-90s band launchTiming.test.ts enforces. Do the arithmetic yourself at dispatch time and hand it to the executor: frames_available = 2700 - current_total, minus the demo act which is FIXED (the PLAYBOOK forbids shortening a recorded demonstration to fit narration). Estimate each act's need at ~150wpm plus VO_LEAD + VO_PAD. If the narration overruns, say so in the brief and name the act to cut hardest — copy is trimmed ONLY in build-<brand>-audio.mjs, never by editing act constants. Measured on the practicalsystems run (2026-08-17): an 80.8s lock left 276 frames of headroom against ~564 needed, so ~25 words had to go. Name any claim that must survive the trim, because the shortest phrasing is often the false one — "cold outreach never sends without a human" compresses to "nothing sends without a human", which was untrue there.
Phase 3.5 — Responsive export matrix. After the scored launch and social clips pass
their own review, run render-matrix <brand> --project <product> --production --stills-only to prove all formats. This is non-delivery layout evidence. Then run the
production matrix without --stills-only; it binds each complete row to the approved
plan and strict evidence. Use --verify-production to recheck pending existing media
without rerendering it.
Execution mode — pick by session model
- Opus or Sonnet session (default): run each asset skill inline in the main loop. Visual-tuning loops go to Sonnet subagents (
model: claude-sonnet-5, always explicit) so iteration stills die with their context. Mechanical checks: Haiku or inline. Escalate to Fable at most once, standalone, only if a new template must be designed mid-run.
- Fable session (e.g.
ultracode "/marketing" with Fable as the main model): executor-judge mode, below. Fable never executes asset recipes inline — its context grows for hours at judging-grade rates while doing checklist work.