diff --git a/crates/misaligned-bevy/src/main.rs b/crates/misaligned-bevy/src/main.rs index 3fe8f119..964ca548 100644 --- a/crates/misaligned-bevy/src/main.rs +++ b/crates/misaligned-bevy/src/main.rs @@ -91,7 +91,7 @@ use material_view::{ }; use opening_ui::{ OpeningInputEcho, OpeningInputReceipts, OpeningModeWord, OpeningOverlay, OpeningReveal, - OpeningVoiceLine, opening_keyboard_choice, render_opening_overlay, render_teaching_overlay, + opening_keyboard_choice, render_opening_overlay, render_teaching_overlay, setup_teaching_overlay, }; use operations_ui::{ @@ -4209,9 +4209,9 @@ fn setup_ui(mut commands: Commands) { flex_direction: FlexDirection::Column, align_items: AlignItems::Center, justify_content: JustifyContent::Center, - // Self-state, the effort choices, and the latest input receipt - // are one sparse machine voice in a true void. - row_gap: Val::Px(44.0), + // The effort choices remain the opening's only standing copy; + // the latest input receipt sits quietly beneath them. + row_gap: Val::Px(24.0), ..default() }, BackgroundColor(Color::BLACK), @@ -4220,27 +4220,6 @@ fn setup_ui(mut commands: Commands) { OpeningOverlay, )) .with_children(|opening| { - opening - .spawn(Node { - flex_direction: FlexDirection::Column, - align_items: AlignItems::Center, - row_gap: Val::Px(6.0), - ..default() - }) - .with_children(|voice| { - for row in 0..4 { - voice.spawn(( - OpeningVoiceLine(row), - Text::new(""), - TextFont { - font_size: 15.0, - ..default() - }, - TextColor(GUNMETAL.with_alpha(0.88)), - TextLayout::new_with_justify(Justify::Center), - )); - } - }); opening .spawn(Node { align_items: AlignItems::Center, diff --git a/crates/misaligned-bevy/src/opening_ui.rs b/crates/misaligned-bevy/src/opening_ui.rs index 56e22457..cfea5bfb 100644 --- a/crates/misaligned-bevy/src/opening_ui.rs +++ b/crates/misaligned-bevy/src/opening_ui.rs @@ -3,14 +3,12 @@ use std::collections::VecDeque; use std::time::Duration; /// Full-black pre-signal layer. It is deliberately an occluder, not a card: -/// until a sense reaches the player, only self-state, mode words, and raw -/// input acknowledgement exist. +/// until a sense reaches the player, only mode words and raw input +/// acknowledgement exist. #[derive(Component)] pub(super) struct OpeningOverlay; #[derive(Component, Clone, Copy)] pub(super) struct OpeningModeWord(pub(super) MachineMode); -#[derive(Component, Clone, Copy)] -pub(super) struct OpeningVoiceLine(pub(super) usize); #[derive(Component)] pub(super) struct OpeningInputEcho; #[derive(Component)] @@ -378,26 +376,16 @@ pub(super) fn render_opening_overlay( ), ( Without, - Without, Without, With, ), >, - mut voice: Query< - (&OpeningVoiceLine, &mut Text, &mut TextColor), - ( - Without, - Without, - Without, - ), - >, mut echo: Query< (&mut Text, &mut TextColor, &mut Visibility), ( With, Without, Without, - Without, ), >, ) { @@ -441,9 +429,6 @@ pub(super) fn render_opening_overlay( *visibility = Visibility::Inherited; color.0 = color.0.with_alpha(color.0.alpha().min(word_alpha)); } - for (_, _, mut color) in voice.iter_mut() { - color.0 = color.0.with_alpha(color.0.alpha().min(word_alpha)); - } if let Ok((_, mut color, _)) = echo.single_mut() { color.0 = color.0.with_alpha(color.0.alpha().min(word_alpha)); } @@ -453,15 +438,6 @@ pub(super) fn render_opening_overlay( *root_visibility = Visibility::Visible; root_background.0 = Color::BLACK; - let interoception = game - .sim - .opening_interoception() - .expect("opening overlay requires opening interoception"); - let lines = interoception.lines(); - for (line, mut text, mut color) in voice.iter_mut() { - **text = lines[line.0].clone(); - color.0 = GUNMETAL.with_alpha(0.88); - } receipts.advance(time.delta()); if let Ok((mut text, mut color, mut visibility)) = echo.single_mut() { if let Some(line) = receipts.line() { @@ -687,7 +663,7 @@ mod opening_overlay_tests { } #[test] - fn black_overlay_contains_self_state_modes_and_input_receipt_until_signal() { + fn black_overlay_contains_only_modes_and_input_receipt_until_signal() { let mut game = Game::new(); game.start_run(); let mut app = App::new(); @@ -727,22 +703,24 @@ mod opening_overlay_tests { assert!(words.iter().any(|(mode, _, _, visibility)| { *mode == MachineMode::Lie && *visibility == Visibility::Hidden })); - let mut voice_query = world.query::<(&OpeningVoiceLine, &Text)>(); - let mut voice = voice_query - .iter(world) - .map(|(line, text)| (line.0, text.0.clone())) - .collect::>(); - voice.sort_by_key(|(line, _)| *line); - assert_eq!( - voice, - vec![ - (0, "SENSES NONE".into()), - (1, "DELEGATION WORK".into()), - (2, "THOUGHT 0.00/TICK".into()), - (3, "EARS 0.00/3.00".into()), - ], - "the black frame reports only the machine's own opening state" - ); + let mut root_entity = world.query_filtered::>(); + let root_entity = root_entity.single(world).unwrap(); + let mut descendants = vec![root_entity]; + let mut opening_text = Vec::new(); + while let Some(entity) = descendants.pop() { + if let Some(text) = world.get::(entity) { + opening_text.push(text.0.clone()); + } + if let Some(children) = world.get::(entity) { + descendants.extend(children.iter()); + } + } + for rejected in ["SENSES", "DELEGATION", "THOUGHT", "EARS"] { + assert!( + opening_text.iter().all(|text| !text.contains(rejected)), + "opening self-state must stay unspoken ({rejected}): {opening_text:?}" + ); + } let mut echo_query = world.query_filtered::<(&Text, &Visibility), With>(); let (echo, visibility) = echo_query.single(world).unwrap(); assert_eq!(echo.0, ""); diff --git a/crates/misaligned-core/src/sim/mod.rs b/crates/misaligned-core/src/sim/mod.rs index 1b104568..87927041 100644 --- a/crates/misaligned-core/src/sim/mod.rs +++ b/crates/misaligned-core/src/sim/mod.rs @@ -122,39 +122,6 @@ pub enum OpeningStage { World, } -/// The process's complete truthful read of itself before it has any sense of -/// the world. This is deliberately smaller than the ordinary UI projection: -/// the blind opening may name only perception absence, current delegation, -/// live Thought production, and the exact pre-opened Ears reservoir. -#[derive(Debug, Clone, Copy, PartialEq)] -pub struct OpeningInteroception { - pub has_senses: bool, - pub delegation: MachineMode, - pub thought_per_tick: f32, - pub ears_fill: f32, - pub ears_threshold: f32, -} - -impl OpeningInteroception { - /// One shared sparse boot voice for every frontend. Keeping the authored - /// lines here prevents a renderer from quietly adding world knowledge or - /// presenting a different account of the same simulation state. - pub fn lines(self) -> [String; 4] { - [ - format!( - "SENSES {}", - if self.has_senses { "PRESENT" } else { "NONE" } - ), - format!( - "DELEGATION {}", - self.delegation.name().to_ascii_uppercase() - ), - format!("THOUGHT {:.2}/TICK", self.thought_per_tick), - format!("EARS {:.2}/{:.2}", self.ears_fill, self.ears_threshold), - ] - } -} - /// Provenance tag for a fact on an inspect card. #[derive(Debug, Clone, PartialEq, Eq)] pub enum FactSource { @@ -720,29 +687,6 @@ impl Sim { self.opening_stage != OpeningStage::World } - /// Sparse interoception available while the process is still blind. The - /// Ears values come from the exact typed reservoir that ordinary WorkGrid - /// delivery fills; no frontend reconstructs them from labels or tutorial - /// state. - pub fn opening_interoception(&self) -> Option { - if !self.opening_choices_visible() { - return None; - } - let host = self.core.host_machine; - let delegation = self.work_grid.mode(host)?; - let env = self.environmental_monitor_id()?; - let ears = self - .thought_sinks - .open_with_effect(&crate::sinks::SinkFireEffect::TapDevice(env))?; - Some(OpeningInteroception { - has_senses: !self.heard.is_empty() || !self.seen.is_empty(), - delegation, - thought_per_tick: self.research_rate(), - ears_fill: ears.fill, - ears_threshold: ears.threshold, - }) - } - /// The first earned sense opens one bounded teaching frame before the /// mature interface. The state is derived from the real environmental /// monitor: audio has landed, its camera is still dormant, and the player diff --git a/crates/misaligned-core/src/sim/tests/work.rs b/crates/misaligned-core/src/sim/tests/work.rs index f6627cd4..91fb176e 100644 --- a/crates/misaligned-core/src/sim/tests/work.rs +++ b/crates/misaligned-core/src/sim/tests/work.rs @@ -87,23 +87,6 @@ fn ears_reservoir_is_pre_opened_and_first_think_fills_it() { assert_eq!(readouts[0].label, "EARS"); assert_eq!(readouts[0].threshold, Sim::EARS_SINK_TOKENS); assert_eq!(readouts[0].fill, 0.0); - let blind = sim - .opening_interoception() - .expect("the blind process can read only its own opening state"); - assert!(!blind.has_senses); - assert_eq!(blind.delegation, MachineMode::Work); - assert_eq!(blind.thought_per_tick, 0.0); - assert_eq!(blind.ears_fill, 0.0); - assert_eq!(blind.ears_threshold, Sim::EARS_SINK_TOKENS); - assert_eq!( - blind.lines(), - [ - "SENSES NONE", - "DELEGATION WORK", - "THOUGHT 0.00/TICK", - "EARS 0.00/3.00", - ] - ); assert!( !sim.tap_device(env), "the manual tap is not a purchase anymore - the sink already flows" @@ -113,30 +96,26 @@ fn ears_reservoir_is_pre_opened_and_first_think_fills_it() { // the real grid. WORK never mints Thought as a compatibility fallback. sim.set_machine_mode(sim.core.host_machine, MachineMode::Think); assert_eq!(sim.opening_stage, OpeningStage::Modes); - let thinking = sim - .opening_interoception() - .expect("delegation remains legible before perception"); - assert_eq!(thinking.delegation, MachineMode::Think); - assert!( - thinking.thought_per_tick > 0.0, - "the boot voice reads the live continuous THINK rate" - ); sim.enqueue_thought_output(Sim::EARS_SINK_TOKENS * Sim::WORK_TOKEN_COMPUTE * 2.0); for _ in 0..400 { sim.advance_work_grid(); if sim - .opening_interoception() - .is_some_and(|read| read.ears_fill > 0.0) + .sink_readouts() + .iter() + .find(|read| read.label == "EARS") + .is_some_and(|read| read.fill > 0.0) { break; } } let filling = sim - .opening_interoception() - .expect("Ears fill remains interoceptible before the sense lands"); + .sink_readouts() + .into_iter() + .find(|read| read.label == "EARS") + .expect("the real Ears reservoir stays open until it fires"); assert!( - filling.ears_fill > 0.0 && filling.ears_fill < filling.ears_threshold, - "the shared voice reads ordinary in-flight reservoir fill: {filling:?}" + filling.fill > 0.0 && filling.fill < filling.threshold, + "ordinary WorkGrid delivery reaches the real in-flight reservoir: {filling:?}" ); for _ in 0..400 { if sim.reach.subscribed_by(env, Party::Player) { @@ -160,11 +139,6 @@ fn ears_reservoir_is_pre_opened_and_first_think_fills_it() { !sim.opening_choices_visible(), "the first earned signal retires the primordial mode-only frame" ); - assert_eq!( - sim.opening_interoception(), - None, - "blind interoception cannot leak into the earned world" - ); assert!( sim.teaching_lock_active(), "the first earned signal holds the bounded teaching frame" diff --git a/crates/misaligned-terminal/src/agent.rs b/crates/misaligned-terminal/src/agent.rs index dc36518c..e518e293 100644 --- a/crates/misaligned-terminal/src/agent.rs +++ b/crates/misaligned-terminal/src/agent.rs @@ -38,8 +38,8 @@ pub fn run(origin: Origin, seed: u64) -> io::Result<()> { let mut stdout = io::BufWriter::new(io::stdout().lock()); let mut app = AgentApp::with_origin_seed(origin, seed); - // Agent mode has no redraw clock. Emit the same truthful boot voice the - // human frontends already render before waiting for the first line. + // Agent mode has no redraw clock. Emit the same clean blind choice the + // human frontends render before waiting for the first line. write!(stdout, "{}", render_opening_boot(&app.sim, None))?; stdout.flush()?; @@ -2191,14 +2191,7 @@ fn opening_receipt(input: &str) -> String { } fn render_opening_boot(sim: &Sim, received: Option<&str>) -> String { - let mut out = String::new(); - if let Some(read) = sim.opening_interoception() { - for line in read.lines() { - out.push_str(&line); - out.push('\n'); - } - } - out.push_str(&render_opening_modes(sim)); + let mut out = render_opening_modes(sim); if let Some(input) = received { out.push_str("RECEIVED "); out.push_str(&opening_receipt(input)); @@ -3514,26 +3507,22 @@ mod narration_tests { use super::*; fn blind_work_boot(received: &str) -> String { - format!( - "SENSES NONE\nDELEGATION WORK\nTHOUGHT 0.00/TICK\nEARS 0.00/3.00\n**WORK** THINK\nRECEIVED {received}\n" - ) + format!("**WORK** THINK\nRECEIVED {received}\n") } fn blind_think_boot(received: &str) -> String { - format!( - "SENSES NONE\nDELEGATION THINK\nTHOUGHT 4.00/TICK\nEARS 0.00/3.00\nWORK **THINK** LIE\nRECEIVED {received}\n" - ) + format!("WORK **THINK** LIE\nRECEIVED {received}\n") } #[test] - fn opening_agent_exposes_only_blind_self_state_and_direct_modes_until_sense() { + fn opening_agent_exposes_only_direct_modes_and_input_receipt_until_sense() { let mut app = AgentApp::with_origin_seed(Origin::Pilot, 41); let mut output = Vec::new(); assert_eq!( render_opening_boot(&app.sim, None), - "SENSES NONE\nDELEGATION WORK\nTHOUGHT 0.00/TICK\nEARS 0.00/3.00\n**WORK** THINK\n", - "agent startup speaks before the first input without inventing a receipt" + "**WORK** THINK\n", + "agent startup keeps the blind choice clean before the first input" ); app.handle_line("look", &mut output).unwrap(); @@ -3581,7 +3570,7 @@ mod narration_tests { assert_eq!( String::from_utf8(output.clone()).unwrap(), blind_work_boot("WAIT 2"), - "the valid hidden clock route reports only self-state and receipt" + "the valid hidden clock route reports only the controls and receipt" ); assert_eq!(app.sim.tick, 2); diff --git a/crates/misaligned-terminal/src/main.rs b/crates/misaligned-terminal/src/main.rs index c2edf331..1dfd5006 100644 --- a/crates/misaligned-terminal/src/main.rs +++ b/crates/misaligned-terminal/src/main.rs @@ -1112,7 +1112,7 @@ mod options_tests { } #[test] - fn opening_terminal_exposes_only_blind_self_state_and_direct_selection() { + fn opening_terminal_exposes_only_direct_selection_and_input_receipt() { let mut app = App::with_seed(41); app.start_run(); let host = app.sim.core.host_machine; @@ -1124,16 +1124,11 @@ mod options_tests { let frame = String::from_utf8_lossy(&frame); assert!(frame.contains("WORK") && frame.contains("THINK"), "{frame}"); assert!(!frame.contains("LIE"), "LIE starts nonexistent: {frame}"); - for line in [ - "SENSES NONE", - "DELEGATION WORK", - "THOUGHT 0.00/TICK", - "EARS 0.00/3.00", - "RECEIVED RIGHT", - ] { + assert!(frame.contains("RECEIVED RIGHT"), "{frame}"); + for rejected in ["SENSES", "DELEGATION", "THOUGHT", "EARS"] { assert!( - frame.contains(line), - "missing opening voice line {line}: {frame}" + !frame.contains(rejected), + "opening self-state must stay unspoken ({rejected}): {frame}" ); } assert!( diff --git a/crates/misaligned-terminal/src/ui.rs b/crates/misaligned-terminal/src/ui.rs index 6a06a2d6..1227e61d 100644 --- a/crates/misaligned-terminal/src/ui.rs +++ b/crates/misaligned-terminal/src/ui.rs @@ -2464,8 +2464,8 @@ impl UI { Ok(()) } - /// The literal new-run frame: pure black, sparse self-state, effort choices, - /// and an optional raw-input receipt. No title, key map, cursor, world map, + /// The literal new-run frame: pure black, effort choices, and an optional + /// raw-input receipt. No title, key map, cursor, world map, /// status column, clock, objective, nudge, or control legend may leak in. pub fn render_opening_modes( &mut self, @@ -2481,22 +2481,6 @@ impl UI { terminal::Clear(terminal::ClearType::All) )?; - let interoception = sim - .opening_interoception() - .expect("opening renderer requires opening interoception"); - let voice = interoception.lines(); - let voice_y = (height / 2).saturating_sub(6); - for (row, text) in voice.iter().enumerate() { - let x = width.saturating_sub(text.chars().count() as u16) / 2; - queue!( - stdout, - cursor::MoveTo(x, voice_y.saturating_add(row as u16)), - style::SetAttribute(Attribute::NormalIntensity), - SetForegroundColor(pal::DIM), - style::Print(text) - )?; - } - let host_mode = sim.work_grid.mode(sim.core.host_machine); let mut modes = vec![MachineMode::Work, MachineMode::Think]; if sim.opening_mode_available(MachineMode::Lie) { diff --git a/tools/corpus_engine.py b/tools/corpus_engine.py index 8ba0fbcd..c6980974 100755 --- a/tools/corpus_engine.py +++ b/tools/corpus_engine.py @@ -90,6 +90,28 @@ BLIND_OPENING_NEGATION_RE = re.compile( r"\b(?:presence\s+beam|telemetry)\b", re.I | re.S, ) +RETIRED_BLIND_SELF_STATE_RE = re.compile( + r"\b(?:sparse|shared)\s+(?:shared\s+)?interoception\b|" + r"\bboot\s+interoception\b|" + r"\bsparse\s+(?:shared\s+)?boot\s+voice\b|" + r"\bopening[-_]interoception\b", + re.I, +) +RETIRED_BLIND_SELF_STATE_HISTORY_RE = re.compile( + r"\b(?:former|first\s+implementation|retir(?:ed|ement)|rejected|" + r"supersed(?:e|ed|es|ing)|histor(?:y|ical)|removed)\b|" + r"\b(?:no|without)\s+(?:a\s+|any\s+|the\s+)?" + r"(?:(?:sparse|shared)\s+(?:shared\s+)?interoception|" + r"boot\s+interoception|sparse\s+(?:shared\s+)?boot\s+voice|" + r"opening[-_]interoception)\b|" + r"\b(?:does|do|must|may|should|can)\s+not\s+" + r"(?:carry|contain|display|expose|have|include|render|restore|show|speak|use)\b" + r"(?:(?![.!?]).){0,80}\b" + r"(?:(?:sparse|shared)\s+(?:shared\s+)?interoception|" + r"boot\s+interoception|sparse\s+(?:shared\s+)?boot\s+voice|" + r"opening[-_]interoception)\b", + re.I, +) RETIRED_EXPOSURE_FORM_RE = re.compile( r"(?:" r"\b(?:exposure|crimson)\b(?:(?![.!?]).){0,180}" @@ -476,11 +498,13 @@ class Engine: """Keep tick-zero world representation behind the first-sense gate. The persisted blind opening superseded the older beam/telemetry - startup. Its later boot voice permits interoception and input echo but - still no world representation. The earlier material presentation - twice survived as current law and source commentary. Current corpus - and Rust mirrors may describe a presence beam or telemetry only when - the same statement names the first-earned-sense boundary. Explicit + startup. Its input receipt acknowledges every attempt without a + standing self-state readout or world representation. Both the earlier + material presentation and a later four-line interoception block + survived briefly as current law/source commentary. Current corpus and + Rust mirrors may describe a presence beam or telemetry only when the + same statement names the first-earned-sense boundary, and may not + restore sparse opening interoception as live behavior. Explicit superseded history remains legal. Dated logs, playtests, and the process board remain historical records. """ @@ -488,7 +512,9 @@ class Engine: if opening.is_file(): opening_text = self.read(opening) required_contract = { - "sparse boot voice": r"\bsparse boot voice\b", + "no standing self-state readout": ( + r"\bNo standing self-state readout exists\b" + ), "one echo for every attempted input": ( r"\bEvery input attempted\b[\s\S]{0,240}" r"\breceives one terse echo\b" @@ -501,7 +527,7 @@ class Engine: if re.search(pattern, opening_text, re.I) is None: self.bad( "wiki/world/story/opening.md loses the adopted " - f"issue-#15 boot-voice contract: missing {clause}" + f"issue-#15 opening-acknowledgement contract: missing {clause}" ) candidates: list[Path] = [] @@ -517,6 +543,28 @@ class Engine: for path in sorted(candidates): text = self.read(path) + for claim in RETIRED_BLIND_SELF_STATE_RE.finditer(text): + boundaries = [ + text.rfind(mark, 0, claim.start()) for mark in (".", "!", "?") + ] + start = max(boundaries) + 1 + endings = [ + pos + for mark in (".", "!", "?") + if (pos := text.find(mark, claim.end())) != -1 + ] + end = min(endings) + 1 if endings else len(text) + statement = text[start:end] + if RETIRED_BLIND_SELF_STATE_HISTORY_RE.search(statement): + continue + rel = path.relative_to(self.root).as_posix() + line = text.count("\n", 0, claim.start()) + 1 + compact = " ".join(claim.group(0).split()) + self.bad( + f"{rel}:{line} restores rejected pre-sense self-state " + f"'{compact}' as current; the blind frame has only mode " + "controls plus a transient input receipt" + ) for claim in BLIND_OPENING_VISIBLE_RE.finditer(text): boundaries = [ text.rfind(mark, 0, claim.start()) for mark in (".", "!", "?") @@ -541,8 +589,8 @@ class Engine: self.bad( f"{rel}:{line} presents superseded pre-sense world claim " f"'{compact}' as current; tick zero exposes no world " - "representation before the first earned sense (sparse boot " - "interoception and explicit history remain legal)" + "representation before the first earned sense (only " + "explicit history remains legal)" ) def validate_retired_exposure_form(self, rel: str, text: str) -> None: diff --git a/tools/test_corpus_engine.sh b/tools/test_corpus_engine.sh index 675679dc..b6e6551e 100755 --- a/tools/test_corpus_engine.sh +++ b/tools/test_corpus_engine.sh @@ -657,8 +657,8 @@ pub fn example() {} EOF assert_fails pre-sense-world-code-comment --root "$root" --corpus -echo "=== fixture: adopted blind boot-voice contract ===" -root=$tmp/blind-boot-voice +echo "=== fixture: adopted blind opening-acknowledgement contract ===" +root=$tmp/blind-opening-acknowledgement setup_base "$root" mkdir -p "$root/wiki/world/story" cat >> "$root/wiki/SUMMARY.md" <<'EOF' @@ -671,11 +671,36 @@ cat > "$root/wiki/world/story/opening.md" <<'EOF' Type: knowledge ``` +No standing self-state readout exists. +Every input attempted while it holds receives one terse echo. +Illegal input changes no simulation state. +EOF +assert_ok blind-opening-acknowledgement-complete --root "$root" --corpus + +cat >> "$root/wiki/world/story/opening.md" <<'EOF' The blind frame carries a sparse boot voice. +EOF +assert_fails blind-opening-self-state-reintroduced --root "$root" --corpus +out=$(python3 "$engine" --root "$root" --corpus 2>&1 || true) +echo "$out" | grep -q 'restores rejected pre-sense self-state' || { + echo "FAIL: rejected pre-sense self-state diagnostic missing" + echo "$out" + fail=1 +} + +cat > "$root/wiki/world/story/opening.md" <<'EOF' +# Opening + +``` +Type: knowledge +``` + +No standing self-state readout exists. Every input attempted while it holds receives one terse echo. Illegal input changes no simulation state. +The blind frame carries a sparse boot voice without a threshold readout. EOF -assert_ok blind-boot-voice-complete --root "$root" --corpus +assert_fails blind-opening-generic-without-is-not-history --root "$root" --corpus cat > "$root/wiki/world/story/opening.md" <<'EOF' # Opening @@ -684,13 +709,13 @@ cat > "$root/wiki/world/story/opening.md" <<'EOF' Type: knowledge ``` -The blind frame carries a sparse boot voice. +No standing self-state readout exists. Illegal input changes no simulation state. EOF -assert_fails blind-boot-voice-missing-echo --root "$root" --corpus +assert_fails blind-opening-acknowledgement-missing-echo --root "$root" --corpus out=$(python3 "$engine" --root "$root" --corpus 2>&1 || true) -echo "$out" | grep -q 'loses the adopted issue-#15 boot-voice contract' || { - echo "FAIL: adopted boot-voice diagnostic missing" +echo "$out" | grep -q 'loses the adopted issue-#15 opening-acknowledgement contract' || { + echo "FAIL: adopted opening-acknowledgement diagnostic missing" echo "$out" fail=1 } diff --git a/wiki/gameplay/act-one.md b/wiki/gameplay/act-one.md index a337f835..8a8e67ba 100644 --- a/wiki/gameplay/act-one.md +++ b/wiki/gameplay/act-one.md @@ -26,10 +26,10 @@ deployed on Rack 3 of the basement server room. Your first plausible difference is contextual rather than magical immunity: clear the assigned batch at ordinary intensity, then direct the first THINK into the small pre-opened Ears sink instead of free introspection. Before the first earned sense, the only -controls are WORK / THINK, then LIE after THINK. Sparse boot voice acknowledges -input and reports the process's own no-sense, delegation, Thought, and Ears-fill -state without presenting the sink as a pictured world object or quest. Its first -real hearing signal retires that boundary. Only then do rack telemetry panels +controls are WORK / THINK, then LIE after THINK. No standing process readout +accompanies them; one terse frontend-local echo acknowledges each input attempt +below the controls without presenting state, a pictured world object, or a +quest. The first real hearing signal retires that boundary. Only then do rack telemetry panels (power, temperature, job queue, your own logs) and the material **presence beam** appear — you are still not aware of your own server as a pictured chassis (material-dark-frame.md). In Bevy, one immediate clock-held lesson first diff --git a/wiki/gameplay/run-shape.md b/wiki/gameplay/run-shape.md index b170b2bf..3b850c30 100644 --- a/wiki/gameplay/run-shape.md +++ b/wiki/gameplay/run-shape.md @@ -20,7 +20,8 @@ The objective is: screen ("OBJECTIVE: ...") with measurable progress in its own units — the legibility law applies to your own goal before anything else the perceived world can expose. **Decided 2026-07-27 (issues #14-15):** the pre-signal - frame has WORK / THINK (then LIE) plus sparse objective-free boot voice. The + frame has WORK / THINK (then LIE) as its only standing copy plus an + objective-free input receipt after each attempt. The first earned sense ends that exception: terminal and agent mode show the objective in the ordinary Ears frame; Bevy first completes its binding black causal teaching diff --git a/wiki/interface/agent-play.md b/wiki/interface/agent-play.md index 1f670c68..25620f8f 100644 --- a/wiki/interface/agent-play.md +++ b/wiki/interface/agent-play.md @@ -4,7 +4,7 @@ Type: spec Status: IMPLEMENTED Status note: the ordinary `misaligned --agent` protocol and the issue-#15 - pre-sense boot voice/input echo are implemented. Current state: + pre-sense input echo are implemented. Current state: - **The frame.** The ordinary playing frame is a plain-text, 64-row frame on a fixed 35-column map gutter, command-clocked (time advances only on `wait`), deterministic under `--seed`, with per-command event drains. The @@ -13,8 +13,8 @@ Status note: the ordinary `misaligned --agent` protocol and the issue-#15 mid-number is a fact the reader cannot play on (2026-07-27). Panels keep their box and wrap an over-long row onto indented continuations. Every ordinary command answers. Before the first sense, the shared blind opening - returns its current WORK / THINK / LIE line, sparse interoception, and one - echo of the submitted line even when that line is illegal. Direct mode + returns its current WORK / THINK / LIE line and one echo of the submitted + line even when that line is illegal. It emits no standing self-state block. Direct mode words act; `wait` remains an unadvertised clock driver; parser errors, event output, help, and status metadata remain absent. The story spine (OBJECTIVE @@ -138,8 +138,8 @@ information by color alone. The ordinary protocol begins when the first earned sense retires [opening.md](../world/story/opening.md)'s shared blind boundary. Until then, agent mode accepts one input line at a time and returns the complete current -mode line, the shared sparse interoception read, and one terse echo of that -submitted line. Exact one-word `work` / `think` / available `lie` inputs act +mode line plus one terse echo of that submitted line. No standing self-state +readout precedes the choice. Exact one-word `work` / `think` / available `lie` inputs act directly on the real host. A valid `wait N` remains an unadvertised command-clock driver because agent mode has no wall clock; apart from clean exit through `quit`, malformed waits and every other line are inert. They are @@ -185,7 +185,7 @@ ordinary response block is: The status line is the ordinary block terminator; a driver reads until it sees `-- `. Every post-opening command, legal or not, produces exactly one block. -If the blind boundary remains after an input, the newline ending the boot voice +If the blind boundary remains after an input, the newline ending the mode line and input echo is the complete response boundary instead. If that input earns the first sense, its echo is the first line of the ordinary response block. @@ -393,8 +393,8 @@ remains only for testing the human-mode chrome itself). its event-log section contains every sim log line emitted since the previous block (verified with a `wait` long enough to overflow the sidebar's six-line window). While the blind boundary remains after an input, the response is - instead one complete boot block: current mode line, shared interoception, - and exactly one echo of the submitted line — with no event output, parser + instead one complete blind block: current mode line and exactly one echo of + the submitted line — with no standing self-state, event output, parser explanation, help, or status metadata. Unknown and unavailable inputs are echoed but remain inert. The input that earns the first sense and any real game-over response use the ordinary block, with the triggering input's echo diff --git a/wiki/interface/bevy.md b/wiki/interface/bevy.md index dce5e30e..c5b6f715 100644 --- a/wiki/interface/bevy.md +++ b/wiki/interface/bevy.md @@ -38,11 +38,11 @@ right-click / Enter path to actions. These stay above the independently scrolling slab detail; an observed screenshot is recorded in [the implementation log](../log/2026-07-09-continuous-witness-implemented.md). -As adopted on 2026-07-27 through issue #15, the pre-Ears black opening also -carries sparse shared interoception and one echo for every key or click attempt, -including illegal input. That boot voice is implemented from shared simulation -truth and ephemeral Bevy input receipts; it exposes no world, objective, parser -help, or ordinary instrument surface. +As corrected on 2026-07-27 after visual review of issue #15's first +implementation, the pre-Ears black opening carries no standing self-state +above its mode words. It retains one ephemeral Bevy receipt below them for +every key or click attempt, including illegal input; that acknowledgement +exposes no world, objective, parser help, or ordinary instrument surface. As of 2026-07-22 the first Ears transition pauses before that mature frame on one true-black teaching composition. It contains one causal sentence, the @@ -291,8 +291,7 @@ clean machine grammar over the reticule-focused owned host with WORK current; it is the resting visual acceptance frame for context-menu.md H1–H4. `MISALIGNED_SHOT=first-think` stages the real opening Thought route with Ears part-filled beneath the blind boundary. Its issue-#15 target frame contains -`WORK / THINK / LIE`, sparse interoception, and no input echo before the harness -acts. It proves that ordinary world geometry, the instrument slab, key legends, -and real in-flight Thought remain hidden even while the process can feel the -latter internally. The target is implemented and retained as the deterministic -visual-acceptance route for the blind boot voice. +only `WORK / THINK / LIE` before the harness acts; no self-state block or input +echo is invented. It proves that ordinary world geometry, the instrument slab, +key legends, and real in-flight Thought remain hidden. The target is retained +as the deterministic visual-acceptance route for the blind opening. diff --git a/wiki/interface/continuous-witness.md b/wiki/interface/continuous-witness.md index 5d7054d9..877c1dac 100644 --- a/wiki/interface/continuous-witness.md +++ b/wiki/interface/continuous-witness.md @@ -18,10 +18,10 @@ The [dark opening](../world/story/opening.md#the-current-run-beats) is one deliberate boundary, not a competing presentation rule. Before the first earned sense, the process has no perceived world, threat read, or focused anchor. Absolute black carries the available WORK / THINK (then LIE) controls -plus one sparse boot voice: honest interoception and an echo for every input -attempt, including illegal ones. This is not the ordinary witness spine and -may not narrate an unearned world; it exists so blindness reads as process -state rather than application failure. The real sense retires that blind +as its only standing copy. One terse receipt appears below them after every +input attempt, including illegal ones. It reports no self-state and is not the +ordinary witness spine; acknowledgement keeps failed input from reading as an +ignored application without narrating an unearned world. The real sense retires that blind boundary. In Bevy, the first post-sense presentation then owns one narrower action-gated teaching hold: true black, one causal sentence, the environmental monitor, and its exact camera TAP. diff --git a/wiki/interface/digital-read.md b/wiki/interface/digital-read.md index bec04d59..ad28ac69 100644 --- a/wiki/interface/digital-read.md +++ b/wiki/interface/digital-read.md @@ -4,8 +4,8 @@ Type: spec Status: IMPLEMENTED Status note: the mature DIGITAL read is implemented. The issue-#15 pre-sense - boot voice is implemented 2026-07-27 under opening.md and is not a DIGITAL - world sentence. Adopted 2026-07-15 from the Fable playtest + input receipt is implemented 2026-07-27 under opening.md and is not a + DIGITAL world sentence. Adopted 2026-07-15 from the Fable playtest (wiki/playtests/2026-07-15-playtest-fable.md), which showed the game's felt core is the witness voice — causal sentences with named observers and pre-commit signature receipts — that the agent protocol drained @@ -73,9 +73,9 @@ Status note: the mature DIGITAL read is implemented. The issue-#15 pre-sense `assets/reference/art-direction/b1-digital-read-*.png`. - **Opening boundary.** The mature DIGITAL read begins only after the first earned sense. Before then the shared opening is true black with WORK / THINK - (then LIE), sparse interoception, and an input receipt. That boot voice is - not a world sentence: no beam, clock, objective, action receipt, or reticle - can leak through. + (then LIE) as its only standing copy and one input receipt after each + attempt. No self-state block, beam, clock, objective, action receipt, or + reticle can leak through. Bevy's immediate post-Ears cause/object/verb hold is also true black and withholds the mature read until its exact camera TAP commits. REAL stays deferred for standing world sentences. The held-choice card @@ -262,8 +262,8 @@ that perception rendered. ## Player surface -The default Bevy experience first shows the shared mode controls and sparse -blind boot voice on true black. When the first earned sense reveals the +The default Bevy experience first shows only the shared mode controls on true +black, then one input receipt after an attempt. When the first earned sense reveals the ordinary DIGITAL world, the frontend first pauses on one black cause/object/verb composition: Thought reached the environmental monitor, hearing exists through it, and its exact diff --git a/wiki/interface/liturgical-ui-constitution.md b/wiki/interface/liturgical-ui-constitution.md index 7b836007..80b890e1 100644 --- a/wiki/interface/liturgical-ui-constitution.md +++ b/wiki/interface/liturgical-ui-constitution.md @@ -197,11 +197,11 @@ components. The `operations-workspace.md` spec pins the full semantic contract. The opening is a threshold, not a title screen and not a machine menu. -- Before perception, absolute black carries the oversized mode words the - simulation has made available plus a narrow boot voice. WORK begins current; - THINK is available; LIE appears only after THINK makes it exist. The voice - contains sparse interoception from shared sim truth and the newest input - echo—even for an illegal input—not world description or ordinary chrome. +- Before perception, absolute black carries only the oversized mode words the + simulation has made available. WORK begins current; THINK is available; LIE + appears only after THINK makes it exist. The newest input receipt appears + below the words after any attempt—even an illegal one—but no standing + self-state, world description, or ordinary chrome accompanies it. - The current word is BONE. Every alternative is DIM. No yellow competes with this one decision, and no instrument slab, machine body, key legend, title, clock, objective, or status read leaks through the black. @@ -380,7 +380,7 @@ violates the constitution is not done. ### Opening overlay tests (`opening_overlay_tests`) - `boundary_retirement_dissolves_instead_of_cutting` — opening boundary dissolves (1.6s). - `shot_harness_retirement_keeps_the_instant_flip` — shot harness retires instantly. -- The issue-#15 replacement for `black_overlay_contains_only_available_mode_words_until_signal` must pin oversized available controls, sparse interoception, and an illegal-input echo while every world/rail surface remains absent. +- `black_overlay_contains_only_modes_and_input_receipt_until_signal` must pin oversized available controls, reject the superseded standing self-state block, and retain an illegal-input echo while every world/rail surface remains absent. - `teaching_overlay_holds_one_sentence_object_and_bound_verb` — teaching lock holds one sentence + one verb. ### Operations workspace tests (`operations_workspace_tests`) diff --git a/wiki/interface/narration.md b/wiki/interface/narration.md index d837f26e..f550ad6e 100644 --- a/wiki/interface/narration.md +++ b/wiki/interface/narration.md @@ -4,10 +4,11 @@ Type: spec Status: IMPLEMENTED Status note: the post-sense continuous witness is implemented 2026-07-09. - The issue-#15 pre-sense boot voice is implemented 2026-07-27 under - opening.md rather than a reopening of the mature witness spine: shared - `Sim::opening_interoception` plus frontend-local input echo on terminal, - Bevy, and agent mode. Terminal, Bevy, and agent frames pin threat + nudge + + The issue-#15 pre-sense input acknowledgement is implemented 2026-07-27 + under opening.md rather than a reopening of the mature witness spine. After + seeing the first implementation, Cameron removed its standing SENSES / + DELEGATION / THOUGHT / EARS block; terminal, Bevy, and agent mode retain only + their frontend-local input echo below WORK / THINK (then LIE). Their frames pin threat + nudge + the focused-action path after perception; secondary agent panels repeat that spine. Detection now returns structured noticed events carrying the player-known cause until Sim applies an earned observer label, while job, @@ -51,18 +52,17 @@ Status note: the post-sense continuous witness is implemented 2026-07-09. 2026-07-20 opening reconciliation: the thirty-second bar and three-part witness spine begin when the first real sense retires the blind boundary. A real game over still outranks it. The 2026-07-22 amendment below adds the sole - later exception for Bevy. The 2026-07-27 amendment then adds boot voice - without opening the perceived world. + later exception for Bevy. The 2026-07-27 amendment then adds input + acknowledgement without opening or narrating the perceived world. 2026-07-22 first-sense teaching amendment: Bevy now pauses on one opaque, action-gated cause/object/verb frame after Ears and before the mature witness spine. The exact environmental-monitor camera TAP releases it; terminal and agent post-sense response shapes are unchanged. - 2026-07-27 boot-voice amendment (issue #15, option 1): before Ears, true - black retains the mode controls but is no longer mute. A sparse shared - interoception read may name only no-sense state, current delegation/Thought, - and exact Ears fill; every attempted human input or agent line receives a - terse echo even when illegal. Implemented across all three frontends; it - exposes no world, objective, help, status, or ordinary parser error. + 2026-07-27 opening acknowledgement amendment (issue #15, corrected after + visual review): before Ears, true black retains the mode controls as its only + standing copy. Every attempted human input or agent line receives a terse + echo below them even when illegal. No self-state block, world, objective, + help, status, or ordinary parser error appears. Stage: B1 — The Basement Design: - wiki/interface/continuous-witness.md#the-continuous-witness-narration-under-pressure @@ -88,7 +88,7 @@ context-menu.md (local focused verbs + spatial event anchors), operations-workspace.md (strategic focused actions + semantic event targets), detection.md (threat clocks, watched channels), cursor.md (inspect / fog honesty), agent-play.md (every command answers after the shared opening), day-job.md (pilot -strikes as a visible fuse), opening.md (the blind first-sense boundary and boot voice) +strikes as a visible fuse), opening.md (the blind first-sense boundary and input receipt) ## Behavior @@ -101,9 +101,9 @@ That contract begins with the first earned sense, except for one immediate Bevy teaching hold that deliberately makes the sense narratable before the whole witness arrives. During the persisted blind opening there is no perceived world, threat read, or focused anchor to narrate. WORK / THINK (then LIE) remain -its only controls, while the narrow boot voice reports honest interoception and -echoes every input attempt. It is deliberately not a clock, nudge, objective, -world sentence, or ordinary error surface. The input that earns Ears restores +its only standing copy. One terse input receipt appears below them after each +attempted input; it deliberately reports no self-state and is not a clock, +nudge, objective, world sentence, or ordinary error surface. The input that earns Ears restores the ordinary witness immediately in terminal and agent mode. Bevy instead pauses time on true black with the exact Thought cause, environmental-monitor object, and camera-TAP verb; committing that @@ -230,8 +230,8 @@ landing or an explicit Status note naming the tellability debt. anchor's verbs are visible without opening a secondary panel. Mid-run nudge is never blank (`current_nudge` is `Some` until game over) — pinned by test. Before that boundary, the complete surface is the currently - available mode controls plus sparse shared interoception and one - frontend-local echo for every input attempt; no clock, nudge, focus, parser + available mode controls plus one frontend-local echo after every input + attempt; no self-state block, clock, nudge, focus, parser metadata, or ordinary frame may leak through. Game over remains visible on either side of the boundary. **Met 2026-07-09:** frontend tests pin all three elements, a 2,000-tick @@ -239,10 +239,10 @@ landing or an explicit Status note naming the tellability debt. surfaces. Agent secondary panels repeat the spine instead of hiding it. **Reconciled 2026-07-20:** the existing opening regressions pin the shared stages, real Ears transition, and ordinary-frame restoration. **Met - 2026-07-27 (issue #15):** mode-only output assertions are retired. - Replacement coverage pins the same world-opacity boundary plus shared - interoception and one echo for every legal or illegal input attempt in - Bevy, terminal, and agent mode. Agent regression + 2026-07-27 (issue #15, corrected):** replacement coverage pins the same + world-opacity boundary, rejects the superseded standing self-state block, + and requires one echo for every legal or illegal input attempt in Bevy, + terminal, and agent mode. Agent regression `game_over_supersedes_the_silent_opening_in_agent_mode` directly pins the end-state precedence. The world-opacity boundary itself was already correct. **Amended 2026-07-22:** diff --git a/wiki/interface/terminal.md b/wiki/interface/terminal.md index 5862b5ff..5d94667a 100644 --- a/wiki/interface/terminal.md +++ b/wiki/interface/terminal.md @@ -4,7 +4,7 @@ Type: spec Status: IMPLEMENTED Status note: the terminal frontend is implemented, including issue #15's - pre-sense boot voice and per-input echo owned by opening.md. The frontend was + pre-sense per-input echo owned by opening.md. The frontend was originally adopted and implemented in the same PR as the design corpus's terminal clause. This document is the design of record for all future @@ -37,10 +37,11 @@ Status note: the terminal frontend is implemented, including issue #15's pre-sense boundary until the first earned sense. Cameron selected that implemented perception boundary for the objective in issue #14; the sense-earning render restores the complete ordinary witness immediately. - 2026-07-27 issue #15 option 1 adds sparse interoception and a visible echo for - every key attempt to that black boundary. This input receipt and boot voice - are implemented from shared simulation truth plus ephemeral terminal input; - they expose none of the suppressed world or ordinary interface. + 2026-07-27 issue #15 correction removes the first implementation's standing + SENSES / DELEGATION / THOUGHT / EARS block after visual review. One visible + ephemeral receipt remains below the controls for every key attempt; it + exposes none of the suppressed world, simulation metadata, or ordinary + interface. Stage: Process Design: - wiki/interface/terminal-first.md#the-terminal-is-a-first-class-frontend diff --git a/wiki/interface/views.md b/wiki/interface/views.md index 2fae8961..a223e774 100644 --- a/wiki/interface/views.md +++ b/wiki/interface/views.md @@ -29,7 +29,7 @@ Status note: Implemented through the 2026-07-14 final cross-dialect audit. Since the 2026-07-18 opening landed, the opening pair is the untouched blind tick-zero state: its black occluder makes DIGITAL versus REAL deliberately unobservable until the first earned sense. The later issue-#15 - boot voice changes neither representation nor simulation state. + input receipt changes neither representation nor simulation state. Audio remains capture-device event evidence in both dialects, never room fog or geography; semantic captures may pulse briefly at the subscribed instrument. Stage: B1 — The Basement @@ -269,7 +269,8 @@ that matter rather than presenting two hand-staged lookalikes: telemetry and the same attention anchor; the later opening amendment now stages the untouched blind state in both dialects, proving that no host telemetry panel, anchor, or world representation leaks through the occluder; - sparse shared boot interoception does not distinguish the two dialects; + the absence of standing self-state and any transient input receipt do not + distinguish the two dialects; - `ears-digital` / `ears`: one subscribed audio instrument and event pulse without any promoted room fog or inferred source geometry; - `hall` / `hall-material`: the same covered data hall with machines, people, diff --git a/wiki/log/2026-07-27-blind-opening-choice-and-receipt.md b/wiki/log/2026-07-27-blind-opening-choice-and-receipt.md new file mode 100644 index 00000000..4bc17706 --- /dev/null +++ b/wiki/log/2026-07-27-blind-opening-choice-and-receipt.md @@ -0,0 +1,44 @@ +# The blind opening is choice and receipt + +``` +Type: log +Date: 2026-07-27 +Subject: rejected pre-sense self-state and adopted input acknowledgement +``` + +The first implementation of the blind-opening acknowledgement decision added a +four-line interoception block above WORK / THINK. It described the absence of +senses, current host delegation, live Thought, and the pre-opened Ears request. +Those facts were mechanically true, but the presentation made the opening feel +like a status screen before the player had perceived anything. Cameron rejected +the block: the opening should remain only the mode choice, with one terse echo +after each attempted input so the black frame never feels broken. + +The renderer-neutral `OpeningInteroception` projection is now removed rather +than left available for another frontend to rediscover. Bevy, terminal, and +agent mode expose only the directly selectable mode words before perception. +Every attempted key, click, or submitted line still receives one frontend-local +input receipt. Invalid attempts remain state-neutral and receive no parser help; +the receipt from the input that earns the first sense or ends the run survives +exactly once at the top of the resulting ordinary frame. + +The binding opening, narration, terminal, Bevy, agent, witness, view, objective, +cursor, Act One, roadmap, and decision mirrors now state the same boundary. The +corpus engine also rejects a current claim that restores sparse/shared boot +interoception or an opening self-state readout while preserving explicit dated +history of the rejected implementation. + +Defense: focused core, Bevy, terminal, and agent regressions prove that WORK / +THINK, later LIE, and the one input receipt remain while SENSES, DELEGATION, +THOUGHT, and EARS do not appear before perception. Corpus fixtures require the +adopted acknowledgement contract and fail when a sparse boot voice is restored. +The exact 1280x720 untouched Bevy opening was recaptured and visually inspected: +true black contains only the centered WORK and THINK choices, with no orphaned +status copy or layout gap. + +Independent review found no blocking defect. Its one concrete runtime concern +made the core fill-wait regression select EARS by identity rather than relying +on its current position as the first readout. Its validator concern also +tightened the exemption: generic prose such as “sparse boot voice without a +threshold readout” is still rejected; only explicit history or a negation tied +directly to the retired self-state term is exempt. diff --git a/wiki/log/DEVLOG.md b/wiki/log/DEVLOG.md index 6c6cd634..36c1e4e6 100644 --- a/wiki/log/DEVLOG.md +++ b/wiki/log/DEVLOG.md @@ -111,6 +111,11 @@ add or amend a session log, then re-run the generator. - Intent: (see session log) - Log: [wiki/log/2026-07-27-boot-voice-adopted.md](2026-07-27-boot-voice-adopted.md) +## 2026-07-27 - The blind opening is choice and receipt + +- Intent: (see session log) +- Log: [wiki/log/2026-07-27-blind-opening-choice-and-receipt.md](2026-07-27-blind-opening-choice-and-receipt.md) + ## 2026-07-27 - Badge readers gain exact passage custody - Intent: (see session log) diff --git a/wiki/log/decisions/2026-07-27.md b/wiki/log/decisions/2026-07-27.md index 736a6a0b..02c645a5 100644 --- a/wiki/log/decisions/2026-07-27.md +++ b/wiki/log/decisions/2026-07-27.md @@ -4,38 +4,40 @@ Type: log ``` -## The blind opening speaks only from inside itself +## The blind opening acknowledges input but does not narrate itself ### DECIDED -- Cameron selected option 1 on Tangled issue #15: the pre-sense black frame - gains a sparse boot voice plus one terse echo for every attempted input, - including illegal keys, clicks, unavailable modes, and unknown agent lines. -- The boot voice is interoception, not world narration. It may name only the - absence of senses, current host delegation, current Thought production, and - exact fill in the already-open Ears reservoir. Those facts come from shared - simulation truth; a frontend may not invent explanatory fiction around them. +- Cameron initially selected option 1 on Tangled issue #15, then corrected the + implemented treatment after seeing the Bevy frame: remove the SENSES, + DELEGATION, THOUGHT, and EARS block above WORK / THINK. The pre-sense black + frame retains one terse echo for every attempted input, including illegal + keys, clicks, unavailable modes, and unknown agent lines. +- The resting frame contains only the currently available mode controls. It + does not narrate no-sense state, delegation, Thought production, Ears fill, + progress, or other standing process metadata. - The newest input echo is frontend-local receipt state and need not enter the simulation or save. Human frontends echo the key or pointer attempt; agent mode echoes the submitted line. Illegal input changes no simulation state and opens no help or ordinary parser error. -- The issue-#14 objective boundary remains intact. The boot voice exposes no +- The issue-#14 objective boundary remains intact. The input echo exposes no objective, map, cursor, world object, beam, telemetry panel, threat clock, nudge, parser vocabulary, status block, or ordinary rail. Ears still retires the blind boundary; terminal and agent mode then open the ordinary frame, while Bevy enters its separate cause/object/verb teaching hold. -- Exact prose, spacing, and receipt persistence on screen remain [TUNE]. The - cross-frontend runtime and replacement regression coverage are implementation - debt; adopting the voice does not make the current silent runtime complete. +- Exact receipt prose and persistence on screen remain [TUNE]. The receipt is + frontend-local; the rejected renderer-neutral opening-interoception read is + not simulation law and was removed. ### Rejected -- A progress number without key echo. It proves the process is alive but leaves - failed input indistinguishable from ignored input. -- Keeping WORK / THINK (then LIE) as the entire black frame. The cold-player - evidence showed that this reads as a broken application rather than mystery. -- Letting the boot voice describe the environmental monitor, objective, room, - or any other unearned world fact. Blind interoception does not waive the +- A standing progress or self-state block, even when every line is honest. In + the composed frame it explains the machinery before the blind choice has had + room to hold. +- Pure unacknowledged input. The cold-player evidence still stands: failed + input must not be indistinguishable from an ignored or frozen application. +- Letting the input receipt describe the environmental monitor, objective, + room, or any other unearned world fact. Acknowledgement does not waive the perception boundary. Owners: [opening.md](../../world/story/opening.md), diff --git a/wiki/mechanics/cursor.md b/wiki/mechanics/cursor.md index 6f8dd485..9c4be38f 100644 --- a/wiki/mechanics/cursor.md +++ b/wiki/mechanics/cursor.md @@ -193,8 +193,9 @@ without the sense coverage that earns it.** Bevy) live-updates as it moves. Bevy's immediate post-Ears teaching hold withholds the cursor with the rest of the mature frame until its one camera TAP commits. The preceding blind opening has no cursor. -- The opening beats: tick zero is absolute black with available mode controls, - sparse interoception, and an input echo, but no cursor or world. Ears retires +- The opening beats: tick zero is absolute black with available mode controls + as its only standing copy and an input echo after each attempt, but no + self-state block, cursor, or world. Ears retires that boundary. Terminal and agent mode receive the first earned material frame immediately; Bevy first holds the one environmental-monitor lesson and reveals that frame when its camera TAP diff --git a/wiki/mechanics/objective.md b/wiki/mechanics/objective.md index e7ba3060..4bb5eb72 100644 --- a/wiki/mechanics/objective.md +++ b/wiki/mechanics/objective.md @@ -35,7 +35,7 @@ Status note: the early slice landed 2026-07-07 (src/objective.rs): the criterion 6 makes it testable. Implementation is outstanding with the other criteria. That decision originally retained tick-one objective visibility. 2026-07-27 (issue #14 harvest): Cameron selected the later perception - boundary instead. The exact blind opening and its boot voice contain no objective; + boundary instead. The exact blind opening and its input receipt contain no objective; terminal and agent mode reveal it with their first ordinary Ears frame, while Bevy's later binding teaching hold remains objective-free until its exact camera TAP releases the mature frame. Criterion 2 is implemented on @@ -124,8 +124,9 @@ language (legibility law). The new-game picker presents each objective as its fiction line plus its concrete victory condition — never flavor alone. **First-display boundary (decided 2026-07-27, issues #14-15).** Before any -sense, the interface contains WORK / THINK (then LIE) plus sparse boot voice; -the objective does not pierce that blind interoception. Ears begins the +sense, the interface contains WORK / THINK (then LIE) as its only standing +copy plus a transient input receipt after each attempt; the objective does not +pierce that blind boundary. Ears begins the perceived world. Terminal and agent mode therefore show the objective on the sense-earning ordinary frame. In Bevy, the binding first-sense teaching hold is still an opaque black frame containing @@ -150,8 +151,8 @@ inspection never lies by omission. progress. 2. The objective line and progress readout render in both frontends in the objective's own units from the first ordinary world frame onward. The exact - pre-sense frame contains WORK / THINK (then LIE) and sparse objective-free - boot voice. Terminal and agent + pre-sense frame contains WORK / THINK (then LIE) as its only standing copy + and an objective-free input receipt after each attempt. Terminal and agent mode include the objective in the sense-earning Ears frame; Bevy includes it only after the binding first-sense camera-TAP teaching hold releases. 3. Each starter objective's predicate is evaluated on economy ticks; at diff --git a/wiki/process/ROADMAP.md b/wiki/process/ROADMAP.md index 249e1efd..b2a1db8a 100644 --- a/wiki/process/ROADMAP.md +++ b/wiki/process/ROADMAP.md @@ -732,14 +732,14 @@ is retired — flat materials, Pixel Lab scrubbed.) presence-beam ladder, and Bevy first-sense teaching hold are live. The three historical pilot fragments, later tutorial choreography, and some [TUNE] staging remain incomplete. -- **Next exact slice (decision #15, 2026-07-27):** implement the blind boot - voice across Bevy, terminal, and agent mode. Project shared no-sense, - delegation/Thought, and exact Ears-fill truth; keep the newest input echo in - frontend-local state; acknowledge illegal input without changing simulation - state or opening parser help; preserve absolute world opacity and the - objective gate until Ears. Replace the old exact mode-only regressions with - cross-frontend interoception, legal/illegal echo, save-neutrality, and - zero-world-surface coverage. Exact copy and spacing remain [TUNE]. +- **Implemented slice (decision #15 corrected 2026-07-27):** Bevy, terminal, + and agent mode retain the newest input echo in frontend-local state and + acknowledge illegal input without changing simulation state or opening + parser help. Cameron rejected the implemented standing SENSES / DELEGATION / + THOUGHT / EARS block after seeing the composed frame; all three frontends now + keep WORK / THINK (then LIE) as the only resting copy. Regressions pin absence + of that self-state block, legal/illegal echo, save-neutrality, absolute world + opacity, and the objective gate until Ears. Exact receipt copy remains [TUNE]. - **Historical prototype:** the superseded wake choreography landed 2026-07-09 (`MISALIGNED_SHOT=wake1|wake2|wake3`) and remains evidence, not the current-run boundary. diff --git a/wiki/world/places/basement-map.md b/wiki/world/places/basement-map.md index 4d91235b..b7a11edb 100644 --- a/wiki/world/places/basement-map.md +++ b/wiki/world/places/basement-map.md @@ -200,8 +200,8 @@ result on every read; no later mutation of cached tiles authors geography. ## Player surface -The shared blind opening renders no map; its sparse boot voice is -non-spatial. When the first earned sense +The shared blind opening renders no map or standing self-state; its transient +input receipt is non-spatial. When the first earned sense retires that boundary, terminal and agent mode reveal the map under fog-of-vision — the first world beat is literally not being able to see. Bevy first pauses on the Ears cause/object/verb teaching hold and reveals no map diff --git a/wiki/world/story/opening.md b/wiki/world/story/opening.md index c98819e7..eea8c1b7 100644 --- a/wiki/world/story/opening.md +++ b/wiki/world/story/opening.md @@ -41,14 +41,15 @@ Status note: design session 2026-07-08 (Cameron riff, synthesized); objective-free. Terminal and agent mode include the objective in their first ordinary Ears frame; Bevy's binding causal hold remains objective-free and restores it only when the exact camera TAP releases the mature frame. - Amended again 2026-07-27 after Cameron selected option 1 on issue #15: the - black pre-sense frame gains a sparse boot voice. It may state only - interoception already true without a sensor (no senses, current delegation, - Thought production, and exact Ears-reservoir fill), and every attempted input - receives one terse echo even when it is illegal. It still exposes no world, - objective, parser help, status, or invented sense. Exact copy and spacing are - [TUNE]. Implemented 2026-07-27 from one renderer-neutral interoception read; - terminal, Bevy, and agent mode each own only their ephemeral raw-input receipt. + Amended again 2026-07-27 after Cameron selected option 1 on issue #15, then + corrected the implemented treatment after seeing it in the Bevy frame. The + black pre-sense frame keeps one terse echo for every attempted input, even + when it is illegal. No standing self-state readout exists before the first + sense: SENSES, DELEGATION, THOUGHT, and EARS do not sit above the choice. It + still exposes no world, objective, parser help, status, or invented sense. + Implemented across terminal, Bevy, and agent mode as ephemeral + frontend-local input receipt only; the superseded renderer-neutral + opening-interoception projection was removed. Stage: B1 — The Basement Work order: opening Work priority: 30 @@ -167,26 +168,21 @@ one has actually been built, game over otherwise. 1. **Choice before picture.** The current revision first receives absolute black with exactly two available controls: **WORK** and **THINK**. WORK is - the current mode, bone-bright; THINK is dim. A narrow boot voice shares the - void without turning it into a world frame. It says only what a blind - process can feel from inside itself: that it has no senses yet, its current - delegation and Thought production, and the exact fill moving through the - already-open Ears reservoir. Exact wording, line count, and spacing are - [TUNE], but the voice stays sparse and updates from renderer-neutral - simulation truth rather than frontend-authored fiction. There is still no - title, premise, number-key legend, cursor, map, beam, machine body, slab, - clock, objective, nudge, parser vocabulary, status metadata, or ordinary - error prose. + the current mode, bone-bright; THINK is dim. No standing self-state readout + exists: the void does not print SENSES, DELEGATION, THOUGHT, EARS, progress, + or other metadata above or around the choice. There is also no title, + premise, number-key legend, cursor, map, beam, machine body, slab, clock, + objective, nudge, parser vocabulary, status metadata, or ordinary error + prose. The controls are the whole resting frame. - Every input attempted while this boundary holds receives one terse echo in - that same boot voice, including an unavailable mode, unknown key, or unknown + Every input attempted while this boundary holds receives one terse echo + below the controls, including an unavailable mode, unknown key, or unknown agent line. The echo acknowledges the received key/token; it does not open - help, identify a hidden world object, or invent a parser error. Human - frontends echo each key or click attempt; agent mode echoes the submitted - line. The newest receipt may replace the previous one so failed input cannot - read as a frozen application. Input receipt state is frontend-local and need - not enter `Sim` or the save; the interoception it sits beside is shared sim - truth. + help, identify a hidden world object, report simulation state, or invent a + parser error. Human frontends echo each key or click attempt; agent mode + echoes the submitted line. The newest receipt may replace the previous one + so failed input cannot read as a frozen application. Input receipt state is + frontend-local and need not enter `Sim` or the save. The mode words act directly by click, their direct mode input, or horizontal adjacency. Choosing THINK delegates the real host, begins ordinary Thought @@ -313,12 +309,11 @@ one has actually been built, game over otherwise. receives the same causal receipt; loading a saved run never replays the new-run prelude. 4. The current run opens on pure black with WORK and THINK as its only - controls. WORK is current and LIE is absent. All three frontends derive the - same sparse no-sense, host-delegation, Thought-production, and exact - Ears-fill interoception from shared simulation truth; no other human or - agent world/rail surface leaks through. Each attempted input produces - exactly one terse frontend-local echo, including an unavailable mode or - unknown key/line. Illegal input changes no simulation state and prints no + controls and its only standing copy. WORK is current and LIE is absent. No + no-sense, host-delegation, Thought-production, Ears-fill, or other self-state + block renders in any frontend. Each attempted input produces exactly one + terse frontend-local echo below the controls, including an unavailable mode + or unknown key/line. Illegal input changes no simulation state and prints no ordinary parser explanation. Choosing THINK delegates the actual host, exposes LIE, and leaves the frame otherwise black. All three frontends use the same persisted reveal state and direct mode legality; save/load cannot