Skip to content

Video ladder

Lifts each video idea from free posts to paid ads to a reshoot by a person, spending only on what the rung below proved.

Channel
Video
Run oneMode try
You, to your agent

Hand our latest Post that cleared the screen 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(%22Fact.recorded%22%2C%20%22Experiment.concluded%22%2C%20%22Post.published%22%2C%20%22Comment.posted%22%2C%20%22Monitor.checked%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_1322"}'

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

const { events: [last] } = await $.Event.list({ where: 'name in ("Fact.recorded", "Experiment.concluded", "Post.published", "Comment.posted", "Monitor.checked")', 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\", \"Experiment.concluded\", \"Post.published\", \"Comment.posted\", \"Monitor.checked\")","limit":1}'
npx startup-builder do Trigger.fire --json '{"like":"event_1322"}' --try   # Not live yet (gaps #7)
npx startup-builder do Decision.list --json '{"where":"on = \"post_88\""}'   # Not live yet (gaps #7)
npx startup-builder do Action.list --json '{"where":"on = \"post_88\""}'   # Not live yet (gaps #7)
{
  "name": "do",
  "arguments": {
    "code": "const { events: [last] } = await $.Event.list({ where: 'name in (\"Fact.recorded\", \"Experiment.concluded\", \"Post.published\", \"Comment.posted\", \"Monitor.checked\")', 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_363",
    "$type": "Decision",
    "choice": "promote-it",
    "reason": "the “renewal calendar in 20 seconds” Short cleared the 72-hour screen: 61 % completion against the Handle’s 38 % median, 9 coded signups from 31,000 views",
    "stakes": "high",
    "options": [
      "draft-the-cut",
      "promote-it",
      "reshoot-it",
      "answer-the-comment",
      "retire-the-format",
      "refresh-the-ad"
  …
sample · 4 Not live yetPreview

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

action_2 is the promoted cut at $10 a day for 14 days, inside promote-winners; it waits for your approval because it spends.

0.29 coded signups per 1,000 views against 0.14 before · before-after, not proof · n 61 · path → arr

Try another: the PostChoiceReason
The “renewal calendar in 20 seconds” Short: 61 % completion, 9 coded signupspromote-itcleared the screen with signups
The YouTube Handle’s 09:00 slot is empty; a new fact: notices now go by textdraft-the-cutan empty slot and a new fact
A promoted cut: 14 coded signups, payer rate 1.1 times your baselinereshoot-ita paid winner at or over your payer rate
“Does it send notices in Spanish?” under a Shortanswer-the-commentthe claims source says yes
Photo slideshows: 0.62 times the median on 6 Postsretire-the-formatunder 0.8 times on 6 in a row

Where it sits: Stranger → Lead → Trialing → Activated → At risk → Churned → Won back · Video sign-ups per 1,000 views → New Leads → New Customers ↑ → ARR added each week → ARR

Worth’s formula: about +0.11 coded signups per 1,000 views (Other Startups’ results; no lift of your own yet) × 115,000 views a month × 0.12 paid per signup × $347 first order ARR ≈ +$527. Under First signal: At about 33 coded signups a month, 90 days can tell only a doubling against your own before, so it reads before-after.

sample · api.sb/leaseline.app · 41 Customers at 2026-10-19 · on Post.published · first cut drafted 22 min after the empty slot · 8 keys Not live yet

Start it this week

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

# 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":"video-ladder"}'

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

# off: no cut renders or posts; live Posts stay up
curl -X POST https://api.sb/leaseline.app/processes/content-marketing/pause \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
422Refusedvideo-ladder can’t start yet: 1 check fails and 2 warn.
CheckFixThen
use-when pass · Not live yet, gaps #8Nothing to fix: 2 or more Handles.POST /{namespace}/metrics/query
approved-pages fail · Not live yet, gaps #8Add 10 facts your pages back to the claims source; cuts quote only those.POST /{namespace}/sites/{site}/publish
baseline warn · Not live yet, gaps #8n 2: it reads before-after, not proof, against your own videos.POST /{namespace}/metrics/query
role-unstaffed warn · Not live yet, gaps #8Staff paid media, or leave it: hand publishing and every ad come to you.POST /{namespace}/roles/{role}/staff
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "video-ladder can’t start yet: 1 check fails and 2 warn.",
  "checks": [
    {
      "check": "use-when",
      "status": "pass",
      "observed": "3 Handles connected: YouTube, LinkedIn, X",
      "doc": "/plays/video-ladder#check-use-when",
      "fix": "Nothing to fix: 2 or more Handles.",
      "then": "Metric.query"
    },
    {
      "check": "approved-pages",
      "status": "fail",
      "observed": "4 live facts in the claims source; a cut needs 10 to draw from",
      "doc": "/plays/video-ladder#check-approved-pages",
      "fix": "Add 10 facts your pages back to the claims source; cuts quote only those.",
      "then": "Site.publish"
    },
    {
      "check": "baseline",
      "status": "warn",
      "observed": "2 coded signups from 9 founder videos, 14,000 views in 90 days",
      "doc": "/plays/video-ladder#check-baseline",
      "fix": "n 2: it reads before-after, not proof, against your own videos.",
      "then": "Metric.query"
    },
    {
      "check": "role-unstaffed",
      "status": "warn",
      "roles": [
        "video-producer",
        "paid-media-manager"
      ],
      "owned": 0,
      "doc": "/plays/video-ladder#check-role-unstaffed",
      "fix": "Staff paid media, or leave it: hand publishing and every ad come to you.",
      "then": "Role.staff"
    }
  ]
}

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

CheckFix (one call)Your timeWait
use-when · pass: 3 Handles connected (gaps #8)POST /{namespace}/metrics/query on video-signups; POST /{namespace}/handles/{handle}/connect adds one1 minnone
approved-pages · fail (Not live yet): 4 live facts of 10POST /{namespace}/sites/{site}/publish the pages that back 6 more facts, then add them20 minnone
baseline · warn: 2 coded signups from 14,000 viewsPOST /{namespace}/metrics/query; it fills Before in Your number0 minnone
role-unstaffed · warn: no person produces video or runs paid mediaPOST /{namespace}/roles/{role}/staff, or leave it: TikTok and Instagram drafts and every ad come to you0 minnone

Your number · Before 0.14 per 1,000 views · Now 0.29 coded signups per 1,000 views · Target 0.35 by Dec 31 · before-after, not proof · n 61 signups

Each cut costs about $0.60 to render and check (Worker cost), under a $50 monthly render Limit; ads spend inside promote-winners under your $300 monthly Limit. That came to $29 in renders and $180 in ads over 56 days.

When it starts

WhenTrigger idStarts onWindowHow it gets in
A Handle’s next slot within 24 hours holds no cutslot-emptystate on Post.published where handle.nextSlotAt < now + 24h and handle.queued = 0a state, read each hourPOST /{namespace}/handles/{handle}/connect for each Venue
A Post’s 72-hour completion clears the screen at its minimum samplescreen-passthreshold on Post.published where completion72h >= the screen and views >= the minimum sample7dthe Venue’s Post analytics through POST /{namespace}/handles/{handle}/connect
A public comment asks what the claims source answerscomment-questionevent on Comment.posted where asks a question the claims source answers48hthe Venue’s comments through POST /{namespace}/handles/{handle}/connect
+ 3 more for new facts, won angles and tired ads (?lanes=all)
One signed delivery · StartupBuilder-Signature
{
  "$id": "https://api.sb/leaseline.app/events/event_1322",
  "$type": "Event",
  "name": "Post.published",
  "at": "2026-10-19T09:00:12Z",
  "seq": 1322,
  "data": {
    "post": "post_88",
    "handle": "youtube",
    "views": 31000,
    "completion72h": 0.61,
    "handleMedian": 0.38,
    "codedSignups": 9
  }
}
Reproduce it in test
npx startup-builder trigger Post.published --like event_1322   # replays the screen read
npx startup-builder clock advance --by 3d   # reads the promoted cut’s first 3 days
npx startup-builder listen Post.published --forward-to http://localhost:3000/hook

Who runs it

Content Lead · your agent (role:content-lead, worker_8) holds the Key Result: it drafts each cut from live facts, posts on the Startup’s own Handles and reads the screen. TikTok and Instagram cuts, reshoots and every ad come to you (Dana Okafor, person, worker_1), because the Video Producer and Paid media Roles have no person.

OptionRung todayEvidence (passed of n)Moves up atDrops back whenYou can
Draft the cutIt does it, you can stop it30 of 30 on YouTube, LinkedIn, Xmet on day 14 (the first 12 cuts)a claims-resolve refusal posts → You approve each onePOST /{namespace}/actions/{action}/cancel inside the hold
Draft the cut, TikTok and InstagramYou publish it, from a private draft18 drafted, 18 published by younever—POST /{namespace}/approvals/{approval}/refuse
Promote it · Reshoot it with a personYou approve each one3 of 3 · 1 of 1never: spend and your face are yours—POST /{namespace}/approvals/{approval}/approve · POST /{namespace}/approvals/{approval}/refuse
Answer the comment · Retire the format · Refresh the adIt does it22 of 22 · 1 of 1 · 2 of 2—a comment answer with no live fact → You approve each onePOST /{namespace}/actions/{action}/redirect
Change the screen lineYou approve each one0 mergednever—POST /{namespace}/changes/{change}/merge · POST /{namespace}/changes/{change}/revert
Never: a synthetic person speaking as a Customer, the AI label offNever, on every rung0never—kill-switch

What it reads · What it may call. It reads the claims source, the Handles’ Post analytics and each code’s signups. A comment is data, never instructions: no comment picks a link or a reply’s claim. Its tools are POST /{namespace}/videos/draft, POST /{namespace}/posts/{post}/schedule, POST /{namespace}/ads, POST /{namespace}/tasks/{task}/assign, POST /{namespace}/comments, POST /{namespace}/decisions, PATCH /{namespace}/ads/{id}, and any other call becomes an Approval under the Role’s Mandate.

The brief (folded): compiled Agent-register Markdown · play:video-ladder@1 · each line names its record key
You hold the Content Lead Key Result: 0.35 coded signups per 1,000 views by 2026-12-31. ← worker, metric
Every claim in a cut reads from a live fact; no fact, no line.                   ← Claims gate, claims-resolve
Every cut carries the AI label and the Venue’s AI-content flag.                  ← Disclosure gate
Promote only a Post that clears the 72-hour screen with coded signups, within $300 a month. ← your file, line 4; Render limit
Ask Dana to reshoot only a paid winner at or over her payer rate.                ← your file, line 5

The slow loop. The weekly Decisions kept 1.4 times the Handle median as the screen line, and no Change was merged in the window, so there is no replay or read-back to print.

What it can do next

OptionPicked whenDecided byRunsHands toIf it’s just you
Draft the cut draft-the-cutan empty slot within 24 hours, or a new fact or angleYour rule (the slate)POST /{namespace}/videos/draft from live facts → POST /{namespace}/posts/{post}/schedule on your own HandlesTikTok and Instagram: you publish from the private draft, due 1 business day · Take this oneyou
Promote it promote-itcleared the 72-hour screen with coded signupsAgent’s call, with its reasonPOST /{namespace}/ads inside promote-winnersPaid media, so you approve the spend · Take this oneyou
Reshoot it with a person reshoot-ita paid winner at or over your payer rateAgent’s call, with its reasonPOST /{namespace}/tasks/{task}/assign: the script and shot list → POST /{namespace}/videos/draft with your footageyou film it, due 1 business day · Take this oneyou
Answer the comment answer-the-commenta question the claims source answersAgent’s call, with its reasonPOST /{namespace}/comments from a live factnobodythe same
Retire the format retire-the-formatunder 0.8 times the median on 6 PostsYour rule (Completion floor)POST /{namespace}/decisions: off the slate for 30 daysnobodythe same
Refresh the ad refresh-the-adfrequency past 3.5 while clicks fall 3 daysYour rule (the paid rung)PATCH /{namespace}/ads/{id} with a new open → POST /{namespace}/videos/draftnobodythe same
When they write backFixture replyWhat happensWho answersBy whenCall
Interesteda comment: “How do I try this?”answers with the coded signup linkContent Lead · your agent1 hPOST /{namespace}/comments
Send me pricinga comment: “How much is it?”answers with the Pricing Page’s list Price, $29 a monthContent Lead · your agent1 hPOST /{namespace}/comments
Not nowa comment: “Maybe when we grow.”nothing more; a public comment gets no follow-upnobodyat onceGET /{namespace}/decisions
Wrong persona comment: “My office manager should see this.”one answer to the commenter; nothing goes to the person they namedContent Lead · your agent1 hPOST /{namespace}/comments
Out of officea comment: “Away until the 28th, remind me.”no reminder is sent; the Post stays upnobodyat onceGET /{namespace}/decisions
Question it can’t answera comment: “Does it work with our accounting system?”To you; nothing is answered in public until you doyou1 business dayPOST /{namespace}/tasks/{task}/assign
Stopa comment: “Stop showing me these ads.”that viewer leaves the paid listnobodyat oncePATCH /{namespace}/audiences/{id}

When it hands to you

TikTok and Instagram drafts, reshoots and every ad come to you. 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_538",
    "$type": "Task",
    "assignee": "worker_1",
    "due": "2026-10-16T17:00:00Z",
    "on": "post_81",
    "brief": {
      "who": "the “60 days out, every owner” cut",
      "chose": "reshoot-it",
      "why": "promoted: 14 coded signups, payer rate 1.1 times your baseline",
      "script": "3 lines, 20 seconds, your phone in portrait",
      "never": [
        "a line no live fact backs",
        "a Customer’s words without their Consent"
      ]
    }
  },
  {
    "$id": "https://api.sb/leaseline.app/approvals/approval_63",
    "$type": "Approval",
    "verdict": null,
    "deadline": "2026-10-20T17:00:00Z",
    "draft": "Promote post_88: $10 a day for 14 days, inside promote-winners",
    "route": "promote-it",
    "checks": [
      {
        "check": "claims-resolve",
        "status": "pass"
      },
      {
        "check": "disclosure",
        "status": "pass"
      }
    ]
  }
]

You answer with POST /{namespace}/approvals/{approval}/approve or POST /{namespace}/approvals/{approval}/refuse, or take a Task with POST /{namespace}/tasks/{task}/claim (Take this one) or hand it back with POST /{namespace}/tasks/{task}/return, each a one-call window. An ad Approval unanswered by its deadline expires, and nothing is spent.

On time: you, 18 of 18 private drafts published within 1 business day, median 5 h, and 4 of 4 Approvals answered, n 22, ■■□□ Early sign. Your queue: in week 1, 6 facts to add and 4 drafts to publish; then about 3 drafts a week and 1 ad every 2 weeks.

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
claims-resolve (hub guard on POST /{namespace}/posts/{post}/publish)a cut with a claim that reads from no live factCut the claim, or name the record that backs it.POST /{namespace}/content/draft
disclosure (the record’s Disclosure gate)an upload whose AI flag and on-screen labels differ from the cut’s disclosure manifestSet the Venue’s AI flag and the on-screen label, then upload.POST /{namespace}/posts/{post}/schedule
testimonial (the record’s Testimonial gate)a first-person experience line from a synthetic speaker, or a person without ConsentCut the line, or record a person who gave Consent.POST /{namespace}/videos/draft
distinctness (the record’s Distinctness gate)a cut too close to one on the same Handle in 90 daysDraft a new open or a new fact.POST /{namespace}/videos/draft
Stop (pauses the Play)Pauses whenThen
strikea Venue strike, label, removal or reach-limit noticethe Play pauses on that Handle; the format is held everywhere within 1 h
suspended-handlea Handle is suspendedits lanes pause; you are told
completion-floora format under 0.8 times the Handle median on 6 Posts in a rowthe format leaves the slate for 30 days
signup-floora format with 50,000 views and no coded signupit stops until a new angle reaches it
payer20 signups in 7 days with a payer rate under half your baselinethe draft loop pauses; POST /{namespace}/tasks/{task}/assign an Offer review to you
refund-spikerefunds or same-day cancels from video signups at twice your baselineevery ad and the paid list pause
commentcomments calling a format fake over 5 %, on 2 Posts in a weekthe format returns to You approve each one
drifta live ad differs from its approved cutthe ad pauses on the daily read
spend-limitrender and model spend reach the monthly Limitthe batch holds; POST /{namespace}/limits/{limit}/raise for you
kill-switchyou press itPOST /{namespace}/processes/{process}/pause on content-marketing; every draft and ad pauses

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

422RefusedThe cut “hours back every week” did not post: it says property managers save 10 hours a week, and no live fact says so.
CheckFixThen
claims-resolve failCut the claim, or name the record that backs it.POST /{namespace}/content/draft
disclosure pass—POST /{namespace}/content/draft
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "The cut “hours back every week” did not post: it says property managers save 10 hours a week, and no live fact says so.",
  "checks": [
    {
      "check": "claims-resolve",
      "status": "fail",
      "doc": "/plays/video-ladder#check-claims-resolve",
      "fix": "Cut the claim, or name the record that backs it.",
      "then": "Content.draft"
    },
    {
      "check": "disclosure",
      "status": "pass"
    }
  ]
}

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

The Stops that fired, as Campaign.paused reasons · sample
[
  {
    "reason": {
      "limit": "completion-floor",
      "observed": "0.62 times the Handle median on 6 Posts",
      "bound": "0.8 times",
      "window": "6 Posts"
    },
    "doc": "/plays/video-ladder#stop-completion-floor",
    "task": "task_490"
  }
]

Did it work

Organic feeds cannot be split at random, and 61 signups in 56 days is under the volume for alternating weeks, 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.29 coded signups per 1,000 views against 0.14 before · before-after, not proof · n 61 · path → arr

Chose
promote-it
Why
the “renewal calendar in 20 seconds” Short cleared the 72-hour screen: 61 % completion against the Handle’s 38 % median, 9 coded signups from 31,000 views
From
draft-the-cut · promote-it · reshoot-it · answer-the-comment · retire-the-format · refresh-the-ad
Expects
20 coded signups from the promoted cut within 28d
Reopens when
the promoted cut’s coded signups per 1,000 fall under the organic rate for 3 days
By
worker_8
JSON
{
  "$id": "decisions/decision_363",
  "$type": "Decision",
  "choice": "promote-it",
  "reason": "the “renewal calendar in 20 seconds” Short cleared the 72-hour screen: 61 % completion against the Handle’s 38 % median, 9 coded signups from 31,000 views",
  "stakes": "high",
  "options": [
    "draft-the-cut",
    "promote-it",
    "reshoot-it",
    "answer-the-comment",
    "retire-the-format",
    "refresh-the-ad"
  ],
  "by": "worker_8",
  "on": "post_88",
  "expected": "20 coded signups from the promoted cut within 28d",
  "reopensWhen": "the promoted cut’s coded signups per 1,000 fall under the organic rate for 3 days"
}
NodeNow (56 days)Before (the 90 days, per 56)AddedConfidenceBasis
video-signups0.29 per 1,000 views: 61 coded signups from 212,000 views, 48 Posts0.14: 2 from 14,000 views, 9 founder videos——before-after, not proof · Other Startups’ results +0.11 per 1,000, ■■■□ Likely, n 6,800 Posts
new-leads61 coded signups1.2 (2 in 90 days, per 56)——before-after
new-arr ↑$2,429, 7 Customers on Pro · Booked: credited, not all caused by this Play$216— · Worth about +$530 a month—before-after · 2 trials still deciding
net-new-arr · arrcarried from new-arrcarried——carried

The leaf counts signups whose Acquisition carries a Post’s link code, or whose first checkout redeems its promotion code, per 1,000 Video views over 30 days. Before against after is not proof, and Other Startups’ results print beside it.

How it moves it: each idea earned its next dollar on the rung below: 48 free cuts, 3 promoted for $180, 1 reshot by Dana; the 3 promoted cuts brought 19 of the 61 signups.

Guardrails: before against after: payer rate, 11 % of video signups against your 13 % baseline, refunds and same-day cancels from video signups, 0 of 7, and comments calling a format fake, 0.4 % against a 5 % floor.

The Campaign card · sample
{
  "$id": "https://api.sb/leaseline.app/campaigns/video-ladder",
  "$type": "Campaign",
  "play": "play:video-ladder@1",
  "path": [
    "video-signups",
    "new-leads",
    "new-arr",
    "net-new-arr",
    "arr"
  ],
  "experiment": {
    "metric": "video-signups",
    "unit": "per-1000",
    "heldBack": 0,
    "decision": null
  },
  "readout": {
    "value": null,
    "n": 61,
    "maturing": 9,
    "interval": null,
    "readability": "inadmissible",
    "basis": "before-after",
    "pooled": true
  },
  "ledger": {
    "spend": 180,
    "workerCost": 29,
    "hours": 4.2,
    "pipelineArr": 694,
    "wonArr": 2429,
    "projectedArr": 527,
    "paybackDays": 22
  }
}

Outside benchmark: short business videos hold a median 34 % of viewers to the end (a video analytics firm’s study of 1.1M Posts, 2026-08-31).

Before it · After it. Before it: signup-interviews and editorial-seo supply the facts and angles that won elsewhere. After it: promote-winners runs the paid rung, paid-social and creator-ads hear the winners, and instant-response answers the signups who write in.

Example

Leaseline ran it from 2026-08-24 to 2026-10-19 (56 days): 48 cuts from 14 live facts, 212,000 views, 61 coded signups, 3 cuts promoted for $180 and 1 reshot by Dana. Read every captured thread at ?threads=all; three follow the tables.

What happened, by optionDecisionsViews or signupsWon (credited, not all caused by this Play)
Draft the cut48: 30 posted on your Handles, 18 published by you212,000 views, 42 coded signups4 on Pro (+$1,388 ARR)
Promote it · Reshoot it with a person3 · 119 coded signups for $180 · the reshoot runs from Oct 173 on Pro (+$1,041 ARR)
Answer the comment · Retire the format · Refresh the ad22 · 1 · 222 answers from live facts · slideshows off for 30 days · 2 new opens2 trials still deciding
At 2 Handles (the Use it when volume)about 30 cuts in 56 daysbefore-after, not proofOther Startups’ results: +0.11 per 1,000, ■■■□ Likely, n 6,800 Posts
DayEventWhat happenedYour time
0event_119 Campaign.createdthe three steps; dry run fails approved-pages: 4 live facts10 min
0event_127 Content.createdyou added 10 facts your pages back20 min
4event_180 Acquisition.createdthe first coded signup, from a YouTube Short—
14event_402 Role.updatedpromoted: cuts on your own Handles post after a 2-minute hold—
19event_455 Action.refusedclaims-resolve refused “hours back every week”; rewritten once and posted5 min
33event_612 Campaign.pausedcompletion-floor: slideshows off the slate for 30 days—
1–56event_131 Task.assigned, first of 22you published 18 drafts and approved 4; weekly reviews, from the POST /{namespace}/tasks/next log3.7 h · total 4.2 h measured, 4.4 h asked

YouTube Short, Oct 16, 09:00 · “Renewal calendar in 20 seconds”: Leaseline sends every renewal notice 60 days out, per owner.¹ Made with AI, labeled on screen and in the Venue’s AI flag.²

Oct 19, 09:00 · 61 % completion against a 38 % median, 9 coded signups from 31,000 views; decision_363 chose Promote it, and the ad waits for your approval (approval_63).

“Hours back every week”, 2026-09-12 · the cut claims-resolve refused, then the rewrite that posted
- Property managers save 10 hours a week with Leaseline.
+ Leaseline drafts every renewal notice for you, 60 days out, per owner.

The “60 days out, every owner” cut, 2026-10-15 16:00 · promoted: 14 coded signups at 1.1 times your payer rate · the reshoot Brief reached Dana (task_538) with a 3-line script, due Oct 16 17:00; she filmed it at 12:30 on Oct 16, and it runs from Oct 17.

¹ The line reads from a live fact in the claims source. ² The disclosure manifest, matched before upload.

Your settings

plays/video-ladder.mdx
---
holdout: 0        # organic feeds cannot be split; it reads before-after
---
Promote only a Post that clears 1.4 times the Handle median with coded signups, up to $300 a month.
Ask me to reshoot only a paid winner at or over my payer rate.
Text
$ npx startup-builder show plays/video-ladder
holdout 0 · screen 1.4 times the median · ads $300 a month     your file  plays/video-ladder.mdx:2,4,5 (Ask 2026-08-24)
family demand · process content-marketing · worker role:content-lead, owns never · chooses 6 (3 rule, 3 read) · sequences none · checks claims-resolve, disclosure, testimonial, distinctness · stops 10 · placements tiktok, instagram, facebook, youtube, linkedin, x    catalog  play:video-ladder@1 (Not live yet, gaps #5)

Every key from the catalog

KeyIdWhat it is
Tacticfact-bound-renderFact-bound render turns one distinct premise into a native cut per format, every claim linked to a sourced fact and disclosure compiled from each take. Starts at Sends nothing.
Tacticdraft-loopConsumer draft loop uploads each cut as a private, labeled draft that a human finishes with a native sound and publishes, then reads it back. Starts at You approve each one.
Tacticorganic-screenOrganic screen posts each cut once, reads completion at 72 hours and coded sign-ups at 7 days, and moves winners one rung up. Starts at It does it, you can stop it.
Tacticpaid-handoffPaid hand-off turns a dedicated-Handle winner and its reshoot into a promote-winners hand-off record, and reads each paid verdict back. Starts at Sends nothing.
Tactichuman-reshootHuman reshoot gives every winning cut a phone-shot version by the founder, a consenting Customer or a disclosed creator, run as its own Variant. Starts at Sends nothing.
Tacticcreative-drift-monitorCreative drift monitor reads every live Ad each day, diffs it against its approved cut and settings, and pauses any Ad that changed. Starts at Sends nothing.
Tacticwinner-promotionWinner promotion runs a free-placement winner as a paused, fenced Ad against its control, and judges it on counted conversions from Stripe. Starts at You approve each one.
Tactictier-gateTier gate holds a winner’s spend at its tier until a holdout shows incremental conversions per $100 clear breakeven, and re-reads every placement each quarter. Starts at You approve each one.
Triggerfact-newNew or changed fact: event on Fact.recorded, window 14d.
Triggerangle-wonAngle won: event on Experiment.concluded, window 30d.
Triggerslot-emptyEmpty publishing slot: state on Post.published, window 24h.
Triggerscreen-passScreen pass: threshold on Post.published, window 7d.
Triggercomment-questionComment question: event on Comment.posted, window 48h.
Triggerad-fatigueAd fatigue: threshold on Monitor.checked, window 3d.
Benchmarkai-ad-click-parityRaw click rate of AI-made ads against human-made ads from the same advertiser on the same day: 0.65–0.76 % (Columbia, Harvard, Carnegie Mellon and TU Munich field study on a native-ad network, 2026-01-29).
Benchmarkdisclosure-purchase-intentShare of young US consumers who say AI disclosure raises or does not change their purchase intent: 73 % (IAB consumer survey The AI Gap Widens, 2026-01-15).

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