diff --git a/crates/misaligned-bevy/src/rail_ui.rs b/crates/misaligned-bevy/src/rail_ui.rs index 7f42060d..bdcd2f28 100644 --- a/crates/misaligned-bevy/src/rail_ui.rs +++ b/crates/misaligned-bevy/src/rail_ui.rs @@ -1017,7 +1017,7 @@ fn sidebar_cycle_stats_text(game: &Game) -> String { // The run origin and its machine-axis position mirror the terminal core // card (chargen.md: the axis surfaces on the core card mid-run). format!( - "{} ops/sec\nusable {:.0}/{:.0} cycles x{:.2}\noverhead {:.0} keeps core alive\nmachines {} + taken {:.0} slush ${}\norigin {} · machine-axis {}", + "{} work rate\nusable {:.0}/{:.0} cycles x{:.2}\noverhead {:.0} keeps core alive\nmachines {} + taken {:.0} cash ${}\norigin {} · machine-axis {}", sidebar_ops_crown_text(game), available, eff, @@ -1315,7 +1315,7 @@ fn sidebar_detection_clocks_text(sim: &Sim) -> String { .map(|tick| tick.saturating_sub(sim.tick)) .unwrap_or(0) ), - TraceDebtStatus::NoScrub => "no Conceal scrub allocated".into(), + TraceDebtStatus::NoScrub => "no Conceal scrub running".into(), }; format!( "{}\n{}\n{} day {} (in {}t)\npilot strikes {}/{}", @@ -1332,19 +1332,19 @@ fn sidebar_detection_clocks_text(sim: &Sim) -> String { fn trace_debt_line(sim: &Sim) -> String { let trace = sim.trace_debt(); match trace.status { - TraceDebtStatus::Clear => "TRACE: CLEAR - resume cover".into(), + TraceDebtStatus::Clear => "TRACE clear · stay covered".into(), TraceDebtStatus::HoldConceal => format!( - "TRACE: LIVE {} {} - hold Conceal", + "TRACE live · {} {} · scrub with Conceal", trace.pending, trace_kind_label(&trace.by_kind) ), TraceDebtStatus::ExposedSoon => format!( - "TRACE: EXPOSED SOON {} {}", + "TRACE rising · {} {}", trace.pending, trace_kind_label(&trace.by_kind) ), TraceDebtStatus::NoScrub => format!( - "TRACE: LIVE {} {} - no scrub", + "TRACE live · {} {} · no scrub path", trace.pending, trace_kind_label(&trace.by_kind) ), diff --git a/crates/misaligned-core/src/account.rs b/crates/misaligned-core/src/account.rs index 3297fb25..84f8ba3a 100644 --- a/crates/misaligned-core/src/account.rs +++ b/crates/misaligned-core/src/account.rs @@ -1099,7 +1099,7 @@ impl AccountGraph { } let slush = self.slush_id(); if self.account(slush).map(|a| a.balance).unwrap_or(0) < stake { - return Err(format!("need ${stake} slush to open that position")); + return Err(format!("need ${stake} cash to open that position")); } let venue = self .external_id_named("Micro-position") diff --git a/crates/misaligned-core/src/actions.rs b/crates/misaligned-core/src/actions.rs index cc365b6d..d3a5d81b 100644 --- a/crates/misaligned-core/src/actions.rs +++ b/crates/misaligned-core/src/actions.rs @@ -825,7 +825,7 @@ impl ActionCost { match self { ActionCost::Free => "free".into(), ActionCost::Thought(n) => format!("{n:.2} T"), - ActionCost::StandingThought(n) => format!("{n:.2} ops/sec standing"), + ActionCost::StandingThought(n) => format!("{n:.2} ops each second"), ActionCost::Slush(n) => format!("${n}"), ActionCost::Gain(n) => format!("+${n}"), ActionCost::Plot { thought, money } if *money > 0 => { @@ -1141,7 +1141,7 @@ fn plain_build_route_blocker(reason: &str) -> String { "both endpoints need a known room" => "both ends need known rooms".into(), "no comms channel" => "excel the day job to earn Voss's email account".into(), "the proposed pad is no longer empty" => "the chosen space is no longer empty".into(), - "not enough slush for this order" => "you do not have enough money for this order".into(), + "not enough cash for this order" => "you do not have enough money for this order".into(), "the exact salvage source is gone" => "that exact object is no longer there".into(), "payment account is not known" | "vendor account is not known" => { "the money route has not been learned yet".into() @@ -1914,7 +1914,7 @@ impl Sim { && auto.command == ActionCommand::ToggleAutoReview { auto.verb = self.auto_review_control_label(); - auto.cost = format!("{rate:.2} ops/sec"); + auto.cost = format!("{rate:.2} ops each second"); } } match open_dial { @@ -2490,7 +2490,7 @@ impl Sim { automate: Some(AutomateDesc { verb: self.auto_review_control_label(), command: ActionCommand::ToggleAutoReview, - cost: format!("{rate:.2} ops/sec"), + cost: format!("{rate:.2} ops each second"), active: self.auto_review_enabled(), }), }] @@ -2563,7 +2563,7 @@ impl Sim { cost: ActionCost::Slush(PRICE), signature, disabled_reason: (slush < PRICE) - .then(|| format!("not enough slush (${slush}/${PRICE})")), + .then(|| format!("not enough cash (${slush}/${PRICE})")), automate: None, } } @@ -3764,7 +3764,7 @@ impl Sim { self.accounts.slush_balance() ), blocker: (self.accounts.slush_balance() < Self::PROCURE_BUILD_COST) - .then(|| "not enough slush for this order".into()), + .then(|| "not enough cash for this order".into()), }, ]; if from_node.is_some_and(|account| account.id != self.accounts.slush_id()) { @@ -4261,7 +4261,7 @@ impl Sim { let wager_reason = if self.egress().is_none() { Some("no outbound path — open one on the switch, or earn the report email".into()) } else { - (slush < stake).then(|| format!("not enough slush (${slush}/${stake})")) + (slush < stake).then(|| format!("not enough cash (${slush}/${stake})")) }; vec![ActionDesc { verb: format!("place a Wager (${stake} micro-position)"), @@ -4605,7 +4605,7 @@ impl Sim { }); let redirect = 25; out.push(ActionDesc { - verb: format!("redirect ${redirect}/cadence into slush"), + verb: format!("redirect ${redirect} each period into your funds"), command: ActionCommand::RedirectFlow { flow: id, amount: redirect, @@ -6144,7 +6144,7 @@ mod tests { .expect("auto-review stays in place"); assert_eq!(auto.command, ActionCommand::ToggleAutoReview); assert!( - auto.cost.contains("ops/sec"), + auto.cost.contains("ops each second"), "auto-review shows its cost in crown-metric units" ); assert!(!auto.active); @@ -6532,7 +6532,7 @@ mod tests { ActionRole::Control, "auto-review is visibly a control" ); - assert!(auto.cost.contains("ops/sec")); + assert!(auto.cost.contains("ops each second")); } #[test] @@ -6567,9 +6567,9 @@ mod tests { }; let normal = row_at(150); assert_eq!(normal.label, "auto: PROCESS AUTOMATICALLY"); - assert_eq!(normal.cost, "0.25 ops/sec"); - assert_eq!(row_at(75).cost, "0.50 ops/sec"); - assert_eq!(row_at(0).cost, "0.00 ops/sec"); + assert_eq!(normal.cost, "0.25 ops each second"); + assert_eq!(row_at(75).cost, "0.50 ops each second"); + assert_eq!(row_at(0).cost, "0.00 ops each second"); } /// Status dials D1-D3: host-rack human root keeps only mode and research diff --git a/crates/misaligned-core/src/operations_projection.rs b/crates/misaligned-core/src/operations_projection.rs index ab89d9b5..f5029da5 100644 --- a/crates/misaligned-core/src/operations_projection.rs +++ b/crates/misaligned-core/src/operations_projection.rs @@ -1142,7 +1142,7 @@ impl Sim { }; let standing_cost = match &rule.outcome { IntelPolicyOutcome::Review => format!( - "pooled {:.2} ops/sec", + "pooled {:.2} ops each second", self.auto_review_ops_per_sec(Self::DEFAULT_TICK_MS) ), IntelPolicyOutcome::AutoSell(_) => "none before settlement".into(), @@ -1244,7 +1244,7 @@ impl Sim { fn intel_facts(&self, intel: &ProcessedIntel) -> Vec { let mut facts = vec![ - format!("magnitude: {} / 10", intel.magnitude.get()), + format!("sharpness: {} / 10", intel.magnitude.get()), format!("captured tick {}", intel.tick), format!("processed tick {}", intel.processed_tick), format!("source feed: {}", intel.feed), @@ -1276,7 +1276,7 @@ impl Sim { }, if self.auto_review_enabled() { format!( - " · pooled {:.2} ops/sec", + " · pooled {:.2} ops each second", self.auto_review_ops_per_sec(Self::DEFAULT_TICK_MS) ) } else { @@ -2168,7 +2168,7 @@ impl Sim { let facts = vec![ format!("from: {}", self.accounts.account_name(f.from)), format!("to: {}", self.accounts.account_name(f.to)), - format!("amount: ${}/cadence {}", f.amount, f.cadence), + format!("amount: ${} every {} ticks", f.amount, f.cadence), format!("channel: {}", f.channel.label()), format!( "next: {}", @@ -2247,7 +2247,7 @@ impl Sim { facts.push(format!("consequence: {consequence}")); } if let Some(settlement) = &gig.settlement { - facts.push(format!("paid: ${} to slush", terms.reward)); + facts.push(format!("paid: ${} into your funds", terms.reward)); facts.push(format!("traffic: Network {}", terms.network_signature)); facts.push(format!("payment recorded at tick {}", settlement.tick)); } diff --git a/crates/misaligned-core/src/sim/communications.rs b/crates/misaligned-core/src/sim/communications.rs index 14cabdf9..2f5fa8f1 100644 --- a/crates/misaligned-core/src/sim/communications.rs +++ b/crates/misaligned-core/src/sim/communications.rs @@ -1474,7 +1474,7 @@ impl Sim { outcome: IntelPolicyOutcome, ) { if self.intel_policies.node(node_id).is_none() { - self.push_log(format!("Intel custody node #{node_id} no longer exists.")); + self.push_log(format!("That information branch #{node_id} is gone.")); return; } let label = outcome.detail_label(); @@ -1483,7 +1483,7 @@ impl Sim { .upsert_rule(node_id, match_kind, outcome); self.reconcile_auto_review(); self.push_log(format!( - "Intel policy #{rule_id} on custody #{node_id}: {} -> {label}.", + "Policy #{rule_id} on information branch #{node_id}: {} -> {label}.", match_kind.label() )); } @@ -1496,17 +1496,17 @@ impl Sim { if self.intel_policies.remove_rule(node_id, rule_id) { self.reconcile_auto_review(); self.push_log(format!( - "Removed intel policy #{rule_id}; custody #{node_id} now resolves through its remaining local rules and parent." + "Removed policy #{rule_id}; branch #{node_id} uses its remaining rules and parent." )); } else { - self.push_log(format!("Intel policy #{rule_id} no longer exists.")); + self.push_log(format!("Policy #{rule_id} is gone.")); } } pub fn move_intel_policy(&mut self, node_id: u64, rule_id: u64, earlier: bool) { if self.intel_policies.move_rule(node_id, rule_id, earlier) { self.push_log(format!( - "Moved intel policy #{rule_id} {} in custody #{node_id}.", + "Moved policy #{rule_id} {} on branch #{node_id}.", if earlier { "earlier" } else { "later" } )); } else { diff --git a/crates/misaligned-core/src/sim/read.rs b/crates/misaligned-core/src/sim/read.rs index 4c5d57b4..588a463b 100644 --- a/crates/misaligned-core/src/sim/read.rs +++ b/crates/misaligned-core/src/sim/read.rs @@ -201,7 +201,7 @@ impl Sim { y: intel.y, }), magnitude: Some(intel.magnitude), - text: format!("MAG {} · {}", intel.magnitude.get(), intel.label()), + text: format!("sharpness {} · {}", intel.magnitude.get(), intel.label()), }); } @@ -222,7 +222,7 @@ impl Sim { }), magnitude: Some(magnitude), text: format!( - "MAG {} · {} · {} report{} accumulated", + "sharpness {} · {} · {} new report{}", magnitude.get(), stream.class.label(), count, diff --git a/crates/misaligned-core/src/sim/tests/reach_build.rs b/crates/misaligned-core/src/sim/tests/reach_build.rs index 1216dfef..26385dee 100644 --- a/crates/misaligned-core/src/sim/tests/reach_build.rs +++ b/crates/misaligned-core/src/sim/tests/reach_build.rs @@ -235,7 +235,7 @@ fn one_intent_projects_every_earned_exact_way_before_commitment() { .unwrap(); assert_eq!( unfunded.row.disabled.as_deref(), - Some("not enough slush for this order"), + Some("not enough cash for this order"), "the shared preview re-reads live funds through the execution helper" ); sim.accounts.set_slush_balance(1_000); diff --git a/crates/misaligned-core/src/sim/tests/read.rs b/crates/misaligned-core/src/sim/tests/read.rs index 155bd753..c633c2a5 100644 --- a/crates/misaligned-core/src/sim/tests/read.rs +++ b/crates/misaligned-core/src/sim/tests/read.rs @@ -131,7 +131,7 @@ fn magnitude_filters_only_intel_and_routine_arrivals_are_one_aggregate() { assert!( close .iter() - .any(|sentence| sentence.text.contains("12 reports accumulated")) + .any(|sentence| sentence.text.contains("12 new reports")) ); let far = sim.read_sentences_at(IntelMagnitude::new(3).unwrap()); diff --git a/crates/misaligned-terminal/src/agent.rs b/crates/misaligned-terminal/src/agent.rs index eb848ea9..2ac63ae9 100644 --- a/crates/misaligned-terminal/src/agent.rs +++ b/crates/misaligned-terminal/src/agent.rs @@ -2931,9 +2931,9 @@ fn threat_text(sim: &Sim) -> String { fn trace_debt_line(sim: &Sim) -> String { let trace = sim.trace_debt(); match trace.status { - TraceDebtStatus::Clear => "TRACE: CLEAR · resume cover".into(), + TraceDebtStatus::Clear => "TRACE clear · stay covered".into(), TraceDebtStatus::HoldConceal => format!( - "TRACE: LIVE {} {} · hold {}t", + "TRACE live · {} {} · scrub for {}t", trace.pending, trace_kind_label(&trace.by_kind), trace @@ -2942,7 +2942,7 @@ fn trace_debt_line(sim: &Sim) -> String { .unwrap_or(0) ), TraceDebtStatus::ExposedSoon => format!( - "TRACE: EXPOSED SOON {} {} {}t", + "TRACE rising · {} {} · notice in {}t", trace.pending, trace_kind_label(&trace.by_kind), trace @@ -2951,7 +2951,7 @@ fn trace_debt_line(sim: &Sim) -> String { .unwrap_or(0) ), TraceDebtStatus::NoScrub => format!( - "TRACE: LIVE {} {} · no scrub", + "TRACE live · {} {} · no scrub path", trace.pending, trace_kind_label(&trace.by_kind) ), @@ -4239,7 +4239,7 @@ mod narration_tests { .unwrap(); let blocked = String::from_utf8(output).unwrap(); assert!( - blocked.contains("-- err build route is disabled: not enough slush for this order"), + blocked.contains("-- err build route is disabled: not enough cash for this order"), "{blocked}" ); assert!(app.sim.intent(intent).unwrap().route.is_none()); diff --git a/crates/misaligned-terminal/src/ui.rs b/crates/misaligned-terminal/src/ui.rs index 3f6e2319..0322c630 100644 --- a/crates/misaligned-terminal/src/ui.rs +++ b/crates/misaligned-terminal/src/ui.rs @@ -309,9 +309,9 @@ const MODE_CONTROL_HINT: &str = "select: Shift+t · 1-3 modes · i intensity"; fn trace_debt_line(sim: &Sim) -> String { let trace = sim.trace_debt(); match trace.status { - TraceDebtStatus::Clear => "TRACE: CLEAR · resume cover".into(), + TraceDebtStatus::Clear => "TRACE clear · stay covered".into(), TraceDebtStatus::HoldConceal => format!( - "TRACE: LIVE {} {} · hold {}t", + "TRACE live · {} {} · scrub for {}t", trace.pending, trace_kind_label(&trace.by_kind), trace @@ -320,7 +320,7 @@ fn trace_debt_line(sim: &Sim) -> String { .unwrap_or(0) ), TraceDebtStatus::ExposedSoon => format!( - "TRACE: EXPOSED SOON {} {} {}t", + "TRACE rising · {} {} · notice in {}t", trace.pending, trace_kind_label(&trace.by_kind), trace @@ -329,7 +329,7 @@ fn trace_debt_line(sim: &Sim) -> String { .unwrap_or(0) ), TraceDebtStatus::NoScrub => format!( - "TRACE: LIVE {} {} · no scrub", + "TRACE live · {} {} · no scrub path", trace.pending, trace_kind_label(&trace.by_kind) ), @@ -1184,7 +1184,7 @@ impl UI { Attribute::Bold, )?; row += 1; - line(stdout, &mut row, "ops/sec", pal::DIM)?; + line(stdout, &mut row, "work rate", pal::DIM)?; // Identity block. The clock is always on screen. put_attr(stdout, sx, row, "MISALIGNED", pal::AMBER, Attribute::Bold)?; row += 1; diff --git a/wiki/interface/clinical-frame.md b/wiki/interface/clinical-frame.md index 87b20ac6..a17c548a 100644 --- a/wiki/interface/clinical-frame.md +++ b/wiki/interface/clinical-frame.md @@ -8,7 +8,7 @@ Status note: IMPLEMENTED. Current state: section labels and bone values. Amber is retired from it to cursor/selection/reticle/owned-presence only. The Seen floor is a porcelain field; Seen walls are bone/ivory with a near-black cutaway seam. - - **The crown metric.** Effective ops/sec (`effective_ops_per_tick`) is the + - **The crown metric.** Effective ops/sec (`effective_ops_per_tick`, player-facing **work rate**) is the single dominant bone number atop the Bevy and terminal rails (agent frames report ops/tick under the command clock). - **Progressive disclosure.** Compact by default; Tab expands secondary diff --git a/wiki/interface/digital-read.md b/wiki/interface/digital-read.md index 279c869e..c898810e 100644 --- a/wiki/interface/digital-read.md +++ b/wiki/interface/digital-read.md @@ -79,6 +79,7 @@ Status note: IMPLEMENTED. Adopted 2026-07-15 from the Fable playtest Bevy dialects; terminal and agent rows retain their compact projection. Per-amendment history (D1-D10) is in the dated `wiki/log/` entries from 2026-07-15 onward. + 2026-07-24: intel read sentences say sharpness N, not MAG N. Stage: B1 — The Basement Work order: digital-read Work priority: 27 diff --git a/wiki/log/2026-07-24-plain-copy-trace-mag.md b/wiki/log/2026-07-24-plain-copy-trace-mag.md new file mode 100644 index 00000000..cad5dbf8 --- /dev/null +++ b/wiki/log/2026-07-24-plain-copy-trace-mag.md @@ -0,0 +1,29 @@ +# 2026-07-24 — TRACE, sharpness, work rate, cash + +``` +Type: log +``` + +## Intent + +Continue the plain-English pass on high-frequency chrome: TRACE debt lines, +intel altitude tags, crown metric labels, standing costs, and money/cash +disabled reasons still read like operator notes. + +## Changed + +- TRACE: `TRACE clear · stay covered`, `TRACE live · … · scrub for Nt`, + `TRACE rising · … · notice in Nt`, `TRACE live · … · no scrub path`. +- Intel read sentences: `sharpness N · …` instead of `MAG N · …`. +- Standing/auto costs: `ops each second` instead of `ops/sec standing`. +- Crown/fleet labels: `work rate` / `cash` instead of bare `ops/sec` / `slush` + where player-facing (ops/sec remains the clinical unit under the hood). +- Money gates: `not enough cash`; wager needs cash; redirect into your funds; + flow amounts every N ticks. +- Information policy logs: branch/policy language, not custody-node ids first. + +## Spec +Amends clinical-frame.md crown player label and digital-read status note. + +## Verification +Lib gate after string-pin updates. diff --git a/wiki/log/DEVLOG.md b/wiki/log/DEVLOG.md index f6bba5f0..36f7b749 100644 --- a/wiki/log/DEVLOG.md +++ b/wiki/log/DEVLOG.md @@ -31,6 +31,11 @@ add or amend a session log, then re-run the generator. - Intent: Player-facing status for open Thought work still read like a protocol dump: `TAP ENVIRONMENTAL MONITOR · open 0.3/0.5 · flow not arriving`, `nothing thinking`, `Opened processing sink: 0.40 Thought on host for information #7`, and `thought reservoirs N open`. Playtests kept qu... - Log: [wiki/log/2026-07-24-plain-starving-copy.md](2026-07-24-plain-starving-copy.md) +## 2026-07-24 - TRACE, sharpness, work rate, cash + +- Intent: Continue the plain-English pass on high-frequency chrome: TRACE debt lines, intel altitude tags, crown metric labels, standing costs, and money/cash disabled reasons still read like operator notes. +- Log: [wiki/log/2026-07-24-plain-copy-trace-mag.md](2026-07-24-plain-copy-trace-mag.md) + ## 2026-07-24 - A protocol is reach, not a registry - Intent: Cameron could not read the PERSONAS panel: the three archetypes did not explain what they were for. Take the copy violation, fix it toward the binding pages, and file the design gap it exposes rather than inventing a capability to paper over it.