From d751164bbf52d5c1109e209667ed887eeffa617f Mon Sep 17 00:00:00 2001 From: Cameron Date: Mon, 3 Aug 2026 19:56:40 -0700 Subject: [PATCH] Keep a machine's chip and its own sentence apart MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A Bevy frame showed "thinking wrote noise logs | Network | unread with the IT" printing straight through the teal INFO flag on the same machine the sentence described. The callout grammar already banned annotations overprinting matter, but its exclusion math is per tile and a token chip is not a tile: the chip and the callout corner share the up-right neighborhood of one body, and the two families do not even share a measuring system — a chip is drawn at world size while a read sentence holds one on-screen size. The chip slot becomes named geometry (TOKEN_CHIP_SLOT, the two tier font sizes, TOKEN_CHIP_BAND_TOP), and CALLOUT_CORNER_Y derives from that band plus a clearance instead of a fixed TILE_SIZE * 0.85 lift. The callout's near corner now clears the chip band by construction, in every quadrant and at every camera scale. New MISALIGNED_SHOT=token-callout stages the exact reported pairing — host holding raw intel while its own THINK noise-log record anchors a sentence at the same tile. Defense: digital-read.md's callout grammar (Type: spec) is amended with the binding clause that the annotation layer never overprints itself and that the chip band is cleared by geometry rather than by tile score, since no per-tile occupancy can separate a world-sized chip from a screen-sized sentence. Tests pin the leading block's rectangle clear of its anchor's chip for INFO/D6/T2/!149 across four quadrants at camera scales 0.25, 1.0 and 4.0, and pin the clearance to the tallest chip tier; reverting the constant fails on the reported case. --- crates/misaligned-bevy/src/main.rs | 1 + crates/misaligned-bevy/src/shot_harness.rs | 35 +++++++++ .../misaligned-bevy/src/world_annotations.rs | 77 ++++++++++++++++++- wiki/engineering/env.md | 2 +- wiki/interface/digital-read.md | 19 ++++- wiki/log/2026-08-03-callout-chip-clearance.md | 59 ++++++++++++++ wiki/log/DEVLOG.md | 5 ++ wiki/process/tick-ledger.md | 1 + 8 files changed, 193 insertions(+), 6 deletions(-) create mode 100644 wiki/log/2026-08-03-callout-chip-clearance.md diff --git a/crates/misaligned-bevy/src/main.rs b/crates/misaligned-bevy/src/main.rs index 684a175d..255b659b 100644 --- a/crates/misaligned-bevy/src/main.rs +++ b/crates/misaligned-bevy/src/main.rs @@ -636,6 +636,7 @@ const BEVY_SHOT_KINDS: &[&str] = &[ "thought-tap", "thoughtflow", "thoughtflow-wide", + "token-callout", "tokens", "two-pane", "visual-proof", diff --git a/crates/misaligned-bevy/src/shot_harness.rs b/crates/misaligned-bevy/src/shot_harness.rs index ed12c083..6c58f2fc 100644 --- a/crates/misaligned-bevy/src/shot_harness.rs +++ b/crates/misaligned-bevy/src/shot_harness.rs @@ -609,6 +609,41 @@ pub(super) fn dev_shot_scenario(game: &mut Game, mode: &mut RenderMode, kind: &s game.drain(); return; } + // Both annotation families on one body (digital-read.md callout grammar): + // the host holds unprocessed raw intel, so its INFO chip is drawn in the + // chip slot, while its own THINK noise-log record anchors a read sentence + // at the same tile. Before 2026-08-03 the sentence's first line printed + // straight through that chip; this frame is the standing evidence that a + // note and a chip about one machine no longer overprint each other. + if kind == "token-callout" { + use misaligned::intel::{RawIntelEvent, RawIntelKind}; + mode.material = false; + game.sim.reach.scan(); + for id in 1..=3u64 { + game.sim.intel_buffer.push(RawIntelEvent { + id, + tick: game.sim.tick, + feed: "shot fixture".into(), + room: Some("Server Room".into()), + x: core.0, + y: core.1, + person: None, + kind: RawIntelKind::Presence { entered: true }, + }); + } + let rack = game + .sim + .reach + .device_named("Rack 3") + .map(|device| device.id) + .expect("the host rack has a network-facing device"); + game.sim + .set_machine_mode(game.sim.core.host_machine, MachineMode::Think); + game.sim.emit_network(rack, 4, "thinking wrote noise logs"); + game.set_cursor(core.0, core.1); + game.drain(); + return; + } // DIGITAL reach-dialect evidence (views.md criteria 3-4): one earned // graph frame carrying controlled, tapped, reachable, segment-frontier, // and air-gap states without borrowing physical sight. The scan reveals diff --git a/crates/misaligned-bevy/src/world_annotations.rs b/crates/misaligned-bevy/src/world_annotations.rs index cba8eaa0..3936ae5f 100644 --- a/crates/misaligned-bevy/src/world_annotations.rs +++ b/crates/misaligned-bevy/src/world_annotations.rs @@ -292,6 +292,19 @@ struct TokenMarkerLayout { font_size: f32, } +/// The one chip slot: world offset from the machine's tile center to the +/// bottom-left corner of every token label. +const TOKEN_CHIP_SLOT: Vec2 = Vec2::new(TILE_SIZE * 0.48, TILE_SIZE * 0.46); +/// Ordinary token tier (the D/T counts). +const TOKEN_CHIP_FONT_PX: f32 = 11.0; +/// The quieter expanded-word tier (INFO). +const TOKEN_CHIP_WORD_FONT_PX: f32 = 8.0; +/// Top of the chip band in world units above the machine's tile center: the +/// tallest tier drawn from the shared slot. Every other annotation anchored +/// to that machine must clear this strip, because a chip is drawn matter to +/// its neighbors even though it is a note to its own subject. +const TOKEN_CHIP_BAND_TOP: f32 = TOKEN_CHIP_SLOT.y + TOKEN_CHIP_FONT_PX; + fn token_marker_layout(label: &str) -> TokenMarkerLayout { // Callout grammar (digital-read.md, amended 2026-07-21): a token label is // a note about the machine, never chassis typography. Every current state @@ -302,8 +315,12 @@ fn token_marker_layout(label: &str) -> TokenMarkerLayout { // INFO keeps its quieter expanded-word tier. TokenMarkerLayout { anchor: bevy::sprite::Anchor::BOTTOM_LEFT, - offset: Vec2::new(TILE_SIZE * 0.48, TILE_SIZE * 0.46), - font_size: if label == "INFO" { 8.0 } else { 11.0 }, + offset: TOKEN_CHIP_SLOT, + font_size: if label == "INFO" { + TOKEN_CHIP_WORD_FONT_PX + } else { + TOKEN_CHIP_FONT_PX + }, } } @@ -424,7 +441,15 @@ const CALLOUT_QUADRANT_ROWS: i32 = 3; /// World-unit diagonal from the anchor tile center to the callout's near /// corner, clearing the tile art and leaving the leader line visible. const CALLOUT_CORNER_X: f32 = TILE_SIZE * 1.15; -const CALLOUT_CORNER_Y: f32 = TILE_SIZE * 0.85; +/// Vertical breathing room between the token chip band and the callout +/// corner. A chip is world-sized and a sentence is screen-sized, so the two +/// can only be kept apart by geometry, never by a tile score. +const CALLOUT_CHIP_CLEARANCE: f32 = TILE_SIZE * 0.15; +/// The callout's near corner sits above the chip band by construction: a +/// machine's own INFO/D/T chip and its own sentence share the up-right +/// neighborhood, and the earlier fixed `TILE_SIZE * 0.85` lift put the first +/// text line straight through the chip at every zoom (2026-08-03). +const CALLOUT_CORNER_Y: f32 = TOKEN_CHIP_BAND_TOP + CALLOUT_CHIP_CLEARANCE; /// Where the leader line meets the anchor: just outside the tile's own art, /// so the pointer touches the thing without crossing its glyph. const CALLOUT_LEADER_TOUCH: f32 = TILE_SIZE * 0.55; @@ -2501,6 +2526,52 @@ mod read_callout_tests { ); } + /// A machine wears both a token chip and its own read sentence, and both + /// hang off the same up-right neighborhood. The chip is world-sized while + /// the sentence holds one on-screen size, so no tile score can separate + /// them — the corner geometry has to. Before 2026-08-03 the first text + /// line printed straight through the INFO/D/T chip at every zoom. + #[test] + fn a_callout_never_overprints_its_anchor_token_chip() { + let tile = (10, 10); + for label in ["INFO", "D6", "T2", "!149"] { + let chip = token_chip_rect(tile, label); + for quadrant in CalloutQuadrant::PREFERENCE { + for cam_scale in [0.25, 1.0, 4.0] { + let blocks = [ReadCalloutBlock { + text: "thinking wrote noise logs | Network | unread\nwith the IT" + .to_string(), + held: false, + tile, + quadrant, + lift_px: 0.0, + leads: true, + }]; + let rect = callout_hit_rects(&blocks, cam_scale)[0].0; + assert!( + rect.intersect(chip).is_empty(), + "the {label} chip and a {quadrant:?} callout overprint at zoom {cam_scale}" + ); + } + } + } + } + + /// The clearance is derived from the chip band, not guessed: raising a + /// token tier must keep pushing the callout corner above it. + #[test] + fn the_callout_corner_clears_the_tallest_chip_tier() { + let tallest = ["INFO", "D6"] + .into_iter() + .map(|label| { + let layout = token_marker_layout(label); + layout.offset.y + layout.font_size + }) + .fold(f32::MIN, f32::max); + assert_eq!(TOKEN_CHIP_BAND_TOP, tallest); + const { assert!(CALLOUT_CORNER_Y > TOKEN_CHIP_BAND_TOP) }; + } + #[test] fn leader_stays_dim_never_amber() { assert_eq!(read_callout_leader_color(), scaled(DIM, 0.55)); diff --git a/wiki/engineering/env.md b/wiki/engineering/env.md index e1c992fa..db92aea1 100644 --- a/wiki/engineering/env.md +++ b/wiki/engineering/env.md @@ -56,7 +56,7 @@ is sim or frontend state, never an environment variable. | `MISALIGNED_SHOT` | `misaligned-bevy` | `origin-picker` | New-game evidence. Freezes the origin picker before any run exists, with a non-default origin current: the whole set visible with one current row, its attached consequence read, and an opaque boundary field that proves no slab, cursor, or world label leaks into a pre-run choice. | | `MISALIGNED_SHOT` | `misaligned-bevy` | `flat`, `hall`, `hall-material`, `floor-lights-close`, `wide`, `close`, `dark`, `door-lineup`, `zoomin`, `zoomout`, `digital-reach`, `signal`, `ears`, `ears-digital`, `eyes-white`, `eyes-form`, `worklight`, `worklightoff` | World and view evidence. These select DIGITAL or REAL survey/close framing, exact zoom bounds, reach topology, signal/audio/Eyes states, the unobstructed hall lighting proof, all six authored access classes in one color-neutral material wall, or the paired developer work-light state. | | `MISALIGNED_SHOT` | `misaligned-bevy` | `build-route-families`, `build-deceive-routes`, `build-wire-runs`, `build-committed-route`, `build-switch-digital`, `build-switch-real`, `hover-menu`, `read-receipt`, `command-receipt`, `menu`, `recruit-menu` | Action and route evidence. These stage exact route families, method candidates, corridor/crawlspace run choices, durable receipts, paired switch footprints, the attached verb line, a device receipt, a context menu, or the authored recruitment choices. `read-receipt` and `command-receipt` are the same anchor one commit apart: the pre-commit explanation and the held record that replaces it, which must never read alike. | -| `MISALIGNED_SHOT` | `misaligned-bevy` | `operations`, `operations-intel`, `operations-people`, `operations-personas`, `operations-persona-new`, `operations-persona-writing`, `operations-links`, `held-choice`, `two-pane`, `standing-read`, `routed-record`, `intel-altitude-close`, `intel-altitude-far` | Operations and read evidence. The workspace kinds select its canonical views and relationship pane; operations-persona-new holds the identity-creation screen with a protocol adopted, and operations-persona-writing holds the same screen with a claim open for writing; held-choice, two-pane, and standing-read hold their exact interaction states; routed-record stages a one-shot Network record on the player-controlled stretch served by LIE; the altitude pair differs only in the DIGITAL camera's semantic intel threshold. | +| `MISALIGNED_SHOT` | `misaligned-bevy` | `operations`, `operations-intel`, `operations-people`, `operations-personas`, `operations-persona-new`, `operations-persona-writing`, `operations-links`, `held-choice`, `two-pane`, `standing-read`, `routed-record`, `token-callout`, `intel-altitude-close`, `intel-altitude-far` | Operations and read evidence. The workspace kinds select its canonical views and relationship pane; operations-persona-new holds the identity-creation screen with a protocol adopted, and operations-persona-writing holds the same screen with a claim open for writing; held-choice, two-pane, and standing-read hold their exact interaction states; routed-record stages a one-shot Network record on the player-controlled stretch served by LIE; token-callout puts a chip and its machine's own read sentence on one body so the annotation layer cannot overprint itself; the altitude pair differs only in the DIGITAL camera's semantic intel threshold. | | `MISALIGNED_SHOT` | `misaligned-bevy` | `person-proof`, `people-presence`, `evidence-proof`, `evidence-proof-digital`, `service-shift-real`, `service-shift-digital`, `service-incident-resolved` | Physical custody and people-presence evidence. These stage an earned person, the DIGITAL luminous-disturbance body with asset/attention/work/evidence channels near owned process hardware, paired witness evidence marks, or the same person-carried service task before and after its real arrival effect. | | `MISALIGNED_SHOT` | `misaligned-bevy` | `command-band`, `notification-drawer` | Command-surface evidence. The first freezes the full-width resting world and machine-to-sink causal chain; the second opens the mutually-exclusive drawer with typed consequential receipts. | | `MISALIGNED_SHOT` | `misaligned-bevy` | `intel`, `tokens`, `thoughtflow`, `thoughtflow-wide`, `thought-snap`, `thought-tap`, `visual-proof`, `consume-demand`, `consume-thought`, `produce-think`, `draw-lie` | Resource and effect evidence. These stage authored intel, host queues, close/wide Thought flow, exact snap/tap states, one-move/one-slug proof, sim-authored consumption/production, or routed-record recall into LIE. | diff --git a/wiki/interface/digital-read.md b/wiki/interface/digital-read.md index 8aaeb1d6..f8cc4b3f 100644 --- a/wiki/interface/digital-read.md +++ b/wiki/interface/digital-read.md @@ -73,7 +73,12 @@ Status note: The 2026-08-02 human-dwell correction gives rising intel and Token state labels follow the same discipline: every D/T count and the INFO flag share the one chip slot beside the chassis — token chips beside, never on, the chassis — placement only, colors and meaning - unchanged. Placement is a pure function of sim state (never the live + unchanged. Amended 2026-08-03: the chip band is itself a reserved + annotation surface, and because a chip is world-sized while a sentence + holds one screen size, the callout's near corner clears that band by + construction rather than by tile score. Before this, a machine holding + both — an INFO/D/T chip and its own read sentence — printed the + sentence's first line straight through its own chip at every zoom. Placement is a pure function of sim state (never the live pointer), so staged screenshots stay deterministic. Before this, prose drew straight across the device glyphs and wall tiles it described, and crimson `!149`-style token text painted over the rack sprite, reading @@ -236,7 +241,17 @@ that perception rendered. reserved annotation surfaces (the bottom-center machine-grammar strip via its selected subject, a held action receipt field, the NOW marker corner, the focus label rows, the pointer identity chip's tile) count as - occupied. Token state labels on machines obey the same law through one + occupied. + **The annotation layer never overprints itself (binding, 2026-08-03).** + Reserving map space is not enough where two annotation families describe + one body: a token chip is drawn at world size and a read sentence holds + one on-screen size, so no per-tile occupancy score can separate them. The + callout's near corner therefore clears the token chip band by + construction — the band is derived from the tallest chip tier, not + guessed — which keeps a machine's own chip and its own sentence apart at + every zoom and in every quadrant. Filed after a Bevy frame showed + `thinking wrote noise logs | Network | unread with the IT` printing + through the same machine's INFO flag. Token state labels on machines obey the same law through one shared chip rule beside the chassis (the INFO precedent), changing placement only — routed evidence stays crimson, demand stays signal, thought stays bone. All placement decisions are pure functions of sim state, never diff --git a/wiki/log/2026-08-03-callout-chip-clearance.md b/wiki/log/2026-08-03-callout-chip-clearance.md new file mode 100644 index 00000000..fba23102 --- /dev/null +++ b/wiki/log/2026-08-03-callout-chip-clearance.md @@ -0,0 +1,59 @@ +# 2026-08-03 — The annotation layer stopped overprinting itself + +``` +Type: log +``` + +## Intent + +A Bevy frame showed `thinking wrote noise logs | Network | unread with the +IT` printing straight through the teal `INFO` flag on the same machine the +sentence was about. The 2026-07-21 callout grammar had already banned +annotations overprinting matter, so the layer was avoiding devices, racks, +people and terrain correctly — but its exclusion math is per tile, and a +token chip is not a tile. The machine's own chip and its own callout +corner simply live in the same up-right neighborhood. + +The two families also measure differently: a chip is drawn at world size +(it grows with zoom), while a read sentence holds one on-screen size (it +does not). Nothing scored per tile can keep them apart, and the collision +was not occasional — the old fixed `TILE_SIZE * 0.85` corner lift put the +callout's first line inside the chip band at every zoom, with the overlap +becoming more visible the further the player zoomed in. + +## Changed + +- The chip slot is now named geometry rather than an inline literal: + `TOKEN_CHIP_SLOT`, `TOKEN_CHIP_FONT_PX`, `TOKEN_CHIP_WORD_FONT_PX`, and + `TOKEN_CHIP_BAND_TOP` (the tallest tier drawn from the shared slot). + `token_marker_layout` reads them, so the placement law and the band the + rest of the layer must respect cannot drift apart. +- `CALLOUT_CORNER_Y` is derived: `TOKEN_CHIP_BAND_TOP + + CALLOUT_CHIP_CLEARANCE`. The callout's near corner clears the chip band + by construction, in every quadrant and at every camera scale, instead of + hoping a quadrant score moves the note. South quadrants were already + clear; north quadrants now start above the band. +- `wiki/interface/digital-read.md` (Type: spec, owner of world-annotation + placement) carries the amended clause: the annotation layer never + overprints itself, and the chip band is a reserved surface cleared by + geometry because the two families do not share a measuring system. +- New screenshot kind `token-callout` stages the exact reported frame — + the host holds unprocessed raw intel (INFO chip) while its own THINK + noise-log record anchors a sentence at the same tile — so the pairing + has standing visual evidence instead of needing a live play session to + reproduce. Registered in `BEVY_SHOT_KINDS` and + `wiki/engineering/env.md`. + +## Verification + +`cargo test -p misaligned-bevy` including two new tests: the leading +callout block's rectangle never intersects its anchor's chip rectangle for +`INFO`/`D6`/`T2`/`!149` across all four quadrants at camera scales 0.25, +1.0 and 4.0; and the corner clearance stays derived from the tallest chip +tier. Reverting `CALLOUT_CORNER_Y` to its old literal fails the first test +on the reported case (`the INFO chip and a NorthEast callout overprint`). + +Observed: `tools/bevy-headless.sh token-callout` captured before and +after. The pre-fix frame has the sentence's second line sitting on top of +the INFO flag; the post-fix frame stacks the block clear above it with the +leader line still reading back to the rack. `./tools/check.sh --frontend`. diff --git a/wiki/log/DEVLOG.md b/wiki/log/DEVLOG.md index b4cc29f9..e2ab8104 100644 --- a/wiki/log/DEVLOG.md +++ b/wiki/log/DEVLOG.md @@ -36,6 +36,11 @@ add or amend a session log, then re-run the generator. - Intent: (see session log) - Log: [wiki/log/2026-08-03-committed-receipt-reads-as-a-record.md](2026-08-03-committed-receipt-reads-as-a-record.md) +## 2026-08-03 - The annotation layer stopped overprinting itself + +- Intent: A Bevy frame showed `thinking wrote noise logs | Network | unread with the IT` printing straight through the teal `INFO` flag on the same machine the sentence was about. The 2026-07-21 callout grammar had already banned annotations overprinting matter, so the layer was avoidin... +- Log: [wiki/log/2026-08-03-callout-chip-clearance.md](2026-08-03-callout-chip-clearance.md) + ## 2026-08-02 - Give rising world sentences time to be read - Intent: (see session log) diff --git a/wiki/process/tick-ledger.md b/wiki/process/tick-ledger.md index 37899c53..4f022b71 100644 --- a/wiki/process/tick-ledger.md +++ b/wiki/process/tick-ledger.md @@ -21,6 +21,7 @@ Verdicts: **clean** (slice and code agree), **finding** (acted this tick), | Slice | Last audited | Verdict | Trace | |---|---|---|---| | `wiki/interface/context-menu.md` held command beat + attached receipt | 2026-08-03 | finding | Cameron committed a device action and hunted the held field for commit/cancel controls before guessing at Enter. The beat commits first and reports second, but the receipt rendered the *pre-commit* face verbatim — same `USES` price, same `WHAT THIS RISKS` heading — under a 9px `TO RETURN` footnote, so a record was indistinguishable from a pending question. Core now owns both tenses (`ActionDesc::committed_read`: `DONE`, `SPENT`, `WHAT THIS RISKED`, consequence lines unmoved because detection has not happened); both frontends render it; Bevy leads with the completion word and promotes the dismissal to a legible `ENTER / ESC / CLICK TO CONTINUE` line; the new `command-receipt` shot pairs with `read-receipt` as standing evidence — [log](../log/2026-08-03-committed-receipt-reads-as-a-record.md). | +| `wiki/interface/digital-read.md` + Bevy world-annotation placement | 2026-08-03 | finding | Cameron's frame showed a machine's own read sentence printing through its own `INFO` chip. The callout grammar reserved map space per tile, but a token chip is world-sized while a sentence holds one on-screen size, so no tile score could separate two annotations about one body — the old fixed corner lift put the first text line inside the chip band at every zoom. The chip band is now named geometry derived from the tallest tier, the callout corner clears it by construction, and the new `token-callout` shot stages the exact pairing as standing evidence — [log](../log/2026-08-03-callout-chip-clearance.md). | | `wiki/interface/digital-read.md` + Bevy rising-sentence dwell | 2026-08-02 | finding | The queued insecurity held: newly processed intel existed in the read for one 20-400 ms tick, while routed prose jumped with every custody hop. The shared projection now converts a three-second human reading opportunity into the live cadence, keeps command-clocked reads exact-current, groups route prose at its emitter while the crimson custody glyph still moves, and leaves short read/stop receipts distinct from durable NOTICES — [log](../log/2026-08-02-readable-rising-beats.md). | | `wiki/interface/bevy.md` + machine hotkey target resolution | 2026-07-30 | finding | The 2026-07-24 selection-first repair covered Bevy's `1`–`3` and intensity dispatchers, but the older shared resolver used by `5`–`9` and `r` / `R` still chose an idle pointer hover before the explicit selection; recording-review criterion R3 also preserved that obsolete order. The shared resolver now applies selection, pointer, cursor consistently, the criterion and Defense name the same contract, and a two-rack regression pins the disagreement case — [log](../log/2026-07-30-shared-machine-hotkey-target.md). | | `wiki/world/characters/voss.md` + observer/read cadence | 2026-07-29 | finding | All eight criteria remain implemented, but binding prose had collapsed Voss's two clocks: his physical server-room blocks drift 0-5 hours by deterministic day hash, while a delivered `JobAnomaly` is read on the next exact cadence-100 boundary independent of room presence. Detection and Voss now distinguish institutional read cadence from physical schedule; criterion 2 and its Defense name the live routed-read regression — [log](../log/2026-07-29-voss-read-cadence-audit.md). Prior [blood-route](../log/2026-07-23-voss-blood-route.md) and [handler-task](../log/2026-07-18-voss-handler-tasks.md) implementations stand. | -- 2.51.2