|
| 1 | +# Does writing a lesson down make the same work cheaper? — a measurement |
| 2 | + |
| 3 | +**Status: measured, negative. Do not build the session-level relearn rework on this corpus.** |
| 4 | +Run 2026-07-26 against the full local corpus (6,176 sessions / 527,089 spans / 2026-05-22 → 2026-07-24). |
| 5 | +Reproduce with `tokenjam/core/optimize/repeat_task.py` (unit tests: `tests/unit/test_repeat_task.py`). |
| 6 | + |
| 7 | +## The question |
| 8 | + |
| 9 | +`relearn` prices **failure episodes** — individual erroring tool calls, clustered by failure |
| 10 | +signature. Measured total on this corpus: **$46.26 across 55 clusters**. The hypothesis was that this |
| 11 | +is implausibly small because the episode is the wrong unit: the waste is not the failed call, it is |
| 12 | +the **inflated session** around it. An agent that does not know a project's constraints explores, |
| 13 | +reads the wrong files, backtracks, and re-sends a growing context on every turn of that flailing. |
| 14 | + |
| 15 | +The proposed replacement: cluster sessions doing the same repeated work, then compare cost across the |
| 16 | +point at which the relevant lesson was written down. The field observation motivating it: setting up |
| 17 | +one project repeatedly took 40+ minutes, and dropped to under 20 minutes after its faults were |
| 18 | +codified. |
| 19 | + |
| 20 | +Four things had to be true. Three of them are not. |
| 21 | + |
| 22 | +## 1. Are repeat-task clusters identifiable? — **Yes, and easily** |
| 23 | + |
| 24 | +Using the session's first user prompt as a task statement, with ids / paths / numbers masked and |
| 25 | +scoped to the project (`repeat_task.task_cluster_key`): |
| 26 | + |
| 27 | +| | | |
| 28 | +|---|---| |
| 29 | +| sessions with a recoverable task statement | 2,711 | |
| 30 | +| distinct clusters | 346 | |
| 31 | +| clusters with ≥ 24 sessions | 19, covering 1,668 sessions | |
| 32 | +| largest cluster | 496 sessions | |
| 33 | + |
| 34 | +31 clusters at n ≥ 5 cover **89%** of all sessions with a task statement. This is much better than |
| 35 | +expected, for a reason worth stating plainly: most of these prompts are **machine-issued templates**, |
| 36 | +so matching on them is closer to an identity test than a similarity test. False-positive risk is |
| 37 | +near zero *for templated work*. |
| 38 | + |
| 39 | +That caveat is load-bearing. This corpus belongs to a heavy agent-harness user, and its repeat |
| 40 | +structure is harness-generated. A corpus of hand-typed human prompts would cluster far worse, and |
| 41 | +nothing here measures how much worse. |
| 42 | + |
| 43 | +## 2. Does the method reach back far enough? — **No. ~30 days.** |
| 44 | + |
| 45 | +The task statement lives in the agent harness's on-disk transcript, which the harness rotates on its |
| 46 | +own schedule. Availability, by month, over sessions tokenjam retained spans for: |
| 47 | + |
| 48 | +| month | sessions in DB | with a recoverable task statement | |
| 49 | +|---|---|---| |
| 50 | +| 2026-05 | 42 | 0 (**0.0%**) | |
| 51 | +| 2026-06 | 3,906 | 142 (**3.6%**) | |
| 52 | +| 2026-07 | 2,188 | 2,186 (**99.9%**) | |
| 53 | + |
| 54 | +This is fatal in a specific way. A before/after needs the **uninformed** runs, and the uninformed runs |
| 55 | +are by definition the *old* ones — the ones that happened before anyone had written the lesson down. |
| 56 | +Those are exactly the sessions whose task statement no longer exists. The high-confidence clusterer |
| 57 | +can only see the informed side. |
| 58 | + |
| 59 | +For the motivating project specifically: 22 sessions in May, **0 with a recoverable task statement**. |
| 60 | + |
| 61 | +## 3. Can the span-only fallback substitute? — **No, and this is the load-bearing negative** |
| 62 | + |
| 63 | +Spans are retained past transcript rotation, so a span-only "same work" similarity is the only thing |
| 64 | +that reaches the uninformed era. The ticket proposed `cwd` + tool-sequence shape. That was scored |
| 65 | +against the task-statement ground truth on the window where both exist (972 July sessions with ≥ 8 |
| 66 | +tool calls, 200,000 sampled session pairs). Baseline same-work pair rate: **0.147**. |
| 67 | + |
| 68 | +| predicate | precision | recall | lift | |
| 69 | +|---|---|---|---| |
| 70 | +| identical opening-3 tools | 0.260 | 0.501 | 1.8× | |
| 71 | +| identical opening-8 tools | 0.247 | 0.183 | 1.7× | |
| 72 | +| tool-mix cosine ≥ 0.98 | 0.236 | 0.356 | 1.6× | |
| 73 | +| tool-mix cosine ≥ 0.99 | 0.247 | 0.202 | 1.7× | |
| 74 | +| **same project** (alone) | 0.383 | 0.244 | 2.6× | |
| 75 | +| same project + opening-8 | 0.481 | 0.051 | 3.3× | |
| 76 | +| same project + cosine ≥ 0.98 | 0.499 | 0.096 | 3.4× | |
| 77 | +| **same project + opening-8 + cosine ≥ 0.95** | **0.538** | **0.043** | **3.7×** | |
| 78 | +| same project + opening-12 + cosine ≥ 0.99 | 0.535 | 0.015 | 3.6× | |
| 79 | + |
| 80 | +The best achievable operating point is **precision 0.54 at recall 0.04**: roughly **half** of the |
| 81 | +pairs it calls "the same work" are not, while it captures 4% of the real repeats. Tightening the |
| 82 | +predicate does not help — precision plateaus at ~0.54 and recall collapses. |
| 83 | + |
| 84 | +The reason is mundane. Tool-call shape is dominated by *which tool the agent is holding*, not by |
| 85 | +*what task it is doing*. Almost every coding-agent session looks like Bash, Read, Edit, Bash, Bash. |
| 86 | + |
| 87 | +`repeat_task.TOOL_SHAPE_MATCH` carries this measured 0.54 as data, and |
| 88 | +`measure_codification_delta` **refuses** to price any cluster derived from it. |
| 89 | + |
| 90 | +### This also settles the `script` / `relearn` boundary |
| 91 | + |
| 92 | +`analyzers/workflow_restructure.py` (the `script` analyzer) clusters sessions by ordered tool-call |
| 93 | +signature — the same primitive measured above. So the table is a direct audit of `script`'s |
| 94 | +clustering, and it says: **that primitive identifies a shape, not a task.** |
| 95 | + |
| 96 | +That is not a bug in `script`, because a script replaces a *shape*. It is exactly the right unit for |
| 97 | +"could a deterministic script do this". It is the wrong unit for "was this the same work", which is |
| 98 | +why `relearn` cannot borrow it. |
| 99 | + |
| 100 | +The two analyzers are **disjoint and should stay separate**: |
| 101 | + |
| 102 | +| | `script` | `relearn` | |
| 103 | +|---|---|---| |
| 104 | +| recurrence detected | same tool-call **shape** | same **failure** signature | |
| 105 | +| question | is this deterministic enough to replace with code? | is this recurring because a lesson isn't written down? | |
| 106 | +| fix emitted | a script | a rule (CLAUDE.md / skill / hook) | |
| 107 | +| unit | the session's shape | the failure episode | |
| 108 | + |
| 109 | +They overlap only in that both are triggered by repetition. Neither subsumes the other, and |
| 110 | +converging them would merge a shape-clusterer with a failure-clusterer that were measured here to be |
| 111 | +answering different questions. **Recorded boundary: keep both; `relearn` must not adopt `script`'s |
| 112 | +signature as a same-work test.** |
| 113 | + |
| 114 | +## 4. Is the effect detectable above the noise? — **No, not at this effect size** |
| 115 | + |
| 116 | +Even inside the tightest cluster obtainable — one machine-generated prompt template, one project — |
| 117 | +per-session cost is extremely noisy: |
| 118 | + |
| 119 | +| cluster | n | median $ | CV | p10 | p90 | |
| 120 | +|---|---|---|---|---|---| |
| 121 | +| ticket-worker × project A | 87 | 4.41 | 0.79 | 1.48 | 12.07 | |
| 122 | +| ticket-worker × project B | 78 | 2.23 | 1.15 | 0.26 | 8.79 | |
| 123 | +| ticket-worker × project C | 95 | 1.34 | 1.21 | 0.51 | 7.32 | |
| 124 | +| ticket-worker × project D | 63 | 2.77 | 0.85 | 1.13 | 8.91 | |
| 125 | +| interactive sessions × project B | 29 | 20.32 | 1.36 | 1.71 | 296.48 | |
| 126 | + |
| 127 | +Coefficient of variation **0.7–1.2**, with p10→p90 spanning an order of magnitude. The 95% bootstrap |
| 128 | +interval on the median at n ≈ 45 per side is **±46–49%**. |
| 129 | + |
| 130 | +The effect being hunted is ~50% (40 min → under 20 min). **It sits at the noise floor of the best |
| 131 | +cluster available.** Detecting it reliably needs either far larger n per side or a paired design that |
| 132 | +holds task difficulty constant — and the residual variance here is task difficulty, since each run of |
| 133 | +the "same" template does a different ticket. |
| 134 | + |
| 135 | +## 5. The before/after test itself |
| 136 | + |
| 137 | +Codification events = commits touching `CLAUDE.md` / `learnings.md` in each project (135 events in |
| 138 | +the motivating project, spread over ~30 distinct days from 2026-05-28 to 2026-07-17 — codification is |
| 139 | +**continuous and drip-fed**, not a single step change, which is itself a problem for a before/after |
| 140 | +design). |
| 141 | + |
| 142 | +Across the entire corpus there are **13** testable (cluster × codification-event) pairs with ≥ 12 |
| 143 | +sessions on both sides. Results: |
| 144 | + |
| 145 | +| project | event | n before / after | median $ before → after | ratio | 95% CI | verdict | |
| 146 | +|---|---|---|---|---|---|---| |
| 147 | +| C | 2026-07-18 | 56 / 39 | 0.92 → 3.09 | 3.35 | [1.92, 4.83] | dearer | |
| 148 | +| C | 2026-07-18 | 70 / 25 | 1.21 → 4.05 | 3.36 | [2.32, 6.28] | dearer | |
| 149 | +| C | 2026-07-19 | 76 / 19 | 1.27 → 4.11 | 3.23 | [2.31, 6.55] | dearer | |
| 150 | +| A | 2026-06-28 | 13 / 74 | 3.26 → 4.96 | 1.52 | [0.93, 2.10] | null | |
| 151 | +| A | 2026-06-29 | 30 / 57 | 3.52 → 5.14 | 1.46 | [0.97, 2.34] | null | |
| 152 | +| A | 2026-07-02 | 60 / 27 | 3.42 → 7.19 | 2.10 | [1.25, 2.84] | dearer | |
| 153 | +| B | 2026-07-03 | 24 / 54 | 5.33 → 1.45 | 0.27 | [0.17, 0.48] | cheaper | |
| 154 | +| B | 2026-07-10 | 26 / 52 | 4.87 → 1.45 | 0.30 | [0.17, 0.51] | cheaper | |
| 155 | +| B | 2026-07-16 | 50 / 28 | 3.36 → 0.52 | 0.16 | [0.09, 0.44] | cheaper | |
| 156 | +| A | 2026-07-16 | 24 / 39 | 2.83 → 2.77 | 0.98 | [0.54, 1.60] | null | |
| 157 | +| B (interactive) | 3 events | ~13-17 / ~12-16 | — | 0.56–1.25 | e.g. [0.06, 5.88] | null | |
| 158 | + |
| 159 | +**The same treatment produces ratios from 0.16× to 3.35×, with intervals excluding 1.0 in both |
| 160 | +directions.** That is the signature of a confound, not an effect. |
| 161 | + |
| 162 | +### The confound, identified |
| 163 | + |
| 164 | +Model routing. The harness right-sizes the model per ticket, and that mix moved *hard* under every |
| 165 | +comparison: |
| 166 | + |
| 167 | +| project | week | median $ | model mix | |
| 168 | +|---|---|---|---| |
| 169 | +| B | 2026-W27 | 6.48 | opus 94% | |
| 170 | +| B | 2026-W28 | 2.35 | sonnet 71%, opus 22%, haiku 6% | |
| 171 | +| B | 2026-W29 | 1.40 | sonnet 36%, opus 35%, haiku 27% | |
| 172 | +| C | 2026-W29 | 1.25 | opus 57%, sonnet 39% | |
| 173 | +| C | 2026-W30 | 7.00 | opus 99% | |
| 174 | + |
| 175 | +Project B's "codification saved 84%" is the model right-sizing rollout. Project C's "codification |
| 176 | +cost 235% more" is the same mechanism running backwards. **5 of the 7 apparently-significant results |
| 177 | +had the model mix change underneath them.** |
| 178 | + |
| 179 | +### Controlling for it |
| 180 | + |
| 181 | +Restricting to sessions ≥ 90% served by a single model (`repeat_task.model_mix_is_stable`): |
| 182 | + |
| 183 | +| project | event | n before / after | ratio | 95% CI | verdict | |
| 184 | +|---|---|---|---|---|---| |
| 185 | +| C | 2026-07-18 | 25 / 33 | 2.26 | [1.51, 3.12] | dearer | |
| 186 | +| C | 2026-07-18 | 34 / 24 | 2.36 | [1.50, 4.00] | dearer | |
| 187 | +| C | 2026-07-19 | 40 / 18 | 2.19 | [1.12, 4.26] | dearer | |
| 188 | +| **A** | 2026-06-28 | 13 / 73 | 1.48 | [0.91, 2.14] | **null** | |
| 189 | +| **A** | 2026-06-29 | 30 / 56 | 1.52 | [0.96, 2.37] | **null** | |
| 190 | +| **A** | 2026-07-02 | 59 / 27 | 2.17 | [1.26, 2.87] | **dearer** | |
| 191 | +| **A** | 2026-07-16 | 21 / 37 | 0.89 | [0.51, 1.55] | **null** | |
| 192 | +| B | 2026-07-03 | 22 / 22 | 0.40 | [0.24, 0.75] | cheaper | |
| 193 | +| B | 2026-07-10 | 24 / 20 | 0.45 | [0.25, 0.88] | cheaper | |
| 194 | +| B | 2026-07-16 | 30 / 14 | 0.37 | [0.21, 0.78] | cheaper | |
| 195 | + |
| 196 | +**Project A is the motivating project — the known-positive the method exists to reproduce. It comes |
| 197 | +back `null` or `dearer` at every testable codification event**, with up to 144 model-matched sessions. |
| 198 | +The gate prices it at **$0.00**. |
| 199 | + |
| 200 | +The signs still disagree across projects for the same treatment, so the surviving B/C results are |
| 201 | +residual confounding (ticket-difficulty drift, harness version), not a demonstrated effect. |
| 202 | + |
| 203 | +## 6. What about the original field observation? |
| 204 | + |
| 205 | +It is real as a *project-level trend*, and it is not attributable to codification. Median active |
| 206 | +session minutes for the motivating project: |
| 207 | + |
| 208 | +| week | n | median active min | p25 | p75 | median $ | |
| 209 | +|---|---|---|---|---|---| |
| 210 | +| 2026-W22 | 16 | 111.4 | 9.6 | 812.4 | 21.03 | |
| 211 | +| 2026-W23 | 71 | **37.5** | 9.5 | 315.4 | 22.73 | |
| 212 | +| 2026-W24 | 76 | **45.1** | 11.8 | 255.5 | 24.29 | |
| 213 | +| 2026-W26 | 13 | 30.2 | 1.6 | 122.3 | 2.39 | |
| 214 | +| 2026-W27 | 12 | **16.7** | 3.0 | 454.6 | 3.20 | |
| 215 | +| 2026-W29 | 15 | 29.5 | 4.0 | 141.4 | 1.64 | |
| 216 | + |
| 217 | +37.5–45.1 min falling to 16.7–29.5 min matches the recollection closely. But: |
| 218 | + |
| 219 | +- The interquartile range is enormous (9.5 → 315 min in W23). The median is drifting inside noise an |
| 220 | + order of magnitude wider than the drift. |
| 221 | +- Median cost fell **10×** ($22.73 → $1.64) over the same span. No plausible codification effect is |
| 222 | + 10×. |
| 223 | +- What actually changed is **what a "project A session" is**: long human-driven interactive sessions |
| 224 | + in W22–W24 gave way to short headless ticket-worker sessions from W26 on. That is a change of task |
| 225 | + mix, not a change in the informedness of a fixed task. |
| 226 | +- There is no repeat-task cluster spanning the boundary, because W22–W24 transcripts are gone. |
| 227 | + |
| 228 | +The observation is consistent with codification helping. It is equally consistent with three other |
| 229 | +explanations, and this corpus cannot separate them. |
| 230 | + |
| 231 | +## Verdict |
| 232 | + |
| 233 | +**The uninformed-vs-informed signal cannot be measured on this corpus at a confidence that would |
| 234 | +support pricing.** Specifically: |
| 235 | + |
| 236 | +1. Repeat-task clusters are identifiable — but only for ~30 days, and the uninformed side is older. |
| 237 | +2. The only similarity method that reaches further tops out at precision 0.54. Half its clusters |
| 238 | + would be wrong, in an unknown direction, behind a causal claim. |
| 239 | +3. Within-cluster cost noise (CV 0.7–1.2) puts the ±47% detection floor right at the ~50% effect size. |
| 240 | +4. Every apparently-significant delta is explained by model routing; controlling for it leaves the |
| 241 | + known-positive project at null. |
| 242 | + |
| 243 | +Shipping a session-level relearn rework on this basis would produce **confident nonsense**, which is |
| 244 | +worse than $46.26. The session-inflation hypothesis is not refuted — it is **unfalsifiable with |
| 245 | +current instrumentation**. |
| 246 | + |
| 247 | +## What this does to the write-budget verdict |
| 248 | + |
| 249 | +The write budget suppresses a proposed rule when its modelled standing cost exceeds its modelled |
| 250 | +gross saving — recorded as net-negative for 18 of 25 clusters, 6–24× underwater. The hope was that a |
| 251 | +measured before/after would either validate or overturn that model. |
| 252 | + |
| 253 | +**It does neither, and that is the honest status.** The measurement that could adjudicate it is not |
| 254 | +obtainable here. Concretely: |
| 255 | + |
| 256 | +- **Not overturned.** There is no measured evidence that codification saves more than the model |
| 257 | + credits it for. In the one project where a saving was expected, the measured result is null. |
| 258 | +- **Not validated.** The model's blind spot is real and unaddressed: it counts what a rule costs to |
| 259 | + carry and never counts what it saves by preventing a flail. This measurement does not fill that |
| 260 | + gap; it shows the gap cannot be filled by observation alone at present. |
| 261 | +- **Practical consequence:** keep the current suppression rule, and stop describing it as |
| 262 | + empirically settled in either direction. It is a model, and it remains one. |
| 263 | + |
| 264 | +## What would make this measurable |
| 265 | + |
| 266 | +Not more analysis of this corpus — different instrumentation. In rough order of value: |
| 267 | + |
| 268 | +1. **Persist the task statement at ingest.** A normalized, masked task-statement hash written to the |
| 269 | + session row at ingest survives transcript rotation and would extend the high-confidence clusterer |
| 270 | + backwards indefinitely. This is the single highest-value change and it is cheap. |
| 271 | +2. **Stamp the codification event on the session.** Sessions already resolve a project `cwd`; |
| 272 | + recording which CLAUDE.md/learnings.md revision was in effect turns the before/after from a |
| 273 | + date-join into an exact attribute, and handles drip-fed codification correctly. |
| 274 | +3. **Record the routed model on the session row.** The confound that dominated every result here has |
| 275 | + to be a first-class control, not something reconstructed from span aggregation. |
| 276 | +4. **Only then** revisit the session-level unit, on repeat clusters that straddle a *specific* |
| 277 | + lesson rather than a project-wide commit stream. |
| 278 | + |
| 279 | +Until at least (1) and (3) exist, `relearn` should keep pricing failure episodes. The $46.26 is |
| 280 | +small, but it is *measured*, and the alternative on offer is not. |
0 commit comments