ktstr 0.4.12

Test harness for Linux process schedulers
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
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
1129
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
1292
1293
1294
1295
1296
1297
1298
1299
1300
1301
1302
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
//! Metric extraction pipeline for payload outputs.
//!
//! Payloads declared with [`OutputFormat::Json`] emit JSON to either
//! stdout or stderr — `PayloadRun` applies a stdout-primary /
//! stderr-fallback contract and hands whichever stream produced a
//! non-empty metric set to this module. Benchmark tools split
//! across the two conventions (schbench writes structured summaries
//! to stderr, fio / stress-ng to stdout); the fallback lets either
//! discipline round-trip through the same extractor. This module
//! locates the JSON document region inside mixed text output
//! (many tools emit a banner line before their structured body) and
//! walks numeric leaves into [`Metric`]s keyed by dotted paths.
//!
//! [`OutputFormat::ExitCode`] returns an empty metric set; exit-code
//! pass/fail is handled by the [`Check::ExitCodeEq`] pre-pass
//! elsewhere.
//!
//! [`OutputFormat::LlmExtract`] is HOST-ONLY. The guest-side
//! `extract_metrics` short-circuits the LlmExtract arm to an empty
//! metric set so the guest never loads the ~2.4 GiB local model into
//! its constrained VM RAM. The captured raw stdout/stderr are shipped
//! over the SHM ring as a `MSG_TYPE_RAW_PAYLOAD_OUTPUT` entry; the
//! host's `eval.rs` post-VM-exit pipeline calls
//! [`crate::test_support::model::extract_via_llm`] on the captured
//! text and threads the resulting metrics back into the
//! [`PayloadMetrics`](crate::test_support::PayloadMetrics) slot the
//! guest emitted alongside.

use crate::test_support::{Metric, MetricSource, MetricStream, OutputFormat, Polarity};

/// Extract metrics from a payload's captured output per its declared
/// [`OutputFormat`].
///
/// `output` carries whichever stream `PayloadRun` decided to extract
/// from — stdout on the happy path, stderr under the stdout-primary
/// stderr-fallback contract when stdout produced an empty result.
/// The extractor itself is stream-agnostic; it parses whatever byte
/// blob it is handed.
///
/// Returns an empty `Vec` for [`OutputFormat::ExitCode`] and for
/// [`OutputFormat::Json`] when no JSON document is located or the
/// document carries no numeric leaves. JSON-parse errors are
/// non-fatal: the extraction returns `Vec::new()` so downstream
/// [`Check`](crate::test_support::Check) evaluation reports each
/// referenced metric as missing rather than failing the whole run.
///
/// [`OutputFormat::LlmExtract`] returns an empty `Vec` from this
/// function regardless of `output`. The LLM-backed extraction does
/// NOT run here: the guest does not load the 2.4 GiB model, and the
/// host runs `extract_via_llm` post-VM-exit on the raw output that
/// the guest shipped over the SHM ring. Callers that need
/// LlmExtract metrics must consume the host-extracted result through
/// the `eval.rs` pipeline. The `hint` carried on the
/// `LlmExtract(Option<&'static str>)` payload is preserved on the
/// raw-output SHM message for the host extractor to consume.
///
/// # Known truncation point: depth cap
///
/// The `Json` arm routes through [`walk_json_leaves`], which enforces
/// a hard recursion cap of [`MAX_WALK_DEPTH`] (currently 64).
/// Subtrees past that depth are silently dropped from the metric
/// list — a `tracing::warn!` fires and a sentinel metric named
/// [`WALK_TRUNCATION_SENTINEL_NAME`]
/// (`__walk_json_leaves_truncated`) is appended to the return
/// value, with `value` set to the depth at which truncation
/// occurred. Callers that want to distinguish "no deep metrics"
/// from "deep metrics dropped by the cap" scan the returned `Vec`
/// for a metric with that name. Practical upper bound: 64 is well
/// below serde_json's default parse recursion limit (128) and
/// covers every realistic payload schema observed in the crate
/// (fio maxes out around depth 8, schbench around depth 3). The same
/// cap applies to the host-side LlmExtract pipeline that runs the
/// model response through this module's walker.
pub fn extract_metrics(
    output: &str,
    format: &OutputFormat,
    stream: MetricStream,
) -> Result<Vec<Metric>, String> {
    match format {
        OutputFormat::ExitCode => Ok(Vec::new()),
        OutputFormat::Json => Ok(find_and_parse_json(output)
            .map(|v| walk_json_leaves(&v, MetricSource::Json, stream))
            .unwrap_or_default()),
        // LlmExtract is host-only — the guest captures raw text and
        // ships it across the SHM ring; the host runs
        // `extract_via_llm` post-VM-exit. Returning an empty vec here
        // is the no-op the guest's `evaluate()` short-circuits past
        // when emitting `MSG_TYPE_RAW_PAYLOAD_OUTPUT`, and is also
        // the correct value for any non-payload-pipeline caller that
        // happens to invoke `extract_metrics` against an LlmExtract
        // format on the host (e.g. unit tests for the dispatcher
        // shape) — those callers should reach for
        // `crate::test_support::model::extract_via_llm` directly when
        // they want the LLM-backed extraction.
        OutputFormat::LlmExtract(_) => Ok(Vec::new()),
    }
}

/// Locate a JSON document within mixed text output and parse it.
///
/// Many benchmark tools emit a banner line (fio, stress-ng)
/// before the structured JSON body. A strict
/// `serde_json::from_str(output)` fails for those. This helper
/// first tries the whole input; on failure, scans for the first
/// balanced `{...}` (or `[...]`) region and parses that.
///
/// Returns `None` when no JSON document is locatable or parsing
/// both candidates fails. Does NOT heuristically repair malformed
/// JSON — only brace-balancing for region extraction; serde_json
/// does the actual parse strictly.
///
/// # Multiple JSON objects in one output
///
/// When `output` contains more than one balanced top-level region
/// (e.g. `{"first": 1} noise {"second": 2}`), only the FIRST is
/// returned. The region finder scans left-to-right for the first
/// `{` or `[`, walks to its matching closer, and stops — it does
/// not merge or concatenate subsequent balanced regions. Payloads
/// that emit multiple JSON documents per run therefore lose all
/// but the first; authors needing full capture should switch the
/// payload to a wrapper that emits a single aggregate document
/// (or use `OutputFormat::LlmExtract` to consolidate prose +
/// multiple JSONs through the model pipeline).
pub(crate) fn find_and_parse_json(output: &str) -> Option<serde_json::Value> {
    // Fast path: whole input is a single JSON document.
    if let Ok(v) = serde_json::from_str::<serde_json::Value>(output.trim()) {
        return Some(v);
    }
    // Slow path: find the first balanced `{...}` or `[...]` region.
    let region = extract_json_region(output)?;
    serde_json::from_str::<serde_json::Value>(region).ok()
}

/// Find the first balanced `{...}` or `[...]` region in `s`.
///
/// Scans left-to-right for the first `{` or `[` and returns a slice
/// spanning to its matching closer, tracking nesting + escaped
/// quotes. Returns `None` if no opener found or no balanced match
/// within the input.
///
/// This is NOT a JSON parser — it's a region locator. The returned
/// slice is handed to `serde_json::from_str` for strict parsing.
/// Mismatched structures (e.g. `{...}]`) are detected there, not
/// here.
fn extract_json_region(s: &str) -> Option<&str> {
    let bytes = s.as_bytes();
    let start = bytes.iter().position(|&c| c == b'{' || c == b'[')?;
    let opener = bytes[start];
    let closer = if opener == b'{' { b'}' } else { b']' };
    let mut depth = 0i32;
    let mut in_string = false;
    let mut escape = false;
    for (i, &c) in bytes.iter().enumerate().skip(start) {
        if escape {
            escape = false;
            continue;
        }
        if in_string {
            match c {
                b'\\' => escape = true,
                b'"' => in_string = false,
                _ => {}
            }
            continue;
        }
        match c {
            b'"' => in_string = true,
            x if x == opener => depth += 1,
            x if x == closer => {
                depth -= 1;
                if depth == 0 {
                    return Some(&s[start..=i]);
                }
            }
            _ => {}
        }
    }
    None
}

/// Walk numeric leaves of a JSON value, emitting [`Metric`]s keyed
/// by dotted paths.
///
/// Objects contribute `"key.subkey"` paths; arrays contribute
/// `"key.0", "key.1"`. Numeric leaves where `as_f64()` yields a
/// finite value are emitted; String, Bool, and Null leaves are
/// skipped. NaN/infinite f64s are rejected by serde_json at parse
/// time, so natural inputs never reach this walker with non-finite
/// numbers; the defensive `is_finite()` guard catches hand-built
/// `Value` constructions.
///
/// Each [`Metric`] is emitted with [`Polarity::Unknown`] and empty
/// unit; the caller resolves these against the payload's declared
/// [`MetricHint`](crate::test_support::MetricHint)s to upgrade
/// polarity.
///
/// # Stability contract (pre-1.0)
///
/// This function, [`MAX_WALK_DEPTH`], [`WALK_TRUNCATION_SENTINEL_NAME`],
/// and [`is_truncation_sentinel_name`] together form the public
/// numeric-JSON-extraction surface ktstr offers to in-tree sibling
/// binaries (`ktstr-jemalloc-probe` is the one current external
/// consumer — see `src/bin/jemalloc_probe.rs`). Their visibility
/// is aligned at `pub` so an external consumer that wants to
/// distinguish "no deep metrics present" from "deep metrics
/// dropped by the depth cap" can reach every piece of the
/// contract from outside the crate.
///
/// ktstr is pre-1.0: the four items above are free to change in
/// signature or behaviour without a compat shim. A caller depending
/// on them must vendor the ktstr version at a known commit, not
/// track `main`. Concretely:
///
/// - Path format (`key.subkey` / `key.0`): may grow a shape
///   option to prefer arrays-by-key over positional index.
/// - Depth cap ([`MAX_WALK_DEPTH`]): may raise or lower as
///   pathological inputs are observed; consumers must not hard-code
///   the literal value.
/// - Sentinel shape: may migrate to a typed return
///   (`WalkResult { metrics, truncated: Option<u64> }`) per the
///   note on [`WALK_TRUNCATION_SENTINEL_NAME`]. Consumers that
///   need zero-collision certainty should gate on
///   [`is_truncation_sentinel_name`] (the predicate, not the
///   literal string) so a sentinel-name rewording lands in one
///   place.
pub fn walk_json_leaves(
    value: &serde_json::Value,
    source: MetricSource,
    stream: MetricStream,
) -> Vec<Metric> {
    let mut out = Vec::new();
    // Single reusable path buffer: children push their segment,
    // recurse, then truncate back. O(total_path_chars) work across
    // the whole walk instead of O(depth × path_chars) per leaf.
    let mut path = String::new();
    walk(value, &mut path, 0, source, stream, &mut out);
    out
}

/// Hard cap on recursion depth in [`walk`]. Object and array
/// children past this depth are skipped and a single
/// [`tracing::warn!`] fires. Serde_json's default parser recursion
/// limit is 128, so this caps us well below that; a hand-built
/// `serde_json::Value` that bypasses the parser can still reach
/// arbitrary depth, so an explicit walker guard is the last line of
/// defence against a stack overflow.
///
/// See [`walk_json_leaves`]'s stability contract — the concrete
/// value may change across ktstr pre-1.0 versions.
pub const MAX_WALK_DEPTH: usize = 64;

/// Sentinel metric name emitted when [`walk`] hits
/// [`MAX_WALK_DEPTH`] and skips a subtree. Callers of
/// [`walk_json_leaves`] / [`extract_metrics`] that want to
/// distinguish "no deep metrics present" from "deep metrics
/// dropped by the depth cap" scan the returned `Vec<Metric>` for
/// a metric whose `name` equals this constant — its `value` is
/// the depth at which truncation occurred, so nested failures at
/// different subtrees produce one sentinel per trigger.
///
/// # Accepted collision risk
///
/// The double-underscore prefix makes collision extremely unlikely
/// in practice, but not impossible: a benchmark whose JSON has
/// this exact literal string as a **top-level** key produces a
/// `Metric.name` indistinguishable from the cap-hit sentinel
/// (nested leaves get at least one `.` injected by `walk`, so only
/// the top-level depth-0 push can produce a name without a `.`).
/// Consumers treat the sentinel as advisory, not authoritative —
/// a caller that depends on zero-collision guarantees must reject
/// sentinel-named paths from its input schema.
///
/// A future refactor could eliminate the risk structurally by
/// widening the return type to `WalkResult { metrics: Vec<Metric>,
/// truncated: Option<u64> }` — separating the truncation signal
/// from the metric stream. Held off pending a consumer that
/// materially benefits from zero-collision certainty; the current
/// advisory contract is sufficient for every in-crate consumer.
///
/// Exported `pub` so sibling binaries that embed ktstr as a
/// library (e.g. `ktstr-jemalloc-probe`) can gate on the
/// sentinel from their own consumer code. See
/// [`walk_json_leaves`]'s stability contract — consumers
/// comparing against the sentinel should prefer
/// [`is_truncation_sentinel_name`] over the literal string so a
/// future rewording lands in one place.
pub const WALK_TRUNCATION_SENTINEL_NAME: &str = "__walk_json_leaves_truncated";

/// Predicate for "this metric name / map key is the
/// walk-truncation sentinel." Centralises the literal-equality
/// check so every consumer stays in sync when the sentinel name
/// changes, and so future sentinel variants (e.g. a
/// parser-rejection sentinel) can be threaded through one
/// predicate instead of scattered string literals.
///
/// Visibility aligned with [`walk_json_leaves`] and
/// [`WALK_TRUNCATION_SENTINEL_NAME`] so external consumers have a
/// complete sentinel-discrimination API.
pub fn is_truncation_sentinel_name(name: &str) -> bool {
    name == WALK_TRUNCATION_SENTINEL_NAME
}

fn walk(
    value: &serde_json::Value,
    path: &mut String,
    depth: usize,
    source: MetricSource,
    stream: MetricStream,
    out: &mut Vec<Metric>,
) {
    if depth > MAX_WALK_DEPTH {
        tracing::warn!(
            depth,
            max = MAX_WALK_DEPTH,
            path = %path,
            "walk_json_leaves: depth cap hit, subtree skipped",
        );
        // Emit a sentinel metric so callers inspecting only the
        // returned `Vec<Metric>` see the truncation — the
        // `tracing::warn!` above only reaches a subscriber, which
        // the default test dispatch path does not install. See
        // [`WALK_TRUNCATION_SENTINEL_NAME`] for the discrimination
        // contract.
        out.push(Metric {
            name: WALK_TRUNCATION_SENTINEL_NAME.to_string(),
            value: depth as f64,
            polarity: Polarity::Unknown,
            unit: String::new(),
            source,
            stream,
        });
        return;
    }
    match value {
        serde_json::Value::Object(map) => {
            for (k, v) in map {
                let saved_len = path.len();
                if !path.is_empty() {
                    path.push('.');
                }
                path.push_str(k);
                walk(v, path, depth + 1, source, stream, out);
                path.truncate(saved_len);
            }
        }
        serde_json::Value::Array(items) => {
            for (i, v) in items.iter().enumerate() {
                let saved_len = path.len();
                if !path.is_empty() {
                    path.push('.');
                }
                // Avoid an extra String allocation for the index
                // segment by writing directly into `path` via the
                // fmt::Write impl (infallible for String).
                use std::fmt::Write;
                let _ = write!(path, "{i}");
                walk(v, path, depth + 1, source, stream, out);
                path.truncate(saved_len);
            }
        }
        serde_json::Value::Number(n) => {
            if let Some(f) = n.as_f64()
                && f.is_finite()
            {
                // Leaf emission is the one unavoidable allocation —
                // `Metric.name` is owned. `clone()` copies exactly
                // the current path bytes, not every intermediate
                // ancestor path that `format!` used to materialize.
                out.push(Metric {
                    name: path.clone(),
                    value: f,
                    polarity: Polarity::Unknown,
                    unit: String::new(),
                    source,
                    stream,
                });
            }
        }
        // Strings/bools/null: skipped. Check::Exists can gate on
        // presence via the PayloadMetrics lookup — a missing
        // string-valued key is treated the same as a missing numeric.
        _ => {}
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn is_truncation_sentinel_name_matches_the_constant() {
        assert!(is_truncation_sentinel_name(WALK_TRUNCATION_SENTINEL_NAME));
    }

    #[test]
    fn is_truncation_sentinel_name_rejects_other_names() {
        assert!(!is_truncation_sentinel_name("foo"));
        assert!(!is_truncation_sentinel_name(""));
        // Near-miss: same prefix but not the full sentinel name.
        assert!(!is_truncation_sentinel_name("__walk_json_leaves"));
    }

    #[test]
    fn exit_code_returns_empty() {
        let m = extract_metrics("whatever", &OutputFormat::ExitCode, MetricStream::Stdout).unwrap();
        assert!(m.is_empty());
    }

    #[test]
    fn json_full_document_extracts_numeric_leaves() {
        let s = r#"{"iops": 10000, "lat_ns": 500}"#;
        let m = extract_metrics(s, &OutputFormat::Json, MetricStream::Stdout).unwrap();
        assert_eq!(m.len(), 2);
        let names: Vec<_> = m.iter().map(|x| x.name.as_str()).collect();
        assert!(names.contains(&"iops"));
        assert!(names.contains(&"lat_ns"));
        for metric in &m {
            assert_eq!(metric.source, MetricSource::Json);
            assert_eq!(metric.polarity, Polarity::Unknown);
            assert_eq!(metric.unit, "");
        }
    }

    #[test]
    fn json_with_banner_prefix_extracts_region() {
        // Fio-style: banner line then JSON body.
        let s = "fio-3.36 starting up\n{\"iops\": 500}";
        let m = extract_metrics(s, &OutputFormat::Json, MetricStream::Stdout).unwrap();
        assert_eq!(m.len(), 1);
        assert_eq!(m[0].name, "iops");
        assert_eq!(m[0].value, 500.0);
    }

    #[test]
    fn json_nested_objects_use_dotted_paths() {
        let s = r#"{"jobs": {"0": {"read": {"iops": 123}}}}"#;
        let m = extract_metrics(s, &OutputFormat::Json, MetricStream::Stdout).unwrap();
        assert_eq!(m.len(), 1);
        assert_eq!(m[0].name, "jobs.0.read.iops");
        assert_eq!(m[0].value, 123.0);
    }

    #[test]
    fn json_arrays_use_numeric_index_paths() {
        let s = r#"{"samples": [100, 200, 300]}"#;
        let m = extract_metrics(s, &OutputFormat::Json, MetricStream::Stdout).unwrap();
        assert_eq!(m.len(), 3);
        let mut actual: Vec<(&str, f64)> = m.iter().map(|x| (x.name.as_str(), x.value)).collect();
        actual.sort_by_key(|(n, _)| n.to_string());
        assert_eq!(
            actual,
            vec![
                ("samples.0", 100.0),
                ("samples.1", 200.0),
                ("samples.2", 300.0),
            ]
        );
    }

    #[test]
    fn json_malformed_returns_empty() {
        let m = extract_metrics(
            "garbage not json",
            &OutputFormat::Json,
            MetricStream::Stdout,
        )
        .unwrap();
        assert!(m.is_empty());
    }

    #[test]
    fn json_empty_stdout_returns_empty() {
        let m = extract_metrics("", &OutputFormat::Json, MetricStream::Stdout).unwrap();
        assert!(m.is_empty());
    }

    #[test]
    fn json_skips_string_and_bool_leaves() {
        let s = r#"{"name": "fio", "ok": true, "iops": 42}"#;
        let m = extract_metrics(s, &OutputFormat::Json, MetricStream::Stdout).unwrap();
        // Only iops is numeric.
        assert_eq!(m.len(), 1);
        assert_eq!(m[0].name, "iops");
    }

    #[test]
    fn json_top_level_array_extracts_entries() {
        let s = "[1, 2, 3]";
        let m = extract_metrics(s, &OutputFormat::Json, MetricStream::Stdout).unwrap();
        assert_eq!(m.len(), 3);
    }

    /// `extract_metrics` short-circuits the `OutputFormat::LlmExtract`
    /// arm to `Ok(Vec::new())` regardless of input. The LLM-backed
    /// extraction has moved host-side: the guest-facing `evaluate()`
    /// path does NOT load the 2.4 GiB model into VM RAM. Pinning this
    /// invariant here ensures a future refactor cannot reintroduce
    /// the in-VM model load by silently re-routing the LlmExtract arm
    /// back through `super::model::extract_via_llm`.
    ///
    /// Both the `None` (no-hint) and `Some(hint)` payload shapes are
    /// covered together — neither must trigger any model-side code
    /// path. If a future change splits the dispatch by hint presence,
    /// the assertion would surface the regression before it hit a
    /// guest VM.
    #[test]
    fn llm_extract_returns_empty_unconditionally() {
        // No env-var locking, no model::reset() — this test covers a
        // pure constant-return contract; if the assertion ever
        // requires environment manipulation again, the LlmExtract
        // arm has been re-wired back through `extract_via_llm` and
        // the host-only invariant has been broken.
        for (label, format) in [
            ("no-hint", OutputFormat::LlmExtract(None)),
            (
                "with-hint",
                OutputFormat::LlmExtract(Some("focus on latency")),
            ),
        ] {
            for input in [
                "",
                "anything",
                r#"{"latency_us": 42}"#,
                "schbench-shaped percentile table\n50.0%: 100ns\n",
            ] {
                let m = extract_metrics(input, &format, MetricStream::Stdout)
                    .unwrap_or_else(|e| panic!("{label}: extract_metrics returned Err: {e}"));
                assert!(
                    m.is_empty(),
                    "{label}: LlmExtract arm must short-circuit to empty Vec; \
                     got {} metric(s) for input {input:?}",
                    m.len(),
                );
            }
        }
    }

    #[test]
    fn extract_json_region_finds_braced_region() {
        let r = extract_json_region("prefix {\"a\": 1} suffix").unwrap();
        assert_eq!(r, "{\"a\": 1}");
    }

    #[test]
    fn extract_json_region_handles_nested_braces() {
        let r = extract_json_region("log: {\"a\": {\"b\": 1}} done").unwrap();
        assert_eq!(r, "{\"a\": {\"b\": 1}}");
    }

    #[test]
    fn extract_json_region_skips_braces_in_strings() {
        let r = extract_json_region(r#"{"text": "not a }"}"#).unwrap();
        assert_eq!(r, r#"{"text": "not a }"}"#);
    }

    #[test]
    fn extract_json_region_handles_escaped_quotes() {
        let r = extract_json_region(r#"{"text": "has \"escaped\" quotes"}"#).unwrap();
        assert_eq!(r, r#"{"text": "has \"escaped\" quotes"}"#);
    }

    #[test]
    fn extract_json_region_returns_none_for_no_brace() {
        assert!(extract_json_region("no braces here").is_none());
    }

    #[test]
    fn extract_json_region_returns_none_for_unbalanced() {
        assert!(extract_json_region("incomplete {").is_none());
    }

    // -- extract_json_region stderr-bracket-noise scenarios --
    //
    // Interaction coverage for the realistic payload scenario:
    // the captured stream carries stderr-style bracket noise
    // (dmesg-like `[ TIME] message` lines, stress-ng status,
    // kernel stacktraces printed with `[...]` prefixes, etc.)
    // BEFORE the actual stdout JSON document. The region finder
    // scans left-to-right and returns the FIRST balanced
    // `{...}` or `[...]` region regardless of what the outer
    // content looks like, so a leading `[   0.001234]`-shaped
    // token can in fact parse as a valid one-element JSON array
    // and masquerade as the payload's data.
    //
    // Each of the three scenarios below is isolated in its own
    // `#[test]` so an individual failure points directly at the
    // limitation that regressed, not a shared composite that
    // requires scanning the whole test body to localize. Each
    // scenario documents EXPECTED behaviour, not desired behaviour.
    //
    // If a future change adds a "skip unparseable regions and
    // keep scanning" rule, the stderr-balanced-noise scenario
    // will flip — the `[stderr bracket message]` region fails to
    // parse as JSON, so a richer extractor would advance past
    // it to the stdout `{..}`. The dmesg-timestamp scenario
    // would NOT flip under that rule alone: `[   0.001234]` IS
    // valid JSON (a single-element array), so an
    // "unparseable-skip" heuristic never triggers on it.
    // Correcting the dmesg scenario requires a stronger rule —
    // e.g. prefer regions whose shape matches the payload's
    // expected metric keys, or reject numeric-leaf-only regions
    // that lack object wrappers. Its flip is therefore the
    // correct signal that `extract_metrics` gained shape-aware
    // selection, not just unparseable-skip.

    /// Scenario 1: dmesg-style timestamp prefix
    /// `[   0.001234] kernel boot banner {"iops": 100}`.
    /// The leading bracket parses as a JSON array
    /// (`[0.001234]`). `extract_metrics` on this input returns
    /// a metric for the array's single element keyed by its
    /// positional path, NOT the stdout `{"iops": 100}`.
    /// Documents the known-limitation behaviour: callers that
    /// need robust stderr-noise rejection must pre-strip
    /// timestamped brackets before handing the blob to
    /// `extract_metrics`.
    #[test]
    fn extract_json_region_dmesg_timestamp_prefix_wins_over_stdout_json() {
        let input = "[   0.001234] kernel boot banner\n{\"iops\": 100}";
        let first_region = extract_json_region(input)
            .expect("dmesg-style prefix starts with `[` — finder must return SOME region");
        assert_eq!(
            first_region, "[   0.001234]",
            "left-to-right scan picks the FIRST balanced region; \
             the dmesg prefix is self-balancing and wins over the \
             stdout JSON that follows",
        );
        // End-to-end: `extract_metrics` on the same input should
        // emit a metric derived from the leading array, not from
        // the stdout `{"iops": 100}`. This pins that payloads
        // needing stderr-noise tolerance must pre-strip
        // timestamps rather than relying on the extractor.
        let m = extract_metrics(input, &OutputFormat::Json, MetricStream::Stdout).unwrap();
        let names: Vec<&str> = m.iter().map(|x| x.name.as_str()).collect();
        assert!(
            !names.contains(&"iops"),
            "regression check: the finder picking up the dmesg \
             timestamp array means the real stdout `iops` metric \
             is NOT extracted; if this ever starts containing \
             `iops`, the finder must have gained smarter \
             noise-skipping (update this test and the \
             documented contract); got: {names:?}",
        );
    }

    /// Scenario 2: stderr noise that is NOT self-balancing (an
    /// open bracket without its closer: `[FAIL stress-ng ...`).
    /// The finder commits to the first opener and returns
    /// `None` rather than retrying past its failure point.
    /// Stdout JSON that follows the unbalanced prefix is LOST,
    /// not recovered. Documents a known limitation: the finder
    /// has no fallback-search after a failed region.
    #[test]
    fn extract_json_region_unbalanced_stderr_prefix_returns_none() {
        let input = "[FAIL stress-ng: worker timed out\n{\"iops\": 200}";
        let r = extract_json_region(input);
        assert!(
            r.is_none(),
            "unbalanced leading `[` makes the finder return \
             None even though valid stdout JSON follows — the \
             finder commits to the first opener and does not \
             retry past its failure point. Known limitation; \
             callers pre-strip stderr noise. Got: {r:?}",
        );
    }

    /// Scenario 3: stderr noise with BALANCED brackets containing
    /// non-numeric content (`[stderr bracket message]`). The
    /// region is balanced at the byte level so the finder
    /// returns it, but `serde_json` rejects the unquoted content
    /// as invalid JSON. `extract_metrics` yields no metrics
    /// because the extractor only tries the FIRST region — the
    /// following valid stdout `{..}` is never inspected.
    ///
    /// Also acts as a positive control: the same stdout JSON
    /// with NO preceding noise extracts cleanly, so the failure
    /// above is specifically due to the preceding bracket noise,
    /// not the JSON itself.
    #[test]
    fn extract_json_region_balanced_unparseable_stderr_wins_first_region() {
        let input = "[stderr bracket message]\n{\"iops\": 300}";
        let first_region = extract_json_region(input).expect(
            "leading `[stderr bracket message]` is a balanced region \
             at the byte level (ignoring JSON validity); finder must \
             return it",
        );
        assert_eq!(
            first_region, "[stderr bracket message]",
            "balanced-but-invalid-JSON regions still win the \
             first-region scan; the following valid `{{..}}` is \
             never inspected by the finder",
        );
        let m = extract_metrics(input, &OutputFormat::Json, MetricStream::Stdout).unwrap();
        assert!(
            m.is_empty(),
            "region parses unsuccessfully as JSON → fallback \
             yields no metrics. The stdout `iops` metric is lost. \
             Documents the known limitation: mixed-stream \
             captures lose valid JSON when a preceding balanced \
             region fails to parse; got: {m:?}",
        );

        // Positive control: the same stdout JSON with NO
        // preceding noise extracts cleanly, so the failure
        // above is specifically due to the preceding bracket
        // noise, not the JSON itself.
        let m_clean = extract_metrics(
            r#"{"iops": 400}"#,
            &OutputFormat::Json,
            MetricStream::Stdout,
        )
        .unwrap();
        let clean_names: Vec<&str> = m_clean.iter().map(|x| x.name.as_str()).collect();
        assert!(
            clean_names.contains(&"iops"),
            "control: stdout JSON in isolation must extract the \
             `iops` metric so the preceding assertion is \
             isolating the noise-interaction behaviour, not \
             hiding a broken extractor; got: {clean_names:?}",
        );
    }

    #[test]
    fn walk_json_leaves_polarity_is_unknown_before_hint_resolution() {
        let v: serde_json::Value = serde_json::from_str(r#"{"a": 1}"#).unwrap();
        let m = walk_json_leaves(&v, MetricSource::Json, MetricStream::Stdout);
        assert_eq!(m[0].polarity, Polarity::Unknown);
    }

    #[test]
    fn walk_json_leaves_tags_source() {
        let v: serde_json::Value = serde_json::from_str(r#"{"a": 1}"#).unwrap();
        let json_tagged = walk_json_leaves(&v, MetricSource::Json, MetricStream::Stdout);
        assert_eq!(json_tagged[0].source, MetricSource::Json);
        let llm_tagged = walk_json_leaves(&v, MetricSource::LlmExtract, MetricStream::Stdout);
        assert_eq!(llm_tagged[0].source, MetricSource::LlmExtract);
    }

    /// `stream` attribution is orthogonal to `source`: every cross
    /// product of (`Json`/`LlmExtract`) × (`Stdout`/`Stderr`) must
    /// round-trip through the walker, and the stream field on the
    /// emitted `Metric` must match the argument. Pins the
    /// orthogonality contract asserted in the [`MetricStream`]
    /// docstring so a regression that silently coupled the two
    /// axes (e.g. forced `LlmExtract` to always stamp `Stdout`)
    /// fails here.
    ///
    /// Exercises BOTH walker branches: the object-recurse branch
    /// (via `{"a": 1}`) AND the array-recurse branch (via
    /// `[{"a": 1}, {"b": 2}]`) — a regression that stamped the
    /// stream only on one branch's emitted metrics would pass the
    /// object fixture but fail the array leaves. The array
    /// fixture also doubles coverage (two leaves per call) so the
    /// cross-product's 4 stream×source combos each produce 2
    /// assertions, catching any leaf-specific drift.
    #[test]
    fn walk_json_leaves_tags_stream_orthogonally_to_source() {
        let obj: serde_json::Value = serde_json::from_str(r#"{"a": 1}"#).unwrap();
        let arr: serde_json::Value = serde_json::from_str(r#"[{"a": 1}, {"b": 2}]"#).unwrap();
        for (fixture_label, value, expected_len) in
            [("object", &obj, 1_usize), ("array", &arr, 2_usize)]
        {
            for (src, stream) in [
                (MetricSource::Json, MetricStream::Stdout),
                (MetricSource::Json, MetricStream::Stderr),
                (MetricSource::LlmExtract, MetricStream::Stdout),
                (MetricSource::LlmExtract, MetricStream::Stderr),
            ] {
                let tagged = walk_json_leaves(value, src, stream);
                assert_eq!(
                    tagged.len(),
                    expected_len,
                    "walker on {fixture_label} fixture must produce \
                     exactly {expected_len} leaf(s); got {}",
                    tagged.len(),
                );
                for (i, m) in tagged.iter().enumerate() {
                    assert_eq!(
                        m.source, src,
                        "{fixture_label} leaf {i}: source tag must \
                         match the argument ({src:?}); got {:?}",
                        m.source,
                    );
                    assert_eq!(
                        m.stream, stream,
                        "{fixture_label} leaf {i}: stream tag must \
                         match the argument ({stream:?}); got {:?}. \
                         A regression that stamped the stream only \
                         on the object-recurse branch would pass \
                         the object fixture but fail here.",
                        m.stream,
                    );
                }
            }
        }
    }

    /// `extract_metrics` on the `Json` format threads the `stream`
    /// argument through to every emitted `Metric.stream`. Pins the
    /// wire between `extract_metrics` (caller-facing API) and the
    /// walker that actually stamps the field — a regression that
    /// dropped the `stream` parameter on the way in, or hardcoded
    /// `Stdout` inside the `Json` arm, silently drops the stderr
    /// attribution and breaks the `PayloadRun` stderr-fallback
    /// labelling. Mirrors the `walk_json_leaves_tags_stream_...`
    /// test one layer up.
    #[test]
    fn extract_metrics_threads_stream_from_argument_to_emitted_metric() {
        let json = r#"{"iops": 100}"#;
        for stream in [MetricStream::Stdout, MetricStream::Stderr] {
            let metrics = extract_metrics(json, &OutputFormat::Json, stream).unwrap();
            assert_eq!(metrics.len(), 1, "one leaf expected from {{\"iops\": 100}}",);
            assert_eq!(
                metrics[0].stream, stream,
                "extract_metrics must thread stream={stream:?} to the \
                 emitted Metric; got {:?}",
                metrics[0].stream,
            );
        }
    }

    // Additional edge-case coverage for walk_json_leaves paths.

    #[test]
    fn json_deeply_nested_array_of_objects() {
        // Edge case: array of objects. Each object's field should
        // emit `samples.N.field` paths.
        let s = r#"{"samples": [{"iops": 100}, {"iops": 200}, {"iops": 300}]}"#;
        let m = extract_metrics(s, &OutputFormat::Json, MetricStream::Stdout).unwrap();
        assert_eq!(m.len(), 3);
        let names: Vec<&str> = m.iter().map(|x| x.name.as_str()).collect();
        assert!(names.contains(&"samples.0.iops"));
        assert!(names.contains(&"samples.1.iops"));
        assert!(names.contains(&"samples.2.iops"));
    }

    #[test]
    fn json_large_integer_round_trip_via_f64() {
        // Large but f64-safe integer (below 2^53). serde_json's
        // Number::as_f64 lossily converts any JSON number to f64;
        // values below 2^53 are exact.
        let s = r#"{"big_iops": 1000000000000}"#; // 1e12 = 2^40
        let m = extract_metrics(s, &OutputFormat::Json, MetricStream::Stdout).unwrap();
        assert_eq!(m.len(), 1);
        assert_eq!(m[0].value, 1_000_000_000_000.0);
    }

    #[test]
    fn json_fio_style_full_output_with_multiline_banner() {
        // Real-world fio output has multiple banner lines + a large
        // JSON object. Region-finder must skip all non-JSON prefix
        // and parse the JSON body.
        let s = "fio-3.36 starting up\n\
                 Running fio with 4 jobs\n\
                 test: (g=0): rw=randread, bs=4k, ioengine=libaio\n\
                 \n\
                 {\"jobs\": [{\"jobname\": \"test\", \"read\": {\"iops\": 12345, \"bw_bytes\": 50593792}}], \
                 \"disk_util\": [{\"util\": 99.5}]}";
        let m = extract_metrics(s, &OutputFormat::Json, MetricStream::Stdout).unwrap();
        // Extracted: jobs.0.read.iops, jobs.0.read.bw_bytes, disk_util.0.util.
        // jobname is a string, skipped.
        assert_eq!(m.len(), 3);
        let by_name: std::collections::BTreeMap<&str, f64> =
            m.iter().map(|x| (x.name.as_str(), x.value)).collect();
        assert_eq!(by_name.get("jobs.0.read.iops"), Some(&12345.0));
        assert_eq!(by_name.get("jobs.0.read.bw_bytes"), Some(&50593792.0));
        assert_eq!(by_name.get("disk_util.0.util"), Some(&99.5));
    }

    #[test]
    fn walk_json_leaves_skips_nonfinite_defensively() {
        // serde_json rejects NaN/Infinity at parse time (strict JSON),
        // so naturally-occurring inputs never reach walk_json_leaves
        // with non-finite numbers. The defensive filter is still
        // verified by constructing a Value directly with
        // Number::from_f64 which returns None for non-finite.
        assert!(serde_json::Number::from_f64(f64::NAN).is_none());
        assert!(serde_json::Number::from_f64(f64::INFINITY).is_none());
        assert!(serde_json::Number::from_f64(f64::NEG_INFINITY).is_none());
        // Finite values ARE accepted:
        assert!(serde_json::Number::from_f64(2.78).is_some());
    }

    /// JSON integers above 2^53 lose precision when coerced to
    /// f64 via `serde_json::Number::as_f64` — the f64 mantissa is 52
    /// bits, so consecutive integers beyond 9007199254740992 round
    /// to the nearest representable f64. Pin the observed behavior:
    /// `9007199254740993` (2^53 + 1) round-trips as `9007199254740992.0`
    /// (2^53). Payloads emitting integer metrics larger than 2^53
    /// must scale down (µs → s) or encode as strings — the Json
    /// walker cannot preserve integer identity past that boundary.
    #[test]
    fn json_large_integer_above_2_pow_53_loses_precision() {
        // 2^53 = 9_007_199_254_740_992 is the last exactly-representable
        // consecutive integer in f64. 2^53 + 1 rounds down to 2^53
        // (banker's rounding lands on the even representable
        // neighbor). Test via u64 → f64 to pin the u64 input value
        // distinct from the emitted f64 — a direct f64 literal of
        // 2^53+1 would itself round at parse time, obscuring what
        // the walker did.
        let s = r#"{"huge": 9007199254740993}"#;
        let m = extract_metrics(s, &OutputFormat::Json, MetricStream::Stdout).unwrap();
        assert_eq!(m.len(), 1);
        // The emitted f64 IS the nearest representable value —
        // which is 2^53, not 2^53+1. Both literals happen to print
        // as "9007199254740992.0" because f64 can't distinguish
        // them; compare against the exact f64 produced by the
        // next-representable-below path.
        assert_eq!(m[0].value, 9_007_199_254_740_992.0_f64);
        // Cast the u64 source input to f64 to reproduce the same
        // rounding serde_json performed. Both sides land at 2^53;
        // that equality IS the lossy cast being documented.
        let rounded: f64 = 9_007_199_254_740_993_u64 as f64;
        assert_eq!(m[0].value, rounded);
        // Confirm bit-level that the u64 input and the resulting
        // f64 are NOT identity-preserving: casting the f64 back to
        // u64 yields 2^53, not 2^53+1.
        assert_eq!(m[0].value as u64, 9_007_199_254_740_992_u64);
        assert_ne!(m[0].value as u64, 9_007_199_254_740_993_u64);
    }

    /// At exactly 2^53 the f64 IS exact — the precision loss is
    /// strictly one-above-the-boundary. Pair with
    /// `json_large_integer_above_2_pow_53_loses_precision` so both
    /// sides of the precision cliff are pinned.
    #[test]
    fn json_integer_at_2_pow_53_is_exact() {
        let s = r#"{"exact": 9007199254740992}"#;
        let m = extract_metrics(s, &OutputFormat::Json, MetricStream::Stdout).unwrap();
        assert_eq!(m.len(), 1);
        assert_eq!(m[0].value, 9_007_199_254_740_992.0_f64);
    }

    /// `find_and_parse_json` tries the whole trimmed input as
    /// a single document on the fast path. If the input has a
    /// balanced object followed by trailing non-JSON text, the
    /// whole-input parse fails (strict serde) and the region-
    /// finder slow path extracts the leading `{...}` region and
    /// parses that. Pins the "trailing garbage is stripped by the
    /// region finder" behavior.
    #[test]
    fn find_and_parse_json_recovers_object_with_trailing_garbage() {
        let s = r#"{"a": 1, "b": 2} --- trailing prose from banner"#;
        let v = find_and_parse_json(s).expect("trailing garbage must not block parse");
        assert_eq!(v["a"], serde_json::json!(1));
        assert_eq!(v["b"], serde_json::json!(2));
    }

    /// A leading array followed by trailing garbage recovers
    /// symmetrically — the region finder handles `[...]` the same
    /// way it handles `{...}`.
    #[test]
    fn find_and_parse_json_recovers_array_with_trailing_garbage() {
        let s = "[1, 2, 3]\nextra: banner line\n";
        let v = find_and_parse_json(s).expect("array with trailing garbage must parse");
        assert_eq!(v, serde_json::json!([1, 2, 3]));
    }

    /// Real-world fio pattern — banner line, JSON body,
    /// *and* trailing "done" marker. The region finder locks to
    /// the first balanced opener/closer, so the trailing content
    /// is ignored even if it contains unbalanced braces.
    #[test]
    fn find_and_parse_json_with_banner_and_trailer() {
        let s = "fio-3.36 starting up\n{\"iops\": 100}\nfio done }";
        let v = find_and_parse_json(s).expect("banner + trailer must resolve to body");
        assert_eq!(v["iops"], serde_json::json!(100));
    }

    /// When the trailing garbage itself contains a
    /// BALANCED brace pair, the region finder still returns the
    /// first one — downstream parsing uses the first match, not
    /// a merged document.
    #[test]
    fn find_and_parse_json_returns_first_region_when_trailer_also_balanced() {
        let s = r#"{"first": 1} unrelated {"second": 2}"#;
        let v = find_and_parse_json(s).expect("first balanced region parses");
        assert_eq!(v["first"], serde_json::json!(1));
        assert!(v.get("second").is_none(), "second region must not merge in");
    }

    /// Embedded `{` / `}` characters inside a JSON string literal
    /// must NOT be counted as structural openers/closers by the
    /// region finder. The in-string tracker flips on `"` and
    /// suppresses nesting accounting until the matching closing
    /// `"`, so the only braces that affect `depth` are the
    /// structural outer ones. Pins that a log message which happens
    /// to contain `{` / `}` inside a quoted string still round-trips
    /// through the slow path.
    #[test]
    fn find_and_parse_json_ignores_braces_inside_string_literals() {
        let s = "fio-3.36 starting up\n\
                 {\"msg\": \"look at {nested} in text\", \"ok\": 1}\n\
                 trailing banner";
        let v = find_and_parse_json(s).expect("embedded braces in string must not break scan");
        assert_eq!(v["msg"], serde_json::json!("look at {nested} in text"));
        assert_eq!(v["ok"], serde_json::json!(1));
    }

    /// Negative numeric leaves extract at their declared value
    /// without any sign-absoluting or filtering. Canonical for
    /// metrics like scheduler_delta_ns that can legitimately be
    /// negative (improvement from baseline).
    #[test]
    fn json_negative_numbers_extract_preserving_sign() {
        let s = r#"{"delta_ns": -500.5, "underflow": -1000000}"#;
        let m = extract_metrics(s, &OutputFormat::Json, MetricStream::Stdout).unwrap();
        let by_name: std::collections::BTreeMap<&str, f64> =
            m.iter().map(|x| (x.name.as_str(), x.value)).collect();
        assert_eq!(by_name.get("delta_ns"), Some(&-500.5));
        assert_eq!(by_name.get("underflow"), Some(&-1_000_000.0));
    }

    /// Zero is emitted as a real metric value, not filtered
    /// out. A payload that genuinely measured zero (idle CPU, no
    /// errors) must produce a zero metric — otherwise downstream
    /// checks like `Check::exit_code_eq(0)` against an `exit_code`
    /// metric of 0.0 would spuriously report "missing" instead of
    /// passing.
    #[test]
    fn json_zero_values_are_emitted_not_filtered() {
        let s = r#"{"errors": 0, "cpu_idle_pct": 0.0, "count": -0.0}"#;
        let m = extract_metrics(s, &OutputFormat::Json, MetricStream::Stdout).unwrap();
        let by_name: std::collections::BTreeMap<&str, f64> =
            m.iter().map(|x| (x.name.as_str(), x.value)).collect();
        assert_eq!(by_name.len(), 3, "all three zeros must extract: {m:?}");
        assert_eq!(by_name.get("errors"), Some(&0.0));
        assert_eq!(by_name.get("cpu_idle_pct"), Some(&0.0));
        // -0.0 round-trips via f64; assert the numeric equality.
        assert_eq!(by_name.get("count"), Some(&0.0));
    }

    /// Mixed positive + negative + zero in one document
    /// exercises the walker's sign-agnostic branch.
    #[test]
    fn json_mixed_signs_and_zero_all_extract() {
        let s = r#"{"pos": 10.0, "neg": -10.0, "zero": 0.0}"#;
        let m = extract_metrics(s, &OutputFormat::Json, MetricStream::Stdout).unwrap();
        assert_eq!(m.len(), 3);
    }

    /// An empty JSON object `{}` at the top level parses
    /// successfully but yields no metric leaves — the walker
    /// traverses zero children and falls through to produce an
    /// empty Vec. No `None` return, no panic.
    #[test]
    fn json_empty_object_yields_no_metrics() {
        let m = extract_metrics("{}", &OutputFormat::Json, MetricStream::Stdout).unwrap();
        assert!(m.is_empty(), "empty object has no leaves: {m:?}");
    }

    /// An empty array at the top level likewise yields zero
    /// metrics.
    #[test]
    fn json_empty_array_yields_no_metrics() {
        let m = extract_metrics("[]", &OutputFormat::Json, MetricStream::Stdout).unwrap();
        assert!(m.is_empty(), "empty array has no leaves: {m:?}");
    }

    /// Nested empty containers also produce no leaves — the
    /// walker still recurses but finds nothing numeric at the
    /// bottom. Pins the "no ghost metrics from empty containers"
    /// invariant.
    #[test]
    fn json_nested_empty_containers_yield_no_metrics() {
        let s = r#"{"outer": {"inner": {}, "also": []}}"#;
        let m = extract_metrics(s, &OutputFormat::Json, MetricStream::Stdout).unwrap();
        assert!(m.is_empty(), "nested empties emit nothing: {m:?}");
    }

    /// Empty container alongside real metrics — empties are
    /// silent, real leaves still emit.
    #[test]
    fn json_empty_container_mixed_with_real_metrics() {
        let s = r#"{"iops": 100.0, "meta": {}, "samples": []}"#;
        let m = extract_metrics(s, &OutputFormat::Json, MetricStream::Stdout).unwrap();
        assert_eq!(m.len(), 1);
        assert_eq!(m[0].name, "iops");
        assert_eq!(m[0].value, 100.0);
    }

    /// walk_json_leaves uses push/pop on a single
    /// path buffer instead of per-level format!(). This test pins
    /// the *behavior* (path output unchanged across deep nesting)
    /// so a future refactor of the path plumbing can't silently
    /// drop a segment or duplicate a dot.
    #[test]
    fn walk_json_leaves_deep_nesting_paths_are_correct() {
        // 6 levels deep → one leaf at a.b.c.d.e.f.
        let s = r#"{"a":{"b":{"c":{"d":{"e":{"f": 42.0}}}}}}"#;
        let m = extract_metrics(s, &OutputFormat::Json, MetricStream::Stdout).unwrap();
        assert_eq!(m.len(), 1);
        assert_eq!(m[0].name, "a.b.c.d.e.f");
        assert_eq!(m[0].value, 42.0);
    }

    /// Sibling keys under the same parent must see the parent
    /// segment truncated between each child — the bug that the
    /// push/pop refactor would hit is "path accumulates across
    /// siblings" producing `root.a.b`, `root.a.b.c` etc. instead
    /// of `root.a.b`, `root.a.c`.
    #[test]
    fn walk_json_leaves_siblings_do_not_accumulate_path() {
        let s = r#"{"root":{"a": 1, "b": 2, "c": 3}}"#;
        let m = extract_metrics(s, &OutputFormat::Json, MetricStream::Stdout).unwrap();
        assert_eq!(m.len(), 3);
        let names: std::collections::BTreeSet<&str> = m.iter().map(|x| x.name.as_str()).collect();
        let expected: std::collections::BTreeSet<&str> =
            ["root.a", "root.b", "root.c"].into_iter().collect();
        assert_eq!(names, expected, "path must truncate between siblings");
    }

    /// Array indices use the same push/pop path: `arr.0`, `arr.1`.
    /// Deep array-of-array-of-object combinations exercise every
    /// code path in the walker.
    #[test]
    fn walk_json_leaves_deep_array_object_interleaving() {
        let s = r#"{"data":[{"vals":[10.0, 20.0]},{"vals":[30.0]}]}"#;
        let m = extract_metrics(s, &OutputFormat::Json, MetricStream::Stdout).unwrap();
        let by_name: std::collections::BTreeMap<&str, f64> =
            m.iter().map(|x| (x.name.as_str(), x.value)).collect();
        assert_eq!(by_name.get("data.0.vals.0"), Some(&10.0));
        assert_eq!(by_name.get("data.0.vals.1"), Some(&20.0));
        assert_eq!(by_name.get("data.1.vals.0"), Some(&30.0));
        assert_eq!(by_name.len(), 3);
    }

    /// Programmatically build a `serde_json::Value` nested deeper than
    /// [`MAX_WALK_DEPTH`] and confirm that `walk_json_leaves` returns
    /// without a stack overflow and without emitting metrics from
    /// beyond the cap. Serde_json's own parser depth limit (128 by
    /// default) blocks malicious JSON strings before the walker sees
    /// them, so a parser-bypass (direct `Value::Object` construction)
    /// is the only way to reach this depth — the test exercises
    /// exactly that path.
    #[test]
    fn walk_json_leaves_depth_cap_skips_deeply_nested_subtree() {
        // Build an Object nested 100 deep with a numeric leaf at the
        // bottom. The leaf at depth > MAX_WALK_DEPTH (64) must be
        // skipped by the guard. A sentinel metric with
        // `WALK_TRUNCATION_SENTINEL_NAME` MUST appear in the return
        // so callers without a tracing subscriber still observe the
        // truncation.
        let mut value = serde_json::json!({"leaf": 42.0});
        for _ in 0..100 {
            let mut m = serde_json::Map::new();
            m.insert("x".to_string(), value);
            value = serde_json::Value::Object(m);
        }
        let metrics = walk_json_leaves(&value, MetricSource::Json, MetricStream::Stdout);
        let real_leaves: Vec<_> = metrics
            .iter()
            .filter(|m| m.name != WALK_TRUNCATION_SENTINEL_NAME)
            .collect();
        assert!(
            real_leaves.is_empty(),
            "leaf beyond MAX_WALK_DEPTH cap must not be emitted, got {real_leaves:?}"
        );
        let sentinel = metrics
            .iter()
            .find(|m| m.name == WALK_TRUNCATION_SENTINEL_NAME)
            .expect("truncation sentinel must be present on cap hit");
        assert!(
            sentinel.value > MAX_WALK_DEPTH as f64,
            "sentinel value must carry the depth at which truncation fired, got {}",
            sentinel.value,
        );
    }

    /// A leaf exactly at [`MAX_WALK_DEPTH`] is still emitted — the
    /// cap bails BEFORE recursing past `depth > MAX_WALK_DEPTH`, so a
    /// leaf reached at `depth == MAX_WALK_DEPTH` is preserved.
    /// Boundary pair with the depth_cap_skips test above so an
    /// off-by-one in the guard (e.g. `>=` instead of `>`) surfaces.
    #[test]
    fn walk_json_leaves_depth_cap_boundary_leaf_preserved() {
        // Build Object of exactly MAX_WALK_DEPTH nesting: top-level
        // holds an Object, which holds an Object, ... for
        // MAX_WALK_DEPTH levels, with the numeric leaf at the bottom.
        // The leaf's path has MAX_WALK_DEPTH segments and walk() is
        // called at depths 0..=MAX_WALK_DEPTH — the leaf call at
        // depth MAX_WALK_DEPTH must pass the guard.
        let mut value = serde_json::Value::Number(serde_json::Number::from_f64(42.0).unwrap());
        for _ in 0..MAX_WALK_DEPTH {
            let mut m = serde_json::Map::new();
            m.insert("x".to_string(), value);
            value = serde_json::Value::Object(m);
        }
        let metrics = walk_json_leaves(&value, MetricSource::Json, MetricStream::Stdout);
        assert_eq!(metrics.len(), 1, "boundary leaf must be preserved");
        assert_eq!(metrics[0].value, 42.0);
    }

    /// Mixed-depth invariant: a single walk must emit every finite
    /// numeric leaf regardless of the depth at which it appears, so
    /// long as the depth is ≤ MAX_WALK_DEPTH. Mirrors real payload
    /// schemas (fio's `jobs[0].read.lat_ns.mean` sits at depth 5
    /// while `jobs[0].jobname` sits at depth 2). A single-depth
    /// regression — e.g. a premature `return` inside the Object arm
    /// — would skip the shallower siblings of a deep subtree.
    #[test]
    fn walk_json_leaves_mixed_depth_leaves_all_emitted() {
        let value = serde_json::json!({
            "shallow": 1.0,
            "mid": {
                "leaf": 2.0,
                "deeper": {
                    "still": {
                        "further": 3.0
                    }
                }
            },
            "also_shallow": 4.0,
            "deeper_sibling": {
                "only_child": 5.0
            }
        });
        let metrics = walk_json_leaves(&value, MetricSource::Json, MetricStream::Stdout);
        let by_name: std::collections::BTreeMap<&str, f64> =
            metrics.iter().map(|m| (m.name.as_str(), m.value)).collect();
        assert_eq!(by_name.get("shallow"), Some(&1.0));
        assert_eq!(by_name.get("mid.leaf"), Some(&2.0));
        assert_eq!(by_name.get("mid.deeper.still.further"), Some(&3.0));
        assert_eq!(by_name.get("also_shallow"), Some(&4.0));
        assert_eq!(by_name.get("deeper_sibling.only_child"), Some(&5.0));
        assert_eq!(metrics.len(), 5, "exactly five numeric leaves expected");
    }

    /// Array-chain invariant: nested arrays produce dotted-index
    /// paths with no stray separators. An off-by-one in the
    /// separator injection at :203-205 (array arm) or a swapped
    /// push-path/truncate order would surface as either a leading
    /// dot, a doubled separator, or an index segment merged into
    /// the previous one.
    #[test]
    fn walk_json_leaves_array_chain_paths_correct() {
        // `a` is a 2x2x2 array of numeric leaves; the walker must
        // produce paths `a.0.0.0`, `a.0.0.1`, `a.0.1.0`, …, `a.1.1.1`.
        let value = serde_json::json!({
            "a": [
                [[1.0, 2.0], [3.0, 4.0]],
                [[5.0, 6.0], [7.0, 8.0]]
            ]
        });
        let metrics = walk_json_leaves(&value, MetricSource::Json, MetricStream::Stdout);
        let names: Vec<&str> = metrics.iter().map(|m| m.name.as_str()).collect();
        // 8 leaves in lexicographic index order.
        assert_eq!(names.len(), 8);
        assert_eq!(names[0], "a.0.0.0");
        assert_eq!(names[1], "a.0.0.1");
        assert_eq!(names[2], "a.0.1.0");
        assert_eq!(names[3], "a.0.1.1");
        assert_eq!(names[4], "a.1.0.0");
        assert_eq!(names[5], "a.1.0.1");
        assert_eq!(names[6], "a.1.1.0");
        assert_eq!(names[7], "a.1.1.1");
        // Values map 1:1 against path order — confirm no segment
        // got dropped or reordered.
        assert_eq!(metrics[0].value, 1.0);
        assert_eq!(metrics[7].value, 8.0);
    }

    /// Null-at-boundary invariant: a `serde_json::Value::Null` leaf
    /// is skipped by the `_ => {}` arm and contributes nothing — no
    /// metric, no sentinel, no side effect — regardless of the
    /// depth at which it sits. Specifically pins the case where the
    /// null is the direct child of a depth-MAX_WALK_DEPTH container,
    /// ensuring the cap check fires first when the container would
    /// itself be above the cap rather than the null stopping
    /// recursion harmlessly short. A regression that treats Null
    /// the same as a Number would surface as a spurious leaf with
    /// `value = 0.0` (or a panic) on this fixture.
    #[test]
    fn walk_json_leaves_null_at_boundary_produces_no_metric() {
        // Build `{a: {a: {a: ... {a: null}}}}` at exactly
        // MAX_WALK_DEPTH nesting — the Null sits at depth
        // MAX_WALK_DEPTH; the walker recurses into the outer Objects
        // at depths 0..=MAX_WALK_DEPTH-1, sees Null at the
        // boundary, and falls through the `_ => {}` arm.
        let mut value = serde_json::Value::Null;
        for _ in 0..MAX_WALK_DEPTH {
            let mut m = serde_json::Map::new();
            m.insert("a".to_string(), value);
            value = serde_json::Value::Object(m);
        }
        let metrics = walk_json_leaves(&value, MetricSource::Json, MetricStream::Stdout);
        assert!(
            metrics.is_empty(),
            "Null leaves must produce no metrics (and no truncation sentinel), \
             got {metrics:?}",
        );
    }

    #[test]
    fn module_level_example_usage() {
        // Canonical invocation: declare a Payload with
        // OutputFormat::Json, feed stdout, get Vec<Metric>.
        const EXAMPLE_PAYLOAD: crate::test_support::Payload = crate::test_support::Payload {
            name: "example",
            kind: crate::test_support::PayloadKind::Binary("example"),
            output: OutputFormat::Json,
            default_args: &[],
            default_checks: &[],
            metrics: &[],
            include_files: &[],
            uses_parent_pgrp: false,
            known_flags: None,
            metric_bounds: None,
        };
        let stdout = r#"{"throughput": 42.5}"#;
        let m = extract_metrics(stdout, &EXAMPLE_PAYLOAD.output, MetricStream::Stdout).unwrap();
        assert_eq!(m.len(), 1);
        assert_eq!(m[0].name, "throughput");
        assert_eq!(m[0].value, 42.5);
        assert_eq!(m[0].source, MetricSource::Json);
    }
}