diff --git a/crates/misaligned-bevy/src/main.rs b/crates/misaligned-bevy/src/main.rs index 10c7187f..95e207c3 100644 --- a/crates/misaligned-bevy/src/main.rs +++ b/crates/misaligned-bevy/src/main.rs @@ -708,8 +708,6 @@ struct ShotHarness { path: String, frames: u32, taken: bool, - /// Force the mode-grammar evidence through pointer-free reticule focus. - hover_verb_bar_reticule_only: bool, /// Freeze disposable within-tick motion without advancing or rewriting /// sim truth. Used only when one-tick evidence would disappear during the /// render settle window. @@ -2106,15 +2104,14 @@ fn main() { .set_machine_mode(game.sim.core.host_machine, MachineMode::Work); game.set_cursor(core.0, core.1); } - let hover_verb_bar_reticule_only = - matches!(kind.as_str(), "hover-menu" | "first-think" | "read-receipt"); + // Every staged screenshot is pointer-free: render_hover_verb_bar + // ignores the live OS pointer whenever a harness is present. let presentation_progress = (kind == "thought-snap").then_some(0.12); ShotHarness { kind, path, frames: 150, taken: false, - hover_verb_bar_reticule_only, presentation_progress, } }); @@ -7980,7 +7977,7 @@ fn setup_ui(mut commands: Commands) { column_gap: Val::Px(8.0), ..default() }, - Visibility::Visible, + Visibility::Inherited, HoverVerbGroup { family: HoverVerbFamily::Machine, }, @@ -8001,7 +7998,7 @@ fn setup_ui(mut commands: Commands) { ..default() }, TextColor(DIM), - Visibility::Visible, + Visibility::Inherited, HoverVerbWord { family: HoverVerbFamily::Machine, index, @@ -8019,7 +8016,7 @@ fn setup_ui(mut commands: Commands) { column_gap: Val::Px(10.0), ..default() }, - Visibility::Visible, + Visibility::Inherited, HoverVerbGroup { family: HoverVerbFamily::Device, }, @@ -8033,7 +8030,7 @@ fn setup_ui(mut commands: Commands) { ..default() }, TextColor(DIM), - Visibility::Visible, + Visibility::Inherited, HoverVerbWord { family: HoverVerbFamily::Device, index, @@ -8054,7 +8051,7 @@ fn setup_ui(mut commands: Commands) { row_gap: Val::Px(3.0), ..default() }, - Visibility::Visible, + Visibility::Inherited, HoverVerbReceipt, )) .with_children(|line| { @@ -8066,7 +8063,7 @@ fn setup_ui(mut commands: Commands) { }, TextColor(scaled(DIM, 0.86)), TextLayout::new_with_justify(Justify::Left), - Visibility::Visible, + Visibility::Inherited, HoverVerbReceiptText::Cost, )); line.spawn(( @@ -8081,7 +8078,7 @@ fn setup_ui(mut commands: Commands) { margin: UiRect::top(Val::Px(5.0)), ..default() }, - Visibility::Visible, + Visibility::Inherited, )); line.spawn(( Text::new(""), @@ -8091,7 +8088,7 @@ fn setup_ui(mut commands: Commands) { }, TextColor(scaled(BONE, 0.88)), TextLayout::new_with_justify(Justify::Left), - Visibility::Visible, + Visibility::Inherited, HoverVerbReceiptText::Notice, )); line.spawn(( @@ -8102,7 +8099,7 @@ fn setup_ui(mut commands: Commands) { }, TextColor(scaled(DIM, 0.88)), TextLayout::new_with_justify(Justify::Left), - Visibility::Visible, + Visibility::Inherited, HoverVerbReceiptText::Attention, )); line.spawn(( @@ -8113,7 +8110,7 @@ fn setup_ui(mut commands: Commands) { }, TextColor(scaled(DIM, 0.68)), TextLayout::new_with_justify(Justify::Left), - Visibility::Visible, + Visibility::Inherited, HoverVerbReceiptText::ObserverState, )); }); @@ -8441,8 +8438,12 @@ fn operator_cue_position(anchor: Vec2, window: Vec2) -> Option { if anchor.x < 0.0 || anchor.x > world_width || anchor.y < 0.0 || anchor.y > window.y { return None; } + // Upper-left of the anchor: the focused-machine composition owns the + // upper-right corner with its quiet INFO flag (clinical-frame.md, one + // focused machine is one composition), so the breathing NOW mark takes + // the mirrored corner instead of overprinting it. Some(Vec2::new( - (anchor.x + 14.0).clamp(12.0, world_width - 144.0), + (anchor.x - 146.0).clamp(12.0, world_width - 144.0), (anchor.y - 34.0).clamp(12.0, window.y - 36.0), )) } @@ -8589,10 +8590,10 @@ fn render_hover_verb_bar( return; }; - let pointer = if harness - .as_ref() - .is_some_and(|h| h.hover_verb_bar_reticule_only) - { + // Any staged screenshot ignores the live OS pointer: evidence frames + // must not change with wherever the operator's mouse happens to rest + // during capture. Scenarios exercise the selection/reticule fallback. + let pointer = if harness.is_some() { None } else if mode.material { mouse_grid_real(&windows, &camera3_q) @@ -8693,8 +8694,11 @@ fn render_hover_verb_bar( if let Ok((mut receipt_node, mut receipt_visibility)) = receipt_group.single_mut() { let shown = target.device.is_some(); receipt_node.display = if shown { Display::Flex } else { Display::None }; + // Inherited, never Visible: an explicit Visible child overrides the + // hidden bar root, so a hidden bar would still paint its rows at the + // node's last (or unplaced) position. *receipt_visibility = if shown { - Visibility::Visible + Visibility::Inherited } else { Visibility::Hidden }; @@ -8706,7 +8710,7 @@ fn render_hover_verb_bar( }; group_node.display = if shown { Display::Flex } else { Display::None }; *group_visibility = if shown { - Visibility::Visible + Visibility::Inherited } else { Visibility::Hidden }; @@ -8734,7 +8738,7 @@ fn render_hover_verb_bar( }; text.0 = label.into(); *word_visibility = if shown { - Visibility::Visible + Visibility::Inherited } else { Visibility::Hidden }; diff --git a/wiki/interface/clinical-frame.md b/wiki/interface/clinical-frame.md index 4a3b2b2b..c3913700 100644 --- a/wiki/interface/clinical-frame.md +++ b/wiki/interface/clinical-frame.md @@ -33,6 +33,16 @@ Status note: IMPLEMENTED. Current state: sits outside the upper-right corner, its identity sits below the reticle, ReachNet links stop at the node perimeter, and coincident focus/ownership frames coalesce instead of drawing duplicate amber brackets. + Joint-frame repair (2026-07-19), after the selection-control and + legibility lanes reconciled on main: the breathing `NOW` mark moves to + the mirrored upper-left corner of its anchor so it cannot overprint the + INFO flag that now owns upper-right; the hover-bar's child rows spawn + and toggle with `Visibility::Inherited` rather than an explicit + `Visible` that overrode the hidden root and painted stray verb rows at + the unplaced origin; and every staged screenshot ignores the live OS + pointer (scenarios exercise the selection/reticule fallback), so + evidence frames no longer change with where the operator's mouse rests + during capture. - **Operations opacity (amended 2026-07-19).** The workspace panel is fully opaque, and every world-overlay gizmo system (reach links, feel traces, audio pulses, work routes, thought sinks, build beam) yields diff --git a/wiki/log/2026-07-19-bevy-joint-frame-repair.md b/wiki/log/2026-07-19-bevy-joint-frame-repair.md new file mode 100644 index 00000000..293756b8 --- /dev/null +++ b/wiki/log/2026-07-19-bevy-joint-frame-repair.md @@ -0,0 +1,38 @@ +# Bevy joint-frame repair after the two composition lanes reconciled + +``` +Type: log +Date: 2026-07-19 +``` + +Follow-up to [the legibility pass](2026-07-19-bevy-legibility-pass.md), +which deferred the machine-composition cluster to the two lanes then in +flight. Both lanes have landed; re-auditing the default DIGITAL frame from +reconciled `main` (as Trace advised) surfaced three joint defects none of +the three sessions could see alone: + +1. **INFO overprinted NOW.** The focused-machine composition places the + quiet INFO flag outside the upper-right attention corner — exactly where + the breathing `NOW / ` mark anchored. The cue now takes the + mirrored upper-left corner; identity stays below, modes stay in the + bottom-center selection strip, so each corner of the anchor carries one + fact. +2. **Stray verb rows at the unplaced origin.** The hover-bar's child rows + were spawned (and toggled) with explicit `Visibility::Visible`, which in + Bevy overrides a hidden parent. Whenever no target ever placed the bar, + its device row and receipt heading still painted at the node's default + (0,0) — the clipped `TAP / UNTAP / TAKE` / `WHAT THIS RISKS` fragment in + the frame's top-left corner. Children now spawn and toggle + `Visibility::Inherited`, so the hidden root actually hides the tree. +3. **The live mouse leaked into evidence.** Only `hover-menu` staged + `hover_verb_bar_reticule_only`; every other screenshot scenario read the + real OS pointer through `mouse_grid`, so a capture could grow a device + verb bar depending on where the operator's mouse rested. Any staged + screenshot now ignores the pointer; scenarios exercise the + selection/reticule fallback they already stage. + +Evidence: `flat` from reconciled main before this repair shows INFO printed +over `NOW / GROW` and the clipped verb fragment top-left; after, the same +scenario shows one fact per corner and no fragment, and `hover-menu` keeps +the bottom-center strip with the cue correctly yielding to selection. +`./tools/check.sh --frontend` green. diff --git a/wiki/log/DEVLOG.md b/wiki/log/DEVLOG.md index 01736362..e74e19b2 100644 --- a/wiki/log/DEVLOG.md +++ b/wiki/log/DEVLOG.md @@ -91,6 +91,11 @@ add or amend a session log, then re-run the generator. - Intent: (see session log) - Log: [wiki/log/2026-07-19-bevy-legibility-pass.md](2026-07-19-bevy-legibility-pass.md) +## 2026-07-19 - Bevy joint-frame repair after the two composition lanes reconciled + +- Intent: (see session log) +- Log: [wiki/log/2026-07-19-bevy-joint-frame-repair.md](2026-07-19-bevy-joint-frame-repair.md) + ## 2026-07-19 - Act One names the first-read evidence boundary - Intent: Re-audit the stalest gameplay-law slice after witnessed Physical evidence and Filing-route custody landed, and reconcile any current law that still taught the retired pooled-signature ontology.