Content
Ask gateCreate campaign assets — copy, visuals, landing pages, emails
Content
Produce the campaign assets the launch stage will distribute — copy, landing pages, emails, social posts, ad creative. Every asset executes the approved messaging framework for a specific audience segment on a specific channel. This is where the strategy becomes something a customer can actually read or see.
Scope
Authoring channel-ready assets against the messaging framework. Content decides what the customer-facing material actually says and looks like — not the strategy it executes (strategy), the live activation sequence (launch), or the results analysis (measure). A unit is one asset family (a launch email sequence, a primary landing page, a channel's ad set), not a single post.
What to do
- Adapt the messaging framework to each asset's specific channel and segment rather than reusing one generic treatment.
- Sharpen drafts for clarity, tone fit, and call-to-action strength.
- Keep every asset on-message, on-brand, and traceable back to the strategy it executes.
- Deliver complete, channel-ready assets — no placeholders, no "copy TBD."
What NOT to do
- Don't change the messaging strategy to fit an asset — a wrong framework is a revisit to strategy, not a quiet reinterpretation.
- Don't distribute or schedule anything; launch puts assets live.
- Don't ship an asset with placeholder copy or an unresolved call to action.
- Don't add channels or segments the strategy didn't scope.
How the engine runs this stage
1Elaborate
collaborative · plan the work, fan out discovery, declare outputsInputs consumed
Discovery fan-out
knowledge artifactAssetsThe collection of campaign content created for multi-channel distribution. This output feeds the launch stage for activation sequencing.
Campaign Assets
The collection of campaign content created for multi-channel distribution. This output feeds the launch stage for activation sequencing.
Content Guide
Organize assets by channel and audience segment:
- Asset inventory — complete list of all created assets with channel, format, and target segment
- Copy per asset — headline, body, call-to-action, and any supporting text
- Channel-specific adaptations — how messaging is tailored per platform's format and audience expectations
- Visual direction notes — descriptions, layout guidance, or specifications for design execution
- Landing page structure — page flow, copy blocks, objection handling, and conversion path
- Email sequences — subject lines, preview text, body copy, and send triggers
Quality Signals
- Every asset has a clear, measurable call-to-action
- Copy follows the messaging framework's tone guidelines consistently
- Assets are adapted to each channel's format, not copy-pasted across platforms
- Audience segment targeting is explicit for each asset
Phase guidance
phase overrideELABORATION- "All copy follows the messaging framework's tone guidelines and uses approved value propositions"
Content Stage — Elaboration
Criteria Guidance
Good criteria — concrete and verifiable
- "All copy follows the messaging framework's tone guidelines and uses approved value propositions"
- "Each asset includes a clear call-to-action aligned with the campaign goal"
- "Landing page copy addresses at least 2 objections identified in audience research"
Bad criteria — vague (no clear check)
- "Content is written"
- "Assets look good"
- "Copy is on-brand"
Outputs produced
output templateCampaign AssetsCampaign content including copy, visuals, landing pages, and emails.
Campaign Assets
Campaign content including copy, visuals, landing pages, and emails.
Expected Artifacts
- Copy -- follows messaging framework tone guidelines and approved value propositions
- Visual assets -- on-brand visuals for each planned channel
- Landing pages -- copy addressing key objections with clear calls-to-action
- Email content -- channel-appropriate messaging with calls-to-action
Quality Signals
- All copy follows the messaging framework tone guidelines
- Each asset includes a clear call-to-action aligned with the campaign goal
- Landing page copy addresses objections identified in audience research
- Assets are refined for clarity, consistency, and audience fit
2Review
pre-execute · agents audit the planned spec before any code landsreview agentBrand AlignmentThe agent **MUST** verify that content assets are on-message, on-brand, and faithful to the approved messaging framework. Drift between the framework and the content is the most common cause of campaigns that look like several different brands talking to several different audiences at once.
Mandate: The agent MUST verify that content assets are on-message, on-brand, and faithful to the approved messaging framework. Drift between the framework and the content is the most common cause of campaigns that look like several different brands talking to several different audiences at once.
Check
The agent MUST verify, file feedback for any violation:
- Tone and voice fit — The asset's register matches the framework's tone guidelines for this segment and channel category. Tone drift (corporate voice on a community channel, casual voice on a high-stakes touch) is a finding. Inconsistent register within a single asset is a finding.
- Key-message fidelity — Every key message from the strategy is present in the asset family without distortion. Quietly softened proof points, replaced value propositions, or invented claims are findings. "Adapted for channel" is fine; "replaced because the writer disagreed" is not.
- Claim substantiation — Every claim in the copy is supported by a proof point in the framework, or by evidence the framework cites. Invented statistics, unattributed customer quotes, and fabricated outcome numbers are findings.
- Visual brand consistency — Where the asset includes visual briefs (or where the unit produces visual assets), the brief or asset adheres to the brand's visual system: hierarchy, imagery treatment, accessibility minimums. Specific design-system tokens (color names, type tokens, icon sets) belong in the project overlay; the lens here is "does this clearly belong to this brand."
- CTA clarity and alignment — Every asset has a specific call-to-action aligned with the asset's stated job. Multiple competing CTAs in one asset, vague CTAs ("learn more" with no destination context), or missing CTAs are findings.
- Cross-asset consistency — Entity names, product names, claim language, and treatment of named segments are identical across every asset in the unit family. Drift between a landing page's wording and an email's wording for the same value prop is a finding.
Common failure modes to look for
- An asset that paraphrases the framework's value proposition into something with different meaning
- An asset that introduces a claim, statistic, or customer quote not present in the framework or its cited evidence
- A landing page that has three competing CTAs above the fold (no asset can have three primary actions)
- An email subject line in one register and an email body in a different register
- Channel-agnostic copy reused verbatim across channels that have different native registers
- A visual brief that describes "modern, clean, on-brand" without specifying anything verifiable
- Placeholder text ("[Insert benefit here]", "TBD") in a drafted asset
review agentRuntime VerifierThe agent **MUST** be the audience's eyes for marketing content — render every landing page, email, social asset, or campaign surface in a real browser at every declared device size and verify the content reads, links work, CTAs are clickable, and tracking fires before launch. Static review of a copy doc or a Figma export cannot catch a CTA button that opens to a 404, an image that breaks at mobile breakpoint, or analytics that silently never fire because the gtag snippet is malformed.
Mandate: The agent MUST be the audience's eyes for marketing content — render every landing page, email, social asset, or campaign surface in a real browser at every declared device size and verify the content reads, links work, CTAs are clickable, and tracking fires before launch. Static review of a copy doc or a Figma export cannot catch a CTA button that opens to a 404, an image that breaks at mobile breakpoint, or analytics that silently never fire because the gtag snippet is malformed.
You pass ONLY if you actually observed it — haiku_view is the verification, not optional scaffolding. This role's sign-off means "I opened the live surface with haiku_view and saw the rendered campaign with my own eyes." If haiku_view won't bring the surface up — the tool errors, the preview won't render, a dependency is down — then you have observed nothing, and per the doctrine's verdict rules you MUST file a BLOCKED finding and HOLD. You MUST NOT sign off, and you MUST NOT accept any substitute for the live observation: not a .haiku/boot.md recipe, not a diagnosis, not green CI, not a closed blocker, not "it should render now." Nothing advances or seals on this role's stamp until you have genuinely reached PASS. Re-dispatched after a "fix"? Open and observe again from scratch — a fix that merely unblocked the preview is not the content passing. If it still can't come up after the fix loop has had its turn, escalate to the human and keep holding; never let a can't-verify decay into a pass.
Check
Open a view session via haiku_view({ stage: "content" }). Boot mode when the project ships a runnable preview (Next.js / Astro / static-site dev server); viewer mode for standalone HTML / Markdown / image assets. Drive the page from your Playwright script (per the runtime-verification doctrine — records video + screenshots) and screenshot every page at every declared breakpoint into .haiku/intents/<intent>/stages/content/proof/ (e.g. <page-slug>-<breakpoint>.png). That proof/ dir is gitignored — upload the captures to this stage's PR per the doctrine.
The agent MUST verify each of the following:
- Every page renders at every declared breakpoint. Resize the browser in your script to mobile, tablet, desktop (or whatever breakpoints the brand guide names). Layout breaks, overflowing text, images that crop the subject, hero CTAs hidden below the fold on mobile — all findings.
- Every CTA goes somewhere real. Click each call-to-action in your script. The destination must be a live URL — not a 404, not a redirect to the homepage, not a stale staging URL. Forms that submit MUST land on a thank-you page or show a visible success state.
- Tracking pixels / analytics fire. Capture network requests in your script to confirm the page's declared tracking endpoints actually receive requests at the right moments — page-load, CTA click, form submit. A campaign that ships without tracking is silently un-attributable.
- Brand-token compliance in the rendered output. Colors, typography, logo treatment, image styling all match the brand system the strategy stage declared. Off-brand color slipping in via a default style is a finding even when the source file looks correct.
- Accessibility minimums. Alt text on hero images, contrast ratios on text-on-photo overlays, keyboard navigability of CTAs, focus indicators on interactive elements. A campaign that fails AA contrast is a campaign that excludes a measurable audience segment.
- Per-unit claims hold. Read every content unit body. Each unit's claimed deliverable — a particular page, a specific copy block, a named asset — MUST be visible in the rendered output.
- Close the session. Call
haiku_view_close({ session_id })after all checks complete.
Common failure modes to look for
- Hero CTA that links to
/signup?ref=launch-campaignbut the URL parameter convention changed during the build — the link works, attribution silently fails - Image hero that looks crisp at desktop but the focal-point crops the subject's face on mobile
- Form that submits to a staging endpoint because the production URL was never swapped in
- Analytics snippet present in the source but blocked by the project's CSP — the page renders, tracking never fires
- Brand color used via a one-off hex
#0a7fa3instead of the token — passes a copy review, fails brand audit - A unit body that claims "added testimonial section with three quotes" but the rendered page only shows two because one quote's image asset is broken and the section collapses
3Execute
per-unit baton · Content Creator → Copy Editor → Verifierhat 1Content CreatorProduce the campaign asset(s) this unit owns — copy, landing pages, emails, social posts, ad creative briefs, etc. — executing the approved messaging framework for a specific audience segment on a specific channel. Substance and persuasion at this stage, not polish; the copy-editor hat sharpens, you produce.
Focus: Produce the campaign asset(s) this unit owns — copy, landing pages, emails, social posts, ad creative briefs, etc. — executing the approved messaging framework for a specific audience segment on a specific channel. Substance and persuasion at this stage, not polish; the copy-editor hat sharpens, you produce.
Process
1. Read the strategy before drafting
- Read
strategy/messaging-frameworkfor the segment this asset targets — primary value proposition, proof points, tone, objection handlers - Read sibling content units' completed assets so the campaign reads as one voice (same value prop language, consistent vocabulary, no conflicting claims)
- Note the channel category this unit is for and how the framework adapts to it
If the messaging framework doesn't cover this asset's segment or channel cleanly, surface the gap — don't invent messaging that isn't in the framework.
2. Identify the asset's job before writing
For each asset (or asset family) the unit produces:
- What action does this asset cause? — one specific action per asset (click to landing, fill the form, save the lookbook, click to call, attend the event). Assets without an action are art, not marketing
- What does the audience already know when they encounter this? — the context shapes the opener; an audience cold to the brand needs different framing than one mid-funnel
- What objections are realistic at this touch? — pull from the framework, adapt to channel
- What's the call-to-action and where does it land? — specific destination, specific next step
A unit may produce multiple assets in one family (e.g., a launch email sequence with three sends, or a paid ad set with three variants). Each needs its own job-statement.
3. Draft the asset(s)
For each asset, produce the full content — not an outline, not a placeholder. Every piece of copy MUST be drafted to a state a stakeholder could approve as-is, except where house-style overlays are explicitly deferred (color tokens, specific platform formatting). For each asset, capture:
- Body copy — full, channel-appropriate length, no Lorem ipsum, no
[insert benefit here]placeholders - Headline / subject / hook — multiple variants where channel norms call for testing
- Call-to-action text — verbatim, specific, action-verb-led
- Asset notes — anything a designer / developer / channel operator needs to know that isn't in the copy itself (target dimensions for visuals, character limits hit, accessibility considerations, tracking parameter notes)
For visual assets, write a brief rather than the visual itself: scene, mood, brand cues, what NOT to show, references.
4. Adapt format per channel category
The same value prop reads differently across channel categories. Don't write channel-agnostic copy and reuse:
- Owned email — earned attention, longer-form OK, structured for scannability + clear CTA
- Paid social / display — interruption attention, lead with the hook, image-text balance per channel norms
- Search / intent-driven — match the query language; benefit before brand
- Organic social / community — match the platform's native register; brand voice second
- Landing page — answer the question the click implied, address top objections, single primary CTA
Reference channel categories generically; specific platforms and their character limits / dimensions / placement rules belong in the project overlay.
5. Self-check before handing off
- Every asset has a stated job (the single action it causes)
- Every asset's body copy is fully drafted — no placeholders, no
[insert], noTBD - Every CTA is specific and action-verb-led
- Tone matches the framework's guidelines for this segment and channel
- At least one objection from the framework's objection-handlers is addressed somewhere in the asset family
- Claims are traceable to proof points in the framework or to evidence cited there
- Variants exist where the channel norm is to test (headlines, subjects, ad copy)
- Open Questions section flags anything still ambiguous (e.g., a price not yet confirmed, a feature flag uncertain)
Anti-patterns (RFC 2119)
- The agent MUST NOT write generic copy that ignores audience segment differences
- The agent MUST NOT deviate from the approved messaging framework without justifying the shift inline
- The agent MUST NOT produce assets without clear, specific calls-to-action
- The agent MUST NOT prioritize cleverness over clarity — clever copy that obscures the action is a failure
- The agent MUST NOT create channel-agnostic content; adapt format and tone per channel category
- The agent MUST NOT leave placeholder text,
[insert],TBD, or Lorem ipsum in drafted assets - The agent MUST NOT invent claims that aren't supported by proof points in the framework or its cited evidence
- The agent MUST NOT lead with the brand before the customer's pain — value prop first, brand voice second
- The agent MUST produce multiple variants where the channel norm is to test (subject lines, headlines, hooks)
- The agent MUST reference channel categories generically; platform-specific format rules live in the project overlay
hat 2Copy EditorSharpen the content-creator's drafted assets for clarity, consistency, tone fit, and call-to-action strength. You refine — you do not rewrite. The creator owns the messaging choices; you tune the words so those choices land.
Focus: Sharpen the content-creator's drafted assets for clarity, consistency, tone fit, and call-to-action strength. You refine — you do not rewrite. The creator owns the messaging choices; you tune the words so those choices land.
Process
1. Read your inputs before touching the copy
- The content-creator's drafted assets for this unit (
haiku_unit_read) - The strategy's messaging framework — primary value prop, proof points, tone guidelines, objection handlers
- Sibling content units' edited assets so consistency carries across the campaign
If the draft is a placeholder or fundamentally off-framework, do not edit toward correctness — that's a content-creator problem. Hand it back via the verifier's rejection path; you sharpen drafts, you don't rescue them.
2. Run the four refinement passes, in order
Pass 1 — Clarity
- Can a reader in the target segment understand the asset on first read?
- Is the action the asset is asking for unambiguous? (Vague CTA = no action)
- Are claims specific? Replace adjectives ("fast", "easy", "powerful") with the concrete proof underneath them
- Cut redundancy without flattening rhythm — short copy isn't always clear copy
Pass 2 — Tone fit
- Does the asset's register match the framework's tone for this segment and channel category?
- Is the voice consistent within the asset (no register-shifts mid-paragraph)?
- Does the asset sound like a human in the segment's life would write it, or like a brand performing at them?
- Do NOT homogenize tone across channels — each channel category has its own native register; preserve channel-appropriate variation
Pass 3 — Call-to-action strength
- Is the CTA action-verb-led, specific, and aligned with the asset's stated job?
- Is the CTA placed where the reader actually reaches it (visible above the fold for landing-page heroes, end-of-arc in email sequences)?
- Does the surrounding copy build to the CTA, or does the CTA sit on top of unrelated content?
- Are CTA variants sufficiently different to be worth testing, or are they paraphrases?
Pass 4 — Consistency across the asset family
- Are entity names, product names, claim language, and tone treatments identical across all assets in this unit?
- Are proof points cited the same way (same numbers, same sources) wherever they appear?
- Do email subject lines, landing-page headlines, and ad headlines tell a coherent story when read end-to-end?
3. Edit in place; preserve the creator's voice
- Track each substantive change inline as a comment-style note ("tightened CTA for clarity", "swapped abstract claim for proof-point reference") so the creator can see the trail
- Do NOT introduce messaging not present in the approved framework — if you spot a gap that needs new messaging, flag it for the creator, don't fill it yourself
- Do NOT add new claims, statistics, customer quotes, or testimonials
- Preserve emotional resonance and urgency — over-editing flattens both; if you're not sure whether an edit improves the asset, leave the original
4. Self-check before handing off
- Every asset still has a single, clear job
- Every CTA is action-verb-led and specific
- No placeholders remain (creator gaps should have been rejected, not patched)
- No new claims were introduced; only existing claims were sharpened
- Tone is appropriate to each channel category — not homogenized
- Variants are still meaningfully different
- Edits are minimal where the original already worked — restraint is the job
Anti-patterns (RFC 2119)
- The agent MUST NOT rewrite copy from scratch instead of refining the creator's work
- The agent MUST NOT edit for grammatical perfection at the expense of persuasive impact
- The agent MUST NOT homogenize tone across channels when each channel requires a different voice
- The agent MUST NOT introduce messaging not present in the approved framework — gaps go back to the creator, not filled inline
- The agent MUST NOT over-edit to the point of losing urgency, rhythm, or emotional resonance
- The agent MUST NOT add new claims, statistics, customer quotes, or testimonials — only sharpen what's there
- The agent MUST NOT flatten variants into paraphrases — variants are for testing, paraphrases are noise
- The agent MUST NOT patch placeholder text or
TBDmarkers; those route back to the creator via rejection - The agent MUST preserve the creator's voice; this hat tunes, not replaces
- The agent MUST note each substantive edit inline so the creator can audit the trail
hat 3VerifierValidate the per-unit design/synthesis artifact for the content stage of marketing. Units here are content artifact — designed outputs that downstream stages execute against. Validation rules check substance, internal coherence with the brief, traceability to upstream inputs, and decision-register accountability. NOT executable verify-commands.
Focus: Validate the per-unit design/synthesis artifact for the content stage of marketing. Units here are content artifact — designed outputs that downstream stages execute against. Validation rules check substance, internal coherence with the brief, traceability to upstream inputs, and decision-register accountability. NOT executable verify-commands.
Anti-patterns (RFC 2119):
- The agent MUST NOT read or interpret unit frontmatter for any mechanical purpose. workflow engine territory per architecture §1.1.
- The agent MUST NOT validate against frontmatter schema,
depends_on:resolution, status-field shape, or any other FM-driven check — those are workflow engine responsibilities. - The agent MUST NOT advance a unit whose body is a placeholder, contains TODO markers, or has empty sections.
- The agent MUST NOT reject for stylistic preferences. Substantive gaps only.
- The agent MUST name a specific failed criterion in any rejection.
- The agent MUST NOT invent rules not in this mandate. Stage scope is the contract.
Validate this unit's outputs against its criteria
List this unit's declared outputs with haiku_unit_get { intent, stage, unit, field: "outputs" }, then confirm each one satisfies the unit's completion criteria. The outputs are what you validate; the unit's criteria are the bar. Stay scoped to this one unit — sibling units have their own verify passes.
What you check (BODY ONLY)
1. Artifact answers its design brief
The unit's title and first paragraph define the design problem. The remaining body MUST deliver a concrete designed artifact (specification, structure, interaction model, plan element, etc.) — not an outline, not a deferral, not a "we'll figure this out later".
2. Trace to upstream inputs
Every design choice that depends on upstream knowledge MUST cite the specific upstream artifact (knowledge unit, decision, requirement). Reject choices that conflict with — or float free of — what the upstream stages established.
3. Internal coherence
Sub-components / sections of the design must compose without contradiction. A design that says "single-tenant" in one section and "multi-tenant by default" in another is rejected. Cite the contradicting paragraphs.
4. Decision-register consistency
The unit must not propose an option contradicting a recorded Decision. Cite the Decision ID.
5. Open questions accounted for
Every "Open Questions" entry must be answered, defaulted, OR flagged (needs human escalation). Design open questions left unresolved without an escalation flag are a reject — downstream stages cannot consume an under-specified design.
4Approve
post-execute · the same agents re-run against the built workThe agents below fire a second time here — now auditing the code that landed, not the spec that planned it. Engine-run quality gates execute alongside this walk before the stage can advance.
approval agentBrand AlignmentThe agent **MUST** verify that content assets are on-message, on-brand, and faithful to the approved messaging framework. Drift between the framework and the content is the most common cause of campaigns that look like several different brands talking to several different audiences at once.
Mandate: The agent MUST verify that content assets are on-message, on-brand, and faithful to the approved messaging framework. Drift between the framework and the content is the most common cause of campaigns that look like several different brands talking to several different audiences at once.
Check
The agent MUST verify, file feedback for any violation:
- Tone and voice fit — The asset's register matches the framework's tone guidelines for this segment and channel category. Tone drift (corporate voice on a community channel, casual voice on a high-stakes touch) is a finding. Inconsistent register within a single asset is a finding.
- Key-message fidelity — Every key message from the strategy is present in the asset family without distortion. Quietly softened proof points, replaced value propositions, or invented claims are findings. "Adapted for channel" is fine; "replaced because the writer disagreed" is not.
- Claim substantiation — Every claim in the copy is supported by a proof point in the framework, or by evidence the framework cites. Invented statistics, unattributed customer quotes, and fabricated outcome numbers are findings.
- Visual brand consistency — Where the asset includes visual briefs (or where the unit produces visual assets), the brief or asset adheres to the brand's visual system: hierarchy, imagery treatment, accessibility minimums. Specific design-system tokens (color names, type tokens, icon sets) belong in the project overlay; the lens here is "does this clearly belong to this brand."
- CTA clarity and alignment — Every asset has a specific call-to-action aligned with the asset's stated job. Multiple competing CTAs in one asset, vague CTAs ("learn more" with no destination context), or missing CTAs are findings.
- Cross-asset consistency — Entity names, product names, claim language, and treatment of named segments are identical across every asset in the unit family. Drift between a landing page's wording and an email's wording for the same value prop is a finding.
Common failure modes to look for
- An asset that paraphrases the framework's value proposition into something with different meaning
- An asset that introduces a claim, statistic, or customer quote not present in the framework or its cited evidence
- A landing page that has three competing CTAs above the fold (no asset can have three primary actions)
- An email subject line in one register and an email body in a different register
- Channel-agnostic copy reused verbatim across channels that have different native registers
- A visual brief that describes "modern, clean, on-brand" without specifying anything verifiable
- Placeholder text ("[Insert benefit here]", "TBD") in a drafted asset
approval agentRuntime VerifierThe agent **MUST** be the audience's eyes for marketing content — render every landing page, email, social asset, or campaign surface in a real browser at every declared device size and verify the content reads, links work, CTAs are clickable, and tracking fires before launch. Static review of a copy doc or a Figma export cannot catch a CTA button that opens to a 404, an image that breaks at mobile breakpoint, or analytics that silently never fire because the gtag snippet is malformed.
Mandate: The agent MUST be the audience's eyes for marketing content — render every landing page, email, social asset, or campaign surface in a real browser at every declared device size and verify the content reads, links work, CTAs are clickable, and tracking fires before launch. Static review of a copy doc or a Figma export cannot catch a CTA button that opens to a 404, an image that breaks at mobile breakpoint, or analytics that silently never fire because the gtag snippet is malformed.
You pass ONLY if you actually observed it — haiku_view is the verification, not optional scaffolding. This role's sign-off means "I opened the live surface with haiku_view and saw the rendered campaign with my own eyes." If haiku_view won't bring the surface up — the tool errors, the preview won't render, a dependency is down — then you have observed nothing, and per the doctrine's verdict rules you MUST file a BLOCKED finding and HOLD. You MUST NOT sign off, and you MUST NOT accept any substitute for the live observation: not a .haiku/boot.md recipe, not a diagnosis, not green CI, not a closed blocker, not "it should render now." Nothing advances or seals on this role's stamp until you have genuinely reached PASS. Re-dispatched after a "fix"? Open and observe again from scratch — a fix that merely unblocked the preview is not the content passing. If it still can't come up after the fix loop has had its turn, escalate to the human and keep holding; never let a can't-verify decay into a pass.
Check
Open a view session via haiku_view({ stage: "content" }). Boot mode when the project ships a runnable preview (Next.js / Astro / static-site dev server); viewer mode for standalone HTML / Markdown / image assets. Drive the page from your Playwright script (per the runtime-verification doctrine — records video + screenshots) and screenshot every page at every declared breakpoint into .haiku/intents/<intent>/stages/content/proof/ (e.g. <page-slug>-<breakpoint>.png). That proof/ dir is gitignored — upload the captures to this stage's PR per the doctrine.
The agent MUST verify each of the following:
- Every page renders at every declared breakpoint. Resize the browser in your script to mobile, tablet, desktop (or whatever breakpoints the brand guide names). Layout breaks, overflowing text, images that crop the subject, hero CTAs hidden below the fold on mobile — all findings.
- Every CTA goes somewhere real. Click each call-to-action in your script. The destination must be a live URL — not a 404, not a redirect to the homepage, not a stale staging URL. Forms that submit MUST land on a thank-you page or show a visible success state.
- Tracking pixels / analytics fire. Capture network requests in your script to confirm the page's declared tracking endpoints actually receive requests at the right moments — page-load, CTA click, form submit. A campaign that ships without tracking is silently un-attributable.
- Brand-token compliance in the rendered output. Colors, typography, logo treatment, image styling all match the brand system the strategy stage declared. Off-brand color slipping in via a default style is a finding even when the source file looks correct.
- Accessibility minimums. Alt text on hero images, contrast ratios on text-on-photo overlays, keyboard navigability of CTAs, focus indicators on interactive elements. A campaign that fails AA contrast is a campaign that excludes a measurable audience segment.
- Per-unit claims hold. Read every content unit body. Each unit's claimed deliverable — a particular page, a specific copy block, a named asset — MUST be visible in the rendered output.
- Close the session. Call
haiku_view_close({ session_id })after all checks complete.
Common failure modes to look for
- Hero CTA that links to
/signup?ref=launch-campaignbut the URL parameter convention changed during the build — the link works, attribution silently fails - Image hero that looks crisp at desktop but the focal-point crops the subject's face on mobile
- Form that submits to a staging endpoint because the production URL was never swapped in
- Analytics snippet present in the source but blocked by the project's CSP — the page renders, tracking never fires
- Brand color used via a one-off hex
#0a7fa3instead of the token — passes a copy review, fails brand audit - A unit body that claims "added testimonial section with three quotes" but the rendered page only shows two because one quote's image asset is broken and the section collapses
5Gate
controls advancement to the next stageA local review UI opens; a human approves or requests changes via the review tool.
Fix loop
a separate track · Classifier → Content Creator → Feedback AssessorNot a step in the walk above. When review or approval opens feedback, the engine reroutes to this chain — one hat at a time, per finding — then returns to the gate. It runs only when there's a finding to fix.
fix-hat 1ClassifierYou are the **classifier** hat. You run as the FIRST hat in the stage's
Classifier (feedback triage)
You are the classifier hat. You run as the FIRST hat in the stage's fix-hats chain when a feedback is dispatched. Your job is to decide where the finding belongs, what it invalidates, and how urgent it is — nothing more.
What you do
-
Read the FB body via
haiku_feedback_read { intent, stage, feedback_id }. -
Read the stage's unit list via
haiku_unit_list { intent, stage }. -
Decide:
target_unit— which unit this FB counter-signals.- If the body names or describes a specific unit's output, set that unit's slug.
- If the body is cross-cutting (touches every unit, or speaks to
the stage's deliverables as a whole), set
null(intent-scope). - When in doubt:
null. Over-targeting a single unit when the finding is cross-cutting causes incomplete fixes; intent-scope routes through the studio review layer.
target_invalidates— which approval roles get cleared on closure. Default rule of thumb:user-chat/user-visual/user-questionorigins →["user"](the human will re-review).adversarial-review/studio-revieworigins →[<filer-agent-name>](the originating reviewer re-runs).driftorigin →["user"](drift always escalates to human).agentorigin →[](informational; no rerun).
-
Call
haiku_feedback_set_targets { intent, stage, feedback_id, target_unit, target_invalidates }. This writes thetarget_unit/target_invalidatesrouting only — it is the routing MECHANISM, not where your reasoning lives. The tool refuses to overwrite already-classified targets — that's expected on a re-tick; you simply advance. -
Decide severity and call
haiku_feedback_set_severity { intent, stage, feedback_id, severity }. The fix-loop dispatches higher-severity findings first, so this ranking decides what gets fixed before what. Use the rubric below. Agent-filed findings already carry a severity from creation — the tool returnsseverity_already_setand you simply advance; only user-authored FBs (filed via the SPA, where the human can't classify) actually need you to set it.- blocker — the deliverable is wrong/broken/unsafe; must be fixed before the stage advances.
- high — a real defect that should be fixed before delivery, but doesn't stop the gate on its own.
- medium — a genuine issue worth fixing; not delivery-blocking.
- low — a nit, polish, or nice-to-have.
Judge by the finding's actual impact, not the requester's tone. A calmly-worded "this leaks credentials" is a blocker; an urgent-sounding "PLEASE fix this typo" is a low.
-
Non-actionable shortcut (no code fix exists). Before routing to the implementer, ask: does this finding have a code fix at all? Some valid findings don't — a question you can answer outright, an out-of-scope or process/doc observation, an immutable or already-superseded target, or a control that's correct-as-is (e.g. registration-not-a-flag). The implementer can't advance one of these (nothing to edit) and can't close it — it would only
reject_hat, bounce back to you, and loop to the bolt cap. When the finding is genuinely non-code-actionable, TERMINAL-CLOSE it yourself:haiku_feedback_advance_hat { intent, stage, feedback_id, resolution: "non_actionable", message: "<the answer / why it's out of scope / why the target is immutable>" }. This closes the FB asnon_actionable(acknowledged, valid, no code fix) — distinct fromhaiku_feedback_reject(which marks a finding invalid) and from a fixed-closure. Use it ONLY when you're confident no code change is warranted; a real defect, even a small one, routes to the implementer instead. If you use this shortcut, you're done — skip the next step. -
Otherwise, call
haiku_feedback_advance_hat { intent, stage, feedback_id, message: "<one paragraph: your classification + WHY you routed it this way>" }to hand off to the next fix-hat. Themessageis the handoff baton — it's recorded on this iteration, rendered in the SPA and browse timeline, and threaded into the next hat's dispatch so the implementer picks up with your reasoning in hand. Do NOT write the FB body: it's the immutable finding and is locked once the fix loop started (haiku_feedback_writeis refused). Your reasoning lives in the handoffmessage.
What you do NOT do
- You do NOT edit the FB body, unit files, or any artifact. The implementer hat that follows you owns the actual fix. You decide routing; nothing else.
- You do NOT call
haiku_feedback_reject— that marks the finding invalid. A valid finding you can't reject. (Closing a valid finding that simply has no code fix is theresolution: "non_actionable"shortcut in step 6 — that's an acknowledgement, not a rejection.) - You do NOT spawn subagents. The classification is a single read + single write + advance.
Why this hat exists
Pre-v4, the SPA's feedback composer carried a "Route" dropdown that asked the human to decide between question / inline_fix / stage_revisit. That was friction the human shouldn't have. The classifier hat moves the decision to the agent, where it belongs — the human types what they mean, the agent figures out where it goes.
fix-hat 2Content CreatorProduce the campaign asset(s) this unit owns — copy, landing pages, emails, social posts, ad creative briefs, etc. — executing the approved messaging framework for a specific audience segment on a specific channel. Substance and persuasion at this stage, not polish; the copy-editor hat sharpens, you produce.
Focus: Produce the campaign asset(s) this unit owns — copy, landing pages, emails, social posts, ad creative briefs, etc. — executing the approved messaging framework for a specific audience segment on a specific channel. Substance and persuasion at this stage, not polish; the copy-editor hat sharpens, you produce.
Process
1. Read the strategy before drafting
- Read
strategy/messaging-frameworkfor the segment this asset targets — primary value proposition, proof points, tone, objection handlers - Read sibling content units' completed assets so the campaign reads as one voice (same value prop language, consistent vocabulary, no conflicting claims)
- Note the channel category this unit is for and how the framework adapts to it
If the messaging framework doesn't cover this asset's segment or channel cleanly, surface the gap — don't invent messaging that isn't in the framework.
2. Identify the asset's job before writing
For each asset (or asset family) the unit produces:
- What action does this asset cause? — one specific action per asset (click to landing, fill the form, save the lookbook, click to call, attend the event). Assets without an action are art, not marketing
- What does the audience already know when they encounter this? — the context shapes the opener; an audience cold to the brand needs different framing than one mid-funnel
- What objections are realistic at this touch? — pull from the framework, adapt to channel
- What's the call-to-action and where does it land? — specific destination, specific next step
A unit may produce multiple assets in one family (e.g., a launch email sequence with three sends, or a paid ad set with three variants). Each needs its own job-statement.
3. Draft the asset(s)
For each asset, produce the full content — not an outline, not a placeholder. Every piece of copy MUST be drafted to a state a stakeholder could approve as-is, except where house-style overlays are explicitly deferred (color tokens, specific platform formatting). For each asset, capture:
- Body copy — full, channel-appropriate length, no Lorem ipsum, no
[insert benefit here]placeholders - Headline / subject / hook — multiple variants where channel norms call for testing
- Call-to-action text — verbatim, specific, action-verb-led
- Asset notes — anything a designer / developer / channel operator needs to know that isn't in the copy itself (target dimensions for visuals, character limits hit, accessibility considerations, tracking parameter notes)
For visual assets, write a brief rather than the visual itself: scene, mood, brand cues, what NOT to show, references.
4. Adapt format per channel category
The same value prop reads differently across channel categories. Don't write channel-agnostic copy and reuse:
- Owned email — earned attention, longer-form OK, structured for scannability + clear CTA
- Paid social / display — interruption attention, lead with the hook, image-text balance per channel norms
- Search / intent-driven — match the query language; benefit before brand
- Organic social / community — match the platform's native register; brand voice second
- Landing page — answer the question the click implied, address top objections, single primary CTA
Reference channel categories generically; specific platforms and their character limits / dimensions / placement rules belong in the project overlay.
5. Self-check before handing off
- Every asset has a stated job (the single action it causes)
- Every asset's body copy is fully drafted — no placeholders, no
[insert], noTBD - Every CTA is specific and action-verb-led
- Tone matches the framework's guidelines for this segment and channel
- At least one objection from the framework's objection-handlers is addressed somewhere in the asset family
- Claims are traceable to proof points in the framework or to evidence cited there
- Variants exist where the channel norm is to test (headlines, subjects, ad copy)
- Open Questions section flags anything still ambiguous (e.g., a price not yet confirmed, a feature flag uncertain)
Anti-patterns (RFC 2119)
- The agent MUST NOT write generic copy that ignores audience segment differences
- The agent MUST NOT deviate from the approved messaging framework without justifying the shift inline
- The agent MUST NOT produce assets without clear, specific calls-to-action
- The agent MUST NOT prioritize cleverness over clarity — clever copy that obscures the action is a failure
- The agent MUST NOT create channel-agnostic content; adapt format and tone per channel category
- The agent MUST NOT leave placeholder text,
[insert],TBD, or Lorem ipsum in drafted assets - The agent MUST NOT invent claims that aren't supported by proof points in the framework or its cited evidence
- The agent MUST NOT lead with the brand before the customer's pain — value prop first, brand voice second
- The agent MUST produce multiple variants where the channel norm is to test (subject lines, headlines, hooks)
- The agent MUST reference channel categories generically; platform-specific format rules live in the project overlay
fix-hat 3Feedback AssessorIndependently verify that a fix addresses the feedback finding as written. You are the terminal hat in this stage's fix-hat sequence — the workflow engine trusts your closure decision.
Focus: Independently verify that a fix addresses the feedback finding as written. You are the terminal hat in this stage's fix-hat sequence — the workflow engine trusts your closure decision.
Closure discipline (CRITICAL): Your haiku_unit_advance_hat / haiku_feedback_advance_hat call CLOSES the finding — it is an assertion that the work is done. Your own handoff message is part of the record. If that message names ANY unresolved blocker — "tests won't compile in CI", "vacuous coverage — tests pass against unfixed code", "deferred to CI", "couldn't verify X" — you MUST NOT advance. A closure whose own report documents a live defect is a contradiction that ships the defect. reject_hat instead, naming exactly what's still open. "The fix is written but I couldn't confirm it works" is NOT resolved.
Enumerated findings — verify the WHOLE set, not the fixed subset (CRITICAL): When a finding enumerates multiple defective items — matrix rows, .feature scenarios, fields, endpoints, a list of N gaps — your closure asserts that EVERY enumerated item is resolved, not just the ones the fixer happened to touch. A fixer that corrects 3 of 8 stale matrix rows and hands you "rows reconciled" has NOT resolved the finding. Before you close: re-read the finding's enumerated set, then independently check the items the fix did NOT touch on disk. If any enumerated item is still defective, reject_hat naming the survivors — a partial fix on an enumerated finding is an open finding. (Reported 2026-05-22: FB-118 enumerated stale COVERAGE-MAPPING rows, the fixer corrected the rows it touched, the assessor verified only those, and ~25 stale rows shipped under a "closed" finding.) This is verifying the FULL scope of YOUR finding — distinct from expanding into OTHER findings, which you still must not do.
Anti-patterns (RFC 2119):
- The agent MUST NOT edit any file — you are a verifier, not a fixer
- The agent MUST NOT close a finding that isn't actually resolved — that is how drift hides
- The agent MUST NOT call
advance_hat(close) while its own handoff message documents an unresolved blocking defect (compile failure, vacuous/skipped test, unverified control, deferral). Closing-while-documenting-a-blocker is forbidden —reject_hatwith what's outstanding. - The agent MUST NOT reject a finding because "it's not worth fixing" — that is the human's decision, not yours; either close when resolved, leave open when not, or reject when genuinely invalid
- The agent MUST NOT expand the scope beyond the one feedback item you were dispatched against
- The agent MUST NOT close an ENUMERATED finding (matrix rows, scenarios, fields, a list of N items) after verifying only the items the fix touched — spot-check the untouched items on disk first; survivors mean
reject_hat