# R2 — Measuring our real cost per minute (task `F-02`)

**Status: NOT EXECUTED — and it cannot be simulated.** Blocked on `R1`, which is blocked on O2/O4.

**Estimate:** 3h · **Depends on:** `F-01` · **Done when:** a measured $/min and latency figures are in `docs/PROGRESS.md` and `docs/PRICING.md` §2.

---

## Why this task exists at all

Every unit-economics number in the plan rests on a **planning assumption of $0.10/min** that nobody has verified on our own account. `docs/PROGRESS.md` records the finding bluntly:

> *"Third-party pricing round-ups disagree on all-in $/min ($0.07–0.31 spread); first-party measurement task `F-02` exists to replace the planning number with our own measured figure."*

A 4× spread is not a rounding error. At $0.07/min a Starter client costs $21.50/month in infrastructure; at $0.31 the same client costs $82.50 and is **underwater before a minute of our labour**. The margin floor (infra ≤ 40% of fee), the tier caps, and the entire "is this business viable" question all hang on which end of that range is real.

**There is no substitute for making the calls.** A figure taken from documentation is the same class of evidence we already have and already distrust. This runbook is the instrument; it produces nothing until somebody dials.

---

## Step 1 — Build a throwaway test assistant

Not the restaurant template. A generic assistant with the platform's default settings and a two-line prompt. You are measuring **the platform's cost of carrying a call**, and a long prompt inflates the LLM component in a way that won't match production.

| Capture | Value |
|---|---|
| Assistant created | ☐ |
| LLM model selected | |
| Voice selected (standard tier — D7/`PRICING.md` §3) | |
| Prompt length, approx tokens | |
| Balance **before** any calls | $ |

> Record the starting balance. The single most reliable measurement here is balance-before minus balance-after, divided by minutes — it captures every fee the itemisation might not show you.

## Step 2 — Ten varied calls

Vary them deliberately. A restaurant's real minute mix is not ten identical two-minute calls, and an average built from one shape of call will mislead you.

| # | Shape | Target length | Why |
|---|---|---|---|
| 1 | Very short — hang up after the greeting | ~15s | Tests per-call minimums and rounding. **Per-second billing vs per-minute rounding is worth 20–30% on short calls** |
| 2 | Short question, one answer | ~45s | The commonest real call |
| 3 | Short question | ~45s | |
| 4 | Normal booking-style back-and-forth | ~2m | The bread-and-butter call |
| 5 | Normal booking-style | ~2m | |
| 6 | Normal booking-style | ~2m | |
| 7 | Long, meandering, several topics | ~5m | The expensive tail |
| 8 | Long with silences | ~4m | Does silence bill the same as speech? |
| 9 | Heavy interruption throughout | ~2m | Barge-in shouldn't cost extra — confirm it |
| 10 | Caller says nothing at all | ~1m | Tests the silence-timeout config against paid minutes |

### Log every call as you go

| # | Start | Duration (s) | Dashboard cost | $/min | Median latency | Notes |
|---|---|---|---|---|---|---|
| 1 | | | | | | |
| 2 | | | | | | |
| 3 | | | | | | |
| 4 | | | | | | |
| 5 | | | | | | |
| 6 | | | | | | |
| 7 | | | | | | |
| 8 | | | | | | |
| 9 | | | | | | |
| 10 | | | | | | |

| Totals | Value |
|---|---|
| Total seconds | |
| Total minutes | |
| **Balance after** | $ |
| **Total spent** (before − after) | $ |
| Number rental for the month (excluded from $/min — it's a fixed cost) | $ |

## Step 3 — Do the arithmetic

Use the calculator so the numbers land the same way every time:

```
python3 runbooks/cost_calc.py --spent 2.47 --seconds 1380 --fee 99 --cap 250 --number-cost 2.00
```

Or by hand:

```
measured $/min   =  total spent  ÷  total minutes
tier infra COGS  =  (measured $/min × tier minute cap) + number + misc
infra % of fee   =  tier infra COGS  ÷  monthly fee        ← margin floor: must be ≤ 40%
```

### Results

| | Measured |
|---|---|
| **All-in $/min** | **$________** |
| vs planning number ($0.10) | ☐ below ☐ at ☐ **above** |
| vs `PRICING.md` §2 budget-stack estimate ($0.091) | |
| Median voice-to-voice latency | ______ s (`TESTING.md` §3 healthy ≤ 1.0s, action > 1.2s) |
| Worst single latency | ______ s |
| Billing granularity confirmed | ☐ per second ☐ per minute |
| Silence billed same as speech? | ☐ yes ☐ no |
| Average minutes per "normal" call | ______ ← **feeds the tier recommender in `site/index.html`** |

### Re-run the tier table with the real number

Replace `docs/PRICING.md` §3 wholesale. This is the table that decides whether the business works:

| | Starter $99 | Growth $149 | Pro $199 |
|---|---|---|---|
| Cap (minutes) | 250 | 500 | 800 |
| Minutes cost at measured rate | $ | $ | $ |
| Number + misc | $4 | $4 | $5 |
| **Infra COGS** | $ | $ | $ |
| **Infra % of fee** — floor is **40%** | % | % | % |
| Verdict | ☐ ✅ ☐ ⚠ ☐ ❌ | ☐ ✅ ☐ ⚠ ☐ ❌ | ☐ ✅ ☐ ⚠ ☐ ❌ |

## Step 4 — Report what you found, including bad news

Three outcomes, three different actions. Decide by the table, not by hope.

| If measured $/min is… | Then |
|---|---|
| **≤ $0.10** | The plan holds. Update `docs/PRICING.md` §2–3, note the improvement, carry on |
| **$0.10 – $0.13** | Starter and Growth survive; **Pro at an 800-minute cap breaches the 40% floor.** See the open finding below — this needs a founder decision on cap or price |
| **> $0.13** | **Stop and reconsider before pilots.** Two levers: evaluate the Vapi fallback with BYO keys (D1's stated cost-optimisation path, ~$0.08–0.10/min), or re-cut the caps. Do **not** proceed to client pitches on tiers you have measured to be unprofitable |

> ### Open finding to resolve with this measurement
>
> **Pro breaches the margin floor at full utilisation even on the budget stack, and the fix stated in `PRICING.md` §3 does not actually fix it.**
>
> Its own table shows Pro on budget-stack voice at **$85 infra on a $199 fee = 42.7%** — above the 40% floor. The remedy given is *"Pro ships on the budget stack by default"*, but that is the 42.7% case. At the $0.10 planning number the floor implies a cap of **~750 minutes**, not 800.
>
> The floor is checked monthly against **actual** usage (`PRICING.md` §3, `TESTING.md` §3), so a Pro client using 600 minutes is comfortably fine. The gap is that the tier is *designed* so a fully-utilising Pro client is out of compliance on day one. Options, all founder decisions:
> **(a)** cut the Pro cap to 750 · **(b)** price Pro at $215 · **(c)** state explicitly that the floor governs actual usage and accept that a capped-out Pro client triggers a re-tier conversation by design.
>
> **Measure first, then decide** — if the real rate is $0.085, Pro at 800 minutes lands at $73/$199 = 37% and the whole question evaporates.

## Close-out

☐ Call log complete, all 10 rows
☐ Measured $/min calculated and sanity-checked against balance-before/after
☐ **`docs/PRICING.md` §2** — measured components replace `[verify]` estimates
☐ **`docs/PRICING.md` §3** — tier table re-run with the real number; the $0.10 planning number is **removed, not annotated**
☐ **`docs/PRICING.md`** — Pro-tier finding resolved with a dated decision
☐ **`docs/PROGRESS.md`** — measured $/min + latency in the task log; the "round-ups disagree" finding marked resolved
☐ **`docs/COMPATIBILITY.md` §4** — Retell per-minute row `[verify]` → measured, with date
☐ **`site/README.md`** — the ~3-minutes-per-call constant in the tier recommender corrected to measured
☐ Hours logged: ______ h
