adr: +0009 spend-gate rescope +0010 spearhead 4.5 benchmark/sim; amend 0004
All checks were successful
CI / fmt (push) Successful in 1m5s
CI / clippy (push) Successful in 1m53s
CI / test (1.85) (push) Successful in 5m54s
CI / test (stable) (push) Successful in 6m36s
CI / deny (push) Successful in 2m12s

Maintainer-ratified from the 2026-07-03 review (R1-R3):
- ADR-0009: retire "structurally impossible for a 3-vendor stack" post-0007;
  restate the gate's true guarantees (credential isolation, unskippable
  mediation, media-plane enforcement, audit co-location). Propagated to
  README pillar 3, ARCHITECTURE, PORT_PLAN s10; amendment note on ADR-0002.
- ADR-0010: insert step 4.5 (benchmark + simulation harness, rutster-sim
  seed, CI-regressed p50/p99 + kill-time) after barge-in; pull rung-2
  escalation ahead of steps 5-6. Spearhead lists updated.
- ADR-0004: delete the legally-broken AGPL escape hatch; GPL-3.0-or-later
  permanent, no CLA; tap protocol/SDKs intended permissive (future ADR).
- README: add brain-vendor-direct competitor row (review D2).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_018vNe64BBDkgo5oQVkBa3XF
This commit is contained in:
2026-07-04 00:00:31 -04:00
parent 4c36a4ded3
commit da6b7c9ff0
7 changed files with 208 additions and 9 deletions

View File

@@ -4,6 +4,9 @@
- **Date:** 2026-06
- **Origin:** [vision-revision](../superpowers/specs/2026-06-26-vision-revision-design.md) §14, 67
- **Amends:** `README.md`, `docs/ARCHITECTURE.md`, `docs/PORT_PLAN.md` (the founding identity framing)
- **Amended by:** [ADR-0009](0009-spend-gate-honest-rescope.md) — the pillar table's spend-gate
phrasing ("structurally impossible for a 3-vendor stack") is retired post-0007; see 0009 for
the gate's precise guarantees (2026-07-03)
## Context

View File

@@ -36,9 +36,20 @@ hosted service may be nothing. The license is the **floor**, not the moat: the w
+ data-ownership + one auditable boundary + operational simplicity + data-ownership as a buying
criterion — is the actual reason operators self-host rather than wrap.
If cloud-wrap becomes a demonstrated threat, **re-evaluate AGPL-3.0-or-later** (this ADR's
"or-later" clause permits that transition cleanly, since GPL-3.0-or-later is a strict subset of
AGPL-3.0-or-later for recipients).
> **Amended 2026-07-03** (maintainer-ratified; origin:
> [adversarial review D5](../reviews/2026-07-03-adversarial-review.md)). The paragraph this note
> replaces claimed the "or-later" clause permits a clean later transition to AGPL. **That claim
> was wrong:** "or-later" covers later versions of the *GNU GPL* (GPLv3 §14); AGPL is a different
> license, not a later GPL version — GPLv3 §13 permits *combining* with AGPL works, not
> relicensing GPL code as AGPL. Relicensing requires the consent of every copyright holder, so
> the option would die at the first external contribution accepted without a CLA.
>
> **Resolution:** rutster accepts **GPL-3.0-or-later permanently** for the engine. No CLA — the
> contributor friction and community optics were judged worse than the loss of a relicensing
> option. Cloud-wrap remains a named, accepted risk mitigated by the wedge, exactly as the
> trade-off paragraph above already argued. (The tap *protocol spec* and client SDKs are
> intended to be permissively licensed for adoption — engine GPL, protocol permissive — to be
> ratified in the tap-protocol ADR when that interface hardens.)
## Consequences

View File

@@ -0,0 +1,90 @@
# ADR-0009 — Spend/abuse gate: honest re-scope of the structural claim post-0007
- **Status:** Accepted (maintainer-ratified 2026-07-03)
- **Date:** 2026-07-03
- **Origin:** [2026-07-03 adversarial review](../reviews/2026-07-03-adversarial-review.md),
finding D4 / recommendation R3.
- **Amends:** [ADR-0002](0002-north-star-and-fused-core.md) (pillar table), `README.md`
(pillar 3), `docs/PORT_PLAN.md` (§10 toll-fraud row), `docs/ARCHITECTURE.md` (in-boundary
spend/abuse gate bullet)
## Context
ADR-0002 promoted the spend/abuse gate to *constitutive* with the argument: "a runaway brain
can't exceed pacing or spend because it doesn't hold the wire — **structurally impossible for a
3-vendor stack**." Under [ADR-0003](0003-sip-rust-native-trunk.md) (rutster terminates the
carrier trunk) that claim was structural: rutster held the wire.
[ADR-0007](0007-trunk-rented-transport.md) changed the topology. Under rented transport,
**rutster does not hold the wire either — the CPaaS does.** The gate's mechanism became
"rutster holds the provider call-control credential and the brain doesn't," which is an
IAM/configuration property, not a structural one:
1. Any orchestrator that holds the provider credentials can make the same claim (a Python
framework with a spend counter and scoped credentials).
2. The CPaaS itself ships spend limits.
3. A provider credential scoped too widely, or leaked outside rutster, bypasses the gate
entirely — rutster cannot see, let alone stop, provider-API calls it doesn't mediate.
Meanwhile the ADR-0007 architecture *is* a 3-vendor stack (CPaaS + rutster + brain), making the
unamended pillar self-describing. The claim must be narrowed to what is actually true before it
is repeated in public-facing material.
## Decision
The spend/abuse gate remains **FOB and constitutive** ([ADR-0008](0008-fob-and-green-zone.md):
security-constitutive), but its guarantees are restated precisely:
**What the gate structurally guarantees (true post-0007):**
1. **Credential isolation** — the brain never holds provider credentials. Every
call-origination, transfer, or hangup the brain wants happens through rutster's API, where
the gate sits. The brain cannot spend *through rutster* beyond the gate, ever.
2. **Unskippable on mediated egress** — spend/pacing checks are in-process with the tap and the
provider call-control client. There is no deployment topology in which brain-initiated
actions reach the provider without passing the gate. (Contrast: a bolt-on spend service in a
3-vendor chain can be *routed around*; an in-boundary gate cannot — for traffic rutster
mediates.)
3. **Media-plane enforcement** — pacing, half-duplex, and playout caps are enforced over media
rutster terminates. The brain *proposes* audio; the core *disposes*. A flooding or
overlapping brain is throttled at the playout ring regardless of what it sends.
4. **Audit co-location** — every allowed/denied spend decision is recorded at the same trust
boundary that made it, so the audit log and the enforcement point cannot diverge.
**What the gate does NOT guarantee (stated so we don't kid ourselves):**
- It cannot constrain spend on provider credentials used *outside* rutster (mis-scoped keys,
console access, a second integration holding the same key). **Deployment guidance must pair
the gate with provider-side caps** (defense in depth) and per-integration credential scoping.
- The "structurally impossible for a 3-vendor stack" phrasing is **retired**. The honest
comparative claim: *in-boundary co-location makes the gate unskippable for everything rutster
mediates, and rutster mediates everything the brain can do* — a property a bolt-on spend
service cannot offer, but not a physical monopoly on the wire.
## Propagation (on acceptance)
| Doc | Change |
|---|---|
| ADR-0002 | Add amendment note to the pillar table pointing here |
| `README.md` pillar 3 | Replace "doesn't hold the wire — structurally impossible for a 3-vendor stack" with the credential-isolation + unskippable-mediation phrasing |
| `docs/ARCHITECTURE.md` | Same fix in the "In-boundary spend / abuse gate" bullet |
| `docs/PORT_PLAN.md` §10 | Same fix in the toll-fraud/spend row |
## Consequences
- **Positive:** the security narrative survives adversarial scrutiny (the previous phrasing
invited a one-tweet rebuttal); the gate's real guarantees — credential isolation, unskippable
mediation, media-plane throttling, audit co-location — are strong and defensible; deployment
guidance gains the provider-side-caps pairing, which operators need anyway.
- **Negative:** the pitch loses a superlative ("structurally impossible") in exchange for
precision; step 6's scope grows slightly (the gate should also *meter* — per-call cost
attribution into the CDR — per the
[market feature scan F5](../reviews/2026-07-03-market-feature-scan.md), since integrator unit
economics run on cost-per-contained-call).
## References
- [ADR-0002](0002-north-star-and-fused-core.md) — the pillar this amends
- [ADR-0007](0007-trunk-rented-transport.md) — the topology change that invalidated the phrasing
- [ADR-0008](0008-fob-and-green-zone.md) — FOB test the gate still passes (security-constitutive)
- [Adversarial review 2026-07-03](../reviews/2026-07-03-adversarial-review.md) — finding D4

View File

@@ -0,0 +1,75 @@
# ADR-0010 — Spearhead re-sequencing: benchmark + simulation harness at step 4½; escalation pulled forward
- **Status:** Accepted (maintainer-ratified 2026-07-03)
- **Date:** 2026-07-03
- **Origin:** [2026-07-03 adversarial review](../reviews/2026-07-03-adversarial-review.md)
(recommendations R1, R2) + [market feature scan](../reviews/2026-07-03-market-feature-scan.md)
(F1 — simulation testing as the standout engine-fit feature).
- **Amends:** `README.md` (spearhead list), `docs/PORT_PLAN.md` (phasing section),
the vision-revision spearhead sequence (design record; unmodified — this ADR is the amendment)
## Context
Three findings converged on the spearhead's back half:
1. **The wedge is unmeasured (review P3/R2).** The no-GC determinism pillar — the only claim
justifying Rust over a weekend of Pipecat — has no proof artifact. README latency figures are
arithmetic estimates; `TapMetrics` counts drops, not latency. Slice 4's design sets a ≤60 ms
barge-in kill budget but ships only a synthetic e2e test, not a measurement harness.
2. **The step-5 demo was commoditized (review D2).** OpenAI Realtime SIP is GA: a trunk pointed
at `sip.api.openai.com` reproduces "I called my box and an AI answered" with zero
infrastructure. The momentum value of rushing to step 5 has collapsed; the differentiating
value of *measured* reflex quality and of escalation (rung 2 — which no framework or brain
vendor ships) has risen.
3. **Simulation is the standout engine-fit feature (scan F1).** Parloa sells pre-deployment
simulation + evals as an enterprise phase; Cekura/Coval sell it standalone. Nobody ships it
self-hosted. rutster's tap symmetry (a synthetic caller is just another media-leg ingress)
and the slice-3 mock brain mean the substrate is half-built.
One build serves all three: the benchmark *is* a simulation harness pointed at latency metrics.
## Decision
**Insert step 4½ into the spearhead — the benchmark + simulation harness — after barge-in (4),
before rented transport (5).** Numbered 4½ deliberately: existing "step 5"/"step 6" references
(stub-crate docs, PORT_PLAN rows, fuzz plan) stay valid.
**Step 4½ scope (the `rutster-sim` seed):**
- **Synthetic-caller ingress** — scripted scenario playback (WAV/PCM segments with timing
directives: speak, pause, interrupt-at-T) driving the same media-leg ingress path a real
caller uses. LLM-driven callers are a later extension, not this step.
- **Latency measurement** — p50/p99 mouth-to-ear round-trip and barge-in kill-time
(caller-speech-onset → playout-ring-flushed), measured against slice-4's ≤60 ms budget.
- **Concurrency sweep** — the same measurements at 1 / 10 / 50 concurrent synthetic calls,
which also surfaces the single-poll-task head-of-line-blocking debt (review P2) with data
instead of doctrine.
- **CI-regressed** — thresholds asserted per commit; a latency regression fails the build the
same way a broken test does.
**Sequencing after 4½:** **rung-2 escalation (human takeover) is pulled forward ahead of
steps 56.** It is the white space no competitor ships (warm-handoff artifact + whisper — scan
F2), it works entirely on WebRTC ingress (no PSTN dependency), and it is the capability that
answers "why not point the trunk at OpenAI directly?" before step 5 makes that question live.
Steps 5 (rented transport) and 6 (spend cap) follow, unchanged in content.
## Consequences
- **Positive:** the wedge gains its proof artifact (and the only differentiating demo available
this year: reproducible p99 kill-latency vs. the GC'd frameworks); the doctrine-drift detector
for the timing-thread debt exists before scale makes it urgent; the eval-infrastructure
foundation (scenario packs, rung-3/4 regression evals) is laid as a side effect; the spearhead's
next public moment is a capability no one else has, not a commoditized one.
- **Negative:** steps 56 slip by two slices; "a real phone number" — still the most *visceral*
demo — waits. Accepted deliberately: the demo it enables is no longer scarce (D2), and the
reflex claims stay unsubstantiated until measured.
- **Debt paired:** if the concurrency sweep shows the shared-tokio poll loop breaching budget at
realistic call counts, the dedicated-timing-thread work (ARCHITECTURE.md doctrine, review P2)
gets scheduled on data, not vibes.
## References
- [Adversarial review 2026-07-03](../reviews/2026-07-03-adversarial-review.md) — findings D1, D2, P2, P3; recommendations R1, R2
- [Market feature scan 2026-07-03](../reviews/2026-07-03-market-feature-scan.md) — F1 (simulation harness), F2 (handoff protocol), A8 (scenario packs)
- [ADR-0007](0007-trunk-rented-transport.md) — the trunk posture step 5 implements
- Slice-4 design (`docs/superpowers/specs/2026-07-01-slice-4-barge-in-design.md`) — the ≤60 ms kill budget this harness measures