URL: /plays/category-kit · Id: `play:category-kit`

# 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.

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](https://startupbuilder.dev/business/nouns/deal).

```text title="Set it up · Ask"
Be our Content Lead: make renewal ops the name for getting every renewal notice out on time. Build the canon from my own words, book one category day, and kill it at day 90 if term-touched Leads open fewer than 3 qualified Deals. I write every pitch myself. Show me what’s missing; don’t send.
```

```text title="Run one · Ask"
Hand this week’s term panel run to the Content Lead agent and show me what it chose and why. Don’t send.
```

```ts title="Run one · SDK"
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 }
```

```json title="Run one · Response · sample"
{
  "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"
    ],
    "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"
  },
  "actions": [
    {
      "$id": "https://api.sb/leaseline.app/actions/action_1",
      "$type": "Action",
      "status": "done",
      "mode": "try",
      "by": "worker_7",
      "verb": "Content.draft",
      "checks": [
        {
          "check": "fact-check",
          "status": "pass"
        }
      ]
    },
    {
      "$id": "https://api.sb/leaseline.app/actions/action_2",
      "$type": "Action",
      "status": "pending",
      "reason": "awaitingApproval",
      "mode": "try",
      "by": "worker_7",
      "verb": "Message.schedule",
      "checks": [
        {
          "check": "owned-by-a-person",
          "status": "pass"
        },
        {
          "check": "fact-check",
          "status": "pass"
        },
        {
          "check": "embargo",
          "status": "pass"
        },
        {
          "check": "pitch-cap",
          "status": "pass"
        }
      ]
    }
  ]
}
```

`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 source | Choice | Reason |
| --- | --- | --- |
| A property-ops glossary: cited on 4 of 9 Perplexity runs for “HR contract renewals” | `correct-the-source` | 3 or more misdefined runs in a week, one cited Page |
| A rival’s pricing Page now says “renewal ops” | `refresh-the-comparison` | a rival uses the term; nothing is sent to the rival |
| A landlord forum thread: “Is renewal ops just a spreadsheet with reminders?” | `answer-the-thread` | a thread asks what the term means; you write the reply |
| A property-tech newsletter cited in 11 panel answers, never using the term | `work-a-cited-source` | it decides prompts and has a guest-spot opening that matches your buyers |

| Worth | Your time | Spend | First signal | Use it when | Instead |
| --- | --- | --- | --- | --- | --- |
| ≈ +$130 ARR a month at 2,600 Visitors | 3 h week 1, about 13 h over the 90 days | $0.01 per panel run, ~$23 a month at 540 a week | T+9: first engine cites your definition | A graded new-category stance, 1,000+ Visitors a month | No graded stance: `positioning-tournament` · under 1,000 Visitors: `aeo` · under 5 Interviews: `signup-interviews` |

**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
```bash
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"}'
```


```json title="The dry run’s 422 · 2026-07-08 · sample"
{
  "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"
    }
  ]
}
```

| Check | Fix (one call) | Your time | Wait |
| --- | --- | --- | --- |
| <a id="check-use-when"></a>`use-when` · <a id="check-baseline"></a>`baseline` · pass: stance graded Jul 7, 2,610 Visitors a month · warn: no term history (gaps #8) | <Op verb="Metric.query" /> on `category-term-share`; the 2 baseline weeks fill Before in Your number | 1 min | 2 baseline weeks |
| <a id="check-approved-pages"></a>`approved-pages` · fail (gaps #8) | <Op verb="Site.publish" /> your pricing and about Pages | 20 min | none |
| <a id="check-domain-authenticated"></a>`domain-authenticated` · pass | <Op verb="Domain.authenticate" />, already done for the day notice | 0 min | none |
| <a id="check-role-unstaffed"></a>`role-unstaffed` · warn (gaps #8): 31 of your open Leads have a person owner, you | <Op verb="Role.staff" />, or leave it: pitches, corrections and thread replies come to you | 0 min | none |

`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
| When | Trigger id | Starts on | Window | How it gets in |
| --- | --- | --- | --- | --- |
| The weekly run of your locked 30-prompt panel is due | `term-panel-week` | `at` on `Monitor.checked` where every 7 days from the panel lock | 7d | <Op verb="Monitor.check" /> on the panel your file locks |
| An engine defines the term against your in-and-out rules on 3+ runs in a week | `term-misdefined` | `threshold` on `Monitor.checked` where 3 or more runs in one week against the in-and-out rules | 28d | the panel run itself (<Op verb="Monitor.check" />) |
| A countdown step before or after the category day is due | `category-day-due` | `at` 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+90 | 1d | <Op verb="Post.schedule" /> books each step on the day |
| + 6 more for the graded stance, collisions, independent uses, rivals, search demand and threads (`?lanes=all`) | | | | |

```json title="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"
  }
}
```

```bash title="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.

| Option | Rung today | Evidence (passed of n) | Moves up at | Drops back when | You can |
| --- | --- | --- | --- | --- | --- |
| Refresh the comparison · Hand it to search | It does it, you can stop it | 2 of 2 · 1 of 1 | met on day 50 (the first 3 Pages) | a Page fails `fact-check` → You approve each one | <Op verb="Action.cancel" /> inside the hold |
| Correct the source · Work a cited source | You approve each one | 5 of 6 (1 cut) · 4 of 4 | never: each sends in your name | — | <Op verb="Approval.approve" /> · <Op verb="Approval.refuse" /> |
| Answer the thread · Hold the day | To a person, every time | 7 drafted, 7 written by you · 0 fired | never | — | <Op verb="Task.claim" /> |
| Change the panel or the kill rule | You approve each one | 0 merged: both are fixed from T-28 | never | — | <Op verb="Change.merge" /> · <Op verb="Change.revert" /> |
| Never: a pitch, a launch post or a thread reply the agent wrote; a vote ask | To a person, every time | 28 pitches, 1 launch post, 7 replies: all yours | never | — | <Op verb="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 <Op verb="Content.draft" />, <Op verb="Message.schedule" />, <Op verb="Task.assign" />, <Op verb="Content.publish" />, <Op verb="Keyword.measure" />, and any other call becomes an Approval under the Role’s Mandate.

```md title="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
| Option | Picked when | Decided by | Runs | Hands to | If it’s just you |
| --- | --- | --- | --- | --- | --- |
| Correct the source `correct-the-source` | 3+ misdefined runs in a week, one cited Page | Your rule (the record’s cited-source queue) | <Op verb="Content.draft" /> the correcting fact → <Op verb="Message.schedule" /> from your Mailbox | you approve it, due 1 business day · Take this one | the same |
| Work a cited source `work-a-cited-source` | a cited domain that decides prompts never uses the term | Agent’s call, with its reason | <Op verb="Content.draft" /> a guest-spot brief → <Op verb="Task.assign" /> | you pitch it from your Mailbox, due 1 business day · Take this one | the same |
| Answer the thread `answer-the-thread` | a thread names the term or asks what it means | Agent’s call, with its reason | <Op verb="Content.draft" /> the fact pack → <Op verb="Task.assign" /> | you write the reply, due 60 min · Take this one | the same |
| Refresh the comparison `refresh-the-comparison` | a rival’s Page, Ad or listing uses the term | Your rule (copyRules 12) | <Op verb="Content.draft" /> → <Op verb="Content.publish" /> your comparison Page within 24 h | nobody; nothing goes to the rival | the same |
| Hand it to search `hand-to-search` | search demand above 0 for 4 weeks running | Your rule (term-seeding step 10) | <Op verb="Keyword.measure" /> → `publish-content` | nobody | the same |
| Hold the day `hold-the-day` | another meaning on 30 %+ of runs, or another party’s mark | Your rule (the Collision hold) | <Op verb="Task.assign" />: the countdown holds | you pick the next name or accept the hold · Take this one | the same |

| When they write back | Fixture reply | What happens | Who answers | By when | Call |
| --- | --- | --- | --- | --- | --- |
| Interested | “Send me the per-state split; I’m writing Thursday.” | the CSV link from the release Page goes into your reply draft | you (Dana Okafor, person) | 60 min | <Op verb="Conversation.answer" /> |
| Send me pricing | “What does Leaseline cost?” | a fragment with the Pricing Page’s list Price, for your reply | you | 1 business day | <Op verb="Conversation.answer" /> |
| Not now | “Not this cycle.” | the day-3 follow-up cancels; the Contact waits for the next release | nobody | at once | <Op verb="Conversation.close" /> |
| Wrong person | “Our data desk covers this.” | a fragment asking them to forward it; it never writes to an address from their text | you | 1 business day | <Op verb="Conversation.answer" /> |
| Out of office | an auto-reply until Aug 31 | the follow-up waits for the return date, inside the 3-day rule or not at all | nobody | the return date | <Op verb="Message.schedule" /> |
| Question it can’t answer | “Is the 31 % figure seasonally adjusted?” | the method note from the release Page, in the Brief | you | 60 min | <Op verb="Conversation.escalate" /> |
| Stop | “Take me off your list.” | nothing else sends to them, from any of your Startups | nobody | at once | <Op verb="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).

```json title="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 <Op verb="Task.claim" /> (Take this one), <Op verb="Task.return" /> with a reason, <Op verb="Approval.approve" /> or <Op verb="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:** <Op verb="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) | Refuses | Fix | Then |
| --- | --- | --- | --- |
| <a id="check-owned-by-a-person"></a>`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 owns | Leave it to the person who owns it: the draft waits in their queue. | <Op verb="Task.assign" /> |
| <a id="check-fact-check"></a>`fact-check` (hub, on <Op verb="Content.publish" />) | a Page, Post or Message with a number or claim no Fact backs | Cut the claim, or name the Fact that backs it. | <Op verb="Content.draft" /> |
| <a id="check-embargo"></a>`embargo` (the record’s Embargo hold) | a dataset number on any Page or Post before the release lifts | Hold the number until lift at T-0. | <Op verb="Post.schedule" /> |
| <a id="check-pitch-cap"></a>`pitch-cap` (the record’s Pitch cap) | a 41st pitch on the day, a second exclusive, or a pitch off the release and the term | Cut the pitch, or keep the Contact for the next release. | <Op verb="Task.assign" /> |
| <a id="check-readiness"></a>`readiness` (the record’s Readiness gate) | a start with no graded stance, a closed proof gate or no lease on the name | Grade the stance in `positioning-tournament` first. | <Op verb="Experiment.conclude" /> |
| <a id="check-problem-cost"></a>`problem-cost` (the record’s Problem cost floor) | a canon with no cost Fact from an Interview or Customer record | Record the cost from 5 Interviews first. | <Op verb="Task.assign" /> |

| Stop (pauses the Play) | Pauses when | Then |
| --- | --- | --- |
| <a id="stop-collision"></a>`collision` | another meaning on 30 %+ of baseline runs, or another party’s mark | the countdown holds; `hold-the-day` hands it to you |
| <a id="stop-hostile-reply"></a>`hostile-reply` | 2 hostile replies to pitches in one day | the pitch waves pause; each sender goes to <Op verb="Contact.suppress" /> |
| <a id="stop-meaning-drift"></a>`meaning-drift` | meaning fidelity under 60 % for 3 weeks running | term seeding pauses; a canon review Task opens |
| <a id="stop-common-ownership"></a>`common-ownership` | a Page of one of your other Startups recommends Leaseline without stating common ownership | house placements pause until it does |
| <a id="stop-iterate"></a>`iterate` | at T+45, term share under 10 % with no independent use | one second release angle and one 45-day extension, once |
| <a id="stop-kill-rule"></a>`kill-rule` | at T+90, term-touched Leads opened under 3 qualified Deals | the Story reverts to the runner-up; the canon stays up as a glossary |
| <a id="stop-holdout-harm"></a>`holdout-harm` | at T+90, the category headline trails the runner-up beyond the interval | the same as `kill-rule` |
| <a id="stop-kill-switch"></a>`kill-switch` | you press it | every 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.

```json title="The captured refusal · sample"
{
  "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"
    }
  ]
}
```


```json title="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 <Op verb="Metric.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`

| Node | Category headline (80 %) | Runner-up headline (20 %, held back) | Added | Confidence | Basis |
| --- | --- | --- | --- | --- | --- |
| `category-term-share` | Now: 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 tell | held 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 | $0 | carried: it moves no other bridge term | ■□□□ Too early to tell | carried 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.

```json title="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 option | Decisions | Sent or published | So far |
| --- | --- | --- | --- |
| Correct the source | 6 | 5 corrections from your Mailbox, 1 cut | 3 Pages changed their definition |
| Work a cited source | 9 | 4 guest-spot pitches, 2 listings | 2 guest spots given, 3 independent uses |
| Answer the thread | 7 | 7 replies, each written by you | 2 term-touched Leads |
| Refresh the comparison · Hand it to search · Hold the day | 2 · 1 · 0 | 2 Pages within 24 h · 1 hand-off · — | — |
| The category day, Aug 25 | 28 pitches, 1 exclusive | 9 replies, 4 pieces published | 1,206 release Page visits on the day |
| At 1,000 Visitors a month (the Use it when volume) | about 400 held back by T+90 | the parent reads Too early to tell | Other Startups’ results: +1.8 qualified Leads per 1,000 Visitors, ■■□□ Early sign, n 14 |

| Day | Event | What happened | Your time |
| --- | --- | --- | --- |
| T-48 · Jul 8 | `event_402` Campaign.created | the dry run fails `approved-pages`; you publish your pricing and about Pages | 25 min |
| T-43 to T-30 | `event_418` Monitor.checked, first of 2 | baseline: 22 of 360 definitional runs give another meaning (6 %), under the 30 % hold | — |
| T-28 · Jul 28 | `event_477` Post.scheduled | the day drawn at random from Aug 25, Aug 26 and Sep 1; you accepted it | 5 min |
| T-7 · Aug 18 | `event_560` Content.published | definition, point-of-view, glossary, comparison and origin Pages up, unannounced | 2 h on your point of view |
| T-5 · Aug 20 | `event_571` Action.refused | `embargo` held a LinkedIn Post with the 31 % finding | — |
| T-0 · Aug 25 | `event_602` Post.published | the release lifts; you send 28 pitches in 3 waves; 9 reply | 3 h 20 min |
| T+9 · Sep 3 | `event_655` Monitor.checked | first cited definition: Perplexity cites `page_61` on 2 of 9 runs | — |
| T+21 · Sep 15 | `event_701` Campaign.paused | `meaning-drift` at 55, 58 and 57 %; you tightened the in-and-out rules on Sep 17 | 40 min |
| T+45 · Oct 9 | `event_811` Decision.created | the iterate rule reads 15.8 % and 3 independent uses, so no second angle | — |
| T-48 to T+55 | `event_431` Approval.created, first of 15 | you approved 14 corrections and pitches, cut 1, and wrote 7 thread replies | 4 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.

```diff title="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
```mdx title="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 | <a id="tactic-category-readiness-check"></a>`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 | <a id="tactic-category-name-round"></a>`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 | <a id="tactic-term-panel-build"></a>`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 | <a id="tactic-category-canon-build"></a>`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 | <a id="tactic-category-day-plan"></a>`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 | <a id="tactic-term-seeding"></a>`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 | <a id="tactic-term-share-readout"></a>`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 | <a id="tactic-prompt-panel-run"></a>`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 | <a id="tactic-cited-source-queue"></a>`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 | <a id="tactic-honest-comparison"></a>`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 | <a id="tactic-retrieval-readiness-check"></a>`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 | <a id="tactic-release-gate"></a>`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 | <a id="tactic-media-list-build"></a>`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 | <a id="tactic-pitch-critic"></a>`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 | <a id="tactic-release-pitch"></a>`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 | <a id="tactic-release-publish"></a>`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 | <a id="tactic-launch-readiness-gate"></a>`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 | <a id="tactic-launch-booking"></a>`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 | <a id="tactic-launch-kit"></a>`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 | <a id="tactic-owned-audience-notice"></a>`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 | <a id="tactic-launch-desk"></a>`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 | <a id="trigger-category-stance-graded"></a>`category-stance-graded` | Category stance graded: `event` on `Experiment.concluded`, window 90d. |
| Trigger | <a id="trigger-term-panel-week"></a>`term-panel-week` | Term panel week: `at` on `Monitor.checked`, window 7d. |
| Trigger | <a id="trigger-category-day-due"></a>`category-day-due` | Category day due: `at` on `Post.scheduled`, window 1d. |
| Trigger | <a id="trigger-term-collision"></a>`term-collision` | Term collision: `threshold` on `Monitor.checked`, window 7d. |
| Trigger | <a id="trigger-term-misdefined"></a>`term-misdefined` | Term misdefined: `threshold` on `Monitor.checked`, window 28d. |
| Trigger | <a id="trigger-term-used-independently"></a>`term-used-independently` | Term used independently: `event` on `Monitor.checked`, window 28d. |
| Trigger | <a id="trigger-rival-uses-term"></a>`rival-uses-term` | Rival uses term: `event` on `Monitor.checked`, window 72h. |
| Trigger | <a id="trigger-term-search-appears"></a>`term-search-appears` | Term search appears: `threshold` on `Keyword.measured`, window 30d. |
| Trigger | <a id="trigger-term-thread"></a>`term-thread` | Term thread: `event` on `Monitor.checked`, window 48h. |
| Trigger | <a id="trigger-model-release"></a>`model-release` | Model release: `event` on `Monitor.checked`, window 7d. |
| Sequence | <a id="sequence-category-press-countdown"></a>`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 | <a id="sequence-category-day-notice"></a>`category-day-notice` | Category day notice: 3 steps; it ends on An opt-out; A bounce. |
| Benchmark | <a id="benchmark-category-kit-ai-pitch-selection"></a>`category-kit-ai-pitch-selection` | Selection rate of fully AI-generated press pitches by journalists.: 10 % (Pitch-marketplace detection study., 2026-09-23). |
| Benchmark | <a id="benchmark-category-kit-human-pitch-selection"></a>`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 | <a id="benchmark-category-kit-journalist-ai-opt-out"></a>`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 | <a id="benchmark-category-kit-mention-correlation"></a>`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 | <a id="benchmark-category-kit-brand-list-repeat"></a>`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). |