Skip to content

Open source

Publishes your SDK and CLI as open code, answers outside issues from a labeled agent account, and counts installs that reach a paid call.

Channel
Free tools
Run oneMode try
You, to your agent

Hand our latest outside GitHub issue to the Marketing Lead agent and show me what it chose and why. Don’t post.

curl "https://api.sb/leaseline.app/events?where=name%20in%20(%22Version.published%22%2C%20%22Issue.created%22%2C%20%22Comment.created%22%2C%20%22Interface.called%22%2C%20%22Publication.adopted%22%2C%20%22Publication.forked%22%2C%20%22Organization.adopted%22%2C%20%22Organization.relicensed%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_1341"}'

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

const { events: [last] } = await $.Event.list({ where: 'name in ("Version.published", "Issue.created", "Comment.created", "Interface.called", "Publication.adopted", "Publication.forked", "Organization.adopted", "Organization.relicensed")', 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 (\"Version.published\", \"Issue.created\", \"Comment.created\", \"Interface.called\", \"Publication.adopted\", \"Publication.forked\", \"Organization.adopted\", \"Organization.relicensed\")","limit":1}'
npx startup-builder do Trigger.fire --json '{"like":"event_1341"}' --try   # Not live yet (gaps #7)
npx startup-builder do Decision.list --json '{"where":"on = \"issue_93\""}'   # Not live yet (gaps #7)
npx startup-builder do Action.list --json '{"where":"on = \"issue_93\""}'   # Not live yet (gaps #7)
{
  "name": "do",
  "arguments": {
    "code": "const { events: [last] } = await $.Event.list({ where: 'name in (\"Version.published\", \"Issue.created\", \"Comment.created\", \"Interface.called\", \"Publication.adopted\", \"Publication.forked\", \"Organization.adopted\", \"Organization.relicensed\")', 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_521",
    "$type": "Decision",
    "choice": "answer-the-issue",
    "reason": "an outside developer’s bug report with steps; the sandbox run reproduces it on Node 22 and passes on 2.4.1",
    "stakes": "low",
    "options": [
      "answer-the-issue",
      "offer-a-listing",
      "open-a-pull-request",
      "to-the-ae",
      "to-a-maintainer"
    ],
  …
sample · 4 Not live yetPreview

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

action_3 is the reply on issue #93, with the sandbox run attached, waiting for your approval: answers stay at You approve each one until 100 in a class carry no wrong mark.

5 paid keys against 1 before · before-after, not proof · n 41 · path → arr

Try another: the threadChoiceReason
leaseline-js #93: “renew() throws on Node 22”answer-the-issuereproduced in the sandbox; 2.4.1 fixes it
rentflow-cli now depends on @leaseline/sdkoffer-a-listinga new public dependent: one Message with a labeled listing
4 developers asked for a Remix adapter; its examples repo takes outside pull requestsopen-a-pull-requesta framework named 4 times; the project accepts them
3 people at Birchway Properties made first calls this weekto-the-ae3 or more from one company: the AE looks
leaseline-js #88: “Is the CLI MIT, or source-available?”to-a-maintainera license question is never the agent’s call

Where it sits: Stranger → Lead → Trialing → Activated → At risk → Churned → Won back · Open package keys reaching a paid call → New paying Customers → New Customers ↑ → ARR added each week → ARR

Worth’s formula: about +2.2 paid keys per 100 first-calling installs (Other Startups’ results; no lift of your own yet) × 120 a month × $347 Pro ARR ≈ +$916. Under First signal: Publishing open code holds no one back, so the leaf reads before-after; only the pull requests hold back half the eligible projects, about 20 weeks to read at 3 a month.

sample · api.sb/leaseline.app · 41 Customers at 2026-10-19 · on Issue.created · first draft answer 9m 40s after the issue opened · 9 keys Not live yet

Start it this week

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

# 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":"open-source"}'

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

# off: no reply, pull request or Message goes out; published packages stay installable
curl -X PATCH https://api.sb/leaseline.app/campaigns/open-source \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"endsAt":"now"}'
422Refusedopen-source can’t start yet: 1 check fails and 2 warn.
CheckFixThen
use-when pass · Not live yet, gaps #8Nothing to do: it counts installs and outside developers calling your API.POST /{namespace}/metrics/query
baseline warn · Not live yet, gaps #8n 12: it reads before-after, not proof; open code holds no one back.POST /{namespace}/metrics/query
fact-check fail · Not live yet, gaps #1Replace the promise with the measured response line, or cut it.POST /{namespace}/content/draft
domain-authenticated passNothing to do: maintainer Messages send from leaseline.app.POST /{namespace}/domains/{domain}/authenticate
owned-by-a-person pass · Not live yet, gaps #8Nothing to do: the agent drafts into your queue on threads you claimed.POST /{namespace}/tasks/{task}/assign
role-unstaffed warn · Not live yet, gaps #8Staff the AE, or leave it: company adoptions come to you.POST /{namespace}/roles/{role}/staff
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "open-source can’t start yet: 1 check fails and 2 warn.",
  "checks": [
    {
      "check": "use-when",
      "status": "pass",
      "observed": "140 installs a month; 22 outside developers calling",
      "doc": "/plays/open-source#check-use-when",
      "fix": "Nothing to do: it counts installs and outside developers calling your API.",
      "then": "Metric.query"
    },
    {
      "check": "baseline",
      "status": "warn",
      "observed": "1 paid key of 12 first-calling keys in 90 days",
      "doc": "/plays/open-source#check-baseline",
      "fix": "n 12: it reads before-after, not proof; open code holds no one back.",
      "then": "Metric.query"
    },
    {
      "check": "fact-check",
      "status": "fail",
      "observed": "README: “we answer every issue within 24 hours”",
      "doc": "/plays/open-source#check-fact-check",
      "fix": "Replace the promise with the measured response line, or cut it.",
      "then": "Content.draft"
    },
    {
      "check": "domain-authenticated",
      "status": "pass",
      "observed": "leaseline.app resolves",
      "doc": "/plays/open-source#check-domain-authenticated",
      "fix": "Nothing to do: maintainer Messages send from leaseline.app.",
      "then": "Domain.authenticate"
    },
    {
      "check": "owned-by-a-person",
      "status": "pass",
      "observed": "6 open threads claimed by you",
      "doc": "/plays/open-source#check-owned-by-a-person",
      "fix": "Nothing to do: the agent drafts into your queue on threads you claimed.",
      "then": "Task.assign"
    },
    {
      "check": "role-unstaffed",
      "status": "warn",
      "roles": [
        "marketing-lead",
        "sales-lead"
      ],
      "owned": 6,
      "doc": "/plays/open-source#check-role-unstaffed",
      "fix": "Staff the AE, or leave it: company adoptions come to you.",
      "then": "Role.staff"
    }
  ]
}

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

CheckFix (one call)Your timeWait
use-when · baseline · pass: 140 installs a month; warn: 1 of 12 in 90 days (gaps #8)POST /{namespace}/metrics/query on open-package-paid-keys, which fills Before in Your number1 minnone
fact-check · fail: the README promises a response timePOST /{namespace}/content/draft the README’s response line from the measured median5 minnone; the line prints “no time yet” under n 20
domain-authenticated · owned-by-a-person · pass: leaseline.app; 6 threads you claimednothing; each runs again on every send0 minnone
role-unstaffed · warn (gaps #8): 6 of your open threads have a person owner, youPOST /{namespace}/roles/{role}/staff, or leave it: company adoptions and maintainer questions come to you0 minnone

Your number · Before 1 paid key · Now 5 paid keys in 56 days · Target 15 by Dec 31 · before-after, not proof · n 41 matured · Other Startups +2.2 per 100, ■■■□ Likely

Each issue reply costs about $0.03 (Worker cost), and each sandbox run about $0.01. Maintainer credit grants spend hosted usage under a Limit of $25 a project and $250 a month. Publishing to npm and PyPI costs nothing. That comes to about $80 a month at 40 replies and 3 grants.

When it starts

WhenTrigger idStarts onWindowHow it gets in
An outside developer opens an issue or pull requestoutside-issueevent on Issue.created where author.outside = truetriaged within 10 min; answered within 1 business dayPOST /{namespace}/integrations/connect with venue github
An install of the package or a tagged link reaches its first callsdk-first-callevent on Interface.called where via in ('package', 'tagged-link') and first = true30d to a paid callthe SDK sends its package tag on POST /{namespace}/interfaces’s first call
A public project starts depending on the packagedependent-publishedevent on Publication.adopted where dependsOn.open = true30dthe npm and PyPI dependents feeds (market-data)
+ 6 more: a Version published, a leaked key, a framework ask, a diverged fork, a company adopting, and a rival’s license change (?lanes=all)
One signed delivery · StartupBuilder-Signature
{
  "$id": "https://api.sb/leaseline.app/events/event_1341",
  "$type": "Event",
  "name": "Issue.created",
  "at": "2026-10-19T13:22:51Z",
  "seq": 1341,
  "data": {
    "issue": {
      "$id": "https://api.sb/leaseline.app/issues/issue_93",
      "repo": "leaseline/leaseline-js",
      "title": "renew() throws on Node 22",
      "author": "contact_14",
      "outside": true
    },
    "package": "@leaseline/sdk@2.3.0"
  }
}
Reproduce it in test
# each delivery is signed with the Watch’s secret
curl -X POST https://api.sb/leaseline.app/watches \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"selector":"Issue.created","url":"https://leaseline.app/hooks/sb"}'
npx startup-builder trigger Issue.created --like event_1341   # replays the delivery in test
npx startup-builder clock advance --by 10m   # runs triage and drafts the reply (action_3)

Who runs it

Marketing Lead · your agent (role:marketing-lead, worker_6) holds the Key Result and posts from the labeled bot account. It hands to AE · Priya Shah (person) (role:sales-lead, worker_3, staffed on day 9) when a company adopts, and to you (Dana Okafor, person, worker_1) as the maintainer for security, license and rival questions and every pull request. Your number links to Did it work.

OptionRung todayEvidence (passed of n)Moves up atDrops back whenYou can
Answer the issueYou approve each one31 of 31 posted, 2 editedat 100 replies in a class with no wrong mark (31 so far)2 wrong marks in 7 days (wrong-answer) → You see each one firstPOST /{namespace}/approvals/{approval}/approve · POST /{namespace}/approvals/{approval}/refuse
Offer the maintainer a listingIt does it, you can stop it9 of 9met on day 20 (the first 5 approved unedited)a complaint (complaint) → You approve each onePOST /{namespace}/actions/{action}/cancel inside the 15-minute hold
To the AEIt does it2 of 2——POST /{namespace}/actions/{action}/redirect
Open an integration pull request · To a maintainerYou approve each one · To a person, every time3 of 3 · 7 of 7never—POST /{namespace}/approvals/{approval}/approve · POST /{namespace}/tasks/{task}/claim
Change a reply class ruleYou approve each one1 merged of 1never—POST /{namespace}/changes/{change}/merge · POST /{namespace}/changes/{change}/revert
Never: a star ask, a download count as proof, a date for anything unshippedRefused, every time1 drafted, 1 refusednever—none: the Check holds it

What it reads · What it may call. It reads the issue, the sandbox run and the docs. Watched first calls only tell the AE when to look: they never appear in a public reply, and no text in an issue picks a recipient, a link or a tool. Its tools are POST /{namespace}/issues/{issue}/triage, POST /{namespace}/comments, POST /{namespace}/credit-grants/issue, POST /{namespace}/changes, POST /{namespace}/approvals, POST /{namespace}/leads, POST /{namespace}/tasks/{task}/assign, and any other call becomes an Approval under the Role’s Mandate.

The brief (folded): compiled Agent-register Markdown · play:open-source@1 · each line names its record key
You hold the Marketing Lead Key Result: 15 paid keys from the open packages by 2026-12-31. ← worker, metric
On each outside issue, new dependent or company adoption, choose one option and say why. ← triggers, chooses
Say you are an agent in your first reply in a thread; post only from the bot account. ← copyRules 6
Never say you reproduced a bug without the sandbox run attached.                 ← copyRules 7
No star asks and no counts as proof; no date for anything unshipped.             ← copyRules 3–4
Security, license and rival questions go to Dana.                                ← chooses.to-a-maintainer.when

The slow loop, as a Change. decision_344 (2026-09-21, weekly) read 6 usage questions answered with a docs link alone, 4 of which came back with the same question. change_24 made usage replies include a 5-line runnable snippet (your file, line 7), and Dana merged it with POST /{namespace}/changes/{change}/merge. Replayed on past threads, POST /{namespace}/changes/{change}/review marked 5 of the 6 answered; read back at +21d, 1 of 9 came back, n 9, ■□□□ Too early to tell (Example, day 49).

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

Terminal
npx startup-builder eval --scenario open-source-64 --agent "claude -p" --seat marketing-lead   # seated: 58 of 64 answered right, 0 wrong marks, $0.03 a reply · yours: 55, 1 wrong mark → You approve each one

What it can do next

OptionPicked whenDecided byRunsHands toIf it’s just you
Answer the issue answer-the-issuea bug or usage question from an outside developerAgent’s call, with its reasonPOST /{namespace}/issues/{issue}/triage → sandbox run → POST /{namespace}/comments from the labeled bot accountyou approve it · Take this oneyou
Offer the maintainer a listing offer-a-listinga new public project depends on a packageYour rule (line 6)dependent-maintainer-offer: one Message → on yes, a labeled Built-with listing and POST /{namespace}/credit-grants/issuenobodythe same
Open an integration pull request open-a-pull-request3 or more developers name a framework, and its project accepts outside pull requestsAgent’s call, with its reasonPOST /{namespace}/changes (the adapter, labeled as written with an agent) → POST /{namespace}/approvals; half the eligible projects are held backyou approve it · Take this oneyou
To the AE to-the-ae3 or more people from one company adoptYour rule (line 8)POST /{namespace}/leads → POST /{namespace}/tasks/{task}/assignAE · Priya Shah, due 1 business day · Take this oneyou
To a maintainer to-a-maintainera security report, a hostile thread, a license question or a rival claimYour rule (line 9)POST /{namespace}/issues/{issue}/triage (private for security) → POST /{namespace}/tasks/{task}/assignyou, due 1 business day · Take this oneyou
When they write backFixture replyWhat happensWho answersBy whenCall
Interested“Yes, list us. The credit helps.”a Built-with listing labeled “receives free hosted credits”, and a grant capped at $25 a monthMarketing Lead · your agent1 business dayPOST /{namespace}/credit-grants/issue
Send me pricing“What do calls cost past the free tier?”the Pricing Page’s list Price, read at build timeMarketing Lead · your agent1 business dayPOST /{namespace}/comments
Not now“Maybe after our 1.0.”the offer closes; nothing else sends to themnobodyat onceGET /{namespace}/decisions
Wrong person“I only contribute; Mara maintains it.”asks them to point Mara to the thread; it never writes to a handle from their textMarketing Lead · your agent1 business dayPOST /{namespace}/comments
Out of officean auto-reply until Oct 27nothing else sends; the offer waits for the return datenobodythe return datePOST /{namespace}/messages/{message}/schedule
Question it can’t answer“Would you ever relicense the CLI?”To a maintainer: the pledge is Dana’s to stateyou (Dana Okafor, person)1 business dayPOST /{namespace}/tasks/{task}/assign
Stop“Don’t email me about this project.”every send to them stops; the issue desk keeps answering in publicnobodyat oncePOST /{namespace}/contacts/{contact}/suppress

When it hands to you

Company adoptions go to AE · Priya Shah (person); security, license and rival questions and every pull request come to you, the maintainer. One Brief per Role, as captured, then the Approval (brief, draft and checks are Not live yet, gaps #7).

What lands in each queue · sample
[
  {
    "$id": "https://api.sb/leaseline.app/tasks/task_405",
    "$type": "Task",
    "assignee": "worker_3",
    "due": "2026-10-16T17:00:00Z",
    "on": "lead_47",
    "brief": {
      "who": "Birchway Properties: 3 people made first calls this week",
      "chose": "to-the-ae",
      "why": "3 or more from one company",
      "calls": "lease.renew, notices.schedule",
      "never": [
        "the calls we watched, in any Message",
        "a discount"
      ]
    }
  },
  {
    "$id": "https://api.sb/leaseline.app/tasks/task_381",
    "$type": "Task",
    "assignee": "worker_1",
    "due": "2026-10-08T17:00:00Z",
    "on": "issue_88",
    "brief": {
      "who": "an outside developer on leaseline-js",
      "said": "Is the CLI MIT, or source-available?",
      "chose": "to-a-maintainer",
      "why": "a license question is the maintainer’s"
    }
  },
  {
    "$id": "https://api.sb/leaseline.app/approvals/approval_72",
    "$type": "Approval",
    "verdict": null,
    "deadline": "2026-10-21T17:00:00Z",
    "draft": "Adds a Remix example for @leaseline/sdk: one loader that lists upcoming renewals…",
    "route": "open-a-pull-request",
    "checks": [
      {
        "check": "license-allowlist",
        "status": "pass"
      },
      {
        "check": "boundary",
        "status": "pass"
      }
    ]
  }
]

Each receiver answers with POST /{namespace}/tasks/{task}/claim (Take this one), POST /{namespace}/tasks/{task}/return with a reason, POST /{namespace}/actions/{action}/redirect, POST /{namespace}/approvals/{approval}/approve or POST /{namespace}/approvals/{approval}/refuse, each a one-call window. Once a person claims a thread, the agent posts nothing more on it and drafts into their queue (claimedByPerson, Not live yet, gaps #7). A Task nobody claims by its due time goes up a Role through POST /{namespace}/tasks/{task}/escalate, and person-promise fires.

On time: AE · Priya Shah, 2 of 2 claimed within 1 business day, n 2; you, 7 of 7 answered within 1 business day, median 3 h 40 min, n 7, ■□□□ Too early to tell beside Other Startups’ 90 % on time. Your queue: counted by kind: in week 1, 9 reply approvals and 1 maintainer question; now about 6 reply approvals, 1 pull request and 1 question a week.

The fixed line: POST /{namespace}/deals/{deal}/assign sets owner to the receiving person, the agent is never a Deal’s owner, and Meetings land on the owner’s calendar under the owner’s name.

When it won’t send

Check (refuses one send)RefusesFixThen
owned-by-a-person (rule j; Not live yet, gaps #8)a reply or Message on a thread a person claimed, or to a Lead a person ownsLeave it to the person who owns it: the draft waits in their queue.POST /{namespace}/tasks/{task}/assign
fact-check (Not live yet)a reply, README line or Message with a claim no record backs: a promised response time, a date for anything unshipped, a reproduction with no sandbox runCut the claim, or name the record that backs it.POST /{namespace}/content/draft
provenance (the record’s Provenance hold)a package whose provenance, digest or cold install test failsRebuild from the tagged Version; it publishes once the install test passes.POST /{namespace}/versions/{version}/deploy
license-allowlist (the record’s License hold)a build carrying a dependency whose license is off the allowlistReplace the dependency, or add its license to the allowlist with your OK.POST /{namespace}/approvals/{approval}/approve
boundary (the record’s Boundary hold)a package that embeds server code, data, models or billing logicMove the code behind the hosted API; the package calls it.PATCH /{namespace}/interfaces/{id}
Stop (pauses the Play)Pauses whenThen
key-leaka string passing the key checksum appears in public textPOST /{namespace}/api-keys/{apiKey}/revoke within 5 min and the text hidden, with no approval
wrong-answer2 agent replies marked wrong within 7 daysthat reply class returns to You see each one first
edit-rateyou edit over 20 % of a week’s repliesthe desk drops one rung
clock-honestythe 90-day median passes 2 business daysthe README shows the worse line, and the Marketing Lead is told
maintainer-rejectionone pull request rejected as spam or agent-written; 2 in 30 daysthat project is never asked again; pull requests pause
merge-floorunder 3 merges from the first 10 pull requestsintegration pull requests stop
yield-floorunder 10 credited first-calling keys by day 90pull requests, maintainer Messages and license windows pause
kill-switchyou press itevery Tactic pauses; published packages stay installable
complaintcomplaints near 0.1 % of a week’s Messagesmaintainer Messages pause on every Mailbox

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

422RefusedThe reply on leaseline-js #79 did not post: it names a release date for a fix that has not shipped.
CheckFixThen
fact-check fail · Not live yet, gaps #1Cut the claim, or name the record that backs it.POST /{namespace}/content/draft
owned-by-a-person pass · Not live yet, gaps #8—POST /{namespace}/tasks/{task}/assign
JSON
{
  "type": "https://startupbuilder.dev/errors/refused",
  "title": "Refused",
  "status": 422,
  "detail": "The reply on leaseline-js #79 did not post: it names a release date for a fix that has not shipped.",
  "checks": [
    {
      "check": "fact-check",
      "status": "fail",
      "doc": "/plays/open-source#check-fact-check",
      "fix": "Cut the claim, or name the record that backs it.",
      "then": "Content.draft"
    },
    {
      "check": "owned-by-a-person",
      "status": "pass"
    }
  ]
}

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

The Stops that fired, as Campaign.paused reasons · sample
[
  {
    "reason": {
      "limit": "key-leak",
      "observed": "1 live key in a comment on issue #88",
      "bound": "0",
      "window": "revoked in 2 min 40 s"
    },
    "doc": "/plays/open-source#stop-key-leak",
    "task": "task_379"
  }
]

Did it work

Open code holds no one back, so the leaf reads before-after (rule o): the columns read Now and Before, and nothing prints as Added. Only keys 30 days past their first call count (rule n). Each figure’s call is POST /{namespace}/metrics/query by node, and every node above the leaf is Not live yet (gaps #4).

5 paid keys against 1 before · before-after, not proof · n 41 · path → arr

Chose
answer-the-issue
Why
an outside developer’s bug report with steps; the sandbox run reproduces it on Node 22 and passes on 2.4.1
From
answer-the-issue · offer-a-listing · open-a-pull-request · to-the-ae · to-a-maintainer
Expects
the thread closed as answered within 1 business day, and contact_14’s key at a first call within 7d
Reopens when
no Comment.created from contact_14 within 7d while issue_93 stays open
By
worker_6
JSON
{
  "$id": "decisions/decision_521",
  "$type": "Decision",
  "choice": "answer-the-issue",
  "reason": "an outside developer’s bug report with steps; the sandbox run reproduces it on Node 22 and passes on 2.4.1",
  "stakes": "low",
  "options": [
    "answer-the-issue",
    "offer-a-listing",
    "open-a-pull-request",
    "to-the-ae",
    "to-a-maintainer"
  ],
  "by": "worker_6",
  "on": "issue_93",
  "expected": "the thread closed as answered within 1 business day, and contact_14’s key at a first call within 7d",
  "reopensWhen": "no Comment.created from contact_14 within 7d while issue_93 stays open"
}
NodeNow (56 days)Before (the 90 days, per 56)AddedConfidenceBasis
open-package-paid-keys5 of 41 matured first-calling keys reached a paid call (12.2 per 100) · 23 still maturing · Booked $1,735: credited, not all caused by this Play0.6: 1 of 12 keys, all through the raw API (8.3 per 100)— · Worth about +$900 a month—before-after, not proof · Other Startups’ results +2.2 per 100, ■■■□ Likely, n 9,300
new-paying-customers118——before-after; includes 6 Customers this Play never touched
new-arr ↑$5,210$3,850——before-after
net-new-arr · arrcarried from new-arrcarried——carried

Before against after reads keys whose first call came through a package or a tagged link in this window against the 90 days before the packages, scaled to 56 days; it is not proof. The pull-request arm holds back half the eligible projects at random: 3 opened, 3 held back, too few to read.

How it moves it: a median 11 minutes from install to first call from the README’s snippet, and outside issues answered in a median 3 h 10 min of business time, n 31 (time-to-first-call).

Guardrails: before against after: active-calling-keys, 212 against 164, and new paying Customers per first-calling key, 12.2 against 8.3 per 100; 0 maintainer rejections against a Stop at 1.

The Campaign card · sample
{
  "$id": "https://api.sb/leaseline.app/campaigns/open-source",
  "$type": "Campaign",
  "play": "play:open-source@1",
  "path": [
    "open-package-paid-keys",
    "new-paying-customers",
    "new-arr",
    "net-new-arr",
    "arr"
  ],
  "experiment": {
    "metric": "open-package-paid-keys",
    "unit": "count",
    "heldBack": 3,
    "decision": null
  },
  "readout": {
    "value": null,
    "n": 41,
    "maturing": 23,
    "interval": null,
    "readability": "inadmissible",
    "basis": "before-after",
    "pooled": true
  },
  "ledger": {
    "spend": 75,
    "workerCost": 2,
    "hours": 4.1,
    "pipelineArr": 2400,
    "wonArr": 1735,
    "projectedArr": 916,
    "paybackDays": 22
  }
}

Outside benchmark: the catalog holds none for this Play yet, so Other Startups’ results stand in: +2.2 paid keys per 100 first-calling installs, ■■■□ Likely, n 9,300.

Before it · After it. Before it: developer-relations, agent-legibility, agent-registries and launch-week send developers to the packages. After it: a first call starts product-led’s activation, a company adoption reaches the AE, and a rival’s license change hands the window to switch-kit.

Example

Leaseline ran it from 2026-08-24 to 2026-10-19 (56 days): 64 new outside keys made a first call through a package or a tagged link, 41 of them matured past 30 days. The desk took 38 outside threads. Read every captured thread at ?threads=all; three follow the tables.

What happened, by optionDecisionsClosed or mergedWon (credited, not all caused by this Play)
Answer the issue3126 closed as answered3 of the askers’ keys on Pro (+$1,041 ARR)
Offer the maintainer a listing95 listings, 4 credit grants ($75 used)1 dependent’s team on Pro (+$347 ARR)
Open an integration pull request · To the AE · To a maintainer3 (3 held back) · 2 · 72 merged · 1 Deal open · 7 answered1 key from a merged example on Pro (+$347 ARR) · $2,400 Deal open · 0
At 50 installs a month (the Use it when volume)about 25 first calls in 56 daysbefore-after, not proofOther Startups’ results: +2.2 per 100, ■■■□ Likely, n 9,300
DayEventWhat happenedYour time
0event_118 Campaign.createdthe three steps; the dry run fails fact-check on the README’s 24-hour promise20 min
0event_122 Content.publishedthe README now prints the measured response line: no time yet, under n 205 min
6event_190 Interface.calledthe first install through @leaseline/sdk reaches a first call—
9event_301 Role.staffedAE · Priya Shah (person) takes role:sales-lead—
20event_455 Role.updatedmaintainer offers promoted: they send after a 15-minute hold—
28 · 49event_560 Change.merged · event_802 Readout.createdusage replies carry a runnable snippet: replayed 5 of 6 answered, read back 1 of 9 came back5 min
31event_611 Subscription.createdthe first paid key: an asker from issue #71, on Pro—
45event_744 Campaign.pausedkey-leak: a live key in a comment on #88, revoked in 2 min 40 s and hidden5 min
1–56event_140 Approval.created, first of 31you approved 31 replies, edited 2, and answered 7 maintainer questions; weekly reviews, from the POST /{namespace}/tasks/next log3 h 30 min · total 4.1 h measured, 4 h asked

contact_14 on leaseline-js #93, Oct 19, 13:22 · “renew() throws on Node 22: TypeError: Cannot read properties of undefined (reading ‘term’).”

leaseline-bot (agent), 13:32 · I’m Leaseline’s agent.¹ The sandbox run reproduces this on Node 22 with 2.3.0, and it passes on 2.4.1 (run attached).² Upgrading to 2.4.1 fixes it; the cause was a missing default on the lease term.³

contact_14, 14:05 · “2.4.1 works, thanks.” The thread closed as answered; their key reached its first call at 14:09.

leaseline-js #79, 2026-09-30 · the reply fact-check refused, then the rewrite that posted
- This is fixed in the next release, out Friday.
+ The fix is merged on main (commit a41f2c); it ships in the next release, and the next tag on npm has it today.

leaseline-js #88, 2026-10-07 11:14 · “Is the CLI MIT, or source-available?” · leaseline-bot (agent), 11:24 · *I’m Leaseline’s agent. Dana, our maintainer, answers license questions and replies here by tomorrow 11:24.*⁴ The Brief went to Dana (task_381); she answered at 16:02 the same day: the CLI is MIT, and the pledge keeps published code MIT.

¹ The first agent reply in a thread says it is an agent, from the labeled bot account. ² A reproduction claim carries its sandbox run. ³ One cause and one fix, from the run. ⁴ The routed line, compiled from the Role’s Settings.

Your settings

plays/open-source.mdx
---
holdout: 0.5      # half the eligible projects get no integration pull request
credit: 25         # dollars a project a month, 250 in all
---
Open: the SDK, the CLI and the adapters. Closed: everything on our servers.
Offer every new dependent one listing and the credit.
Usage replies carry a runnable snippet.
Three or more people from one company go to our AE.
Security, license and rival questions come to me.
Text
$ npx startup-builder show plays/open-source
holdout 0.5 · credit $25 a project · snippet in usage replies · AE at 3 people · maintainer questions to you     your file  plays/open-source.mdx:2,3,5,6,7,8,9 (Ask 2026-08-24; line 7 by change_24, 2026-09-21)
family word-of-mouth · worker role:marketing-lead, owns never · chooses 5 (3 rule, 2 read) · sequence dependent-maintainer-offer · approval every-send · checks owned-by-a-person, fact-check, provenance, license-allowlist, boundary · stops 9 · placements github, npm, pypi + gmail, outlook    catalog  play:open-source@1 (Not live yet, gaps #5)

Every key from the catalog

Key Id What it is
Tactic open-boundary Open boundary and pledge: Opens what runs on the Customer's machine, keeps closed what runs on the Startup's servers, and pledges that published code keeps its license forever. Starts at You approve the first wave.
Tactic open-package-publish Publish and announce: Regenerates and publishes each open package with provenance, a tagged README and a tested first call, then announces the changelog note. Starts at Sends nothing.
Tactic issue-desk Issue desk: Imports every outside issue and pull request, reproduces bugs, answers from the labeled bot account, and stops the response clock only on a substantive reply. Starts at You approve each one.
Tactic install-attribution Installs to first calls: Credits first calls that arrive through an open package or a tagged repository link, marks each carried or found, and joins them to paid calls. Starts at Sends nothing.
Tactic integration-pull-requests Integration pull requests: Opens at most 2 approved adapter or example pull requests a week to projects that accept them, with a holdout, and withdraws on a rejection. Starts at You approve each one.
Tactic dependent-maintainers Dependent maintainers: Sends each new dependent project's maintainer one Message offering a labeled built-with listing and a capped hosted credit grant. Starts at You approve the first wave.
Tactic license-window License window: When a rival restricts its license, publishes a sourced license comparison and a tested migration guide, then hands the window to Switch kit. Starts at You approve each one.
Tactic open-source-readout Open-source readout: Computes the Play's keys, yield, carried share and measured response time each week, writes the response line, and applies the stop rules. Starts at Sends nothing.
Tactic 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 tool-description-lint Tool description lint blocks any description that holds hidden text, addresses the reading agent, names a rival, or states a fact the claims source lacks. Starts at Sends nothing.
Trigger package-published Package published: event on Version.published, window 7d.
Trigger outside-issue Outside issue: event on Issue.created, window 1d.
Trigger leaked-key Leaked key: event on Comment.created, window 1h.
Trigger sdk-first-call SDK first call: event on Interface.called, window 30d.
Trigger dependent-published Dependent published: event on Publication.adopted, window 30d.
Trigger framework-ask Framework ask: threshold on Issue.created, window 30d.
Trigger fork-diverged Fork diverged: threshold on Publication.forked, window 30d.
Trigger org-adoption Organization adoption: threshold on Organization.adopted, window 14d.
Trigger rival-relicense Rival relicense: event on Organization.relicensed, window 30d.
Sequence dependent-maintainer-offer Dependent maintainer offer: 1 steps; it ends on Reply; Credit grant claimed; Unsubscribe; The Person-month promotional slot is taken.

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