diff --git a/.claude/board/ISSUES.md b/.claude/board/ISSUES.md index 8aa539c51..435ba8e4e 100644 --- a/.claude/board/ISSUES.md +++ b/.claude/board/ISSUES.md @@ -1,6 +1,6 @@ ## ISS-MAILBOX-ROUTES-WITNESS-WITHOUT-GRAPH — `MailboxSoA` accepts same-slot edges from any graph (2026-10-06) -**Status:** OPEN. **Basis:** TEST-PINNED in `cognitive-shader-driver/examples/spog_witness_probe.rs` +**Status:** RESOLVED 2026-10-06 as not a `MailboxSoA` defect (D-ALPHA-G-0, `alpha_world_provenance_probe`): the cross-graph delivery is constructed by bypassing the Alpha split tunnel. The world is selected upstream by `SpogTenants` (route to `graph_of(addr)`, `NoTenant` for an undeclared world); `MailboxSoA` works inside an already-selected world and stays graph-blind; `apply_edges` has no production caller. Neither closing option below is taken, and no G check goes into `apply_edges`. The residue moves upstream: the attention-to-edge join does not exist yet, and when it is built it must feed mailboxes from the tunnel's per-world output, as the probe does (OPEN in the D-ALPHA-G-0 entry). The bullets below record the issue as filed. **Basis:** TEST-PINNED in `cognitive-shader-driver/examples/spog_witness_probe.rs` (`across_graphs_routing_diverges_from_the_spog_reading`). `MailboxSoA::apply_edges` compares only `edge.w_slot()` with the mailbox's slot and reads no classid. diff --git a/.claude/board/STATUS_BOARD.md b/.claude/board/STATUS_BOARD.md index bdca5cf21..ea167735d 100644 --- a/.claude/board/STATUS_BOARD.md +++ b/.claude/board/STATUS_BOARD.md @@ -36,7 +36,9 @@ Plan: `.claude/plans/2026-10-06-global-sudoku-replayable-orchestration-v1.md`. O | **D-GSO-7** | P7: reasoning-band earning and downgrade | Shipped (#1360) | `cognitive-shader-driver/examples/reasoning_band_probe.rs`: `ReasoningBand` (bits 61..63) read only via `band_reading::project_band`; earned one rung per executed passing proof under the shipped Pearl `CausalMask` (SO majority → Association, PO intervention trial passed → Causal, SPO removal attack passed → Counterfactual), outcomes executed from trial data and never supplied, no skipping, `NotRun` never raises; failed test, contradicting `Quorum` (minority caps at Association, majority drops to Surface) and `simpsons_paradox_risk` lower it; replay gives the same edge bits; unreadable provenance / undeclared / band-absent refuse; ladder and thresholds are policy pins; 7 tests, 10 disable runs red | | **D-GSO-7a** | P7a: the reasoning band as a relational certification (supersedes the meaning of D-GSO-7's rungs; #1360 unchanged) | Shipped (#1369) | `cognitive-shader-driver/examples/relational_certification_probe.rs`: a reading declared per class over bits 61..63 (`0 Open, 1 Associated, 2 Related, 3 Contributes, 4 CausalCandidate, 5 Causes`, 6..7 refuse; a class declared under the historical reading refuses the same bits); contracts are integer folds over unit masks + `causal_audit::SupportLedger` (2 distinct sources; the robustness mask only refutes; `Causes` = 2 distinct `InterventionBacked` sources + executed randomized arms); `entails` is an explicit table equal to `code >=` on 0..=5 only; repetition, observational effect size, the inference mantissa and confounded observational data never raise or demote past their contract; exhaustive 2,500-model family: 0 chain violations with scoped association, 10 with marginal (Simpson); sibling specificity and removal (overdetermination) are shown not to be rungs; only receipts recorded at or before the model's seal count, so a later receipt cannot change an earlier seal's replay; 13 tests, 12 disable runs red | | **D-GSO-AFF-0** | Affordance measurement: `CausalEdge64 × RecipeLaw[0..63] → EligibleRecipes: u64` | Shipped (#1370) | `cognitive-shader-driver/examples/affordance_measurement_probe.rs`: bits 59..63 read as one EpistemicState5 code (`spare() << 2 \| truth_raw()`, 10 declared codes, non-monotone, 22 refuse) + Pearl3; 7 recipes as `requires`/`forbids` facts + Pearl planes, compiled at build time to `[u64; 32]` × `[u64; 8]`; measure = 2 lookups + AND, 0 allocations; F1 determinism and law-generation dependence, F2 relevant factor flips its bit, F3 S/P/O/F/C/43..45/mantissa/plasticity/witness swept with no change, F4/F5 tables agree bit-for-bit with an independent rule re-derivation that names every refusal, F6/F7 preference only clears, half-field writes to 59..60 yield refusing codes; v1 / unknown provenance refuses (a v1 row with temporal 128 would read as `Causes`); no scheduler/task/capability object; 9 tests, 8 disable runs red | -| **D-SPOG-W-0** | Witness slot as a SPOG sub-context under classid-G | In PR | `cognitive-shader-driver/examples/spog_witness_probe.rs`: SPOG view = (S/P/O blind bytes, G = `graph_of(classid)`, sub = `w_slot()` under a per-class declared reading, slot 0 = no anchor); undeclared class, another slot reading and v1 / unknown provenance refuse; G never moves with the slot; real `MailboxSoA::apply_edges` routing agrees with the reading on all 64 × 64 slot pairs within one graph and diverges across graphs (routing reads no classid; `ISS-MAILBOX-ROUTES-WITNESS-WITHOUT-GRAPH`); 0 allocations; 7 tests, 6 disable runs red | +| **D-SPOG-W-0** | Witness slot as a SPOG sub-context under classid-G | Shipped (#1371) | `cognitive-shader-driver/examples/spog_witness_probe.rs`: SPOG view = (S/P/O blind bytes, G = `graph_of(classid)`, sub = `w_slot()` under a per-class declared reading, slot 0 = no anchor); undeclared class, another slot reading and v1 / unknown provenance refuse; G never moves with the slot; real `MailboxSoA::apply_edges` routing agrees with the reading on all 64 × 64 slot pairs within one graph and diverges across graphs (routing reads no classid; `ISS-MAILBOX-ROUTES-WITNESS-WITHOUT-GRAPH`, since resolved as a false positive by D-ALPHA-G-0: the cross-graph case bypasses the Alpha split tunnel); 0 allocations; 7 tests, 6 disable runs red | +| **D-ALPHA-G-0** | WorldG as Alpha-route provenance, not a CE64 field | In PR | `cognitive-shader-driver/examples/alpha_world_provenance_probe.rs`: event = (Alpha-attended address, CE64); WorldG = `graph_of(addr)`, order = `SpogTenants` route (`merge_in_claim_order`); same CE64 bits in two worlds = two events; replay of the same claims recovers the world sequence with all-zero edges; changing CE64 fields never moves the world while the events change; fed from the tunnel's per-world shadows each `MailboxSoA` holds only its own deliveries through the unchanged `apply_edges`; an undeclared world is refused at the tunnel (`NoTenant`). No production caller of `apply_edges` exists, so "no mixing" is absence of a path; 5 tests, 5 disable runs red | +| **D-WA-0** | Witness × Angle as a declared sparse local source coordinate | In PR | `cognitive-shader-driver/examples/witness_angle_probe.rs`: `(class, generation, w_slot, direction bits 43..45) → SourceCoord` under a probe-local sparse law (6 entries); same bits mean different sources in another class of the same world, in another world and in another generation; undeclared class, a class reading the bits as pathology triad or cohort `WitnessTable`, an undeclared generation, Witness 0 and v1/unknown provenance refuse; other CE64 fields never move the coordinate; world from the attended key, never the edge; 0 allocations; 7 tests, 8 disable runs red | | **D-GSO-8** | P8: seal boundary | Shipped (#1363) | `lance-graph-planner/examples/seal_boundary_probe.rs`: internal events change only working rows; a declared `Boundary` event freezes the changed rows with the shipped `DetachedCycleBatch::freeze` into a local ledger (no `WalSink`); an unchanged boundary writes nothing; replaying the persisted events from each prior seal reproduces the next seal exactly (frame, landings, image, hash); wrong base, dropped event and swapped order each change the seal; tie limit handled by plan option 1: the key is the event's own durable unique `seq`, a tied batch is refused, and a test shows on the real `freeze` that tied keys make the seal arrival-dependent; 6 tests, 5 disable runs red. Follow-up: `apply` refuses a `seq` not greater than the last (a reuse on one row or across seals escaped `first_tie`), `resume_after` restores the top persisted key; 7 tests, 2 more disable runs red | ## D-PLX — Population-law cross-check (2026-10-03) diff --git a/.claude/board/entries/2026-10-06-alpha-world-provenance-and-witness-angle.md b/.claude/board/entries/2026-10-06-alpha-world-provenance-and-witness-angle.md new file mode 100644 index 000000000..69e53c4f0 --- /dev/null +++ b/.claude/board/entries/2026-10-06-alpha-world-provenance-and-witness-angle.md @@ -0,0 +1,71 @@ +# 2026-10-06 — D-ALPHA-G-0 + D-WA-0: WorldG from the Alpha route; Witness × Angle as a declared local source + +## VERIFIED-IN-CODE — inventory (main @ 705509fe) + +1. **Where WorldG is selected.** `lance_graph_contract::spog_tenants`: + `graph_of(addr) = classid >> 16` (`spog_tenants.rs:41`) and + `SpogTenants::claim` (`:167`), which routes an attended address to the tenant + of its world and returns `TenantClaim::NoTenant` for an undeclared one. + `AlphaTunnel` (`alpha_tunnel.rs`) is the same split tunnel keyed by rung, not + by world. +2. **What preserves G across the saccade.** Every claimed row keeps the base + row's `NodeGuid` byte-for-byte (`alpha.rs` `claim`), so the world is in the + attention record. `SpogTenants::route` records the world of each fresh claim; + `merge_in_claim_order` replays the saccade in time. +3. **Can two worlds feed one `MailboxSoA` in production?** No path exists: + `MailboxSoA::apply_edges` has no production caller (only its own tests and + the probes). The driver's mailbox backing expects at most one designated + mailbox (`debug_assert` under `mailbox-thoughtspace`, `driver.rs:208`; + multi-mailbox routing is the unbuilt W5). Nothing connects `SpogTenants` or + `AlphaTunnel` to a mailbox. +4. **#1371's divergence** is constructible only, by handing a foreign-world edge + to `apply_edges` directly. +5. **Where the split tunnel is tested.** `alpha_tunnel.rs` (parallel == + sequential, byte-identical; cross-rung revisit counting) and + `spog_tenants.rs` (tenant isolation, claim-order replay). +6. **Saccade provenance exists:** `AlphaStamp` (cycle, seq, rung, visits) plus + `SpogTenants::route`. +7. **G recoverable on replay without CE64:** yes, from the attended key and the + route. +8. **16-byte hosts for an explicit row-local SPOG later:** `Register128` + (classid-free, meaning from the resolved SPOG context), the 4 + 12 + `FacetCascade` (also the edge block), `Quad8`. None carries a LocalG today. +9. **Odoo/ERP LocalG:** none at runtime. `company_id` exists only as a + blueprint field (`odoo_blueprint/l3.rs`); the Odoo hydrator keys an OWL + context bundle by namespace. +10. **Witness (53..58) and bits 43..45** are disjoint and readable together + without moving bits. Both already have shipped readings that must refuse a + new one: bits 43..45 = pathology triad (`direction()`), bits 53..58 = + cohort `WitnessTable` index (`witness_table.rs`, not wired). + +## MEASURED + +- `alpha_world_provenance_probe.rs`: 5 tests, 5 disable runs red (world read + from the edge, grouped merge instead of the route, all deliveries to one + mailbox, a mixed received count, `NoTenant` accepted). The first mailbox + disable came back green; the test now reads each mailbox's own + `plasticity_at` counts. After review (#1372) the mailbox deliveries are built + from the tunnel's per-world shadows (`tenant(w).scanpath()`), not routed by + the test; feeding both mailboxes from one shadow fails it. +- `witness_angle_probe.rs`: 7 tests, 8 disable runs red (law ignores class, + ignores generation, reading check off, generation check off, Witness 0 + accepted, v1 accepted, Angle read from other bits, law keyed by world instead + of class); 0 allocations. The world-keyed disable needed a second + source-coordinate class in the same world, added after review (#1372). + +## RESOLVED + +`ISS-MAILBOX-ROUTES-WITNESS-WITHOUT-GRAPH`: not a `MailboxSoA` defect. +`MailboxSoA` stays graph-blind; no G check in `apply_edges`. The residue is the +unbuilt join below. + +## OPEN + +- Where production will join an attended address to the CE64 it produced: no + caller does this yet, so the event pairing exists only in the probe. When + built, it must feed mailboxes from the tunnel's per-world output (the probe's + `tenant(w).scanpath()` shape), never by re-deriving the world itself. +- Whether `graph_of` is the right WorldG granularity for every consumer. +- Whether the Witness × Angle declaration (and the D-SPOG-W-0 one) becomes a + contract declaration beside `band_reading`. +- LocalG (row-local SPOG G in a 16-byte register): not modelled. diff --git a/.claude/board/entries/README.md b/.claude/board/entries/README.md index 273492e43..ac581e4f4 100644 --- a/.claude/board/entries/README.md +++ b/.claude/board/entries/README.md @@ -25,7 +25,7 @@ index row, (3) no duplicate entry id. Checks 1 and 2 are deliberately opposite directions; the stranding this convention prevents shows up in exactly one of them, never both. -232 entries, 2026-08-06 .. 2026-10-06. +233 entries, 2026-08-06 .. 2026-10-06. | date | entry id | finding | file | |---|---|---|---| @@ -41,6 +41,7 @@ exactly one of them, never both. | 2026-10-06 | `diff-plateau-as-expression-round5` | | [2026-10-06-diff-plateau-as-expression-round5.md](2026-10-06-diff-plateau-as-expression-round5.md) | | 2026-10-06 | `dav-resident-reading-round2` | | [2026-10-06-dav-resident-reading-round2.md](2026-10-06-dav-resident-reading-round2.md) | | 2026-10-06 | `dav-carrier-invariance-quack` | | [2026-10-06-dav-carrier-invariance-quack.md](2026-10-06-dav-carrier-invariance-quack.md) | +| 2026-10-06 | `D-ALPHA-G-0` | | [2026-10-06-alpha-world-provenance-and-witness-angle.md](2026-10-06-alpha-world-provenance-and-witness-angle.md) | | 2026-10-06 | `D-GSO-AFF-0` | | [2026-10-06-affordance-measurement.md](2026-10-06-affordance-measurement.md) | | 2026-10-05 | `text-to-numeric-boundary-inventory` | | [2026-10-05-text-to-numeric-boundary-inventory.md](2026-10-05-text-to-numeric-boundary-inventory.md) | | 2026-10-05 | `report-pair-key-and-stack-recon` | | [2026-10-05-report-pair-key-and-stack-recon.md](2026-10-05-report-pair-key-and-stack-recon.md) | diff --git a/crates/cognitive-shader-driver/Cargo.toml b/crates/cognitive-shader-driver/Cargo.toml index 3d061ce15..e17400d24 100644 --- a/crates/cognitive-shader-driver/Cargo.toml +++ b/crates/cognitive-shader-driver/Cargo.toml @@ -112,6 +112,16 @@ test = true name = "spog_witness_probe" test = true +# D-ALPHA-G-0 WorldG-as-Alpha-route provenance probe; tests run under `cargo test`. +[[example]] +name = "alpha_world_provenance_probe" +test = true + +# D-WA-0 Witness x Angle declared local source coordinate probe; tests run under `cargo test`. +[[example]] +name = "witness_angle_probe" +test = true + [dependencies] lance-graph-contract = { path = "../lance-graph-contract" } # Read-only ontology registry (Phase 7, v4 plan). default-features = false so the diff --git a/crates/cognitive-shader-driver/examples/README.md b/crates/cognitive-shader-driver/examples/README.md index 977056978..c782bcaa1 100644 --- a/crates/cognitive-shader-driver/examples/README.md +++ b/crates/cognitive-shader-driver/examples/README.md @@ -222,12 +222,42 @@ inside G only for classes that declare that reading (slot 0 = no anchor), and S/P/O passed through as blind bytes. Undeclared classes, another reading of the slot, and v1 / unknown provenance refuse. Compared with the real `MailboxSoA::apply_edges` routing: they agree on all 64 × 64 slot pairs within -one graph and diverge across graphs, because routing reads no classid. +one graph and diverge across graphs, because routing reads no classid. That +cross-graph case bypasses the Alpha split tunnel and is not a production path +(D-ALPHA-G-0 below). ```bash cargo run -p cognitive-shader-driver --example spog_witness_probe ``` +## alpha_world_provenance_probe.rs + +D-ALPHA-G-0. WorldG is attention provenance carried by the Alpha route, not a +CausalEdge64 field. An event is (Alpha-attended address, edge); WorldG is +`graph_of(addr)` and the order of worlds is the `SpogTenants` route. The same +edge bits in two worlds are two events; replaying the same claims recovers the +world sequence with all-zero edges; changing edge fields never moves the world. +Partitioned by recovered world, each `MailboxSoA` receives only its own +deliveries through the unchanged `apply_edges`; an undeclared world is refused +at the tunnel. + +```bash +cargo run -p cognitive-shader-driver --example alpha_world_provenance_probe +``` + +## witness_angle_probe.rs + +D-WA-0. Witness (`w_slot`) × Angle (bits 43..45) as a declared, sparse local +source coordinate under a per-class, versioned probe law. The same raw pair +means different sources in another class and another generation; classes +reading those bits as the pathology triad or a cohort `WitnessTable` refuse, as +do undeclared classes and generations, Witness 0 and v1 / unknown provenance. +The world comes from the attended key, never from the edge. + +```bash +cargo run -p cognitive-shader-driver --example witness_angle_probe +``` + ## ewa_anisotropic_probe.rs D-CTX-3. Anisotropic EWA: the footprint is each virtual surfel's normalised diff --git a/crates/cognitive-shader-driver/examples/alpha_world_provenance_probe.rs b/crates/cognitive-shader-driver/examples/alpha_world_provenance_probe.rs new file mode 100644 index 000000000..dde6d24dc --- /dev/null +++ b/crates/cognitive-shader-driver/examples/alpha_world_provenance_probe.rs @@ -0,0 +1,388 @@ +//! D-ALPHA-G-0: WorldG is attention provenance, carried by the Alpha route, +//! not by `CausalEdge64`. +//! +//! Claim under test: +//! +//! ```text +//! epistemic event = (Alpha-attended address, CausalEdge64) +//! WorldG = graph_of(address) read from the attended key +//! order of worlds = SpogTenants route which tenant took each fresh claim +//! CausalEdge64 = opaque epistemic delta carries no world and needs none +//! ``` +//! +//! # The seam used +//! +//! `lance_graph_contract::spog_tenants::SpogTenants` is the Alpha split tunnel +//! keyed by graph: one `AlphaOverlay` shadow per world over ONE +//! `AlphaAllocation`. `claim(addr)` routes to the tenant `graph_of(addr)`, +//! refuses an address whose world has no tenant (`TenantClaim::NoTenant`), +//! and records the world of every fresh claim in its `route`. +//! `merge_in_claim_order` replays the saccade in time. Every attended row keeps +//! the base row's key byte-for-byte, so the world is read from the attention +//! record itself. +//! +//! # What the probe shows +//! +//! - The same CE64 bits attended in two worlds are two different events. +//! - Replaying the same claims on a fresh tunnel recovers the world sequence, +//! with all-zero edges, so no world can have come from the edge. +//! - Changing every CE64 field leaves the recovered worlds unchanged, while +//! the events themselves change. +//! - Fed from the tunnel's per-world shadows, each `MailboxSoA` receives only +//! its own world's deliveries and accepts all of them; `apply_edges` is +//! unchanged and reads no G. +//! - An address of an undeclared world is refused at the tunnel and never +//! becomes a delivery. +//! +//! # What it does NOT prove +//! +//! - That production delivers edges this way. `MailboxSoA::apply_edges` has no +//! production caller today and nothing connects `SpogTenants` to a mailbox, +//! so no production path mixes worlds at a mailbox. That is absence of a +//! path, not a guard on one; the multi-mailbox routing that would become one +//! (W5) is unbuilt. +//! - That `graph_of` (classid high half) is the right WorldG granularity for +//! every consumer; it is the canonical rule today (`spog_tenants`). +//! - Anything about a row-local SPOG G (LocalG); that is a separate +//! coordinate inside the selected world and is not modelled here. +//! +//! # Correction to D-SPOG-W-0 +//! +//! `spog_witness_probe`'s cross-graph case built a delivery from a foreign +//! world directly, bypassing this tunnel. It is a constructed case, not a +//! reachable one; `ISS-MAILBOX-ROUTES-WITNESS-WITHOUT-GRAPH` is reframed +//! accordingly, and `MailboxSoA` stays graph-blind. +//! +//! Run: `cargo run -p cognitive-shader-driver --example alpha_world_provenance_probe` +//! Tests: `cargo test -p cognitive-shader-driver --example alpha_world_provenance_probe` + +use causal_edge::edge::CausalEdge64; +use causal_edge::pearl::CausalMask; +use causal_edge::PlasticityState; +use cognitive_shader_driver::mailbox_soa::MailboxSoA; +use lance_graph_contract::alpha::{AlphaAddr, AlphaAllocation}; +use lance_graph_contract::canonical_node::{EdgeBlock, NodeGuid, NodeRow, TailVariant}; +use lance_graph_contract::spog_tenants::{graph_of, SpogTenants, TenantClaim}; + +/// Two worlds. Probe placeholders, not OGAR mints. +const W_OBS: u16 = 0x9101; +const W_ERP: u16 = 0x9102; +/// A world the spine carries but the tunnel below does not declare. +const W_IAM: u16 = 0x9103; + +/// Rows per world in the probe spine. +const PER_WORLD: u16 = 4; + +/// The Witness slot every probe mailbox and edge uses, so `apply_edges`'s own +/// slot filter never decides anything here. +const SLOT: u8 = 7; + +/// One attended row of world `w`, index `i`. Only the classid's high half is +/// the world; `heel` makes the keys distinct. +fn addr(w: u16, i: u16) -> AlphaAddr { + NodeGuid::mint_for(TailVariant::V3, (u32::from(w) << 16) | 1, i, 0, 0, 0, 0, 1) +} + +/// The base spine the allocation borrows: three worlds, interleaved, so the +/// world is never a slice range. +fn spine() -> Vec { + (0..PER_WORLD) + .flat_map(|i| [addr(W_OBS, i), addr(W_ERP, i), addr(W_IAM, i)]) + .map(|key| NodeRow { + key, + edges: EdgeBlock::default(), + value: [0u8; 480], + }) + .collect() +} + +fn edge(s: u8, p: u8, o: u8) -> CausalEdge64 { + CausalEdge64::pack_v2( + s, + p, + o, + 200, + 180, + CausalMask::SO, + 0b010, + PlasticityState::ALL_HOT, + ) + .with_inference_mantissa(1) + .with_w_slot(SLOT) +} + +/// One observation: attention landed at `addr` and produced `edge`. +#[derive(Debug, Clone, Copy)] +struct Observation { + addr: AlphaAddr, + edge: CausalEdge64, +} + +/// An epistemic event: the world the attention route supplies, plus the edge. +/// Transient; never stored. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +struct Event { + world: u16, + bits: u64, +} + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum Refusal { + /// The address's world has no tenant in this tunnel. + NoTenant(u16), + /// The substrate refused the address (not in the spine). + Substrate, +} + +/// Attend every observation through the split tunnel. The first refusal stops +/// the walk; claims made before it stand. +fn attend(tunnel: &mut SpogTenants<'_>, obs: &[Observation]) -> Result<(), Refusal> { + for o in obs { + match tunnel.claim(o.addr, 1) { + TenantClaim::Routed(..) => {} + TenantClaim::NoTenant(g) => return Err(Refusal::NoTenant(g)), + TenantClaim::Substrate(_) => return Err(Refusal::Substrate), + } + } + Ok(()) +} + +/// The events of a saccade: the world from the attended key, the delta from +/// the edge. +fn events(obs: &[Observation]) -> Vec { + obs.iter() + .map(|o| Event { + world: graph_of(o.addr), + bits: o.edge.0, + }) + .collect() +} + +/// The world sequence replayed from the tunnel alone: its route plus each +/// tenant's scanpath. No edge is consulted. +fn replay_worlds(tunnel: &SpogTenants<'_>) -> Vec { + tunnel + .merge_in_claim_order() + .into_iter() + .map(|(a, _)| graph_of(a)) + .collect() +} + +/// A saccade that switches worlds several times, one fresh claim per address. +fn saccade(edge_for: impl Fn(usize) -> CausalEdge64) -> Vec { + let path = [ + addr(W_OBS, 0), + addr(W_ERP, 0), + addr(W_ERP, 1), + addr(W_OBS, 1), + addr(W_ERP, 2), + addr(W_OBS, 2), + addr(W_OBS, 3), + ]; + path.iter() + .enumerate() + .map(|(i, &a)| Observation { + addr: a, + edge: edge_for(i), + }) + .collect() +} + +fn main() { + let rows = spine(); + let alloc = AlphaAllocation::over(&rows); + let mut tunnel = SpogTenants::over(&alloc, 1, &[W_OBS, W_ERP]); + let obs = saccade(|_| edge(1, 2, 3)); + attend(&mut tunnel, &obs).expect("both worlds declared"); + println!("D-ALPHA-G-0: WorldG from the Alpha route, not from CE64"); + println!(" events {:x?}", events(&obs)); + println!(" replayed worlds {:x?}", replay_worlds(&tunnel)); + let refused = attend( + &mut tunnel, + &[Observation { + addr: addr(W_IAM, 0), + edge: edge(1, 2, 3), + }], + ); + println!(" undeclared world -> {refused:?}"); + // Inside the selected world the mailbox is graph-blind: deliver the + // observations world W_OBS produced to that world's mailbox. + let mut mb: MailboxSoA<16> = MailboxSoA::new(1, SLOT, 0.5); + let own: Vec<(u16, CausalEdge64)> = tunnel + .tenant(W_OBS) + .map(|shadow| { + shadow + .scanpath() + .filter_map(|a| { + let e = obs.iter().find(|o| o.addr == a)?.edge; + Some((alloc.ordinal(a).unwrap_or(0) as u16 % 16, e)) + }) + .collect() + }) + .unwrap_or_default(); + println!( + " W_OBS mailbox accepted {} of {}", + mb.apply_edges(&own), + own.len() + ); +} + +#[cfg(test)] +mod tests { + use super::*; + + /// Same CE64 bits, two Alpha-selected worlds: two distinct events. + #[test] + fn same_ce64_bits_in_two_worlds_are_two_events() { + let e = edge(9, 9, 9); + let ev = events(&[ + Observation { + addr: addr(W_OBS, 0), + edge: e, + }, + Observation { + addr: addr(W_ERP, 0), + edge: e, + }, + ]); + assert_eq!(ev[0].bits, ev[1].bits, "same delta"); + assert_ne!(ev[0], ev[1], "different events"); + assert_eq!((ev[0].world, ev[1].world), (W_OBS, W_ERP)); + } + + /// The falsifier: replay of the same route over the same spine recovers + /// which world produced each observation, with edges that carry nothing. + #[test] + fn replay_recovers_the_world_sequence_without_the_edge() { + let rows = spine(); + let alloc = AlphaAllocation::over(&rows); + let obs = saccade(|_| CausalEdge64::ZERO); + let generated: Vec = obs.iter().map(|o| graph_of(o.addr)).collect(); + + let mut first = SpogTenants::over(&alloc, 1, &[W_OBS, W_ERP]); + attend(&mut first, &obs).unwrap(); + let mut again = SpogTenants::over(&alloc, 1, &[W_OBS, W_ERP]); + attend(&mut again, &obs).unwrap(); + + assert_eq!( + replay_worlds(&first), + generated, + "the route recovers the worlds" + ); + assert_eq!( + replay_worlds(&again), + generated, + "and does so again on replay" + ); + + // Anti-vacuity: the saccade switches worlds more than once, and the + // grouped merge (no route) gives a different order, so the route is + // what carries the sequence. + let switches = generated.windows(2).filter(|w| w[0] != w[1]).count(); + assert!(switches >= 3, "{switches} world switches"); + let grouped: Vec = first.merge().iter().map(|(a, _)| graph_of(*a)).collect(); + assert_ne!(grouped, generated, "grouping by world loses the order"); + } + + /// Stay-silent: changing CE64 fields does not move the recovered world, + /// while the events do change (so the edges are really in them). + #[test] + fn ce64_changes_do_not_move_the_world() { + let variants: [fn(usize) -> CausalEdge64; 5] = [ + |_| CausalEdge64::ZERO, + |i| edge(i as u8, 2, 3), + |i| edge(1, 2, 3).with_w_slot(i as u8 + 1), + |i| edge(1, 2, 3).with_inference_mantissa(-(i as i8)), + |_| CausalEdge64(u64::MAX), + ]; + let worlds: Vec> = variants + .iter() + .map(|f| events(&saccade(f)).iter().map(|e| e.world).collect()) + .collect(); + let bits: Vec> = variants + .iter() + .map(|f| events(&saccade(f)).iter().map(|e| e.bits).collect()) + .collect(); + assert!(worlds.iter().all(|w| *w == worlds[0]), "worlds never move"); + for i in 0..bits.len() { + for j in i + 1..bits.len() { + assert_ne!(bits[i], bits[j], "variants {i} and {j} differ in the edge"); + } + } + } + + /// Inside one already-selected world the mailbox needs no G: fed from the + /// tunnel's per-world shadows, each mailbox receives only its own world's + /// deliveries and accepts all of them, through the unchanged `apply_edges`. + #[test] + fn inside_one_world_the_mailbox_needs_no_g() { + let rows = spine(); + let alloc = AlphaAllocation::over(&rows); + let mut tunnel = SpogTenants::over(&alloc, 1, &[W_OBS, W_ERP]); + let obs = saccade(|i| edge(i as u8, 2, 3)); + attend(&mut tunnel, &obs).unwrap(); + + let worlds = [W_OBS, W_ERP]; + let mut boxes: [MailboxSoA<16>; 2] = + [MailboxSoA::new(1, SLOT, 0.5), MailboxSoA::new(2, SLOT, 0.5)]; + let mut received = [0usize; 2]; + let mut accepted = [0usize; 2]; + // Deliveries are built from the tunnel's routed output: each world's + // mailbox is fed only the addresses that world's tenant shadow holds, + // joined back to the edge observed there. The test never routes by + // itself. + for (k, &w) in worlds.iter().enumerate() { + let shadow = tunnel.tenant(w).expect("declared tenant"); + for a in shadow.scanpath() { + assert_eq!(graph_of(a), w, "the tunnel routed {a:?} to world {w:x}"); + let e = obs.iter().find(|o| o.addr == a).expect("observed").edge; + let row = alloc.ordinal(a).unwrap() as u16 % 16; + received[k] += 1; + accepted[k] += boxes[k].apply_edges(&[(row, e)]); + } + } + let expected = |w: u16| obs.iter().filter(|o| graph_of(o.addr) == w).count(); + assert_eq!(received, [expected(W_OBS), expected(W_ERP)]); + assert_eq!(accepted, received, "every in-world delivery is accepted"); + assert!(received.iter().all(|&n| n > 0), "both worlds deliver"); + // Read back from the mailboxes themselves: each holds exactly its own + // world's deliveries, so the partition happened before `apply_edges`. + let held = |b: &MailboxSoA<16>| { + (0..16) + .map(|r| usize::from(b.plasticity_at(r))) + .sum::() + }; + assert_eq!([held(&boxes[0]), held(&boxes[1])], received); + } + + /// An address from a world the tunnel does not serve is refused upstream + /// and never reaches a mailbox; an address outside the spine likewise. + #[test] + fn a_foreign_world_is_refused_at_the_tunnel() { + let rows = spine(); + let alloc = AlphaAllocation::over(&rows); + let mut tunnel = SpogTenants::over(&alloc, 1, &[W_OBS]); + let foreign = Observation { + addr: addr(W_IAM, 0), + edge: edge(1, 2, 3), + }; + assert_eq!( + attend(&mut tunnel, &[foreign]), + Err(Refusal::NoTenant(W_IAM)) + ); + let outside = Observation { + addr: addr(W_OBS, 99), + edge: edge(1, 2, 3), + }; + assert_eq!(attend(&mut tunnel, &[outside]), Err(Refusal::Substrate)); + assert_eq!(tunnel.claimed_len(), 0, "nothing was attended"); + + // Silent twin: an address of the served world is accepted. + let own = Observation { + addr: addr(W_OBS, 0), + edge: edge(1, 2, 3), + }; + assert_eq!(attend(&mut tunnel, &[own]), Ok(())); + assert_eq!(tunnel.claimed_len(), 1); + } +} diff --git a/crates/cognitive-shader-driver/examples/spog_witness_probe.rs b/crates/cognitive-shader-driver/examples/spog_witness_probe.rs index 29c3ed624..79b378f26 100644 --- a/crates/cognitive-shader-driver/examples/spog_witness_probe.rs +++ b/crates/cognitive-shader-driver/examples/spog_witness_probe.rs @@ -25,11 +25,17 @@ //! //! - **Within one G they agree** on all 64 × 64 slot pairs, including slot 0 //! (unanchored mailbox accepts unanchored edges). -//! - **Across graphs they diverge.** `apply_edges` reads no classid, so a -//! mailbox accepts an edge from another graph that happens to carry the same -//! slot value, while the SPOG reading places it in a different context. The -//! agreement therefore holds only for a mailbox scoped to one graph; nothing -//! in `MailboxSoA` enforces that today. Pinned as a test, not fixed here. +//! - **Across graphs they diverge** when a foreign-graph edge is handed to the +//! mailbox directly. `apply_edges` reads no classid, so it accepts an edge +//! carrying the same slot value that the SPOG reading places elsewhere. +//! +//! ⊘ Corrected by D-ALPHA-G-0 (`alpha_world_provenance_probe`): that case is +//! constructed by bypassing the Alpha split tunnel and is not a production +//! path. The world is selected upstream (`SpogTenants` routes each attended +//! address to the tenant `graph_of(addr)` and refuses an undeclared world), and +//! `MailboxSoA` operates inside an already-selected world and stays graph-blind. +//! `apply_edges` has no production caller today. The earlier reading here, +//! that agreement needs a graph check in the mailbox, is withdrawn. //! //! # Not decided here //! @@ -37,7 +43,8 @@ //! `band_reading`-style contract declaration is open. //! - What a sub-context ordinal means (corpus, frame, schema) is the //! consumer's binding, not this probe's. -//! - Making `MailboxSoA` graph-aware is a production change and out of scope. +//! - Making `MailboxSoA` graph-aware: rejected by D-ALPHA-G-0; G is attention +//! provenance, not an edge-local routing field. //! //! Run: `cargo run -p cognitive-shader-driver --example spog_witness_probe` //! Tests: `cargo test -p cognitive-shader-driver --example spog_witness_probe` @@ -319,8 +326,11 @@ mod tests { /// Across graphs they diverge: the mailbox reads no classid, so it accepts /// an edge from another graph carrying the same slot, which the SPOG - /// reading places in a different context. Agreement needs a mailbox scoped - /// to one graph. + /// reading places in a different context. + /// + /// A constructed case: the foreign edge is delivered directly, bypassing + /// the Alpha split tunnel that selects the world upstream (D-ALPHA-G-0). + /// It pins what `apply_edges` does with such input, not a reachable path. #[test] fn across_graphs_routing_diverges_from_the_spog_reading() { let mailbox_ctx = (0x9101u16, sub_context(23)); diff --git a/crates/cognitive-shader-driver/examples/witness_angle_probe.rs b/crates/cognitive-shader-driver/examples/witness_angle_probe.rs new file mode 100644 index 000000000..35193fb5b --- /dev/null +++ b/crates/cognitive-shader-driver/examples/witness_angle_probe.rs @@ -0,0 +1,401 @@ +//! D-WA-0: Witness × Angle as a declared, sparse local source coordinate. +//! +//! Claim under test: inside a world the Alpha route has already selected, +//! two resident CE64 fields can address a local source reading under a law +//! the class declares: +//! +//! ```text +//! Witness = w_slot() bits 53..58, 6 bits +//! Angle = direction() bits 43..45, 3 bits +//! (class, generation, Witness, Angle) --sparse law--> SourceCoord +//! ``` +//! +//! Nothing global is encoded in the bits. The same raw pair means different +//! things under different classes and under different generations of one +//! class, and means nothing for a class that reads those bits another way. +//! The world comes from the attended key (`graph_of`), never from the edge, +//! and no source record is stored beside the edge: the coordinate is computed +//! on read from a tiny probe codebook. +//! +//! # Readings of the same bits that refuse here +//! +//! - **Pathology triad**: the shipped meaning of bits 43..45 +//! (`s/p/o_pathological`). +//! - **Cohort witness**: the shipped meaning of bits 53..58 in +//! `witness_table::WitnessTable` (slot → `(mailbox_ref, spo_fact_ref)`). +//! +//! A class that declares either reading refuses the source-coordinate +//! reading, so the two shipped meanings are never silently reinterpreted. +//! +//! # What it does NOT prove +//! +//! - What a source coordinate means: `SourceCoord` is two opaque ordinals of +//! a six-entry test codebook, not an ontology. +//! - That the declaration belongs in the contract: it is probe-local, like +//! D-SPOG-W-0's. +//! - Anything about LocalG (a row-local SPOG G): not modelled. +//! +//! Run: `cargo run -p cognitive-shader-driver --example witness_angle_probe` +//! Tests: `cargo test -p cognitive-shader-driver --example witness_angle_probe` + +use std::alloc::{GlobalAlloc, Layout, System}; +use std::cell::Cell; + +use causal_edge::edge::CausalEdge64; +use causal_edge::pearl::CausalMask; +use causal_edge::PlasticityState; +use lance_graph_contract::band_reading::EdgeProvenance; +use lance_graph_contract::canonical_node::{NodeGuid, TailVariant}; +use lance_graph_contract::spog_tenants::graph_of; + +// ── allocation counter (the recipe_quartet_probe pattern) ───────────────── + +/// Counts allocations on the current thread; test threads run in parallel. +struct CountingAlloc; + +thread_local! { + static ALLOCATIONS: Cell = const { Cell::new(0) }; +} + +// SAFETY: forwards every call to `System` unchanged; it only adds a counter. +unsafe impl GlobalAlloc for CountingAlloc { + unsafe fn alloc(&self, layout: Layout) -> *mut u8 { + let _ = ALLOCATIONS.try_with(|c| c.set(c.get() + 1)); + unsafe { System.alloc(layout) } + } + unsafe fn dealloc(&self, ptr: *mut u8, layout: Layout) { + unsafe { System.dealloc(ptr, layout) } + } + unsafe fn realloc(&self, ptr: *mut u8, layout: Layout, new_size: usize) -> *mut u8 { + let _ = ALLOCATIONS.try_with(|c| c.set(c.get() + 1)); + unsafe { System.realloc(ptr, layout, new_size) } + } +} + +#[global_allocator] +static GLOBAL: CountingAlloc = CountingAlloc; + +/// Run `f` and return its result with the allocations it made on this thread. +fn counting(f: impl FnOnce() -> T) -> (T, usize) { + let before = ALLOCATIONS.with(Cell::get); + let out = f(); + (out, ALLOCATIONS.with(Cell::get) - before) +} + +// ── declarations ────────────────────────────────────────────────────────── + +/// How a class reads Witness and bits 43..45 together. Declared per class. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum SlotReading { + /// Witness × Angle → a local source coordinate under the class's law. + SourceCoordinate, + /// Bits 43..45 are the S/P/O pathology triad (the shipped meaning). + PathologyTriad, + /// Bits 53..58 index a cohort `WitnessTable` (the shipped meaning). + CohortWitness, +} + +/// Probe placeholders, not OGAR mints: two worlds (`0x9101`, `0x9102`). +const CLASS_OBS: u32 = 0x9101_0001; +const CLASS_ERP: u32 = 0x9102_0001; +/// A second source-coordinate class in the same world as `CLASS_OBS`. +const CLASS_OBS2: u32 = 0x9101_0005; +const CLASS_PATHOLOGY: u32 = 0x9101_0002; +const CLASS_COHORT: u32 = 0x9101_0003; +const CLASS_UNDECLARED: u32 = 0x9101_0004; + +/// `(class, reading, declared generations)`. +const DECLARATIONS: [(u32, SlotReading, &[u8]); 5] = [ + (CLASS_OBS, SlotReading::SourceCoordinate, &[1, 2]), + (CLASS_OBS2, SlotReading::SourceCoordinate, &[1]), + (CLASS_ERP, SlotReading::SourceCoordinate, &[1]), + (CLASS_PATHOLOGY, SlotReading::PathologyTriad, &[1]), + (CLASS_COHORT, SlotReading::CohortWitness, &[1]), +]; + +/// A local source/read position: two opaque ordinals of the probe codebook. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +struct SourceCoord { + table: u8, + column: u8, +} + +const fn sc(table: u8, column: u8) -> SourceCoord { + SourceCoord { table, column } +} + +/// The sparse law: `(class, generation, witness, angle) → coordinate`. Every +/// pair not listed is unmapped. A test codebook, not an ontology. +const LAW: [(u32, u8, u8, u8, SourceCoord); 6] = [ + (CLASS_OBS, 1, 23, 5, sc(1, 7)), + (CLASS_OBS, 1, 23, 2, sc(1, 3)), + (CLASS_OBS, 1, 4, 5, sc(2, 7)), + // Generation 2 re-reads (23, 5) and drops the other two pairs. + (CLASS_OBS, 2, 23, 5, sc(1, 8)), + // Same world, another class, same raw pair: a different source. + (CLASS_OBS2, 1, 23, 5, sc(5, 1)), + // Another world, same raw pair, a different source. + (CLASS_ERP, 1, 23, 5, sc(9, 2)), +]; + +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +enum Refusal { + /// The edge's bits were not asserted to be v2/V3-stamped. + Provenance(EdgeProvenance), + /// The class declared no reading of these bits. + Undeclared(u32), + /// The class reads these bits another way. + OtherReading(SlotReading), + /// The class never declared this generation. + UndeclaredGeneration(u8), + /// Witness 0: no anchor, so no source. + NoAnchor, + /// The pair has no entry in this class generation's law. + Unmapped { witness: u8, angle: u8 }, +} + +/// The world and the local source of one epistemic delta. Transient. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +struct LocalSource { + /// From the attended key, never from the edge. + world: u16, + source: SourceCoord, +} + +fn key(classid: u32) -> NodeGuid { + NodeGuid::mint_for(TailVariant::V3, classid, 0, 0, 0, 0, 0, 0) +} + +/// Read the local source of `edge`, attended under `classid`, at the declared +/// `generation`. +fn local_source( + classid: u32, + generation: u8, + edge: CausalEdge64, + provenance: EdgeProvenance, +) -> Result { + if !matches!( + provenance, + EdgeProvenance::V2Stamped | EdgeProvenance::V3Register + ) { + return Err(Refusal::Provenance(provenance)); + } + let Some(&(_, reading, gens)) = DECLARATIONS.iter().find(|(c, _, _)| *c == classid) else { + return Err(Refusal::Undeclared(classid)); + }; + if reading != SlotReading::SourceCoordinate { + return Err(Refusal::OtherReading(reading)); + } + if !gens.contains(&generation) { + return Err(Refusal::UndeclaredGeneration(generation)); + } + let (witness, angle) = (edge.w_slot(), edge.direction()); + if witness == 0 { + return Err(Refusal::NoAnchor); + } + LAW.iter() + .find(|(c, g, w, a, _)| *c == classid && *g == generation && *w == witness && *a == angle) + .map(|&(_, _, _, _, source)| LocalSource { + world: graph_of(key(classid)), + source, + }) + .ok_or(Refusal::Unmapped { witness, angle }) +} + +fn stamped(classid: u32, generation: u8, edge: CausalEdge64) -> Result { + local_source(classid, generation, edge, EdgeProvenance::V2Stamped) +} + +/// An edge with the given Witness and Angle; the rest is fixed filler. +fn edge(witness: u8, angle: u8) -> CausalEdge64 { + CausalEdge64::pack_v2( + 1, + 2, + 3, + 200, + 180, + CausalMask::SO, + angle, + PlasticityState::ALL_HOT, + ) + .with_inference_mantissa(1) + .with_w_slot(witness) +} + +fn main() { + let e = edge(23, 5); + println!("D-WA-0: Witness x Angle as a declared local source coordinate"); + println!( + " bits w={} a={}", + e.w_slot(), + e.direction() + ); + for (name, c, g) in [ + ("observations gen 1", CLASS_OBS, 1), + ("observations gen 2", CLASS_OBS, 2), + ("erp gen 1", CLASS_ERP, 1), + ("pathology class", CLASS_PATHOLOGY, 1), + ("undeclared class", CLASS_UNDECLARED, 1), + ] { + println!(" {name:<25} {:?}", stamped(c, g, e)); + } + let (r, allocs) = counting(|| stamped(CLASS_OBS, 1, e)); + println!( + " read allocations {allocs} ({:?})", + r.map(|s| s.source) + ); +} + +#[cfg(test)] +mod tests { + use super::*; + + /// Same bits, same class, same generation: the same coordinate, every time. + #[test] + fn same_bits_and_generation_give_the_same_coordinate() { + let a = stamped(CLASS_OBS, 1, edge(23, 5)).unwrap(); + let b = stamped(CLASS_OBS, 1, edge(23, 5)).unwrap(); + assert_eq!(a, b); + assert_eq!(a.source, sc(1, 7)); + assert_eq!(a.world, 0x9101); + } + + /// The same raw pair in two classes is two sources, whether the classes + /// share a world or not. The world comes from the class's key; the edge is + /// identical. + #[test] + fn same_bits_in_another_class_are_another_source() { + let e = edge(23, 5); + let obs = stamped(CLASS_OBS, 1, e).unwrap(); + let obs2 = stamped(CLASS_OBS2, 1, e).unwrap(); + let erp = stamped(CLASS_ERP, 1, e).unwrap(); + // Same world, different class: class identity alone separates them. + assert_eq!(obs.world, obs2.world); + assert_ne!(obs.source, obs2.source); + // Different world as well. + assert_ne!(obs.source, erp.source); + assert_eq!((obs.world, erp.world), (0x9101, 0x9102)); + } + + /// A later generation may legally re-read the same bits, and may drop a + /// pair the earlier one mapped. + #[test] + fn a_new_generation_may_read_the_bits_differently() { + assert_eq!(stamped(CLASS_OBS, 1, edge(23, 5)).unwrap().source, sc(1, 7)); + assert_eq!(stamped(CLASS_OBS, 2, edge(23, 5)).unwrap().source, sc(1, 8)); + assert_eq!(stamped(CLASS_OBS, 1, edge(23, 2)).unwrap().source, sc(1, 3)); + assert_eq!( + stamped(CLASS_OBS, 2, edge(23, 2)), + Err(Refusal::Unmapped { + witness: 23, + angle: 2 + }) + ); + } + + /// Every way the read can be illegitimate refuses, each for its own reason. + #[test] + fn illegitimate_reads_refuse() { + let e = edge(23, 5); + assert_eq!( + stamped(CLASS_UNDECLARED, 1, e), + Err(Refusal::Undeclared(CLASS_UNDECLARED)) + ); + assert_eq!( + stamped(CLASS_PATHOLOGY, 1, e), + Err(Refusal::OtherReading(SlotReading::PathologyTriad)) + ); + assert_eq!( + stamped(CLASS_COHORT, 1, e), + Err(Refusal::OtherReading(SlotReading::CohortWitness)) + ); + assert_eq!( + stamped(CLASS_ERP, 2, e), + Err(Refusal::UndeclaredGeneration(2)) + ); + assert_eq!(stamped(CLASS_OBS, 1, edge(0, 5)), Err(Refusal::NoAnchor)); + for p in [EdgeProvenance::V1Legacy, EdgeProvenance::Unknown] { + assert_eq!( + local_source(CLASS_OBS, 1, e, p), + Err(Refusal::Provenance(p)) + ); + } + // Silent twin: the legitimate read of the same edge succeeds. + assert!(stamped(CLASS_OBS, 1, e).is_ok()); + } + + /// No global meaning: over all 63 × 8 anchored pairs, each class maps only + /// its own few, and the two classes do not map the same set to the same + /// sources. + #[test] + fn the_law_is_sparse_and_class_scoped() { + let mapped = |c: u32| -> Vec<(u8, u8, SourceCoord)> { + (1..64u8) + .flat_map(|w| (0..8u8).map(move |a| (w, a))) + .filter_map(|(w, a)| stamped(c, 1, edge(w, a)).ok().map(|s| (w, a, s.source))) + .collect() + }; + let (obs, erp) = (mapped(CLASS_OBS), mapped(CLASS_ERP)); + assert_eq!(obs.len(), 3, "{obs:?}"); + assert_eq!(erp.len(), 1, "{erp:?}"); + assert!(obs.len() * 100 < 63 * 8, "sparse"); + assert!(erp.iter().all(|x| !obs.contains(x)), "no shared meaning"); + } + + /// Stay-silent: fields other than Witness and Angle do not move the + /// coordinate. Can-fire: changing Witness or Angle does. + #[test] + fn only_witness_and_angle_address_the_source() { + let base = stamped(CLASS_OBS, 1, edge(23, 5)).unwrap(); + let others = [ + CausalEdge64::pack_v2( + 9, + 8, + 7, + 10, + 20, + CausalMask::SPO, + 5, + PlasticityState::ALL_HOT, + ) + .with_w_slot(23), + edge(23, 5).with_inference_mantissa(-6), + CausalEdge64::pack_v2(0, 0, 0, 0, 0, CausalMask::None, 5, PlasticityState::ALL_HOT) + .with_w_slot(23), + ]; + for e in others { + assert_eq!(stamped(CLASS_OBS, 1, e).unwrap(), base, "{:016x}", e.0); + } + assert_ne!( + stamped(CLASS_OBS, 1, edge(4, 5)).unwrap(), + base, + "Witness moves it" + ); + assert_ne!( + stamped(CLASS_OBS, 1, edge(23, 2)).unwrap(), + base, + "Angle moves it" + ); + } + + /// The read allocates nothing. + #[test] + fn the_read_allocates_nothing() { + let edges: [CausalEdge64; 64] = core::array::from_fn(|i| { + // Half the edges hit the law, half miss it: both paths are measured. + if i % 2 == 0 { + edge(23, 5) + } else { + edge(i as u8, (i % 8) as u8) + } + }); + let (hits, allocs) = counting(|| { + edges + .iter() + .filter(|e| stamped(CLASS_OBS, 1, **e).is_ok()) + .count() + }); + assert_eq!(allocs, 0); + assert_eq!(hits, 32, "the hit path ran"); + } +}