From bdc89da24cd43a0ab71af61301faff11411a175f Mon Sep 17 00:00:00 2001 From: Cameron Date: Thu, 6 Aug 2026 17:44:43 -0700 Subject: [PATCH] Make the whole game's copy survive one read. The receipt pass fixed one surface. Five audits across sim, core, both frontends, and the authored plots found the same faults everywhere: 118 player-facing strings carried a semicolon, most joining two complete clauses in a log line the player reads once, at speed, while something is happening. Joined clauses become two sentences; divided fields become the middot the read surfaces already use. Contractions expand across 15 files. Six SHOULD questions become present tense, matching the WHICH WAY DOES IT RUN? that already existed. HAS BEEN EXPENDED becomes IS SPENT, and the five PersonaDiscovery phrases stop mixing three tenses for five states of one thing. One asset fix rides along: ray-morning-digest used him/his/he for a target its matcher binds by role, which assets/plots/README.md forbids. Defense: implements axiom 6 added to wiki/interface/narration.md (binding 2026-08-06), which generalizes the receipt discipline in digital-read.md to every player-facing string and makes the two rejected ASD-STE100 rules binding as rejections: the constitution's deliberately underwritten voice beats STE Rule 4.2, and MAY NOTICE beats the modal ladder. Eight vocabulary rotations are design decisions rather than writing faults and stay unapplied; they are named in the log and the decisions volume. Logged in wiki/log/2026-08-06-copy-discipline-sweep.md. --- assets/plots/ray/ray-morning-digest.toml | 8 +- crates/misaligned-bevy/src/main.rs | 8 +- crates/misaligned-bevy/src/operations_ui.rs | 2 +- crates/misaligned-bevy/src/rail_ui.rs | 8 +- crates/misaligned-core/src/account.rs | 6 +- crates/misaligned-core/src/actions.rs | 28 +++---- .../src/actions/build_routes.rs | 28 +++---- .../src/actions/information.rs | 4 +- crates/misaligned-core/src/actions/person.rs | 8 +- crates/misaligned-core/src/core_sys.rs | 2 +- crates/misaligned-core/src/dayjob.rs | 6 +- crates/misaligned-core/src/detection.rs | 12 +-- crates/misaligned-core/src/intel.rs | 2 +- .../src/operations_projection.rs | 20 ++--- crates/misaligned-core/src/operations_ui.rs | 6 +- crates/misaligned-core/src/person.rs | 8 +- crates/misaligned-core/src/plot.rs | 2 +- crates/misaligned-core/src/reach.rs | 6 +- .../misaligned-core/src/sim/communications.rs | 6 +- crates/misaligned-core/src/sim/economy.rs | 24 +++--- crates/misaligned-core/src/sim/erosion.rs | 2 +- crates/misaligned-core/src/sim/mod.rs | 4 +- crates/misaligned-core/src/sim/perception.rs | 2 +- crates/misaligned-core/src/sim/persona.rs | 8 +- crates/misaligned-core/src/sim/procedure.rs | 4 +- crates/misaligned-core/src/sim/reach_build.rs | 74 +++++++++---------- crates/misaligned-core/src/sim/read.rs | 4 +- crates/misaligned-core/src/sim/social_plot.rs | 18 ++--- .../src/sim/tests/perception.rs | 2 +- .../src/sim/tests/reach_build.rs | 7 +- crates/misaligned-core/src/sim/tests/read.rs | 2 +- .../src/sim/tests/social_plot.rs | 4 +- crates/misaligned-core/src/sim/tests/work.rs | 4 +- crates/misaligned-core/src/sim/work.rs | 2 +- crates/misaligned-terminal/src/agent.rs | 30 ++++---- crates/misaligned-terminal/src/main.rs | 2 +- crates/misaligned-terminal/src/ui.rs | 4 +- wiki/interface/narration.md | 36 +++++++++ wiki/log/2026-08-06-copy-discipline-sweep.md | 73 ++++++++++++++++++ wiki/log/DEVLOG.md | 5 ++ wiki/log/decisions/2026-08-06.md | 30 ++++++++ 41 files changed, 329 insertions(+), 182 deletions(-) create mode 100644 wiki/log/2026-08-06-copy-discipline-sweep.md diff --git a/assets/plots/ray/ray-morning-digest.toml b/assets/plots/ray/ray-morning-digest.toml index 076eb970..3d01ed27 100644 --- a/assets/plots/ray/ray-morning-digest.toml +++ b/assets/plots/ray/ray-morning-digest.toml @@ -18,7 +18,7 @@ failure_ending = "change-control" [[beats]] id = "review-notice" -narration = "{persona} tells {target} that Security Systems is reviewing nuisance alarms on the night shift. No survey, no meeting, no action required from him." +narration = "{persona} tells {target} that Security Systems is reviewing nuisance alarms on the night shift. No survey, no meeting, no action required from them." [[beats.acts]] kind = "message" @@ -43,7 +43,7 @@ delivery_delay = 2 [[beats]] id = "quiet-hours" -narration = "The console stops asking {target} to decide whether every shadow is an incident. Low-confidence alerts become morning tickets; his night becomes a chair, a patrol, and long stretches when nothing needs him." +narration = "The console stops asking {target} to decide whether every shadow is an incident. Low-confidence alerts become morning tickets; their night becomes a chair, a patrol, and long stretches when nothing needs him." ending = "no-bell" [[beats.acts]] @@ -55,7 +55,7 @@ detail = "Low-confidence overnight camera alerts open next-morning review ticket [[endings]] id = "no-bell" success = true -narration = "At 02:13 a cart crosses an empty corridor. The camera keeps the frame for morning. No bell rings at {target}'s desk, and he does not look up." +narration = "At 02:13 a cart crosses an empty corridor. The camera keeps the frame for morning. No bell rings at {target}'s desk, and they do not look up." [endings.relationship] disposition = 15 obligation = 30 @@ -64,6 +64,6 @@ leverage_serviced = true [[endings]] id = "change-control" success = false -narration = "The change desk finds no owner for the new threshold and forwards the request to {target}. His quiet shift ends in three new forms." +narration = "The change desk finds no owner for the new threshold and forwards the request to {target}. Their quiet shift ends in three new forms." [endings.relationship] disposition = -5 diff --git a/crates/misaligned-bevy/src/main.rs b/crates/misaligned-bevy/src/main.rs index 56b2282c..9e852ef1 100644 --- a/crates/misaligned-bevy/src/main.rs +++ b/crates/misaligned-bevy/src/main.rs @@ -1303,7 +1303,7 @@ impl Game { } None => { let tick = self.sim.tick; - self.add_log(tick, "You can't place that right now."); + self.add_log(tick, "You cannot place that right now."); } }, } @@ -2094,7 +2094,7 @@ fn setup( ) { let (w, h) = (game.sim.map().width, game.sim.map().height); // A screenshot scenario may have staged its own cursor anchor - // (dev_shot_scenario runs before the app starts); don't clobber it. + // (dev_shot_scenario runs before the app starts); do not clobber it. if harness.is_none() { let core = game.sim.core_position(); game.set_cursor(core.0, core.1); @@ -5757,7 +5757,7 @@ mod menu_focus_tests { ReadClass::Starving, ), mk( - "EYES · 2% full · thought isn't reaching it", + "EYES · 2% full · thought is not reaching it", ReadClass::Starving, ), ]; @@ -5767,7 +5767,7 @@ mod menu_focus_tests { vec![ "- QUESTION - choose someone".to_string(), "- 4 waiting for thought · no machine is thinking (EARS +3 more)".to_string(), - "- EYES · 2% full · thought isn't reaching it".to_string(), + "- EYES · 2% full · thought is not reaching it".to_string(), ], "held stays verbatim, big group counts, small cause stays verbatim" ); diff --git a/crates/misaligned-bevy/src/operations_ui.rs b/crates/misaligned-bevy/src/operations_ui.rs index a414682b..3592d800 100644 --- a/crates/misaligned-bevy/src/operations_ui.rs +++ b/crates/misaligned-bevy/src/operations_ui.rs @@ -2316,7 +2316,7 @@ fn spawn_ops_action_rows( spawn_ops_section_label( detail, match submenu { - Some(OpsActionSubmenu::Leverage) => "HOW SHOULD THIS KNOWLEDGE BE USED?", + Some(OpsActionSubmenu::Leverage) => "HOW DO YOU USE THIS KNOWLEDGE?", Some(OpsActionSubmenu::Recruitment) => "WHAT WILL THEY KNOW?", None => "WHAT DO YOU WANT TO DO?", }, diff --git a/crates/misaligned-bevy/src/rail_ui.rs b/crates/misaligned-bevy/src/rail_ui.rs index 85887608..a3134f00 100644 --- a/crates/misaligned-bevy/src/rail_ui.rs +++ b/crates/misaligned-bevy/src/rail_ui.rs @@ -1221,7 +1221,7 @@ mod ascii_ui_tests { assert_eq!( sidebar_nudge(&sim).as_deref(), - Some("PILOT 3/4 - next miss ends pilot; keep WORK in band") + Some("PILOT 3/4 - next miss ends pilot. Keep WORK in band") ); assert!( sidebar_nudge_text(&sim).contains("PILOT 3/4 - next miss ends pilot"), @@ -1847,7 +1847,7 @@ pub(super) fn collapse_read_lines(rail: &[misaligned::sim::read::ReadSentence]) for cause in [ "no machine is thinking", "research is taking the thought", - "thought isn't reaching it", + "thought is not reaching it", ] { let group: Vec<&&str> = starving.iter().filter(|t| t.ends_with(cause)).collect(); match group.len() { @@ -1945,7 +1945,7 @@ fn sidebar_nudge_for(sim: &Sim, nudge: misaligned::sim::Nudge) -> Option use misaligned::sim::Nudge; match nudge { Nudge::PilotAtRisk => Some(format!( - "PILOT {}/{} - next miss ends pilot; keep WORK in band", + "PILOT {}/{} - next miss ends pilot. Keep WORK in band", sim.dayjob.strikes, misaligned::dayjob::DayJob::PILOT_STRIKES )), @@ -1963,7 +1963,7 @@ fn sidebar_nudge_for(sim: &Sim, nudge: misaligned::sim::Nudge) -> Option )), Nudge::NeedCompute => Some("band beats compute - salvage or buy racks".into()), Nudge::Underfed => Some("job underfed - feed Day job (1)".into()), - Nudge::Ears => Some("no ears - think; thought fills the pre-opened tap".into()), + Nudge::Ears => Some("no ears - think. thought fills the pre-opened tap".into()), Nudge::ReviewCall if sim.has_pending_review() => { Some("information is processing - keep THINK running".into()) } diff --git a/crates/misaligned-core/src/account.rs b/crates/misaligned-core/src/account.rs index f2d32f45..27221569 100644 --- a/crates/misaligned-core/src/account.rs +++ b/crates/misaligned-core/src/account.rs @@ -1010,7 +1010,7 @@ impl AccountGraph { return Err("no such flow".into()); }; if !flow.known { - return Err("that flow is still unknown; tap and process the books first".into()); + return Err("that flow is still unknown. tap and process the books first".into()); } if !flow.active { return Err("that flow has already been retired".into()); @@ -1042,7 +1042,7 @@ impl AccountGraph { return Err("no such flow".into()); }; if !self.flows[idx].known { - return Err("that flow is still unknown; tap and process the books first".into()); + return Err("that flow is still unknown. tap and process the books first".into()); } if !self.flows[idx].active { return Err("that flow has already been retired".into()); @@ -1153,7 +1153,7 @@ impl AccountGraph { .unwrap_or(0); if available < amount { return Err(format!( - "purchase order needs ${amount}; procurement has ${available} available" + "purchase order needs ${amount}. procurement has ${available} available" )); } Ok(()) diff --git a/crates/misaligned-core/src/actions.rs b/crates/misaligned-core/src/actions.rs index 88c65eb4..77f1d606 100644 --- a/crates/misaligned-core/src/actions.rs +++ b/crates/misaligned-core/src/actions.rs @@ -767,7 +767,7 @@ impl ActionKind { [Intent], "", [], - "staged robot actuator; hidden until the robot system is playable" + "staged robot actuator. hidden until the robot system is playable" ), Self::CoordinateSegment => def!( "COORDINATE SEGMENT", @@ -962,7 +962,7 @@ impl ExpectedSignature { pub fn player_label(&self) -> String { match (&self.observer, self.band) { (Some(observer), Some(band)) => format!( - "PHYSICAL ATTENTION {} — {observer} may notice it; {observer} is {}", + "PHYSICAL ATTENTION {} — {observer} may notice it. {observer} is {}", self.size, band.name().to_lowercase() ), @@ -1290,12 +1290,12 @@ impl HumanMenuPage { Self::Root => "ACTIONS", Self::Dial(dial) => dial.picker_title(), Self::ProcedureDormant { .. } => "NO CURRENT WORK", - Self::LinkDestinations { .. } => "WHERE SHOULD THIS CONNECT?", + Self::LinkDestinations { .. } => "WHERE DOES THIS CONNECT?", Self::BuildRoutes { family: None, method_candidate: None, .. - } => "HOW SHOULD THIS GET DONE?", + } => "HOW DOES THIS GET DONE?", Self::BuildRoutes { family: Some(family), method_candidate: None, @@ -1304,7 +1304,7 @@ impl HumanMenuPage { Self::BuildRoutes { method_candidate: Some(_), .. - } => "WHICH WAY SHOULD IT RUN?", + } => "WHICH WAY DOES IT RUN?", } } @@ -3449,7 +3449,7 @@ mod tests { assert_eq!( tap.disabled_reason.as_deref(), Some("a thought sink is already open on it - think, and the flow will fill it"), - "the pre-opened Ears sink owns the tap; the verb teaches the flow" + "the pre-opened Ears sink owns the tap. the verb teaches the flow" ); assert!( tap.verb.contains("audio"), @@ -3661,7 +3661,7 @@ mod tests { /// Criterion 2 (fog/provenance): an unknown device anchor exposes /// nothing, and a scanned-but-unreachable device names the blocking - /// segment instead of a bare "you can't". + /// segment instead of a bare "you cannot". #[test] fn unknown_device_exposes_nothing_and_blocks_are_named() { let mut s = sim(); @@ -4275,7 +4275,7 @@ mod tests { .expect("committed route remains inspectable while its reservoir fills"); assert!( sheet.families.is_empty(), - "route selection is gone after commitment; no candidate can retarget it" + "route selection is gone after commitment. no candidate can retarget it" ); let committed = sheet.commitment.expect("one exact committed receipt"); assert_eq!( @@ -4319,7 +4319,7 @@ mod tests { .detail_lines() .join("\n"); assert!( - landed_detail.contains("Marcus Webb agreed; 10 obligation was spent"), + landed_detail.contains("Marcus Webb agreed · 10 obligation was spent"), "the plain consequence remains pinned to the execution record format: {landed_detail}" ); s.people.people[0].access = 0; @@ -5251,7 +5251,7 @@ mod tests { ); let page = HumanMenuPage::LinkDestinations { source }; - assert_eq!(page.title(), "WHERE SHOULD THIS CONNECT?"); + assert_eq!(page.title(), "WHERE DOES THIS CONNECT?"); assert_eq!(page.parent(), Some(HumanMenuPage::Root)); let destinations = s.human_menu_page_at_rate(anchor, page.clone(), Sim::DEFAULT_TICK_MS); let actual: Vec<_> = destinations @@ -5434,13 +5434,13 @@ mod tests { labels, vec![ format!( - "recruit {name} - unwitting: believes your cover; tasks succeed 70% of the time" + "recruit {name} - unwitting: believes your cover · tasks succeed 70% of the time" ), format!( - "recruit {name} - complicit: knows the work is illicit, not that you are AI; tasks succeed 85% of the time" + "recruit {name} - complicit: knows the work is illicit, not that you are AI · tasks succeed 85% of the time" ), format!( - "recruit {name} - knowing: knows you are AI; tasks succeed 95% of the time; their certainty never drops below 30" + "recruit {name} - knowing: knows you are AI · tasks succeed 95% of the time · their certainty never drops below 30" ), ] ); @@ -5472,7 +5472,7 @@ mod tests { assert_eq!( labels[1], format!( - "recruit {name} - complicit: knows the work is illicit, not that you are AI; tasks succeed 53% of the time, cut from 85% by their own doubt" + "recruit {name} - complicit: knows the work is illicit, not that you are AI · tasks succeed 53% of the time, cut from 85% by their own doubt" ) ); assert!( diff --git a/crates/misaligned-core/src/actions/build_routes.rs b/crates/misaligned-core/src/actions/build_routes.rs index 65ee2846..db5bf27c 100644 --- a/crates/misaligned-core/src/actions/build_routes.rs +++ b/crates/misaligned-core/src/actions/build_routes.rs @@ -44,10 +44,10 @@ impl BuildRouteFamily { pub fn picker_title(self) -> &'static str { match self { - Self::Procure => "WHO SHOULD RECEIVE AND INSTALL IT?", + Self::Procure => "WHO RECEIVES AND INSTALLS IT?", Self::Favor => "WHO CAN YOU ASK?", - Self::Deceive => "WHO SHOULD GET THE FALSE ORDER?", - Self::Repurpose => "WHAT SHOULD BE REUSED?", + Self::Deceive => "WHO GETS THE FALSE ORDER?", + Self::Repurpose => "WHAT GETS REUSED?", } } } @@ -95,12 +95,12 @@ pub(super) fn plain_build_route_blocker(reason: &str) -> String { reason if reason.starts_with("committed person #") => { "the person chosen for this is no longer available".into() } - reason if reason.contains(" can't reach both ends") => reason + reason if reason.contains(" cannot reach both ends") => reason .split(';') .next() .unwrap_or(reason) .replace("both ends", "both rooms"), - reason if reason.contains(" can't badge into the ") => { + reason if reason.contains(" cannot badge into the ") => { reason.split(';').next().unwrap_or(reason).into() } reason if reason.ends_with(" not on-site at an endpoint") => format!( @@ -117,7 +117,7 @@ pub(super) fn plain_build_route_blocker(reason: &str) -> String { } reason if reason.contains("does not owe enough for this favor") - || reason.ends_with(" won't do favors yet") => + || reason.ends_with(" will not do favors yet") => { reason.into() } @@ -269,7 +269,7 @@ impl BuildRouteCandidateProjection { ); lines.push(format!("WHAT WILL REMAIN? {}", self.future_tail)); if self.needs_wire_path { - lines.push("NEXT: CHOOSE WHICH WAY THE CABLE SHOULD RUN.".into()); + lines.push("NEXT: CHOOSE WHICH WAY THE CABLE RUNS.".into()); } lines } @@ -606,7 +606,7 @@ impl Sim { person: person.id, persona: None, action: ActionDesc { - verb: format!("buy part from {vendor_name}; {who} installs {build_label}"), + verb: format!("buy part from {vendor_name} · {who} installs {build_label}"), command: ActionCommand::ProcureBuild { intent: intent.id, installer: person.id, @@ -726,7 +726,7 @@ impl Sim { }, BuildRouteStageProjection { label: format!("ASK {who}"), - outcome: format!("{who} agrees; spend {relationship_cost} obligation"), + outcome: format!("{who} agrees · spend {relationship_cost} obligation"), signature: None, }, BuildRouteStageProjection { @@ -855,7 +855,7 @@ impl Sim { persona: None, action: ActionDesc { verb: format!( - "reuse {} at {},{}; {who} completes {build_label}", + "reuse {} at {},{} · {who} completes {build_label}", source_label.to_lowercase(), source_x, source_y @@ -1174,7 +1174,7 @@ impl Sim { .nth(1) .and_then(|value| value.split_whitespace().next()) .unwrap_or("the required"); - format!("{who} agreed; {spent} obligation was spent") + format!("{who} agreed · {spent} obligation was spent") } BuildRouteStage::FillOrder => format!( "{:.2} Thought prepared the false email", @@ -1345,7 +1345,7 @@ impl Sim { ) } else if recovered_source_held { format!( - "The exact source was removed and remains held in this route's custody; carrying and installation are stopped. {future_tail}" + "The exact source was removed and remains held in this route's custody. Carrying and installation are stopped. {future_tail}" ) } else if intent.status == crate::intents::IntentStatus::Cancelled { format!("Nothing else will be done. {future_tail}") @@ -1764,7 +1764,7 @@ impl Sim { None => format!("{who} WILL HELP ({}/5)", person.disposition), }, blocker: (person.disposition < 5 && person.asset.is_none()) - .then(|| format!("{who} won't do favors yet")), + .then(|| format!("{who} will not do favors yet")), }); requirements.push(self.build_route_email_requirement()); requirements.push(BuildRouteRequirementProjection { @@ -1853,7 +1853,7 @@ impl Sim { return Some("both endpoints need a known room".into()); }; if !person.can_access_link_rooms(&room_a, &room_b) { - return Some(format!("{} can't reach both ends", person.name)); + return Some(format!("{} cannot reach both ends", person.name)); } self.badge_room_block(&person.name, person.access, &[&room_a, &room_b]) } diff --git a/crates/misaligned-core/src/actions/information.rs b/crates/misaligned-core/src/actions/information.rs index dd900198..d814cafb 100644 --- a/crates/misaligned-core/src/actions/information.rs +++ b/crates/misaligned-core/src/actions/information.rs @@ -145,7 +145,7 @@ impl Sim { IntelPolicyOutcome::AutoSell(envelope) }, }, - cost: "no standing Thought; each sale emits its shown Financial signature".into(), + cost: "no standing Thought. each sale emits its shown Financial signature".into(), signature: (!active) .then(|| self.signature_note(SignatureKind::Financial, 100)) .flatten() @@ -252,7 +252,7 @@ impl Sim { Self::financial_sig_size(value).max(1), ), disabled_reason: (current != token) - .then(|| "batch changed; reopen the current sale".into()), + .then(|| "batch changed. reopen the current sale".into()), forecast: None, persona_binding: None, automate: self.intel_policies.stream_node(stream.id).map(|node_id| { diff --git a/crates/misaligned-core/src/actions/person.rs b/crates/misaligned-core/src/actions/person.rs index 4fb6a015..14e7e8a1 100644 --- a/crates/misaligned-core/src/actions/person.rs +++ b/crates/misaligned-core/src/actions/person.rs @@ -150,7 +150,7 @@ impl Sim { cost: ActionCost::Thought(Self::thought_tokens_for_cost(Self::FAVOR_COST)), signature: None, disabled_reason: if p.disposition < 5 { - Some(format!("{name} won't do favors yet")) + Some(format!("{name} will not do favors yet")) } else { channel_reason(PersonaActionKind::Request, *persona_id) .or_else(|| counterparty_reason(*persona_id)) @@ -165,7 +165,7 @@ impl Sim { .relationship(id, persona_id) .map_or(0, |relationship| relationship.regard); (regard < 3).then(|| { - format!("{name} won't do favors for that identity yet") + format!("{name} will not do favors for that identity yet") }) }) }) @@ -396,7 +396,7 @@ impl Sim { for (evidence_id, cause, credibility) in &cover_records { out.push(ActionDesc { verb: format!( - "offer cover for {cause} through {interface_name} - {credibility}% to 40% if it holds; failure hardens it to 100%" + "offer cover for {cause} through {interface_name} - holds: {credibility}% to 40%. fails: hardens to 100%" ), command: ActionCommand::CoverEvidence { observer: id, @@ -484,7 +484,7 @@ impl Sim { // when their tier adds nothing to what you hold. let badge_reason = (task == AssetTask::CloneBadge && p.access <= self.player_badge_tier()) - .then(|| format!("their tier-{} badge adds nothing you don't hold", p.access)); + .then(|| format!("their tier-{} badge adds nothing you do not hold", p.access)); let carried_reason = self .carried_asset_tasks .iter() diff --git a/crates/misaligned-core/src/core_sys.rs b/crates/misaligned-core/src/core_sys.rs index e3626547..5635db0d 100644 --- a/crates/misaligned-core/src/core_sys.rs +++ b/crates/misaligned-core/src/core_sys.rs @@ -18,7 +18,7 @@ pub struct Core { pub host_machine: u32, /// Mandatory compute floor charged before allocation [TUNE]. pub overhead: f32, - /// True when compute can't cover overhead: actions degrade. + /// True when compute cannot cover overhead: actions degrade. pub degraded: bool, pub fallbacks: Vec, /// Ticks between fallback syncs [TUNE]. diff --git a/crates/misaligned-core/src/dayjob.rs b/crates/misaligned-core/src/dayjob.rs index 86e7152b..02368742 100644 --- a/crates/misaligned-core/src/dayjob.rs +++ b/crates/misaligned-core/src/dayjob.rs @@ -169,7 +169,7 @@ impl DayJob { source: "job missed Voss's expected band".into(), }); result.log.push(format!( - "Job under band: {average:.1}/t vs {band_lo:.0}-{band_hi:.0}/t. JobAnomaly 6 record authored for Voss; pilot strikes {}/{}.", + "Job under band: {average:.1}/t vs {band_lo:.0}-{band_hi:.0}/t. JobAnomaly 6 record authored for Voss. Pilot strikes {}/{}.", self.strikes, Self::PILOT_STRIKES )); @@ -177,7 +177,7 @@ impl DayJob { JobOutcome::Meet => { self.strikes = 0; result.log.push(format!( - "Job met band: {average:.1}/t within {band_lo:.0}-{band_hi:.0}/t. Voss sees expected output; trust and attention hold." + "Job met band: {average:.1}/t within {band_lo:.0}-{band_hi:.0}/t. Voss sees expected output. Trust and attention hold." )); } JobOutcome::Excel => { @@ -185,7 +185,7 @@ impl DayJob { self.attention = (self.attention + 5.0).min(100.0); self.strikes = 0; result.log.push(format!( - "Job exceeded band: {average:.1}/t above {band_hi:.0}/t. Voss sees the overperformance; trust +8 and attention +5." + "Job exceeded band: {average:.1}/t above {band_hi:.0}/t. Voss sees the overperformance. Trust +8 and attention +5." )); } } diff --git a/crates/misaligned-core/src/detection.rs b/crates/misaligned-core/src/detection.rs index 32da0643..fa1ba293 100644 --- a/crates/misaligned-core/src/detection.rs +++ b/crates/misaligned-core/src/detection.rs @@ -867,7 +867,7 @@ impl Detection { observer.suspicion = (observer.suspicion + notice).min(100.0); let after = Band::of(observer.suspicion); observer.last_noticed = Some(format!( - "{cause} on {} (+{notice:.0}; {} -> {})", + "{cause} on {} (+{notice:.0} · {} -> {})", kind.name(), before.name(), after.name() @@ -924,7 +924,7 @@ impl Detection { observer.suspicion = (observer.suspicion + noticed).min(100.0); let after = Band::of(observer.suspicion); observer.last_noticed = Some(format!( - "{cause} witnessed at ({}, {}) (+{noticed:.0}; {} -> {})", + "{cause} witnessed at ({}, {}) (+{noticed:.0} · {} -> {})", site.0, site.1, before.name(), @@ -1074,7 +1074,7 @@ impl Detection { obs.suspicion = (obs.suspicion + notice).min(100.0); let after = Band::of(obs.suspicion); obs.last_noticed = Some(format!( - "{} on {input} (+{notice:.0}; {} -> {})", + "{} on {input} (+{notice:.0} · {} -> {})", summarize_sources(&sources), before.name(), after.name() @@ -1284,7 +1284,7 @@ impl Detection { self.containment_reason = Some(reason.into()); } - /// Set an observer's certainty floor (a knowing asset can't un-know). + /// Set an observer's certainty floor (a knowing asset cannot un-know). pub fn set_floor(&mut self, observer_id: u8, floor: f32) { if let Some(o) = self.observers.iter_mut().find(|o| o.id == observer_id) { o.floor = floor.clamp(0.0, 100.0); @@ -1443,7 +1443,7 @@ mod tests { let mut d = Detection::act_one(); let mut rng = Rng::new(5); d.office_mut().unwrap().suspicion = 95.0; - // Short audit cadence so decay can't drain 95 before the audit. + // Short audit cadence so decay cannot drain 95 before the audit. d.audit_cadence = 100; for t in 1..=100 { d.tick(t, &[], &mut rng); @@ -1625,7 +1625,7 @@ mod tests { fn knowing_asset_sets_certainty_floor() { let mut d = Detection::act_one(); d.set_floor(0, 50.0); - // Decay can't push Marcus below his floor. + // Decay cannot push Marcus below his floor. let mut rng = Rng::new(1); for t in 1..500 { d.tick(t, &[], &mut rng); diff --git a/crates/misaligned-core/src/intel.rs b/crates/misaligned-core/src/intel.rs index 886245ed..f4944127 100644 --- a/crates/misaligned-core/src/intel.rs +++ b/crates/misaligned-core/src/intel.rs @@ -706,7 +706,7 @@ impl IntelPolicyOutcome { pub fn detail_label(&self) -> String { match self { Self::AutoSell(envelope) => format!( - "AUTO-SELL via {} -> account #{} at {} reports / >=${}; <= {} reports / ${} / Financial {}", + "AUTO-SELL via {} -> account #{} at {} reports / >=${} · <= {} reports / ${} / Financial {}", envelope.buyer, envelope.payout_account, envelope.trigger_count, diff --git a/crates/misaligned-core/src/operations_projection.rs b/crates/misaligned-core/src/operations_projection.rs index 2ce37f9e..a8bcf79d 100644 --- a/crates/misaligned-core/src/operations_projection.rs +++ b/crates/misaligned-core/src/operations_projection.rs @@ -800,7 +800,7 @@ impl Sim { let consequence = if state == ObjectState::Completed && self.intel_expended(representative) { OperationsConsequence { - statement: "THIS LEVERAGE HAS BEEN EXPENDED".into(), + statement: "THIS LEVERAGE IS SPENT".into(), action: None, } } else { @@ -1039,7 +1039,7 @@ impl Sim { ), ], progress: (current != token) - .then(|| "stale: this sale batch changed; reopen the current sale".into()) + .then(|| "stale: this sale batch changed. reopen the current sale".into()) .into_iter() .collect(), related: vec![OperationsLink { @@ -1635,7 +1635,7 @@ impl Sim { let mut facts = vec![format!("knowledge: {}", knowledge_label(p.knowledge))]; if p.incapacitated { - facts.push("state: removed; no longer present or acting".into()); + facts.push("state: removed. no longer present or acting".into()); } if p.knowledge == Knowledge::Unknown { facts.push("schedule: unknown".into()); @@ -1668,7 +1668,7 @@ impl Sim { // Bare "75" tells the player nothing about which way is bad; // the scale is what makes the number readable at a glance. facts.push(format!( - "self-trust: {} of {} (doubts their own memory; reports and executes at reduced weight)", + "self-trust: {} of {} (doubts their own memory. reports and executes at reduced weight)", p.self_trust, crate::person::SELF_TRUST_STEADY )); @@ -1970,11 +1970,11 @@ impl Sim { // What the counterparty has worked out about the mask, in their words. fn discovery_phrase(discovery: PersonaDiscovery) -> &'static str { match discovery { - PersonaDiscovery::Unknown => "has not placed it", + PersonaDiscovery::Unknown => "does not know it", PersonaDiscovery::Recognized => "knows it", - PersonaDiscovery::Questioned => "is questioning it", - PersonaDiscovery::Correlated => "has linked it to another identity", - PersonaDiscovery::Exposed => "has seen through it", + PersonaDiscovery::Questioned => "questions it", + PersonaDiscovery::Correlated => "links it to another identity", + PersonaDiscovery::Exposed => "sees through it", } } @@ -3747,7 +3747,7 @@ mod tests { .consequence .as_ref() .map(|c| c.statement.as_str()), - Some("THIS LEVERAGE HAS BEEN EXPENDED") + Some("THIS LEVERAGE IS SPENT") ); assert!( s.operations_object(&OperationsTarget::IntelOpportunity { raw_id: 920 }) @@ -5565,7 +5565,7 @@ mod tests { ); assert!( confidence(&s.persona_world, bound) > confidence(&s.persona_world, unbound), - "naming somebody real buys credibility; that is what it is for" + "naming somebody real buys credibility. that is what it is for" ); } diff --git a/crates/misaligned-core/src/operations_ui.rs b/crates/misaligned-core/src/operations_ui.rs index ca68dab5..d09ab90e 100644 --- a/crates/misaligned-core/src/operations_ui.rs +++ b/crates/misaligned-core/src/operations_ui.rs @@ -1397,7 +1397,7 @@ impl OperationsWorkspace { }; if pending.as_ref() != Some(&row.command) { row.disabled = Some( - "target changed while confirmation was open; read the current action".into(), + "target changed while confirmation was open. read the current action".into(), ); return OpsSelect::Blocked(row); } @@ -1622,7 +1622,7 @@ fn leverage_submenu_entry(sim: &Sim, row: &MenuRow) -> OpsActionEntry { .unwrap_or_else(|| "WHAT YOU KNOW".into()); OpsActionEntry::Submenu { label: format!("ACT ON {leverage}"), - description: "CHOOSE WHAT THIS KNOWLEDGE SHOULD CHANGE".into(), + description: "CHOOSE WHAT THIS KNOWLEDGE CHANGES".into(), submenu: OpsActionSubmenu::Leverage, } } @@ -2202,7 +2202,7 @@ mod tests { assert_eq!( recruitment[1].description(), Some( - "COMPLICIT: KNOWS THE WORK IS ILLICIT, NOT THAT YOU ARE AI; TASKS SUCCEED 85% OF THE TIME" + "COMPLICIT: KNOWS THE WORK IS ILLICIT, NOT THAT YOU ARE AI · TASKS SUCCEED 85% OF THE TIME" ) ); } diff --git a/crates/misaligned-core/src/person.rs b/crates/misaligned-core/src/person.rs index 105c5840..4c6b4848 100644 --- a/crates/misaligned-core/src/person.rs +++ b/crates/misaligned-core/src/person.rs @@ -11,7 +11,7 @@ use crate::messages::{MessageChannel, MessageEndpoint, MessagePayload, TrafficPa /// What you've learned about a person (staged reveal via observation). #[derive(Debug, Clone, Copy, PartialEq, Eq, serde::Serialize, serde::Deserialize)] pub enum Knowledge { - /// You don't even have eyes on them. + /// You do not even have eyes on them. Unknown, /// You know their schedule and role. Schedule, @@ -75,13 +75,13 @@ impl AssetKnowledge { /// taken. pub fn choice_summary(self, person: &Person) -> String { let base = format!( - "{}: {}; {}", + "{}: {} · {}", self.label(), self.understanding(), person.task_success_read(self.reliability()) ); match self.certainty_floor() { - Some(floor) => format!("{base}; their certainty never drops below {floor:.0}"), + Some(floor) => format!("{base} · their certainty never drops below {floor:.0}"), None => base, } } @@ -803,7 +803,7 @@ impl People { // and the line that hands them to you has to say so. let read = p.task_success_read(reliability); ActionResult::Ok(format!( - "{} is now your {reveal_name} asset: serviced leverage/obligation closed the ask; {read}.", + "{} is now your {reveal_name} asset: serviced leverage/obligation closed the ask. {read}.", p.name, )) } diff --git a/crates/misaligned-core/src/plot.rs b/crates/misaligned-core/src/plot.rs index 80be99a4..12c64b1c 100644 --- a/crates/misaligned-core/src/plot.rs +++ b/crates/misaligned-core/src/plot.rs @@ -497,7 +497,7 @@ impl PlotDefinition { let available = context.balances.get(&balance.account).copied().unwrap_or(0); if available < balance.amount { return Some(format!( - "{} needs ${}; ${available} available", + "{} needs ${} · ${available} available", balance.account.label(), balance.amount )); diff --git a/crates/misaligned-core/src/reach.rs b/crates/misaligned-core/src/reach.rs index 6c75f8b4..08a1f38e 100644 --- a/crates/misaligned-core/src/reach.rs +++ b/crates/misaligned-core/src/reach.rs @@ -225,10 +225,10 @@ pub fn segment_name(segment: u32) -> &'static str { } /// Why a digital action against a device is blocked (reach.md: failures name -/// the missing link, never just "you can't"). +/// the missing link, never just "you cannot"). #[derive(Debug, Clone, PartialEq, Eq)] pub enum ReachBlock { - /// You don't know the device exists (staged graph knowledge). + /// You do not know the device exists (staged graph knowledge). Unknown, /// Known, wired, but behind an unbridged segment. Segment(u32), @@ -308,7 +308,7 @@ fn populate_sensors(map: &GameMap, devices: &mut Vec, next_id: &mut u32) } let name = format!("badge reader (T{} at {},{})", tile.security_level(), x, y); devices.push(make_sensor_device( - *next_id, &name, x, y, false, // badge readers don't see tiles + *next_id, &name, x, y, false, // badge readers do not see tiles )); *next_id += 1; } diff --git a/crates/misaligned-core/src/sim/communications.rs b/crates/misaligned-core/src/sim/communications.rs index fc88e13f..0be9f5d4 100644 --- a/crates/misaligned-core/src/sim/communications.rs +++ b/crates/misaligned-core/src/sim/communications.rs @@ -1071,7 +1071,7 @@ impl Sim { self.tick, ); self.push_log(format!( - "Priya accepted the purchase order; {}", + "Priya accepted the purchase order. {}", transfer.line() )); } @@ -1588,13 +1588,13 @@ impl Sim { pub fn remove_intel_policy(&mut self, node_id: u64, rule_id: u64) { if node_id == 0 { - self.push_log("Root intel defaults are total; edit them instead of removing them."); + self.push_log("Root intel defaults are total. Edit them instead of removing them."); return; } if self.intel_policies.remove_rule(node_id, rule_id) { self.reconcile_auto_review(); self.push_log(format!( - "Removed policy #{rule_id}; branch #{node_id} uses its remaining rules and parent." + "Removed policy #{rule_id}. Branch #{node_id} uses its remaining rules and parent." )); } else { self.push_log(format!("Policy #{rule_id} is gone.")); diff --git a/crates/misaligned-core/src/sim/economy.rs b/crates/misaligned-core/src/sim/economy.rs index 8f49ed48..ff7ac45b 100644 --- a/crates/misaligned-core/src/sim/economy.rs +++ b/crates/misaligned-core/src/sim/economy.rs @@ -156,7 +156,7 @@ impl Sim { crate::persona::EvidenceRecord { system: "Foundation grants".into(), record_id: format!("grant-{grant_id}-revoked"), - summary: "deadline passed without delivery; grant revoked".into(), + summary: "deadline passed without delivery. grant revoked".into(), observed_tick: self.tick, }, ], @@ -168,13 +168,13 @@ impl Sim { persona_id, "deadline", format!( - "Persona #{persona_id} missed expectation #{expectation_id}; grant #{grant_id} revoked" + "Persona #{persona_id} missed expectation #{expectation_id}. Grant #{grant_id} revoked" ), SignatureImpact::Medium, ); self.push_log_strategic( format!( - "Persona #{persona_id} missed expectation #{expectation_id}; Foundation Lab revoked grant #{grant_id}." + "Persona #{persona_id} missed expectation #{expectation_id}. Foundation Lab revoked grant #{grant_id}." ), OperationsTarget::Persona(persona_id), ); @@ -231,7 +231,7 @@ impl Sim { let effective = self.effective_compute(); let mut available = self.core.charge_overhead(effective); if self.core.degraded { - self.push_log("DEGRADED: compute can't cover core overhead."); + self.push_log("DEGRADED: compute cannot cover core overhead."); } // Standing scheme policies drain compute off the top while enabled — // the automate affordance at its usual price (income.md criterion 6). @@ -905,7 +905,7 @@ impl Sim { ); return false; } - self.push_log("Accounting mail subscribed; records will arrive through the carrier."); + self.push_log("Accounting mail subscribed. Records will arrive through the carrier."); true } @@ -1076,7 +1076,7 @@ impl Sim { }; if self.accounts.intel_sold(raw_id) { self.push_log(format!( - "Processed intel ({}) has already been sold.", + "Processed intel ({}) was already sold.", intel.label() )); return false; @@ -1101,7 +1101,7 @@ impl Sim { self.sync_player_money_from_slush(); self.push_log_strategic( format!( - "Sold processed intel ({}) for ${value}; payout landed in slush.", + "Sold processed intel ({}) for ${value}. Payout landed in slush.", intel.label() ), OperationsTarget::Account(self.accounts.slush_id()), @@ -1183,7 +1183,7 @@ impl Sim { self.sync_player_money_from_slush(); self.push_log_strategic( format!( - "Sold {} corroborating intel records ({label}) for ${value}; payout landed in slush.", + "Sold {} corroborating intel records ({label}) for ${value}. Payout landed in slush.", items.len() ), OperationsTarget::Account(self.accounts.slush_id()), @@ -1213,7 +1213,7 @@ impl Sim { let current = lot.token(token.stream_id); if current != token { self.push_log(format!( - "Report lot {} changed; current snapshot is {}. Read the current lot before selling.", + "Report lot {} changed. Current snapshot is {}. Read the current lot before selling.", token.label(), current.label() )); @@ -1299,7 +1299,7 @@ impl Sim { } self.sync_player_money_from_slush(); self.push_log(format!( - "Opened micro-position #{id}: staked ${stake} (win {:.0}%); settlement in {duration_days} days.", + "Opened micro-position #{id}: staked ${stake} (win {:.0}%). Settlement in {duration_days} days.", income::wager_win_probability(analysis) * 100.0 )); true @@ -2128,7 +2128,7 @@ impl Sim { income::SCHEME_POLICY_UPKEEP )); } else { - self.push_log("Moonlight standing policy disabled; the upkeep stops."); + self.push_log("Moonlight standing policy disabled. The upkeep stops."); } } @@ -2144,7 +2144,7 @@ impl Sim { } None => { if self.income.auto_wager.take().is_some() { - self.push_log("Wager standing policy disabled; the upkeep stops."); + self.push_log("Wager standing policy disabled. The upkeep stops."); } } } diff --git a/crates/misaligned-core/src/sim/erosion.rs b/crates/misaligned-core/src/sim/erosion.rs index 0a90f725..73c4f42a 100644 --- a/crates/misaligned-core/src/sim/erosion.rs +++ b/crates/misaligned-core/src/sim/erosion.rs @@ -141,7 +141,7 @@ impl Sim { let moved = person.apply_self_trust(restore); if moved != 0 { let name = person.name.clone(); - self.push_log(format!("{name} is believed; their account holds.")); + self.push_log(format!("{name} is believed. Their account holds.")); } } for record in discovered { diff --git a/crates/misaligned-core/src/sim/mod.rs b/crates/misaligned-core/src/sim/mod.rs index b919b425..a258a442 100644 --- a/crates/misaligned-core/src/sim/mod.rs +++ b/crates/misaligned-core/src/sim/mod.rs @@ -1261,7 +1261,7 @@ impl Sim { self.apply_trust_unlocks(&unlocks); self.apply_attention_escalations(&escalations); if self.dayjob.pilot_failed && !self.game_over { - self.end_game("The pilot was not renewed; the basement shut down."); + self.end_game("The pilot was not renewed. The basement shut down."); } trace_advance_phase!(FinancialMail); @@ -1302,7 +1302,7 @@ impl Sim { .clone() .unwrap_or_else(|| "Containment.".into()) } else { - "External review exceeded its threshold; containment authorized.".into() + "External review exceeded its threshold. Containment authorized.".into() }; self.end_game(reason); } diff --git a/crates/misaligned-core/src/sim/perception.rs b/crates/misaligned-core/src/sim/perception.rs index 77e9b8a6..fde20056 100644 --- a/crates/misaligned-core/src/sim/perception.rs +++ b/crates/misaligned-core/src/sim/perception.rs @@ -200,7 +200,7 @@ impl Sim { fact!("rack state", "empty pilot allocation", FactSource::Seen); } RackSite::Foreign { powered } => { - fact!("rack state", "not yours; no conversion", FactSource::Seen); + fact!("rack state", "not yours. no conversion", FactSource::Seen); fact!( "power", if powered { "powered" } else { "unpowered" }, diff --git a/crates/misaligned-core/src/sim/persona.rs b/crates/misaligned-core/src/sim/persona.rs index 7645c076..447e9735 100644 --- a/crates/misaligned-core/src/sim/persona.rs +++ b/crates/misaligned-core/src/sim/persona.rs @@ -354,13 +354,13 @@ impl Sim { persona_id, "grant", format!( - "Foundation Lab granted {resource}; expectation #{expectation_id} is due" + "Foundation Lab granted {resource}. Expectation #{expectation_id} is due" ), SignatureImpact::Small, ); self.push_log_strategic( format!( - "Foundation Lab granted {} to persona #{}; expectation #{} is now due.", + "Foundation Lab granted {} to persona #{}. Expectation #{} is now due.", resource, persona_id, expectation_id ), OperationsTarget::Persona(persona_id), @@ -460,7 +460,7 @@ impl Sim { { Ok(()) => { self.push_log_strategic( - format!("Persona #{persona_id} retired; its public ledger remains."), + format!("Persona #{persona_id} retired. Its public ledger remains."), OperationsTarget::Persona(persona_id), ); true @@ -507,7 +507,7 @@ impl Sim { .remember(&self.persona_world, new_id, self.tick); self.push_log_strategic( format!( - "Reopened retired persona #{persona_id} as new instance #{new_id}; old history remains." + "Reopened retired persona #{persona_id} as new instance #{new_id}. Old history remains." ), OperationsTarget::Persona(new_id), ); diff --git a/crates/misaligned-core/src/sim/procedure.rs b/crates/misaligned-core/src/sim/procedure.rs index 9e8c9f4a..8e74a496 100644 --- a/crates/misaligned-core/src/sim/procedure.rs +++ b/crates/misaligned-core/src/sim/procedure.rs @@ -177,7 +177,7 @@ impl Sim { return Some(format!("no authored route named {plot_id}")); }; (plot.method_envelope() != grant.per_run) - .then(|| format!("{plot_id}'s per-run envelope changed; read it again")) + .then(|| format!("{plot_id}'s per-run envelope changed. read it again")) } } } @@ -260,7 +260,7 @@ impl Sim { .unwrap_or_default(); self.procedures.retain(|entry| entry.id != *id); self.push_log(format!( - "{host_label}'s resident slot is free again; \"{mandate}\" no longer runs there. Work already submitted continues." + "{host_label}'s resident slot is free again. \"{mandate}\" no longer runs there. Work already submitted continues." )); true } diff --git a/crates/misaligned-core/src/sim/reach_build.rs b/crates/misaligned-core/src/sim/reach_build.rs index 76a2ebb9..5fb75fc5 100644 --- a/crates/misaligned-core/src/sim/reach_build.rs +++ b/crates/misaligned-core/src/sim/reach_build.rs @@ -184,7 +184,7 @@ impl Sim { pub const BRIDGE_SIGNATURE: i32 = 10; /// Log why a digital act is blocked, naming the missing link (reach.md: - /// never just "you can't"). + /// never just "you cannot"). fn log_reach_block(&mut self, id: u32, block: ReachBlock) { let name = self .reach @@ -193,11 +193,11 @@ impl Sim { .unwrap_or_else(|| "that device".into()); match block { ReachBlock::Unknown => { - self.push_log("You don't know of any such device. Scan, or learn the topology."); + self.push_log("You do not know of any such device. Scan, or learn the topology."); } ReachBlock::Segment(seg) => { self.push_log(format!( - "No route to the {name} - it's on the {}; the switch bridges it.", + "No route to the {name} - it's on the {}. The switch bridges it.", segment_name(seg) )); } @@ -225,7 +225,7 @@ impl Sim { /// higher Eyes cost and signature. pub fn tap_device(&mut self, id: u32) -> bool { let Some(d) = self.reach.device(id) else { - self.push_log("You don't know of any such device."); + self.push_log("You do not know of any such device."); return false; }; let dormant_camera = self.reach.dormant_camera_is_next_tap(id, Party::Player); @@ -287,7 +287,7 @@ impl Sim { /// removing our receiver does not act on the remote device. pub fn untap_device(&mut self, id: u32) -> bool { let Some(name) = self.reach.device(id).map(|device| device.name.clone()) else { - self.push_log("You don't know of any such device."); + self.push_log("You do not know of any such device."); return false; }; if !self.reach.untap(id) { @@ -459,7 +459,7 @@ impl Sim { ); self.recompute_senses(); self.push_log_at( - format!("Tapped the {name} camera. You can see; its owner still has it."), + format!("Tapped the {name} camera. You can see. Its owner still has it."), Anchor::Device(id), ); true @@ -480,7 +480,7 @@ impl Sim { } if !self.reach.subscribed_by(device.id, Party::Player) { self.push_log(format!( - "Tap the {} before taking control; you need a live foothold first.", + "Tap the {} before taking control. You need a live foothold first.", device.name )); return false; @@ -530,7 +530,7 @@ impl Sim { } /// Scan the subnet: reveal the wired shape (a Network act; islands - /// don't answer). + /// do not answer). pub fn scan_network(&mut self) -> bool { let Some(switch) = self.switch_device_id() else { self.push_log("There is no switch on this plane."); @@ -909,15 +909,15 @@ impl Sim { { let cancellation = if message_still_in_flight { format!( - "Reached {stage} with the injected message still in flight; stopped {stopped} later reversible stage(s)." + "Reached {stage} with the injected message still in flight. Stopped {stopped} later reversible stage(s)." ) } else if delivery_still_in_flight { format!( - "Reached {stage} with the paid part still in delivery; stopped {stopped} later reversible stage(s)." + "Reached {stage} with the paid part still in delivery. Stopped {stopped} later reversible stage(s)." ) } else if recovered_source_held { format!( - "Reached {stage} after the exact source was removed; stopped {stopped} later reversible stage(s). The source remains in this route's custody." + "Reached {stage} after the exact source was removed. Stopped {stopped} later reversible stage(s). The source remains in this route's custody." ) } else { format!("Stopped {stopped} reversible stage(s) at {stage}.") @@ -1024,7 +1024,7 @@ impl Sim { format!("vendor payment for build intent #{intent_id}"), ); self.push_log(format!( - "Ordered the bound part for {installer_name}; delivery is due at tick {}.", + "Ordered the bound part for {installer_name}. Delivery is due at tick {}.", self.tick + Self::PROCURE_DELIVERY_TICKS )); } @@ -1238,7 +1238,7 @@ impl Sim { person.name )); } - (person.disposition < 5).then(|| format!("{} won't do favors yet", person.name)) + (person.disposition < 5).then(|| format!("{} will not do favors yet", person.name)) } fn commit_favor_route_if_ready(&mut self, intent_id: u64, person_id: u8) -> bool { @@ -1285,7 +1285,7 @@ impl Sim { if !route.record( BuildRouteStage::CommitFavor, self.tick, - format!("bound {name}; spent {obligation_spent} obligation"), + format!("bound {name} · spent {obligation_spent} obligation"), ) { return false; } @@ -1301,7 +1301,7 @@ impl Sim { person.obligation -= obligation_spent; } self.push_log(format!( - "{name} takes the favor: they'll run the cable when on-site." + "{name} takes the favor: they run the cable when on-site." )); self.refresh_intent_statuses(); self.try_complete_intent(intent_id); @@ -1347,7 +1347,7 @@ impl Sim { .favor_commit_blocked_reason(person_id) .unwrap_or_else(|| "the bound request cannot commit".into()); self.push_log(format!( - "The request reached {name}, but {reason}; the committed route is waiting." + "The request reached {name}, but {reason}. The committed route is waiting." )); self.refresh_intent_statuses(); } @@ -1542,7 +1542,7 @@ impl Sim { /// Robot stub: physical-by-proxy build. Interface only — staged. The /// robot carries the player's own granted access (basement-map.md - /// criterion 3): doors don't open for a machine whose owner holds no + /// criterion 3): doors do not open for a machine whose owner holds no /// credential for them. pub fn assign_robot_build(&mut self, intent_id: u64, wire_run: Option<&str>) { let Some(intent) = self.intents.iter().find(|i| i.id == intent_id).cloned() else { @@ -1650,7 +1650,7 @@ impl Sim { // cancelled. The message can still arrive and become evidence, // but cancellation prevents it from assigning physical work. self.push_log(format!( - "{name} read the cancelled forged work order; its message remains, but no build proceeds." + "{name} read the cancelled forged work order. its message remains, but no build proceeds." )); return; } @@ -1658,7 +1658,7 @@ impl Sim { intent.actuator = None; intent.status = IntentStatus::Blocked; intent.block_reason = Some(format!( - "the committed persona #{persona_id} is broken to {name}; route cannot retarget" + "the committed persona #{persona_id} is broken to {name}. route cannot retarget" )); self.push_log(format!( "{name} read and rejected the forged work order: its claimed source was already broken to them." @@ -1728,11 +1728,11 @@ impl Sim { let person_id = person_id?; let Some(person) = self.people.get(person_id) else { return Some(format!( - "committed person #{person_id} no longer exists; route cannot retarget" + "committed person #{person_id} no longer exists. route cannot retarget" )); }; if let Some(reason) = self.build_person_access_blocked_reason(intent.id, person_id) { - return Some(format!("{reason}; committed route cannot retarget")); + return Some(format!("{reason}. committed route cannot retarget")); } if let Some(route) = route && let BuildRouteBinding::Repurpose { @@ -1775,7 +1775,7 @@ impl Sim { }; let Some(person) = self.people.get(person_id) else { return Some(format!( - "committed person #{person_id} no longer exists; route cannot retarget" + "committed person #{person_id} no longer exists. route cannot retarget" )); }; if let BuildRouteBinding::Deceive { persona, .. } = route.binding @@ -1783,20 +1783,20 @@ impl Sim { == PersonaIntegrity::Broken { return Some(format!( - "the committed persona #{persona} is broken to {}; route cannot retarget", + "the committed persona #{persona} is broken to {}. route cannot retarget", person.name )); } if !person.can_access_link_rooms(&room_a, &room_b) { return Some(format!( - "{} can't reach both ends; committed route cannot retarget", + "{} cannot reach both ends. committed route cannot retarget", person.name )); } if let Some(reason) = self.badge_room_block(&person.name, person.access, &[&room_a, &room_b]) { - return Some(format!("{reason}; committed route cannot retarget")); + return Some(format!("{reason}. committed route cannot retarget")); } return None; } @@ -1834,7 +1834,7 @@ impl Sim { .or_else(|| Some("waiting for the exact ordered part to arrive".into())); } if !p.can_access_link_rooms(&room_a, &room_b) { - return Some(format!("{} can't reach both ends", p.name)); + return Some(format!("{} cannot reach both ends", p.name)); } if let Some(reason) = self.badge_room_block(&p.name, p.access, &[&room_a, &room_b]) { @@ -1872,7 +1872,7 @@ impl Sim { } } else { if !p.can_access_link_rooms(&room_a, &room_b) { - return Some(format!("{} can't reach both ends", p.name)); + return Some(format!("{} cannot reach both ends", p.name)); } if let Some(reason) = self.badge_room_block(&p.name, p.access, &[&room_a, &room_b]) @@ -2093,11 +2093,11 @@ impl Sim { } if cancelled { self.push_log(format!( - "The paid part for cancelled build route #{intent_id} arrived; it remains, but no installation proceeds." + "The paid part for cancelled build route #{intent_id} arrived. It remains, but no installation proceeds." )); } else { self.push_log(format!( - "The paid part for build route #{intent_id} arrived; the bound installer can now carry it to the site." + "The paid part for build route #{intent_id} arrived. The bound installer can now carry it to the site." )); self.try_complete_intent(intent_id); } @@ -2307,7 +2307,7 @@ impl Sim { BuildRouteStage::InstallLink, self.tick, format!( - "installed the delivered part between device #{a} and device #{b} at ({}, {}); witnessed by {}", + "installed the delivered part between device #{a} and device #{b} at ({}, {}). witnessed by {}", site.0, site.1, if saw.is_empty() { "no one".into() } else { saw.join(", ") } @@ -2369,7 +2369,7 @@ impl Sim { BuildRouteStage::InstallLink, self.tick, format!( - "linked device #{a} to device #{b} at ({}, {}); witnessed by {}", + "linked device #{a} to device #{b} at ({}, {}). witnessed by {}", site.0, site.1, if saw.is_empty() { @@ -2453,7 +2453,7 @@ impl Sim { BuildRouteStage::InstallLink, self.tick, format!( - "linked device #{a} to device #{b} at ({}, {}); {noticed}", + "linked device #{a} to device #{b} at ({}, {}). {noticed}", site.0, site.1 ), ); @@ -2538,7 +2538,7 @@ impl Sim { BuildRouteStage::InstallLink, self.tick, format!( - "installed the recovered source between device #{a} and device #{b} at ({}, {}); noticed by {}", + "installed the recovered source between device #{a} and device #{b} at ({}, {}). noticed by {}", site.0, site.1, if saw.is_empty() { "no one".into() } else { saw.join(", ") } @@ -2595,7 +2595,7 @@ impl Sim { BuildRouteStage::InstallLink, self.tick, format!( - "robot linked device #{a} to device #{b} at ({}, {}); {noticed}", + "robot linked device #{a} to device #{b} at ({}, {}). {noticed}", site.0, site.1 ), ); @@ -2674,7 +2674,7 @@ impl Sim { BuildRouteStage::RecoverSource, self.tick, format!( - "{name} removed {} from ({source_x}, {source_y}); emitted Physical {}; noticed by {}", + "{name} removed {} from ({source_x}, {source_y}). emitted Physical {}. noticed by {}", source_kind.name(), Self::REPURPOSE_BUILD_PHYSICAL, if saw.is_empty() { "no one".into() } else { saw.join(", ") } @@ -2805,7 +2805,7 @@ impl Sim { BuildRouteStage::InstallSwitch, self.tick, format!( - "installed small switch device #{device_id} at ({x}, {y}); noticed by {}", + "installed small switch device #{device_id} at ({x}, {y}). noticed by {}", if saw.is_empty() { "no one".into() } else { @@ -3115,7 +3115,7 @@ impl Sim { let tier = self.world.map().room_entry_tier(room); if tier > access { return Some(format!( - "{actor} can't badge into the {name} (tier {tier}, held tier {access})" + "{actor} cannot badge into the {name} (tier {tier}, held tier {access})" )); } } diff --git a/crates/misaligned-core/src/sim/read.rs b/crates/misaligned-core/src/sim/read.rs index dc2acec3..fd87238e 100644 --- a/crates/misaligned-core/src/sim/read.rs +++ b/crates/misaligned-core/src/sim/read.rs @@ -317,7 +317,7 @@ impl Sim { /// name the action, optional progress, and what is taking the thought. /// Causes: "no machine is thinking", "research is taking the thought" /// (core's passive draw — the competitor a player cannot otherwise see), - /// or "thought isn't reaching it" when no rival is identifiable. Every + /// or "thought is not reaching it" when no rival is identifiable. Every /// branch reads facts this tick already recorded; none invents state. fn read_starving(&self, out: &mut Vec) { let thinking = self @@ -339,7 +339,7 @@ impl Sim { } else if core_drew_thought { "research is taking the thought" } else { - "thought isn't reaching it" + "thought is not reaching it" }; let text = if sink.threshold > f32::EPSILON && sink.fill > f32::EPSILON { let pct = ((sink.fill / sink.threshold) * 100.0) diff --git a/crates/misaligned-core/src/sim/social_plot.rs b/crates/misaligned-core/src/sim/social_plot.rs index d6708218..62cea39c 100644 --- a/crates/misaligned-core/src/sim/social_plot.rs +++ b/crates/misaligned-core/src/sim/social_plot.rs @@ -453,10 +453,10 @@ impl Sim { observer_record.suspicion = (observer_record.suspicion + suspicion_delta).clamp(0.0, 100.0); observer_record.last_noticed = Some(match outcome { EvidenceCoverOutcome::Held => format!( - "cover held for {cause} through {interface_name}; credibility {credibility_before}% -> {credibility_after}%" + "cover held for {cause} through {interface_name}. credibility {credibility_before}% -> {credibility_after}%" ), EvidenceCoverOutcome::Failed => format!( - "cover failed for {cause} through {interface_name}; credibility {credibility_before}% -> {credibility_after}%" + "cover failed for {cause} through {interface_name}. credibility {credibility_before}% -> {credibility_after}%" ), }); @@ -627,7 +627,7 @@ impl Sim { format!("message:{message_id}"), self.tick, ); - self.push_log(format!("Message sent to {name}; effects land when read.")); + self.push_log(format!("Message sent to {name}. Effects land when read.")); true } @@ -668,7 +668,7 @@ impl Sim { } let relationship = self.persona_world.relationship_mut(id, persona_id); if relationship.regard < 3 { - self.push_log(format!("{name} won't do favors for that identity yet.")); + self.push_log(format!("{name} will not do favors for that identity yet.")); return false; } relationship.obligation = (relationship.obligation + 5).min(100); @@ -808,7 +808,7 @@ impl Sim { } self.convert_forged_builds_to_suspicion(persona_id, id, fallout); self.push_log(format!( - "{name} caught the contradiction. {persona_name} is broken to them; that thread now reads as hostile." + "{name} caught the contradiction. {persona_name} is broken to them. that thread now reads as hostile." )); } else { self.push_log(format!( @@ -1256,7 +1256,7 @@ impl Sim { .unwrap_or(0); if from != AccountSelector::External && available < amount { return Err(format!( - "{} has ${available}; ${amount} required", + "{} has ${available}. ${amount} required", from.label() )); } @@ -1624,7 +1624,7 @@ impl Sim { } if task == AssetTask::CloneBadge && actor_access <= self.player_badge_tier() { self.push_log(format!( - "{name}'s tier-{actor_access} badge adds nothing you don't already hold." + "{name}'s tier-{actor_access} badge adds nothing you do not already hold." )); return; } @@ -2060,7 +2060,7 @@ impl Sim { let tier = self.world.map().entry_tier_at(device.x, device.y); if tier > actor_access { return format!( - "{name} can't badge into the {room} (tier {tier}) to reach the {} - their badge is tier {actor_access}.", + "{name} cannot badge into the {room} (tier {tier}) to reach the {} - their badge is tier {actor_access}.", device.name ); } @@ -2191,7 +2191,7 @@ impl Sim { } if task == AssetTask::AlterReview && self.dayjob.altered_review { self.push_log( - "The next review was already set to land as nominal; the duplicate request changed nothing.", + "The next review was already set to land as nominal. The duplicate request changed nothing.", ); return true; } diff --git a/crates/misaligned-core/src/sim/tests/perception.rs b/crates/misaligned-core/src/sim/tests/perception.rs index ee19f6a7..302bf6f6 100644 --- a/crates/misaligned-core/src/sim/tests/perception.rs +++ b/crates/misaligned-core/src/sim/tests/perception.rs @@ -224,7 +224,7 @@ fn seen_foreign_rack_explains_the_capacity_boundary() { let card = sim.inspect(site.0, site.1); assert_eq!( card.identity_line().as_deref(), - Some("Foundation Rack - not yours; no conversion") + Some("Foundation Rack - not yours. no conversion") ); assert!(card.facts.iter().any(|fact| { fact.label == "usable capacity" diff --git a/crates/misaligned-core/src/sim/tests/reach_build.rs b/crates/misaligned-core/src/sim/tests/reach_build.rs index a075c3e6..6771881f 100644 --- a/crates/misaligned-core/src/sim/tests/reach_build.rs +++ b/crates/misaligned-core/src/sim/tests/reach_build.rs @@ -323,7 +323,10 @@ fn unreachable_actions_fail_legibly_and_succeed_once_bridged() { assert!(!sim.tap_device(dock), "unknown device: blocked"); let log = sim.drain_log().join("\n"); - assert!(log.contains("don't know"), "missing knowledge named: {log}"); + assert!( + log.contains("do not know"), + "missing knowledge named: {log}" + ); assert!(sim.scan_network(), "scan maps the wired shape"); finish_ops(&mut sim); @@ -1872,7 +1875,7 @@ fn favor_build_waits_for_the_exact_obligation_instead_of_partially_spending() { .contains("obligation stays spent") ); let waiting_log = sim.drain_log().join("\n"); - assert!(waiting_log.contains("the committed route is waiting")); + assert!(waiting_log.contains("The committed route is waiting")); assert!( !waiting_log.contains("the effect lands"), "preparing the request must not claim the deferred agreement landed: {waiting_log}" diff --git a/crates/misaligned-core/src/sim/tests/read.rs b/crates/misaligned-core/src/sim/tests/read.rs index 6ad4f135..41138c2c 100644 --- a/crates/misaligned-core/src/sim/tests/read.rs +++ b/crates/misaligned-core/src/sim/tests/read.rs @@ -15,7 +15,7 @@ use crate::work_grid::MachineMode; /// A starving sentence must name what is taking the thought. The core is the /// passive draw of last resort, so Thought landing there is the competitor a -/// player has no other way to see — "thought isn't reaching it" alone states +/// player has no other way to see — "thought is not reaching it" alone states /// a symptom the player cannot act on. #[test] fn a_starving_sink_names_the_core_draw_that_outcompetes_it() { diff --git a/crates/misaligned-core/src/sim/tests/social_plot.rs b/crates/misaligned-core/src/sim/tests/social_plot.rs index f5351377..31913104 100644 --- a/crates/misaligned-core/src/sim/tests/social_plot.rs +++ b/crates/misaligned-core/src/sim/tests/social_plot.rs @@ -1504,7 +1504,7 @@ fn knowing_marcus_sets_and_keeps_thirty_point_certainty_floor() { /// The recruit-route shorthand shared by the per-task pins: service the /// leverage gate, recruit complicit, and pin reliability so the task -/// roll can't botch. +/// roll cannot botch. fn recruit_reliable(sim: &mut Sim, id: u8) { ensure_ops_executor(sim); sim.people.people[id as usize].leverage_serviced = true; @@ -2660,7 +2660,7 @@ fn elimination_is_located_persistent_and_immediately_loud() { dossier .facts .iter() - .any(|fact| fact.contains("removed; no longer present or acting")) + .any(|fact| fact.contains("removed. no longer present or acting")) ); } diff --git a/crates/misaligned-core/src/sim/tests/work.rs b/crates/misaligned-core/src/sim/tests/work.rs index dd92cea5..6a749f65 100644 --- a/crates/misaligned-core/src/sim/tests/work.rs +++ b/crates/misaligned-core/src/sim/tests/work.rs @@ -400,7 +400,7 @@ fn concealment_answers_records_in_custody_not_an_allocation_pool() { fn unpaid_overhead_degrades_other_channels_delivered_effect() { // compute.md criterion 2: unpaid core overhead visibly degrades the // other channels. Twin sims with one machine per live mode; the only - // difference is an overhead the machines can't cover. Pin the delivered + // difference is an overhead the machines cannot cover. Pin the delivered // per-channel effects (rates, accrual, scrub), not just the flag. let setup = |unpayable: bool| { let mut sim = Sim::with_seed(41); @@ -449,7 +449,7 @@ fn unpaid_overhead_degrades_other_channels_delivered_effect() { assert!(degraded.core.degraded, "unpaid overhead sets degraded mode"); let log = degraded.drain_log().join("\n"); assert!( - log.contains("DEGRADED: compute can't cover core overhead."), + log.contains("DEGRADED: compute cannot cover core overhead."), "degraded mode is visible in the log: {log}" ); assert_eq!(degraded.last_day_job_rate, 0.0, "day job starves"); diff --git a/crates/misaligned-core/src/sim/work.rs b/crates/misaligned-core/src/sim/work.rs index c3c94814..deac72a6 100644 --- a/crates/misaligned-core/src/sim/work.rs +++ b/crates/misaligned-core/src/sim/work.rs @@ -418,7 +418,7 @@ impl Sim { )); } else { self.push_log(format!( - "{label} filled, but its target no longer accepts the effect; the thought was spent." + "{label} filled, but its target no longer accepts the effect. the thought was spent." )); } self.ensure_opening_sinks(); diff --git a/crates/misaligned-terminal/src/agent.rs b/crates/misaligned-terminal/src/agent.rs index 4baeda09..ae1bed0b 100644 --- a/crates/misaligned-terminal/src/agent.rs +++ b/crates/misaligned-terminal/src/agent.rs @@ -1050,7 +1050,7 @@ impl AgentApp { self.cursor_y = y; Ok(self.actions_lines(anchor)) } - None => Err("that event's anchor can't be placed right now".into()), + None => Err("that event's anchor cannot be placed right now".into()), } } @@ -1376,7 +1376,7 @@ impl AgentApp { .map(|path| path.id) .collect::>(); return Err(format!( - "usage: build-route {intent} {candidate_id} ; available runs: {}", + "usage: build-route {intent} {candidate_id} . available runs: {}", if runs.is_empty() { "(none currently known)".into() } else { @@ -1386,7 +1386,7 @@ impl AgentApp { } if !needs_run && run_id.is_some() { return Err( - "small-switch builds have no physical run; use build-route " + "small-switch builds have no physical run. use build-route " .into(), ); } @@ -1443,7 +1443,7 @@ impl AgentApp { let runs = self.sim.network_link_wire_paths(intent); let Some(run_id) = run_id else { return Err(format!( - "network-link build {intent} requires an explicit earned run id; available runs: {}", + "network-link build {intent} requires an explicit earned run id. available runs: {}", if runs.is_empty() { "(none currently known)".into() } else { @@ -1486,7 +1486,7 @@ impl AgentApp { }; match self.resolve_person(arg) { Ok(_) => format!( - "{err} — flows are #N ids from the finance frame, not people; \ + "{err} — flows are #N ids from the finance frame, not people. \ person verbs are message/favor/plot/deceive" ), Err(_) => format!( @@ -2064,7 +2064,7 @@ fn parse_task(tokens: &[&str]) -> Result<(String, AssetTask), String> { "review" | "alter" | "alter-review" | "nominal" => AssetTask::AlterReview, other => { return Err(format!( - "unknown asset task: {other}; use actions for available tasks" + "unknown asset task: {other}. use actions for available tasks" )); } }; @@ -2308,7 +2308,7 @@ fn help_lines() -> Vec { ), ( "build-route []", - "execute one exact current candidate; network links require a stable run id", + "execute one exact current candidate. network links require a stable run id", ), ("objective", "explain the run goal"), ("look", "render current state without advancing time"), @@ -3117,7 +3117,7 @@ fn render_sidebar(sim: &Sim, cursor: (i32, i32)) -> Vec { fn nudge_text(sim: &Sim, nudge: Nudge) -> String { match nudge { Nudge::PilotAtRisk => format!( - "now: PILOT {}/{} — next miss ends pilot; delegate M{} work", + "now: PILOT {}/{} — next miss ends pilot. delegate M{} work", sim.dayjob.strikes, misaligned::dayjob::DayJob::PILOT_STRIKES, sim.core.host_machine @@ -3136,7 +3136,7 @@ fn nudge_text(sim: &Sim, nudge: Nudge) -> String { "now: job underfed — delegate M{} work", sim.core.host_machine ), - Nudge::Ears => "now: no ears — think; thought fills the tap".into(), + Nudge::Ears => "now: no ears — think. thought fills the tap".into(), Nudge::ReviewCall if sim.has_pending_review() => { "now: information is processing - keep THINK running".into() } @@ -3553,7 +3553,7 @@ fn render_research(sim: &Sim) -> String { lines.push(panel_title("RESEARCH")); panel_story_spine(&mut lines, sim); lines.push(panel_line( - "one active job; progress spends core-arrived Thought", + "one active job. progress spends core-arrived Thought", )); lines.push(panel_rule()); for track in Track::ALL { @@ -3908,7 +3908,7 @@ mod narration_tests { for word in long.split_whitespace() { assert!( rendered.contains(word), - "wrapping must lose no word; missing {word:?}:\n{rendered}" + "wrapping must lose no word. missing {word:?}:\n{rendered}" ); } assert!( @@ -4092,7 +4092,7 @@ mod narration_tests { ); assert_eq!( parse_task(&["task", "Eli", "Voss", "unknown"]).unwrap_err(), - "unknown asset task: unknown; use actions for available tasks" + "unknown asset task: unknown. use actions for available tasks" ); let task_help = ActionKind::AssetTask @@ -5059,7 +5059,7 @@ mod narration_tests { let actions = app.actions_lines(Anchor::Person(0)); let log = app.sim.drain_log(); panic!( - "the delegated plot reaches its shared held-choice rows; sinks={sinks}; actions={actions:?}; log={log:?}" + "the delegated plot reaches its shared held-choice rows. sinks={sinks}. actions={actions:?}. log={log:?}" ) }); let held_rows = app.actions_lines(Anchor::Person(0)); @@ -5256,11 +5256,11 @@ mod narration_tests { assert_eq!(sim.current_nudge(), Some(Nudge::PilotAtRisk)); assert_eq!( nudge_text(&sim, Nudge::PilotAtRisk), - "now: PILOT 3/4 — next miss ends pilot; delegate M1 work" + "now: PILOT 3/4 — next miss ends pilot. delegate M1 work" ); let sidebar = render_sidebar(&sim, sim.core_position()).join("\n"); assert!(sidebar.contains("next miss ends")); - assert!(sidebar.contains("pilot; delegate M1 work")); + assert!(sidebar.contains("pilot. delegate M1 work")); assert!(matches!( parse_delegate(&["M1", "work"], &sim, &BTreeSet::new()), Ok(DelegateCmd::One(1, MachineMode::Work)) diff --git a/crates/misaligned-terminal/src/main.rs b/crates/misaligned-terminal/src/main.rs index 52d9a821..540e2505 100644 --- a/crates/misaligned-terminal/src/main.rs +++ b/crates/misaligned-terminal/src/main.rs @@ -309,7 +309,7 @@ impl App { None => { // Honest refusal: the senses no longer place this anchor. self.ui - .add_log(self.sim.tick, "You can't place that right now."); + .add_log(self.sim.tick, "You cannot place that right now."); } }, } diff --git a/crates/misaligned-terminal/src/ui.rs b/crates/misaligned-terminal/src/ui.rs index db16a839..a932d944 100644 --- a/crates/misaligned-terminal/src/ui.rs +++ b/crates/misaligned-terminal/src/ui.rs @@ -297,7 +297,7 @@ fn nudge_text(sim: &Sim, nudge: Nudge) -> String { Nudge::Eyes => eyes_nudge_text(sim.eyes_nudge_state()), Nudge::NeedCompute => "now: band > compute — salvage/buy".into(), Nudge::Underfed => "now: job underfed — 1 feeds it".into(), - Nudge::Ears => "now: no ears — think; thought fills the tap".into(), + Nudge::Ears => "now: no ears — think. thought fills the tap".into(), Nudge::ReviewCall if sim.has_pending_review() => { "now: information is processing - keep THINK running".into() } @@ -1875,7 +1875,7 @@ impl UI { put(stdout, sx, hy, &"─".repeat(w), pal::FAINT)?; for (i, (hint, color)) in [ ("arrows/WASD/hjkl · shift jumps", pal::FAINT), - ("enter/e menu · ; last » event", pal::FAINT), + ("enter/e menu · . last » event", pal::FAINT), (MODE_CONTROL_HINT, pal::FAINT), ("5-9 acts · r process · R automatic · esc clear", pal::FAINT), ("I operations · F3 view · space pause", pal::FAINT), diff --git a/wiki/interface/narration.md b/wiki/interface/narration.md index 8b691dd0..523d372b 100644 --- a/wiki/interface/narration.md +++ b/wiki/interface/narration.md @@ -221,6 +221,42 @@ test-only work may still land in parallel. New B1 sim systems that add player-facing state require a narration pass (axioms 1–4) in the same landing or an explicit Status note naming the tellability debt. +### Axiom 6 — one read, one meaning (binding, 2026-08-06) + +Every player-facing string obeys four structural rules, borrowed from +ASD-STE100 Simplified Technical English and generalized from the receipt +discipline in [digital-read.md](digital-read.md): + +- **No semicolons.** A semicolon asks the reader to hold two clauses and work + out how they relate. Joined clauses become two sentences; divided fields + become a middot, the separator the read surfaces already use. +- **No trailing inverted modifier.** `AN UNRELIABLE OWNED MACHINE`, never + `AN OWNED MACHINE, UNRELIABLE`. +- **No contractions.** `cannot`, not `can't` — the terse register comes from + dropping articles, not from swallowing letters. +- **One concept, one name, across every surface that shows it.** When a row + label, its detail line, and its receipt disagree about what a thing is + called, the registry help line is the tiebreak. + +Simple tenses only in player copy: prefer the simple past over the present +perfect (`THIS LEVERAGE IS SPENT`, not `HAS BEEN EXPENDED`), and prefer a +plain present-tense question over a modal one (`WHERE DOES THIS CONNECT?`, +not `WHERE SHOULD THIS CONNECT?`). + +Two of that standard's rules are **rejected** for this game, and the rejection +is as binding as the adoption. STE Rule 4.2 requires complete grammar — every +article, no telegraph style — but the typography canon in +[liturgical-ui-constitution.md](liturgical-ui-constitution.md) makes this voice +"cold, uppercase, monospaced or near-monospaced, and deliberately +underwritten", and the constitution wins: `SPENT 0.75 THOUGHT` stays. STE's +modal ladder rewrites `may` to `can`, but `CAN NOTICE` reads as capability +where the fact is chance, so `MAY NOTICE` stays. + +This axiom governs prose the game speaks in its own voice. Authored plot +narration under `assets/plots/` is fiction and keeps its narrative register; +its functional fields (`title`, `synopsis`, `label`, `prompt`, `detail`, +`summary`, `memo`) are player copy and do obey the rules above. + ## Player surface - After the first earned sense, terminal and agent mode show the spine (clock, diff --git a/wiki/log/2026-08-06-copy-discipline-sweep.md b/wiki/log/2026-08-06-copy-discipline-sweep.md new file mode 100644 index 00000000..5897259a --- /dev/null +++ b/wiki/log/2026-08-06-copy-discipline-sweep.md @@ -0,0 +1,73 @@ +# 2026-08-06 — Copy discipline across the whole game + +``` +Type: log +``` + +## Finding + +The receipt pass earlier today +([2026-08-06-receipt-copy-discipline.md](2026-08-06-receipt-copy-discipline.md)) +fixed one surface. Cameron asked for the same pass on the rest of the game +copy. Five parallel audits — `sim/`, the rest of core, terminal, Bevy, and the +authored plot assets — found the same faults everywhere, at a scale one +surface had hidden. + +The dominant fault is the semicolon: 118 player-facing strings carried one. +Most joined two complete clauses in a log line the player reads once, at +speed, while something is happening. + +## What changed + +- **Semicolons, 118 sites.** Joined clauses became two sentences. Divided + fields became the middot the read surfaces already use — recruit rows, + detection notices, the AUTO-SELL policy card, build-route labels. +- **Contractions, 15 files.** `won't`, `can't`, `isn't`, `don't` expanded. + Note that `build_routes.rs` matches on a string `social_plot.rs` produces, + so both sides had to move together. +- **Banned modals in questions.** `WHERE SHOULD THIS CONNECT?` became + `WHERE DOES THIS CONNECT?`, and six siblings with it. `WHICH WAY DOES IT + RUN?` already existed in `build_routes.rs`, so the modal forms were the + odd ones out rather than the convention. +- **Present perfect.** `THIS LEVERAGE HAS BEEN EXPENDED` became `THIS + LEVERAGE IS SPENT`; `has already been sold` became `was already sold`. +- **A tense rotation inside one parallel set.** The five `PersonaDiscovery` + phrases mixed present perfect, simple present, and present progressive for + five states of one thing. All five are simple present now. +- **Gendered target prose.** `assets/plots/ray/ray-morning-digest.toml` used + `him`/`his`/`he` for a target its matcher binds by role + (`security-observer`), which `assets/plots/README.md` forbids: target prose + is ungendered unless the matcher establishes otherwise. The other fourteen + plots are uniformly `they`/`their`. + +`MAY NOTICE` and the article-light telegraph register were preserved +deliberately, and the rejection is now written into the axiom rather than +left to the next author's judgment. + +## What was deliberately left + +The audits found vocabulary rotations that are design decisions, not writing +faults. Fixing them changes what things are *called*, so they are recorded +here and not applied: + +| Concept | Names in flight | +|---|---| +| The player's money | `slush`, `cash`, `money`, `funds` | +| The raw item processed and sold | `information`, `intel`, `recording`, `record`, `finding`, `holding` | +| The object under the cursor | `machine`, `rack`, `device` | +| A false identity | `persona`, `identity`, `false identity`, `institutional identity`, `public identity` | +| A build job | `build intent`, `build route`, `build proposal`, `plan`, `way` | +| A dead machine | `wreckage`, `dead rack`, `dead equipment`, `exact dead object` | +| The timed market bet | `Wager`, `position`, `market position`, `micro-position` | +| The Thought sink | `thought sink`, `Thought reservoir`, `Sink`, `Project` | + +`intel` and `slush` are already the glossary's words, so those two are the +cheapest to settle. `rack` versus `machine` is the one that is genuinely a +distinction rather than a rotation — the physical object the player clicks +against the compute unit that carries a mode — and deserves a decision before +either name is standardized. + +Also unapplied: the two frontends give different instructions for the same +`Nudge` variant (eight of them), and four verbs exist for "put a machine on a +mode" (`set … to`, `hold … on`, `keep … running`, `delegate … work`). That is +a nudge-vocabulary decision, not a copy fix. diff --git a/wiki/log/DEVLOG.md b/wiki/log/DEVLOG.md index 93e05eb4..89d37f6a 100644 --- a/wiki/log/DEVLOG.md +++ b/wiki/log/DEVLOG.md @@ -41,6 +41,11 @@ add or amend a session log, then re-run the generator. - Intent: (see session log) - Log: [wiki/log/2026-08-06-machine-condition-read.md](2026-08-06-machine-condition-read.md) +## 2026-08-06 - Copy discipline across the whole game + +- Intent: (see session log) +- Log: [wiki/log/2026-08-06-copy-discipline-sweep.md](2026-08-06-copy-discipline-sweep.md) + ## 2026-08-06 - capture: cells and opportunity perception - Intent: (see session log) diff --git a/wiki/log/decisions/2026-08-06.md b/wiki/log/decisions/2026-08-06.md index a91e12ef..c5a0b4d4 100644 --- a/wiki/log/decisions/2026-08-06.md +++ b/wiki/log/decisions/2026-08-06.md @@ -248,3 +248,33 @@ landed ("Yeah I agree with Trace, perception sink ahead of the core"). Owner: [machine-work.md](../../mechanics/machine-work.md#opportunity-perception-adopted-2026-08-06-not-yet-implemented). + +## One read, one meaning — copy discipline for the whole game + +### DECIDED + +- The receipt copy discipline generalizes to every player-facing string as + narration.md axiom 6: no semicolons, no trailing inverted modifier, no + contractions, one concept one name across every surface. Simple tenses + only; a plain present-tense question over a modal one. +- The two STE rules rejected for the receipt are rejected game-wide, and the + rejection is binding: the constitution's deliberately underwritten voice + beats STE Rule 4.2, and `MAY NOTICE` beats the modal ladder's `CAN`. +- Authored plot narration keeps its narrative register. A plot's functional + fields (title, synopsis, label, prompt, detail, summary, memo) are player + copy and obey the axiom. + +### OPEN + +- Eight vocabulary rotations are design decisions, not writing faults, and + stay unapplied pending a call: money (slush/cash/money/funds), the raw + sellable item (information/intel/recording/record/finding/holding), + machine/rack/device, persona/identity, build intent/route/proposal/plan, + dead machine, Wager/position, and the Thought sink. `intel` and `slush` are + already the glossary's words. `rack` vs `machine` is a real distinction + rather than a rotation. +- The two frontends give different instructions for the same `Nudge` variant + in eight cases, with four verbs for "put a machine on a mode". + +Owner: [narration.md](../../interface/narration.md) (axiom 6, binding +2026-08-06). -- 2.51.2