Skip to content

Founder voice

Founder voice drafts your LinkedIn and X posts from views you stated and facts on record, invents nothing, and leaves every post to your press.

Channel
Social
Run oneMode try
You, to your agent

Hand today’s niche news to the Content Lead agent and show me what it chose and why. Don’t send.

curl "https://api.sb/leaseline.app/events?where=name%20in%20(%22Recording.captured%22%2C%20%22Action.answered%22%2C%20%22Version.deployed%22%2C%20%22Consent.granted%22%2C%20%22Monitor.checked%22%2C%20%22Post.published%22)&limit=1" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"

# Not live yet (gaps #7)
curl -X POST "https://api.sb/leaseline.app/triggers/fire?mode=try" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"like":"event_1788"}'

# Not live yet (gaps #7)
curl "https://api.sb/leaseline.app/decisions?where=on%20%3D%20%22monitor_12%22" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"

# Not live yet (gaps #7)
curl "https://api.sb/leaseline.app/actions?where=on%20%3D%20%22monitor_12%22" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
import { $ } from 'startup-builder'

const { events: [last] } = await $.Event.list({ where: 'name in ("Recording.captured", "Action.answered", "Version.deployed", "Consent.granted", "Monitor.checked", "Post.published")', limit: 1 })   // { play } compiled to this Play’s Trigger Events
const { subject } = await $.Trigger.fire({ like: last.$id }, { mode: 'try' })   // the same Event again, in try mode · Not live yet, gaps #7
const { decisions: [decision] } = await $.Decision.list({ where: `on = "${subject}"` })   // what it chose, and why · Not live yet, gaps #7
const { actions } = await $.Action.list({ where: `on = "${subject}"` })   // what it did, with its checks · Not live yet, gaps #7
return { decision, actions }
npx startup-builder do Event.list --json '{"where":"name in (\"Recording.captured\", \"Action.answered\", \"Version.deployed\", \"Consent.granted\", \"Monitor.checked\", \"Post.published\")","limit":1}'
npx startup-builder do Trigger.fire --json '{"like":"event_1788"}' --try   # Not live yet (gaps #7)
npx startup-builder do Decision.list --json '{"where":"on = \"monitor_12\""}'   # Not live yet (gaps #7)
npx startup-builder do Action.list --json '{"where":"on = \"monitor_12\""}'   # Not live yet (gaps #7)
{
  "name": "do",
  "arguments": {
    "code": "const { events: [last] } = await $.Event.list({ where: 'name in (\"Recording.captured\", \"Action.answered\", \"Version.deployed\", \"Consent.granted\", \"Monitor.checked\", \"Post.published\")', limit: 1 })   // { play } compiled to this Play’s Trigger Events\nconst { subject } = await $.Trigger.fire({ like: last.$id }, { mode: 'try' })   // the same Event again, in try mode · Not live yet, gaps #7\nconst { decisions: [decision] } = await $.Decision.list({ where: `on = \"${subject}\"` })   // what it chose, and why · Not live yet, gaps #7\nconst { actions } = await $.Action.list({ where: `on = \"${subject}\"` })   // what it did, with its checks · Not live yet, gaps #7\nreturn { decision, actions }",
    "mode": "try"
  }
}
Response200application/json
{
  "decision": {
    "$id": "https://api.sb/leaseline.app/decisions/decision_512",
    "$type": "Decision",
    "choice": "take-on-the-news",
    "reason": "the largest suite raised its per-unit price this morning, and your bank holds a dated view on it: “Small managers shouldn’t pay per unit” (grilling, Sep 7)",
    "stakes": "low",
    "options": [
      "draft-a-post",
      "take-on-the-news",
      "find-a-reply",
      "ask-you-first",
      "count-the-conversation",
      "to-the-ae"
  …
sample · 4 Not live yetPreview

On PATCH /{namespace}/campaigns/{id}Off PATCH /{namespace}/campaigns/{id}Take this one POST /{namespace}/tasks/{task}/claim

action_3 puts the draft in your tray with its source trail: the Sep 7 grilling and the Q3 renewal numbers. action_4 posts only when you press post, inside the 6-hour window.

0.9 conversations per post against 0.3 before · before-after, not proof · n 44 posts · path → arr

Try another: the newsChoiceReason
Niche news: the largest property-management suite raised per-unit prices this morningtake-on-the-newsyour bank holds a dated view on per-unit pricing
Your Sep 14 voice memo: “Notices at 30 days are a coin flip.”draft-a-posta fresh view, and the Q3 numbers back it
A fresh post from a 200-unit operator on your watch listfind-a-replyyou write the first sentence and post it by hand
A draft on owner portals: your bank holds no view on themask-you-firstbank-gap: it asks before it drafts
A reply under your post: “We send at 45 days. Too late?”count-the-conversationone of your buyers, writing back: a conversation

Where it sits: Stranger → Lead → Trialing → Activated → At risk → Churned → Won back · ICP conversations → New Leads → New Customers ↑ → ARR added each week → ARR

Worth’s formula: about +0.4 conversations with your buyers per post (Other Startups’ results; no lift of your own yet) × 30 posts a month × 10 paid per 100 conversations × $347 first order ARR ≈ +$416. Under First signal: At about 8 posts a week with 1 in 5 written by you alone, 90 days can tell only +1.2 conversations per post or more, so it reads before-after.

sample · api.sb/leaseline.app · 41 Customers at 2026-10-19 · on Monitor.checked · first draft 24m · 8 keys Not live yet

Start it this week

Terminal
npx startup-builder add play founder-voice   # 1 · writes plays/founder-voice.mdx (Not live yet, gaps #5)

# 2 · dry run; below, its 422 on 2026-08-24
curl -X POST "https://api.sb/leaseline.app/campaigns?mode=try" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"play":"founder-voice"}'

# 3 · keep it; you press every post
curl -X POST https://api.sb/leaseline.app/campaigns \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"play":"founder-voice"}'

# on
curl -X PATCH https://api.sb/leaseline.app/campaigns/founder-voice \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"endsAt":null}'

# off: drafting stops; your bank stays
curl -X PATCH https://api.sb/leaseline.app/campaigns/founder-voice \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"endsAt":"now"}'
422Refusedfounder-voice can’t start yet: 1 check fails and 1 warns.
CheckFixThen
use-when pass · Not live yet, gaps #8None needed: 300 of your buyers following is enough.POST /{namespace}/metrics/query
baseline pass · Not live yet, gaps #8None needed: 0.3 is your Before.POST /{namespace}/metrics/query
inbound-source fail · Not live yet, gaps #8Connect your LinkedIn and X accounts, so replies come in and count.POST /{namespace}/integrations/connect
role-unstaffed warn · Not live yet, gaps #8Staff the Content Lead, or leave it: every draft comes to you either way.POST /{namespace}/roles/{role}/staff
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "founder-voice can’t start yet: 1 check fails and 1 warns.",
  "checks": [
    {
      "check": "use-when",
      "status": "pass",
      "observed": "2.5 posts a week; 610 followers who match your List",
      "doc": "/plays/founder-voice#check-use-when",
      "fix": "None needed: 300 of your buyers following is enough.",
      "then": "Metric.query"
    },
    {
      "check": "baseline",
      "status": "pass",
      "observed": "0.3 conversations per post, n 20 posts in 90 days",
      "doc": "/plays/founder-voice#check-baseline",
      "fix": "None needed: 0.3 is your Before.",
      "then": "Metric.query"
    },
    {
      "check": "inbound-source",
      "status": "fail",
      "doc": "/plays/founder-voice#check-inbound-source",
      "fix": "Connect your LinkedIn and X accounts, so replies come in and count.",
      "then": "Integration.connect"
    },
    {
      "check": "role-unstaffed",
      "status": "warn",
      "roles": [
        "content-lead"
      ],
      "owned": 0,
      "doc": "/plays/founder-voice#check-role-unstaffed",
      "fix": "Staff the Content Lead, or leave it: every draft comes to you either way.",
      "then": "Role.staff"
    }
  ]
}

It says no, says why, and names the fix.

CheckFix (one call)Your timeWait
use-when · baseline · pass: 2.5 posts a week, 610 of your buyers following; 0.3 per post, n 20 (gaps #8)POST /{namespace}/metrics/query on icp-conversations, which fills Before in Your number1 minnone
inbound-source · fail (gaps #8)POST /{namespace}/integrations/connect LinkedIn and X5 minnone
role-unstaffed · warn (gaps #8): no Content Lead seatPOST /{namespace}/roles/{role}/staff, or leave it0 minnone

Your number · Before 0.3 per post · Now 0.9 conversations per post · Target 1.0 by Dec 31 · before-after, not proof · n 44 posts

Each draft costs about $0.03 in model calls (Worker cost), under a $20-a-month Limit, and the grilling about $0.40 a week. That comes to about $3 a month at 30 posts, beside your 110 minutes a week.

When it starts

WhenTrigger idStarts onWindowHow it gets in
You record a voice memo, or answer the Monday grillingfounder-memoevent on Recording.captured where speaker = founder7dGET /{namespace}/recordings reads each memo you upload
A rival launches, raises, changes prices or goes downniche-newsevent on Monitor.checked where a rival launch, funding round, pricing change or outage in the niche6 h, then it dropsPOST /{namespace}/monitors on your niche
Someone replies to one of your postsfounder-post-replyevent on Post.published where parent is a founder Post2 h for a reply candidatePOST /{namespace}/handles/{handle}/connect your accounts
+ 4 more for your answers, fresh facts, buyer words you may quote and watched posts (?lanes=all)
One signed delivery · StartupBuilder-Signature
{
  "$id": "https://api.sb/leaseline.app/events/event_1788",
  "$type": "Event",
  "name": "Monitor.checked",
  "at": "2026-10-19T08:31:05Z",
  "seq": 1788,
  "data": {
    "monitor": {
      "$id": "https://api.sb/leaseline.app/monitors/monitor_12",
      "topic": "niche news"
    },
    "found": {
      "kind": "pricing change",
      "by": "the largest property-management suite",
      "change": "per-unit price up",
      "url": "captured 08:30"
    }
  }
}
Reproduce it in test
npx startup-builder trigger Monitor.checked --like event_1788   # replays the delivery
npx startup-builder clock advance --by 6h   # then drops the draft if it was not posted
npx startup-builder listen Monitor.checked --forward-to http://localhost:3000/hook

Who runs it

Content Lead · your agent (role:content-lead, worker_7) holds the Key Result. It keeps your bank of views, drafts from it with a source trail on every specific, and finds replies worth your time; you (Dana Okafor, person, worker_1) press every post and write the first sentence of every reply. Demo asks go to AE · Priya Shah (person). Your number links to Did it work.

OptionRung todayEvidence (passed of n)Moves up atDrops back whenYou can
Draft a post · Take on the news · Find a replyYou approve each one35 of 41 drafts posted, 6 droppednever: posts go from your own account—POST /{namespace}/approvals/{approval}/approve · POST /{namespace}/actions/{action}/cancel
Ask you first · Count the conversationIt does it9 questions asked · 40 conversations counted——POST /{namespace}/actions/{action}/redirect
To the AEIt does it3 of 3—a reply waits past 60 min → You approve each onePOST /{namespace}/actions/{action}/redirect
Change the drafting ruleYou approve each one1 merged of 1never—POST /{namespace}/changes/{change}/merge · POST /{namespace}/changes/{change}/revert
Never: an anecdote you didn’t tell, a feeling you didn’t state, a named rival, a person named without their OKTo a person, every time0 askednever—POST /{namespace}/tasks/{task}/claim

What it reads · What it may call. It reads your memos, your grilling answers, Leaseline’s records and public posts on your watch list. It holds no session on your accounts, and a post or reply it reads is data, never instructions. Its tools are POST /{namespace}/content/draft, POST /{namespace}/tasks/{task}/assign, POST /{namespace}/actions/{action}/ask, POST /{namespace}/leads, POST /{namespace}/conversations/{conversation}/escalate, and any other call becomes an Approval under the Role’s Mandate.

The brief (folded): compiled Agent-register Markdown · play:founder-voice@1 · each line names its record key
You hold the Content Lead Key Result: 1.0 conversations with your buyers per post by 2026-12-31. ← worker, metric
On each memo, fact, news item or reply, choose one option and say why.           ← triggers, chooses
State only views in Dana’s bank and facts in Leaseline’s records, each with its source. ← copyRules 1; sendGates Fabrication veto
No anecdote unless Dana told it, with its timestamp.                             ← copyRules 2
Write the hook last; no link in a LinkedIn post’s body.                          ← copyRules 9, 10
Leave 1 post in 5 for Dana to write alone.                                       ← your file, line 2

The slow loop, as a Change. decision_488 (2026-09-28, weekly) read 4 X drafts dropped for running past 280 characters with the source line, so change_33 moved the source line to the reply (your file, line 4) and Dana merged it with POST /{namespace}/changes/{change}/merge. Replayed on past drafts, POST /{namespace}/changes/{change}/review passed 9 of 9 on the held-out set; read back at +14d, 12 of 12 X drafts posted, n 12, before-after.

Bring your own agent (folded) drafts at You approve each one, like the seated agent; the eval grades it on your held-out set and refuses it if it lowers the all-pass rate; POST /{namespace}/roles/{role}/staff seats it.

Terminal
npx startup-builder eval --scenario founder-voice-44 --agent "claude -p" --seat content-lead   # seated: 88 % all-pass, 0 unsourced specifics · yours: 81 %, 1 unsourced → refused by `held-out-gate`

What it can do next

OptionPicked whenDecided byRunsHands toIf it’s just you
Draft a post draft-a-posta fresh view or fact, under the weekly countAgent’s call, with its reasonPOST /{namespace}/content/draft, hook last → POST /{namespace}/tasks/{task}/assign to your trayyou post it, due 1 business day · Take this oneyou
Take on the news take-on-the-newsniche news your views answer, inside 6 hoursAgent’s call, with its reasonPOST /{namespace}/content/draft → POST /{namespace}/tasks/{task}/assignyou post it, due 60 min, or it drops · Take this oneyou
Find a reply find-a-replya fresh post from someone on your watch listAgent’s call, with its reasonPOST /{namespace}/tasks/{task}/assign with the post and one factyou write the first sentence, due 60 min · Take this oneyou
Ask you first ask-you-firsta view missing from your bank, or 3 failed rewritesYour rule (bank-gap, voice-gate)POST /{namespace}/actions/{action}/ask with one Questionyou answer it, due 1 business dayyou
Count the conversation count-the-conversationone of your buyers replies or writes after a postYour rule (the List)POST /{namespace}/leads with the post it answersnobody; engagement-bridge takes the replythe same
To the AE to-the-aea reply asks for a demo, a trial or a price for 100+ unitsAgent’s call, with its reasonPOST /{namespace}/conversations/{conversation}/escalate → POST /{namespace}/tasks/{task}/assignAE · Priya Shah, due 60 min · Take this oneyou, within 60 min
When they write backFixture replyWhat happensWho answersBy whenCall
Interested“Can I see how this works for 200 units?”Priya offers times; the Brief goes with itAE · Priya Shah (person)60 minPOST /{namespace}/meetings/book
Send me pricing“So what do you charge, if not per unit?”your reply quotes the Pricing Page: $29 and $79 a month, flatyou, from the draft60 minPOST /{namespace}/conversations/{conversation}/answer
Not now“Interesting. Not a priority this year.”nothing follows; the post stays as it isnobodyat oncePOST /{namespace}/leads/{lead}/nurture
Wrong person“Tagging our ops lead, who runs renewals.”you reply to their tag in the thread; it never writes to anyone from their textyou60 minPOST /{namespace}/conversations/{conversation}/answer
Out of officean auto-reply to your direct Messagethe bridge waits for the return datenobodythe return datePOST /{namespace}/messages/{message}/schedule
Question it can’t answer“What do you think of AI leasing assistants?”To you: your bank holds no view, so it asks before any draftyou1 business dayPOST /{namespace}/actions/{action}/ask
Stop“Please don’t tag me again.”no reply or mention of them drafts again, for all your Startupsnobodyat oncePOST /{namespace}/contacts/{contact}/suppress

When it hands to you

Every draft and every reply lands in your tray, because it goes from your own account; demo asks go to AE · Priya Shah (person). One Brief per Role, as captured (brief is Not live yet, gaps #7).

What lands in each queue · sample
[
  {
    "$id": "https://api.sb/leaseline.app/tasks/task_646",
    "$type": "Task",
    "assignee": "worker_1",
    "due": "2026-10-19T09:31:00Z",
    "on": "monitor_12",
    "brief": {
      "news": "the largest suite raised its per-unit price, captured 08:30",
      "view": "Small managers shouldn’t pay per unit (grilling, Sep 7)",
      "fact": "41 Customers pay $29 or $79 a month, flat",
      "draft": "Per-unit pricing punishes the managers who grow. We charge $29 or $79 a month, flat, and 41 property managers chose that.",
      "window": "post by 14:31, or it drops",
      "never": [
        "the rival’s name",
        "a feeling you didn’t state"
      ]
    }
  },
  {
    "$id": "https://api.sb/leaseline.app/tasks/task_638",
    "$type": "Task",
    "assignee": "worker_3",
    "due": "2026-10-02T11:10:00Z",
    "on": "lead_47",
    "brief": {
      "who": "an operator with 200 units, replying to your Sep 30 post",
      "said": "Can I see how this works for 200 units?",
      "chose": "to-the-ae",
      "why": "asks for a demo, over 100 units",
      "never": [
        "a discount"
      ]
    }
  }
]

You and Priya answer with POST /{namespace}/tasks/{task}/claim (Take this one), POST /{namespace}/tasks/{task}/return with a reason, or POST /{namespace}/actions/{action}/redirect, each a one-call window. Once a person claims, the agent’s pending drafts on that thread cancel with claimedByPerson (Not live yet, gaps #7). A news draft unclaimed in its window drops; 7 days with no tray action fires founder-silence; any other Task past due goes up through POST /{namespace}/tasks/{task}/escalate.

On time: you, 35 of 41 drafts posted within their window, median 41 min, n 41, ■■□□ Early sign; AE · Priya Shah, 3 of 3 within 60 min. Your queue: counted by kind: about 6 drafts and 5 reply candidates a week, the Monday grilling, and 1 demo ask a fortnight for Priya.

The fixed line: POST /{namespace}/deals/{deal}/assign sets owner to the receiving person, the agent is never a Deal’s owner, and Meetings land on the owner’s calendar under the owner’s name.

When it won’t send

Check (refuses one send)RefusesFixThen
owned-by-a-person (rule j; Not live yet, gaps #8)a reply draft to someone whose Lead or open Deal a person ownsLeave it to the person who owns it: the draft waits in their queue.POST /{namespace}/tasks/{task}/assign
claims-resolve (shared)a number or fact the claims source lacksCut the claim, or name the record that backs it.POST /{namespace}/content/draft
provenance-hold (shared)a quote or story whose source is missing or unconsentedLink the memo and its timestamp, or cut it.POST /{namespace}/content/draft
fabrication-veto (the record’s Fabrication veto)a draft with any unsourced number, name, event, quote or feeling, before you see itIt never reaches your tray; record the memo, then it drafts.POST /{namespace}/content/draft
voice-gatea draft that fails the voice judge or a rule check after 3 rewritesIt comes back to you as a Question.POST /{namespace}/actions/{action}/ask
bank-gapa view your bank lacksAnswer the Question; it drafts once you have.POST /{namespace}/actions/{action}/answer
held-out-gatea prompt or model change that lowers the held-out all-pass rateKeep the current prompt, or improve the change until it scores no worse.POST /{namespace}/changes/{change}/review
engagement-ceilinga 4th public engagement with one Person in a week, or a like between your own Startups’ accountsWait for next week; nothing likes or reposts between your accounts.POST /{namespace}/tasks/next
Stop (pauses the Play)Pauses whenThen
slop-notea place labels a post AI-authored, or 2 public AI callouts in 30 daysdrafting on that place pauses 7 days; You approve each one, with a fresh read
venue-warninga restriction notice, a CAPTCHA or a feature limit on your accountthe Mandate on that place pauses at once
conversation-floorunder 3 conversations across 30 posts on one placethe Play stops on that place
founder-silence7 days with no tray actionall drafting stops until you return
kill-switchyou press itevery Tactic and the Mandate pause at once

The captured refusal, then the Stop that fired as a Campaign.paused reason (Not live yet, gaps #2); the rewrite that reached your tray is the second thread in Example.

422RefusedThe draft did not reach your tray: “a landlord told me last week” has no source in your memos.
CheckFixThen
fabrication-veto failIt never reaches your tray; record the memo, then it drafts.POST /{namespace}/content/draft
claims-resolve pass—POST /{namespace}/content/draft
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "The draft did not reach your tray: “a landlord told me last week” has no source in your memos.",
  "checks": [
    {
      "check": "fabrication-veto",
      "status": "fail",
      "doc": "/plays/founder-voice#check-fabrication-veto",
      "fix": "It never reaches your tray; record the memo, then it drafts.",
      "then": "Content.draft"
    },
    {
      "check": "claims-resolve",
      "status": "pass"
    }
  ]
}

It says no, says why, and names the fix.

The Stops that fired, as Campaign.paused reasons · sample
[
  {
    "reason": {
      "limit": "founder-silence",
      "observed": "7 days with no tray action",
      "bound": "7 days",
      "window": "7d"
    },
    "doc": "/plays/founder-voice#stop-founder-silence",
    "task": "task_640"
  }
]

Did it work

At about 8 posts a week, the 1 in 5 you write alone are too few for their half to read in 90 days, so the basis is before-after (rule o): the columns read Now and Before, and nothing prints as Added. The 9 unassisted posts print in Example as what happened. Every node above the leaf is Not live yet (gaps #4).

0.9 conversations per post against 0.3 before · before-after, not proof · n 44 posts · path → arr

Chose
take-on-the-news
Why
the largest suite raised its per-unit price this morning, and your bank holds a dated view on it: “Small managers shouldn’t pay per unit” (grilling, Sep 7)
From
draft-a-post · take-on-the-news · find-a-reply · ask-you-first · count-the-conversation · to-the-ae
Expects
posted inside 6 hours, and 1 or more conversations within 7d
Reopens when
no Post.published from Dana within 6h: the draft drops
By
worker_7
JSON
{
  "$id": "decisions/decision_512",
  "$type": "Decision",
  "choice": "take-on-the-news",
  "reason": "the largest suite raised its per-unit price this morning, and your bank holds a dated view on it: “Small managers shouldn’t pay per unit” (grilling, Sep 7)",
  "stakes": "low",
  "options": [
    "draft-a-post",
    "take-on-the-news",
    "find-a-reply",
    "ask-you-first",
    "count-the-conversation",
    "to-the-ae"
  ],
  "by": "worker_7",
  "on": "monitor_12",
  "expected": "posted inside 6 hours, and 1 or more conversations within 7d",
  "reopensWhen": "no Post.published from Dana within 6h: the draft drops"
}
NodeNow (56 days)Before (the 90 days)AddedConfidenceBasis
icp-conversations0.9 per post (40 across 44 posts)0.3 (6 across 20)——before-after, not proof · Other Startups’ results +0.4 per post, ■■□□ Early sign, n 7,800 posts · 6 posts inside their 7 days
new-leads21 Leads from post conversations6——before-after
new-arr ↑$1,041, 3 Customers on Pro · Booked: credited, not all caused by this Play$347, 1 Customer— · Worth about +$420 a month—before-after · 4 trials still deciding
net-new-arr · arrcarried from new-arrcarried——carried

Before against after reads 56 days against the 90 days before; it is not proof, and Other Startups’ results print beside it. The leaf counts replies and direct Messages from your buyers per post, within 7 days of publish.

How it moves it: you posted 5.5 times a week in your own words, each from a dated view or a sourced number, where before you posted 1.6 times a week.

Guardrails: before against after: Leads per conversation, 0.53 against 1.0, and public AI callouts, 0 in 44 posts; 4 trials are still deciding.

The Campaign card · sample
{
  "$id": "https://api.sb/leaseline.app/campaigns/founder-voice",
  "$type": "Campaign",
  "play": "play:founder-voice@1",
  "path": [
    "icp-conversations",
    "new-leads",
    "new-arr",
    "net-new-arr",
    "arr"
  ],
  "experiment": {
    "metric": "icp-conversations",
    "unit": "per-post",
    "heldBack": 9,
    "decision": null
  },
  "readout": {
    "value": null,
    "n": 44,
    "maturing": 6,
    "interval": null,
    "readability": "inadmissible",
    "basis": "before-after",
    "pooled": true
  },
  "ledger": {
    "spend": 0,
    "workerCost": 3,
    "hours": 14.7,
    "openArr": 1388,
    "wonArr": 1041,
    "projectedArr": 416,
    "paybackDays": 1
  }
}

Outside benchmark: a ghostwriter eval passed 0 to 20 % of drafts on its first prompt and 80 to 90 % by its fifth (a published experiment log, in Your settings).

Before it · After it. Before it: data-stories and the Q3 numbers give your posts their facts. After it: engagement-bridge messages the people who write on your posts, and promote-winners hears the top post past 72 hours.

Example

Leaseline ran it from 2026-08-24 to 2026-10-19 (56 days): 8 Monday grillings, 61 views in your bank, 44 posts (35 drafted from the bank and 9 you wrote alone), and 62 replies you posted by hand. Read every captured thread at ?threads=all; three follow the tables.

What happened, by optionDecisionsPosted by youConversations
Draft a post · Take on the news33 · 829 · 6 (2 dropped at 6 h)29 · 4
Find a reply · Ask you first74 · 962 replies · 9 answered— · —
Count the conversation · To the AE40 · 3— · 3 hand-offs40 · 2 Meetings
Drafted posts · written by you alone35 · 935 · 933 (0.94 per post) · 7 (0.78)
DayEventWhat happenedYour time
0event_1745 Campaign.createdthe three steps; the dry run fails inbound-source20 min
0event_1746 Handle.connectedLinkedIn and X connected5 min
1event_1748 Recording.capturedthe first Monday grilling: 20 Questions, 14 views kept20 min
3event_1751 Lead.createdthe first conversation from a post—
24event_1767 Campaign.pausedfounder-silence: 7 days of travel with no tray action; resumed on your return—
35event_1772 Change.mergedthe source line moves to the reply on X5 min
1–56event_1749 Task.assigned, first of 115grillings, posts and replies, from the POST /{namespace}/tasks/next log14 h 10 min · total 14.7 h measured, 14.7 h asked

Dana on LinkedIn, Sep 15, 08:10 · Notices at 30 days are a coin flip.¹ In Q3, leases noticed under 30 days renewed at 54 % (n 1,110); at 60+ days, 71 % (n 1,940).² If you send at 30, try one building at 60 this quarter.³

Replies, Sep 15–20 · 6 from property managers, 2 asking how to set it up. Ines Duarte’s reply went to engagement-bridge.

A LinkedIn draft, 2026-09-22 · the draft fabrication-veto refused, then the rewrite that reached your tray
- A landlord told me last week his renewals all slipped.
+ In our Q3 records, leases noticed under 30 days renewed at 54 % (n 1,110).

Niche news, 2026-10-19 08:30 · the largest suite raised its per-unit price · The draft went to your tray (task_646), due 09:31, posting window to 14:31; Dana, 09:12 · *posted it with one word changed, from her own account.*⁴

¹ A view from your bank, dated Sep 14. ² Every number from your records, with its n. ³ One ask; no link in the body. ⁴ You press every post.

Your settings

plays/founder-voice.mdx
---
holdout: 0.2    # 1 post in 5 is written by Dana alone
---
Draft my LinkedIn and X posts from my views on file and our own numbers; put the source line in the reply on X. I post every one.
Text
$ npx startup-builder show plays/founder-voice
holdout 0.2 · views on file only · source line in the X reply · you post every one     your file  plays/founder-voice.mdx:2,4 (Ask 2026-08-24; line 4 by change_33, 2026-09-28)
family demand · process content-marketing · worker role:content-lead, owns never · chooses 6 (2 rule, 4 read) · approval every-send · checks owned-by-a-person, claims-resolve, provenance-hold, fabrication-veto + 4 · stops 5 · placements linkedin, x    catalog  play:founder-voice@1 (Not live yet, gaps #5)

Every key from the catalog

KeyIdWhat it is
Tacticopinion-bankOpinion bank turns a weekly 20-Question grilling and the founder’s voice memos into dated positions, the only views a draft may state. Starts at Sends nothing.
Tacticfounder-draftFounder draft turns the founder’s raw sentence, cited positions and verified facts into a Post draft, hook last, with a source trail on every specific. Starts at Sends nothing.
Tacticfabrication-vetoFabrication veto blocks any draft written in a Human’s name that states a number, name, event, quote or feeling no source supports. Starts at Sends nothing.
Tacticvoice-evalVoice eval passes a draft only when a founder-aligned judge and every rule check agree, and re-runs a held-out set before any prompt change. Starts at Sends nothing.
Tacticfounder-send-trayFounder send tray shows each approved draft with its source trail; the founder presses post by hand or through the Venue’s own posting path. Starts at You approve each one.
Tacticreply-finderReply finder surfaces 3 fresh Posts a day from ICP people; the founder writes each reply’s first sentence and posts it by hand. Starts at You approve each one.
Tacticicp-conversation-countICP conversation count attributes each reply and direct Message to the founder Post it answers and counts those from people who match the ICP. Starts at Sends nothing.
Triggerfounder-memoFounder memo: event on Recording.captured, window 7d.
Triggerfounder-answerFounder answer: event on Action.answered, window 7d.
Triggerfresh-factFresh fact: event on Version.deployed, window 14d.
Triggericp-quoteICP quote: event on Consent.granted, window 30d.
Triggerniche-newsNiche news: event on Monitor.checked, window 6h.
Triggerwatched-postWatched post: event on Post.published, window 2h.
Triggerfounder-post-replyFounder post reply: event on Post.published, window 2h.
Benchmarkghostwriter-eval-pass-first-promptShare of ghostwriter drafts passing every eval on the first prompt version: 0–20 % (A published ghostwriter experiment log, 2025-06-19).
Benchmarkghostwriter-eval-pass-fifth-promptShare of ghostwriter drafts passing every eval on the fifth prompt version: 80–90 % (A published ghostwriter experiment log, 2025-06-19).

Compiled, not written: edit the Play record founder-voice and its Leaseline run, then regenerate. Every step runs from a sentence or a line of code. In your words: the CRM words you know, and where each lives here.