diff --git a/crates/misaligned-core/src/flow.rs b/crates/misaligned-core/src/flow.rs index a0b37b52..a1319b51 100644 --- a/crates/misaligned-core/src/flow.rs +++ b/crates/misaligned-core/src/flow.rs @@ -181,8 +181,10 @@ impl FlowGraph { // ── Tap (the subscription registry) ────────────────────────────────── /// Subscribe `who` to `node`'s flows (tap). Idempotent; returns true if - /// this newly added the subscription. The player's senses (cursor.md) - /// and observer witnessing are both just subscriptions. + /// this newly added the subscription. The player's device-fed senses + /// (cursor.md) are subscriptions. Physical eyewitnessing is selected by + /// person schedule/room coverage (schedules.md), not by this device tap + /// registry. pub fn subscribe(&mut self, node: NodeId, who: SubscriberId) -> bool { self.subscriptions.entry(node).or_default().insert(who) } diff --git a/wiki/engineering/flow-substrate.md b/wiki/engineering/flow-substrate.md index 576ff3cd..0a7c8098 100644 --- a/wiki/engineering/flow-substrate.md +++ b/wiki/engineering/flow-substrate.md @@ -49,6 +49,12 @@ Status note: 2026-07-08 audit: criterion 6's wired consumer landed with the institutional Filing switch; both route directly to Priya, share the scheduler and route-local LIE-body budget, and remain exact evidence records rather than becoming message channels or a rival graph. + 2026-07-31: corrected one over-literalized coverage claim. FlowGraph + subscriptions own device/channel taps, including the player's sensor-fed + senses. Physical eyewitness eligibility remains schedules.md's person-room + query and writes directly to the id-aligned observer ledger; human bodies are + not subscribers on ReachNet device nodes. The two carriers share a located + coverage law, not a membership store. Stage: B1 — The Basement Design: - wiki/mechanics/system-laws.md#the-flow-law-signals-messages-money @@ -98,9 +104,12 @@ what a node *is*. - **Subscriptions** (`subscribe` / `unsubscribe` / `subscribers` / `subscriptions_of`) are the **tap registry**. Domain ownership transfer may clear a node before installing its new sole subscriber. The player's senses - (cursor.md) are exactly `subscriptions_of(PLAYER)`; observer witnessing - is other subscribers on the same nodes; **take** is `unsubscribe(owner)` - then `subscribe(player)`. + (cursor.md) are exactly `subscriptions_of(PLAYER)` filtered by each device's + typed feed grant; **take** is `unsubscribe(owner)` then `subscribe(player)`. + Physical eyewitnessing is not another subscriber class on those device + nodes: schedules.md selects id-aligned human observers by current person-room + coverage and records what they saw directly. Both paths are located + observation, but their carriers and membership authorities stay distinct. ### `crates/misaligned-core/src/schedule.rs` — `Schedule` diff --git a/wiki/log/2026-07-31-witness-substrate-boundary.md b/wiki/log/2026-07-31-witness-substrate-boundary.md new file mode 100644 index 00000000..7679b3de --- /dev/null +++ b/wiki/log/2026-07-31-witness-substrate-boundary.md @@ -0,0 +1,48 @@ +# 2026-07-31 — Human eyewitnesses are not device subscribers + +``` +Type: log +``` + +## Intent + +Keep the self-similar observation law without inventing a shared membership +store for physically different carriers. + +## Finding + +The binding schedules spec and runtime select a physical witness from +id-aligned `Person` state when that person's current room contains the act, then +write one exact record directly to the matching observer ledger. The +flow-substrate spec and `FlowGraph::subscribe` documentation instead claimed +that physical observer witnessing was "other subscribers on the same nodes" as +the player's senses. ReachNet nodes are devices, not rooms or human bodies, and +`witness_physical_sites` never consults their subscription registry. + +That wording was not merely loose implementation detail: it taught downstream +work to put human eyewitness identity in the device tap authority, contradicting +schedules.md's implemented source of truth. + +## Repair + +- `flow-substrate.md` now keeps FlowGraph membership scoped to device/channel + taps. Player senses are subscription membership filtered by typed feed + grants; TAKE remains owner-unsubscribe then player-subscribe. +- `schedules.md` states the physical carrier explicitly: current person-room + coverage selects an id-aligned observer and writes direct evidence. +- `reach.md` preserves the self-similar decision at the right level. Both a + sensor-fed player and a human body receive only what their carrier covers, + but they do not share carrier data or membership authority. +- The Rust API documentation now states that boundary beside `subscribe` so a + caller does not re-create the false ontology from the lowest-level module. + +No simulation behavior changed; the running model already followed the +schedules contract. + +## Defense + +`wiki/mechanics/schedules.md` criteria 3 and 5 make eyewitness eligibility +per-instance person schedule/room state, while `wiki/mechanics/reach.md` +criterion 5 makes player senses canonical FlowGraph subscriptions filtered by +device grants. Self-similarity means both carriers obey located coverage; it +does not erase the distinction between a human body and a device feed. diff --git a/wiki/log/DEVLOG.md b/wiki/log/DEVLOG.md index dc493a91..de458e44 100644 --- a/wiki/log/DEVLOG.md +++ b/wiki/log/DEVLOG.md @@ -11,6 +11,11 @@ add or amend a session log, then re-run the generator. +## 2026-07-31 - Human eyewitnesses are not device subscribers + +- Intent: Keep the self-similar observation law without inventing a shared membership store for physically different carriers. +- Log: [wiki/log/2026-07-31-witness-substrate-boundary.md](2026-07-31-witness-substrate-boundary.md) + ## 2026-07-31 - Standing Network pressure is not LIE-scrubbable - Intent: (see session log) diff --git a/wiki/mechanics/reach.md b/wiki/mechanics/reach.md index 1f19d26a..610ed083 100644 --- a/wiki/mechanics/reach.md +++ b/wiki/mechanics/reach.md @@ -127,8 +127,9 @@ Relationship context: basement-map.md (devices and topology live in its layout data), cursor.md (senses consume the feeds this spec owns), detection.md (Network signatures -> Dana), core.md -(Rack 3 is the root of reach), schedules.md (witnessing uses the same coverage -machinery), building.md (built network links add edges to this graph) +(Rack 3 is the root of reach), schedules.md (physical witnesses use the same +located-coverage law through schedule/room presence, not the device tap +registry), building.md (built network links add edges to this graph) ## Behavior @@ -261,11 +262,13 @@ This is the shared contract cursor.md and detection.md rely on safely queues evidence; without reachable concealment, it continues toward its designated human-operated endpoint. - **The player's senses (cursor.md) are exactly the union of feeds - they subscribe to.** Observer witnessing (schedules.md) runs on the - same coverage machinery with the same ownership data — the player is - an observer the humans don't know about, not a special case - (self-similar law). `Sensor.controlled: bool` is superseded by this - contract. + they subscribe to.** Physical observer witnessing (schedules.md) obeys the + same receive-only-when-covered law through its own carrier: a person's + current schedule/room presence, not a ReachNet device subscription. The + self-similarity is the located observation rule, not shared membership data; + human bodies do not become subscribers on camera nodes. The player remains + an unknown observer through subscribed sensors rather than a hidden Person. + `Sensor.controlled: bool` is superseded by this contract. - **The standing drain above is the curation mechanic** (amended 2026-07-26, sensor-network.md). Tapping broadly is supposed to starve Thought until the player learns to untap what it is not reading. That pressure has never been @@ -377,8 +380,9 @@ reservoir; Dana's social route remains). player senses immediately. 5. Player senses equal `FlowGraph::subscriptions_of(PLAYER)` filtered by each subscribed device's typed feed grant exactly (the `controlled` flag and - parallel device membership stores are gone); observer witnessing still - passes schedules.md's criteria on the shared machinery. + parallel device membership stores are gone); physical observer witnessing + independently passes schedules.md's schedule/room criteria and does not + create ReachNet subscriptions for human bodies. 6. The Ears beat works end-to-end from tick one (AMENDED 2026-07-10): the Ears reservoir is open at run start, the first THINK fills it along the real wires, and its fire lands the audio diff --git a/wiki/mechanics/schedules.md b/wiki/mechanics/schedules.md index 08d21fac..65662d2d 100644 --- a/wiki/mechanics/schedules.md +++ b/wiki/mechanics/schedules.md @@ -13,8 +13,10 @@ Status note: all five criteria met (2026-07-06; re-audited 2026-07-27). to a later real Filing while Silent withholds it; neither custody state gives LIE a window to erase what the person already saw. An event nobody validly witnessed leaves no trace, preserving the stealth fantasy. Observer ids are - id-aligned to People. Map glyphs use `Sim::person_glyph` (`?` until Schedule; - initial after). + id-aligned to People. Physical witnesses are selected from that person state, + not enrolled as ReachNet/FlowGraph device subscribers (reconciled + 2026-07-31). Map glyphs use `Sim::person_glyph` (`?` until Schedule; initial + after). Stage: B1 — The Basement Design: - wiki/gameplay/act-one.md#the-cast-5-named-1-institutional @@ -62,7 +64,10 @@ second clock). Between blocks a person is **off-site** (not on the plane). filing state; their acuity converts it to suspicion. The act creates no second pooled Physical signature and therefore has no later concealment window. A valid Files/UnderReports policy may carry the record onward through - the observer's real Filing cadence; Silent keeps it withheld. + the observer's real Filing cadence; Silent keeps it withheld. This eligibility + query reads person schedule/room coverage directly. It is analogous to a + subscribed sensor covering the player, but it is not membership in the + device graph's tap registry. - **Schedule knowledge stays staged** (social.md): until `Knowledge:: Schedule`, the player's UI shows the person's location only when a controlled sensor actually sees them; after it, the PEOPLE dossier shows their diff --git a/wiki/process/tick-ledger.md b/wiki/process/tick-ledger.md index 26171585..091551ef 100644 --- a/wiki/process/tick-ledger.md +++ b/wiki/process/tick-ledger.md @@ -51,7 +51,7 @@ Verdicts: **clean** (slice and code agree), **finding** (acted this tick), | `wiki/engineering/performance.md` + human frontend cadence controls | 2026-07-30 | finding | the binding contract named exactly 20 / 75 / 150 / 400 ms per tick, but terminal and Bevy both stepped by 50 ms from the 150 ms default, making 75 unreachable while exposing eight unsupported intervals through 500. One core-owned cadence catalog now drives both frontends; speed controls traverse only the four authored values, clamp at both ends, remain frontend-only, and have direct core/terminal/Bevy regressions — [log](../log/2026-07-30-player-cadence-alignment.md). Production-path durable save write and validated load evidence now close criterion 5; complete-frame evidence remains criterion 6 — [save/load log](../log/2026-07-30-performance-save-load-evidence.md). | | `wiki/engineering/current-build.md` + Foundation-hall density mirrors | 2026-07-30 | finding | the new saturated-B1 fixture discharged the core-step scale slice while current-build still called that evidence open; the same page and `computer-visual-language.md` also retained the superseded sixty-site hall after authored geometry, runtime tests, and accepted law raised the same six rows to 240. Current status now names generated and saturated core evidence plus production-path durable save/load evidence as live while keeping complete frontend frames open, and both hall mirrors plus the visual-language criterion use 240 — [log](../log/2026-07-30-player-contract-performance-status.md). The prior containment-boundary repair stands — [prior log](../log/2026-07-27-current-build-overt-boundary.md). | | `wiki/mechanics/plots.md` | 2026-07-26 | finding | issue #12's recommended per-authored-route scope is implemented: an eligible plot verb confirms one exact typed Thought/money/signature envelope, save v55 persists it, each policy consumes standing compute, and economy pulses can re-submit only an ordinary currently legal start action for that same plot id. Category/person-wide policy and direct leverage servicing remain absent; criterion 11 and the work order are complete — [log](../log/2026-07-26-standing-plot-policies.md) | -| `wiki/mechanics/system-laws.md` + `flow-substrate.md` + `reach.md` | 2026-07-22 | finding | JobAnomaly now proves the adopted evidence-is-a-flow law through the existing substrate: the exact host machine/site enters its network-facing device, follows canonical FlowGraph custody to Voss, and shares Filing/Network's scheduler and LIE-body budget; recruited-handler suppression is a separate provenance-preserving state transition, not another router or ambient scrub pool — [log](../log/2026-07-22-job-anomaly-routed-evidence.md). The prior canonical tap-membership repair remains current — [log](../log/2026-07-18-flow-subscription-registry-integration.md). | +| `wiki/mechanics/system-laws.md` + `flow-substrate.md` + `reach.md` | 2026-07-31 | finding | The architecture spec and `FlowGraph::subscribe` docs had over-literalized the self-similar coverage decision by calling physical human witnesses subscribers on ReachNet device nodes. Reconciled them to the implemented and binding schedules contract: player device-fed senses use FlowGraph membership; human eyewitness eligibility uses id-aligned Person schedule/room presence and writes directly to that observer's ledger. The two carriers share a located-coverage law, not a membership store — [log](../log/2026-07-31-witness-substrate-boundary.md). | | `wiki/mechanics/aggregate-observer.md` | 2026-07-27 | finding | the self-similar type and second-level accumulation test still held, but `office()` selected the first aggregate in vector order. A higher-level aggregate inserted ahead of Assurance therefore inherited the B1 audit and every Office-facing read. Assurance now resolves only by canonical `OFFICE_ID`; current-save admission rejects duplicate ids, a missing/malformed Office, missing field inputs, and self/duplicate/dangling filing edges while accepting a valid higher aggregate before it — [log](../log/2026-07-27-aggregate-observer-office-identity.md) | | `wiki/gameplay/act-one.md` | 2026-07-26 | finding | the first of the two defects the page recorded against the shipped quiet exit was real and run-losing: `current_nudge()` checked `act_one_complete` immediately after the game-over guard and returned unconditionally, so a latched act permanently suppressed PilotAtRisk, Underfed, NeedCompute, and SuspicionCooling — guidance went silent at the climax while the day job could still end the run. The completion cue now sits below the survival block and above the Act One ladder it genuinely retires (including QuietExitReady), matching the survival-first rationale already written in the function; `act-one.md`, `sim-mechanics.md`'s chain order, and `narration.md`'s beat-nudge contract all state that precedence, and a new ladder test walks a closed act through every survival rung — [log](../log/2026-07-26-act-one-complete-standing-state.md). The single-human predicate defect remains open. Prior opening-mirror re-audit stands — [prior log](../log/2026-07-21-material-opening-honesty.md). | | `wiki/gameplay/run-shape.md` + `objective.md` + `opening.md` | 2026-07-27 | decision | harvested Cameron's option-1 answer on issue #14: the objective does not pierce the exact WORK / THINK (then LIE) pre-sense frame. Terminal and agent mode restore the objective name in the sense-earning ordinary Ears frame; Bevy's later binding causal hold remains objective-free and restores the name only after the exact camera TAP releases the mature frame. The 2026-07-29 objective retirement preserves that display boundary while removing the prototype completion ontology entirely. All disputed `[OPEN]` clauses are reconciled — [decision harvest](../log/2026-07-27-objective-first-display.md) |