trusty-mpm 1.8.2

trusty-mpm: unified multi-agent orchestration platform (core, daemon, CLI, TUI, Telegram)
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
//! Tests for the instruction-compression producer's side files (#7245).
//!
//! Why: both files exist to survive a process boundary, so the properties worth
//! asserting are the ones a single-process implementation would get wrong — a
//! staged row that emits twice, a hook that writes a row nobody staged, and a
//! decline line that repeats on every launch until an operator stops reading
//! it.
//! What: drives the staging, claiming and decline-logging functions against
//! temp directories, with the decline's level and text read back off a real
//! subscriber rather than assumed.
//! Test: this file.

use super::*;

use std::sync::{Arc, Mutex};

/// A row with a known, foldable measurement.
///
/// Why: every emit assertion below turns on the row surviving the round trip
/// intact, so the figures are hand-set rather than measured.
/// What: `session_id` is the compile-time placeholder the emit path replaces.
fn staged_row(session_id: &str) -> SavingsRow {
    SavingsRow {
        ts: "2026-09-09T00:00:00Z".to_string(),
        session_id: session_id.to_string(),
        technique: crate::core::savings::TECHNIQUE_INSTRUCTION_COMPRESSION.to_string(),
        tokens_saved: 600,
        tokens_before: 6_800,
        cost_saved_usd: 0.0018,
        basis: "hand-built".to_string(),
        model_source: crate::core::session_model::MODEL_SOURCE_LAUNCH_CONFIG.to_string(),
    }
}

/// How many rows the ledger holds.
fn rows_in(ledger: &Path) -> usize {
    std::fs::read_to_string(ledger)
        .map(|text| text.lines().filter(|line| !line.trim().is_empty()).count())
        .unwrap_or(0)
}

/// Why (#7245): the compiling process cannot key the row, so the whole fix is
/// this hand-off — the first hook invocation appends it under the id the
/// statusline folds by, and a second invocation must not append it again.
/// Test: itself.
#[test]
fn a_staged_row_emits_once_under_the_claude_session_id() {
    let root = tempfile::tempdir().expect("temp root");
    let compiled = root
        .path()
        .join("project/.trusty-mpm/sessions/m1/INSTRUCTIONS-COMPILED.md");
    let ledger = root.path().join("ledger.jsonl");

    stage_row(root.path(), &compiled, &staged_row("m1"));
    assert!(
        pending_row_path_in(root.path(), &compiled).exists(),
        "the compiling process must leave a staged row behind"
    );

    assert!(
        emit_staged_row(&ledger, root.path(), &compiled, "c1"),
        "the first hook invocation must append the staged row"
    );
    assert!(
        !crate::core::savings::fold_session(&ledger, "c1").is_zero(),
        "the statusline fold under the Claude session id must find the row"
    );
    assert!(
        crate::core::savings::fold_session(&ledger, "m1").is_zero(),
        "nothing may stay attributed to the compile-time id"
    );

    assert!(
        !emit_staged_row(&ledger, root.path(), &compiled, "c1"),
        "a second hook invocation must append nothing"
    );
    assert_eq!(
        rows_in(&ledger),
        1,
        "the staged row must reach the ledger exactly once"
    );
}

/// Why (#7245): the hook runs on every session start, and almost none of those
/// sessions have a staged row waiting. Writing anything in that case would put a
/// fabricated figure on the status bar.
/// Test: itself.
#[test]
fn emitting_without_a_staged_row_writes_nothing() {
    let root = tempfile::tempdir().expect("temp root");
    let compiled = root
        .path()
        .join("project/.trusty-mpm/sessions/m1/INSTRUCTIONS-COMPILED.md");
    let ledger = root.path().join("ledger.jsonl");

    assert!(
        !emit_staged_row(&ledger, root.path(), &compiled, "c1"),
        "with nothing staged the hook must report no append"
    );
    assert!(
        !ledger.exists(),
        "with nothing staged the hook must not create the ledger"
    );
}

/// Why (#7245): Claude Code sends an empty `session_id` before a session has
/// one. Claiming the staged row against that would consume it and key the row by
/// nothing, losing the measurement for the session that actually needs it.
/// Test: itself.
#[test]
fn emitting_without_a_session_id_leaves_the_row_staged() {
    let root = tempfile::tempdir().expect("temp root");
    let compiled = root
        .path()
        .join("project/.trusty-mpm/sessions/m1/INSTRUCTIONS-COMPILED.md");
    let ledger = root.path().join("ledger.jsonl");

    stage_row(root.path(), &compiled, &staged_row("m1"));
    assert!(!emit_staged_row(&ledger, root.path(), &compiled, "   "));
    assert!(
        pending_row_path_in(root.path(), &compiled).exists(),
        "a blank session id must leave the staged row for the next hook"
    );

    assert!(emit_staged_row(&ledger, root.path(), &compiled, "c1"));
    assert_eq!(rows_in(&ledger), 1);
}

/// Why (#7245): the claim and the append are two steps, and the second one can
/// fail on its own — an unwritable ledger, a full disk, a path component that is
/// a file. A claim that consumed the staged file before knowing the append
/// landed would destroy the only copy of the measurement. Exactly-once has to
/// mean "at most one row AND no lost row".
/// What: makes the ledger's parent component a regular file, so `append_row`'s
/// `create_dir_all` fails after the claim, then retries against a writable
/// ledger.
/// Test: itself.
#[test]
fn a_failed_append_leaves_the_row_staged_for_the_next_hook() {
    let root = tempfile::tempdir().expect("temp root");
    let compiled = root
        .path()
        .join("project/.trusty-mpm/sessions/m1/INSTRUCTIONS-COMPILED.md");

    let blocker = root.path().join("blocker");
    std::fs::write(&blocker, b"a regular file, not a directory").expect("write blocker");
    let unwritable = blocker.join("ledger.jsonl");

    stage_row(root.path(), &compiled, &staged_row("m1"));
    assert!(
        !emit_staged_row(&unwritable, root.path(), &compiled, "c1"),
        "an append that fails must report no append"
    );
    assert!(
        pending_row_path_in(root.path(), &compiled).exists(),
        "a failed append must return the row to its staging path for the next hook"
    );

    let ledger = root.path().join("ledger.jsonl");
    assert!(
        emit_staged_row(&ledger, root.path(), &compiled, "c1"),
        "the retry against a writable ledger must append the recovered row"
    );
    assert_eq!(
        rows_in(&ledger),
        1,
        "the recovered row must reach the ledger exactly once"
    );
    assert!(
        !crate::core::savings::fold_session(&ledger, "c1").is_zero(),
        "the recovered row must fold under the Claude session id"
    );
}

/// Why (#7245): `tm hook` fires on several events, and two of them can overlap.
/// The claim is what decides the race, so drive it from two threads at once
/// rather than trusting the single-threaded ordering above.
/// What: two threads call `emit_staged_row` against one staged file; exactly one
/// may report an append, and the ledger holds one row.
/// Test: itself.
#[test]
fn two_racing_claims_append_exactly_one_row() {
    let root = tempfile::tempdir().expect("temp root");
    let compiled = root
        .path()
        .join("project/.trusty-mpm/sessions/m1/INSTRUCTIONS-COMPILED.md");
    let ledger = root.path().join("ledger.jsonl");

    stage_row(root.path(), &compiled, &staged_row("m1"));

    let racers: Vec<_> = (0..2)
        .map(|_| {
            let ledger = ledger.clone();
            let root = root.path().to_path_buf();
            let compiled = compiled.clone();
            std::thread::spawn(move || emit_staged_row(&ledger, &root, &compiled, "c1"))
        })
        .collect();
    let appended = racers
        .into_iter()
        .map(|racer| racer.join().expect("racer thread"))
        .filter(|appended| *appended)
        .count();

    assert_eq!(appended, 1, "exactly one racer may claim the staged row");
    assert_eq!(
        rows_in(&ledger),
        1,
        "two racing hooks must leave exactly one row"
    );
}

/// Why (#7245): two projects' unmanaged launches share the single `local`
/// session scope, so a file named after the scope would let one project's hook
/// claim the other's row. The compiled prompt's full path is what separates
/// them.
/// Test: itself.
#[test]
fn two_compiled_prompts_stage_to_different_files() {
    let root = tempfile::tempdir().expect("temp root");
    let left = root
        .path()
        .join("alpha/.trusty-mpm/sessions/local/INSTRUCTIONS-COMPILED.md");
    let right = root
        .path()
        .join("beta/.trusty-mpm/sessions/local/INSTRUCTIONS-COMPILED.md");

    assert_ne!(
        pending_row_path_in(root.path(), &left),
        pending_row_path_in(root.path(), &right),
        "two projects on the `local` scope must not share a staging file"
    );
}

/// Why (#7411): the staging file's name is a one-way digest, so a hook that
/// derives a different compiled-prompt path than the compile did cannot tell
/// what the file is for, whether its prompt still exists, or whose project it
/// belongs to. That is why rows staged under a managed session scope sat
/// unclaimed forever. The path has to be IN the file — and the file has to stay
/// readable as a bare row, so nothing that reads it that way breaks.
/// Test: itself.
#[test]
fn a_staged_row_remembers_its_compiled_prompt() {
    let root = tempfile::tempdir().expect("temp root");
    let compiled = root
        .path()
        .join("project/.trusty-mpm/sessions/m1/INSTRUCTIONS-COMPILED.md");

    stage_row(root.path(), &compiled, &staged_row("m1"));

    let text = std::fs::read_to_string(pending_row_path_in(root.path(), &compiled))
        .expect("the staged file must be readable");
    let parsed: serde_json::Value =
        serde_json::from_str(&text).expect("the staged file must be one JSON object");
    assert_eq!(
        parsed.get("compiled_prompt").and_then(|v| v.as_str()),
        Some(compiled.to_string_lossy().as_ref()),
        "the staged row must name the compiled prompt it measures: {text}"
    );
    let row: SavingsRow =
        serde_json::from_str(&text).expect("a staged file must still read back as a bare row");
    assert_eq!(row.tokens_saved, 600, "the measurement must survive intact");
}

/// Why (#7245): the decline is permanent for a project that overrides no
/// instruction section, so a line on every launch is one an operator stops
/// reading. It is logged once and then quiet.
/// Test: itself.
#[test]
fn the_no_fold_note_fires_once_per_project() {
    let root = tempfile::tempdir().expect("temp root");
    let project = root.path().join("project");

    assert!(
        log_no_fold_once(root.path(), &project, 26_741, 29_074),
        "the first decline must log"
    );
    assert!(
        !log_no_fold_once(root.path(), &project, 26_741, 29_074),
        "a second compile with the same figures must stay quiet"
    );
}

/// Why (#7245): a project whose instruction sources changed produced a new
/// measurement, and the stamp must not suppress it.
/// Test: itself.
#[test]
fn the_no_fold_note_fires_again_when_the_byte_pair_moves() {
    let root = tempfile::tempdir().expect("temp root");
    let project = root.path().join("project");

    assert!(log_no_fold_once(root.path(), &project, 26_741, 29_074));
    assert!(
        log_no_fold_once(root.path(), &project, 26_741, 28_000),
        "a changed byte pair must log again"
    );
}

/// Collects a subscriber's output so a test can read back what was logged.
///
/// Why: `log_no_fold_once`'s contract is the LEVEL as much as the count — since
/// #7867 this decline is an ordinary state and must NOT reach an operator's WARN
/// stream. Asserting the return value alone would not catch a regression to
/// `warn!`.
/// What: an `io::Write` over a shared buffer, and the `MakeWriter` that hands it
/// to `tracing_subscriber::fmt`.
#[derive(Clone, Default)]
struct CaptureWriter(Arc<Mutex<Vec<u8>>>);

impl std::io::Write for CaptureWriter {
    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
        self.0.lock().expect("capture lock").extend_from_slice(buf);
        Ok(buf.len())
    }

    fn flush(&mut self) -> std::io::Result<()> {
        Ok(())
    }
}

impl<'a> tracing_subscriber::fmt::MakeWriter<'a> for CaptureWriter {
    type Writer = CaptureWriter;

    fn make_writer(&'a self) -> Self::Writer {
        self.clone()
    }
}

/// Why (#7867): a project that overrides no bundled section folds nothing, and
/// that is the ordinary state rather than a fault — the ruling demotes this line
/// out of the operator's WARN stream. A subscriber capped at WARN must therefore
/// capture nothing at all, and the same run at DEBUG must still carry one line
/// with both byte counts.
/// What: runs the decline twice under each level and reads the captured text
/// back off a real subscriber.
/// Test: itself.
#[test]
fn the_no_fold_note_is_emitted_at_debug_level() {
    let root = tempfile::tempdir().expect("temp root");
    let project = root.path().join("project");

    let at_warn = CaptureWriter::default();
    let subscriber = tracing_subscriber::fmt()
        .with_writer(at_warn.clone())
        .with_max_level(tracing::Level::WARN)
        .with_ansi(false)
        .finish();
    tracing::subscriber::with_default(subscriber, || {
        log_no_fold_once(root.path(), &project, 26_741, 29_074);
    });
    let warned = String::from_utf8(at_warn.0.lock().expect("capture lock").clone())
        .expect("the captured log must be utf-8");
    assert!(
        warned.is_empty(),
        "the decline must not reach an operator's WARN stream: {warned}"
    );

    let at_debug = CaptureWriter::default();
    let subscriber = tracing_subscriber::fmt()
        .with_writer(at_debug.clone())
        .with_max_level(tracing::Level::DEBUG)
        .with_ansi(false)
        .finish();
    tracing::subscriber::with_default(subscriber, || {
        log_no_fold_once(root.path(), &project, 26_741, 28_000);
        log_no_fold_once(root.path(), &project, 26_741, 28_000);
    });

    let logged = String::from_utf8(at_debug.0.lock().expect("capture lock").clone())
        .expect("the captured log must be utf-8");
    assert_eq!(
        logged
            .matches("not smaller than the instruction sources")
            .count(),
        1,
        "two compiles must produce exactly one line: {logged}"
    );
    assert!(
        logged.contains("26741") && logged.contains("28000"),
        "the line must name both byte counts: {logged}"
    );
}

/// Why (#7867): the line used to tell an operator this project "contributes
/// nothing to the 💸 statusline segment" and to advise a CLAUDE.md section
/// override. The segment measures tool-output compression now, so the first
/// half is about a surface this decline no longer touches and the second half
/// prescribes an edit for a figure it would not move.
/// What: captures the line at DEBUG and rejects both the segment reference and
/// the override advice, then pins what remains — the measurement itself.
/// Test: itself.
#[test]
fn the_no_fold_note_names_neither_the_segment_nor_an_override() {
    let root = tempfile::tempdir().expect("temp root");
    let project = root.path().join("project");
    let capture = CaptureWriter::default();

    let subscriber = tracing_subscriber::fmt()
        .with_writer(capture.clone())
        .with_max_level(tracing::Level::DEBUG)
        .with_ansi(false)
        .finish();
    tracing::subscriber::with_default(subscriber, || {
        log_no_fold_once(root.path(), &project, 26_741, 29_074);
    });

    let logged = String::from_utf8(capture.0.lock().expect("capture lock").clone())
        .expect("the captured log must be utf-8");
    for banned in [
        "\u{1f4b8}",
        "statusline segment",
        "CLAUDE.md",
        "override",
        "divert",
    ] {
        assert!(
            !logged.contains(banned),
            "the line must state only the measurement, but says {banned:?}: {logged}"
        );
    }
    assert!(
        logged.contains("no instruction-fold savings row is written"),
        "the line must still say what it declined to write: {logged}"
    );
}