Skip to content

Organic social

Turns your own facts and shipped changes into one post a week per account, and drafts first-person posts that you send yourself.

Channel
Social
Run oneMode try
You, to your agent

Hand our latest recorded fact to the Content Lead agent and show me what it chose and why. Don’t post.

curl "https://api.sb/leaseline.app/events?where=name%20in%20(%22Fact.recorded%22%2C%20%22Version.deployed%22%2C%20%22Content.drafted%22%2C%20%22Handle.mentioned%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_1355"}'

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

const { events: [last] } = await $.Event.list({ where: 'name in ("Fact.recorded", "Version.deployed", "Content.drafted", "Handle.mentioned", "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 (\"Fact.recorded\", \"Version.deployed\", \"Content.drafted\", \"Handle.mentioned\", \"Post.published\")","limit":1}'
npx startup-builder do Trigger.fire --json '{"like":"event_1355"}' --try   # Not live yet (gaps #7)
npx startup-builder do Decision.list --json '{"where":"on = \"fact_31\""}'   # Not live yet (gaps #7)
npx startup-builder do Action.list --json '{"where":"on = \"fact_31\""}'   # Not live yet (gaps #7)
{
  "name": "do",
  "arguments": {
    "code": "const { events: [last] } = await $.Event.list({ where: 'name in (\"Fact.recorded\", \"Version.deployed\", \"Content.drafted\", \"Handle.mentioned\", \"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_538",
    "$type": "Decision",
    "choice": "post-the-fact",
    "reason": "a first-party fact recorded Oct 18 from your own records: Customers sent 1,204 renewal notices 60 days out in September, against 790 in August; Thursday’s Company Page slot is open",
    "stakes": "low",
    "options": [
      "post-the-fact",
      "draft-for-you",
      "answer-the-tag",
      "hand-the-angle-on",
      "to-a-person",
      "not-now"
  …
sample · 4 Not live yetPreview

On POST /{namespace}/processes/{process}/enableOff POST /{namespace}/processes/{process}/pauseTake this one POST /{namespace}/tasks/{task}/claim

action_3 is the 6-page document Post for Thursday 09:00, which you can stop until 08:45. action_2 adds the fact to the fact Page the Post ends at, where a reader leaves their email.

0.44 per 1,000 against 0.11 before · before-after, not proof · n 21 · path → arr

Try another: the factChoiceReason
Fact: 1,204 renewal notices sent 60 days out in September, against 790 in Augustpost-the-facta fresh first-party fact; Thursday’s slot is open
Dana’s seed: “Most late renewals I’ve seen start with one owner who never got the notice.”draft-for-youa seed you recorded: a first-person draft for you to send
@rentops_kim tagged the X account: “Does Leaseline handle owner approvals?”answer-the-tagthe claims source answers it: owner approvals shipped Sep 15
The Sep 11 renewal-timing Post: 9 Contacts on 4,100 impressions, 4 times the account’s medianhand-the-angle-onan outlier on Contacts; the angle goes on with its Evidence
Week of Oct 5: no new fact, no seednot-nowthe slot stays empty; nothing fills it with an opinion

Where it sits: Stranger → Lead → Trialing → Activated → At risk → Churned → Won back · Social-sourced Contacts → New Leads → New Customers ↑ → ARR added each week → ARR

Worth’s formula: about +0.25 consented Contacts per 1,000 impressions (Other Startups’ results; no lift of your own yet) × 26,000 impressions a month × 0.12 Contacts to paid × $347 Pro ARR ≈ +$271. Under First signal: At about 3 consented Contacts a week, alternating weeks cannot read, so your file reads before-after; every 6th week stays dark for the comparison Other Startups pool.

sample · api.sb/leaseline.app · 41 Customers at 2026-10-19 · on Fact.recorded · first draft 6m after the fact landed · 9 keys Not live yet

Also runs as: Engagement bridge.

Start it this week

Terminal
npx startup-builder add play organic-social   # 1 · writes plays/organic-social.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":"organic-social"}'

# 3 · keep it, at You approve each one
curl -X POST https://api.sb/leaseline.app/campaigns \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"play":"organic-social"}'

# on
curl -X POST https://api.sb/leaseline.app/processes/content-marketing/enable \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"

# off: scheduled Posts move back to draft
curl -X POST https://api.sb/leaseline.app/processes/content-marketing/pause \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
422Refusedorganic-social can’t start yet: 1 check fails and 2 warn.
CheckFixThen
use-when pass · Not live yet, gaps #8Nothing to do: it counts new facts and shipped changes a week.POST /{namespace}/metrics/query
baseline warn · Not live yet, gaps #8n 4: it reads before-after, not proof, until volume allows alternating weeks.POST /{namespace}/metrics/query
claims-resolve failPublish the facts Page; a Post may state only what it lists.POST /{namespace}/content/draft
owned-by-a-person pass · Not live yet, gaps #8Nothing to do: replies there draft into your queue.POST /{namespace}/tasks/{task}/assign
role-unstaffed warn · Not live yet, gaps #8Staff the Marketing Lead, or leave it: angles and replies come to you.POST /{namespace}/roles/{role}/staff
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "organic-social can’t start yet: 1 check fails and 2 warn.",
  "checks": [
    {
      "check": "use-when",
      "status": "pass",
      "observed": "3 first-party facts a week; LinkedIn page 1,840 followers, X 620",
      "doc": "/plays/organic-social#check-use-when",
      "fix": "Nothing to do: it counts new facts and shipped changes a week.",
      "then": "Metric.query"
    },
    {
      "check": "baseline",
      "status": "warn",
      "observed": "4 consented Contacts from social in 90 days, on 36,000 impressions",
      "doc": "/plays/organic-social#check-baseline",
      "fix": "n 4: it reads before-after, not proof, until volume allows alternating weeks.",
      "then": "Metric.query"
    },
    {
      "check": "claims-resolve",
      "status": "fail",
      "observed": "no facts Page: 0 facts a Post may cite",
      "doc": "/plays/organic-social#check-claims-resolve",
      "fix": "Publish the facts Page; a Post may state only what it lists.",
      "then": "Content.draft"
    },
    {
      "check": "owned-by-a-person",
      "status": "pass",
      "observed": "2 Conversations on X claimed by you",
      "doc": "/plays/organic-social#check-owned-by-a-person",
      "fix": "Nothing to do: replies there draft into your queue.",
      "then": "Task.assign"
    },
    {
      "check": "role-unstaffed",
      "status": "warn",
      "roles": [
        "content-lead",
        "marketing-lead"
      ],
      "owned": 2,
      "doc": "/plays/organic-social#check-role-unstaffed",
      "fix": "Staff the Marketing Lead, or leave it: angles and replies come to you.",
      "then": "Role.staff"
    }
  ]
}

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

CheckFix (one call)Your timeWait
use-when · baseline · pass: 3 facts a week; warn: 4 Contacts in 90 days (gaps #8)POST /{namespace}/metrics/query on social-sourced-contacts, which fills Before in Your number1 minnone
claims-resolve · fail: no facts PagePOST /{namespace}/content/draft the facts Page from your records, then POST /{namespace}/pages20 minnone
owned-by-a-person · pass: 2 Conversations you claimednothing; it runs again on every reply0 minnone
role-unstaffed · warn (gaps #8): 2 Conversations have a person owner, youPOST /{namespace}/roles/{role}/staff, or leave it: winning angles and person replies come to you0 minnone

Your number · Before 0.11 per 1,000 · Now 0.44 per 1,000 impressions · Target 0.5 by Dec 31 · before-after, not proof · n 21 Contacts · Other Startups +0.25, ■■■□ Likely

Each Post draft costs about $0.02 (Worker cost), and the voice judge and the fabrication veto about $0.01 more for a first-person draft. Posting on your own accounts costs nothing. That comes to under $1 a month at 8 Posts and 4 first-person drafts.

When it starts

WhenTrigger idStarts onWindowHow it gets in
A first-party fact lands in your recordsfact-recordedevent on Fact.recorded where source = 'first-party'fills a slot within 14dPOST /{namespace}/content on the facts Page, or a fact from POST /{namespace}/metrics/query
A change your Customers can see shipsversion-shippedevent on Version.deployed where visibleToCustomers = true72hPOST /{namespace}/versions/{version}/deploy
You record a raw sentence for your own profileseed-recordedevent on Content.drafted where kind = 'seed'7dPOST /{namespace}/content/draft with kind seed, from chat
+ 2 more: a tag on the agent account, and a Post that beat its account’s median on Contacts (?lanes=all)
One signed delivery · StartupBuilder-Signature
{
  "$id": "https://api.sb/leaseline.app/events/event_1355",
  "$type": "Event",
  "name": "Fact.recorded",
  "at": "2026-10-18T16:40:02Z",
  "seq": 1355,
  "data": {
    "fact": {
      "$id": "https://api.sb/leaseline.app/facts/fact_31",
      "text": "Leaseline Customers sent 1,204 renewal notices 60 days out in September, against 790 in August.",
      "source": "metrics/renewal-notices-sent",
      "asOf": "2026-09-30"
    }
  }
}
Reproduce it in test
npx startup-builder trigger Fact.recorded --like event_1355   # replays the delivery in test
npx startup-builder clock advance --to thursday-09:00   # publishes the scheduled Post (action_3)
npx startup-builder listen Consent.created --forward-to http://localhost:3000/hook

Who runs it

Content Lead · your agent (role:content-lead, worker_7) holds the Key Result and posts as the Startup from the Company Page and the labeled X account. It hands to you (Dana Okafor, person, worker_1) for every first-person Post, which you send, for replies that need a person, and as the Marketing Lead for winning angles, because that Role has no person. Your number links to Did it work.

OptionRung todayEvidence (passed of n)Moves up atDrops back whenYou can
Post it from the StartupIt does it, you can stop it14 of 15 approved uneditedmet on day 29 (the first 10 approved unedited, no Stop)any Stop on the account → You approve each onePOST /{namespace}/posts/{post}/withdraw or POST /{namespace}/actions/{action}/cancel before the slot
Answer the tag · Not nowIt does it, you can stop it6 of 6 · 2 of 2the samea summons-flood → You approve each onethe same
Draft it for your profileYou approve and send each one7 sent of 8 draftsnever: a first-person Post is yours to send—POST /{namespace}/approvals/{approval}/approve · POST /{namespace}/approvals/{approval}/refuse
Hand the angle on · To a personIt does it2 of 2 · 3 of 3——POST /{namespace}/actions/{action}/redirect
Change a slot ruleYou approve each one1 merged of 1never—POST /{namespace}/changes/{change}/merge · POST /{namespace}/changes/{change}/revert
Never: a like or follow ask, an outcome without the Customer’s OK, the agent as a personRefused, every time1 drafted, 1 refusednever—none: the Check holds it

What it reads · What it may call. It reads your facts Page, your Versions and your own seeds, and never a watched Event. The agent account never writes in the first person, and no text in a tag picks a link or a tool. Its tools are POST /{namespace}/posts/{post}/schedule, POST /{namespace}/content/draft, POST /{namespace}/approvals, POST /{namespace}/posts, POST /{namespace}/evidence, POST /{namespace}/tasks/{task}/assign, and any other call becomes an Approval under the Role’s Mandate.

The brief (folded): compiled Agent-register Markdown · play:organic-social@1 · each line names its record key
You hold the Content Lead Key Result: 0.5 consented Contacts per 1,000 impressions by 2026-12-31. ← worker, metric
On each fact, Version, seed or tag, choose one option and say why.               ← triggers, chooses
State only what the facts Page lists; a Customer outcome needs their OK and their words. ← copyRules 1, 3
The agent account never writes as a person or claims a feeling.                  ← copyRules 2
No like, repost or follow asks; no two accounts publish the same text.           ← copyRules 5, 8
No fresh fact and no seed: leave the slot empty.                                 ← chooses.not-now.when

The slow loop, as a Change. decision_310 (2026-09-21, weekly) read 4 LinkedIn document Posts with 11 Contacts and 3 text Posts with 1. change_23 made the Company Page slot a document Post by default (your file, line 6), and Dana merged it with POST /{namespace}/changes/{change}/merge. Replayed on past weeks, POST /{namespace}/changes/{change}/review put the page at 0.52 per 1,000; read back at +21d it is 0.48, n 9 Contacts, ■□□□ Too early to tell (Example, day 49).

Bring your own agent (folded) starts at It does it, you can stop it when it matches or beats the seated agent on the eval suite, and at You approve each one when it does not; POST /{namespace}/roles/{role}/staff seats it.

Terminal
npx startup-builder eval --scenario organic-social-48 --agent "claude -p" --seat content-lead   # seated: 0 claims failed sent, 1 sameness rejection, $0.02 a Post · yours: 1 claim failed → You approve each one

What it can do next

OptionPicked whenDecided byRunsHands toIf it’s just you
Post it from the Startup post-the-facta fresh fact, an open slot this weekYour rule (line 5)publish-content → POST /{namespace}/posts/{post}/schedule, ending at the facts Pagenobodythe same
Draft it for your profile draft-for-youyou recorded a seedYour rule (line 7)POST /{namespace}/content/draft (voice judge, fabrication veto) → POST /{namespace}/approvalsyou approve and send it from your profile · Take this oneyou
Answer the tag answer-the-tagsomeone tagged the agent account with a question the facts Page answersAgent’s call, with its reasonPOST /{namespace}/posts, one reply under 280 charactersnobodythe same
Hand the angle on hand-the-angle-ona Post beat its account’s median on ContactsAgent’s call, with its reasonPOST /{namespace}/evidence → POST /{namespace}/tasks/{task}/assign, so promote-winners and owned-newsletter can reuse itMarketing Lead, so you · Take this oneyou
To a person to-a-personan untagged reply or a message that needs a personAgent’s call, with its reasonPOST /{namespace}/content/draft → POST /{namespace}/tasks/{task}/assignyou, due 1 business day · Take this oneyou
Not now not-nowno fresh fact and no seedYour rule (line 8)nothing; the slot stays emptynobodythe same
When they write backFixture replyWhat happensWho answersBy whenCall
Interested“Does this work for 40 units? Where do I start?”one reply with the facts Page link, where they leave their email and start a trialContent Lead · your agent5 minPOST /{namespace}/posts
Send me pricing“What does it cost?”the Pricing Page’s list Price and its link, no figure the page lacksContent Lead · your agent5 minPOST /{namespace}/posts
Not now“Bookmarking for next year.”no reply needed; nothing follows themnobody—GET /{namespace}/decisions
Wrong person“Tagging @sam_ops, this is his area.”nothing writes to a handle from their text; the thread stays open for Samnobody—GET /{namespace}/decisions
Out of officean auto-reply in a direct messagenothing sends; it waits for a real messagenobody—GET /{namespace}/decisions
Question it can’t answer“Is this AI writing your posts?”the agent account answers that it is Leaseline’s labeled agent; a first-person question goes to youContent Lead · your agent, or you1 business dayPOST /{namespace}/tasks/{task}/assign
Stop“Stop tagging me.”it never tags or replies to them again, on any accountnobodyat oncePOST /{namespace}/contacts/{contact}/suppress

When it hands to you

Every first-person Post, every reply that needs a person and every winning angle come to you: you are the founder, and the Marketing Lead Role has no person. One Brief per Role, as captured, then the Approval (brief, draft and checks are Not live yet, gaps #7).

What lands in each queue · sample
[
  {
    "$id": "https://api.sb/leaseline.app/approvals/approval_81",
    "$type": "Approval",
    "verdict": "approved",
    "deadline": "2026-10-13T17:00:00Z",
    "draft": "Most late renewals I’ve seen start with one owner who never got the notice. Here’s what we changed…",
    "route": "draft-for-you",
    "checks": [
      {
        "check": "claims-resolve",
        "status": "pass"
      },
      {
        "check": "voice",
        "status": "pass"
      }
    ]
  },
  {
    "$id": "https://api.sb/leaseline.app/tasks/task_422",
    "$type": "Task",
    "assignee": "worker_1",
    "due": "2026-09-18T17:00:00Z",
    "on": "post_17",
    "brief": {
      "who": "the Sep 11 renewal-timing Post",
      "chose": "hand-the-angle-on",
      "why": "9 Contacts on 4,100 impressions, 4 times the median",
      "evidence": "evidence_12",
      "next": "reuse it in `owned-newsletter`; `promote-winners` can boost it"
    }
  },
  {
    "$id": "https://api.sb/leaseline.app/tasks/task_430",
    "$type": "Task",
    "assignee": "worker_1",
    "due": "2026-10-02T15:00:00Z",
    "on": "contact_14",
    "brief": {
      "who": "@rentops_kim, in a direct message",
      "said": "Can you talk to my boss about this?",
      "chose": "to-a-person",
      "why": "a request for a person",
      "never": [
        "a price beyond the list"
      ]
    }
  }
]

You answer with POST /{namespace}/tasks/{task}/claim (Take this one), POST /{namespace}/tasks/{task}/return with a reason, POST /{namespace}/actions/{action}/redirect, POST /{namespace}/approvals/{approval}/approve or POST /{namespace}/approvals/{approval}/refuse, each a one-call window; a first-person draft waits for your send and never goes out on its own. Once you claim a thread, the agent replies nothing more there (claimedByPerson, Not live yet, gaps #7). A Task nobody claims by its due time raises person-promise.

On time: you, 5 of 5 claimed within their due time, median 2 h 15 min, n 5, ■□□□ Too early to tell beside Other Startups’ 89 % on time. Your queue: counted by kind: in week 1, 4 Post approvals, 1 first-person draft and 1 reply; after the promotion, about 1 first-person draft and 1 reply a week.

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 to a Person whose Conversation you claimed, or whose Lead a person ownsLeave it to the person who owns it: the draft waits in their queue.POST /{namespace}/tasks/{task}/assign
claims-resolve (Not live yet)a Post with a claim that resolves to no live record on the facts PageCut the claim, or name the record that backs it.POST /{namespace}/content/draft
Stop (pauses the Play)Pauses whenThen
claimsa published claim turns out to sit outside the claims sourcePOST /{namespace}/posts/{post}/withdraw within 1 h; the account drops to You approve each one
venue-warninga Venue warning, restriction or removed label on an accountthat account pauses and drops to You approve each one
low-quality-flaga Venue note that a Post drew low-quality or AI-content reportsdrafting on that account pauses 7 days
unfollowunfollows within 24 h of a Post pass 0.5 % of followersthat account pauses 7 days
samenessthree drafts in a row fail the sameness passdrafting on that account pauses
contact-floorunder 0.2 Contacts per 1,000 impressions after 50,000 over 60 daysthe Play stops on that account
owner-silenceno review from you for 3 business daysevery draft holds at its rung
kill-switchyou press itPOST /{namespace}/processes/{process}/pause on content-marketing; scheduled Posts move back to draft
summons-floodover 20 tags in an hour from accounts under 30 days oldtag replies pause 24 h

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

422RefusedThe Sep 4 Company Page Post did not schedule: one claim resolves to no record on the facts Page.
CheckFixThen
claims-resolve failCut the claim, or name the record that backs it.POST /{namespace}/content/draft
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "The Sep 4 Company Page Post did not schedule: one claim resolves to no record on the facts Page.",
  "checks": [
    {
      "check": "claims-resolve",
      "status": "fail",
      "doc": "/plays/organic-social#check-claims-resolve",
      "fix": "Cut the claim, or name the record that backs it.",
      "then": "Content.draft"
    }
  ]
}

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

The Stops that fired, as Campaign.paused reasons · sample
[
  {
    "reason": {
      "limit": "owner-silence",
      "observed": "3 business days with no review",
      "bound": "3 business days",
      "window": "Sep 29 to Oct 1"
    },
    "doc": "/plays/organic-social#stop-owner-silence",
    "task": "task_441"
  }
]

Did it work

At about 3 consented Contacts a week, neither a held-back half nor alternating weeks can read within 90 days, so the basis is before-after (rule o): the columns read Now and Before, and nothing prints as Added. Each figure’s call is POST /{namespace}/metrics/query by node, and every node above the leaf is Not live yet (gaps #4).

0.44 per 1,000 against 0.11 before · before-after, not proof · n 21 · path → arr

Chose
post-the-fact
Why
a first-party fact recorded Oct 18 from your own records: Customers sent 1,204 renewal notices 60 days out in September, against 790 in August; Thursday’s Company Page slot is open
From
post-the-fact · draft-for-you · answer-the-tag · hand-the-angle-on · to-a-person · not-now
Expects
consented Contacts carrying the Post’s code within 30d
Reopens when
no Consent.created carrying the Post’s code within 14d: its angle is not handed on
By
worker_7
JSON
{
  "$id": "decisions/decision_538",
  "$type": "Decision",
  "choice": "post-the-fact",
  "reason": "a first-party fact recorded Oct 18 from your own records: Customers sent 1,204 renewal notices 60 days out in September, against 790 in August; Thursday’s Company Page slot is open",
  "stakes": "low",
  "options": [
    "post-the-fact",
    "draft-for-you",
    "answer-the-tag",
    "hand-the-angle-on",
    "to-a-person",
    "not-now"
  ],
  "by": "worker_7",
  "on": "fact_31",
  "expected": "consented Contacts carrying the Post’s code within 30d",
  "reopensWhen": "no Consent.created carrying the Post’s code within 14d: its angle is not handed on"
}
NodeNow (56 days)Before (the 90 days, per 56)AddedConfidenceBasis
social-sourced-contacts0.44 per 1,000: 21 consented Contacts on 48,000 impressions · Booked $694 from 2 of them on Pro: credited, not all caused by this Play0.11: 2.5 on 22,400— · Worth about +$270 a month—before-after, not proof · Other Startups’ results +0.25 per 1,000, ■■■□ Likely, n 31 Startups
new-leads133101——before-after; includes Leads this Play never touched
new-arr ↑$5,210$3,850——before-after
net-new-arr · arrcarried from new-arrcarried——carried

Before against after reads Contacts whose Consent landed within 30 days of a first Visit carrying a Post code, or whose form names a social Venue, in this window against the 90 days before it, scaled to 56 days; it is not proof. Every 6th week stays dark, so the pooled comparison across Other Startups has Leaseline’s weeks in it.

How it moves it: one fact from your own records per Post, 15 of them, each ending at the facts Page; before, 6 Posts in 90 days and none ended at a page that asked for an email (social-sourced-contacts by Post kind).

Guardrails: before against after: Contacts to paid, 2 of 21 against 0 of 4, and unfollows after a Post, a peak of 0.1 % against a 0.5 % Stop.

The Campaign card · sample
{
  "$id": "https://api.sb/leaseline.app/campaigns/organic-social",
  "$type": "Campaign",
  "play": "play:organic-social@1",
  "path": [
    "social-sourced-contacts",
    "new-leads",
    "new-arr",
    "net-new-arr",
    "arr"
  ],
  "experiment": {
    "metric": "social-sourced-contacts",
    "unit": "per-1000",
    "heldBack": 0,
    "decision": null
  },
  "readout": {
    "value": null,
    "n": 21,
    "maturing": 6,
    "interval": null,
    "readability": "inadmissible",
    "basis": "before-after",
    "pooled": true
  },
  "ledger": {
    "spend": 0,
    "workerCost": 1,
    "hours": 4.2,
    "pipelineArr": 0,
    "wonArr": 694,
    "projectedArr": 271,
    "paybackDays": 1
  }
}

Outside benchmark: the catalog holds none for this Play yet, so Other Startups’ results stand in: +0.25 consented Contacts per 1,000 impressions, ■■■□ Likely, n 31 Startups.

Before it · After it. Before it: data-stories, free-tools, review-requests, launch-week and founder-voice feed it facts and seeds. After it: a winning angle goes to promote-winners, and consented Contacts reach owned-newsletter and lead-nurture. engagement-bridge runs inside it as the reply step.

Example

Leaseline ran it from 2026-08-24 to 2026-10-19 (56 days): 24 Decisions, 15 Posts as the Startup, 7 first-person Posts you sent, 48,000 impressions and 21 consented Contacts. Read every captured thread at ?threads=all; three follow the tables.

What happened, by optionDecisionsImpressionsConsented ContactsWon (credited, not all caused by this Play)
Post it from the Startup1531,200141 on Pro (+$347 ARR)
Draft it for your profile8 (7 sent)15,90061 on Pro (+$347 ARR)
Answer the tag · Hand the angle on · To a person · Not now6 · 2 · 3 · 2900 · — · — · —1 · — · — · —0
At 2 facts a week (the Use it when volume)about 16 Posts in 56 daysbefore-after, not proof—Other Startups’ results: +0.25 per 1,000, ■■■□ Likely, n 31 Startups
DayEventWhat happenedYour time
0event_118 Campaign.createdthe three steps; the dry run fails claims-resolve: no facts Page15 min
0event_124 Page.createdthe facts Page goes live with 12 facts from your records20 min
4event_177 Consent.createdthe first Contact from a Post: a reader of the Aug 27 notices Post—
18event_390 Evidence.createdthe Sep 11 renewal-timing Post beat the median 4 times; its angle went to you5 min
28 · 49event_560 Change.merged · event_802 Readout.createddocument Posts by default on the page: replayed at 0.52 per 1,000, read back at 0.485 min
29event_571 Role.updatedpromoted: Company Page and X Posts publish unless you stop them—
36event_655 Campaign.pausedowner-silence: 3 business days with no review while you travelled; drafts held, nothing lost—
1–56event_140 Approval.created, first of 15you approved 15 Posts, sent 7 first-person Posts and answered 3 replies; weekly reviews, from the POST /{namespace}/tasks/next log3 h 30 min · total 4.2 h measured, 4 h asked

Leaseline on LinkedIn, Sep 11, 09:00, a 6-page document · In August, Leaseline Customers sent 790 renewal notices 60 days out.¹ Page 2: the three steps teams took before the first notice went out. Page 6: the facts behind each number, with how to get the same report for your portfolio.²

Rosa Lin, a property manager, 11:40 · “We’re at 40 units and this is exactly our mess.” She opened the facts Page from the Post’s code and left her email (Consent.created, 11:52); her trial started Sep 14 and paid on Pro Sep 29.

The Sep 4 Company Page Post · claims-resolve refused, then the rewrite that posted
- Leaseline cuts late renewals by 40%.
+ Leaseline Customers sent 790 renewal notices 60 days out in August, the first month the report covers.

@rentops_kim, in a direct message on X, 2026-10-01 14:10 · “Can you talk to my boss about this?” · Leaseline (agent), 14:12 · *I’m Leaseline’s agent. Dana, our founder, replies here by tomorrow 15:00.*³ The Brief went to Dana (task_430); she replied at 09:20 the next morning and booked a call for Oct 6.

¹ One fact from the facts Page, with its month. ² The Post ends at the facts Page, where Consent is recorded. ³ The routed line, compiled from the Role’s Settings.

Your settings

plays/organic-social.mdx
---
accounts: [linkedin-page, x-agent]
dark: every 6th week
---
One Post a week per account, from one fact in our records or one thing we shipped.
On the LinkedIn page, a document Post by default.
My own LinkedIn posts start from the sentences I record, and I send them.
No fresh fact and no seed: leave the slot empty.
Text
$ npx startup-builder show plays/organic-social
accounts linkedin-page, x-agent · dark every 6th week · document Posts on the page · empty slots stay empty     your file  plays/organic-social.mdx:2,3,5,6,7,8 (Ask 2026-08-24; line 6 by change_23, 2026-09-21)
family social · process content-marketing · worker role:content-lead, owns never · chooses 6 (3 rule, 3 read) · approval every-send · checks owned-by-a-person, claims-resolve · stops 9 · runs engagement-bridge as its reply step    catalog  play:organic-social@1 (Not live yet, gaps #5)

Every key from the catalog

KeyIdWhat it is
Tacticreference-post-runReference post run: A weekly run that turns a Startup's first-party facts into one native Post per Handle, each ending at a fact Page where Consent is recorded. Starts at You approve each one.
Tacticfirst-person-draftFirst-person draft: Turns a Human's own seed into a draft that passes a voice judge and a fabrication veto, for that Human to approve and send. Starts at You approve each one.
Tacticsummoned-replySummoned reply: Answers a Person who tagged the agent Handle once, from the claims source, and routes each unsummoned reply to a Human as a draft. Starts at You approve each one.
Tacticangle-handoffAngle handoff: Moves a winning Post's angle to the Plays that reuse it, with its Evidence, and drafts reshare notes only Humans send. Starts at Sends nothing.
Tacticclaims-checkClaims check maps every draft sentence to an approved source or the Person’s own words, and holds anything else before it reaches anyone. Starts at Sends nothing.
Triggerfact-recordedFact recorded: event on Fact.recorded, window 14d.
Triggerversion-shippedVersion shipped: event on Version.deployed, window 72h.
Triggerseed-recordedSeed recorded: event on Content.drafted, window 7d.
Triggerhandle-summonedHandle summoned: event on Handle.mentioned, window 24h.
Triggerpost-outlierPost outlier: threshold on Post.published, window 14d.

Compiled, not written: edit the Play record organic-social 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.