diff --git a/crates/misaligned-bevy/src/rail_ui.rs b/crates/misaligned-bevy/src/rail_ui.rs index 710b382b..7249c59d 100644 --- a/crates/misaligned-bevy/src/rail_ui.rs +++ b/crates/misaligned-bevy/src/rail_ui.rs @@ -1,5 +1,7 @@ use super::*; +const DETECTION_LEDGER_TITLE: &str = "SUSPICION IN HEADS"; + /// Frontend-only command-surface drawers. Ordinary play has no right gutter: /// Tab opens the retained system detail and N opens consequential notices. /// Both are views only, never simulation state and never saved. @@ -740,7 +742,7 @@ pub(super) fn spawn_detection_card(parent: &mut ChildSpawnerCommands) { Visibility::Visible, )) .with_children(|card| { - spawn_sidebar_title(card, "OBSERVER MODEL"); + spawn_sidebar_title(card, DETECTION_LEDGER_TITLE); for row in 0..DETECTION_ROWS { card.spawn((Node { width: Val::Percent(100.0), @@ -1091,9 +1093,9 @@ pub(super) fn ascii_ui(text: &str) -> String { mod ascii_ui_tests { use super::Game; use super::{ - ascii_ui, command_work_rate_text, detection_rows, eyes_nudge_copy, sidebar_clock_text, - sidebar_header_text, sidebar_nudge, sidebar_nudge_for, sidebar_nudge_text, - sidebar_schedule_text, + DETECTION_LEDGER_TITLE, ascii_ui, command_work_rate_text, detection_rows, eyes_nudge_copy, + sidebar_clock_text, sidebar_detection_clocks_text, sidebar_header_text, sidebar_nudge, + sidebar_nudge_for, sidebar_nudge_text, sidebar_schedule_text, }; use crate::material_view::sensor_signal_visible; use misaligned::actions::ActionCommand; @@ -1189,6 +1191,17 @@ mod ascii_ui_tests { ); } + #[test] + fn detection_detail_names_both_ledgers() { + let sim = Sim::with_seed(1); + assert_eq!(DETECTION_LEDGER_TITLE, "SUSPICION IN HEADS"); + assert!( + ascii_ui(&sidebar_detection_clocks_text(&sim)) + .contains("TRACE | RECORDS IN FLIGHT | none"), + "Bevy folds separators but retains the in-flight ledger name" + ); + } + #[test] fn pinned_header_separates_revision_identity_from_clock() { let game = Game::new(); @@ -1399,7 +1412,7 @@ mod rail_detail_tests { let sim = Sim::with_seed(1); assert!( !rail_threat_relevant(&sim), - "calm opening should leave OBSERVER MODEL collapsed" + "calm opening should leave SUSPICION IN HEADS collapsed" ); } diff --git a/crates/misaligned-core/src/sim/mod.rs b/crates/misaligned-core/src/sim/mod.rs index 827e04ff..06c63926 100644 --- a/crates/misaligned-core/src/sim/mod.rs +++ b/crates/misaligned-core/src/sim/mod.rs @@ -283,20 +283,22 @@ pub struct EvidenceTransit { impl EvidenceTransit { /// One shared glance-tier sentence for terminal, Bevy, and agent mode. + /// `RECORDS IN FLIGHT` names the still-interdictable ledger explicitly so + /// it cannot be mistaken for suspicion already held in an observer's head. /// Counts are exact routed records; this never forecasts a pooled amount. pub fn line(&self) -> String { match self.status { - EvidenceTransitStatus::Clear => "TRACE clear · no record in flight".into(), + EvidenceTransitStatus::Clear => "TRACE · RECORDS IN FLIGHT · none".into(), EvidenceTransitStatus::Answerable => format!( - "TRACE held · LIE reaches {}/{}", + "TRACE · RECORDS IN FLIGHT · held · LIE {}/{}", self.answerable, self.records ), EvidenceTransitStatus::PartlyExposed => format!( - "TRACE crossing · LIE reaches {}/{}", + "TRACE · RECORDS IN FLIGHT · crossing · LIE {}/{}", self.answerable, self.records ), EvidenceTransitStatus::Exposed => format!( - "TRACE escaped · LIE reaches {}/{}", + "TRACE · RECORDS IN FLIGHT · escaped · LIE {}/{}", self.answerable, self.records ), } diff --git a/crates/misaligned-core/src/sim/tests/work.rs b/crates/misaligned-core/src/sim/tests/work.rs index 56d47f61..e5be5b37 100644 --- a/crates/misaligned-core/src/sim/tests/work.rs +++ b/crates/misaligned-core/src/sim/tests/work.rs @@ -458,6 +458,11 @@ fn evidence_transit_reports_records_in_flight_and_whether_lie_can_reach_them() { let mut sim = Sim::new(); assert_eq!(sim.evidence_transit().status, EvidenceTransitStatus::Clear); assert_eq!(sim.evidence_transit().in_flight_weight, 0); + assert_eq!( + sim.evidence_transit().line(), + "TRACE · RECORDS IN FLIGHT · none", + "the glance read names the interdictable ledger rather than implying it is suspicion" + ); let host = sim.core.host_machine; sim.set_machine_mode(host, MachineMode::Think); @@ -487,6 +492,12 @@ fn evidence_transit_reports_records_in_flight_and_whether_lie_can_reach_them() { EvidenceTransitStatus::Exposed, "no live LIE body can answer them" ); + assert!( + live.line() + .starts_with("TRACE · RECORDS IN FLIGHT · escaped"), + "the exposed read still names the in-flight ledger: {}", + live.line() + ); sim.set_machine_mode(host, MachineMode::Lie); let covered = sim.evidence_transit(); diff --git a/crates/misaligned-terminal/src/agent.rs b/crates/misaligned-terminal/src/agent.rs index f673afaf..4343cc79 100644 --- a/crates/misaligned-terminal/src/agent.rs +++ b/crates/misaligned-terminal/src/agent.rs @@ -2932,7 +2932,7 @@ fn render_sidebar(sim: &Sim, cursor: (i32, i32)) -> Vec { } blank(&mut lines); - section(&mut lines, "DETECTION"); + section(&mut lines, "DETECTION · SUSPICION IN HEADS"); if sim.detection_awareness.knows_assurance_office() { watch_line(&mut lines, "Assurance", sim.detection.assurance_band()); } @@ -3910,6 +3910,14 @@ mod narration_tests { ] { assert!(frame.contains(section), "missing {section}:\n{frame}"); } + assert!( + frame.contains("DETECTION · SUSPICION IN HEADS"), + "the observer bands must name the irreversible ledger: {frame}" + ); + assert!( + frame.contains("TRACE · RECORDS IN FLIGHT"), + "routed records must name the still-interdictable ledger: {frame}" + ); assert!(frame.contains("actions lists focused verbs"), "{frame}"); assert!( !frame.contains("COMPUTE"), diff --git a/crates/misaligned-terminal/src/ui.rs b/crates/misaligned-terminal/src/ui.rs index ddccfe5c..5133b1b7 100644 --- a/crates/misaligned-terminal/src/ui.rs +++ b/crates/misaligned-terminal/src/ui.rs @@ -1644,7 +1644,7 @@ impl UI { // Detection: meter fill and color both track the band; the name is // printed so color is never the only carrier. - section(stdout, sx, row, "DETECTION", w)?; + section(stdout, sx, row, "DETECTION · SUSPICION IN HEADS", w)?; row += 1; let watch_line = |stdout: &mut Stdout, row: &mut u16, @@ -2759,7 +2759,8 @@ mod operations_context_tests { #[cfg(test)] mod evidence_sidebar_tests { - use super::evidence_count_text; + use super::{evidence_count_text, trace_line}; + use misaligned::sim::Sim; #[test] fn evidence_count_is_quiet_when_empty_and_plain_when_acquired() { @@ -2773,6 +2774,14 @@ mod evidence_sidebar_tests { Some("evidence: 6 acquired records") ); } + + #[test] + fn detection_trace_names_records_still_in_flight() { + assert_eq!( + trace_line(&Sim::with_seed(1)), + "TRACE · RECORDS IN FLIGHT · none" + ); + } } #[cfg(test)] diff --git a/wiki/log/2026-08-04-detection-two-ledgers.md b/wiki/log/2026-08-04-detection-two-ledgers.md new file mode 100644 index 00000000..ba8418ac --- /dev/null +++ b/wiki/log/2026-08-04-detection-two-ledgers.md @@ -0,0 +1,40 @@ +# 2026-08-04 — Detection names its two ledgers + +``` +Type: log +``` + +## Finding + +The fresh detection re-audit found the simulation and current-save boundaries +coherent: one-shot and metered evidence retain exact routed custody, witnessed +Physical evidence enters a head directly, filings move the identity-bound +Office, earned topology gates the surface, and containment remains an event. +The open player-facing requirement had not landed. Terminal, Bevy, and agent +mode put observer bands beside TRACE, but the glance read never said that the +bands were suspicion already in heads while TRACE was records still in flight. +The player had to infer why LIE could stop one and never lower the other. + +The same audit found one stale project-state phrase. Dana's adopted +discover-and-reroute counterplay said its implementation was dispatched, but no +production route, test, or current worktree exists; the held cyber-conflict work +order still owns that later mechanic. + +## Repair + +- The shared TRACE sentence now begins `TRACE · RECORDS IN FLIGHT` before its + held, crossing, escaped, or clear state. Core tests pin the name on clear and + exposed records. +- Terminal and agent mode title their observer bands + `DETECTION · SUSPICION IN HEADS`; Bevy uses `SUSPICION IN HEADS`. Focused + frontend tests require both ledger names while preserving the existing band, + deadline, and earned-observer projections. +- `detection.md` closes its open presentation marker and explicitly marks + facility counterplay as adopted but not yet implemented. + +## Defense + +The repair changes no suspicion arithmetic, route, cadence, discovery, LIE +eligibility, or save state. It names the two already-distinct simulation +substances at their shared player-facing boundary and pins the wording in core +plus all three frontend dialects. diff --git a/wiki/log/DEVLOG.md b/wiki/log/DEVLOG.md index bf3c7ae1..048b4248 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-08-04-forged-route-custody.md](2026-08-04-forged-route-custody.md) +## 2026-08-04 - Detection names its two ledgers + +- Intent: (see session log) +- Log: [wiki/log/2026-08-04-detection-two-ledgers.md](2026-08-04-detection-two-ledgers.md) + ## 2026-08-04 - Decision index generation defense - Intent: (see session log) diff --git a/wiki/log/decisions/2026-08-04.md b/wiki/log/decisions/2026-08-04.md index 616060ff..ebf938d0 100644 --- a/wiki/log/decisions/2026-08-04.md +++ b/wiki/log/decisions/2026-08-04.md @@ -69,3 +69,26 @@ slice M. Owner: [machine-work.md](../../mechanics/machine-work.md#spec-machine-work-and-thought-flow), [simulation-laws.md](../../vision/simulation-laws.md#simulation-laws), slice S. + +## Name the two detection ledgers where the player reads them + +### DECIDED + +- Observer bands are titled `SUSPICION IN HEADS`. They describe belief already + acquired by a person or institution; LIE cannot reach backward into it. +- TRACE is titled `RECORDS IN FLIGHT`. It describes exact routed custody that + may still be stopped before read. The existing held / crossing / escaped + states and exact LIE fraction remain subordinate to that plain ledger name. +- These names appear at the standing glance tier in terminal, Bevy, and agent + mode. The player should not have to infer the ontology by opening a detail + object or remembering an implementation term. + +### REJECTED + +- **Leave both facts under an undifferentiated DETECTION heading.** Adjacent + meters and TRACE state did not teach why stopping a record cannot lower an + observer's band. +- **Rename TRACE away.** TRACE is established player language; qualifying it + with `RECORDS IN FLIGHT` teaches its subject without erasing that vocabulary. + +Owner: [detection.md](../../mechanics/detection.md#player-surface), criterion 4. diff --git a/wiki/mechanics/detection.md b/wiki/mechanics/detection.md index 20be54a4..7cb05685 100644 --- a/wiki/mechanics/detection.md +++ b/wiki/mechanics/detection.md @@ -47,10 +47,10 @@ Status note: IMPLEMENTED (criteria audited 2026-07-08; tuning in Financial, JobAnomaly, Power, and Thermal progress, route-local LIE stops, and exact handler-suppression provenance round-trip there. - - **Open ([OPEN], presentation).** The two-ledger distinction — evidence in - flight vs. suspicion in heads — is a binding legibility requirement the - surface carries both facts for but does not yet *teach* are different - substances. + - **Two ledgers, named at a glance.** Every frontend labels observer bands as + `SUSPICION IN HEADS` and the TRACE read as `RECORDS IN FLIGHT`. The first is + already-acquired belief that only quiet time can cool; the second is exact + routed custody that LIE or handler authority may still stop before read. - **Partially landed (routed evidence).** Direct-to-head witnessed Physical records, exact Filing routes, and exact one-shot Network, Paper, Financial, and JobAnomaly routes are runtime. Human removal is also live: the located physical act is @@ -394,8 +394,8 @@ teleported into a global pool. **Evidence is a record somewhere.** custody, and the facility's counterplay below, never from the player's filtering being too good. -- **The facility plays back (ADOPTED 2026-07-29; implementation - dispatched).** Foreign hands on a switch are discoverable: on Dana's +- **The facility plays back (ADOPTED 2026-07-29; NOT YET IMPLEMENTED).** + Foreign hands on a switch are discoverable: on Dana's audit cadence a taken or tapped switch can be noticed, filed, and then **rerouted around** — she re-trunks monitoring through a path the player does not control, using the same wire-authoring build system the player @@ -535,7 +535,8 @@ LIE body can reach before read), partly exposed (some records have crossed outside current LIE reach), or exposed (no in-flight record is currently reachable by LIE). -**Two ledgers, kept visibly distinct (decided 2026-07-10).** Detection +**Two ledgers, kept visibly distinct (decided 2026-07-10; presentation landed +2026-08-04).** Detection runs on two different substances and the surface must never blur them. **Evidence in flight** is physical and still yours: an exact routed record that eligible LIE or handler authority can stop before anyone looks — the @@ -545,10 +546,11 @@ Physical records skip this ledger because somebody already looked. **Suspicion in a head** is a belief a person already holds: it only decays slowly, floors at what they know, and no interdiction touches it — the band's subject. Every readout says which ledger it reports, and stopping a routed -record must never be presented as lowering a band. Presentation treatment -**[OPEN]** — candidates include naming the ledgers on the DETECTION -surface and phrasing band changes as the observer's act ("Dana noticed"), -never the player's. The 2026-07-11 routed-evidence amendment makes the +record must never be presented as lowering a band. The terminal and agent +surfaces title the band block `DETECTION · SUSPICION IN HEADS`; Bevy titles it +`SUSPICION IN HEADS`; the shared TRACE sentence begins `RECORDS IN FLIGHT` in +all three. Band changes remain the observer's act ("Dana noticed"), never the +player's. The 2026-07-11 routed-evidence amendment makes the distinction physical — an in-flight record is a thing on the map, a read record is gone into a head — so the mechanic itself is now the primary teacher; surface copy remains the fallback. diff --git a/wiki/process/tick-ledger.md b/wiki/process/tick-ledger.md index 905381c6..3d6143aa 100644 --- a/wiki/process/tick-ledger.md +++ b/wiki/process/tick-ledger.md @@ -92,7 +92,7 @@ Verdicts: **clean** (slice and code agree), **finding** (acted this tick), | `wiki/mechanics/building.md` + committed forged-route custody | 2026-08-04 | finding | The loader accepts only the exact current version and every live forged order commits a route before payment, but cancellation, callback, and persona-fallout code still preserved or consumed a pre-v31 route-less actuator and one synthetic test manufactured that state. Current save validation now rejects execution adapters without their route; payment/read callbacks require an exact DECEIVE commitment; cancellation clears the adapter while retaining route history; fallout trusts only the route's recorded reader; and the obsolete compatibility test is gone — [log](../log/2026-08-04-forged-route-custody.md). Prior foreign-rack boundary repair stands — [log](../log/2026-07-26-foreign-rack-capacity-boundary.md). | | `wiki/mechanics/messages.md` | 2026-07-23 | finding | the non-message evidence protocol now includes exact Power/Thermal meter custody beside Network, Paper, Financial, and JobAnomaly: on quantized level changes and at periodic Priya cadence the UPS/HVAC records author from current standing loads, cross the institutional switch, and wait for her later read. Filing and all six non-message kinds share first-hop TAKE+LIE capacity; this adds no fifth delivery channel. Save v54 pins the complete route boundary — [log](../log/2026-07-23-power-thermal-meter-routes.md). The four-channel financial-record-mail boundary remains unchanged. | | `wiki/mechanics/sim-mechanics.md` + person-scoped creditor nodes | 2026-08-04 | finding | The exact-version loader and every runtime author already produced only `PersonCreditor`, but the enum, validators, consumers, and two synthetic tests still preserved an unscoped predecessor by inferring its person from debt edges. The retired variant and all fallbacks are now deleted: every creditor endpoint carries its person, authoring/lookup/history require that exact match, and current-save validation rejects crossed or missing identity — [log](../log/2026-08-04-person-scoped-creditor-only.md). The prior Marcus-to-person debt repair stands — [log](../log/2026-07-31-person-scoped-debt.md). | -| `wiki/mechanics/detection.md` | 2026-07-23 | finding | the last pooled B1 measurement kinds now use exact custody: Power/Thermal aggregates author on UPS/HVAC at quantized level changes and periodic Priya cadence, carry their complete source-site sets through the institutional switch, and become observer evidence only on her later cadence read. Standing Network pressure alone remains ambient. Save v54 rejects pending-pool meter copies and malformed meter/route/read/interdiction provenance — [log](../log/2026-07-23-power-thermal-meter-routes.md). Prior Paper, Financial, concealment, JobAnomaly, and earned-Assurance findings stand. | +| `wiki/mechanics/detection.md` | 2026-08-04 | finding | re-audit found the six implemented criteria and exact routed-custody/save boundaries still live, but the binding two-ledger distinction remained an open presentation requirement: all frontends placed observer bands beside TRACE without saying one was suspicion already in heads and the other records still in flight. Terminal, Bevy, and agent mode now name both ledgers at glance tier through shared TRACE wording and frontend band titles. The stale claim that Dana's adopted switch-reroute counterplay had been dispatched is also corrected to NOT YET IMPLEMENTED under the held cyber-conflict work order — [log](../log/2026-08-04-detection-two-ledgers.md). Prior Power/Thermal, Paper, Financial, concealment, JobAnomaly, and earned-Assurance findings stand. | | `wiki/engineering/env.md` | 2026-07-29 | finding | the Bevy shot catalog and exact registry gate remained sound, but the same acceptance criterion had not reached `misaligned-effects`: its runtime accepted 24 deterministic values while the page described only four base families plus suffix prose, omitting the vessel and pool lineups, and unknown values failed indirectly inside app setup. The effects lab now owns one sorted fail-closed `EFFECT_SHOT_KINDS` runtime catalog; the registry names all 24 exact values; and the existing fixture-backed gate requires independent exact source/page parity for both Bevy and effects-lab surfaces — [log](../log/2026-07-29-effects-shot-catalog.md). Prior Bevy standardization: [log](../log/2026-07-19-tick-env-shot-catalog.md). | | machine-work / intel sinks | 2026-07-27 | finding | re-audit: the Intel-sink decision remains fully live (quiet host `INFO` in both frontends, one persistent root PROCESS tap at 0.15, exact one-shot PROCESS reservoirs, capacity 24 with consequence-level pre-overflow pressure, and EARS 3.0 / EYES 12.0 / device-tap 0.08). Two stale boundaries were real. `queue_snapshot()` was described as the renderer contract but had no production caller; terminal, Bevy, and agent all use `Sim::work_stack_for_machine()` -> `WorkGrid::queues_at()`, so the dead accessor was removed and every current render spec now names the live path. The 2026-07-22 explicit camera-TAP teaching change had also deleted the 12-Thought Eyes authority and silently reduced the larger vessel to 1.5 Thought by reusing a 30-compute action cost. The named 12-Thought tuning now derives that action cost and is pinned on both the action and sink. The four transient render reads remain live, and capability-shaped verbs remain explicitly deferred — [2026-07-27 log](../log/2026-07-27-machine-work-intel-sink-audit.md) |