1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
//! The instruction/language-compression savings producer (#6958).
//!
//! Why: the owner asked to see what "language compression" is worth. The one
//! place trusty-mpm folds instruction prose is the composer that writes
//! `INSTRUCTIONS-COMPILED.md`, so that is where the number is available: it
//! knows every candidate instruction body it read and the exact bytes it
//! delivered. Measuring there — rather than against a dated constant recorded
//! by hand — means the figure re-derives itself when the instruction corpus
//! changes, and it goes to zero honestly when nothing was folded.
//!
//! What: `record_instruction_compression_in_with`, called from
//! [`crate::core::instruction_pipeline::write_compiled_prompt_recording_in`].
//! #7514 split that off the bare write, which now records nothing, and made the
//! ledger's root a parameter rather than a read of the process home directory —
//! each launch path resolves the ambient root once, in its own named wrapper.
//! It compares the folded source set against the
//! delivered prompt and appends one [`crate::core::savings::SavingsRow`] per
//! session launch when, and only when, the delivered prompt is smaller.
//!
//! **What counts as "folded".** The source set is every instruction body the
//! composer READ for this session: the ten bundled section sources, each
//! named-section override body it read from the project's `CLAUDE.md`, and the
//! UNDEDUPED agent roster. Each is a candidate; only part of each reaches the
//! output, so the delta is what the composer folded away.
//!
//! **The roster is source, not just output (#7616).** Until #7616 the roster was
//! counted only on the delivered side, on the reasoning that generated context
//! "has no source file behind it" — which made `compiled >= sources` permanent
//! for a project that overrides nothing, and the field measurement was 26,810 B
//! of sources against a 26,695 B prompt (0.4%). That reasoning was wrong twice
//! over. The roster generator resolves the FULL deployed inventory and delivers
//! only the entries the harness's own `Available agent types` listing omits
//! (#4513), so the dropped entries are read-and-discarded exactly as an
//! overridden section body is. And the composer now performs a real fold on the
//! authored prose as well ([`crate::core::instruction_fold`]), which it did not
//! before. The detected stack profile still has no larger source behind it and
//! is still counted only where it lands. A savings figure has to be able to come
//! out zero, or it is not a measurement — and it still does, on a machine with
//! no roster and a corpus with nothing to fold.
//!
//! Everything here is best-effort: an unresolvable session id, an unpriceable
//! model, or an unwritable ledger each skip the row. A missing savings row must
//! never cost a session its launch.
//!
//! **Which session a row is keyed by (#7209, corrected by #7245).** The
//! compiled prompt lives at
//! `<harness-root>/.trusty-mpm/sessions/<scope>/INSTRUCTIONS-COMPILED.md`,
//! where `<scope>` is [`crate::core::harness_root::session_scope`] — the
//! managed session id, or `local`. The `💸` statusline segment folds this
//! ledger by the id Claude Code sends it on stdin, which is
//! [`crate::core::savings::CLAUDE_CODE_SESSION_ID_ENV`] and is a different
//! value.
//!
//! #7209 keyed the row by that variable when it is set. It never is here: this
//! producer runs in the `tm` process that compiles the prompt, before `claude`
//! is spawned, and Claude Code exports the variable into its own children only.
//! Every row therefore fell back to the directory name, which is the one key the
//! statusline cannot match. So since #7245 the fallback does not write a row at
//! all — it STAGES it through [`crate::core::savings_sidecar::stage_row`], and
//! the first `tm hook` invocation (which runs inside Claude Code and knows the
//! id) appends it. The directory location is unchanged: one compiled prompt per
//! managed session is what that path is for.
//!
//! **The decline that zeroes this technique (#7245, narrowed by #7617).** When
//! the compiled prompt is not smaller than its sources there is nothing to
//! record, and for a project that overrides no instruction section that is
//! permanently true — the composer ADDS generated context and folds nothing
//! away. #7245 raised that decline to a per-launch `warn!`; #7867 put it back
//! at `debug!` — [`crate::core::savings_sidecar::log_no_fold_once`], naming both
//! byte counts once per project. The decline touches the `💸` segment not at
//! all: since #7867 that segment folds `compress` and `divert` rows only. `tm
//! doctor`'s `instruction_fold` row is where an operator reads this state.
//!
//! Test: the inline suite in `savings_instructions_tests.rs` —
//! `no_row_when_the_compiled_prompt_is_not_smaller`,
//! `a_folded_source_set_produces_a_row`, `no_row_when_the_model_cannot_be_priced`,
//! `folded_source_bytes_adds_an_override_body`,
//! `the_row_is_keyed_by_the_claude_session_id`,
//! `no_claude_id_stages_the_row_instead_of_writing_an_unfoldable_one`,
//! `a_staged_row_becomes_foldable_at_the_first_hook_invocation`,
//! `a_prompt_that_folds_nothing_warns_once_and_writes_no_row`,
//! `the_row_reports_the_compiled_prompts_own_size`,
//! `a_stub_compiled_prompt_writes_no_row`.
//!
//! **The implausibly small compiled prompt (#7491).** `compiled < sources` was
//! the producer's only plausibility test, and a stub, a truncated write, or a
//! stale file at the compiled-prompt path passes it trivially — the owner's
//! ledger carried `sources 22559 B - compiled 13 B`, a claimed ~100% reduction
//! that inflated the `💸` percentage for as long as the append-only ledger kept
//! it. [`min_plausible_compiled_bytes`] is now the floor, and a file below it
//! declines the row with a `warn!` naming the path and both byte counts.
use Path;
use crate;
use crateCOMPILED_PROMPT_FILE;
use crate;
use crate;
/// The PM section sources' byte figures a fold is measured against (#9012).
///
/// Why: the sections are runtime content, so the sizes come from the content
/// source the prompt was composed from, not from compiled-in constants.
/// What: `total` — every canonical section file's length summed; `min` — the
/// smallest one, the floor below which a compiled prompt cannot be an
/// assembly of them.
/// Test: `folded_source_bytes_counts_the_bundled_sections`.
pub
/// Append one `instruction-compression` row for a session whose compiled prompt
/// came out smaller than the sources that fed it.
///
/// Why: called from the compiled-prompt writer's recording entry points so every
/// launch path — fresh start, daemon resume, in-place relaunch — records the same
/// way without each one growing its own call. #7514 removed the ambient
/// `record_instruction_compression` that resolved `framework_root` from the
/// process home directory: every caller reachable from a test wrote into the
/// operator's own ledger through it. Each launch path now resolves the ambient
/// root once, in its own named wrapper, and passes it down. #7746 split the
/// roster resolver out too: the ambient one reads process-global
/// `$CLAUDE_CONFIG_DIR`/`$HOME`, which raced a concurrently running
/// `RosterTiers`-guarded test mutating either variable between a caller's own
/// read of [`ambient_source_bytes`] and this function's internal
/// recomputation of the same number. Callers that need a deterministic count
/// instead — today, only the regression test — supply `roster_source`
/// directly;
/// [`crate::core::instruction_pipeline::write_compiled_prompt_recording_in`]
/// passes [`ambient_roster_source_bytes`], unchanged from before the split.
/// What: reads the Claude Code session id the statusline folds by, then defers to
/// [`record_instruction_compression_to`] against `framework_root`, with
/// `roster_source` supplied by the caller.
/// Test: `a_bare_compiled_write_records_no_savings_row`,
/// `a_recording_compiled_write_reaches_the_named_framework_root`.
pub
/// Bytes of the roster the composer read, before the #4513 dedup dropped every
/// agent the harness publishes itself.
///
/// Why (#7616): this is the half of the fold that was attributed to neither
/// side. The composer resolves the full deployed-agent inventory and delivers
/// only the entries the harness's own `Available agent types` listing omits, so
/// the dropped entries are read-and-discarded source in exactly the sense an
/// overridden section body is — and counting them only on the delivered side is
/// what made `compiled >= sources` permanent for a project with no override.
/// What: renders the UNDEDUPED roster for `project_dir`'s tiers and returns its
/// length; `0` when no agent is deployed anywhere, which is honest — a machine
/// with no roster folds no roster.
/// Test: `the_roster_dedup_counts_as_folded_source` (the arithmetic),
/// `roster_source_bytes_are_zero_without_a_roster` (the tier seam).
///
/// `pub(crate)` since #7746:
/// [`crate::core::instruction_pipeline::write_compiled_prompt_recording_in`]
/// names it as the default `roster_source` argument to
/// [`record_instruction_compression_in_with`].
pub
/// [`ambient_roster_source_bytes`] against an explicit tier list.
///
/// Why (#7616): the ambient entry point resolves `$CLAUDE_CONFIG_DIR` and the
/// caller's home directory, so on a provisioned machine it can never return `0`
/// and the "no roster folds no roster" branch is untestable through it. Taking
/// the tiers is the seam that makes that branch assertable without mutating
/// process-global state, the same shape `delegation_authority` already uses for
/// `roster_section_from_dirs`.
/// What: the length of the UNDEDUPED roster render for `dirs`, or `0` when no
/// agent is deployed in any of them.
/// Test: `roster_source_bytes_are_zero_without_a_roster`.
// #8019: the entry point this names was renamed by #7514/#7584; the link
// still pointed at the pre-split `record_instruction_compression_in`.
/// [`record_instruction_compression_in_with`] against an explicit framework
/// root, session id and price.
///
/// Why: the three ambient reads the entry point makes — the framework root under
/// the operator's home, the harness's session-id variable, and the configured
/// PM model — are exactly what makes the keying decision untestable in place.
/// Passing all three in keeps the test on a tempdir root with no process-env
/// mutation, which the `tm` binary's env ratchet (#5544) and parallel test
/// binaries both require. `framework_root` rather than a ledger path because
/// #7245 gave this function a second destination under that root: the staging
/// file, which has to land beside the ledger the hook will later append to.
/// What: derives the compile-time session id and the harness root from `dest`
/// (which is always
/// `<harness-root>/.trusty-mpm/sessions/<id>/INSTRUCTIONS-COMPILED.md`),
/// measures the fold, prices the token delta, and then either appends the row —
/// when `claude_session_id` gives it the key the statusline folds by — or stages
/// it for the first `tm hook` invocation, which is the first process that knows
/// that key. A prompt that folded nothing warns once per project and writes
/// nothing. Silent no-op on every other failure.
/// Test: `the_row_is_keyed_by_the_claude_session_id`,
/// `no_claude_id_stages_the_row_instead_of_writing_an_unfoldable_one`,
/// `a_prompt_that_folds_nothing_warns_once_and_writes_no_row`.
/// Re-measure the fold from a compiled prompt already on disk and append the
/// row under a known Claude session id.
///
/// Why (#7411): staging is the only way this producer's row reaches the ledger
/// for a normal launch, so a staged file that is lost — an unwritable
/// `pending-savings/`, a compile whose row was discarded, a `tm` upgraded
/// between the compile and the hook — leaves the session with no row at all and
/// the `💸` segment blank for the rest of it. The compiled prompt itself
/// survives on disk, and it is the same input the producer measured, so the
/// hook can redo the measurement instead of inventing a second staging
/// mechanism to protect the first.
/// What: reads `compiled_prompt`, then runs the ordinary producer against it
/// with `claude_session_id` supplied, which makes it append rather than stage.
/// Reports whether a row landed, read back off the ledger — the producer
/// declines silently for an unpriceable model or a prompt that folded nothing,
/// and a caller must not report those as a row. Callers guard against the
/// double-append themselves with [`crate::core::savings::has_row`].
/// Test: `rederiving_from_the_compiled_prompt_appends_under_the_session_id`,
/// `rederiving_a_prompt_that_folds_nothing_appends_nothing`.
pub
/// Split `<harness-root>/.trusty-mpm/sessions/<id>/INSTRUCTIONS-COMPILED.md`
/// into its session id and its harness root.
///
/// Why: the writer takes only a destination path, and the harness root the
/// source set is measured against is encoded in it. Deriving it here rather
/// than widening the writer's signature keeps the three launch call sites
/// unchanged.
/// What: the session id is the parent directory's name — the FALLBACK key since
/// #7209, used only when the harness exported no Claude Code session id; the
/// harness root is three directories above that (`sessions/`, `.trusty-mpm/`,
/// the root).
/// Returns `None` for any path not of that shape.
///
/// #7514: it now CHECKS that shape. It used to take the parent as a session id
/// and count three directories up for the root without looking at what those
/// directories were called, so `<tmp>/a/b/INSTRUCTIONS-COMPILED.md` resolved to
/// session `b` under root `<tmp>` — which is exactly the
/// `session_id":"b" … compiled 13 B` row the owner's ledger carried, produced by
/// this crate's own `write_compiled_prompt_to_creates_parent_dirs` fixture. A
/// path that is not a compiled prompt now declines, so no row can be attributed
/// to a directory that is not a session.
/// Test: `session_and_root_reads_the_compiled_prompt_path`,
/// `session_and_root_rejects_a_short_path`,
/// `session_and_root_rejects_a_path_that_is_not_under_sessions`,
/// `a_malformed_compiled_prompt_path_records_no_row`.
/// Total bytes of every instruction body the composer read for this project.
///
/// Why: see the module header — this is the "before" half of the fold, and it
/// has to include the override bodies as well as the bundled sections, because
/// an override is a source the composer read and (partly) discarded.
/// What: the ten bundled section sources, every accepted named-section
/// override body found in the project's `CLAUDE.md`, and `roster_source_bytes`
/// — the UNDEDUPED roster render (#7616). Rejected override blocks are excluded:
/// the composer did not fold them, it declined them.
/// Test: `folded_source_bytes_counts_the_bundled_sections`,
/// `folded_source_bytes_adds_an_override_body`,
/// `the_roster_dedup_counts_as_folded_source`.
/// What the fold actually achieved for `project_dir`, last time it ran.
///
/// Why (#7616): the decline branch is silent by design — it warns once per
/// project into the daemon log and writes no ledger row — so an operator seeing
/// no `💸` segment had nowhere to look for the reason. `tm doctor` is the
/// surface that answers "is this working", and it had no compression check at
/// all. This is the measurement behind that check, taken from the same inputs
/// the producer uses so the two can never report different numbers.
/// What: `(source_bytes, compiled_bytes)` for the most recently written compiled
/// prompt under `<project>/.trusty-mpm/sessions/`, or `None` when no session has
/// compiled one yet. The source side is [`folded_source_bytes`] with this
/// machine's roster, exactly as at launch.
/// Test: `the_fold_measurement_is_none_before_any_session_compiles`,
/// `the_fold_measurement_reads_the_newest_compiled_prompt`.
pub
/// [`folded_source_bytes`] with this machine's roster resolved.
///
/// Why (#7616): three callers need the same number — the doctor check, and two
/// tests that must build a fixture prompt provably ABOVE the source set to
/// exercise the decline branch. Before the roster joined the source side they
/// could sum [`crate::core::instruction_pipeline::SECTION_SOURCES`] themselves;
/// now that would undercount and the fixture would land on the wrong branch.
/// What: the bundled sections, the project's override bodies, and the undeduped
/// roster for `project_dir`'s tiers.
/// Test: `the_fold_measurement_reads_the_newest_compiled_prompt`.
pub
/// [`ambient_source_bytes`] with an explicit roster-byte resolver (the test
/// seam, #7746) — mirrors [`record_instruction_compression_in_with`] so a
/// test can compute the SAME number the recording write will, with neither
/// call depending on `$CLAUDE_CONFIG_DIR`/`$HOME`.
/// Test: `a_recording_compiled_write_reaches_the_named_framework_root`.
pub
/// The smallest byte count a real compiled PM prompt can have.
///
/// Why (#7491): the ledger recorded `sources 22559 B - compiled 13 B` — a
/// claimed ~100% reduction — because the producer's only plausibility test was
/// `compiled < sources`, which a stub, a truncated write, or a stale file at the
/// compiled-prompt path passes trivially. The ledger is append-only, so one such
/// row inflates the `💸` percentage for as long as it is folded.
/// What: the smallest single bundled instruction section. The compiled prompt is
/// an assembly of those sections (with overrides substituted for some of them),
/// so anything below one whole section cannot be such an assembly. Derived from
/// the corpus rather than spelled as a constant, so it re-derives when the
/// sections change.
/// Test: `a_stub_compiled_prompt_writes_no_row`,
/// `the_row_reports_the_compiled_prompts_own_size`.
pub
/// Build the row, or decline to.
///
/// Why: separating the arithmetic and every decline condition from the IO is
/// what makes "writes no row when the compiled output is not smaller" a unit
/// test rather than a filesystem assertion.
/// What: returns `None` when the compiled output is not strictly smaller, when
/// the byte delta rounds to no whole token, when `price` cannot price the
/// session's model, or when the resulting cost is not strictly positive.
/// `price` resolves the session's model and its USD-per-million input rate.
/// Test: `no_row_when_the_compiled_prompt_is_not_smaller`,
/// `no_row_when_the_model_cannot_be_priced`,
/// `instruction_compression_tokens_use_the_shared_divisor`.
/// Resolve the session's PM model and its input price.
///
/// Why: the price table is `trusty_common::inference::pricing` — the
/// most complete of the workspace's three and the one the epic already names as
/// the consolidation target. This feature adds no fourth table, and it prices
/// nothing it cannot look up: an unrecognised model slug declines the row
/// rather than substituting a guessed rate.
/// What: resolves the PM model through the same `resolve_pm_model` chain the
/// launcher uses, then returns `(slug, input USD per million tokens)`, or `None`
/// when the table does not know the family.
/// Test: `resolve_pm_price_agrees_with_the_shared_table`.