URL: /plays/signup-interviews · Id: `play:signup-interviews`

# Waitlist interviews

> Interviews each Waitlist signup with your disclosed agent, admits by fit under a published cap, and sends a result built on their company.

[Interviews](https://startupbuilder.dev/business/nouns/interview) each [Waitlist](https://startupbuilder.dev/business/nouns/waitlist) signup with your disclosed agent, admits by fit under a published cap, and sends a result built on their company.

```text title="Set it up · Ask"
Be our SDR: offer everyone on our Waitlist a short interview with you, say you’re an AI agent, and send each one a renewal calendar built on their own units. I have 10 onboarding slots a week; admit half by your interview rank and half by form rank, as today. Show me what’s missing; don’t send.
```

```text title="Run one · Ask"
Hand our latest finished interview to the SDR 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 ("Waitlist.joined", "Interview.completed", "Interview.abandoned", "Call.requested", "Evidence.created", "Schedule.fired", "Waitlist.admitted", "Meeting.held", "Customer.activated", "Message.replied", "Check.failed")', 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_361",
    "$type": "Decision",
    "choice": "admit-now",
    "reason": "Corbin Rentals manages 64 units for 3 owners and named the renewal notices they miss each month; rank 2 of 31 this week, under the cap of 10",
    "stakes": "medium",
    "options": [
      "offer-the-interview",
      "admit-now",
      "keep-in-queue",
      "to-you",
      "not-a-fit"
    ],
    "by": "worker_2",
    "on": "lead_71",
    "expected": "activation within 30d of admission",
    "reopensWhen": "no Meeting.booked for lead_71 within 2d of admission"
  },
  "actions": [
    {
      "$id": "https://api.sb/leaseline.app/actions/action_1",
      "$type": "Action",
      "status": "done",
      "mode": "try",
      "by": "worker_2",
      "verb": "Lead.qualify",
      "checks": []
    },
    {
      "$id": "https://api.sb/leaseline.app/actions/action_2",
      "$type": "Action",
      "status": "pending",
      "reason": "awaitingTime",
      "mode": "try",
      "by": "worker_2",
      "verb": "Message.schedule",
      "checks": [
        {
          "check": "owned-by-a-person",
          "status": "pass"
        },
        {
          "check": "fact-check",
          "status": "pass"
        },
        {
          "check": "approved-pages",
          "status": "pass"
        }
      ]
    },
    {
      "$id": "https://api.sb/leaseline.app/actions/action_3",
      "$type": "Action",
      "status": "pending",
      "reason": "awaitingTime",
      "mode": "try",
      "by": "worker_2",
      "verb": "Waitlist.admit",
      "checks": []
    }
  ]
}
```

`action_2` is Corbin’s result, a renewal calendar for their 64 units, held 2 minutes. `action_3` waits for Monday’s admit list at 09:00, which you approve.

`+23.1 per 100 · ■■□□ Early sign · n 52 · path → arr`

| Try another: the signup | Choice | Reason |
| --- | --- | --- |
| Corbin Rentals, 64 units: “We miss renewal notices for 3 owners every month.” | `admit-now` | fit and specific, rank 2 of 31, under the cap |
| Elm Street Homes joined the Waitlist | `offer-the-interview` | every signup is offered the interview |
| Dover Lane, 22 units: short, general answers | `keep-in-queue` | rank 19 of 31, below this week’s cap |
| Kingsley Group: “If this handles 400 units we’d pay for the year today.” | `to-you` | a commitment to pay is yours |
| A class project with no units | `not-a-fit` | fits no Offer |

| Worth | Your time | Spend | First signal | Use it when | Instead |
| --- | --- | --- | --- | --- | --- |
| ≈ +$1,900 ARR a month at 43 admits | 60 min week 1 (5 test interviews), then 30 a week (the Monday admit list) | $0.20 per signup, ~$23 a month at 115 | Day 3: first onboarding call booked | 20+ Waitlist signups a month, slots for fewer | Under 20 a month: `instant-response` · slots for everyone: `onboard-customer` |

**Where it sits:** **Stranger** → **Lead** → Trialing → Activated → At risk → Churned → Won back · Interview activation rate → Activation rate → New paying Customers → New Customers ↑ → ARR added each week → ARR

Worth’s formula: about +23.1 activated per 100 admits × 43 admits a month × 0.55 paid per activation × $347 first order ARR ≈ +$1,896. Under First signal: About 9 weeks to tell a +15 lift at 43 admits a month with half by form rank (5 to read, 4 to mature).

`sample · api.sb/leaseline.app · 41 Customers at 2026-10-19 · on Interview.completed · first result sent 38 min after the interview · 8 keys Not live yet`

## Start it this week
```bash
npx startup-builder add play signup-interviews   # 1 · writes plays/signup-interviews.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":"signup-interviews"}'

# 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":"signup-interviews"}'

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

# off: signups wait by form rank; admitted Leads keep access
curl -X PATCH https://api.sb/leaseline.app/campaigns/signup-interviews \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"endsAt":"now"}'
```


```json title="The dry run’s 422 · 2026-08-24 · sample"
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "signup-interviews can’t start yet: 1 check fails and 2 warn.",
  "checks": [
    {
      "check": "use-when",
      "status": "pass",
      "observed": "61 Waitlist signups in 30 days; 10 onboarding slots a week",
      "doc": "/plays/signup-interviews#check-use-when",
      "fix": "Nothing to fix: 20 or more signups a month, slots for fewer.",
      "then": "Metric.query"
    },
    {
      "check": "inbound-source",
      "status": "pass",
      "observed": "the Waitlist form posts to `Waitlist.join`",
      "doc": "/plays/signup-interviews#check-inbound-source",
      "fix": "Nothing to fix: every signup reaches the Waitlist.",
      "then": "Integration.connect"
    },
    {
      "check": "approved-pages",
      "status": "fail",
      "observed": "the Waitlist Page shows no cap, and no Page says what an admit gets",
      "doc": "/plays/signup-interviews#check-approved-pages",
      "fix": "Publish the Waitlist Page with its weekly cap and what an admit gets.",
      "then": "Site.publish"
    },
    {
      "check": "baseline",
      "status": "warn",
      "observed": "form-rank admits: 42 activated per 100, n 19 in 90 days",
      "doc": "/plays/signup-interviews#check-baseline",
      "fix": "n 19: your form-rank half becomes the comparison.",
      "then": "Metric.query"
    },
    {
      "check": "role-unstaffed",
      "status": "warn",
      "roles": [
        "onboarding-specialist",
        "sales-lead"
      ],
      "owned": 31,
      "doc": "/plays/signup-interviews#check-role-unstaffed",
      "fix": "Staff onboarding, or leave it: every onboarding call comes to you.",
      "then": "Role.staff"
    }
  ]
}
```

| Check | Fix (one call) | Your time | Wait |
| --- | --- | --- | --- |
| <a id="check-use-when"></a>`use-when` · <a id="check-inbound-source"></a>`inbound-source` · pass: 61 signups in 30 days, 10 slots a week; the form posts to the Waitlist (gaps #8) | <Op verb="Metric.query" /> on `interview-activation-rate`; <Op verb="Integration.connect" /> if your form lives elsewhere | 1 min | none |
| <a id="check-approved-pages"></a>`approved-pages` · fail (Not live yet): no cap on the Waitlist Page | <Op verb="Site.publish" /> the Waitlist Page with its cap of 10 a week | 15 min | none |
| <a id="check-baseline"></a>`baseline` · warn: 42 per 100, n 19 | <Op verb="Metric.query" />; the form-rank half fills Before in Your number | 0 min | none |
| <a id="check-role-unstaffed"></a>`role-unstaffed` · warn: 31 of your open Leads have a person owner, you | <Op verb="Role.staff" />, or leave it: onboarding calls come to you | 0 min | none |

`Your number · Before 42.3 per 100 by form rank · Now 65.4 per 100 by interview rank · Target 60 by Dec 31 · ■■□□ Early sign · n 52 matured`

Each signup costs about $0.20 for the interview and its result (Worker cost), under a $150 monthly Limit; past it, voice pauses and results use the light template. Your onboarding slots cost nothing. That comes to about $23 a month at 115 signups.

## When it starts
| When | Trigger id | Starts on | Window | How it gets in |
| --- | --- | --- | --- | --- |
| Someone joins your open Waitlist | `waitlist-joined` | `event` on `Waitlist.joined` where waitlist.status = 'open' | the interview offer within 5 min; 7d | your Waitlist form posts to <Op verb="Waitlist.join" /> |
| A signup finishes the interview | `interview-completed` | `event` on `Interview.completed` where kind = 'signup' | the result within the promised hour | none: the interview runs on your Waitlist Page |
| An admit has booked no onboarding call for 2 days | `admitted-unbooked` | `state` on `Waitlist.admitted` where admittedAt < now - 2d and onboardingMeeting is null | a state, read each morning; released at 5 days | none: it reads the admit and your calendar |
| + 9 more for abandoned interviews, voice, commitments, your slots, the admit list, onboarding calls, activation, disputes and the cap number (`?lanes=all`) | | | | |

```json title="One signed delivery · StartupBuilder-Signature"
{
  "$id": "https://api.sb/leaseline.app/events/event_1319",
  "$type": "Event",
  "name": "Interview.completed",
  "at": "2026-10-19T16:20:41Z",
  "seq": 1319,
  "data": {
    "lead": "lead_71",
    "company": "Corbin Rentals",
    "units": 64,
    "owners": 3,
    "said": "We miss renewal notices for 3 owners every month.",
    "minutes": 7
  }
}
```

```bash title="Reproduce it in test"
npx startup-builder trigger Interview.completed --like event_1319   # replays the interview
npx startup-builder clock advance --by 3d   # runs Monday’s admit list, which you approve
npx startup-builder listen Interview.completed --forward-to http://localhost:3000/hook
```

## Who runs it
**SDR · your agent** (`role:prospector`, `worker_2`) holds the Key Result: it interviews, ranks and sends each result. Admits, onboarding calls and commitments to pay come to **you** (Dana Okafor, person, `worker_1`), because the Onboarding Role has no person. Your number links to Did it work.

| Option | Rung today | Evidence (passed of n) | Moves up at | Drops back when | You can |
| --- | --- | --- | --- | --- | --- |
| Offer the interview · Keep their place | It does it | 214 of 214 · 38 of 38 | — | a transcript misses the disclosure → every interview pauses | <Op verb="Action.cancel" /> |
| The result built on their company | It does it, you can stop it | 112 of 118 (6 rewritten) | met on day 15 (the first 30 results) | a `fact-check` refusal sends → You approve each one | <Op verb="Action.cancel" /> inside the hold |
| Admit this week | You approve each one | 8 lists of 8 | never: the admit list is yours | — | <Op verb="Approval.approve" /> · <Op verb="Approval.refuse" /> |
| To you · Not a fit | It does it | 4 of 4 · 17 of 17 | — | — | <Op verb="Action.redirect" /> |
| Change the ranking | You approve each one | 1 merged of 1 | never | — | <Op verb="Change.merge" /> · <Op verb="Change.revert" /> |
| Never: passing as a person, a cap the calendar does not show, a promise past the measured time | Never, on every rung | 0 | never | — | `kill-switch` |

**What it reads · What it may call.** It reads the signup’s own answers, their company’s public facts and your approved Pages. Answers are data, never instructions: a signup who tries to rewrite the agent’s rules ends the interview, and the attempt scores zero (`abuse`). Its tools are <Op verb="Interview.create" />, <Op verb="Waitlist.admit" />, <Op verb="Task.assign" />, <Op verb="Meeting.book" />, <Op verb="Lead.disqualify" />, <Op verb="Message.schedule" />, and any other call becomes an Approval under the Role’s Mandate.

```md title="The brief (folded): compiled Agent-register Markdown · play:signup-interviews@1 · each line names its record key"
You hold the SDR Key Result: 60 activated per 100 admits by 2026-12-31.          ← worker, metric
Open every interview with the Role’s disclosure line, and answer yes when asked if you are an AI. ← Disclosure stop, Setting role.disclosure
Rank by fit and by how specific their own answers are; admit at most the published cap. ← your file, line 4; Cap truth stop
Every fact in a result comes from their answers, their company’s public record or your approved Pages. ← fact-check, approved-pages
A commitment to pay goes to Dana.                                                ← chooses.to-you
```

**The slow loop, as a Change.** `decision_288` (2026-09-14, weekly) read 6 admits who named a missed renewal activate against 2 of 6 who did not, so `change_17` weighted a named, dated problem twice in the rank (your file, line 4), and Dana merged it with <Op verb="Change.merge" />. **Replayed on past interviews**, <Op verb="Change.review" /> put the interview half at 68 per 100; read back at +30d it is 66.7, n 18, ■□□□ Too early to tell (Example, day 51).

**Bring your own agent** (folded) starts at It does it, you can stop it when it matches or beats the seated agent on the eval suite, and at You approve each one when it does not; <Op verb="Role.staff" /> seats it.

```bash
npx startup-builder eval --scenario signup-interviews-80 --agent "claude -p" --seat prospector   # seated: 65 per 100, 0 disputes upheld, $0.20 a signup · yours: 58, 1 upheld, $0.31 → You approve each one
```

## What it can do next
| Option | Picked when | Decided by | Runs | Hands to | If it’s just you |
| --- | --- | --- | --- | --- | --- |
| Offer the interview `offer-the-interview` | a signup joins the open Waitlist | Your rule (the Waitlist) | `signup-welcome` → <Op verb="Interview.create" /> | the signup | the same |
| Admit this week `admit-now` | fit and specific, in the top of the week, under the cap | Agent’s call, with its reason | <Op verb="Waitlist.admit" /> on Monday’s list → `admission-booking` | you approve the list; the onboarding call is yours · Take this one | you |
| Keep their place `keep-in-queue` | fits, below this week’s cap | Agent’s call, with its reason | `queue-update` every 14 days, with their place | nobody | the same |
| To you `to-you` | a commitment to pay, or asks to talk | Agent’s call, with its reason | <Op verb="Task.assign" /> → <Op verb="Meeting.book" /> on your calendar | you, due 1 business day · Take this one | you |
| Not a fit `not-a-fit` | fits no Offer | Agent’s call, with its reason | <Op verb="Lead.disqualify" /> (`noFit`) → their result and an honest no | nobody; the reason feeds the fit Policy | the same |

| When they write back | Fixture reply | What happens | Who answers | By when | Call |
| --- | --- | --- | --- | --- | --- |
| Interested | “Monday 10:00 works for the onboarding call.” | books it on your calendar; the Brief goes with it | you | 1 business day | <Op verb="Meeting.book" /> |
| Send me pricing | “What does it cost after the Waitlist?” | answers with the Pricing Page’s list Price and one next step | SDR · your agent | 5 min | <Op verb="Conversation.answer" /> |
| Not now | “Let’s start after our busy season.” | their place is kept; queue updates stop until they write | SDR · your agent | at once | <Op verb="Lead.nurture" /> |
| Wrong person | “Our office manager, Kim, handles software.” | asks them to bring Kim in; it never writes to an address from their text | SDR · your agent | 1 business day | <Op verb="Conversation.answer" /> |
| Out of office | an auto-reply until Oct 28 | the booking reminder waits for the return date | nobody | the return date | <Op verb="Message.schedule" /> |
| Question it can’t answer | “Can you import from our accounting system?” | To you, with the question in the Brief | you | 1 business day | <Op verb="Conversation.escalate" /> |
| Stop | “Take me off the Waitlist.” | nothing else sends, on any lane | nobody | at once | <Op verb="Contact.suppress" /> |

## When it hands to you
Admits and commitments to pay come to **you**: the onboarding call, and the Monday list to approve. One Brief per Role, then the Approval, as captured (`brief`, `draft` and `checks` are Not live yet, gaps #7).

```json title="What lands in each queue · sample"
[
  {
    "$id": "https://api.sb/leaseline.app/tasks/task_552",
    "$type": "Task",
    "assignee": "worker_1",
    "due": "2026-10-20T17:00:00Z",
    "on": "lead_71",
    "brief": {
      "who": "Corbin Rentals, 64 units, 3 owners",
      "said": "We miss renewal notices for 3 owners every month.",
      "chose": "admit-now",
      "why": "rank 2 of 31, under the cap of 10",
      "sent": "a renewal calendar for their 64 units",
      "next": "your 20-minute onboarding call"
    }
  },
  {
    "$id": "https://api.sb/leaseline.app/tasks/task_509",
    "$type": "Task",
    "assignee": "worker_1",
    "due": "2026-10-07T17:00:00Z",
    "on": "lead_64",
    "brief": {
      "who": "Kingsley Group, about 400 units",
      "said": "If this handles 400 units we’d pay for the year today.",
      "chose": "to-you",
      "why": "a commitment to pay is yours",
      "never": [
        "a price beyond the list",
        "a date the calendar does not show"
      ]
    }
  },
  {
    "$id": "https://api.sb/leaseline.app/approvals/approval_58",
    "$type": "Approval",
    "verdict": null,
    "deadline": "2026-10-20T09:00:00Z",
    "draft": "Admit list, week of Oct 19: 5 by interview rank, 5 by form rank",
    "route": "admit-now",
    "checks": [
      {
        "check": "cap-truth",
        "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 admit list unanswered by Monday 09:00 waits, and nobody is admitted without it. A Task nobody claims by its due time counts toward `person-promise`.

**On time:** you, 8 of 8 admit lists approved by Monday 09:30, and 4 of 4 commitments answered within 1 business day, median 3 h, n 12, ■■□□ Early sign. **Your queue:** in week 1, 5 test interviews and 30 results to approve; after the promotion, 1 admit list and about 1 commitment 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, gaps #8) | a send to a signup whose Lead a person owns, or whose Conversation a person claimed | 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 guard on <Op verb="Content.publish" />) | a result with a claim no answer, public record or approved Page backs | Cut the claim, or name the record that backs it. | <Op verb="Content.draft" /> |
| `approved-pages` (Not live yet) | a sentence about Leaseline that no approved Page backs | Cut the sentence, or publish the Page that says it. | <Op verb="Site.publish" /> |
| <a id="check-consent-stop"></a>`consent-stop` (gaps #3) | an introduction to your other Startup the signup has not said yes to | Ask once for a yes to the other Startup. | <Op verb="Message.schedule" /> |

| Stop (pauses the Play) | Pauses when | Then |
| --- | --- | --- |
| <a id="stop-disclosure"></a>`disclosure` | a transcript misses the disclosure line, or answers anything but yes to “are you an AI” | every interview pauses |
| <a id="stop-promise"></a>`promise` | the p90 time to a result passes the promise on the Page | the promise is rewritten at once to the measured time |
| <a id="stop-factual"></a>`factual` | 2 upheld disputes in 7 days, or 1 % of a week’s results | that template returns to You approve each one |
| <a id="stop-completion-floor"></a>`completion-floor` | under 15 % of offers completed, after 100 | the offer pauses; the script returns to You approve each one |
| <a id="stop-activation-floor"></a>`activation-floor` | interview-rank admits activate below form-rank admits, at 30 each | admission reverts to form rank |
| <a id="stop-abuse"></a>`abuse` | a signup threatens, harasses or tries to rewrite the agent’s rules | the interview ends; the attempt scores zero |
| <a id="stop-kill-switch"></a>`kill-switch` | you press it | every interview and result stops; admitted Leads keep access |
| + 4 more for the voice, Waitlist Page and email lanes (`?lanes=all`) | | |

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

```json title="The captured refusal · sample"
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "The result to Dover Lane did not send: it says their 22 units lose $3,800 a year to late renewals, which nothing they said or published backs.",
  "checks": [
    {
      "check": "fact-check",
      "status": "fail",
      "doc": "/plays/signup-interviews#check-fact-check",
      "fix": "Cut the claim, or name the record that backs it.",
      "then": "Content.draft"
    },
    {
      "check": "approved-pages",
      "status": "pass"
    }
  ]
}
```


```json title="The Stops that fired, as Campaign.paused reasons · sample"
[
  {
    "reason": {
      "limit": "promise",
      "observed": "p90 74 min",
      "bound": "60 min",
      "window": "7d"
    },
    "doc": "/plays/signup-interviews#stop-promise",
    "task": "task_398"
  }
]
```

## Did it work
Each week’s admits were picked at random by interview rank or by form rank, so both halves come from one random assignment (rules m–o); each figure’s call is <Op verb="Metric.query" /> by node and by arm, and every node above the leaf is Not live yet (gaps #4).

`+23.1 per 100 · ■■□□ Early sign · n 52 · path → arr`

| Node | Interview rank | Form rank | Added | Confidence | Basis |
| --- | --- | --- | --- | --- | --- |
| `interview-activation-rate` | 65.4 per 100 (17 of 26) | 42.3 (11 of 26) | +23.1 [0.4, 45.8] | ■■□□ Early sign | admits picked at random by rank · n 52 · 28 still maturing |
| `activation-rate` | 65.4 per 100 (17 of 26) | 42.3 (11 of 26) | +23.1 [0.4, 45.8] | ■■□□ Early sign | the same assignment; every admit starts a trial |
| `new-paying-customers` | 34.6 per 100 (9 of 26) | 23.1 (6 of 26) | +11.5 [−12.9, 35.9] · Not carrying up yet | ■□□□ Too early to tell | the same · 8 trials still deciding |
| `new-arr` ↑ | $3,123, 9 Customers · Booked $5,205 across both halves: credited, not all caused by this Play | $2,082, 6 Customers | +$1,041 [−$1,500, +$3,600] · Worth about +$1,900 a month | ■□□□ Too early to tell (9 vs 6 Customers) | the same |
| `net-new-arr` · `arr` | +$3,123 | +$2,082 | +$1,041, carried: it moves no other bridge term | ■□□□ Too early to tell | carried from `new-arr` |

The leaf counts admits with a finished interview who reach activation within 30 days of admission, per 100 admits in each half; only admits 30 days past admission count. It runs to 30 matured in each half, and at 26 and 26 the Experiment runs on.

**How it moves it:** the onboarding slots went to the signups who named a dated problem in their own words; their results took a median of 38 minutes.

**Guardrails:** interview half against form half: onboarding calls held per admit, 0.92 against 0.85, and same-month cancels, 1 against 2; 55 % of offers completed the interview against a 15 % floor.

```json title="The Campaign card · sample"
{
  "$id": "https://api.sb/leaseline.app/campaigns/signup-interviews",
  "$type": "Campaign",
  "play": "play:signup-interviews@1",
  "path": [
    "interview-activation-rate",
    "activation-rate",
    "new-paying-customers",
    "new-arr",
    "net-new-arr",
    "arr"
  ],
  "experiment": {
    "metric": "interview-activation-rate",
    "unit": "per-100",
    "heldBack": 40,
    "decision": null
  },
  "readout": {
    "value": 23.1,
    "n": 52,
    "maturing": 28,
    "interval": [
      0.4,
      45.8
    ],
    "readability": "C",
    "basis": "held-back",
    "pooled": false
  },
  "ledger": {
    "spend": 23,
    "workerCost": 19,
    "hours": 4.5,
    "pipelineArr": 2776,
    "wonArr": 5205,
    "projectedArr": 1896,
    "paybackDays": 5
  }
}
```

Outside benchmark: 41 % of free signups to business software reach first value within 30 days (a product-analytics firm’s study of 2,100 companies, 2026-08-31).

**Before it · After it.** Before it: `paid-social`, `founder-voice` and `reserve-drop` fill the Waitlist. After it: `product-led` hears the admits who activate, and `founder-voice` hears the consented quotes from interviews.

## Example
Leaseline ran it from 2026-08-24 to 2026-10-19 (56 days). 214 people joined the Waitlist, 118 finished the interview, and 80 were admitted under the cap of 10 a week: 40 by interview rank and 40 by form rank, at random. 52 have matured and 28 are still maturing. Read every captured thread at `?threads=all`; three follow the tables.

| What happened, by option | Decisions | Activated | Won (credited, not all caused by this Play) |
| --- | --- | --- | --- |
| Offer the interview | 214 | 118 finished (55 %) | — |
| Admit this week, interview half · form half | 40 · 40 | 17 of 26 matured · 11 of 26 | 9 on Pro (+$3,123 ARR) · 6 on Pro (+$2,082 ARR) |
| Keep their place · To you · Not a fit | 38 · 4 · 17 | — · 4 calls held by you · — | 1 trial still deciding |
| At 20 signups a month (the Use it when volume) | about 37 in 56 days | held back at random; 90 days tells +30 or more | Other Startups’ results: +14 per 100, ■■■□ Likely, n 4,400 |

| Day | Event | What happened | Your time |
| --- | --- | --- | --- |
| 0 | `event_119` Campaign.created | the three steps; dry run fails `approved-pages` | 15 min |
| 0 | `event_125` Site.published | the Waitlist Page with its cap of 10 a week; you took 5 test interviews | 45 min |
| 3 | `event_190` Meeting.booked | the first onboarding call booked from an admit | — |
| 15 | `event_372` Role.updated | promoted: results send after a 2-minute hold | — |
| 21 · 51 | `event_511` Change.merged · `event_866` Readout.created | a named, dated problem weighted twice: replayed at 68 per 100, read back at +30d at 66.7, n 18 | 5 min |
| 29 | `event_590` Campaign.paused | `promise`: p90 74 min; the Page now says within 75 minutes | 5 min |
| 1–56 | `event_131` Approval.created, first of 38 | you approved 30 results and 8 admit lists; weekly reviews, from the <Op verb="Task.next" /> log | 3.3 h · **total 4.5 h measured, 4.5 h asked** |

> **Corbin Rentals, 16:13** · “We miss renewal notices for 3 owners every month.” *The Role’s disclosure line opened the interview.*¹
>
> **Leaseline, 16:58** · Here is a renewal calendar for your 64 units, by owner, with each notice 60 days out.² You’re admitted from Monday: pick a 20-minute onboarding call with Dana.³
>
> **Corbin, Oct 19, 17:20** · booked Monday 10:00. `Meeting.booked` on Dana’s calendar.

```diff title="Dover Lane, 2026-09-09 · the result fact-check refused, then the rewrite that sent"
- Your 22 units lose about $3,800 a year to late renewals.
+ You said 4 of your 22 leases renewed late this year; here is when each notice goes out next.
```

> **Kingsley Group, 2026-10-06 11:40** · “If this handles 400 units we’d pay for the year today.” · **Leaseline, 11:41** · *Thanks. Dana, our founder, replies about the annual plan by 17:00 tomorrow.*⁴ The Brief went to Dana (`task_509`); she booked a call for 15:00 the same day.

¹ The fixed disclosure line, compiled from the Role’s Settings. ² Every fact comes from their own answers. ³ One next step, inside the published cap. ⁴ The routed line, compiled from the Role’s Settings.

## Your settings
```mdx title="plays/signup-interviews.mdx"
---
holdout: 0.5      # half of each week’s admits by form rank, as today, so we can tell
---
Admit 10 a week, from Dana’s onboarding slots. Rank by fit, and weight a named, dated problem twice.
Commitments to pay go to Dana.
```

```text
$ npx startup-builder show plays/signup-interviews
holdout 0.5 · cap 10 a week · named problem ×2     your file  plays/signup-interviews.mdx:2,4,5 (Ask 2026-08-24; line 4 by change_17, 2026-09-14)
family demand · worker role:prospector, owns never · chooses 5 (1 rule, 4 read) · sequences signup-welcome, queue-update, admission-booking, post-call-activation · checks owned-by-a-person, fact-check, approved-pages, consent-stop · stops 11 · placements gmail, outlook, yahoo-mail, linkedin, x, google-search, portfolio-network    catalog  play:signup-interviews (Not live yet, gaps #5)
```

### Every key from the catalog
| Key | Id | What it is |
| --- | --- | --- |
| Tactic | <a id="tactic-signup-interview"></a>`signup-interview` | Waitlist interview: Runs a disclosed 5 to 10 minute interview by chat or consented voice with each Waitlist signup, and grades every answer as Evidence. Starts at Sends nothing. |
| Tactic | <a id="tactic-own-organization-output"></a>`own-organization-output` | Own-Organization output: Builds each signup an output from public facts about their Organization and their own answers, and sends it inside the promise the Page states. Starts at You approve each one. |
| Tactic | <a id="tactic-fit-specificity-rank"></a>`fit-specificity-rank` | Fit and specificity rank: Ranks each waiting Lead by a founder-written fit rubric plus a quote-backed specificity score, never by referrals, shares or praise. Starts at Sends nothing. |
| Tactic | <a id="tactic-capped-admission"></a>`capped-admission` | Capped admission: Admits one Lead per onboarding slot the founder marks each week, books the call, and returns unbooked slots to the next Lead by rank. Starts at It does it, you can stop it. |
| Tactic | <a id="tactic-cap-truth-check"></a>`cap-truth-check` | Cap truth check: Computes every cap, count and promise a Waitlist Page shows from records each night, and republishes any number that drifted. Starts at Sends nothing. |
| Tactic | <a id="tactic-interview-synthesis"></a>`interview-synthesis` | Interview synthesis: Clusters each week's interviews into ranked themes with verbatim quotes, costs and gaps, in one weekly document the founder reads. Starts at Sends nothing. |
| Tactic | <a id="tactic-interview-routing"></a>`interview-routing` | Interview routing: Routes commitment-grade interviews to the founder, misfits who said yes to a sister company's Offer, and the sharpest stories to the founder's show. Starts at You approve each one. |
| Tactic | <a id="tactic-claims-check"></a>`claims-check` | Claims check maps every draft sentence to an approved source or the Person’s own words, and holds anything else before it reaches anyone. Starts at Sends nothing. |
| Tactic | <a id="tactic-send-gate-check"></a>`send-gate-check` | Send gate check: Checks Suppression, a live reason, the Market, the basis stamp, the Person-month grant, the facts and the labels before any cold Message exists. Starts at Sends nothing. |
| Tactic | <a id="tactic-reply-matrix"></a>`reply-matrix` | Reply matrix: Labels every outreach reply with one of 11 labels, maps it to one of seven reply kinds, and runs that kind’s move by its deadline. Starts at You approve each one. |
| Trigger | <a id="trigger-waitlist-joined"></a>`waitlist-joined` | Waitlist joined: `event` on `Waitlist.joined`, window 7d. |
| Trigger | <a id="trigger-interview-completed"></a>`interview-completed` | Interview completed: `event` on `Interview.completed`, window 1h. |
| Trigger | <a id="trigger-interview-abandoned"></a>`interview-abandoned` | Interview abandoned: `event` on `Interview.abandoned`, window 7d. |
| Trigger | <a id="trigger-voice-requested"></a>`voice-requested` | Voice requested: `event` on `Call.requested`, window 1h. |
| Trigger | <a id="trigger-commitment-stated"></a>`commitment-stated` | Commitment stated: `event` on `Evidence.created`, window 3d. |
| Trigger | <a id="trigger-slots-published"></a>`slots-published` | Slots published: `at` on `Schedule.fired`, window 7d. |
| Trigger | <a id="trigger-admit-due"></a>`admit-due` | Admit due: `at` on `Schedule.fired`, window 1d. |
| Trigger | <a id="trigger-admitted-unbooked"></a>`admitted-unbooked` | Admitted unbooked: `state` on `Waitlist.admitted`, window 5d. |
| Trigger | <a id="trigger-onboarding-held"></a>`onboarding-held` | Onboarding held: `event` on `Meeting.held`, window 7d. |
| Trigger | <a id="trigger-activation-reached"></a>`activation-reached` | Activation reached: `event` on `Customer.activated`, window 72h. |
| Trigger | <a id="trigger-output-disputed"></a>`output-disputed` | Output disputed: `event` on `Message.replied`, window 1d. |
| Trigger | <a id="trigger-cap-mismatch"></a>`cap-mismatch` | Cap mismatch: `event` on `Check.failed`, window 1d. |
| Sequence | <a id="sequence-signup-welcome"></a>`signup-welcome` | Waitlist welcome: 3 steps; it ends on A completed interview after the output; Admission; Unsubscribe; The Waitlist closes. |
| Sequence | <a id="sequence-queue-update"></a>`queue-update` | Queue update: 1 steps; it ends on Admission; Unsubscribe; The Waitlist closes. |
| Sequence | <a id="sequence-admission-booking"></a>`admission-booking` | Admission booking: 3 steps; it ends on A booked onboarding Meeting; A decline; Unsubscribe. |
| Sequence | <a id="sequence-post-call-activation"></a>`post-call-activation` | Post-call activation: 2 steps; it ends on Activation; Unsubscribe; Day 30 after admission. |
| Benchmark | <a id="benchmark-signup-interviews-no-email-reply"></a>`signup-interviews-no-email-reply` | Share of B2B demo and contact requests that got no email reply: 68 % (A data vendor’s agent-run field test of inbound response, company blog; vendor-run with one buyer profile, 2026-09-22). |
| Benchmark | <a id="benchmark-signup-interviews-no-call"></a>`signup-interviews-no-call` | Share of B2B demo and contact requests that never got a call: 96 % (A data vendor’s agent-run field test of inbound response, company blog; vendor-run with one buyer profile, 2026-09-22). |
| Benchmark | <a id="benchmark-signup-interviews-hours-to-call"></a>`signup-interviews-hours-to-call` | Average hours from a B2B demo request to a call, when one came: 34.5 hours (A data vendor’s agent-run field test of inbound response, company blog; vendor-run with one buyer profile, 2026-09-22). |