trusty-common 0.52.6

Shared utilities and provider-agnostic streaming chat (ChatProvider, OllamaProvider, OpenRouter, tool-use) for trusty-* projects
Documentation
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
//! Whole-machine host metrics sampling for the Foundry dashboard (#6517).
//!
//! Why: [`sys_metrics`](crate::sys_metrics) samples only the CURRENT process —
//!      its RSS and CPU. The Foundry machine-status dashboard needs the whole
//!      host instead: overall CPU load, system memory with a pressure signal,
//!      per-mount and aggregate disk usage, and network throughput. Per the
//!      workspace "common entry point, clean domain demarcation" rule this
//!      host-sampling capability lives here once rather than being reinvented in
//!      trusty-console, so any future consumer (a second dashboard, a headless
//!      health probe) reuses the same typed shapes.
//! What: [`HostSampler`](crate::host_metrics::HostSampler) wraps a
//!      `sysinfo::System` plus its `Networks`/`Disks` handles and, on each
//!      [`HostSampler::sample`](crate::host_metrics::HostSampler::sample),
//!      returns a [`HostMetrics`](crate::host_metrics::HostMetrics) snapshot.
//!      Health thresholds ([`HostThresholds`](crate::host_metrics::HostThresholds))
//!      are PROVISIONAL — see the type's docs; they need an owner ruling before
//!      any alarm is wired to them.
//!      The [`history`](crate::host_metrics::history) submodule adds the
//!      bounded sliding window of those snapshots the console's real-time
//!      graphs read (#6641).
//! Test: the inline `tests` module — `sampler_produces_plausible_snapshot`,
//!      `pressure_classification_boundaries`, `thresholds_are_configurable`,
//!      and the serde round-trip; the window itself is covered by
//!      `push_evicts_oldest_at_capacity` and its siblings in `history`.
//!
//! ## OS-agnostic sampling
//!
//! `sysinfo` is cross-platform, but some fields are unavailable or shaped
//! differently per OS, and the data model must not assume the macOS screensaver
//! form factor. Specifics:
//! - `MountMetrics::is_removable` is best-effort; some platforms always report
//!   `false`.
//! - `CpuMetrics::physical_cores` is `None` where the OS does not expose a
//!   physical/logical split.
//! - Swap totals read `0` on hosts with no swap configured — not an error.
//! - Disk and network interface enumeration differs per OS (macOS surfaces
//!   synthetic APFS volumes; containers may hide interfaces). The snapshot
//!   reports whatever the OS lists and never fails when a set is empty.

use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
use std::time::{Duration, Instant};
use sysinfo::{CpuRefreshKind, Disk, Disks, MemoryRefreshKind, Networks, RefreshKind, System};

// #6641: the bounded sample history the console's real-time graphs read. It
// lives beside the sampler rather than in trusty-console because the buffer has
// two writers by design — today's sampler and the pushed samples #6284 will
// deliver — and both must enter through `MetricRing::push`.
pub mod history;

/// Coarse pressure classification for one host subsystem (#6517).
///
/// Why: the dashboard renders a traffic-light per subsystem without re-deriving
///      thresholds client-side, and a typed tri-state keeps every consumer's
///      classification identical.
/// What: `Nominal` (below the warning threshold), `Warning` (at/above warning,
///      below critical), `Critical` (at/above critical). Serialised lowercase.
/// Test: `pressure_classification_boundaries`.
// The variant order is the severity order: deriving `Ord` makes
// `Pressure::worst` (via `max`) pick the more severe of two — see `Pressure::worst`.
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
#[non_exhaustive]
pub enum Pressure {
    /// Below the warning threshold — healthy.
    Nominal,
    /// At or above the warning threshold, below critical.
    Warning,
    /// At or above the critical threshold.
    Critical,
}

impl Pressure {
    /// The worse of two pressures (`Critical` > `Warning` > `Nominal`).
    ///
    /// Why: [`HostMetrics::overall_pressure`] is the worst subsystem, so the
    ///      dashboard's single top-level badge never under-reports.
    /// What: returns whichever operand ranks higher on the severity order.
    /// Test: `overall_is_worst_subsystem`.
    #[must_use]
    pub fn worst(self, other: Self) -> Self {
        self.max(other)
    }
}

/// PROVISIONAL health thresholds for host-subsystem pressure (#6517).
///
/// Why: the epic flags "healthy" thresholds as an OWNER DECISION. These
///      defaults are sensible starting points (a busy but functioning host sits
///      in `Nominal`; sustained saturation trips `Warning`, near-exhaustion
///      `Critical`) but they are NOT an owner ruling. Do NOT wire an alarm,
///      auto-remediation, or paging to these numbers until the owner signs off
///      on the levels. The struct is configurable precisely so the eventual
///      ruling changes one call, not the classification logic.
/// What: per-subsystem warning/critical percentages consumed by
///      [`Pressure::classify`]. Percentages are 0..=100.
/// Test: `thresholds_are_configurable`.
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
#[non_exhaustive]
pub struct HostThresholds {
    /// CPU load %% at/above which a host is `Warning`. PROVISIONAL default 80.
    pub cpu_warning_pct: f32,
    /// CPU load %% at/above which a host is `Critical`. PROVISIONAL default 95.
    pub cpu_critical_pct: f32,
    /// Memory-used %% at/above which a host is `Warning`. PROVISIONAL default 80.
    pub memory_warning_pct: f32,
    /// Memory-used %% at/above which a host is `Critical`. PROVISIONAL default 95.
    pub memory_critical_pct: f32,
    /// Disk-used %% at/above which a mount is `Warning`. PROVISIONAL default 85.
    pub disk_warning_pct: f32,
    /// Disk-used %% at/above which a mount is `Critical`. PROVISIONAL default 95.
    pub disk_critical_pct: f32,
}

impl Default for HostThresholds {
    /// PROVISIONAL defaults — see [`HostThresholds`] for why they are not an
    /// owner ruling.
    fn default() -> Self {
        // #6517: provisional levels pending an owner ruling on "healthy".
        Self {
            cpu_warning_pct: 80.0,
            cpu_critical_pct: 95.0,
            memory_warning_pct: 80.0,
            memory_critical_pct: 95.0,
            disk_warning_pct: 85.0,
            disk_critical_pct: 95.0,
        }
    }
}

impl Pressure {
    /// Classify `usage_pct` against a warning/critical pair.
    ///
    /// Why: the ONE place a percentage becomes a tri-state, so CPU, memory, and
    ///      disk all classify identically.
    /// What: `>= critical` → `Critical`; else `>= warning` → `Warning`; else
    ///      `Nominal`. A `NaN` input (a subsystem that could not be measured)
    ///      classifies as `Nominal` rather than panicking.
    /// Test: `pressure_classification_boundaries`.
    #[must_use]
    pub fn classify(usage_pct: f32, warning: f32, critical: f32) -> Self {
        if usage_pct >= critical {
            Pressure::Critical
        } else if usage_pct >= warning {
            Pressure::Warning
        } else {
            Pressure::Nominal
        }
    }
}

/// Overall CPU load across the whole machine (#6517).
///
/// Why: the dashboard's CPU gauge needs one host-wide number plus the core
///      counts to contextualise it.
/// What: `usage_pct` is `sysinfo`'s global CPU usage — the average across all
///      logical cores, 0..=100 (unlike the per-process figure, which can exceed
///      100). `physical_cores` is `None` where the OS hides the split.
/// Test: `sampler_produces_plausible_snapshot`.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct CpuMetrics {
    /// Machine-wide CPU utilisation, 0..=100 (averaged across logical cores).
    pub usage_pct: f32,
    /// Logical (hyperthread) core count.
    pub logical_cores: usize,
    /// Physical core count, or `None` when the OS does not expose it.
    pub physical_cores: Option<usize>,
    /// Pressure classification of `usage_pct` against [`HostThresholds`].
    pub pressure: Pressure,
}

/// System memory + swap with a pressure signal (#6517).
///
/// Why: memory exhaustion is the failure the dashboard most needs to surface
///      early; a used-percentage plus a pressure band gives that at a glance.
/// What: all byte fields are bytes (not KiB — `sysinfo` 0.30+ reports bytes).
///      `available_bytes` is the OS "available" figure (reclaimable included),
///      which is a better headroom signal than `total - used`.
/// Test: `sampler_produces_plausible_snapshot`.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MemoryMetrics {
    /// Total physical RAM, bytes.
    pub total_bytes: u64,
    /// Used RAM, bytes.
    pub used_bytes: u64,
    /// OS-reported available RAM (reclaimable included), bytes.
    pub available_bytes: u64,
    /// `used_bytes / total_bytes` as a percentage, 0..=100.
    pub usage_pct: f32,
    /// Total swap, bytes (`0` when no swap is configured).
    pub swap_total_bytes: u64,
    /// Used swap, bytes.
    pub swap_used_bytes: u64,
    /// Pressure classification of `usage_pct` against [`HostThresholds`].
    pub pressure: Pressure,
}

/// One mounted filesystem's usage (#6517).
///
/// Why: the dashboard lists mounts individually so a single full volume is
///      visible even when the aggregate looks healthy.
/// What: byte fields are bytes. `used_bytes` is `total - available`.
///      `is_removable` is best-effort per OS.
/// Test: `sampler_produces_plausible_snapshot`.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct MountMetrics {
    /// Mount point path (e.g. `/`, `/System/Volumes/Data`).
    pub mount_point: String,
    /// Device/volume name as the OS reports it.
    pub name: String,
    /// Total capacity, bytes.
    pub total_bytes: u64,
    /// Available capacity, bytes.
    pub available_bytes: u64,
    /// Used capacity (`total - available`), bytes.
    pub used_bytes: u64,
    /// `used_bytes / total_bytes` as a percentage, 0..=100.
    pub usage_pct: f32,
    /// Best-effort removable-media flag; `false` on OSes that do not expose it.
    pub is_removable: bool,
    /// Pressure classification of `usage_pct` against [`HostThresholds`].
    pub pressure: Pressure,
}

/// Machine-wide disk usage: aggregate plus per-mount detail (#6517).
///
/// Why: the aggregate drives a single "storage" gauge; the mounts back the
///      drill-down. The aggregate sums only NON-removable, real mounts so a
///      plugged-in USB stick does not distort the machine's headroom.
/// What: `aggregate_*` sum the counted mounts; `mounts` lists every mount the
///      OS reported (removable ones included, for the drill-down).
/// Test: `sampler_produces_plausible_snapshot`.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct DiskMetrics {
    /// Total capacity across counted (non-removable) mounts, bytes.
    pub aggregate_total_bytes: u64,
    /// Available capacity across counted mounts, bytes.
    pub aggregate_available_bytes: u64,
    /// Used capacity across counted mounts, bytes.
    pub aggregate_used_bytes: u64,
    /// Aggregate used percentage, 0..=100.
    pub aggregate_usage_pct: f32,
    /// Pressure classification of `aggregate_usage_pct`.
    pub pressure: Pressure,
    /// Every mount the OS reported.
    pub mounts: Vec<MountMetrics>,
}

/// Machine-wide network throughput (#6517).
///
/// Why: throughput is a rate, so the dashboard needs bytes/sec, not a
///      cumulative counter it would have to difference itself.
/// What: `*_bytes_per_sec` are the delta since the previous sample divided by
///      the elapsed window (`window_secs`); `*_total_bytes` are the cumulative
///      counters. The FIRST sample reports rates over the priming window, which
///      may be near-zero — like the per-process CPU delta in `sys_metrics`.
/// Test: `sampler_produces_plausible_snapshot`.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct NetworkMetrics {
    /// Receive rate over the last sample window, bytes/sec.
    pub rx_bytes_per_sec: f64,
    /// Transmit rate over the last sample window, bytes/sec.
    pub tx_bytes_per_sec: f64,
    /// Cumulative bytes received since interface start, summed over interfaces.
    pub rx_total_bytes: u64,
    /// Cumulative bytes transmitted since interface start, summed.
    pub tx_total_bytes: u64,
    /// The window the rates were computed over, seconds.
    pub window_secs: f64,
}

/// A whole-machine metrics snapshot (#6517).
///
/// Why: the aggregated, serde-stable shape the Foundry machine-status endpoint
///      and its phase-2 UI render. Combining every subsystem in one struct lets
///      the dashboard fetch the whole host in one payload.
/// What: the four subsystem structs plus `overall_pressure` (worst subsystem)
///      and `sampled_at_unix`. All fields are public and serde round-trip.
/// Test: `snapshot_serde_round_trip`, `sampler_produces_plausible_snapshot`.
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HostMetrics {
    /// Overall CPU load.
    pub cpu: CpuMetrics,
    /// System memory + swap.
    pub memory: MemoryMetrics,
    /// Disk usage (aggregate + per-mount).
    pub disks: DiskMetrics,
    /// Network throughput.
    pub network: NetworkMetrics,
    /// Worst of the CPU / memory / disk pressures.
    pub overall_pressure: Pressure,
    /// Unix seconds when the snapshot was taken, or `None` if the clock read
    /// failed.
    pub sampled_at_unix: Option<u64>,
}

/// Divide a byte count by a total, returning a 0..=100 percentage.
///
/// Why: `used / total * 100` recurs for CPU, memory, and every mount; one
///      helper keeps the zero-total guard consistent (an empty/zero-capacity
///      mount reports `0.0`, never a `NaN`).
/// What: returns `0.0` when `total == 0`; otherwise the clamped percentage.
/// Test: exercised via `sampler_produces_plausible_snapshot` and the
///      classification tests.
fn pct(used: u64, total: u64) -> f32 {
    if total == 0 {
        return 0.0;
    }
    (used as f64 / total as f64 * 100.0) as f32
}

/// Whole-machine metrics sampler bound to a live `sysinfo::System` (#6517).
///
/// Why: like [`SysMetrics`](crate::sys_metrics::SysMetrics), CPU and network
///      readings are deltas between refreshes, so the same instance must be
///      reused across samples. A dashboard builds one at startup and samples it
///      on its poll interval.
/// What: holds the `System`, the `Networks` and `Disks` handles, the timestamp
///      of the last network refresh (for rate math), and the configured
///      thresholds. Not `Clone` — it carries mutable sampling state; share it
///      behind a lock if multiple pollers need it.
/// Test: `sampler_produces_plausible_snapshot`.
pub struct HostSampler {
    sys: System,
    networks: Networks,
    disks: Disks,
    last_net_refresh: Instant,
    thresholds: HostThresholds,
    /// How long a [`DiskMetrics`] snapshot stays warm before the next volume walk.
    disk_interval: Duration,
    /// `None` until the first sample, which always refreshes.
    last_disk_refresh: Option<Instant>,
    /// The snapshot served between refreshes; `Some` after the first sample.
    cached_disks: Option<DiskMetrics>,
    /// Volume walks performed so far — test instrumentation only.
    disk_refreshes: u64,
}

impl HostSampler {
    /// Construct a sampler with the [PROVISIONAL](HostThresholds) default
    /// thresholds.
    ///
    /// Why: the common case; a consumer that has no owner ruling yet gets the
    ///      documented provisional levels.
    /// What: delegates to [`HostSampler::with_thresholds`] with
    ///      `HostThresholds::default()`.
    /// Test: `sampler_produces_plausible_snapshot`.
    #[must_use]
    pub fn new() -> Self {
        Self::with_thresholds(HostThresholds::default())
    }

    /// Construct a sampler with explicit thresholds.
    ///
    /// Why: lets the eventual owner ruling (or a per-deployment config) set the
    ///      pressure levels without changing any classification code.
    /// What: builds a `System` scoped to CPU + memory (not per-process — the
    ///      whole-machine figures need no process list), refreshes CPU/memory
    ///      and the disk/network lists once to prime the deltas, and records the
    ///      priming instant.
    /// Test: `thresholds_are_configurable`.
    #[must_use]
    pub fn with_thresholds(thresholds: HostThresholds) -> Self {
        Self::with_thresholds_and_disk_interval(
            thresholds,
            Duration::from_secs(history::DISK_SAMPLE_INTERVAL_SECS),
        )
    }

    /// Construct a sampler with explicit thresholds and an explicit disk cadence.
    ///
    /// Why: disks refresh on their own, slower clock than the rest of the
    ///      sample (see [`history::DISK_SAMPLE_INTERVAL_SECS`]). A caller with a
    ///      CLI flag for it, and a test that must observe the gate without
    ///      waiting 15 s, both need to set that clock; a separate constructor
    ///      keeps the two-argument form off the existing call sites.
    /// What: as [`HostSampler::with_thresholds`], but `disk_interval` is the
    ///      minimum age of a cached [`DiskMetrics`] before the next volume walk.
    ///      A zero interval means every sample refreshes — the pre-#6517-era
    ///      behaviour, useful only in tests.
    /// Test: `disk_refresh_is_skipped_inside_the_interval`,
    ///      `disk_refresh_resumes_after_the_interval`.
    #[must_use]
    pub fn with_thresholds_and_disk_interval(
        thresholds: HostThresholds,
        disk_interval: Duration,
    ) -> Self {
        let sys = System::new_with_specifics(
            RefreshKind::nothing()
                .with_cpu(CpuRefreshKind::nothing().with_cpu_usage())
                .with_memory(MemoryRefreshKind::nothing().with_ram().with_swap()),
        );
        // Prime the network + disk deltas so the first `sample` measures a real
        // (if short) window rather than "everything since boot".
        let networks = Networks::new_with_refreshed_list();
        let disks = Disks::new_with_refreshed_list();
        Self {
            sys,
            networks,
            disks,
            last_net_refresh: Instant::now(),
            thresholds,
            disk_interval,
            last_disk_refresh: None,
            cached_disks: None,
            disk_refreshes: 0,
        }
    }

    /// Volume walks performed since construction — test instrumentation.
    ///
    /// Why: the disk cadence is invisible in the returned snapshot (a cached
    ///      `DiskMetrics` is indistinguishable from a freshly walked one), so a
    ///      test asserting that the walk was SKIPPED has to count the walks.
    /// What: the running count incremented by [`HostSampler::sample`] each time
    ///      it refreshes the disk list.
    /// Test: `disk_refresh_is_skipped_inside_the_interval`.
    #[cfg(test)]
    pub(crate) fn disk_refresh_count(&self) -> u64 {
        self.disk_refreshes
    }

    /// Refresh every subsystem and return a [`HostMetrics`] snapshot.
    ///
    /// Why: the dashboard poll calls this once per interval. As with the
    ///      per-process sampler, the CPU reading needs ~200 ms between refreshes
    ///      to be meaningful; a poll cadence of seconds satisfies that.
    ///      Disks are the exception: their refresh is the expensive part of a
    ///      sample — on macOS `sysinfo` walks every mounted volume through
    ///      `CFURLCopyResourcePropertiesForKeys` and the CacheDelete free-space
    ///      path, with os_log calls per volume, which is essentially the whole
    ///      cost of a sample and held trusty-console at a continuous ~5% CPU at
    ///      idle. So disks run on their own slower clock.
    /// What: refreshes CPU usage, memory and the network list on every call and
    ///      computes network rates over the elapsed window; refreshes the disk
    ///      list only on the FIRST call and thereafter once `disk_interval`
    ///      (default [`history::DISK_SAMPLE_INTERVAL_SECS`]) has elapsed,
    ///      serving the cached [`DiskMetrics`] unchanged in between; classifies
    ///      each subsystem against the configured thresholds; and returns the
    ///      combined snapshot. Never panics — a subsystem the OS cannot measure
    ///      reports zeros and `Nominal`.
    /// Test: `sampler_produces_plausible_snapshot`,
    ///      `disk_refresh_is_skipped_inside_the_interval`,
    ///      `disk_refresh_resumes_after_the_interval`,
    ///      `first_sample_always_refreshes_disks`.
    pub fn sample(&mut self) -> HostMetrics {
        let t = &self.thresholds;

        // ── CPU ──────────────────────────────────────────────────────────────
        self.sys.refresh_cpu_usage();
        let cpu_usage = self.sys.global_cpu_usage();
        let cpu = CpuMetrics {
            usage_pct: cpu_usage,
            logical_cores: self.sys.cpus().len(),
            physical_cores: self.sys.physical_core_count(),
            pressure: Pressure::classify(cpu_usage, t.cpu_warning_pct, t.cpu_critical_pct),
        };

        // ── memory ───────────────────────────────────────────────────────────
        self.sys.refresh_memory();
        let total = self.sys.total_memory();
        let used = self.sys.used_memory();
        let mem_pct = pct(used, total);
        let memory = MemoryMetrics {
            total_bytes: total,
            used_bytes: used,
            available_bytes: self.sys.available_memory(),
            usage_pct: mem_pct,
            swap_total_bytes: self.sys.total_swap(),
            swap_used_bytes: self.sys.used_swap(),
            pressure: Pressure::classify(mem_pct, t.memory_warning_pct, t.memory_critical_pct),
        };

        // ── disks (own slower cadence) ───────────────────────────────────────
        // The first sample always walks the volumes, so the graph is never
        // empty; after that the cached snapshot is served until the interval
        // has elapsed.
        let due = self
            .last_disk_refresh
            .is_none_or(|last| last.elapsed() >= self.disk_interval);
        if due {
            self.disks.refresh(true);
            self.last_disk_refresh = Some(Instant::now());
            self.disk_refreshes = self.disk_refreshes.saturating_add(1);
            let fresh = self.build_disk_metrics();
            self.cached_disks = Some(fresh);
        }
        let disks = self
            .cached_disks
            .clone()
            .expect("the first sample always refreshes, so the cache is populated here");

        // ── network ──────────────────────────────────────────────────────────
        self.networks.refresh(true);
        let window = self.last_net_refresh.elapsed().as_secs_f64();
        self.last_net_refresh = Instant::now();
        let network = build_network_metrics(&self.networks, window);

        let overall_pressure = cpu.pressure.worst(memory.pressure).worst(disks.pressure);

        HostMetrics {
            cpu,
            memory,
            disks,
            network,
            overall_pressure,
            sampled_at_unix: std::time::SystemTime::now()
                .duration_since(std::time::UNIX_EPOCH)
                .ok()
                .map(|d| d.as_secs()),
        }
    }

    /// Build [`DiskMetrics`] from the refreshed disk list.
    ///
    /// Why: keeps `sample` readable and isolates the "sum only real,
    ///      non-removable mounts into the aggregate" rule.
    /// What: lists every mount into `mounts`; sums total/available of
    ///      non-removable mounts into the aggregate and classifies it.
    /// Test: `sampler_produces_plausible_snapshot`.
    fn build_disk_metrics(&self) -> DiskMetrics {
        let t = &self.thresholds;
        let mut mounts = Vec::with_capacity(self.disks.list().len());
        let (mut agg_total, mut agg_avail) = (0u64, 0u64);
        for disk in self.disks.list() {
            let mount = mount_metrics_from(disk, t);
            if !mount.is_removable {
                agg_total = agg_total.saturating_add(mount.total_bytes);
                agg_avail = agg_avail.saturating_add(mount.available_bytes);
            }
            mounts.push(mount);
        }
        let agg_used = agg_total.saturating_sub(agg_avail);
        let agg_pct = pct(agg_used, agg_total);
        DiskMetrics {
            aggregate_total_bytes: agg_total,
            aggregate_available_bytes: agg_avail,
            aggregate_used_bytes: agg_used,
            aggregate_usage_pct: agg_pct,
            pressure: Pressure::classify(agg_pct, t.disk_warning_pct, t.disk_critical_pct),
            mounts,
        }
    }
}

impl Default for HostSampler {
    fn default() -> Self {
        Self::new()
    }
}

/// Sum the refreshed network interfaces into a [`NetworkMetrics`] over `window`.
///
/// Why: a free function so `sample` reads linearly and the rate math is unit
///      testable in isolation.
/// What: sums per-interface `received`/`transmitted` (the delta since the last
///      refresh) and the cumulative totals; divides the deltas by `window` for
///      the rates. A non-positive window (clock non-monotonicity, or the very
///      first instant) yields `0.0` rates rather than a division by zero.
/// Test: `network_rate_over_window`.
fn build_network_metrics(networks: &Networks, window: f64) -> NetworkMetrics {
    let (mut rx_delta, mut tx_delta, mut rx_total, mut tx_total) = (0u64, 0u64, 0u64, 0u64);
    for (_iface, data) in networks {
        rx_delta = rx_delta.saturating_add(data.received());
        tx_delta = tx_delta.saturating_add(data.transmitted());
        rx_total = rx_total.saturating_add(data.total_received());
        tx_total = tx_total.saturating_add(data.total_transmitted());
    }
    let (rx_rate, tx_rate) = if window > 0.0 {
        (rx_delta as f64 / window, tx_delta as f64 / window)
    } else {
        (0.0, 0.0)
    };
    NetworkMetrics {
        rx_bytes_per_sec: rx_rate,
        tx_bytes_per_sec: tx_rate,
        rx_total_bytes: rx_total,
        tx_total_bytes: tx_total,
        window_secs: window,
    }
}

/// Build one [`MountMetrics`] from a refreshed `sysinfo` disk.
///
/// Why: both the whole-machine snapshot and the single-mount lookup
///      ([`mount_for_path`]) need the identical shape, and a second hand-rolled
///      mapping is how the two drift into disagreeing about what `used_bytes`
///      means.
/// What: `used_bytes` is `total - available`; `usage_pct` is that over total
///      (`0.0` for a zero-capacity mount); `pressure` classifies against `t`.
/// Test: `sampler_produces_plausible_snapshot`,
///      `mount_for_path_reports_a_plausible_mount_for_the_cwd`.
fn mount_metrics_from(disk: &Disk, t: &HostThresholds) -> MountMetrics {
    let total = disk.total_space();
    let available = disk.available_space();
    let used = total.saturating_sub(available);
    let usage_pct = pct(used, total);
    MountMetrics {
        mount_point: disk.mount_point().to_string_lossy().into_owned(),
        name: disk.name().to_string_lossy().into_owned(),
        total_bytes: total,
        available_bytes: available,
        used_bytes: used,
        usage_pct,
        is_removable: disk.is_removable(),
        pressure: Pressure::classify(usage_pct, t.disk_warning_pct, t.disk_critical_pct),
    }
}

/// The usage of the mount that holds `path` (#7497).
///
/// Why: a caller that has to decide something about ONE directory — "is the
///      volume this worktree would land on nearly full?" — needs that mount,
///      not the cross-mount aggregate, which stays healthy while a single
///      volume fills. Nothing offered that lookup, so per the workspace
///      "common entry point" rule it lives here beside the sampling it reuses
///      rather than being re-derived by each consumer.
/// What: resolves `path` to its nearest EXISTING ancestor (the target of a
///      creation gate usually does not exist yet), canonicalises it, and picks
///      the mount by device id — the same `st_dev` the OS reports for the
///      ancestor and for the mount point. The device match is what makes this
///      correct on macOS, where `/Users/...` is firmlinked onto the
///      `/System/Volumes/Data` mount and is therefore NOT a lexical child of
///      its own mount point. Where `st_dev` is readable it is AUTHORITATIVE,
///      and a miss is `None`: falling back to the lexical rule there would
///      answer `/` for a path on any filesystem `sysinfo` does not enumerate
///      (NFS, sshfs, some ZFS datasets) — a wrong number rather than no number,
///      and one that makes every "could not measure" branch downstream
///      unreachable (#7497 review). The lexical rule therefore runs ONLY where
///      no device id is available (non-unix, or an unreadable probe).
///      `None` means UNMEASURABLE and the caller must decide what that costs —
///      never a silent `0`.
/// Test: `mount_for_path_reports_a_plausible_mount_for_the_cwd`,
///      `a_device_matching_no_enumerated_mount_is_unmeasurable`.
#[must_use]
pub fn mount_for_path(path: &Path) -> Option<MountMetrics> {
    let probe = nearest_existing_ancestor(path)?;
    let mounts = sample_mounts(&HostThresholds::default());
    match device_id(&probe) {
        Some(device) => select_mount_with_device(&mounts, device, device_id).cloned(),
        None => select_mount_for_path(&mounts, &probe).cloned(),
    }
}

/// The mount whose mount point is the LONGEST lexical prefix of `path`.
///
/// Why: the portable half of [`mount_for_path`], kept separate so the
///      selection rule is testable against synthetic mounts — no real
///      filesystem, no host-dependent assertion.
/// What: component-wise prefix matching (so `/var` never matches `/variable`),
///      resolving ties toward the deeper mount point, which is the nested
///      filesystem actually holding the path. `None` when nothing matches.
/// Test: `select_mount_for_path_picks_the_deepest_matching_mount`,
///      `select_mount_for_path_is_component_wise`.
#[must_use]
pub fn select_mount_for_path<'a>(
    mounts: &'a [MountMetrics],
    path: &Path,
) -> Option<&'a MountMetrics> {
    mounts
        .iter()
        .filter(|m| path.starts_with(Path::new(&m.mount_point)))
        .max_by_key(|m| Path::new(&m.mount_point).components().count())
}

/// Every mount the OS currently reports, classified against `thresholds`.
fn sample_mounts(thresholds: &HostThresholds) -> Vec<MountMetrics> {
    Disks::new_with_refreshed_list()
        .list()
        .iter()
        .map(|disk| mount_metrics_from(disk, thresholds))
        .collect()
}

/// The mount whose mount point sits on the SAME device as `path`.
///
/// Why: the firmlink case above — a lexical rule answers `/` for a path that
///      really lives on the data volume, and a gate reading the root volume's
///      4% while the data volume is at 92% never fires.
/// What: compares `device` against the `st_dev` of each mount point, deepest
///      mount point winning a tie (a nested mount shares no device with its
///      parent, so ties are rare and the deeper one is the closer answer).
///      `None` when NO enumerated mount sits on that device, which is a real
///      outcome — a filesystem `sysinfo` does not list — and is what makes the
///      unmeasurable path reachable. `device_of` is injected so that case is
///      testable without an NFS mount.
/// Test: `a_device_matching_no_enumerated_mount_is_unmeasurable`.
fn select_mount_with_device(
    mounts: &[MountMetrics],
    device: u64,
    device_of: impl Fn(&Path) -> Option<u64>,
) -> Option<&MountMetrics> {
    mounts
        .iter()
        .filter(|m| device_of(Path::new(&m.mount_point)) == Some(device))
        .max_by_key(|m| Path::new(&m.mount_point).components().count())
}

/// `st_dev` for `path`, or `None` where the platform does not expose one.
#[cfg(unix)]
fn device_id(path: &Path) -> Option<u64> {
    use std::os::unix::fs::MetadataExt;
    std::fs::metadata(path).ok().map(|m| m.dev())
}

/// No device ids off unix — [`mount_for_path`] falls back to prefix matching.
#[cfg(not(unix))]
fn device_id(_path: &Path) -> Option<u64> {
    None
}

/// The closest ancestor of `path` that exists, canonicalised.
///
/// Why: [`mount_for_path`]'s callers ask about a directory they are ABOUT to
///      create, which no `stat` can answer. Its parent is on the same mount,
///      and walking up terminates at `/`, which always exists.
/// What: makes `path` absolute against the working directory, walks its
///      ancestors, and canonicalises the first that exists (falling back to the
///      uncanonicalised form if that read fails). `None` only when no ancestor
///      exists at all.
fn nearest_existing_ancestor(path: &Path) -> Option<PathBuf> {
    let absolute = if path.is_absolute() {
        path.to_path_buf()
    } else {
        std::env::current_dir().ok()?.join(path)
    };
    absolute
        .ancestors()
        .find(|a| a.exists())
        .map(|a| a.canonicalize().unwrap_or_else(|_| a.to_path_buf()))
}

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

    /// Why: the sampler must produce a structurally valid snapshot on any CI
    ///      host without panicking, and the classification/percentage math must
    ///      stay in range. This is the one test that exercises the real OS path.
    /// What: samples twice (the second exercises the CPU/network delta path) and
    ///      asserts every percentage is finite and 0..=100, cores are sane, and
    ///      the overall pressure is the worst subsystem.
    /// Test: this test.
    #[test]
    fn sampler_produces_plausible_snapshot() {
        let mut s = HostSampler::new();
        let _first = s.sample();
        let m = s.sample();
        assert!(m.cpu.usage_pct >= 0.0 && m.cpu.usage_pct <= 100.0);
        assert!(m.cpu.logical_cores >= 1, "at least one logical core");
        assert!(m.memory.usage_pct >= 0.0 && m.memory.usage_pct <= 100.0);
        assert!(
            m.memory.total_bytes > 0,
            "a real host reports some total memory"
        );
        assert!(m.disks.aggregate_usage_pct >= 0.0 && m.disks.aggregate_usage_pct <= 100.0);
        for mount in &m.disks.mounts {
            assert!(mount.usage_pct >= 0.0 && mount.usage_pct <= 100.0);
            assert!(mount.used_bytes <= mount.total_bytes.max(mount.used_bytes));
        }
        assert!(m.network.rx_bytes_per_sec >= 0.0);
        assert!(m.network.tx_bytes_per_sec >= 0.0);
        assert!(m.network.window_secs >= 0.0);
    }

    /// Why: the disk refresh is the entire cost of a host sample on macOS
    ///      (`sysinfo` walks every mounted volume), and the console samples
    ///      every second. Running that walk per tick is what held the console
    ///      at ~5% CPU at idle, and nothing in the returned snapshot shows
    ///      whether the walk happened — only the counter does.
    /// What: with a 60 s disk interval, takes four samples and asserts exactly
    ///      one volume walk happened and every snapshot after the first served
    ///      the same cached figures.
    /// Test: this test.
    #[test]
    fn disk_refresh_is_skipped_inside_the_interval() {
        let mut s = HostSampler::with_thresholds_and_disk_interval(
            HostThresholds::default(),
            Duration::from_secs(60),
        );
        let first = s.sample();
        for _ in 0..3 {
            let later = s.sample();
            assert_eq!(
                later.disks.mounts.len(),
                first.disks.mounts.len(),
                "the cached DiskMetrics is served unchanged between refreshes"
            );
            assert_eq!(
                later.disks.aggregate_total_bytes,
                first.disks.aggregate_total_bytes
            );
            assert_eq!(
                later.disks.aggregate_available_bytes,
                first.disks.aggregate_available_bytes
            );
            assert_eq!(later.disks.pressure, first.disks.pressure);
        }
        assert_eq!(
            s.disk_refresh_count(),
            1,
            "four samples inside one 60s disk interval must walk the volumes exactly once"
        );
    }

    /// Why: a cache with no expiry would freeze the disk gauge for the life of
    ///      the daemon — a filling disk would never show as filling.
    /// What: with a 10 ms disk interval, samples, sleeps past the interval, and
    ///      samples again; asserts the second sample walked the volumes.
    /// Test: this test.
    #[test]
    fn disk_refresh_resumes_after_the_interval() {
        let mut s = HostSampler::with_thresholds_and_disk_interval(
            HostThresholds::default(),
            Duration::from_millis(10),
        );
        let _ = s.sample();
        assert_eq!(s.disk_refresh_count(), 1);
        std::thread::sleep(Duration::from_millis(25));
        let _ = s.sample();
        assert_eq!(
            s.disk_refresh_count(),
            2,
            "a sample taken after the disk interval elapsed must refresh again"
        );
    }

    /// Why: if the cadence gate also skipped the FIRST sample, the dashboard
    ///      would open with an empty disk card for up to 15 s after start.
    /// What: with a one-hour disk interval — long enough that only the
    ///      first-call rule can trigger a walk — asserts the single sample
    ///      refreshed and carries real aggregate figures.
    /// Test: this test.
    #[test]
    fn first_sample_always_refreshes_disks() {
        let mut s = HostSampler::with_thresholds_and_disk_interval(
            HostThresholds::default(),
            Duration::from_secs(3600),
        );
        let m = s.sample();
        assert_eq!(
            s.disk_refresh_count(),
            1,
            "the first sample refreshes disks regardless of the interval"
        );
        assert!(m.disks.aggregate_usage_pct >= 0.0 && m.disks.aggregate_usage_pct <= 100.0);
    }

    /// Why: the tri-state classification is the whole point of the pressure
    ///      band; an off-by-one at a boundary would mis-colour the dashboard.
    /// What: pins both boundaries and the interior of each band, plus the
    ///      NaN-is-Nominal guard.
    /// Test: this test.
    #[test]
    fn pressure_classification_boundaries() {
        // warning=80, critical=95.
        assert_eq!(Pressure::classify(79.9, 80.0, 95.0), Pressure::Nominal);
        assert_eq!(Pressure::classify(80.0, 80.0, 95.0), Pressure::Warning);
        assert_eq!(Pressure::classify(94.9, 80.0, 95.0), Pressure::Warning);
        assert_eq!(Pressure::classify(95.0, 80.0, 95.0), Pressure::Critical);
        assert_eq!(Pressure::classify(100.0, 80.0, 95.0), Pressure::Critical);
        // A subsystem that could not be measured must not panic or alarm.
        assert_eq!(Pressure::classify(f32::NAN, 80.0, 95.0), Pressure::Nominal);
    }

    /// Why: `overall_pressure` must be the WORST subsystem so the top badge
    ///      never under-reports a problem.
    /// What: exercises `Pressure::worst` across all orderings.
    /// Test: this test.
    #[test]
    fn overall_is_worst_subsystem() {
        assert_eq!(
            Pressure::Nominal.worst(Pressure::Critical),
            Pressure::Critical
        );
        assert_eq!(
            Pressure::Warning.worst(Pressure::Nominal),
            Pressure::Warning
        );
        assert_eq!(
            Pressure::Critical.worst(Pressure::Warning),
            Pressure::Critical
        );
        assert_eq!(
            Pressure::Nominal.worst(Pressure::Nominal),
            Pressure::Nominal
        );
    }

    /// Why: the thresholds are the seam the owner ruling will change; a custom
    ///      set must actually flow into classification.
    /// What: builds a sampler with a low CPU-warning threshold and asserts the
    ///      classifier used it (independently of the live CPU reading, via a
    ///      direct classify call using the configured value).
    /// Test: this test.
    #[test]
    fn thresholds_are_configurable() {
        let custom = HostThresholds {
            cpu_warning_pct: 1.0,
            cpu_critical_pct: 2.0,
            ..HostThresholds::default()
        };
        let _s = HostSampler::with_thresholds(custom);
        // The classifier is pure, so the configured numbers are what matter.
        assert_eq!(
            Pressure::classify(1.5, custom.cpu_warning_pct, custom.cpu_critical_pct),
            Pressure::Warning
        );
        assert_eq!(
            Pressure::classify(2.0, custom.cpu_warning_pct, custom.cpu_critical_pct),
            Pressure::Critical
        );
    }

    /// Why: rate math must divide the delta by the window, and a zero/negative
    ///      window must not divide by zero.
    /// What: an empty interface set over a positive window yields zero rates and
    ///      records the window; the zero-window guard is covered by the code
    ///      path (empty set → 0 delta → 0 rate regardless).
    /// Test: this test.
    #[test]
    fn network_rate_over_window() {
        let networks = Networks::new(); // empty, no refresh
        let m = build_network_metrics(&networks, 2.0);
        assert_eq!(m.rx_bytes_per_sec, 0.0);
        assert_eq!(m.tx_bytes_per_sec, 0.0);
        assert_eq!(m.window_secs, 2.0);
        let m0 = build_network_metrics(&networks, 0.0);
        assert_eq!(m0.rx_bytes_per_sec, 0.0);
    }

    /// Why: the JSON contract the phase-2 UI renders must survive a serde
    ///      round-trip with every field intact.
    /// What: samples once, serialises to JSON, deserialises back, and asserts
    ///      the top-level fields match.
    /// Test: this test.
    #[test]
    fn snapshot_serde_round_trip() {
        let mut s = HostSampler::new();
        let m = s.sample();
        let json = serde_json::to_string(&m).expect("serialise HostMetrics");
        let back: HostMetrics = serde_json::from_str(&json).expect("deserialise HostMetrics");
        assert_eq!(back.cpu.logical_cores, m.cpu.logical_cores);
        assert_eq!(back.memory.total_bytes, m.memory.total_bytes);
        assert_eq!(back.disks.mounts.len(), m.disks.mounts.len());
        assert_eq!(back.overall_pressure, m.overall_pressure);
    }

    /// A synthetic mount at `mount_point` with `usage_pct`.
    fn mount(mount_point: &str, usage_pct: f32) -> MountMetrics {
        MountMetrics {
            mount_point: mount_point.to_string(),
            name: "synthetic".to_string(),
            total_bytes: 100,
            available_bytes: 100 - usage_pct as u64,
            used_bytes: usage_pct as u64,
            usage_pct,
            is_removable: false,
            pressure: Pressure::Nominal,
        }
    }

    /// Why (#7497): a gate that picked the ROOT mount for a path living on a
    ///      nested volume reads that volume's headroom, not the one it is
    ///      about to consume.
    /// What: `/` and `/System/Volumes/Data` both prefix the probe; the deeper
    ///      mount must win.
    /// Test: this test.
    #[test]
    fn select_mount_for_path_picks_the_deepest_matching_mount() {
        let mounts = vec![mount("/", 4.0), mount("/System/Volumes/Data", 92.0)];
        let picked = select_mount_for_path(&mounts, Path::new("/System/Volumes/Data/Users/x"))
            .expect("a mount must match an absolute path when `/` is listed");
        assert_eq!(picked.mount_point, "/System/Volumes/Data");
        assert_eq!(picked.usage_pct, 92.0);
    }

    /// Why (#7497): a substring rule would match `/var` against `/variable`
    ///      and report a completely unrelated volume's usage.
    /// What: `/variable/x` must select `/`, never `/var`; a path under no
    ///      listed mount selects nothing.
    /// Test: this test.
    #[test]
    fn select_mount_for_path_is_component_wise() {
        let mounts = vec![mount("/", 4.0), mount("/var", 92.0)];
        assert_eq!(
            select_mount_for_path(&mounts, Path::new("/variable/x"))
                .expect("`/` matches")
                .mount_point,
            "/"
        );
        assert!(
            select_mount_for_path(&[mount("/var", 92.0)], Path::new("/home/x")).is_none(),
            "a path under no listed mount must be unmeasurable, not defaulted"
        );
    }

    /// Why (#7497 review): a path on a filesystem `sysinfo` does not enumerate
    ///      — NFS, sshfs, some ZFS datasets — must come back UNMEASURABLE. The
    ///      earlier lexical fallback answered `/` for it, which is a wrong
    ///      number rather than no number, and made every "could not measure"
    ///      branch downstream unreachable.
    /// What: a probe device that matches no mount's device yields `None`, with
    ///      `/` present and prefixing the path — the exact case the fallback
    ///      used to swallow.
    /// Test: this test.
    #[test]
    fn a_device_matching_no_enumerated_mount_is_unmeasurable() {
        let mounts = vec![mount("/", 4.0), mount("/System/Volumes/Data", 92.0)];
        assert!(
            select_mount_with_device(&mounts, 42, |_| Some(7)).is_none(),
            "no enumerated mount sits on the probe's device — that is \
             unmeasurable, not `/`"
        );
        assert_eq!(
            select_mount_with_device(&mounts, 7, |p| (p == Path::new("/System/Volumes/Data"))
                .then_some(7))
            .expect("the matching mount is selected")
            .mount_point,
            "/System/Volumes/Data"
        );
    }

    /// Why (#7497): the live lookup is what a creation gate calls, and it must
    ///      answer for a path that DOES NOT EXIST yet (the worktree it is
    ///      about to create).
    /// What: asks for a not-yet-created child of the working directory and
    ///      asserts a plausible mount comes back — a percentage in range and a
    ///      non-empty mount point.
    /// Test: this test.
    #[test]
    fn mount_for_path_reports_a_plausible_mount_for_the_cwd() {
        let target = std::env::current_dir()
            .expect("cwd")
            .join("does-not-exist-7497")
            .join("nor-this");
        let m = mount_for_path(&target).expect("the working directory sits on some mount");
        assert!(!m.mount_point.is_empty());
        assert!(
            (0.0..=100.0).contains(&m.usage_pct),
            "usage must be a percentage, got {}",
            m.usage_pct
        );
    }
}