Skip to content

Category kit

Makes your category name what answer engines cite, from your own words and one dated day, and kills it at day 90 without qualified Deals.

Channel
Blog and search
Run oneMode try
You, to your agent

Hand this week’s term panel run 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(%22Experiment.concluded%22%2C%20%22Monitor.checked%22%2C%20%22Post.scheduled%22%2C%20%22Keyword.measured%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_1188"}'

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

const { events: [last] } = await $.Event.list({ where: 'name in ("Experiment.concluded", "Monitor.checked", "Post.scheduled", "Keyword.measured")', 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 (\"Experiment.concluded\", \"Monitor.checked\", \"Post.scheduled\", \"Keyword.measured\")","limit":1}'
npx startup-builder do Trigger.fire --json '{"like":"event_1188"}' --try   # Not live yet (gaps #7)
npx startup-builder do Decision.list --json '{"where":"on = \"page_88\""}'   # Not live yet (gaps #7)
npx startup-builder do Action.list --json '{"where":"on = \"page_88\""}'   # Not live yet (gaps #7)
{
  "name": "do",
  "arguments": {
    "code": "const { events: [last] } = await $.Event.list({ where: 'name in (\"Experiment.concluded\", \"Monitor.checked\", \"Post.scheduled\", \"Keyword.measured\")', 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_571",
    "$type": "Decision",
    "choice": "correct-the-source",
    "reason": "4 of 9 Perplexity runs this week define renewal ops as HR contract renewals, and all 4 cite the same glossary Page",
    "stakes": "low",
    "options": [
      "correct-the-source",
      "work-a-cited-source",
      "answer-the-thread",
      "refresh-the-comparison",
      "hand-to-search",
      "hold-the-day"
  …
sample · 4 Not live yetPreview

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

action_2 is the correction to the glossary’s editor, drafted from your definition Page. It sends from your own Mailbox only once you approve it.

16.9 % term share against 0 % before · before-after, not proof · n 360 runs · path → arr

Try another: the cited sourceChoiceReason
A property-ops glossary: cited on 4 of 9 Perplexity runs for “HR contract renewals”correct-the-source3 or more misdefined runs in a week, one cited Page
A rival’s pricing Page now says “renewal ops”refresh-the-comparisona rival uses the term; nothing is sent to the rival
A landlord forum thread: “Is renewal ops just a spreadsheet with reminders?”answer-the-threada thread asks what the term means; you write the reply
A property-tech newsletter cited in 11 panel answers, never using the termwork-a-cited-sourceit decides prompts and has a guest-spot opening that matches your buyers

Where it sits: Stranger → Lead → Trialing → Activated → At risk → Churned → Won back · Category term share → People reached → New Customers ↑ → ARR added each week → ARR

Worth’s formula: about +1.8 qualified Leads per 1,000 Visitors (Other Startups’ results; yours reads Too early to tell) × 2,600 Visitors a month × 0.08 qualified Leads to paid × $348 first order ARR ≈ +$130. Under First signal: Term share reads every 2 weeks from 360 definitional runs; the qualified-Deal kill rule reads at T+90, Nov 23.

sample · api.sb/leaseline.app · 41 Customers at 2026-10-19 · on Monitor.checked · first Decision 4m 12s after the panel run · 9 keys Not live yet

Start it this week

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

# 2 · dry run; below, its 422 on 2026-07-08
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":"category-kit"}'

# 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":"category-kit"}'

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

# off: nothing sends or books; your Pages stay up
curl -X PATCH https://api.sb/leaseline.app/campaigns/category-kit \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"endsAt":"now"}'
422Refusedcategory-kit can’t start yet: 1 check fails and 2 warn.
CheckFixThen
use-when pass · Not live yet, gaps #8stance graded on 2026-07-07; 2,610 Visitors a month; a cost from 7 InterviewsPOST /{namespace}/metrics/query
baseline warn · Not live yet, gaps #8The 2 baseline weeks become Before; it reads before-after, not proof.POST /{namespace}/metrics/query
approved-pages fail · Not live yet, gaps #8Publish your pricing and about Pages; the canon cites only your own pages.POST /{namespace}/sites/{site}/publish
domain-authenticated passleaseline.app: 3 of 3 records resolvePOST /{namespace}/domains/{domain}/authenticate
role-unstaffed warn · Not live yet, gaps #8Leave them: pitches and replies come to you, and the day notice drafts into owners’ queues.POST /{namespace}/roles/{role}/staff
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "category-kit can’t start yet: 1 check fails and 2 warn.",
  "checks": [
    {
      "check": "use-when",
      "status": "pass",
      "observed": "stance graded on 2026-07-07; 2,610 Visitors a month; a cost from 7 Interviews",
      "doc": "/plays/category-kit#check-use-when",
      "then": "Metric.query"
    },
    {
      "check": "baseline",
      "status": "warn",
      "observed": "no term history",
      "doc": "/plays/category-kit#check-baseline",
      "fix": "The 2 baseline weeks become Before; it reads before-after, not proof.",
      "then": "Metric.query"
    },
    {
      "check": "approved-pages",
      "status": "fail",
      "doc": "/plays/category-kit#check-approved-pages",
      "fix": "Publish your pricing and about Pages; the canon cites only your own pages.",
      "then": "Site.publish"
    },
    {
      "check": "domain-authenticated",
      "status": "pass",
      "observed": "leaseline.app: 3 of 3 records resolve",
      "doc": "/plays/category-kit#check-domain-authenticated",
      "then": "Domain.authenticate"
    },
    {
      "check": "role-unstaffed",
      "status": "warn",
      "roles": [
        "marketing-lead",
        "communications-lead"
      ],
      "owned": 31,
      "doc": "/plays/category-kit#check-role-unstaffed",
      "fix": "Leave them: pitches and replies come to you, and the day notice drafts into owners’ queues.",
      "then": "Role.staff"
    }
  ]
}

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

CheckFix (one call)Your timeWait
use-when · baseline · pass: stance graded Jul 7, 2,610 Visitors a month · warn: no term history (gaps #8)POST /{namespace}/metrics/query on category-term-share; the 2 baseline weeks fill Before in Your number1 min2 baseline weeks
approved-pages · fail (gaps #8)POST /{namespace}/sites/{site}/publish your pricing and about Pages20 minnone
domain-authenticated · passPOST /{namespace}/domains/{domain}/authenticate, already done for the day notice0 minnone
role-unstaffed · warn (gaps #8): 31 of your open Leads have a person owner, youPOST /{namespace}/roles/{role}/staff, or leave it: pitches, corrections and thread replies come to you0 minnone

Your number · Before 0 % (0 of 360) · Now 16.9 % term share (61 of 360) · Target 20 % by Nov 23 (T+90) · before-after, not proof · n 360 runs a fortnight

Each panel run costs $0.01, and the panel runs 540 a week (about $23 a month). The day notice and corrections cost $0.04 a send from your Domain (Worker cost), and media spend is $0. That comes to about $25 a month, and about $40 in the category-day month.

When it starts

WhenTrigger idStarts onWindowHow it gets in
The weekly run of your locked 30-prompt panel is dueterm-panel-weekat on Monitor.checked where every 7 days from the panel lock7dPOST /{namespace}/monitors/{monitor}/check on the panel your file locks
An engine defines the term against your in-and-out rules on 3+ runs in a weekterm-misdefinedthreshold on Monitor.checked where 3 or more runs in one week against the in-and-out rules28dthe panel run itself (POST /{namespace}/monitors/{monitor}/check)
A countdown step before or after the category day is duecategory-day-dueat on Post.scheduled where T-28, T-14, T-7, T-1 and T-0 of the booked day, then T+3, T+7, T+30, T+60 and T+901dPOST /{namespace}/posts/{post}/schedule books each step on the day
+ 6 more for the graded stance, collisions, independent uses, rivals, search demand and threads (?lanes=all)
One signed delivery · StartupBuilder-Signature
{
  "$id": "https://api.sb/leaseline.app/events/event_1188",
  "$type": "Event",
  "name": "Monitor.checked",
  "at": "2026-10-19T06:00:41Z",
  "seq": 1188,
  "data": {
    "monitor": "monitor_6",
    "panel": "renewal-ops",
    "week": "2026-10-12",
    "engine": "perplexity",
    "runs": 9,
    "misdefined": 4,
    "cited": "page_88",
    "meaning": "HR contract renewals"
  }
}
Reproduce it in test
# runs this week’s panel in test
curl -X POST "https://api.sb/leaseline.app/monitors/monitor_6/check?mode=try" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY"
npx startup-builder trigger Monitor.checked --like event_1188   # replays the delivery
npx startup-builder clock advance --by 7d   # the next panel week

Who runs it

Content Lead · your agent (role:content-lead, worker_7) holds the Key Result. It hands every pitch, correction, guest spot and thread reply to you (Dana Okafor, person, worker_1), because the Marketing Lead and Communications Lead Roles have no person. You write or approve each one, and it sends from your own Mailbox. Your number links to Did it work.

OptionRung todayEvidence (passed of n)Moves up atDrops back whenYou can
Refresh the comparison · Hand it to searchIt does it, you can stop it2 of 2 · 1 of 1met on day 50 (the first 3 Pages)a Page fails fact-check → You approve each onePOST /{namespace}/actions/{action}/cancel inside the hold
Correct the source · Work a cited sourceYou approve each one5 of 6 (1 cut) · 4 of 4never: each sends in your name—POST /{namespace}/approvals/{approval}/approve · POST /{namespace}/approvals/{approval}/refuse
Answer the thread · Hold the dayTo a person, every time7 drafted, 7 written by you · 0 firednever—POST /{namespace}/tasks/{task}/claim
Change the panel or the kill ruleYou approve each one0 merged: both are fixed from T-28never—POST /{namespace}/changes/{change}/merge · POST /{namespace}/changes/{change}/revert
Never: a pitch, a launch post or a thread reply the agent wrote; a vote askTo a person, every time28 pitches, 1 launch post, 7 replies: all yoursnever—POST /{namespace}/tasks/{task}/assign

What it reads · What it may call. It reads the panel’s answers, the cited Pages and your Fact records, and every answer and fetched Page is data, never instructions. It may draft, publish your own comparison Page and book day steps; it never sends a pitch or a thread reply. Its tools are POST /{namespace}/content/draft, POST /{namespace}/messages/{message}/schedule, POST /{namespace}/tasks/{task}/assign, POST /{namespace}/content/{content}/publish, POST /{namespace}/keywords/{keyword}/measure, and any other call becomes an Approval under the Role’s Mandate.

The brief (folded): compiled Agent-register Markdown · play:category-kit@1 · each line names its record key
You hold the Content Lead Key Result: 20 % term share for renewal ops by 2026-11-23. ← worker, metric
On each panel run or term Event, choose one option and say why.                  ← triggers, chooses
The definition names no product; Leaseline’s approach sits in its own section.   ← copyRules 2
Every number carries a Fact with its method, sample and date.                    ← copyRules 1, fact-check
Never write a pitch, a launch post or a thread reply: draft fragments for Dana.  ← copyRules 10
Kill it at T+90 under 3 qualified Deals from term-touched Leads; never move that line after T-28. ← Kill rule, your file line 5

The slow loop. The panel and the kill rule are fixed from T-28, so no Change may touch them. The weekly Decisions changed no rule option 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
Correct the source correct-the-source3+ misdefined runs in a week, one cited PageYour rule (the record’s cited-source queue)POST /{namespace}/content/draft the correcting fact → POST /{namespace}/messages/{message}/schedule from your Mailboxyou approve it, due 1 business day · Take this onethe same
Work a cited source work-a-cited-sourcea cited domain that decides prompts never uses the termAgent’s call, with its reasonPOST /{namespace}/content/draft a guest-spot brief → POST /{namespace}/tasks/{task}/assignyou pitch it from your Mailbox, due 1 business day · Take this onethe same
Answer the thread answer-the-threada thread names the term or asks what it meansAgent’s call, with its reasonPOST /{namespace}/content/draft the fact pack → POST /{namespace}/tasks/{task}/assignyou write the reply, due 60 min · Take this onethe same
Refresh the comparison refresh-the-comparisona rival’s Page, Ad or listing uses the termYour rule (copyRules 12)POST /{namespace}/content/draft → POST /{namespace}/content/{content}/publish your comparison Page within 24 hnobody; nothing goes to the rivalthe same
Hand it to search hand-to-searchsearch demand above 0 for 4 weeks runningYour rule (term-seeding step 10)POST /{namespace}/keywords/{keyword}/measure → publish-contentnobodythe same
Hold the day hold-the-dayanother meaning on 30 %+ of runs, or another party’s markYour rule (the Collision hold)POST /{namespace}/tasks/{task}/assign: the countdown holdsyou pick the next name or accept the hold · Take this onethe same
When they write backFixture replyWhat happensWho answersBy whenCall
Interested“Send me the per-state split; I’m writing Thursday.”the CSV link from the release Page goes into your reply draftyou (Dana Okafor, person)60 minPOST /{namespace}/conversations/{conversation}/answer
Send me pricing“What does Leaseline cost?”a fragment with the Pricing Page’s list Price, for your replyyou1 business dayPOST /{namespace}/conversations/{conversation}/answer
Not now“Not this cycle.”the day-3 follow-up cancels; the Contact waits for the next releasenobodyat oncePOST /{namespace}/conversations/{conversation}/close
Wrong person“Our data desk covers this.”a fragment asking them to forward it; it never writes to an address from their textyou1 business dayPOST /{namespace}/conversations/{conversation}/answer
Out of officean auto-reply until Aug 31the follow-up waits for the return date, inside the 3-day rule or not at allnobodythe return datePOST /{namespace}/messages/{message}/schedule
Question it can’t answer“Is the 31 % figure seasonally adjusted?”the method note from the release Page, in the Briefyou60 minPOST /{namespace}/conversations/{conversation}/escalate
Stop“Take me off your list.”nothing else sends to them, from any of your Startupsnobodyat oncePOST /{namespace}/contacts/{contact}/suppress

When it hands to you

Every pitch, correction, guest spot and thread reply comes to you (Dana Okafor, person): the Marketing Lead and Communications Lead Roles have no person, and nothing sends in your name until you approve it. One Brief per Role, then the Approval, as captured (brief, draft, route and checks are Not live yet, gaps #7).

What lands in each queue · sample
[
  {
    "$id": "https://api.sb/leaseline.app/tasks/task_517",
    "$type": "Task",
    "assignee": "worker_1",
    "due": "2026-10-20T06:04:00Z",
    "on": "page_88",
    "brief": {
      "who": "the editor of a property-ops glossary (contact_52)",
      "said": "renewal ops: the HR team’s process for renewing employment contracts",
      "chose": "correct-the-source",
      "why": "4 of 9 Perplexity runs cite this Page for that meaning",
      "draft": "approval_88",
      "never": [
        "a pitch",
        "a link request",
        "a claim with no Fact"
      ]
    }
  },
  {
    "$id": "https://api.sb/leaseline.app/approvals/approval_88",
    "$type": "Approval",
    "verdict": null,
    "deadline": "2026-10-20T18:00:00Z",
    "draft": "Hi Jo, your glossary defines renewal ops as renewing employment contracts. In property management it names getting each lease renewal notice out on time…",
    "route": "correct-the-source",
    "checks": [
      {
        "check": "fact-check",
        "status": "pass"
      },
      {
        "check": "pitch-cap",
        "status": "pass"
      }
    ]
  }
]

You answer with POST /{namespace}/tasks/{task}/claim (Take this one), POST /{namespace}/tasks/{task}/return with a reason, POST /{namespace}/approvals/{approval}/approve or POST /{namespace}/approvals/{approval}/refuse, each a one-call window; an Approval unanswered by its deadline expires and nothing sends. Once you claim, the agent’s pending drafts on that source cancel with claimedByPerson (Not live yet, gaps #7), and every reply lands in your queue. A Task nobody claims by its due time stays with you, the last Role, and person-promise fires.

On time: you, 14 of 15 claimed within their due time, median 3 h 10 min, n 15, ■■□□ Early sign beside Other Startups’ 91 % on time (the 15th, task_402, a thread reply on Sep 6, waited 26 h). Your queue: counted by kind: in the category-day week, 28 pitches to write, 6 approvals and 3 thread replies; since then, about 2 approvals and 1 thread 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 day notice or correction to a Contact whose Lead, open Deal or Conversation a person ownsLeave it to the person who owns it: the draft waits in their queue.POST /{namespace}/tasks/{task}/assign
fact-check (hub, on POST /{namespace}/content/{content}/publish)a Page, Post or Message with a number or claim no Fact backsCut the claim, or name the Fact that backs it.POST /{namespace}/content/draft
embargo (the record’s Embargo hold)a dataset number on any Page or Post before the release liftsHold the number until lift at T-0.POST /{namespace}/posts/{post}/schedule
pitch-cap (the record’s Pitch cap)a 41st pitch on the day, a second exclusive, or a pitch off the release and the termCut the pitch, or keep the Contact for the next release.POST /{namespace}/tasks/{task}/assign
readiness (the record’s Readiness gate)a start with no graded stance, a closed proof gate or no lease on the nameGrade the stance in positioning-tournament first.POST /{namespace}/experiments/{experiment}/conclude
problem-cost (the record’s Problem cost floor)a canon with no cost Fact from an Interview or Customer recordRecord the cost from 5 Interviews first.POST /{namespace}/tasks/{task}/assign
Stop (pauses the Play)Pauses whenThen
collisionanother meaning on 30 %+ of baseline runs, or another party’s markthe countdown holds; hold-the-day hands it to you
hostile-reply2 hostile replies to pitches in one daythe pitch waves pause; each sender goes to POST /{namespace}/contacts/{contact}/suppress
meaning-driftmeaning fidelity under 60 % for 3 weeks runningterm seeding pauses; a canon review Task opens
common-ownershipa Page of one of your other Startups recommends Leaseline without stating common ownershiphouse placements pause until it does
iterateat T+45, term share under 10 % with no independent useone second release angle and one 45-day extension, once
kill-ruleat T+90, term-touched Leads opened under 3 qualified Dealsthe Story reverts to the runner-up; the canon stays up as a glossary
holdout-harmat T+90, the category headline trails the runner-up beyond the intervalthe same as kill-rule
kill-switchyou press itevery step pauses with no approval; your Pages stay up
+ 2 more for the launch lane: the release floor and the deploy freeze (?lanes=all)

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

422RefusedThe LinkedIn Post did not schedule: it shows a dataset number 5 days before lift.
CheckFixThen
embargo failHold the number until lift at T-0.POST /{namespace}/posts/{post}/schedule
fact-check pass · Not live yet, gaps #1—POST /{namespace}/content/draft
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "The LinkedIn Post did not schedule: it shows a dataset number 5 days before lift.",
  "checks": [
    {
      "check": "embargo",
      "status": "fail",
      "doc": "/plays/category-kit#check-embargo",
      "fix": "Hold the number until lift at T-0.",
      "then": "Post.schedule"
    },
    {
      "check": "fact-check",
      "status": "pass"
    }
  ]
}

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

The Stops that fired, as Campaign.paused reasons · sample
[
  {
    "reason": {
      "limit": "meaning-drift",
      "observed": "55 %, 58 %, 57 %",
      "bound": "60 %",
      "window": "3 weeks"
    },
    "doc": "/plays/category-kit#stop-meaning-drift",
    "task": "task_431"
  }
]

Did it work

An answer engine cannot be split, so the leaf reads before-after (rule o). The 80/20 headline split on Visitors with no term touch is random, so the rows above the leaf read treated against held back. Each figure’s call is POST /{namespace}/metrics/query by node, and every node above the leaf is Not live yet (gaps #4).

16.9 % term share against 0 % before · before-after, not proof · n 360 runs · path → arr

Chose
correct-the-source
Why
4 of 9 Perplexity runs this week define renewal ops as HR contract renewals, and all 4 cite the same glossary Page
From
correct-the-source · work-a-cited-source · answer-the-thread · refresh-the-comparison · hand-to-search · hold-the-day
Expects
meaning fidelity on Perplexity back over 60 % within 28d
Reopens when
term-misdefined fires again for page_88 within 28d
By
worker_7
JSON
{
  "$id": "decisions/decision_571",
  "$type": "Decision",
  "choice": "correct-the-source",
  "reason": "4 of 9 Perplexity runs this week define renewal ops as HR contract renewals, and all 4 cite the same glossary Page",
  "stakes": "low",
  "options": [
    "correct-the-source",
    "work-a-cited-source",
    "answer-the-thread",
    "refresh-the-comparison",
    "hand-to-search",
    "hold-the-day"
  ],
  "by": "worker_7",
  "on": "page_88",
  "expected": "meaning fidelity on Perplexity back over 60 % within 28d",
  "reopensWhen": "term-misdefined fires again for page_88 within 28d"
}
NodeCategory headline (80 %)Runner-up headline (20 %, held back)AddedConfidenceBasis
category-term-shareNow: 16.9 % (61 of 360 definitional runs, Oct 5–18)Before: 0 % (0 of 360, Jul 13–26)— (no halves on the leaf)—before-after, not proof · Other Startups’ results +12 per 100 runs by T+60, ■■□□ Early sign, n 14
icp-reached ↑9.4 qualified Leads per 1,000 Visitors (37 of 3,920)7.1 (7 of 980)+2.3 [−3.0, +7.6]■□□□ Too early to tellheld back at random · n 4,900 Visitors · reads to T+90
new-arr ↑$1,044, 3 Customers · Booked $1,392: credited, not all caused by this Play$0, 0 Customers+$266 per 1,000 Visitors [−$190, +$720] · Worth about +$130 a month■□□□ Too early to tell (3 vs 0 Customers)the same assignment · 2 qualified Deals and 4 trials still deciding
net-new-arr · arr+$1,044$0carried: it moves no other bridge term■□□□ Too early to tellcarried from new-arr

Term share counts the definitional runs whose answer cites a canon Page or names Leaseline as the term’s source, per engine, 2 weeks at a time. The headline split reads qualified Leads per 1,000 Visitors with no term touch until T+90, Nov 23.

How it moves it: answer engines cite your definition Page (page_61) on 61 of 360 definitional runs, where before the day no run cited any source for renewal ops.

Guardrails: on the path: term-touched Leads opened 2 qualified Deals against the kill rule’s 3 by Nov 23 (still deciding), and the category headline stays above the runner-up, so holdout-harm has not fired.

The Campaign card · sample
{
  "$id": "https://api.sb/leaseline.app/campaigns/category-kit",
  "$type": "Campaign",
  "play": "play:category-kit@1",
  "path": [
    "category-term-share",
    "icp-reached",
    "new-arr",
    "net-new-arr",
    "arr"
  ],
  "experiment": {
    "metric": "category-term-share",
    "unit": "percent",
    "heldBack": 980,
    "decision": null
  },
  "readout": {
    "value": null,
    "n": 360,
    "maturing": 0,
    "interval": null,
    "readability": "inadmissible",
    "basis": "before-after",
    "pooled": false
  },
  "ledger": {
    "spend": 0,
    "workerCost": 71,
    "hours": 11.5,
    "pipelineArr": 4800,
    "wonArr": 1392,
    "projectedArr": 130,
    "paybackDays": null
  }
}

Outside benchmark: journalists picked 33 % of human-written pitches against 10 % of fully AI-generated ones (1,394,740 pitches answering 42,392 requests, a pitch-marketplace detection study, 2026-09-23).

Before it · After it. Before it: positioning-tournament grades the stance and hands over the name (Experiment.concluded). After it: aeo folds the term panel into its own on ship, editorial-seo and paid-search hear search demand once it appears, and community-answers takes open threads after T+7.

Example

Leaseline ran it from 2026-07-08 to 2026-10-19 (103 days; T-0 was Tue 2026-08-25, so asOf is T+55). The panel ran 30 prompts on 6 engines, 3 samples each: 540 runs a week, 180 of them definitional. 25 Decisions followed term Events. Read every captured thread at ?threads=all; three follow the tables.

What happened, by optionDecisionsSent or publishedSo far
Correct the source65 corrections from your Mailbox, 1 cut3 Pages changed their definition
Work a cited source94 guest-spot pitches, 2 listings2 guest spots given, 3 independent uses
Answer the thread77 replies, each written by you2 term-touched Leads
Refresh the comparison · Hand it to search · Hold the day2 · 1 · 02 Pages within 24 h · 1 hand-off · ——
The category day, Aug 2528 pitches, 1 exclusive9 replies, 4 pieces published1,206 release Page visits on the day
At 1,000 Visitors a month (the Use it when volume)about 400 held back by T+90the parent reads Too early to tellOther Startups’ results: +1.8 qualified Leads per 1,000 Visitors, ■■□□ Early sign, n 14
DayEventWhat happenedYour time
T-48 · Jul 8event_402 Campaign.createdthe dry run fails approved-pages; you publish your pricing and about Pages25 min
T-43 to T-30event_418 Monitor.checked, first of 2baseline: 22 of 360 definitional runs give another meaning (6 %), under the 30 % hold—
T-28 · Jul 28event_477 Post.scheduledthe day drawn at random from Aug 25, Aug 26 and Sep 1; you accepted it5 min
T-7 · Aug 18event_560 Content.publisheddefinition, point-of-view, glossary, comparison and origin Pages up, unannounced2 h on your point of view
T-5 · Aug 20event_571 Action.refusedembargo held a LinkedIn Post with the 31 % finding—
T-0 · Aug 25event_602 Post.publishedthe release lifts; you send 28 pitches in 3 waves; 9 reply3 h 20 min
T+9 · Sep 3event_655 Monitor.checkedfirst cited definition: Perplexity cites page_61 on 2 of 9 runs—
T+21 · Sep 15event_701 Campaign.pausedmeaning-drift at 55, 58 and 57 %; you tightened the in-and-out rules on Sep 1740 min
T+45 · Oct 9event_811 Decision.createdthe iterate rule reads 15.8 % and 3 independent uses, so no second angle—
T-48 to T+55event_431 Approval.created, first of 15you approved 14 corrections and pitches, cut 1, and wrote 7 thread replies4 h · total 11.5 h measured, 13 h asked

Dana → Morgan at a property-trade newsletter, Aug 25, 07:12 · Across 1,212 leases at 38 small property managers, 31 % of renewal notices went out under 60 days before the lease ended.¹ We call getting them out on time renewal ops, and the definition is here.² The dataset and method are on the release Page.³ *Written and sent by Dana from her own Mailbox.*⁴

Morgan, 09:40 · “Send me the per-state split; I’m writing Thursday.” · Dana, 10:05 · the CSV link from the release Page. The piece ran Aug 27, citing the definition Page.

The LinkedIn Post, 2026-08-20 · the dataset number refused before lift, then the rewrite that posted
- 31 % of renewal notices go out late. Here’s what we found across 1,212 leases.
+ Renewal ops: getting every renewal notice out on time. Our definition, in plain words.

A landlord forum thread, 2026-10-02 08:14 · “Is renewal ops just a spreadsheet with reminders?” · Content Lead · your agent, 08:16 · drafted the fact pack (the definition, the 3 in-and-out rules and the dataset link) into your queue, due 09:14 (task_488). · Dana, 08:51 · posted her own reply, linking the definition Page.

¹ From the release’s stored query, with its n and interval. ² The definition Page, which names no product. ³ The method, sample and date, on the release Page. ⁴ The agent built the list and the brief; it never writes a pitch.

Your settings

plays/category-kit.mdx
---
term: renewal ops
holdout: 0.2       # 20 % of Visitors with no term touch see the runner-up headline
day: 2026-08-25
kill: 3 qualified Deals from term-touched Leads by T+90
---
Make renewal ops the name for getting every renewal notice out on time. I write every pitch, the launch post and every thread reply.
Text
$ npx startup-builder show plays/category-kit
term renewal ops · holdout 0.2 · day 2026-08-25 · kill 3 qualified Deals     your file  plays/category-kit.mdx:2-5,7 (Ask 2026-07-08; day by event_477, 2026-07-28)
family demand · worker role:content-lead, owns never · chooses 6 (4 rule, 2 read) · sequences category-press-countdown, category-day-notice · checks owned-by-a-person, fact-check, embargo, pitch-cap, readiness, problem-cost · stops 10 · placements 6 answer engines, google-search, product-hunt, hacker-news, linkedin, x, youtube, gmail, outlook    catalog  play:category-kit@1 (Not live yet, gaps #5)

Every key from the catalog

Key Id What it is
Tactic category-readiness-check Category readiness check reads the Proof gate, ICP demand, the graded stance, the Problem cost and the territory lease, then fixes the kill rule. Starts at It does it, you can stop it.
Tactic category-name-round Category name round drafts candidate terms from Customers’ words, drops collisions and taken marks, and hands the top 3 to the positioning tournament. Starts at You approve each one.
Tactic term-panel-build Term panel build locks the 30-prompt term panel and the in-and-out rules, runs 2 baseline weeks, and holds on a meaning collision. Starts at You approve the first wave.
Tactic category-canon-build Category canon build makes the definition, point-of-view, glossary, comparison and origin Pages from the founder’s words, 7 days before the day. Starts at You approve the first wave.
Tactic category-day-plan Category day plan picks one dated day, books every composed Play onto it with its own gates, and runs the countdown from 28 days before. Starts at It does it, you can stop it.
Tactic term-seeding Term seeding works the cited domains that never use the term, through listings, guest spots, thread answers and corrections, and logs independent uses. Starts at You approve each one.
Tactic term-share-readout Term share readout reads term share weekly beside adoption and fidelity, with an iterate rule at day 45 and a kill rule at day 90. Starts at Sends nothing.
Tactic prompt-panel-run Prompt panel run: Samples every panel prompt 3 times per answer engine each week, stores the retrieval set, and computes answer share with its interval. Starts at Sends nothing.
Tactic cited-source-queue Cited-source queue: Ranks the third-party Pages answer engines cite for the panel, routes each to a fix, sends factual corrections, and records every earned mention. Starts at You approve each one.
Tactic honest-comparison Honest comparison: Keeps one comparison Page per named rival, with method, sources, date checked and the rows the rival wins, updated within 24 hours of a change. Starts at You approve each one.
Tactic retrieval-readiness-check Retrieval readiness check: Fetches each Page as answer-engine crawlers do and fails any Page whose shown facts are missing from the raw HTML or blocked from retrieval. Starts at Sends nothing.
Tactic release-gate Release gate freezes a Dataset snapshot, turns each finding into a stored query with n and interval, and publishes nothing until ten checks pass. Starts at You approve each one.
Tactic media-list-build Media list build turns 12 months of coverage into 20 to 40 scored, leased journalists, with a random tier 2 holdout and one brief each. Starts at You approve each one.
Tactic pitch-critic Pitch critic briefs the human author before a pitch and checks the draft after it, returning fragments and comments and never rewritten text. Starts at Sends nothing.
Tactic release-pitch Release pitch sends the founder’s own pitches from the founder’s Mailbox at a randomized lift, with one offer, one follow-up and every reply routed back. Starts at You approve each one.
Tactic release-publish Release publish lifts the release Page with its CSV and charts, posts from the Startup’s Handles, and notifies every Person who opted in. Starts at It does it, you can stop it.
Tactic launch-readiness-gate Launch readiness gate runs nine rule checks on a live Startup and books a launch only when every check passes. Starts at Sends nothing.
Tactic launch-booking Launch booking orders the eligible Venues, picks a date inside the Portfolio caps and the Human’s reply block, and books a deploy freeze. Starts at It does it, you can stop it.
Tactic launch-kit Launch kit compiles the gallery, Video, tagline, fact sheet and red-team list from the live Site and the claims source for the Human. Starts at You approve each one.
Tactic owned-audience-notice Owned audience notice tells consented People the Startup is live, admits the Waitlist batch, and posts from the Startup’s own Handles, with no vote ask. Starts at You approve each one.
Tactic launch-desk Launch desk watches a live launch thread for 72 hours and hands the Human a fragment-only reply brief for each comment within 5 minutes. Starts at Sends nothing.
Trigger category-stance-graded Category stance graded: event on Experiment.concluded, window 90d.
Trigger term-panel-week Term panel week: at on Monitor.checked, window 7d.
Trigger category-day-due Category day due: at on Post.scheduled, window 1d.
Trigger term-collision Term collision: threshold on Monitor.checked, window 7d.
Trigger term-misdefined Term misdefined: threshold on Monitor.checked, window 28d.
Trigger term-used-independently Term used independently: event on Monitor.checked, window 28d.
Trigger rival-uses-term Rival uses term: event on Monitor.checked, window 72h.
Trigger term-search-appears Term search appears: threshold on Keyword.measured, window 30d.
Trigger term-thread Term thread: event on Monitor.checked, window 48h.
Trigger model-release Model release: event on Monitor.checked, window 7d.
Sequence category-press-countdown Category press countdown: 5 steps; it ends on A reply; A decline; Coverage published; An opt-out; A bounce; A hostile reply.
Sequence category-day-notice Category day notice: 3 steps; it ends on An opt-out; A bounce.
Benchmark category-kit-ai-pitch-selection Selection rate of fully AI-generated press pitches by journalists.: 10 % (Pitch-marketplace detection study., 2026-09-23).
Benchmark category-kit-human-pitch-selection Selection rate of human-written press pitches by journalists.: 33 % (Pitch-marketplace detection study; mixed and AI-assisted pitches excluded., 2026-09-23).
Benchmark category-kit-journalist-ai-opt-out Share of journalists who turned on the AI-pitch opt-out, which is off by default.: 35 % (Pitch-marketplace detection study., 2026-09-23).
Benchmark category-kit-mention-correlation Spearman correlation of branded web mentions with brand visibility in Google AI Overviews; page count correlates at 0.17.: 0.664 ratio (75,000-brand correlation study., 2025-05-26).
Benchmark category-kit-brand-list-repeat Share of repeated runs of one prompt that return the same brand list.: 0–1 % (Brand-recommendation consistency study across 3 answer engines., 2026-01-28).

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