Skip to content

The metrics/ folder: one file and what it compiles to

What one metrics/ file holds, what each key compiles to, and the checks that read it.

One metrics/ file is the quarter’s Goal and Key Results, and each leaf Metric with its one parent. SalesBuilder compiles it, and show traces every key.

metrics/q4.mdx
---
goal: { objective: "Reach $25k ARR by year end", horizon: quarter }
keyResults:
  - { metric: net-new-arr, baseline: 0, target: 1800, deadline: 2026-12-31 }
  - { metric: opened-deals-and-trials, baseline: 2, target: 6, deadline: 2026-12-31, role: sales/prospector }
---
show
$ npx startup-builder show metrics/q4.mdx
goal        { objective: "Reach $25k ARR by year end", horizon: quarter }  metrics/q4.mdx:2
keyResults                                                                 metrics/q4.mdx:3
parent      new-leads                                                      metrics/positive-reply-rate.mdx:2
owner       SalesBuilder
leaseline.app
leaseline.app/
├── plays/
│   ├── cold-email.mdx
│   ├── warm-intros.mdx
│   ├── signup-interviews.mdx
│   ├── lead-reactivation.mdx
│   └── events-and-webinars.mdx
├── audiences/
│   ├── small-property-managers.mdx
│   ├── lapsed-leads.mdx
│   └── renewal-season.mdx
├── sequences/
│   └── cold-email-thread-founder.mdx
├── funnels/
│   └── signup.mdx
├── workflows/
│   └── outbound.mdx
├── agents/
│   ├── sales/prospector.mdx
│   └── marketing/content-lead.mdx
├── systems/
│   └── sequences.mdx
├── domains/
│   └── leaseline.app.mdx
├── offers/
│   ├── pro.mdx
│   └── team.mdx
├── content/
│   └── webinars/60-day-notices.mdx
├── metrics/   ← this folder
│   ├── q4.mdx
│   └── positive-reply-rate.mdx
└── startups.lock

The file

KeyOn the pageCompiles toChecked by
goalGoalthe quarter’s objective and horizon—
keyResultsKey Resultseach a node or leaf with baseline, target and deadline; one with a role lands in that seat’s numberS9
parentParentin a leaf’s own file: its one parent, so its chain reaches arrS1

Checks

CheckIt holdsWhat dev prints
S1The Metric’s parent chain reaches arr: the Result card’s path.metrics/q4.mdx:5 S1 keyResults[1].metric: demo-requests has no parent chain to arr. Set its parent: opened-deals-and-trials.
S9Each Key Result names a node or leaf of the ARR tree, and a seat’s Key Result sits in its band.agents/sales/prospector.mdx:4 S9 results: reply-count is not a node or leaf of the ARR tree. Did you mean positive-reply-rate?

Refusals

CodeFix, then the call that clears it
baselineRead the last 90 days first; thin history reads before-after, not proof. Then POST /{namespace}/metrics/query.
recomputeRecompute the Metric, then render the log again. Then POST /{namespace}/metrics/query.
scale-gateWait for the holdout readout to win, then raise it. Then POST /{namespace}/metrics/query.
step-gateWait for cost per trial to fall under the line, then sign. Then POST /{namespace}/metrics/query.
stripe-revenueQuery the revenue from live-mode Stripe, then compile the log. Then POST /{namespace}/metrics/query.
use-whenRun the Play Not yet when names, or wait until the volume is there. Then POST /{namespace}/metrics/query.

Calls

metrics/ compiledMode try
You, to your agent

Define the leaf Metric and read its trend.

curl -X POST "https://api.sb/leaseline.app/metrics/define?mode=try" \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"name":"Leaseline","query":"Example query","unit":"Example unit"}'

curl -X POST https://api.sb/leaseline.app/metrics/query \
  -H "Authorization: Bearer $STARTUP_BUILDER_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"metric":"positive-reply-rate","shape":"trend","window":"28d"}'
import { $ } from 'startup-builder'

await $.Metric.define({ name: 'Leaseline', query: 'Example query', unit: 'Example unit' }, { mode: 'try' })   // metrics/positive-reply-rate.mdx
return await $.Metric.query({ metric: 'positive-reply-rate', shape: 'trend', window: '28d' })   // parent new-leads, up to arr
npx startup-builder do Metric.define --json '{"name":"Leaseline","query":"Example query","unit":"Example unit"}' --try
npx startup-builder do Metric.query --json '{"metric":"positive-reply-rate","shape":"trend","window":"28d"}'
{
  "name": "do",
  "arguments": {
    "code": "await $.Metric.define({ name: 'Leaseline', query: 'Example query', unit: 'Example unit' }, { mode: 'try' })   // metrics/positive-reply-rate.mdx\nreturn await $.Metric.query({ metric: 'positive-reply-rate', shape: 'trend', window: '28d' })   // parent new-leads, up to arr",
    "mode": "try"
  }
}
Response200application/json
{
  "rows": {},
  "metric": {
    "$id": "https://api.sb/leaseline.app/metrics/metric_1",
    "$type": "Metric",
    "query": "Example query",
    "status": "draft"
  },
  "action": {
    "$id": "https://api.sb/leaseline.app/actions/action_1",
    "operation": "Metric.query",
    "status": "done"
  }
}
sample
CallWhat it does
POST /{namespace}/metrics/defineDefine compiles a Metric’s query against the Startup’s Events and Entries and lists every Event it reads. Emits Metric.defined.
POST /{namespace}/metrics/queryQuery reads Metrics or Events as a trend, funnel, retention curve, path or lifecycle, broken down by any property. Emits Metric.queried.
POST /{namespace}/metrics/{metric}/watchWatch alerts the owner of a Metric when it crosses a threshold, by a Task or a Message. Emits Metric.watched.

Compiled, not written: edit the records it reads (compile table; cap), 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.

Contents