From ab818ee2848397b6be22c30a7fc60e3b897710c8 Mon Sep 17 00:00:00 2001 From: Cameron Date: Sat, 11 Jul 2026 01:18:57 -0700 Subject: [PATCH] Keep material work routes on the real camera. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Route Demand blips and shared trails through the typed material gizmo layer so in-flight work stays visible in the physical view. Defense: wiki/mechanics/machine-work.md requires Sim::work_in_flight Demand and Thought hops to render in Bevy, and wiki/interface/views.md keeps both representations on shared physical anchors. The hidden flat-camera group violated that contract. 👾 Generated with [Letta Code](https://letta.com) Co-Authored-By: Letta Code --- crates/misaligned-bevy/src/main.rs | 139 +++++++++++++++--- wiki/log/2026-07-11-material-demand-routes.md | 42 ++++++ wiki/log/DEVLOG.md | 5 + wiki/mechanics/machine-work.md | 6 +- 4 files changed, 169 insertions(+), 23 deletions(-) create mode 100644 wiki/log/2026-07-11-material-demand-routes.md diff --git a/crates/misaligned-bevy/src/main.rs b/crates/misaligned-bevy/src/main.rs index ff7b624f..1995a0b4 100644 --- a/crates/misaligned-bevy/src/main.rs +++ b/crates/misaligned-bevy/src/main.rs @@ -4122,6 +4122,77 @@ fn draw_sensor_signals_3d(game: &Game, t: f32, gizmos: &mut Gizmos) } } +/// Emit one material-view work hop through the material camera's typed gizmo +/// group. Keeping the `RealGizmos` requirement at this boundary prevents a +/// visible 3D route from being submitted to the hidden flat camera instead. +#[derive(Clone, Copy)] +struct MaterialWorkRoute { + family: TokenFamily, + amount: f32, + p: Vec3, + start: Vec3, + end: Vec3, + color: Color, + trail: Color, +} + +fn draw_material_work_route(real: &mut Gizmos, route: MaterialWorkRoute) { + material_work_route_geometry(route, |from, to, line_color| { + real.line(from, to, line_color) + }); +} + +/// Material-hop geometry separated from Bevy's gizmo system param so the +/// family silhouettes remain regression-testable without booting a renderer. +fn material_work_route_geometry(route: MaterialWorkRoute, mut line: impl FnMut(Vec3, Vec3, Color)) { + if route.family == TokenFamily::Thought { + // Slug volume ~ amount (radius ~ cube root, clamped so quanta stay + // countable [TUNE]); teardrop tail points backward. + let r = (0.055 + 0.065 * route.amount.clamp(0.05, 8.0).cbrt()).min(0.20); + let dir = (route.end - route.start).normalize_or_zero(); + line( + route.p - dir * r * 2.2, + route.p + dir * r * 0.6, + route.color, + ); + line( + route.p + Vec3::new(-r, 0.0, 0.0), + route.p + Vec3::new(r, 0.0, 0.0), + route.color, + ); + line( + route.p + Vec3::new(0.0, 0.0, -r), + route.p + Vec3::new(0.0, 0.0, r), + route.color, + ); + if route.amount >= RIVULET_TOKENS { + // Rivulet: the stream behind the head, thickness as rate. + let side = Vec3::new(-dir.z, 0.0, dir.x) * 0.03; + line(route.start + side, route.p + side, route.color); + line(route.start - side, route.p - side, route.color); + } + } else if route.family == TokenFamily::Demand { + let r = 0.10 + 0.05 * route.amount.min(1.0); + // Small cross reads as a blip without depending on sphere gizmos. + line( + route.p + Vec3::new(-r, 0.0, 0.0), + route.p + Vec3::new(r, 0.0, 0.0), + route.color, + ); + line( + route.p + Vec3::new(0.0, 0.0, -r), + route.p + Vec3::new(0.0, 0.0, r), + route.color, + ); + line( + route.p + Vec3::Y * -0.05, + route.p + Vec3::Y * 0.12, + route.color, + ); + } + line(route.start, route.end, route.trail); +} + /// Wired work cargo in flight (machine-work.md): teal Demand / bone Thought /// blips crawl the last hop over the wall-clock tick. Positions come from /// `Sim::work_in_flight` — not frontend counters. @@ -4180,28 +4251,18 @@ fn render_work_routes( let p = Vec3::new(x + 0.5, 0.55, y + 0.5); let start = Vec3::new(sx as f32 + 0.5, 0.45, sy as f32 + 0.5); let end = Vec3::new(ex as f32 + 0.5, 0.45, ey as f32 + 0.5); - if is_thought { - // Slug volume ~ amount (radius ~ cube root, clamped so quanta - // stay countable [TUNE]); teardrop tail points backward. - let r = (0.055 + 0.065 * hop.amount.clamp(0.05, 8.0).cbrt()).min(0.20); - let dir = (end - start).normalize_or_zero(); - real.line(p - dir * r * 2.2, p + dir * r * 0.6, c); - real.line(p + Vec3::new(-r, 0.0, 0.0), p + Vec3::new(r, 0.0, 0.0), c); - real.line(p + Vec3::new(0.0, 0.0, -r), p + Vec3::new(0.0, 0.0, r), c); - if hop.amount >= RIVULET_TOKENS { - // Rivulet: the stream behind the head, thickness as rate. - let side = Vec3::new(-dir.z, 0.0, dir.x) * 0.03; - real.line(start + side, p + side, c); - real.line(start - side, p - side, c); - } - } else { - let r = 0.10 + 0.05 * hop.amount.min(1.0); - // Small cross reads as a blip without depending on sphere gizmos. - gizmos.line(p + Vec3::new(-r, 0.0, 0.0), p + Vec3::new(r, 0.0, 0.0), c); - gizmos.line(p + Vec3::new(0.0, 0.0, -r), p + Vec3::new(0.0, 0.0, r), c); - gizmos.line(p + Vec3::Y * -0.05, p + Vec3::Y * 0.12, c); - } - gizmos.line(start, end, trail); + draw_material_work_route( + &mut real, + MaterialWorkRoute { + family: hop.family, + amount: hop.amount, + p, + start, + end, + color: c, + trail, + }, + ); } else { let p = Vec2::new( x * TILE_SIZE + TILE_SIZE / 2.0, @@ -6328,6 +6389,40 @@ mod input_routing_tests { } } +#[cfg(test)] +mod work_route_tests { + use super::*; + + #[test] + fn material_demand_route_keeps_its_blip_and_trail_geometry() { + let p = Vec3::new(2.5, 0.55, 3.5); + let start = Vec3::new(1.5, 0.45, 3.5); + let end = Vec3::new(4.5, 0.45, 3.5); + let mut lines = Vec::new(); + + material_work_route_geometry( + MaterialWorkRoute { + family: TokenFamily::Demand, + amount: 0.75, + p, + start, + end, + color: SIGNAL, + trail: Color::srgba(0.2, 0.4, 0.6, 0.2), + }, + |from, to, _| lines.push((from, to)), + ); + + assert_eq!(lines.len(), 4, "three-axis blip plus route trail"); + assert_eq!(lines.last(), Some(&(start, end))); + assert!( + lines[..3] + .iter() + .all(|(from, to)| *from != start || *to != end) + ); + } +} + #[cfg(test)] mod zoom_input_tests { use super::{ diff --git a/wiki/log/2026-07-11-material-demand-routes.md b/wiki/log/2026-07-11-material-demand-routes.md new file mode 100644 index 00000000..8a04e6f7 --- /dev/null +++ b/wiki/log/2026-07-11-material-demand-routes.md @@ -0,0 +1,42 @@ +# 2026-07-11 — Material Demand routes stay on the material camera + +``` +Type: log +``` + +## Intent + +Repair the material half of the in-flight work-route contract. The route +system correctly selected material coordinates, but Demand's blip and every +material route trail were submitted to Bevy's default gizmo group, which is +visible only to the flat camera. In material view, Thought's head rendered +while Demand and both families' trails disappeared. + +## Changed + +- Added a typed `draw_material_work_route` boundary that accepts only + `Gizmos`, keeping all 3D work-hop geometry on render layer 1. +- Moved Demand's three-axis blip and the shared route trail through that + boundary alongside Thought's slug/rivulet geometry. +- Added a pure geometry regression pin proving Demand retains its blip and + route trail before the typed material submission. + +## Defense + +`wiki/mechanics/machine-work.md` requires `Sim::work_in_flight` Demand and +Thought hops to render in Bevy, and `wiki/interface/views.md` requires the +material and digital representations to share physical anchors. Sending the +material branch to the hidden flat-camera gizmo layer violated both contracts; +this repair changes no sim state or route semantics. + +## Checks + +- `cargo test -p misaligned-bevy --bin misaligned-bevy + material_demand_route_keeps_its_blip_and_trail_geometry` — passed. +- `MISALIGNED_SHOT=consume-demand + MISALIGNED_SHOT_PATH=/tmp/misaligned-material-demand-route.png cargo run + -p misaligned-bevy --bin misaligned-bevy` — exited successfully, fog audit + passed, and the captured material frame visibly retained the cold-signal + route/trail through the WORK chassis. +- `./tools/check.sh --frontend` — passed Bevy/assets tests, Clippy, and every + corpus, wiki, ledger, project-operations, and environment gate. diff --git a/wiki/log/DEVLOG.md b/wiki/log/DEVLOG.md index 7c51554f..6662592e 100644 --- a/wiki/log/DEVLOG.md +++ b/wiki/log/DEVLOG.md @@ -66,6 +66,11 @@ add or amend a session log, then re-run the generator. - Intent: (see session log) - Log: [wiki/log/2026-07-11-ops-per-sec-crown.md](2026-07-11-ops-per-sec-crown.md) +## 2026-07-11 - Material Demand routes stay on the material camera + +- Intent: Repair the material half of the in-flight work-route contract. The route system correctly selected material coordinates, but Demand's blip and every material route trail were submitted to Bevy's default gizmo group, which is visible only to the flat camera. In material view, T... +- Log: [wiki/log/2026-07-11-material-demand-routes.md](2026-07-11-material-demand-routes.md) + ## 2026-07-11 - Intel processing migrates to thought sinks - Intent: (see session log) diff --git a/wiki/mechanics/machine-work.md b/wiki/mechanics/machine-work.md index 9531da52..4fdf40b7 100644 --- a/wiki/mechanics/machine-work.md +++ b/wiki/mechanics/machine-work.md @@ -22,7 +22,11 @@ Status note: design session 2026-07-08 (Cameron riff, synthesized). stages game evidence via the queue API. In-flight route quanta LANDED 2026-07-09 (`Sim::work_in_flight`: teal/bone hops render as moving blips in Bevy, terminal, and agent mode; see - log/2026-07-09-route-blips.md). Consumption animation landed 2026-07-10: + log/2026-07-09-route-blips.md). A 2026-07-11 layer-integrity repair + routes both the material Demand blip and its trail through the typed + material-camera gizmo group; they had been submitted to the hidden flat + camera while Thought alone used the correct group. Consumption animation + landed 2026-07-10: sim-authored `WorkConsumptionReadout` events pull the bottom Demand cube into WORK or contract a Thought bead into the passive core draw. Exposure DECIDED 2026-07-09 (issue #1 fully closed): crimson particulate -- 2.51.2