From c0eef604e86cee558caa08326af05c9433c30706 Mon Sep 17 00:00:00 2001 From: tegwick Date: Fri, 31 Jul 2026 08:51:50 +0200 Subject: [PATCH] =?UTF-8?q?T05:=20CB-EV-0002=20=E2=80=94=20all=209=20metri?= =?UTF-8?q?cs=20met,=20and=20/compact=20measured=20at=203.1x?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AC-1 $93.32 ($92.21 main + $1.11 subagent), residual $0.000000. No unmeasured rows. Composition: 88.0% cache, 11.9% output, 249:1 context re-read to text written. The question that could not be answered before: what /compact costs. The transcript records it directly — 542,991 -> 19,974 tokens, a 27x reduction. Cost per turn fell from $0.457 (136 turns before) to $0.149 (202 turns after). The 202 post-compact turns cost less than half the 136 before them. This qualifies CB-WP-0003 T04: sessions are bounded-quadratic, not quadratic. Cost grows with context between compactions and resets at each one, so the failure mode is a long UNCOMPACTED session. Whether a fresh session beats a compaction is now measurable, and T04 should measure it before prescribing one task per session. Stale $0.66/$92.87 targets updated across survey and workplan. Co-Authored-By: Claude Opus 5 --- evidence/CB-EV-0002-cost-accounting.md | 152 ++++++++++++++++++++++ research/CB-RES-0002-cost-accounting.md | 15 ++- tools/__pycache__/cb-cost.cpython-312.pyc | Bin 0 -> 21980 bytes workplans/CB-WP-0002-cost-accounting.md | 10 +- 4 files changed, 167 insertions(+), 10 deletions(-) create mode 100644 evidence/CB-EV-0002-cost-accounting.md create mode 100644 tools/__pycache__/cb-cost.cpython-312.pyc diff --git a/evidence/CB-EV-0002-cost-accounting.md b/evidence/CB-EV-0002-cost-accounting.md new file mode 100644 index 0000000..a8f986a --- /dev/null +++ b/evidence/CB-EV-0002-cost-accounting.md @@ -0,0 +1,152 @@ +# CB-EV-0002: cost accounting + +capability: meta.loop.cost-accounting +spec: [CostAccounting.md](../specs/CostAccounting.md) v1.0 +decision: [ADR-0003](../decisions/ADR-0003-cost-accounting.md) +research: [CB-RES-0002](../research/CB-RES-0002-cost-accounting.md) +instrument: `make cost-pin` (`tools/cb-cost.py --pin fc76445`) +measured: 2026-07-31 + +Subject of measurement: the CB-WP-0001 session, pinned at commit `fc76445` +(`2026-07-31T02:17:59Z`). All numbers below are emitted by the tool, not +transcribed by hand (CA-15). + +--- + +## 1. Acceptance table + +| ID | Metric | Target | Measured | Verdict | +|---|---|---|---|---| +| AC-1 | pinned total, as two components | $93.32 = $92.21 + $1.11 | **$92.21 main + $1.11 subagent = $93.32** | **met** | +| AC-2 | reconciliation residual | $0.00 | **$0.000000** | **met** | +| AC-3 | unattributed share reported | present, 33% | **32.5%, own line** | **met** | +| AC-4 | composition reported | 5 components | **5 of 5** | **met** | +| AC-5 | dedup violation aborts | non-zero exit | **abort raised** | **met** | +| AC-6 | zero responses refuses to report | non-zero exit | **0 rows, no number emitted** | **met** | +| AC-7 | subagent tree enumerated | >0 found | **2 of 4 transcripts** | **met** | +| AC-8 | 5m cache priced at 1.25× | $1.25/100k @ fable | **$1.2500 (1h would be $2.0000)** | **met** | +| AC-9 | streamed partial output → final | 5,5,195 → 195 | **195** | **met** | + +No `unmeasured` rows. AC-1's target was corrected three times before this +run; §4 records why, because the sequence is more useful than the final +number. + +## 2. Composition — the finding the metric exists for + +```text + input 690 tok $ 0.00 0.0% + output 323,643 tok $ 11.15 11.9% + cache_read 80,611,798 tok $ 59.75 64.0% + write_5m 37,467 tok $ 0.47 0.5% + write_1h 1,672,854 tok $ 21.95 23.5% + TOTAL $ 93.32 +``` + +**88.0% of spend is cache; 11.9% is output.** The ratio of context re-read +to text written is 249:1. A single total would have shown $93.32 and +concealed all of it — which is exactly what CB-WP-0001's `M-D2-TOK` would +have done, and why that metric is now demoted. + +## 3. Per-task attribution + +```text + UNATTRIBUTED $ 30.32 32.5% + T08 $ 21.02 22.5% + T07 $ 12.01 12.9% + T03 $ 9.91 10.6% + T04 $ 8.00 8.6% + T05 $ 7.19 7.7% + T06 $ 3.58 3.8% + T09 $ 1.29 1.4% +``` + +**Stated limit (CA-10):** 32.5% of cost sits in commits whose subject +carries no `T##` tag, so this table is a view over 67.5% of spend. That is +a property of commit hygiene, not of the collector. + +T08 (the GROUND aggregate, six code iterations) at $21.02 is the most +expensive task and was also the one that produced the most rework — the +tuple-map hash panic, the discarded `setup.patch`, and the 5.6×-wrong +benchmark all originated there. Expensive *and* error-dense: the correlation +is worth watching, not yet a conclusion from n=1. + +## 4. What it does not support + +- **The per-task figures are not comparable across passes.** They mix + models (opus/fable/sonnet) at different price points and different cache + states. The dollar figure is comparable; a token count is not. +- **AC-3's 32.5% is a fixture pin, not a quality target.** Improving commit + tagging will move it, and that is the desired direction. +- **This is one session.** Every ratio here (cache share, $/turn, the + compaction effect in §5) is n=1 and should be treated as a hypothesis + until a second pass reproduces it. +- **The price sheet cannot express a time-boxed rate.** Sonnet's intro price + lives in a TOML comment, so sonnet-priced work is off by $0.17 here + (0.19%). This becomes a real error on 2026-08-31. +- **AC-1 is not invoice-verified.** No admin key exists, so the Anthropic + billing API could not independently confirm the total. The transcript + counters are the same ones billing uses, but that is an argument, not a + reconciliation. + +## 5. The question that could not be answered before + +**"What does `/compact` actually cost, and is a long session quadratic?"** + +CB-WP-0003 T04 asserts that cost ≈ turns × mean_context and that mean_context +grows with turns, making long sessions quadratic. The data **qualifies that +claim**: it is true only between compactions. + +The session compacted twice, and the transcript records both directly: + +| compaction | pre-tokens | post-tokens | reduction | +|---|---|---|---| +| C1 `00:07:14Z` (manual) | 542,991 | 19,974 | **27×** | +| C2 `02:22:23Z` (manual) | 344,954 | 19,035 | **18×** | + +Cost per turn across the boundary: + +| segment | turns | mean context | total | $/turn | +|---|---|---|---|---| +| start → C1 | 136 | 304,178 | $62.19 | **$0.457** | +| C1 → C2 | 202 | 193,493 | $30.01 | **$0.149** | + +**The 202 turns after the first compaction cost less than half of the 136 +turns before it — a 3.1× drop in cost per turn.** Context growth *is* the +cost driver, and compaction is the control on it. At the pre-compact rate, +those 202 turns would have cost ~$92 instead of $30. + +Two consequences for CB-WP-0003: + +1. **T04's "one task per session" recommendation is not the only remedy, + and may not be the cheapest one.** Compaction achieved a 27× context + reduction inside a running session at the cost of one summarization + call. A fresh session pays a cold-start re-read of the committed + artifacts; compaction pays a summary. Which is cheaper is now a + measurable question rather than a matter of taste, and T04 should + measure it before prescribing. +2. **The quadratic claim should be restated as bounded-quadratic:** cost + grows with context between compactions and resets at each one. The + failure mode is not "a long session" but "a long *uncompacted* session". + +## 6. Retrospective note + +The positive control paid for itself on its first execution, which is the +strongest evidence this project has produced for the InnerLoop v1.0 rule +that added it. CA-02 asserted that `usage` is identical across the lines of +one `requestId` — verified twice on the main transcript, by the survey +(206/206 groups) and independently by the adversarial reviewer. It is false +in the `subagents/` tree, where `output_tokens` is a running count +(`5, 5, 195`). The assertion fired, the run aborted, and the tool refused to +print a number. Under the prior first-wins rule it would have printed a +plausible one. + +The generalization that failed is worth naming: **a property verified on the +largest sample was assumed to hold on the smallest one.** The main +transcript is 338 of 346 responses, so 206/206 felt conclusive; the +violation lives entirely in the 8 responses nobody checked separately. + +Cost of the adversarial review this pass: **$1.11**, against a $93.32 pass. +It found three approval-blocking defects, one of which (the subagent +exclusion) would have made this evidence file certify a broken collector. +Second consecutive pass where a ~1% spend on review changed the outcome. +That is now two data points for CB-WP-0003 T03. diff --git a/research/CB-RES-0002-cost-accounting.md b/research/CB-RES-0002-cost-accounting.md index 9258b42..cb8869b 100644 --- a/research/CB-RES-0002-cost-accounting.md +++ b/research/CB-RES-0002-cost-accounting.md @@ -90,8 +90,13 @@ acceptance target is therefore pinned by timestamp: | cache write 1h | 1,672,854 tok → $21.95 | | input | 676 tok → $0.00 | | main transcript | **$92.21** — 88.4% cache, 256:1 cache-read:output | -| + subagent tree (7 responses, ran 23:11–23:14Z, inside the pin) | $0.66 | -| **TRUE TOTAL** | **$92.87** | +| + subagent tree (7 responses, ran 23:11–23:14Z, inside the pin) | $1.11 | +| **TRUE TOTAL** | **$93.32** | + +*(The subagent figure was $0.66 when this survey was written. T04's +positive control found the cause: `output_tokens` is a running count in +the `subagents/` tree, so first-wins dedup under-counted it. See +`specs/CostAccounting.md` CA-02a.)* The subagent line is not a footnote. C1's blind-spot finding says a collector reading only the main file under-reports; a target of $92.21 would @@ -255,9 +260,9 @@ b58a913 2026-07-31T02:19:34+02:00 T08 iter 2: Reveal, Resolve, End; … | D2 efficiency (**the deciding row**) | C1 transcript | **error against the billing counters** | **$0.00 — the transcript *is* the counter set; C2's error on the same work is $92.21 − $0.03 recorded ≈ 100%** | measured | | D4 optionality | C4 billing API | authority | invoice-grade, zero attribution, admin key absent (asserted, not measured — used only to keep C4 as an optional check) | availability measured | -**Benchmark-to-beat for the collector:** reproduce **$92.87** for repo +**Benchmark-to-beat for the collector:** reproduce **$93.32** for repo `clay-borg` pinned at `2026-07-31T02:17:59Z` — as its two components, -**$92.21 main transcript + $0.66 subagent tree** — from the committed price +**$92.21 main transcript + $1.11 subagent tree** — from the committed price sheet, with the unattributed remainder reported as its own line (expected **33%**, $30.32) and reconciliation asserted rather than assumed. @@ -297,7 +302,7 @@ correct and useless. runtime rather than trusting this survey's one-time check. 3. **Subagent transcripts are a separate tree.** Measured: CB-WP-0001's one subagent (adversarial review, Fable 5, 7 responses, 158,096 cache - reads) cost **$0.66**, invisible to any collector reading only the + reads) cost **$1.11**, invisible to any collector reading only the main file. Small here; not small for a pass that fans out. 4. **The price sheet has a 90-day staleness rule** (§1a) and no automated check. Every number this capability produces inherits that. diff --git a/tools/__pycache__/cb-cost.cpython-312.pyc b/tools/__pycache__/cb-cost.cpython-312.pyc new file mode 100644 index 0000000000000000000000000000000000000000..12efe0a2067d76fc833505395d4bd166dba9d9a4 GIT binary patch literal 21980 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 m+wzgFJDWc8^lL{zjeNmzBmBRyMDc