facett-core 0.1.15

facett — visual kernel: render a node/edge Scene into egui (wgpu fast path to come)
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
//! **GPU LANE ATTRIBUTION** — is the app actually rendering through a GPU lane, or
//! is it silently on the CPU painter?
//!
//! [`crate::render::adapter`] answers *which device* was opened. That is only half
//! the question, and answering only that half is how a box with an RTX 4090 spent a
//! whole day painting 60 000 shapes per frame on one core: `renderer_installed()`
//! was `true`, the adapter banner said `discrete/Vulkan`, and **nothing on the GPU
//! lane was ever called**, because the pane's only consumer of it lives in another
//! crate. An About box that reads "wgpu" off the adapter alone would repeat that lie
//! in the UI.
//!
//! So this module records the *other* half, as data:
//!
//! * [`note_installed`] — a lane's renderer went into an egui-wgpu
//!   `RenderState`'s callback resources. Called ONCE, by construction, from the
//!   shared `crate::render::gpu::install_renderer` — so every lane that routes
//!   through the one install writer registers itself with no per-lane wiring.
//! * [`note_reports_frames`] — this lane promises to count encoded frames. Opt-in
//!   per lane, because the frame bump has to sit at the one point in that lane's
//!   `prepare` where real GPU work was genuinely encoded, and only the lane knows
//!   where that is.
//! * [`note_frame`] — one frame of real GPU work encoded.
//!
//! ## Why "unknown" is a first-class answer
//!
//! [`lane_use`] folds the registry into [`GpuLaneUse`]. The interesting case is
//! [`GpuLaneUse::Unknown`]: a lane is installed, no frames have been counted, and at
//! least one installed lane never promised to count any. That is exactly the state
//! where "installed but unused" would be a *guess* — the lane may well be painting
//! every frame and simply not reporting. Guessing there is the failure mode this
//! module exists to prevent, so it reports `unknown` instead and says how many lanes
//! it could not account for.
//!
//! This is lane ATTRIBUTION, not a correctness oracle (the same caveat
//! `facett_flowsim`'s `flow_frames_drawn` carries): a lane that encoded a frame of
//! nothing still bumps the counter. It answers *who painted*, which no pixel diff
//! can, and it is only ever meaningful paired with a pixel assertion.

use std::collections::BTreeMap;
use std::sync::{Mutex, OnceLock};

use super::adapter::{
    gpu_unavailable_json, is_management_display, selected_adapter, AdapterSelection,
};

/// One GPU lane's registration.
#[derive(Debug, Clone, PartialEq, Eq, serde::Serialize, serde::Deserialize)]
pub struct LaneRecord {
    /// The lane's renderer type path, e.g. `facett_map::gpu::GpuMapRenderer`
    /// (`std::any::type_name`, so it cannot drift from the type it names).
    pub name: String,
    /// A host installed this lane's renderer in this process.
    pub installed: bool,
    /// This lane promises to count encoded frames ([`note_frame`]), so a zero here
    /// MEANS "did not paint" rather than "did not say".
    pub reports_frames: bool,
    /// Frames of real GPU work this lane encoded.
    pub frames: u64,
    /// **WHY this lane sat idle**, in its owner's own words, when it last declined to
    /// paint ([`note_idle_reason`]). `None` = it never said.
    ///
    /// This exists because "installed but UNUSED" is not, on its own, a diagnosis: a
    /// lane that correctly stood aside (a camera it cannot express, nothing of its kind
    /// to draw) and a lane that is BROKEN produce the identical row, and an operator
    /// looking at the product cannot tell them apart. It cost real time on 2026-08-02:
    /// korp reported `installed but UNUSED` on an RTX 4090 and neither the About box nor
    /// several tool calls could say whether that was a correct choice or the bug.
    pub idle_reason: Option<String>,
}

impl LaneRecord {
    /// The last `::` segment — what a UI row shows (`GpuMapRenderer`).
    #[must_use]
    pub fn short_name(&self) -> &str {
        self.name.rsplit("::").next().unwrap_or(self.name.as_str())
    }
}

/// **Is a GPU lane actually in use?** The honest fold of the lane registry.
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum GpuLaneUse {
    /// No lane's renderer was installed in this process — every pane that has a CPU
    /// painter is on it. (A wgpu *device* may still be open: egui itself paints
    /// through wgpu. This is about facett's own compute/instanced lanes.)
    NotInstalled,
    /// A lane encoded `frames` frames of real GPU work.
    InUse {
        /// Frames counted across every reporting lane.
        frames: u64,
    },
    /// Every installed lane reports frames, and all of them are at zero: installed
    /// and genuinely never painted. **This is korp's map facet.**
    InstalledUnused,
    /// A lane is installed but cannot be accounted for — it never promised to count
    /// frames, so neither "in use" nor "unused" is knowable. Says so instead of
    /// picking one.
    Unknown {
        /// How many installed lanes are unaccounted for.
        silent_lanes: usize,
    },
}

impl GpuLaneUse {
    /// Stable token for `state_json`.
    #[must_use]
    pub fn as_str(self) -> &'static str {
        match self {
            GpuLaneUse::NotInstalled => "not_installed",
            GpuLaneUse::InUse { .. } => "in_use",
            GpuLaneUse::InstalledUnused => "installed_unused",
            GpuLaneUse::Unknown { .. } => "unknown",
        }
    }

    /// Frames counted (0 for every non-[`InUse`](Self::InUse) state).
    #[must_use]
    pub fn frames(self) -> u64 {
        match self {
            GpuLaneUse::InUse { frames } => frames,
            _ => 0,
        }
    }
}

// ── the registry ────────────────────────────────────────────────────────────

static LANES: OnceLock<Mutex<BTreeMap<&'static str, LaneRecord>>> = OnceLock::new();

fn lanes_slot() -> &'static Mutex<BTreeMap<&'static str, LaneRecord>> {
    LANES.get_or_init(|| Mutex::new(BTreeMap::new()))
}

fn with_lane(name: &'static str, f: impl FnOnce(&mut LaneRecord)) {
    if let Ok(mut g) = lanes_slot().lock() {
        let rec = g.entry(name).or_insert_with(|| LaneRecord {
            name: name.to_owned(),
            installed: false,
            reports_frames: false,
            frames: 0,
            idle_reason: None,
        });
        f(rec);
    }
}

/// Record that a lane's renderer was installed into a `RenderState`.
///
/// Called from the ONE shared install writer (`crate::render::gpu::install_renderer`)
/// with `std::any::type_name::<R>()`, so a new lane that uses the shared install is
/// registered without touching this module.
pub fn note_installed(name: &'static str) {
    with_lane(name, |r| r.installed = true);
}

/// Declare that this lane counts encoded frames via [`note_frame`].
///
/// Without this the lane is *silent*, and [`lane_use`] degrades to
/// [`GpuLaneUse::Unknown`] rather than claiming the lane went unused. Call it next to
/// the lane's install.
pub fn note_reports_frames(name: &'static str) {
    with_lane(name, |r| r.reports_frames = true);
}

/// Count one frame of real GPU work encoded by this lane.
///
/// Put this at the point in the lane's `prepare` where the work has actually been
/// recorded against a real device — *after* every fail-safe early-return, or the
/// counter starts claiming frames the GPU never saw. Implies both
/// [`note_installed`] and [`note_reports_frames`]: a lane cannot encode a frame
/// without being installed, and it is plainly reporting.
pub fn note_frame(name: &'static str) {
    with_lane(name, |r| {
        r.installed = true;
        r.reports_frames = true;
        r.frames += 1;
    });
}

/// **The lane has not been ASKED to draw yet** — nobody has painted the pane that owns
/// it since the process started. Not a declined lane and not a broken one.
///
/// Named here, next to the reader that classifies it, rather than as a string literal in
/// the crate that emits it: [`GpuStatus::lane_line`] has to recognise this exact token to
/// avoid printing a sentence that contradicts the very next row (LAW #5 — one writer for
/// a value two crates agree on).
pub const PANE_NOT_PAINTED_YET: &str = "pane_not_painted_yet";

/// **The lane was CHOSEN this frame and has not encoded yet.** The facet picked the GPU,
/// handed egui the callback, and no frame has come out the other side — a covered,
/// clipped or just-mounted pane produces no GPU work, which is correct.
pub const AWAITING_FIRST_ENCODE: &str = "awaiting_first_encode";

/// The reasons that mean **"nothing has asked this lane to draw"**, as opposed to
/// "the lane was offered the work and declined it".
///
/// The distinction is the whole point: a lane that declined (`rotated_camera`,
/// `no_line_ways`) really did leave the work to the CPU painter, and saying so is
/// accurate. A lane in one of the states below did not — **there is no CPU painter doing
/// its work either, because the pane it belongs to has not been drawn at all**. Printing
/// the same sentence for both is what made korp's About box read as a fault on a healthy
/// RTX 4090; see [`GpuStatus::lane_line`].
pub const NOT_YET_DRAWN_REASONS: [&str; 2] = [PANE_NOT_PAINTED_YET, AWAITING_FIRST_ENCODE];

/// **Say why this lane is not painting**, so "installed but UNUSED" stops being
/// ambiguous. `Some(reason)` when the lane's owner chose another route this frame,
/// `None` when it is painting.
///
/// The reason is the OWNER's, because only the owner knows: `facett_map`'s `MapFacet`
/// reports `rotated_camera` / `no_renderer` / `no_line_ways` / `not_compiled`. A lane
/// that declined for a good reason and a lane that is broken must not render the same
/// row — that ambiguity is what this whole module exists to remove, and leaving it at
/// the lane level would have re-created it one level up.
pub fn note_idle_reason(name: &'static str, reason: Option<&str>) {
    with_lane(name, |r| {
        // Only overwrite with a real reason, or clear it deliberately; a caller that
        // does not know must not erase a reason another writer supplied.
        r.idle_reason = reason.map(str::to_owned);
    });
}

/// The reason ONE lane last gave for standing aside (`None` = it never said).
#[must_use]
pub fn idle_reason_of(name: &str) -> Option<String> {
    lanes_slot().lock().ok().and_then(|g| g.get(name).and_then(|r| r.idle_reason.clone()))
}

/// Every registered lane, name-ordered.
#[must_use]
pub fn lanes() -> Vec<LaneRecord> {
    lanes_slot().lock().map(|g| g.values().cloned().collect()).unwrap_or_default()
}

/// **Frames ONE lane has encoded** — `0` for a lane that never registered.
///
/// The cheap read: [`lanes`] clones every record's `String` name, which is fine for an
/// About box and wasteful for something a per-frame paint path consults. And a paint
/// path genuinely needs it: `facett_map::layer::MapFacet` latches its upload-once VRAM
/// bake on "has a frame actually been encoded since I handed the geometry over", because
/// egui may DISCARD the frame a payload rode on (a sizing pass is one) — and a host that
/// latched on the *handover* would never re-send it, leaving the lane at zero frames
/// forever. That is the [`GpuLaneUse::InstalledUnused`] disease reappearing one level
/// down, so the ack is read from the same counter the About box reports.
#[must_use]
pub fn frames_of(name: &str) -> u64 {
    lanes_slot().lock().map(|g| g.get(name).map_or(0, |r| r.frames)).unwrap_or(0)
}

/// **THE fold**: is a GPU lane in use, installed-but-unused, absent — or unknowable?
#[must_use]
pub fn lane_use() -> GpuLaneUse {
    fold_lane_use(&lanes())
}

/// The pure fold [`lane_use`] applies, so the policy is testable without touching
/// the process-global registry.
#[must_use]
pub fn fold_lane_use(lanes: &[LaneRecord]) -> GpuLaneUse {
    let live: Vec<&LaneRecord> = lanes.iter().filter(|l| l.installed || l.frames > 0).collect();
    if live.is_empty() {
        return GpuLaneUse::NotInstalled;
    }
    let frames: u64 = live.iter().map(|l| l.frames).sum();
    if frames > 0 {
        return GpuLaneUse::InUse { frames };
    }
    let silent = live.iter().filter(|l| !l.reports_frames).count();
    if silent == 0 {
        GpuLaneUse::InstalledUnused
    } else {
        GpuLaneUse::Unknown { silent_lanes: silent }
    }
}

/// Clear the registry. **Tests only** — the registry is a process-global and a test
/// that asserts a fold needs a known starting point.
#[doc(hidden)]
pub fn reset_for_test() {
    if let Ok(mut g) = lanes_slot().lock() {
        g.clear();
    }
}

// ── the whole GPU story, as one value ───────────────────────────────────────

/// **What a UI shows about the GPU**: which adapter, which backend, which device
/// class, how many adapters were enumerated, and whether a GPU lane is really being
/// used.
///
/// One value so the About card, a status bar and a robot assertion all read the same
/// facts through the same formatting (LAW #5), instead of each re-deriving "is this
/// software?" from `AdapterInfo` and getting it subtly differently.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct GpuStatus {
    /// The adapter selection the host recorded at startup; `None` when no GPU
    /// backend was brought up in this process (a CPU-painter build, or headless).
    pub adapter: Option<AdapterSelection>,
    /// A recorded bring-up FAILURE (`facet-gpu-<n>` + remedy), if there was one.
    pub unavailable: Option<serde_json::Value>,
    /// The lane fold.
    pub lane: GpuLaneUse,
    /// Every registered lane (what the fold was computed from).
    pub lanes: Vec<LaneRecord>,
}

impl GpuStatus {
    /// Read the live process globals: the recorded adapter selection, any recorded
    /// bring-up failure, and the lane registry.
    #[must_use]
    pub fn probe() -> Self {
        let lanes = lanes();
        let un = gpu_unavailable_json();
        Self {
            adapter: selected_adapter(),
            unavailable: if un.is_null() { None } else { Some(un) },
            lane: fold_lane_use(&lanes),
            lanes,
        }
    }

    /// A status with nothing recorded — what a headless CPU build honestly reports.
    #[must_use]
    pub fn none() -> Self {
        Self { adapter: None, unavailable: None, lane: GpuLaneUse::NotInstalled, lanes: Vec::new() }
    }

    /// Build a status from an explicit selection + lane list (tests, and a host that
    /// wants to show a decision it has in hand rather than the global).
    #[must_use]
    pub fn of(adapter: Option<AdapterSelection>, lanes: Vec<LaneRecord>) -> Self {
        Self { adapter, unavailable: None, lane: fold_lane_use(&lanes), lanes }
    }

    /// **Is the app rendering on a CPU software rasteriser?** Taken from the
    /// selection's `software` flag, which is computed by name AND device class — so
    /// llvmpipe reporting itself as `DiscreteGpu` is still software here. Never read
    /// `kind` alone for this question.
    #[must_use]
    pub fn is_software(&self) -> bool {
        self.adapter.as_ref().is_some_and(|s| s.software)
    }

    /// How many adapters the host enumerated (0 when no backend came up).
    #[must_use]
    pub fn adapter_count(&self) -> usize {
        self.adapter.as_ref().map_or(0, |s| s.considered.len())
    }

    /// The device class as a UI shows it: **`SOFTWARE (CPU rasteriser)`** for
    /// llvmpipe/lavapipe/SwiftShader whatever they claim to be, `management console
    /// (BMC)` for an ASPEED/Matrox framebuffer, else the adapter's own class.
    #[must_use]
    pub fn device_class(&self) -> String {
        match &self.adapter {
            None => "none".to_owned(),
            Some(s) if s.software => "SOFTWARE (CPU rasteriser)".to_owned(),
            Some(s) if is_management_display(&s.chosen) => "management console (BMC)".to_owned(),
            Some(s) => s.chosen.kind.as_str().to_owned(),
        }
    }

    /// Row 1 — the adapter name.
    #[must_use]
    pub fn adapter_line(&self) -> String {
        match &self.adapter {
            Some(s) => format!("GPU: {}", s.chosen.name),
            None => "GPU: none — no adapter was brought up in this process".to_owned(),
        }
    }

    /// Row 2 — backend · device class · how many adapters were enumerated.
    #[must_use]
    pub fn detail_line(&self) -> String {
        match &self.adapter {
            Some(s) => format!(
                "{} · {} · {} adapter(s) enumerated{}",
                if s.chosen.backend.is_empty() { "?" } else { s.chosen.backend.as_str() },
                self.device_class(),
                s.considered.len(),
                if s.forced { " · FORCED" } else { "" },
            ),
            None => "no backend · no adapter enumerated".to_owned(),
        }
    }

    /// Row 3 — the honest lane answer.
    #[must_use]
    pub fn lane_line(&self) -> String {
        let names = |only_used: bool| -> String {
            let v: Vec<&str> = self
                .lanes
                .iter()
                .filter(|l| if only_used { l.frames > 0 } else { l.installed })
                .map(LaneRecord::short_name)
                .collect();
            if v.is_empty() { "".to_owned() } else { v.join(", ") }
        };
        match self.lane {
            GpuLaneUse::InUse { frames } => {
                format!("GPU lane: IN USE — {frames} frame(s) encoded by {}", names(true))
            }
            // **"the CPU painter is doing the work" is a CLAIM, and it is false whenever
            // nothing has drawn the pane.** MEASURED 2026-08-03 on the shipped korp-ui, in
            // the posture a human lands in (korp opens on 🧊 Tables, and the map lane
            // belongs to the 🗺 Map pane):
            //
            //   GPU lane: installed but UNUSED — CloudRenderer, GpuMapRenderer drew 0
            //             frames (the CPU painter is doing the work)
            //   idle because — GpuMapRenderer: pane_not_painted_yet
            //
            // Two adjacent rows contradicting each other: no CPU painter was doing that
            // lane's work, because no map was being drawn by anything. That headline is
            // the exact sentence Rickard has been reading all day and reasonably taking
            // for a broken GPU on a 4090.
            //
            // So the claim is made only when it is TRUE — when at least one idle lane
            // actually DECLINED the work (`rotated_camera`, `no_line_ways`, …). When every
            // idle lane is merely un-drawn ([`NOT_YET_DRAWN_REASONS`]) the row says that
            // instead, and the `idle because` row below still names which lane and why.
            GpuLaneUse::InstalledUnused if self.every_idle_lane_is_undrawn() => format!(
                "GPU lane: installed, NOT YET DRAWN — {} has not been asked to paint (no CPU painter is doing its work either)",
                names(false)
            ),
            GpuLaneUse::InstalledUnused => format!(
                "GPU lane: installed but UNUSED — {} drew 0 frames (the CPU painter is doing the work)",
                names(false)
            ),
            GpuLaneUse::NotInstalled => {
                "GPU lane: not installed — the CPU painter owns every pane".to_owned()
            }
            GpuLaneUse::Unknown { silent_lanes } => format!(
                "GPU lane: unknown — {silent_lanes} installed lane(s) ({}) do not report frames",
                names(false)
            ),
        }
    }

    /// **Has EVERY idle lane merely not been drawn yet** (as opposed to having declined
    /// the work)? Drives the [`lane_line`](Self::lane_line) split above.
    ///
    /// `false` when a single idle lane declined for a reason of its own, or stayed silent
    /// — silence is not evidence of un-drawn-ness, and over-claiming here would swap one
    /// wrong sentence for another. `false` on no idle lanes at all, so a live lane never
    /// reaches this arm.
    #[must_use]
    pub fn every_idle_lane_is_undrawn(&self) -> bool {
        let mut idle = self.lanes.iter().filter(|l| l.installed && l.frames == 0).peekable();
        idle.peek().is_some()
            && idle.all(|l| {
                l.idle_reason.as_deref().is_some_and(|r| NOT_YET_DRAWN_REASONS.contains(&r))
            })
    }

    /// Row 4 — a recorded bring-up failure's code + remedy, when there was one.
    #[must_use]
    pub fn unavailable_line(&self) -> Option<String> {
        let u = self.unavailable.as_ref()?;
        Some(format!(
            "{}{}",
            u["code"].as_str().unwrap_or("facet-gpu-?"),
            u["remedy"].as_str().unwrap_or("(no remedy recorded)")
        ))
    }

    /// Every row, in paint order — the ONE writer a UI and a robot both read, so the
    /// assertion cannot drift from the pixels.
    #[must_use]
    pub fn rows(&self) -> Vec<String> {
        let mut v = vec![self.adapter_line(), self.detail_line(), self.lane_line()];
        v.extend(self.idle_reason_line());
        v.extend(self.unavailable_line());
        v
    }

    /// Row 3b — **WHY each idle lane is idle**, in its owner's words.
    ///
    /// Its OWN row rather than a tail on [`lane_line`](Self::lane_line): that line is
    /// already long enough to reach the edge of korp's About card, and a reason appended
    /// to it was MEASURED clipped off-screen on 2026-08-02 — a diagnosis nobody can read
    /// is no better than the ambiguity it was added to remove.
    ///
    /// `None` when every lane is painting, or when no idle lane has been taught to
    /// explain itself: silence is a truthful "nobody said", never a guess.
    #[must_use]
    pub fn idle_reason_line(&self) -> Option<String> {
        let v: Vec<String> = self
            .lanes
            .iter()
            .filter(|l| l.frames == 0)
            .filter_map(|l| l.idle_reason.as_ref().map(|r| format!("{}: {r}", l.short_name())))
            .collect();
        if v.is_empty() { None } else { Some(format!("idle because — {}", v.join("; "))) }
    }

    /// The `state_json` fragment.
    #[must_use]
    pub fn to_json(&self) -> serde_json::Value {
        serde_json::json!({
            "adapter": match &self.adapter {
                Some(s) => s.to_json(),
                None => serde_json::Value::Null,
            },
            "adapter_count": self.adapter_count(),
            "backend": self.adapter.as_ref().map(|s| s.chosen.backend.clone()),
            "device_class": self.device_class(),
            "software": self.is_software(),
            "lane": self.lane.as_str(),
            "lane_frames": self.lane.frames(),
            "lanes": self.lanes,
            "unavailable": self.unavailable.clone().unwrap_or(serde_json::Value::Null),
            "rows": self.rows(),
        })
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::render::adapter::{AdapterFacts, AdapterKind, VENDOR_MESA, VENDOR_NVIDIA};

    fn nvidia() -> AdapterFacts {
        AdapterFacts::new("NVIDIA GeForce RTX 4090", AdapterKind::DiscreteGpu, "Vulkan")
            .with_vendor(VENDOR_NVIDIA)
    }
    fn llvmpipe() -> AdapterFacts {
        AdapterFacts::new("llvmpipe (LLVM 21.1.8, 256 bits)", AdapterKind::Cpu, "Vulkan")
            .with_vendor(VENDOR_MESA)
    }
    fn lane(name: &str, installed: bool, reports: bool, frames: u64) -> LaneRecord {
        LaneRecord { name: name.to_owned(), installed, reports_frames: reports, frames, idle_reason: None }
    }

    /// **RED-when-broken: the headline must not claim a CPU painter is doing work that
    /// nobody is doing.**
    ///
    /// MEASURED on the shipped korp-ui 2026-08-03, in the posture a human actually lands
    /// in (korp opens on 🧊 Tables; the map lane belongs to the 🗺 Map pane), on a real
    /// Xvfb window with the RTX 4090 selected:
    ///
    /// ```text
    /// GPU lane: installed but UNUSED — CloudRenderer, GpuMapRenderer drew 0 frames
    ///           (the CPU painter is doing the work)
    /// idle because — GpuMapRenderer: pane_not_painted_yet
    /// ```
    ///
    /// Two adjacent rows that contradict each other. No CPU painter was drawing that
    /// lane's work — nothing was drawing a map at all. That parenthesis is the sentence
    /// Rickard read all day and reasonably took for a broken GPU. `idle_reason` alone did
    /// not fix it, because the headline is the line the eye lands on first.
    ///
    /// The negative leg matters as much: a lane that genuinely DECLINED
    /// (`rotated_camera`) really did leave the work to the CPU painter, and must keep
    /// saying so — otherwise this "fix" just installs a different wrong sentence.
    #[test]
    fn an_undrawn_lane_is_not_reported_as_the_cpu_painter_doing_the_work() {
        let undrawn = |name: &str, reason: &str| LaneRecord {
            idle_reason: Some(reason.to_owned()),
            ..lane(name, true, true, 0)
        };
        let status = |lanes: Vec<LaneRecord>| GpuStatus {
            adapter: None,
            unavailable: None,
            lane: fold_lane_use(&lanes),
            lanes,
        };

        // korp's exact measured shape: both installed lanes idle, both merely un-drawn.
        let korp = status(vec![
            undrawn("facett_core::render::gpu::graphcloud::cloud::CloudRenderer", PANE_NOT_PAINTED_YET),
            undrawn("facett_map::gpu::GpuMapRenderer", PANE_NOT_PAINTED_YET),
        ]);
        assert!(korp.every_idle_lane_is_undrawn());
        let line = korp.lane_line();
        assert!(
            !line.contains("the CPU painter is doing the work"),
            "nothing was drawing this lane's pane, so nothing was doing its work: {line}",
        );
        assert!(line.contains("NOT YET DRAWN"), "the row must say what is actually true: {line}");
        // The reason row still names WHICH lane and WHY — the headline replaces nothing.
        assert!(
            korp.rows().iter().any(|r| r.contains("GpuMapRenderer: pane_not_painted_yet")),
            "{:?}",
            korp.rows(),
        );

        // A lane chosen this frame that has not encoded yet is the same class of answer.
        let chosen = status(vec![undrawn("facett_map::gpu::GpuMapRenderer", AWAITING_FIRST_ENCODE)]);
        assert!(!chosen.lane_line().contains("the CPU painter is doing the work"));

        // ── THE NEGATIVE LEG. A lane that DECLINED the work left it to the CPU painter,
        //    and that sentence is true and must survive.
        let declined = status(vec![undrawn("facett_map::gpu::GpuMapRenderer", "rotated_camera")]);
        assert!(!declined.every_idle_lane_is_undrawn());
        assert!(
            declined.lane_line().contains("the CPU painter is doing the work"),
            "a declined lane really did hand the work over: {}",
            declined.lane_line(),
        );

        // ── AND A SILENT LANE IS NOT EVIDENCE. One lane that never said why is enough to
        //    withhold the claim in either direction — this is the arm that made me teach
        //    CloudRenderer to speak rather than weaken the predicate.
        let mixed = status(vec![
            lane("facett_core::render::gpu::graphcloud::cloud::CloudRenderer", true, true, 0),
            undrawn("facett_map::gpu::GpuMapRenderer", PANE_NOT_PAINTED_YET),
        ]);
        assert!(
            !mixed.every_idle_lane_is_undrawn(),
            "a lane that never explained itself cannot be counted as un-drawn",
        );
    }

    /// **RED-when-broken: an idle lane's REASON reaches the row a human reads.**
    ///
    /// `installed but UNUSED — … drew 0 frames (the CPU painter is doing the work)` is
    /// every word true of a lane that correctly stood aside AND of a lane that is broken.
    /// On 2026-08-02 korp printed exactly that on an RTX 4090 while nothing was wrong —
    /// the map pane simply had not been painted yet (modal infra chooser, landing tab is
    /// Tables) — and neither Rickard nor a coordinating agent could tell which it was by
    /// looking at the product. A diagnostic that cannot separate "correct" from "broken"
    /// is the same disease this module was written to cure, one level up.
    #[test]
    fn an_idle_lane_names_its_reason_in_the_row_a_human_reads() {
        let mut rec = lane("facett_map::gpu::GpuMapRenderer", true, true, 0);
        let bare = GpuStatus {
            adapter: None,
            unavailable: None,
            lane: fold_lane_use(std::slice::from_ref(&rec)),
            lanes: vec![rec.clone()],
        };
        let bare_rows = bare.rows();
        assert!(bare_rows.iter().any(|r| r.contains("installed but UNUSED")), "{bare_rows:?}");
        assert!(
            !bare_rows.iter().any(|r| r.contains("idle because")),
            "a lane that never explained itself must not have words put in its mouth: {bare_rows:?}"
        );
        assert_eq!(bare.idle_reason_line(), None);

        // Now the lane says why. The SAME fold, the SAME state — only the reason added.
        rec.idle_reason = Some("pane_not_painted_yet".to_owned());
        let told = GpuStatus {
            adapter: None,
            unavailable: None,
            lane: fold_lane_use(std::slice::from_ref(&rec)),
            lanes: vec![rec.clone()],
        };
        let told_rows = told.rows();
        assert_ne!(bare_rows, told_rows, "the reason must CHANGE what a human reads, or it is not reaching them");
        assert!(
            told_rows.iter().any(|r| r == "idle because — GpuMapRenderer: pane_not_painted_yet"),
            "the reason must be its OWN row, naming lane and reason: {told_rows:?}"
        );
        // …and it must NOT be pasted onto the already-edge-reaching lane line, where it
        // was measured clipped off korp's About card.
        assert!(
            !told.lane_line().contains("pane_not_painted_yet"),
            "the reason belongs on its own row: {}",
            told.lane_line()
        );

        // A PAINTING lane must not be slandered with a stale reason, and a mixed process
        // (korp: map lane painting, graph-3D lane idle with no graph open) must report
        // both halves — `InUse` overall, and WHY the other one sat out.
        let painting = lane("facett_map::gpu::GpuMapRenderer", true, true, 7);
        let mut idle_other = lane("facett_graph3d::gpu::CloudRenderer", true, true, 0);
        idle_other.idle_reason = Some("no_graph_open".to_owned());
        let mixed = GpuStatus {
            adapter: None,
            unavailable: None,
            lane: fold_lane_use(&[painting.clone(), idle_other.clone()]),
            lanes: vec![painting, idle_other],
        };
        let mixed_rows = mixed.rows();
        assert!(mixed_rows.iter().any(|r| r.contains("IN USE — 7 frame(s)")), "{mixed_rows:?}");
        assert!(
            !mixed_rows.iter().any(|r| r.contains("GpuMapRenderer: ")),
            "the lane that PAINTED must not be listed as idle: {mixed_rows:?}"
        );
        assert!(
            mixed_rows.iter().any(|r| r == "idle because — CloudRenderer: no_graph_open"),
            "the idle lane's reason must survive alongside a painting one: {mixed_rows:?}"
        );
    }

    /// **RED-when-broken: the four lane states are distinct and none is guessed.**
    ///
    /// The one that matters is the last: a silent installed lane must fold to
    /// `Unknown`, NOT to `InstalledUnused`. Claiming "unused" there is a guess about
    /// a lane that never reported, and it is the exact overstatement an About box
    /// must not make.
    #[test]
    fn the_lane_fold_never_guesses() {
        assert_eq!(fold_lane_use(&[]), GpuLaneUse::NotInstalled);
        // Registered-but-not-installed is still "not installed".
        assert_eq!(fold_lane_use(&[lane("A", false, true, 0)]), GpuLaneUse::NotInstalled);
        // Reporting lane at zero → genuinely unused (korp's map facet).
        assert_eq!(fold_lane_use(&[lane("A", true, true, 0)]), GpuLaneUse::InstalledUnused);
        // Any frame at all → in use, summed across lanes.
        assert_eq!(
            fold_lane_use(&[lane("A", true, true, 7), lane("B", true, true, 5)]),
            GpuLaneUse::InUse { frames: 12 }
        );
        // A SILENT installed lane is unknowable — never "unused".
        assert_eq!(
            fold_lane_use(&[lane("A", true, false, 0)]),
            GpuLaneUse::Unknown { silent_lanes: 1 },
            "a lane that never promised to count frames must fold to unknown, not to unused"
        );
        // Mixed: one reporting-at-zero + one silent is still unknown.
        assert_eq!(
            fold_lane_use(&[lane("A", true, true, 0), lane("B", true, false, 0)]),
            GpuLaneUse::Unknown { silent_lanes: 1 }
        );
        // …but a real frame from the reporting lane settles it.
        assert_eq!(
            fold_lane_use(&[lane("A", true, true, 3), lane("B", true, false, 0)]),
            GpuLaneUse::InUse { frames: 3 }
        );
    }

    /// **RED-when-broken — THE headline: a software adapter can never read as
    /// discrete.** llvmpipe that *reports itself* `DeviceType::DiscreteGpu` (a
    /// lying ICD, and the shape `is_software_rasteriser` exists to catch) must still
    /// show `SOFTWARE` in the row and `software: true` in the json. If this goes red,
    /// the About box tells a 4090 story on a CPU rasteriser — the failure the rows
    /// exist to expose.
    #[test]
    fn a_lying_software_adapter_still_reads_software() {
        let liar = AdapterFacts::new("llvmpipe (LLVM 21.1.8)", AdapterKind::DiscreteGpu, "Vulkan")
            .with_vendor(VENDOR_MESA);
        let st = GpuStatus::of(AdapterSelection::decide(&[liar], None), vec![]);
        assert!(st.is_software(), "llvmpipe is software however it classes itself");
        assert_eq!(st.device_class(), "SOFTWARE (CPU rasteriser)");
        assert!(
            st.detail_line().contains("SOFTWARE"),
            "the row must say SOFTWARE: {}",
            st.detail_line()
        );
        assert!(
            !st.detail_line().contains("discrete"),
            "the row must NOT call a software rasteriser discrete: {}",
            st.detail_line()
        );
        assert_eq!(st.to_json()["software"], serde_json::json!(true));
        assert_eq!(st.to_json()["device_class"], serde_json::json!("SOFTWARE (CPU rasteriser)"));
    }

    /// The real oden enumeration: the rows name the card, the backend, the class and
    /// the adapter count, and the json carries the same facts.
    #[test]
    fn rows_carry_adapter_backend_class_and_count() {
        let st = GpuStatus::of(
            AdapterSelection::decide(&[llvmpipe(), nvidia()], None),
            vec![lane("facett_map::gpu::GpuMapRenderer", true, true, 42)],
        );
        let rows = st.rows();
        assert!(rows[0].contains("NVIDIA GeForce RTX 4090"), "{:?}", rows);
        assert!(rows[1].contains("Vulkan"), "{:?}", rows);
        assert!(rows[1].contains("discrete"), "{:?}", rows);
        assert!(rows[1].contains("2 adapter(s)"), "the count of enumerated adapters: {:?}", rows);
        assert!(rows[2].contains("IN USE") && rows[2].contains("42"), "{:?}", rows);
        assert!(rows[2].contains("GpuMapRenderer"), "the lane is named: {:?}", rows);
        assert!(!st.is_software());

        let j = st.to_json();
        assert_eq!(j["backend"], serde_json::json!("Vulkan"));
        assert_eq!(j["device_class"], serde_json::json!("discrete"));
        assert_eq!(j["adapter_count"], serde_json::json!(2));
        assert_eq!(j["lane"], serde_json::json!("in_use"));
        assert_eq!(j["lane_frames"], serde_json::json!(42));
        assert_eq!(j["rows"].as_array().expect("rows").len(), 3);
    }

    /// No GPU at all: the rows must SAY so rather than going blank, and the json
    /// keys must still exist so a robot can tell "no GPU" from "key missing".
    #[test]
    fn a_gpu_less_process_says_so() {
        let st = GpuStatus::none();
        assert!(st.adapter_line().contains("none"), "{}", st.adapter_line());
        assert!(st.lane_line().contains("not installed"), "{}", st.lane_line());
        let j = st.to_json();
        assert!(j["adapter"].is_null());
        assert_eq!(j["lane"], serde_json::json!("not_installed"));
        assert_eq!(j["software"], serde_json::json!(false));
        assert_eq!(j["adapter_count"], serde_json::json!(0));
    }

    /// The registry accumulates through the public notes, and `note_frame` implies
    /// both installed and reporting (a lane cannot encode a frame otherwise).
    #[test]
    fn the_registry_records_what_the_lanes_report() {
        reset_for_test();
        note_installed("test::LaneA");
        assert_eq!(lane_use(), GpuLaneUse::Unknown { silent_lanes: 1 });
        note_reports_frames("test::LaneA");
        assert_eq!(lane_use(), GpuLaneUse::InstalledUnused);
        note_frame("test::LaneB");
        assert_eq!(lane_use(), GpuLaneUse::InUse { frames: 1 });
        let recs = lanes();
        let b = recs.iter().find(|l| l.name == "test::LaneB").expect("LaneB registered");
        assert!(b.installed && b.reports_frames && b.frames == 1);
        assert_eq!(b.short_name(), "LaneB");
        reset_for_test();
        assert_eq!(lane_use(), GpuLaneUse::NotInstalled);
    }
}