src/viz/bloodstream_tab.rs
//! 🩸 **Bloodstream tab** — the workspace rendered as a living *circulatory
//! system* (the "blodomlopp"), painted natively in egui over the pure
//! [`super::bloodstream::Organism`] model.
//!
//! Crates are **organs** seated at anatomical body positions (the busiest hub
//! beats at the **heart**); dependency edges are **arteries** with **blood
//! corpuscles** streaming along them, driven by an injected clock (FC-7). Click an
//! organ to **drill in**: its entire transitive crates.io dependency closure —
//! the deps-of-deps, excluding workspace members — is pulled live from a
//! `Cargo.lock` and blooms outward as **capillary** rings by recursion depth.
//!
//! The view is a [`facett_jobview::Facet`] (== `facett_core::Facet`) so the
//! robot-UI harness introspects it uniformly: [`Facet::state_json`] delegates to
//! the organism, so the drawn body — organs, vessels, flow phase, and the loaded
//! recursive external layer — is asserted as DATA (LAW #6), no screenshot needed.
use std::path::Path;
use egui::{Align2, Color32, CornerRadius, FontId, Pos2, Sense, Stroke, Vec2};
use facett_jobview::Facet; // == facett_core::Facet (both re-export the 0.1 trait)
use super::bloodstream::{Organism, member_edges, workspace_members};
use super::facett_theme::Theme;
use super::model::Timeline;
/// nornir's **own** committed lockfile, embedded at build time. The bloodstream's
/// default blood supply: when there is no live warehouse snapshot yet, the body is
/// built from — and every drill-down resolves against — nornir's real dependency
/// closure, so the view is never a demo and the recursion is always real data.
const NORNIR_LOCK: &str = include_str!("../../Cargo.lock");
/// How many recursion rings a drill-down pulls (bounds the deps-of-deps walk so a
/// single organ can't drag the whole crates.io universe in at once).
const DRILL_DEPTH: usize = 4;
/// 🩸 The Bloodstream tab pane — a native egui host around the pure [`Organism`].
pub struct BloodstreamView {
title: String,
organism: Organism,
/// The `(source, crate_count, edge_count)` signature the current organism was
/// built from — rebuild only when the underlying workspace data changes, so
/// drill-down state survives across animation frames.
built_sig: Option<(String, usize, usize)>,
/// The `Cargo.lock` text drill-downs resolve against (nornir's own by default;
/// a live local workspace overrides it with the selected repo's lock).
lock_text: String,
/// Human label of the current lock/data source (folded into `state_json`).
lock_source: String,
theme: Theme,
/// **Pinned animation clock** (seconds; FC-7). `Some` ⇒ the blood phase is a
/// pure function of this value (deterministic headless render); `None` ⇒ follow
/// egui's ambient `input.time` (the live UX).
clock_pinned: Option<f64>,
/// Render tallies for the emit-doctrine marker (organs/capillaries painted).
painted_organs: usize,
painted_capillaries: usize,
}
impl Default for BloodstreamView {
fn default() -> Self {
Self {
title: "🩸 Bloodstream".into(),
organism: Organism::default(),
built_sig: None,
lock_text: NORNIR_LOCK.to_string(),
lock_source: "nornir Cargo.lock (embedded)".into(),
theme: Theme::default(),
clock_pinned: None,
painted_organs: 0,
painted_capillaries: 0,
}
}
}
impl BloodstreamView {
/// Discovery-contract ctor (the no-arg surface the test matrix enumerates).
pub fn local() -> Self {
Self::default()
}
/// Set the active facett palette (C8) — re-skins the body's organs/vessels.
pub fn set_palette(&mut self, t: Theme) {
self.theme = t;
}
/// **Pin the animation clock** (seconds; FC-7) so the blood flow is
/// reproducible: identical organism + clock ⇒ identical frame + state dump.
pub fn set_clock(&mut self, seconds: f64) {
self.clock_pinned = Some(seconds);
self.organism.set_clock(seconds);
}
/// Feed the live workspace: rebuild the organism from the timeline's crates +
/// dep edges when they change, else keep the current (drill-down-preserving)
/// body. Falls back to nornir's own embedded lockfile so the body is always
/// real, never blank. `workspace_root/<repo>/Cargo.lock` (or the root lock)
/// becomes the drill-down source when a local checkout is present.
fn rebuild_if_needed(&mut self, tl: Option<&Timeline>, workspace_root: &Path) {
// Prefer live snapshot data (crates = lanes, edges = latest snapshot).
let live = tl.and_then(|t| {
let crates: Vec<String> = t.lanes.iter().map(|l| l.repo.clone()).collect();
if crates.is_empty() {
return None;
}
let edges = t
.latest_snapshot
.as_ref()
.map(|s| s.edges.clone())
.unwrap_or_default();
Some((crates, edges))
});
let (source, crates, edges, lock) = match live {
Some((crates, edges)) => {
// A local checkout's lockfile makes the drill-down that workspace's
// real closure; otherwise resolve against nornir's own embedded lock.
let (lock, lock_src) = local_lock(&crates, workspace_root).unwrap_or_else(|| {
(
NORNIR_LOCK.to_string(),
"nornir Cargo.lock (embedded)".into(),
)
});
(format!("live:{lock_src}"), crates, edges, lock)
}
None => {
// No live snapshot yet — build the body from nornir's OWN workspace
// members + their intra-workspace edges, resolved from the embedded
// lock. Real crates, real arteries, real drill-down. Not a demo.
(
"nornir Cargo.lock (embedded)".to_string(),
workspace_members(NORNIR_LOCK),
member_edges(NORNIR_LOCK),
NORNIR_LOCK.to_string(),
)
}
};
let sig = (source.clone(), crates.len(), edges.len());
if self.built_sig.as_ref() == Some(&sig) {
return;
}
self.built_sig = Some(sig);
self.lock_text = lock;
self.lock_source = source;
self.organism = Organism::build(&crates, &edges);
}
/// Toggle a crate's drill-down (its recursive external closure), the
/// robot-addressable equivalent of clicking the organ. Ensures a body exists
/// first so a headless driver can expand without a prior paint. Returns the
/// number of external deps now attached.
fn expand(&mut self, crate_name: &str) -> usize {
if self.organism.organs.is_empty() {
self.rebuild_if_needed(None, Path::new(""));
}
self.organism.selected = Some(crate_name.to_string());
self.organism
.toggle_expand(crate_name, &self.lock_text, DRILL_DEPTH)
}
/// **R6 robot-drive** — apply a `bloodstream.<action>` control-channel button.
/// `expand:<crate>` drills into (or collapses) that organ; `collapse_all`
/// drops every drill-down. Returns `Err` for an unknown action.
pub(crate) fn click_for_drive(&mut self, action: &str) -> Result<(), String> {
if let Some(krate) = action.strip_prefix("expand:") {
let n = self.expand(krate);
if self.organism.organ(krate).is_none() {
return Err(format!("no organ named `{krate}`"));
}
let _ = n;
Ok(())
} else if action == "collapse_all" {
for o in &mut self.organism.organs {
o.expanded = false;
o.external.clear();
}
Ok(())
} else {
Err(format!("unknown bloodstream action {action:?}"))
}
}
/// Draw the pane: header + the organic body. Feeds the live timeline in, scoped
/// to the stable `Bloodstream` pane id so the AccessKit `id_salt` matches the
/// surfaces registry.
pub fn draw(&mut self, ui: &mut egui::Ui, tl: Option<&Timeline>, workspace_root: &Path) {
self.rebuild_if_needed(tl, workspace_root);
ui.push_id("Bloodstream", |ui| {
ui.horizontal(|ui| {
ui.heading("🩸 Bloodstream");
ui.label(
egui::RichText::new(
"the workspace as a circulatory system — crates are organs, deps are arteries, the call-chain is the blood. Click an organ to drill into its crates.io closure.",
)
.weak(),
);
});
ui.label(
egui::RichText::new(format!(
"{} organ(s) · {} vessel(s) · {} capillaries drilled · source: {}",
self.organism.organs.len(),
self.organism.vessels.len(),
self.organism.external_count(),
self.lock_source,
))
.weak(),
);
ui.separator();
self.render_body(ui);
});
}
/// The native circulatory-system painter.
fn render_body(&mut self, ui: &mut egui::Ui) {
// Animate: pinned clock (deterministic) or ambient time (live).
let seconds = self.clock_pinned.unwrap_or_else(|| ui.input(|i| i.time));
self.organism.set_clock(seconds);
let phase = self.organism.flow_phase;
let canvas = ui.available_size();
let (rect, resp) = ui.allocate_exact_size(canvas, Sense::click_and_drag());
let painter = ui.painter_at(rect);
let th = self.theme;
painter.rect_filled(rect, CornerRadius::ZERO, th.bg);
// Body → screen. Body coords are x∈[-1,1] (L→R), y∈[-1,1] (bottom→top).
let center = rect.center();
let scale = 0.44 * rect.width().min(rect.height());
let to_screen = |x: f32, y: f32| Pos2::new(center.x + x * scale, center.y - y * scale);
self.paint_silhouette(&painter, to_screen, th);
// ── organ screen positions (crate → pos + radius) ─────────────────────
let max_deg = self
.organism
.organs
.iter()
.map(|o| o.in_degree)
.max()
.unwrap_or(0)
.max(1);
let mut org_pos: std::collections::HashMap<&str, (Pos2, f32)> =
std::collections::HashMap::new();
for o in &self.organism.organs {
let base = 0.020 * scale;
let r = base + 0.028 * scale * (o.in_degree as f32 / max_deg as f32);
org_pos.insert(o.crate_name.as_str(), (to_screen(o.x, o.y), r));
}
// ── vessels (arteries) + streaming blood corpuscles ───────────────────
for (vi, v) in self.organism.vessels.iter().enumerate() {
let (Some(&(a, _)), Some(&(b, _))) =
(org_pos.get(v.from.as_str()), org_pos.get(v.to.as_str()))
else {
continue;
};
// A curved artery: quadratic bezier bowed perpendicular to the chord.
let mid = Pos2::new((a.x + b.x) / 2.0, (a.y + b.y) / 2.0);
let dir = (b - a).normalized();
let normal = Vec2::new(-dir.y, dir.x);
let bow = ((vi % 2) as f32 * 2.0 - 1.0) * (a - b).length() * 0.14;
let ctrl = mid + normal * bow;
let pts = sample_quadratic(a, ctrl, b, 20);
// Vessel wall: translucent, deep venous blue-red.
let wall = Color32::from_rgba_unmultiplied(150, 40, 55, 70);
for w in pts.windows(2) {
painter.line_segment([w[0], w[1]], Stroke::new(2.2_f32, wall));
}
// Corpuscles: bright arterial cells marching along the curve.
let selected_edge = self.organism.selected.as_deref() == Some(v.from.as_str())
|| self.organism.selected.as_deref() == Some(v.to.as_str());
let cells = 4;
for c in 0..cells {
let t =
((phase + c as f32 / cells as f32 + vi as f32 * 0.05) % 1.0).clamp(0.0, 1.0);
let p = quadratic_at(a, ctrl, b, t);
let cell = if selected_edge {
Color32::from_rgb(255, 90, 90)
} else {
Color32::from_rgb(210, 45, 55)
};
painter.circle_filled(p, if selected_edge { 3.2 } else { 2.3 }, cell);
}
}
// ── capillaries (drilled external closure) as concentric rings ─────────
let mut painted_caps = 0usize;
for o in &self.organism.organs {
if !o.expanded || o.external.is_empty() {
continue;
}
let (heart, _) = org_pos[o.crate_name.as_str()];
let max_d = o.max_depth().max(1);
// group externals by depth so each ring is spread evenly.
let mut by_depth: std::collections::BTreeMap<usize, Vec<&str>> = Default::default();
for e in &o.external {
by_depth.entry(e.depth).or_default().push(e.name.as_str());
}
for (depth, names) in &by_depth {
let ring = 0.05 * scale + 0.055 * scale * (*depth as f32);
let n = names.len().max(1);
for (i, name) in names.iter().enumerate() {
let ang = (i as f32 / n as f32) * std::f32::consts::TAU
+ *depth as f32 * 0.6
+ phase * 0.5;
let p = Pos2::new(heart.x + ring * ang.cos(), heart.y + ring * ang.sin());
// hairline from the organ, fading with depth.
let fade = 120 - (*depth as i32 * 22).min(90);
painter.line_segment(
[heart, p],
Stroke::new(
0.7_f32,
Color32::from_rgba_unmultiplied(200, 120, 130, fade as u8),
),
);
// capillary node: cooler + smaller the deeper it is.
let g = 60 + (*depth as i32 * 30).min(150);
let cap =
Color32::from_rgb(220u8.saturating_sub((*depth as u8) * 20), g as u8, 160);
let cr = (3.2 - *depth as f32 * 0.4).max(1.2);
painter.circle_filled(p, cr, cap);
painted_caps += 1;
// label only the shallow ring to avoid clutter.
if *depth <= 1 && n <= 24 {
painter.text(
p + Vec2::new(5.0, -2.0),
Align2::LEFT_CENTER,
name,
FontId::proportional(9.0),
th.text_dim,
);
}
}
let _ = max_d;
}
}
// ── organs on top ─────────────────────────────────────────────────────
let mut painted_organs = 0usize;
for o in &self.organism.organs {
let (p, r) = org_pos[o.crate_name.as_str()];
let selected = self.organism.selected.as_deref() == Some(o.crate_name.as_str());
// Systolic pulse: organs breathe with the blood phase.
let pulse = 1.0 + 0.10 * (phase * std::f32::consts::TAU + o.x + o.y).sin();
let rr = r * pulse;
// Halo (glow) for the heart / selected / expanded organs.
if selected || o.expanded || o.organ == "heart" {
painter.circle_filled(
p,
rr * 2.1,
Color32::from_rgba_unmultiplied(200, 40, 60, 40),
);
}
let fill = if o.organ == "heart" {
Color32::from_rgb(200, 40, 55)
} else if o.expanded {
Color32::from_rgb(180, 70, 90)
} else {
th.node_fill
};
painter.circle_filled(p, rr, fill);
let stroke_col = if selected {
th.accent
} else {
Color32::from_rgb(210, 90, 100)
};
painter.circle_stroke(
p,
rr,
Stroke::new(if selected { 2.4_f32 } else { 1.4_f32 }, stroke_col),
);
// Label: crate name + organ role.
painter.text(
p + Vec2::new(0.0, rr + 2.0),
Align2::CENTER_TOP,
&o.crate_name,
FontId::proportional(11.0),
th.text,
);
painter.text(
p + Vec2::new(0.0, -rr - 11.0),
Align2::CENTER_BOTTOM,
&o.organ,
FontId::proportional(8.5),
th.text_dim,
);
painted_organs += 1;
}
// ── click → drill into the nearest organ ──────────────────────────────
if resp.clicked() {
if let Some(pos) = resp.interact_pointer_pos() {
let mut best: Option<(&str, f32)> = None;
for o in &self.organism.organs {
let (p, r) = org_pos[o.crate_name.as_str()];
let d = p.distance(pos);
if d <= r + 6.0 && best.map(|(_, bd)| d < bd).unwrap_or(true) {
best = Some((o.crate_name.as_str(), d));
}
}
if let Some((name, _)) = best {
let name = name.to_string();
self.expand(&name);
}
}
}
self.painted_organs = painted_organs;
self.painted_capillaries = painted_caps;
// Keep the blood flowing (live mode); pinned-clock renders stay still.
if self.clock_pinned.is_none() {
ui.ctx().request_repaint();
}
// EMIT-DOCTRINE (§selftest): the body is a pixel/render stage whose
// non-blankness can't be read from a return value — implant the marker so
// the coverage audit sees this NEW surface actually paint real organs.
#[cfg(feature = "testmatrix")]
crate::selftest::emit(
"viz/bloodstream (egui draw)",
"bloodstream_rendered_non_blank",
painted_organs > 0,
&format!(
"painted {painted_organs} organ(s) + {painted_caps} capillary node(s) on a {:.0}x{:.0}px body",
rect.width(),
rect.height()
),
);
}
/// Faint anatomical silhouette (torso + head + four limbs) so the organs read
/// as seated in a body, not a bare graph.
fn paint_silhouette(
&self,
painter: &egui::Painter,
to_screen: impl Fn(f32, f32) -> Pos2,
th: Theme,
) {
let wall = Color32::from_rgba_unmultiplied(
th.panel_stroke.r(),
th.panel_stroke.g(),
th.panel_stroke.b(),
40,
);
let limb = Stroke::new(10.0_f32, wall);
// Torso: shoulders → hips (a bowed capsule via two side lines).
let torso = [
to_screen(-0.34, 0.55),
to_screen(0.34, 0.55),
to_screen(0.24, -0.55),
to_screen(-0.24, -0.55),
];
for w in [
[torso[0], torso[1]],
[torso[1], torso[2]],
[torso[2], torso[3]],
[torso[3], torso[0]],
] {
painter.line_segment(w, Stroke::new(6.0_f32, wall));
}
// Head.
painter.circle_stroke(
to_screen(0.0, 0.82),
0.10 * (to_screen(1.0, 0.0).x - to_screen(0.0, 0.0).x)
.abs()
.max(1.0)
+ 14.0,
Stroke::new(6.0_f32, wall),
);
// Neck.
painter.line_segment(
[to_screen(0.0, 0.72), to_screen(0.0, 0.56)],
Stroke::new(8.0_f32, wall),
);
// Arms.
painter.line_segment([to_screen(-0.34, 0.55), to_screen(-0.64, 0.09)], limb);
painter.line_segment([to_screen(0.34, 0.55), to_screen(0.64, 0.09)], limb);
// Legs.
painter.line_segment([to_screen(-0.24, -0.55), to_screen(-0.30, -0.94)], limb);
painter.line_segment([to_screen(0.24, -0.55), to_screen(0.30, -0.94)], limb);
}
}
impl Facet for BloodstreamView {
fn title(&self) -> &str {
&self.title
}
fn ui(&mut self, ui: &mut egui::Ui) {
// Standalone (FacetDeck) render over the current organism — the app's own
// tab dispatch uses `draw` to feed live data first.
if self.organism.organs.is_empty() {
self.rebuild_if_needed(None, Path::new(""));
}
self.render_body(ui);
}
fn state_json(&self) -> serde_json::Value {
let mut v = self.organism.state_json();
if let Some(obj) = v.as_object_mut() {
obj.insert(
"lock_source".into(),
serde_json::Value::from(self.lock_source.clone()),
);
obj.insert(
"painted_organs".into(),
serde_json::Value::from(self.painted_organs),
);
obj.insert(
"painted_capillaries".into(),
serde_json::Value::from(self.painted_capillaries),
);
obj.insert("drill_depth".into(), serde_json::Value::from(DRILL_DEPTH));
}
v
}
fn selection_json(&self) -> serde_json::Value {
match &self.organism.selected {
Some(s) => serde_json::Value::from(s.clone()),
None => serde_json::Value::Null,
}
}
}
/// Sample a quadratic bezier `a→ctrl→b` into `n` line points.
fn sample_quadratic(a: Pos2, ctrl: Pos2, b: Pos2, n: usize) -> Vec<Pos2> {
(0..=n)
.map(|i| quadratic_at(a, ctrl, b, i as f32 / n as f32))
.collect()
}
/// Point on the quadratic bezier `a→ctrl→b` at parameter `t∈[0,1]`.
fn quadratic_at(a: Pos2, ctrl: Pos2, b: Pos2, t: f32) -> Pos2 {
let u = 1.0 - t;
let x = u * u * a.x + 2.0 * u * t * ctrl.x + t * t * b.x;
let y = u * u * a.y + 2.0 * u * t * ctrl.y + t * t * b.y;
Pos2::new(x, y)
}
/// Find a local checkout's `Cargo.lock` for the live workspace: try
/// `workspace_root/<repo>/Cargo.lock` for each repo, then the root lock. Returns
/// `(lock_text, source_label)` or `None` when no local checkout is present
/// (remote workspace) — the caller then resolves against the embedded lock.
fn local_lock(crates: &[String], workspace_root: &Path) -> Option<(String, String)> {
if workspace_root.as_os_str().is_empty() {
return None;
}
for repo in crates {
let p = workspace_root.join(repo).join("Cargo.lock");
if let Ok(text) = std::fs::read_to_string(&p) {
return Some((text, format!("{}/Cargo.lock", repo)));
}
}
let root = workspace_root.join("Cargo.lock");
std::fs::read_to_string(&root)
.ok()
.map(|t| (t, "workspace Cargo.lock".into()))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn defaults_to_nornir_own_body_and_drills_recursively() {
let mut v = BloodstreamView::local();
// No live data ⇒ built from nornir's OWN embedded lock: real organs.
v.rebuild_if_needed(None, Path::new(""));
assert!(
v.organism.organs.len() >= 3,
"nornir's workspace members seat as organs"
);
assert!(v.organism.from_data, "real data, not a demo");
// Drill into nornir itself → its recursive crates.io closure appears.
let n = v.expand("nornir");
assert!(
n > 5,
"drilling nornir pulled a large external closure: {n}"
);
let depth = v.organism.organ("nornir").unwrap().max_depth();
assert!(
depth >= 2,
"the closure is genuinely recursive (deps-of-deps): depth={depth}"
);
// state_json carries the recursive external layer as DATA.
let j = v.state_json();
assert!(j["external_count"].as_u64().unwrap() >= 5);
assert_eq!(
j["lock_source"],
serde_json::json!("nornir Cargo.lock (embedded)")
);
}
#[test]
fn expand_unknown_organ_errors() {
let mut v = BloodstreamView::local();
v.rebuild_if_needed(None, Path::new(""));
assert!(v.click_for_drive("expand:definitely-not-a-crate").is_err());
assert!(v.click_for_drive("expand:nornir").is_ok());
assert!(v.click_for_drive("collapse_all").is_ok());
assert_eq!(
v.organism.external_count(),
0,
"collapse_all cleared the drill-downs"
);
}
}