From 8c19149803c96edaebb59e425114968e514fec3a Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Oct 2026 19:48:24 +0000 Subject: [PATCH 1/5] act-r: rename lance-graph-actr to lance-graph-act-r; refuse stale candidate eligibility ACT-R is Adaptive Control of Thought, Rational; the old name read as actor/ractor. Package lance-graph-act-r, crate lance_graph_act_r, edition 2024 (standalone, zero dependencies, so no workspace-convention conflict). Correctness (#1615 review): Candidate carried no evaluation witness, so arbitrate() stamped any snapshot onto a decision whose eligibility was computed against another state, and witness_matches() then accepted it. Candidate now carries evaluated_at; arbitrate() refuses the whole batch with Refusal::StaleCandidate when any candidate (eligible or not) was evaluated at another snapshot. Tests: stale eligibility, fresh twin, mixed generations, recycled thought address, invalid scores, tie-break, stale decision. Registers the crate in the root exclude list and adds a CI job (.github/workflows/act-r.yml) so its tests run. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VyWZYKycy6MoYDxHRVnV5K --- .github/workflows/act-r.yml | 33 +++ Cargo.toml | 2 + crates/lance-graph-act-r/Cargo.toml | 16 ++ .../README.md | 15 +- crates/lance-graph-act-r/src/lib.rs | 255 ++++++++++++++++++ crates/lance-graph-actr/Cargo.toml | 10 - crates/lance-graph-actr/src/lib.rs | 134 --------- 7 files changed, 317 insertions(+), 148 deletions(-) create mode 100644 .github/workflows/act-r.yml create mode 100644 crates/lance-graph-act-r/Cargo.toml rename crates/{lance-graph-actr => lance-graph-act-r}/README.md (63%) create mode 100644 crates/lance-graph-act-r/src/lib.rs delete mode 100644 crates/lance-graph-actr/Cargo.toml delete mode 100644 crates/lance-graph-actr/src/lib.rs diff --git a/.github/workflows/act-r.yml b/.github/workflows/act-r.yml new file mode 100644 index 000000000..c682e4ec3 --- /dev/null +++ b/.github/workflows/act-r.yml @@ -0,0 +1,33 @@ +name: ACT-R production arbitration +# `crates/lance-graph-act-r` is a standalone crate (own [workspace], listed in +# the root `exclude`), so no workspace job builds it. Without this job its +# tests never run. +on: + pull_request: + paths: + - 'crates/lance-graph-act-r/**' + - '.github/workflows/act-r.yml' + push: + branches: [main] + paths: + - 'crates/lance-graph-act-r/**' + - '.github/workflows/act-r.yml' + workflow_dispatch: +permissions: + contents: read +jobs: + act-r: + runs-on: ubuntu-latest + timeout-minutes: 10 + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + - name: Setup rust toolchain (pinned by rust-toolchain.toml) + run: rustup show + - name: Format + run: cargo fmt --manifest-path crates/lance-graph-act-r/Cargo.toml -- --check + - name: Lint + run: cargo clippy --manifest-path crates/lance-graph-act-r/Cargo.toml --all-targets -- -D warnings + - name: Test + run: cargo test --manifest-path crates/lance-graph-act-r/Cargo.toml diff --git a/Cargo.toml b/Cargo.toml index 2bad121be..5dc8f95df 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -43,6 +43,8 @@ exclude = [ "crates/lance-graph-sap", # D-HOLO-H14c Lance 13 masked-I/O probe: own narrow dependency set. "crates/holo-lance-masked-io-probe", + # ACT-R production arbitration: zero deps, own [workspace], own CI job. + "crates/lance-graph-act-r", "crates/lance-graph-glove-parity", # Python bindings (upstream-inherited, opt-in via --manifest-path) "crates/lance-graph-python", diff --git a/crates/lance-graph-act-r/Cargo.toml b/crates/lance-graph-act-r/Cargo.toml new file mode 100644 index 000000000..9fb4a4c62 --- /dev/null +++ b/crates/lance-graph-act-r/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "lance-graph-act-r" +version = "0.1.0" +edition = "2024" +publish = false +description = "Experimental ACT-R cognitive production arbitration" + +# Standalone on purpose: zero dependencies, so it stays out of the main +# workspace graph. Registered under the root `exclude` list; CI runs it with +# `--manifest-path`. +[workspace] + +[lib] +name = "lance_graph_act_r" + +[dependencies] diff --git a/crates/lance-graph-actr/README.md b/crates/lance-graph-act-r/README.md similarity index 63% rename from crates/lance-graph-actr/README.md rename to crates/lance-graph-act-r/README.md index 88702907a..c6105218f 100644 --- a/crates/lance-graph-actr/README.md +++ b/crates/lance-graph-act-r/README.md @@ -1,6 +1,8 @@ -# lance-graph-actr +# lance-graph-act-r -Experimental ACT-R-inspired **production arbitration kernel**, not a complete ACT-R cognitive architecture. +Experimental ACT-R cognitive **production arbitration kernel**, not a complete ACT-R cognitive architecture. + +ACT-R is *Adaptive Control of Thought, Rational*. This crate is not an actor, mailbox or `ractor` component. The cognitive condition matcher remains in relalg/R2IL/Quack/Mask-RISC. This crate receives already-evaluated candidate eligibility and selects a witnessed **intent**; it cannot execute external effects. @@ -10,14 +12,19 @@ The cognitive condition matcher remains in relalg/R2IL/Quack/Mask-RISC. This cra - Utility = estimated procedural value. - NAL evidence = epistemic support, deliberately outside this arbitration score. - Motivation = future optional priority signal, not implicit authorization. +- Every `Candidate` carries `evaluated_at`, the snapshot its eligibility was computed against; `arbitrate` refuses the whole batch (`Refusal::StaleCandidate`) if any candidate was evaluated at another snapshot. - Snapshot identity and witness version are explicit; currently local experimental types, to be replaced by canonical contract ABI. - The 64-thought frontier is a caller policy, not an ACT-R buffer count. ## Run -`cargo test --manifest-path crates/lance-graph-actr/Cargo.toml` +`cargo test --manifest-path crates/lance-graph-act-r/Cargo.toml` + +Standalone `[workspace]` avoids changing the main workspace's dependency graph; the crate is listed in the root `exclude` and has its own CI job (`.github/workflows/act-r.yml`). -Standalone `[workspace]` avoids changing the main workspace's dependency graph. +```rust +use lance_graph_act_r::{Candidate, Decision, Snapshot}; +``` ## Next diff --git a/crates/lance-graph-act-r/src/lib.rs b/crates/lance-graph-act-r/src/lib.rs new file mode 100644 index 000000000..47df8f08b --- /dev/null +++ b/crates/lance-graph-act-r/src/lib.rs @@ -0,0 +1,255 @@ +//! Deterministic ACT-R production arbitration. +//! +//! ACT-R is the cognitive architecture *Adaptive Control of Thought, Rational*. +//! This crate is not an actor or mailbox framework. +//! +//! The caller evaluates production conditions through relalg/R2IL/Quack/Mask-RISC. +//! This crate never interprets expressions, reads storage, or executes effects. +//! It chooses an eligible rule and returns a witnessed *proposal*. +//! Not a complete ACT-R implementation (no buffer timing or learning yet). + +/// Address of the observed cognitive state. These local types are an experimental +/// boundary; replace with canonical lance-graph contract types before integration. +/// +/// Two snapshots are the same state only when both fields agree: a thought +/// address that is reused under a new `witness_version` is a different state. +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub struct Snapshot { + pub thought_address: u128, + pub witness_version: u64, +} + +/// Rule eligibility is supplied by the sole external masking evaluator. +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct Candidate { + pub rule_id: u64, + pub eligible: bool, + /// Expected learned usefulness of the procedure, not epistemic truth. + pub utility: f32, + /// ACT-R-inspired accessibility, not evidence or permission. + pub activation: f32, + /// The state the evaluator read when it computed `eligible`. + /// [`arbitrate`] refuses the batch unless this equals its `snapshot`. + pub evaluated_at: Snapshot, +} + +/// An intent is not an authorized effect or committed state transition. +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct Decision { + pub snapshot: Snapshot, + pub rule_id: u64, + pub utility: f32, + pub activation: f32, +} + +#[derive(Clone, Copy, Debug, PartialEq, Eq)] +pub enum Refusal { + NoEligibleProduction, + InvalidScore, + /// A candidate was evaluated against another state than the one being + /// arbitrated. The whole batch is refused: dropping the candidate would + /// hide a rule whose current eligibility is unknown. + StaleCandidate { + rule_id: u64, + evaluated_at: Snapshot, + }, +} + +/// Deterministic arbitration: maximize utility, then activation, then prefer +/// smaller rule ID. NaN and infinity are refused rather than silently ordered. +/// No hidden RNG, external LLM, SQL or JSON enters this path. +/// +/// Every candidate, eligible or not, must have been evaluated at `snapshot`; +/// otherwise the batch is refused with [`Refusal::StaleCandidate`] before any +/// selection, so a decision is never stamped with a state its eligibility was +/// not computed against. +pub fn arbitrate(snapshot: Snapshot, candidates: &[Candidate]) -> Result { + if let Some(stale) = candidates.iter().find(|c| c.evaluated_at != snapshot) { + return Err(Refusal::StaleCandidate { + rule_id: stale.rule_id, + evaluated_at: stale.evaluated_at, + }); + } + let mut best: Option = None; + for &candidate in candidates.iter().filter(|c| c.eligible) { + if !candidate.utility.is_finite() || !candidate.activation.is_finite() { + return Err(Refusal::InvalidScore); + } + let replace = match best { + None => true, + Some(previous) => { + candidate.utility > previous.utility + || (candidate.utility == previous.utility + && (candidate.activation > previous.activation + || (candidate.activation == previous.activation + && candidate.rule_id < previous.rule_id))) + } + }; + if replace { + best = Some(candidate); + } + } + let selected = best.ok_or(Refusal::NoEligibleProduction)?; + Ok(Decision { + snapshot, + rule_id: selected.rule_id, + utility: selected.utility, + activation: selected.activation, + }) +} + +/// Only checks that a proposal still refers to the observed snapshot. +/// The caller must independently authorize and atomically commit any effect. +pub fn witness_matches(decision: &Decision, current: Snapshot) -> bool { + decision.snapshot == current +} + +#[cfg(test)] +mod tests { + use super::*; + const STATE: Snapshot = Snapshot { + thought_address: 42, + witness_version: 7, + }; + const NEXT: Snapshot = Snapshot { + thought_address: 42, + witness_version: 8, + }; + + fn candidate(rule_id: u64, eligible: bool, utility: f32, activation: f32) -> Candidate { + at(STATE, rule_id, eligible, utility, activation) + } + + fn at(s: Snapshot, rule_id: u64, eligible: bool, utility: f32, activation: f32) -> Candidate { + Candidate { + rule_id, + eligible, + utility, + activation, + evaluated_at: s, + } + } + + #[test] + fn eligible_utility_beats_ineligible_high_score() { + let result = arbitrate( + STATE, + &[ + candidate(1, false, 100.0, 100.0), + candidate(2, true, 0.7, 0.3), + ], + ) + .unwrap(); + assert_eq!(result.rule_id, 2); + } + + #[test] + fn tie_break_is_independent_of_candidate_order() { + let a = candidate(3, true, 0.7, 0.5); + let b = candidate(2, true, 0.7, 0.5); + assert_eq!(arbitrate(STATE, &[a, b]).unwrap().rule_id, 2); + assert_eq!(arbitrate(STATE, &[b, a]).unwrap().rule_id, 2); + } + + #[test] + fn activation_is_secondary_to_utility() { + assert_eq!( + arbitrate( + STATE, + &[candidate(1, true, 0.8, 0.1), candidate(2, true, 0.7, 0.9)] + ) + .unwrap() + .rule_id, + 1 + ); + } + + #[test] + fn refuses_non_finite_eligible_scores() { + assert_eq!( + arbitrate(STATE, &[candidate(1, true, f32::NAN, 0.0)]), + Err(Refusal::InvalidScore) + ); + assert_eq!( + arbitrate(STATE, &[candidate(1, true, 0.0, f32::INFINITY)]), + Err(Refusal::InvalidScore) + ); + } + + #[test] + fn no_eligible_production_is_explicit() { + assert_eq!( + arbitrate(STATE, &[candidate(1, false, 1.0, 1.0)]), + Err(Refusal::NoEligibleProduction) + ); + } + + /// The #1615 defect: eligibility computed at v7, arbitrated at v8. + /// Before the fix this returned a decision stamped with v8. + #[test] + fn stale_candidate_eligibility_is_refused() { + assert_eq!( + arbitrate(NEXT, &[candidate(1, true, 0.5, 0.5)]), + Err(Refusal::StaleCandidate { + rule_id: 1, + evaluated_at: STATE + }) + ); + } + + /// Silence twin: the same candidate at its own state is accepted. + #[test] + fn fresh_candidate_is_accepted() { + let d = arbitrate(NEXT, &[at(NEXT, 1, true, 0.5, 0.5)]).unwrap(); + assert_eq!((d.rule_id, d.snapshot), (1, NEXT)); + } + + /// One stale candidate refuses the whole batch, even when it is ineligible + /// and would lose: its current eligibility is unknown. + #[test] + fn mixed_candidate_generations_are_refused() { + let batch = [at(NEXT, 1, true, 0.9, 0.9), at(STATE, 2, false, 0.1, 0.1)]; + assert_eq!( + arbitrate(NEXT, &batch), + Err(Refusal::StaleCandidate { + rule_id: 2, + evaluated_at: STATE + }) + ); + } + + /// A reused thought address under a new witness version is another state. + #[test] + fn recycled_thought_address_is_refused() { + let recycled = Snapshot { + thought_address: 42, + witness_version: 1_000, + }; + assert!(matches!( + arbitrate(recycled, &[candidate(1, true, 0.5, 0.5)]), + Err(Refusal::StaleCandidate { .. }) + )); + let other_thought = Snapshot { + thought_address: 43, + witness_version: 7, + }; + assert!(matches!( + arbitrate(other_thought, &[candidate(1, true, 0.5, 0.5)]), + Err(Refusal::StaleCandidate { .. }) + )); + } + + #[test] + fn stale_decision_is_rejected_by_witness_check() { + let decision = arbitrate(STATE, &[candidate(1, true, 0.5, 0.5)]).unwrap(); + assert!(witness_matches(&decision, STATE)); + assert!(!witness_matches(&decision, NEXT)); + assert!(!witness_matches( + &decision, + Snapshot { + thought_address: 43, + witness_version: 7 + } + )); + } +} diff --git a/crates/lance-graph-actr/Cargo.toml b/crates/lance-graph-actr/Cargo.toml deleted file mode 100644 index 6f2de22ed..000000000 --- a/crates/lance-graph-actr/Cargo.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "lance-graph-actr" -version = "0.1.0" -edition = "2021" -publish = false -description = "Experimental deterministic ACT-R-inspired production arbitration over externally evaluated candidate masks" - -[workspace] - -[dependencies] diff --git a/crates/lance-graph-actr/src/lib.rs b/crates/lance-graph-actr/src/lib.rs deleted file mode 100644 index 1aacb7da3..000000000 --- a/crates/lance-graph-actr/src/lib.rs +++ /dev/null @@ -1,134 +0,0 @@ -//! Deterministic ACT-R-inspired production arbitration. -//! -//! The caller evaluates production conditions through relalg/R2IL/Quack/Mask-RISC. -//! This crate never interprets expressions, reads storage, or executes effects. -//! It chooses an eligible rule and returns a witnessed *proposal*. -//! Not a complete ACT-R implementation (no buffer timing or learning yet). - -/// Address of the observed cognitive state. These local types are an experimental -/// boundary; replace with canonical lance-graph contract types before integration. -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub struct Snapshot { - pub thought_address: u128, - pub witness_version: u64, -} - -/// Rule eligibility is supplied by the sole external masking evaluator. -#[derive(Clone, Copy, Debug, PartialEq)] -pub struct Candidate { - pub rule_id: u64, - pub eligible: bool, - /// Expected learned usefulness of the procedure, not epistemic truth. - pub utility: f32, - /// ACT-R-inspired accessibility, not evidence or permission. - pub activation: f32, -} - -/// An intent is not an authorized effect or committed state transition. -#[derive(Clone, Copy, Debug, PartialEq)] -pub struct Decision { - pub snapshot: Snapshot, - pub rule_id: u64, - pub utility: f32, - pub activation: f32, -} - -#[derive(Clone, Copy, Debug, PartialEq, Eq)] -pub enum Refusal { - NoEligibleProduction, - InvalidScore, -} - -/// Deterministic arbitration: maximize utility, then activation, then prefer -/// smaller rule ID. NaN and infinity are refused rather than silently ordered. -/// No hidden RNG, external LLM, SQL or JSON enters this path. -pub fn arbitrate(snapshot: Snapshot, candidates: &[Candidate]) -> Result { - let mut best: Option = None; - for &candidate in candidates.iter().filter(|c| c.eligible) { - if !candidate.utility.is_finite() || !candidate.activation.is_finite() { - return Err(Refusal::InvalidScore); - } - let replace = match best { - None => true, - Some(previous) => { - candidate.utility > previous.utility - || (candidate.utility == previous.utility - && (candidate.activation > previous.activation - || (candidate.activation == previous.activation - && candidate.rule_id < previous.rule_id))) - } - }; - if replace { - best = Some(candidate); - } - } - let selected = best.ok_or(Refusal::NoEligibleProduction)?; - Ok(Decision { - snapshot, - rule_id: selected.rule_id, - utility: selected.utility, - activation: selected.activation, - }) -} - -/// Only checks that a proposal still refers to the observed snapshot. -/// The caller must independently authorize and atomically commit any effect. -pub fn witness_matches(decision: &Decision, current: Snapshot) -> bool { - decision.snapshot == current -} - -#[cfg(test)] -mod tests { - use super::*; - const STATE: Snapshot = Snapshot { thought_address: 42, witness_version: 7 }; - fn candidate(rule_id: u64, eligible: bool, utility: f32, activation: f32) -> Candidate { - Candidate { rule_id, eligible, utility, activation } - } - - #[test] - fn eligible_utility_beats_ineligible_high_score() { - let result = arbitrate(STATE, &[ - candidate(1, false, 100.0, 100.0), - candidate(2, true, 0.7, 0.3), - ]).unwrap(); - assert_eq!(result.rule_id, 2); - } - - #[test] - fn tie_break_is_independent_of_candidate_order() { - let a = candidate(3, true, 0.7, 0.5); - let b = candidate(2, true, 0.7, 0.5); - assert_eq!(arbitrate(STATE, &[a, b]).unwrap().rule_id, 2); - assert_eq!(arbitrate(STATE, &[b, a]).unwrap().rule_id, 2); - } - - #[test] - fn activation_is_secondary_to_utility() { - assert_eq!(arbitrate(STATE, &[ - candidate(1, true, 0.8, 0.1), - candidate(2, true, 0.7, 0.9), - ]).unwrap().rule_id, 1); - } - - #[test] - fn refuses_non_finite_eligible_scores() { - assert_eq!(arbitrate(STATE, &[candidate(1, true, f32::NAN, 0.0)]), - Err(Refusal::InvalidScore)); - } - - #[test] - fn no_eligible_production_is_explicit() { - assert_eq!(arbitrate(STATE, &[candidate(1, false, 1.0, 1.0)]), - Err(Refusal::NoEligibleProduction)); - } - - #[test] - fn stale_witness_cannot_pass_check() { - let decision = arbitrate(STATE, &[candidate(1, true, 0.5, 0.5)]).unwrap(); - assert!(witness_matches(&decision, STATE)); - assert!(!witness_matches(&decision, - Snapshot { thought_address: 42, witness_version: 8 })); - assert!(!witness_matches(&decision, - Snapshot { thought_address: 43, witness_version: 7 })); - } -} From 6791e4ac3a083f118c40399db9279af551364e6f Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Oct 2026 19:51:08 +0000 Subject: [PATCH 2/5] mask-risc: quarantine the #1616 gather hop behind an opt-in feature OutgoingHop's two MaskOp::Gather ops read frontier[sources[i]] and visible[targets[i]], and its terminal scatters by targets[i]: a read at a position taken from another lane's values, the shape the 2026-10-16 ruling marks as not to be built (D-HOLO H14c/H14d). Green CI does not override that. graph_hop now compiles only under the off-by-default `quarantined-gather-hop` feature, with a banner in its module doc. A compile_fail doctest pins that the default build cannot reach OutgoingHop; a CI step still runs the quarantined tests under the feature so the code does not rot. The other Gather consumers (quack Semijoin, dir-sim) predate the ruling and are unchanged: deciding their scope is the open GATHER-DECISION, not this commit. The petgraph lance-fold-hop experiment pins rev 66636da and is unaffected until it bumps; a bump must enable the feature. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VyWZYKycy6MoYDxHRVnV5K --- .github/workflows/rust-test.yml | 5 +++++ crates/lance-graph-mask-risc/Cargo.toml | 10 ++++++++++ crates/lance-graph-mask-risc/src/graph_hop.rs | 11 +++++++++++ crates/lance-graph-mask-risc/src/lib.rs | 19 +++++++++++++++++++ 4 files changed, 45 insertions(+) diff --git a/.github/workflows/rust-test.yml b/.github/workflows/rust-test.yml index 0818360b4..45af511c6 100644 --- a/.github/workflows/rust-test.yml +++ b/.github/workflows/rust-test.yml @@ -123,6 +123,11 @@ jobs: # is added the day the crate joins, not the day its first test goes red. - name: Run mask-risc tests run: cargo test --manifest-path crates/lance-graph-mask-risc/Cargo.toml + # The #1616 gather hop is quarantined behind an off-by-default feature + # (ISS-GATHER-HOP-1616). Its own tests still run so the quarantined code + # does not rot; the default line above proves it is unreachable. + - name: Run quarantined mask-risc gather-hop tests + run: cargo test --manifest-path crates/lance-graph-mask-risc/Cargo.toml --features quarantined-gather-hop --lib graph_hop # The 256-arm ternlog dispatch is GENERATED; a hand edit that drifts from # the generator would otherwise ship silently. The generator's --check # exits non-zero when the committed region differs from its output. diff --git a/crates/lance-graph-mask-risc/Cargo.toml b/crates/lance-graph-mask-risc/Cargo.toml index e3b91bf65..8812e632e 100644 --- a/crates/lance-graph-mask-risc/Cargo.toml +++ b/crates/lance-graph-mask-risc/Cargo.toml @@ -19,6 +19,16 @@ description = "The one mask-RISC evaluator/fuser above ndarray::simd — a plan [dependencies] ndarray = { git = "https://github.com/AdaWorldAPI/ndarray", branch = "master", default-features = false, features = ["std"] } +[features] +# OFF by default. Compiles the merged #1616 `graph_hop::OutgoingHop`, which +# reads `frontier[sources[i]]` and `visible[targets[i]]` (MaskOp::Gather) and +# scatters by `targets[i]`: a read at a position taken from another lane's +# values, the shape the 2026-10-16 ruling bans (D-HOLO H14c/H14d, "the join is +# the layout"). Enabling it is an explicit opt-in to that shape for the +# petgraph lance-fold-hop experiment only; it is not authorization to build on +# it. Lifted only by a written GATHER-DECISION (ISSUES.md ISS-GATHER-HOP-1616). +quarantined-gather-hop = [] + [dev-dependencies] # D-RPF-0 (`tests/resident_ce64_predicate.rs`): the CE64 accessors are the # oracle and the contract supplies the tenant offsets. Test-only — the library diff --git a/crates/lance-graph-mask-risc/src/graph_hop.rs b/crates/lance-graph-mask-risc/src/graph_hop.rs index 8a9e80c82..348d3f979 100644 --- a/crates/lance-graph-mask-risc/src/graph_hop.rs +++ b/crates/lance-graph-mask-risc/src/graph_hop.rs @@ -1,5 +1,16 @@ //! Version-scoped one-hop graph fold over borrowed SoA edge lanes. //! +//! **QUARANTINED — gather shape (2026-10-19 remediation, ISSUES.md +//! ISS-GATHER-HOP-1616).** Both `Gather` ops below read a mask bit at a +//! position taken from another lane's values (`frontier[sources[i]]`, +//! `visible[targets[i]]`), and the terminal scatters by `targets[i]`. That is +//! the read the 2026-10-16 no-gather ruling marks as not to be built; the +//! correct design is co-addressed operands (D-HOLO H14c/H14d). Green tests +//! show the fold is internally consistent, not that the shape is allowed. +//! This module compiles only under the off-by-default `quarantined-gather-hop` +//! feature. A version-attested pre-fold BIND (D-RMAP-1A) is a separate, +//! unapproved proposal and is not a rescue path for this code. +//! //! Origin: the AdaWorldAPI/petgraph BFS-first-layer experiment. The sole //! evaluator remains Mask-RISC (Gather, Gather, ScatterOrU32). //! diff --git a/crates/lance-graph-mask-risc/src/lib.rs b/crates/lance-graph-mask-risc/src/lib.rs index 77821027f..5bc7ea0c6 100644 --- a/crates/lance-graph-mask-risc/src/lib.rs +++ b/crates/lance-graph-mask-risc/src/lib.rs @@ -109,6 +109,19 @@ //! joins. #![forbid(unsafe_code)] +#![cfg_attr( + not(feature = "quarantined-gather-hop"), + doc = r#" +## Quarantine regression (ISS-GATHER-HOP-1616) + +Without the `quarantined-gather-hop` feature the merged #1616 gather hop is +not reachable. This block must fail to compile: + +```compile_fail +use lance_graph_mask_risc::OutgoingHop; +``` +"# +)] // `hop` (src_mask → edge lane → dst_mask) is PR5's and is declared when it // lands — a `mod` line for a file that is not on disk made this crate fail to @@ -116,6 +129,11 @@ // recorded. pub mod exec; pub mod fuse; +// QUARANTINED (see `graph_hop`'s module doc and ISSUES.md +// ISS-GATHER-HOP-1616): the merged #1616 hop reads positions taken from another +// lane's values, the shape the 2026-10-16 no-gather ruling bans. It compiles +// only under the explicit, off-by-default `quarantined-gather-hop` feature. +#[cfg(feature = "quarantined-gather-hop")] pub mod graph_hop; pub mod ir; pub mod reference; @@ -127,6 +145,7 @@ pub use exec::{ tile_words_for, Scratch, TILE_WORDS, }; pub use fuse::{fuse, fuse_program, ternlog_imm, BoolExpr, FuseError, Fused}; +#[cfg(feature = "quarantined-gather-hop")] pub use graph_hop::{EdgeColumns, GraphSnapshot, HopError, OutgoingHop}; pub use ir::{ touched_words, Compiled, CompiledProgram, Foreign, ForeignPlane, FusedFold, FusedKeep, From f95c72fe683de82ad08ad8c0e89516fb2e7f296d Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Oct 2026 19:53:54 +0000 Subject: [PATCH 3/5] docs+qualia: apply verified review findings from #1603-#1613 #1612 Souffle RAM plan: D-SRAM-4 marked OPEN/BLOCKED; its target, the d' driver of D-RA-4, is a banned gather shape and no lawful recursion driver exists yet. D-SRAM-2's gate split: disabling an optimizer rewrite must keep the answer and only remove the plan shape; negative controls disable a semantic guard instead. #1613 JC R API plan: jc::jirak exposes only prove(), so it is listed as a GAP, not a calibration provider. Both row limits stated: per-group exactness, and the total-input refusal (n_rows > 2^32) the grouped moment terminals apply before running. #1605 causal pickaxe plan: the Lance 7 / LanceDB 0.30 prerequisite was stale; the workspace is on lance 13.* / lancedb 0.40.*. Reuses H14c-5's row-identity measurement instead of repeating it. #1604 candidates RFC: adds a witnessed Rejected outcome; fixture C-09 asserts the derived result and admits DRed. #1603 language LEGO RFC: the relative pronoun agrees in gender and number only; its case comes from inside the relative clause. #1607/#1608 qualia verifiers: explicit checks instead of assert (they ran as no-ops under python -O); the four archival fields are checked against a pinned digest and the sidecar against the archive values. Negative controls in test_verify_qualia.py; CI job qualia-verify.yml runs both under -O. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VyWZYKycy6MoYDxHRVnV5K --- ...ickaxe-resident-git-lance13-temporal-v1.md | 6 +- .claude/plans/jc-r-statistical-api-v1.md | 18 ++- .../plans/souffle-ram-64-thought-stack-v1.md | 8 +- .github/workflows/qualia-verify.yml | 33 ++++++ data/qualia/MUSICAL_ANCHORS.md | 2 +- data/qualia/test_verify_qualia.py | 71 ++++++++++++ data/qualia/verify_music_enrichment.py | 80 +++++++++++--- data/qualia/verify_musical_anchors.py | 104 +++++++++++++----- .../linguistic-lego-grammar-to-query-rfc.md | 2 +- ...ned-semantic-candidates-64-thoughts-rfc.md | 3 +- ...ersioned-semantic-candidates-fixtures.json | 5 +- 11 files changed, 275 insertions(+), 57 deletions(-) create mode 100644 .github/workflows/qualia-verify.yml create mode 100644 data/qualia/test_verify_qualia.py diff --git a/.claude/plans/causal-pickaxe-resident-git-lance13-temporal-v1.md b/.claude/plans/causal-pickaxe-resident-git-lance13-temporal-v1.md index df25119d2..af170f7b9 100644 --- a/.claude/plans/causal-pickaxe-resident-git-lance13-temporal-v1.md +++ b/.claude/plans/causal-pickaxe-resident-git-lance13-temporal-v1.md @@ -171,7 +171,7 @@ Harness to land **first**, in an isolated probe (no default workspace pins or pr ## 7. Dependency and rollout order -- **CPG-0:** inventory Cargo pins and cross-crate lockstep; create a minimal, excluded Lance13/LanceDB0.40 executable API probe (no global pin bump). +- **CPG-0:** confirm the current pins (root `Cargo.toml` already uses `lance = "13.*"` and `lancedb = "0.40.*"` as the workspace default, 2026-10-19) and exercise the branch / tag / row-lineage API in the integrated workspace; no isolated probe or pin bump is needed for the version itself. - **CPG-1:** pin row-ID semantics and branch/tag/version behavior using the exact release; correct any previous Lance11 assumptions (#1276) before migration. - **CPG-2:** map one reusable `DurableRef` adapter to the *existing* `LanceCycleWriter`/D-TGA boundary; retain single-writer contract and artifact election. - **CPG-3:** resident logical history and selective squash against D-TGA-1/3/4, preserving candidate receipts from #1604 and NAL independent evidence. @@ -179,7 +179,9 @@ Harness to land **first**, in an isolated probe (no default workspace pins or pr - **CPG-5:** counterfactual replay/ablation and independent oracles; differentiate model dependence, derivation necessity, causal Pearl inference. - **CPG-6:** user-facing Git vocabulary and benchmarks if CPG-0..5 pass, including bounded memory and crash/cleanup recovery. -**Prerequisite:** protect any existing consumers that require older Lance pins (root `Cargo.toml` documents older 7/0.30 lockstep and excluded Lance13 probes). Do not claim whole-workspace migration has happened. If Lance13 and LanceDB0.40 APIs introduce incompatible crate versions, leave the default workspace unchanged and publish only an isolated probe/failing report. +**Prerequisite (corrected 2026-10-19, #1605 review):** the earlier text said the root `Cargo.toml` documents a Lance 7 / LanceDB 0.30 lockstep and that the whole-workspace migration had not happened. Both were stale when written: the workspace default is already Lance 13 / LanceDB 0.40 (`Cargo.toml` `lance = "13.*"`, `lancedb = "0.40.*"`). Validate against that integration, not an isolated probe. + +Do not re-run the row-identity measurement; reuse D-HOLO H14c-5 (`.claude/plans/d-holo-h14c-thought-first-v1.md` § Coordinate identity). Measured there on Lance 13: without stable row IDs, compaction changed 3,510 of 3,510 `_rowid`s and an update moved 85 of 85 rows; with stable row IDs, 0 and 0. A stale mapping used without a version check caused **silent omission** (160 of 160 live rows missing), not a wrong coordinate, and a version-checked map refused every stale read. Keep four things distinct: canonical identity (`NodeGuid`), physical row position (`_rowaddr`), version witness (dataset version / seal), and compaction-safe references (stable `_rowid`, opt-in, per dataset). ## 8. What would falsify the idea? diff --git a/.claude/plans/jc-r-statistical-api-v1.md b/.claude/plans/jc-r-statistical-api-v1.md index 6dfaa2782..0b91fabe9 100644 --- a/.claude/plans/jc-r-statistical-api-v1.md +++ b/.claude/plans/jc-r-statistical-api-v1.md @@ -36,9 +36,9 @@ cross-validation, and parameter estimation for cognitive experiments. | Sample covariance from cross moments | jc::stats::sample_covariance_from_cross_power_sums | Resident covariance | | Simple OLS and R² from cross moments | jc::stats::simple_regression_from_cross_power_sums / r_squared_from_cross_power_sums | Small model-spec subset | | One-way ANOVA and eta² from per-group moments | jc::stats::anova_from_power_sums / eta_squared_from_power_sums | Grouped response ~ categorical predictor | -| Weak-dependence calibration | jc::jirak | Explicit noise-floor claims, not ordinary independent-sample p-values | +| Weak-dependence noise-floor **proof** (not a calibration API) | jc::jirak exposes only `prove() -> PillarResult`, a fixed 5,000-sample simulation | **GAP (2026-10-19, #1613 review):** no function consumes a statistical request or returns a calibration; a `CalibrationId::Jirak` provider does not exist and would have to be built | -The last four groups of calls consume ndarray::simd::CrossPowerSums or +The four cross-moment / grouped-moment rows above consume ndarray::simd::CrossPowerSums or PowerSums rather than materialized row-group vectors. The grouped moment terminals exist in lance-graph-mask-risc / ndarray; they are a particularly strong precedent for the intended pipeline. @@ -173,13 +173,21 @@ not as a valid 0.0 or false significance. - Keep **JC** responsible for variance-divisor conventions, p-value tails, effect-size definitions, undefined estimates, and conditioning. - CrossPowerSums / PowerSums have bounded exact integer accumulation and - checked conversions; specifically preserve the currently documented - ~2^32 rows/group bound and checked i128 centering. Overflow is refusal. + checked conversions; specifically preserve the checked i128 centering. + **Two row limits, both refusals (2026-10-19 correction, #1613 review):** + the per-group exactness bound (~2^32 rows/group), and the **total input** + bound: the grouped moment terminals (`GroupPowerSumsI32`, + `GroupCrossPowerSumsI32`) refuse `n_rows > MASKED_SUM_I32_MAX_ROWS` (2^32) + for the whole plane before running, even when every group is small + (`lance-graph-mask-risc/src/reference.rs`, `ExecError::SumRowBound`). A + request contract that validates only group counts would pass inputs the + executor then refuses; validate the total too. - Use ndarray::simd for numeric execution; mask-risc remains the single bulk evaluator. A statistical frontend cannot introduce a scalar alternative, even as an unadvertised fallback. - The significance path must distinguish classical IID t/ANOVA calculations - from jc::jirak weak-dependence calibration for correlated Hamming bitfields. + from weak-dependence calibration for correlated Hamming bitfields, which + does not exist as a callable API yet (jc::jirak is a fixed proof, see §2). No single p-value label is valid for both without declaring the model. - Retain precision and rounding conventions and test adversarial large offsets, constant series, sparse groups, NaNs and overflow. diff --git a/.claude/plans/souffle-ram-64-thought-stack-v1.md b/.claude/plans/souffle-ram-64-thought-stack-v1.md index ebbdfc6b9..1b75526c8 100644 --- a/.claude/plans/souffle-ram-64-thought-stack-v1.md +++ b/.claude/plans/souffle-ram-64-thought-stack-v1.md @@ -124,7 +124,7 @@ A RAM plan may use existing operations only after proof of its coordinate semant - **P1 co-addressed:** `T_a[i]` and `T_b[i]` share the same sealed allocation and ordinal; select `A & P_a & P_b` then read survivors at `i`. Different versions or codebooks cannot AND without an independently verified mapping. - **P2 canonical pre-arrangement:** a relation was *already* co-located or legally projected into the same coordinate frame at admission/seal, with schema/codebook witness. Charge the build/maintenance cost; **never** sneak an extra foreign-lane dereference into the hot executor. - **P3 not expressible:** an unaligned `path(x,z) :- path(x,y), edge(y,z)` is **not a mask AND**. Refuse this proposed physical lowering and record a capability gap until a correct, separately authorized layout/projection is demonstrated. Datafrog/Soufflé may compute the oracle off-path, never invisibly substitute in production. -- **P4 recursive:** call one compiled `Program` per frontier delta via existing external d′ / semi-naive driver only after D-RA-4 gate; datafrog's `recent/stable` is reference semantics, not a new runtime in mask-risc. +- **P4 recursive:** call one compiled `Program` per frontier delta via a recursion driver that does not exist yet (D-RA-4's d′ preimage driver is a banned gather shape, so D-SRAM-4 is BLOCKED); datafrog's `recent/stable` is reference semantics, not a new runtime in mask-risc. - **P5 NAL:** weighted frequency/confidence stays an existing typed fold with source independence; derivation support is not a Boolean membership bit. - **P6 Git:** `status`, `diff`, `blame`, `rebase`, `pickaxe` lower through existing resident selections. `land` follows G1..G7 and the canonical single writer. Compile-time scheduling does not certify a semantic conclusion. @@ -136,14 +136,14 @@ No new opcode, key format, hot String, runtime JSON, row allocator, per-fold Lan | --- | --- | --- | | D-SRAM-0 | Inventory pinned Soufflé AST/ast2ram/RAM passes; map to D-ASM/D-RA/D-TGA owners and current shipped code; establish source notices | Explicit evidence for every mapped pass; no code imported; list gaps and superseded gather plans | | D-SRAM-1 | Define a **conceptual bound AST → RAM-like schedule** for pure conjunctive selection, including bag vs set, address seal and negative dependencies | Same canonical answers and read sets on hand-built fixtures; every unsupported operation typed-refused | -| D-SRAM-2 | Prototype cold optimizer rewrites: SCC/strata, magic-set/aperture propagation, predicate ordering, safe dedup; keep optimizer out of hot path | `optimized == unoptimized == source oracle` for query **and** evidential roots; negative controls must fail when rewrite disabled | +| D-SRAM-2 | Prototype cold optimizer rewrites: SCC/strata, magic-set/aperture propagation, predicate ordering, safe dedup; keep optimizer out of hot path | `optimized == unoptimized == source oracle` for query **and** evidential roots. Disabling a rewrite must leave the answer unchanged and only remove the optimized plan shape (assert the shape is absent, never a wrong answer). Negative controls disable a **semantic correctness guard** (e.g. SCC stratification of a negative dependency, dedup under bag semantics), and those must fail (2026-10-19 correction, #1612 review) | | D-SRAM-3 | Investigate co-addressed physical selection and coordinate proof; exact R2IL `Program` reproducibility across eligible front ends | P1/P2 agree with scalar reference; P3 always refuses; no foreign-gather or phantom equal-row assumption | -| D-SRAM-4 | Hook recursive region scheduling to already-authorized d′ driver; compare with Datafrog, then Soufflé | Identical least fixpoint for set workloads, terminated cycles, consistent bag categorization; one thought remains live across many iterations | +| D-SRAM-4 | **OPEN / BLOCKED (2026-10-19, #1612 review).** The earlier target, the "already-authorized d′ driver", is D-RA-4, which STATUS_BOARD marks as a gather violation (preimage hop). There is no lawful recursion driver to hook into yet; this phase waits for a co-addressed recursion design under D-HOLO H14c/H14d, not invented here. Once one exists: compare with Datafrog, then Soufflé | Identical least fixpoint for set workloads, terminated cycles, consistent bag categorization; one thought remains live across many iterations | | D-SRAM-5 | Analyze *speculative thought* liveness and nested-alternative lifetime with the existing 0+63 slots; integrate with D-TGA when implemented | Exhaustion refused, deterministic re-use, negative-read strata safe, no tombstoned branch reused before proof receipt | | D-SRAM-6 | Candidate resolution and Git porcelain/admission/rebase/land under pinned temporal horizon; source-aware DRed/replay | Deleted support removes only dependent proofs; independent proof survives; stale-horizon and fake-causality controls red | | D-SRAM-7 | Evaluate hierarchical **chunk** promotion as a compilation optimization only after correctness gates | Cold source graph + versioned receipts can unfold; no confidence inflation; compare physical reads/bytes/ops/time, not just row count | -**Release order:** Do not begin D-SRAM-4 before D-RA-4's real recursive-driver gate; D-SRAM-5/6 depend on D-TGA-1/3 plus #1605's temporal/provenance gates. D-SRAM-2 is research/probe until D-ASM's Datalog AST placement and D-RA-2 are resolved. This plan **adds no new D-ASM/W wave implementation authorization**. +**Release order:** D-SRAM-4 is blocked until a lawful (co-addressed, non-gather) recursion driver is designed and approved; D-RA-4 is not that driver; D-SRAM-5/6 depend on D-TGA-1/3 plus #1605's temporal/provenance gates. D-SRAM-2 is research/probe until D-ASM's Datalog AST placement and D-RA-2 are resolved. This plan **adds no new D-ASM/W wave implementation authorization**. ## 7. Measurement and decision rules diff --git a/.github/workflows/qualia-verify.yml b/.github/workflows/qualia-verify.yml new file mode 100644 index 000000000..6ffcdc5e7 --- /dev/null +++ b/.github/workflows/qualia-verify.yml @@ -0,0 +1,33 @@ +name: Qualia archive verifiers +# The two verifiers guard the archived 219 musical annotations (#1607, #1608). +# They run under `python -O`, which strips `assert`, to prove they do not +# depend on it. +on: + pull_request: + paths: + - 'data/qualia/**' + - '.github/workflows/qualia-verify.yml' + push: + branches: [main] + paths: + - 'data/qualia/**' + - '.github/workflows/qualia-verify.yml' +permissions: + contents: read +jobs: + verify: + runs-on: ubuntu-latest + timeout-minutes: 5 + steps: + - uses: actions/checkout@v4 + with: + persist-credentials: false + - uses: actions/setup-python@v5 + with: + python-version: '3.11' + - name: Verifiers pass on the committed archive (optimized mode) + run: | + python3 -O data/qualia/verify_musical_anchors.py + python3 -O data/qualia/verify_music_enrichment.py + - name: Negative controls (optimized mode) + run: python3 -O -m unittest discover -s data/qualia -p 'test_*.py' -v diff --git a/data/qualia/MUSICAL_ANCHORS.md b/data/qualia/MUSICAL_ANCHORS.md index bd6674069..b5c4b58b0 100644 --- a/data/qualia/MUSICAL_ANCHORS.md +++ b/data/qualia/MUSICAL_ANCHORS.md @@ -26,4 +26,4 @@ The 219-item corpus was extracted from [AdaWorldAPI/Chat/music/Interval_Qualia_a Run `python3 data/qualia/verify_musical_anchors.py` from the repository root. -This asserts 219 unique IDs in both files and exact correspondence for IDs, labels, families, subfamilies, vectors and descriptive tags. The original `calibrated_219.json` and `.bin1024` are never rewritten by the script. +This asserts 219 unique IDs in both files and exact correspondence for IDs, labels, families, subfamilies, vectors and descriptive tags. It also checks that the four musical fields are non-empty strings and match a pinned SHA-256 of their canonical JSON, so an altered or emptied annotation fails. Checks raise explicitly (no `assert`), so they also run under `python -O`; negative controls live in `test_verify_qualia.py` and run in CI (`.github/workflows/qualia-verify.yml`). The original `calibrated_219.json` and `.bin1024` are never rewritten by the script. diff --git a/data/qualia/test_verify_qualia.py b/data/qualia/test_verify_qualia.py new file mode 100644 index 000000000..4ecdc7e2c --- /dev/null +++ b/data/qualia/test_verify_qualia.py @@ -0,0 +1,71 @@ +"""Negative controls for the two qualia verifiers. + +Run as `python3 -O -m unittest discover -s data/qualia -p 'test_*.py'`: the +`-O` flag strips `assert`, so these tests also prove the verifiers do not rely +on it. Each test mutates an in-memory copy; no file is written. +""" +import copy +import importlib.util +import json +import unittest +from pathlib import Path + +ROOT = Path(__file__).resolve().parent + + +def load(name): + spec = importlib.util.spec_from_file_location(name, ROOT / f"{name}.py") + module = importlib.util.module_from_spec(spec) + spec.loader.exec_module(module) + return module + + +anchors_v = load("verify_musical_anchors") +enrich_v = load("verify_music_enrichment") +CAL = json.loads((ROOT / "calibrated_219.json").read_text(encoding="utf-8")) +ANCHORS = json.loads((ROOT / "calibrated_219.musical_anchors.json").read_text(encoding="utf-8")) +ENRICHED = json.loads((ROOT / "calibrated_219.music_enriched.json").read_text(encoding="utf-8")) + + +class AnchorsVerifier(unittest.TestCase): + def test_committed_archive_passes(self): + anchors_v.verify(CAL, ANCHORS) + + def test_altered_musical_value_is_refused(self): + bad = copy.deepcopy(ANCHORS) + bad[0]["harmonic_bias"][0] = bad[0]["harmonic_bias"][0] + " (edited)" + with self.assertRaises(anchors_v.VerificationError): + anchors_v.verify(CAL, bad) + + def test_emptied_musical_field_is_refused(self): + bad = copy.deepcopy(ANCHORS) + bad[5]["neighbors"] = [] + with self.assertRaises(anchors_v.VerificationError): + anchors_v.verify(CAL, bad) + + def test_label_mismatch_is_refused(self): + bad = copy.deepcopy(ANCHORS) + bad[3]["label"] = "not the label" + with self.assertRaises(anchors_v.VerificationError): + anchors_v.verify(CAL, bad) + + +class EnrichmentVerifier(unittest.TestCase): + def test_committed_sidecar_passes(self): + enrich_v.verify(CAL, ENRICHED, ANCHORS) + + def test_well_formed_but_different_value_is_refused(self): + bad = copy.deepcopy(ENRICHED) + bad["entries"][7]["melodic_motions"] = ["a plausible but wrong motion"] + with self.assertRaises(enrich_v.VerificationError): + enrich_v.verify(CAL, bad, ANCHORS) + + def test_empty_sidecar_is_refused(self): + bad = copy.deepcopy(ENRICHED) + bad["entries"] = [] + with self.assertRaises(enrich_v.VerificationError): + enrich_v.verify(CAL, bad, ANCHORS) + + +if __name__ == "__main__": + unittest.main() diff --git a/data/qualia/verify_music_enrichment.py b/data/qualia/verify_music_enrichment.py index 7cf04c6bc..41626b24f 100644 --- a/data/qualia/verify_music_enrichment.py +++ b/data/qualia/verify_music_enrichment.py @@ -1,22 +1,68 @@ #!/usr/bin/env python3 -"""Archival consistency fixture, not production runtime code.""" +"""Archival consistency fixture, not production runtime code. + +Every check raises explicitly instead of using `assert`, so it still runs +under `python -O` / `PYTHONOPTIMIZE`, which strips assert statements. +""" import json +import sys from pathlib import Path ROOT = Path(__file__).resolve().parent -canonical = json.loads((ROOT / "calibrated_219.json").read_text(encoding="utf-8")) -enriched = json.loads((ROOT / "calibrated_219.music_enriched.json").read_text(encoding="utf-8")) -original = canonical["entries"] -extra = enriched["entries"] -assert canonical["count"] == enriched["count"] == len(original) == len(extra) == 219 -ids = [x["id"] for x in original] -extra_ids = [x["id"] for x in extra] -assert len(set(ids)) == len(set(extra_ids)) == 219, "duplicate ID" -assert set(ids) == set(extra_ids), "sidecar changes ID inventory" -assert enriched["join_key"] == "id" -for entry in extra: - assert set(entry) == {"id", "melodic_motions", "harmonic_bias", "truth_anchor_candidates", "neighbors"} - for field in ("melodic_motions", "harmonic_bias", "truth_anchor_candidates", "neighbors"): - assert isinstance(entry[field], list) and entry[field], (entry["id"], field) - assert all(isinstance(v, str) and v.strip() for v in entry[field]), (entry["id"], field) -print("PASS: 219/219 IDs match; musical enrichment is additive and complete.") +FIELDS = ("melodic_motions", "harmonic_bias", "truth_anchor_candidates", "neighbors") + + +class VerificationError(Exception): + pass + + +def check(condition, message): + if not condition: + raise VerificationError(message) + + +def verify(canonical, enriched, anchors): + original = canonical["entries"] + extra = enriched["entries"] + check( + canonical["count"] == enriched["count"] == len(original) == len(extra) == 219, + "counts differ from 219", + ) + ids = [x["id"] for x in original] + extra_ids = [x["id"] for x in extra] + check(len(set(ids)) == len(set(extra_ids)) == 219, "duplicate ID") + check(set(ids) == set(extra_ids), "sidecar changes ID inventory") + check(enriched["join_key"] == "id", "join_key is not id") + by_id = {a["id"]: a for a in anchors} + for entry in extra: + check(set(entry) == {"id", *FIELDS}, f"{entry.get('id')}: unexpected keys {sorted(entry)}") + for field in FIELDS: + values = entry[field] + check(isinstance(values, list) and values, f"{entry['id']}: {field} missing or empty") + check( + all(isinstance(v, str) and v.strip() for v in values), + f"{entry['id']}: {field} has a blank or non-string value", + ) + # The sidecar must carry exactly the archived annotations, not + # merely well-formed lists. + check( + values == by_id[entry["id"]][field], + f"{entry['id']}: {field} differs from calibrated_219.musical_anchors.json", + ) + + +def main(): + canonical = json.loads((ROOT / "calibrated_219.json").read_text(encoding="utf-8")) + enriched = json.loads((ROOT / "calibrated_219.music_enriched.json").read_text(encoding="utf-8")) + anchors = json.loads((ROOT / "calibrated_219.musical_anchors.json").read_text(encoding="utf-8")) + try: + verify(canonical, enriched, anchors) + except VerificationError as e: + print(f"FAIL: {e}", file=sys.stderr) + return 1 + print("PASS: 219/219 IDs match; musical enrichment is additive, complete and equal to the archived annotations.") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/data/qualia/verify_musical_anchors.py b/data/qualia/verify_musical_anchors.py index 939f3cbe9..eb98d686e 100644 --- a/data/qualia/verify_musical_anchors.py +++ b/data/qualia/verify_musical_anchors.py @@ -3,41 +3,95 @@ Usage: python3 data/qualia/verify_musical_anchors.py No dependencies, no files modified. + +Every check raises explicitly instead of using `assert`, so it still runs +under `python -O` / `PYTHONOPTIMIZE`, which strips assert statements. """ +import hashlib import json +import sys from pathlib import Path ROOT = Path(__file__).resolve().parent -with (ROOT / "calibrated_219.json").open(encoding="utf-8") as f: - calibrated = json.load(f) -with (ROOT / "calibrated_219.musical_anchors.json").open(encoding="utf-8") as f: - original = json.load(f) +MUSICAL_FIELDS = ("melodic_motions", "harmonic_bias", "truth_anchor_candidates", "neighbors") + +# SHA-256 of the four archival fields of all 219 records, as canonical JSON +# ({id: {field: value}}, sorted keys, compact separators, UTF-8). These fields +# are this file's unique archival content, so a type check alone would accept +# an altered or emptied annotation. Recompute only when the archive is +# deliberately replaced, and say so in the commit. +MUSICAL_FIELDS_SHA256 = "027f6753cbe17f14109d45aefb679b1baf363e5333a87cb720f112d3c49147dc" + + +class VerificationError(Exception): + pass + + +def check(condition, message): + if not condition: + raise VerificationError(message) -assert calibrated.get("schema") == "ada.qualia.calibrated/1" -assert calibrated.get("count") == 219 -assert len(calibrated["axes_17d"]) == 17 -assert len(calibrated["entries"]) == len(original) == 219 def by_id(rows): result = {} for row in rows: - assert "id" in row, "missing id" - assert row["id"] not in result, f"duplicate id: {row['id']}" + check("id" in row, "missing id") + check(row["id"] not in result, f"duplicate id: {row['id']}") result[row["id"]] = row return result -a = by_id(calibrated["entries"]) -b = by_id(original) -assert set(a) == set(b), f"ID set difference: {set(a) ^ set(b)}" - -for ident, src in b.items(): - dst = a[ident] - for field in ("label", "family", "subfamily"): - assert src[field] == dst[field], f"{ident}: {field} differs" - assert src["vector"] == dst["vector_17d"], f"{ident}: 17D vector differs" - assert set(src["vector"]) == set(calibrated["axes_17d"]), f"{ident}: axes differ" - assert src["qualia"] == dst["qualia_tags"], f"{ident}: qualia tags differ" - for field in ("melodic_motions", "harmonic_bias", "truth_anchor_candidates", "neighbors"): - assert isinstance(src[field], list), f"{ident}: missing {field}" - -print("OK: 219/219 IDs and primary fields identical; musical annotations retained.") + +def musical_digest(rows): + payload = {ident: {f: row[f] for f in MUSICAL_FIELDS} for ident, row in rows.items()} + blob = json.dumps(payload, sort_keys=True, ensure_ascii=False, separators=(",", ":")) + return hashlib.sha256(blob.encode("utf-8")).hexdigest() + + +def verify(calibrated, original): + check(calibrated.get("schema") == "ada.qualia.calibrated/1", "unexpected schema") + check(calibrated.get("count") == 219, "count is not 219") + check(len(calibrated["axes_17d"]) == 17, "axes_17d is not 17 long") + check(len(calibrated["entries"]) == len(original) == 219, "entry counts differ from 219") + + a = by_id(calibrated["entries"]) + b = by_id(original) + check(set(a) == set(b), f"ID set difference: {set(a) ^ set(b)}") + + for ident, src in b.items(): + dst = a[ident] + for field in ("label", "family", "subfamily"): + check(src[field] == dst[field], f"{ident}: {field} differs") + check(src["vector"] == dst["vector_17d"], f"{ident}: 17D vector differs") + check(set(src["vector"]) == set(calibrated["axes_17d"]), f"{ident}: axes differ") + check(src["qualia"] == dst["qualia_tags"], f"{ident}: qualia tags differ") + for field in MUSICAL_FIELDS: + values = src.get(field) + check(isinstance(values, list) and values, f"{ident}: {field} missing or empty") + check( + all(isinstance(v, str) and v.strip() for v in values), + f"{ident}: {field} has a blank or non-string value", + ) + + digest = musical_digest(b) + check( + digest == MUSICAL_FIELDS_SHA256, + f"musical annotations changed: sha256 {digest} != pinned {MUSICAL_FIELDS_SHA256}", + ) + + +def main(): + with (ROOT / "calibrated_219.json").open(encoding="utf-8") as f: + calibrated = json.load(f) + with (ROOT / "calibrated_219.musical_anchors.json").open(encoding="utf-8") as f: + original = json.load(f) + try: + verify(calibrated, original) + except VerificationError as e: + print(f"FAIL: {e}", file=sys.stderr) + return 1 + print("OK: 219/219 IDs and primary fields identical; musical annotations retained and match the pinned digest.") + return 0 + + +if __name__ == "__main__": + sys.exit(main()) diff --git a/docs/research/linguistic-lego-grammar-to-query-rfc.md b/docs/research/linguistic-lego-grammar-to-query-rfc.md index fd1acb195..941f9ccae 100644 --- a/docs/research/linguistic-lego-grammar-to-query-rfc.md +++ b/docs/research/linguistic-lego-grammar-to-query-rfc.md @@ -163,7 +163,7 @@ Use an **independently defined semantic-query fixture set** (the corpus itself i 1. Paraphrases across languages with distinct case/preposition/word-order constructions. 2. Known near-misses with different quantifier, scope, polarity, tense, role or evidence binding. 3. German Wechselpräposition (`wo` vs `wohin`), dative recipient vs beneficiary, and accusative object vs direction. -4. Relative clauses: antecedent gender/number/case agreement *within the relative clause*, long references outside the i4 window, and ambiguous neuter pronouns. +4. Relative clauses: the relative pronoun agrees with its antecedent in **gender and number only**; its **case** comes from its role inside the relative clause (`dem Kind, das dort wartet`: antecedent dative, pronoun nominative — valid, and must not be rejected). Plus long references outside the i4 window, and ambiguous neuter pronouns. (Corrected 2026-10-19, #1603 review: case was wrongly listed as agreement.) 5. TEKAMOLO event scoping: `damit` as PURPOSE, `weil` as REASON, `so` as MODAL, `da` ambiguous, clause attachment. 6. Haspelmath connected-region held-out languages, disconnected complete counterexamples and incomplete attestations. 7. Natural-language graph questions with `which`, `why`, negation, existential/universal scope, time qualifiers and evidence restrictions. diff --git a/docs/research/versioned-semantic-candidates-64-thoughts-rfc.md b/docs/research/versioned-semantic-candidates-64-thoughts-rfc.md index 4d450e5eb..29b1275fd 100644 --- a/docs/research/versioned-semantic-candidates-64-thoughts-rfc.md +++ b/docs/research/versioned-semantic-candidates-64-thoughts-rfc.md @@ -56,7 +56,7 @@ These are **logical** terms to lower to the *existing* SoA and thought-git carri | `EvidenceBase` | independently attested source stamps/roots supporting or contesting a claim | not thought count, translation count or audience count | | `Perspective` | compiled thought program, front end, rules and interpretive lens | a named philosophical lens is not a historical individual's actual judgment | | `ReadSet(t, v)` | addresses/fields the thought inspected, plus negative dependencies | must support rebase invalidation when prior reads change | -| `CandidateOutcome` | derived result: Absent / Admissible / Contested / Preferred / Established / Abstained / Superseded | a view of versioned evidence, NOT a CE64 bit or write-side fact rewrite | +| `CandidateOutcome` | derived result: Absent / Admissible / Contested / Preferred / Established / Abstained / Superseded / Rejected | a view of versioned evidence, NOT a CE64 bit or write-side fact rewrite | | `ResolutionReceipt` | canonical claim(s), decision policy version, supporting/contesting roots, alternatives, program hash, base and landing version | required to replay and compare, not a bare latest-wins value | **Names above are proposed logical vocabulary, not committed Rust types or field IDs.** A receipt's provenance may be represented by source bitsets and sealed-version references when the corresponding existing facilities support it; do not import an arbitrary new witness pointer. If it cannot be represented safely, refuse the write pending a narrow ABI decision. @@ -84,6 +84,7 @@ A changed *calibrated* reference value (COCA/DeReKo frequency, UD gold correctio - `Contested`: admissible rivals or conflicting evidence remain, possibly one preferred. - `Abstained`: insufficient constraints, scope/identity unknown, or source access denied. - `Superseded`: new evidence or changed context makes an earlier candidate no longer preferred; history and receipt remain. +- `Rejected` (added 2026-10-19, #1604 review): the candidate is refused under an explicit, versioned decision policy (e.g. a hard constraint or a refuting evidence root fails it). Distinct from `Superseded`, which is only for a previously preferred candidate displaced by better evidence. Rejection keeps its witnesses: the refuting evidence roots, the policy version and the program hash stay in the `ResolutionReceipt`, so a later change to that evidence can reopen the candidate. A query may return many candidates and not a winner. No fabricated single answer. **Missing in an open-world knowledge graph ≠ false**; negation must state its closed-world/stratification scope. diff --git a/docs/research/versioned-semantic-candidates-fixtures.json b/docs/research/versioned-semantic-candidates-fixtures.json index ec45bed2a..081c596bc 100644 --- a/docs/research/versioned-semantic-candidates-fixtures.json +++ b/docs/research/versioned-semantic-candidates-fixtures.json @@ -265,7 +265,10 @@ }, "expected": { "v2_derived": [], - "must_rederive_from_scratch": true, + "retracted": [ + "B" + ], + "maintenance_note": "Assert the derived result only. DRed (delete-and-rederive) or an independent from-scratch reference are both admissible (corrected 2026-10-19, #1604 review).", "stale_B_refused": true } }, From 429fcba62c68736c53a5438103a6e2d6f2817e91 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Oct 2026 19:54:23 +0000 Subject: [PATCH 4/5] d-rmap: palette and map generations in the tile and binding identities #1617 review (both findings verified): RelationTile was keyed by focus frame only, so it survived a map append, delete, compaction or reseal and could return obsolete adjacency; MapPalette had no generation of its own although the execution context requires MapPaletteId+Generation. RelationTile is now keyed by global MapId + map generation (or seal digest) + FocusBinding generation + access scope; MapPalette carries a palette generation that a slot reassignment bumps. Adds a falsifier table (map regeneration, palette-slot reassignment, focus-slot reuse, thought incarnation reuse, stale tile access, cross-tenant change). Architecture only; nothing implemented, CE64 untouched, RelAlg owns no tables. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VyWZYKycy6MoYDxHRVnV5K --- ...map-separate-tables-thought-palettes-v1.md | 23 ++++++++++++++++--- 1 file changed, 20 insertions(+), 3 deletions(-) diff --git a/.claude/plans/d-rmap-separate-tables-thought-palettes-v1.md b/.claude/plans/d-rmap-separate-tables-thought-palettes-v1.md index 5ed300b62..1064dca03 100644 --- a/.claude/plans/d-rmap-separate-tables-thought-palettes-v1.md +++ b/.claude/plans/d-rmap-separate-tables-thought-palettes-v1.md @@ -11,7 +11,7 @@ | OGAR Class / ClassView / DTO-IR | Types, fields, associations, actions, compiled class vocabulary, generated field masks and DTO projection descriptors | Persistent relationship index pages, RelAlg evaluator, runtime DTO copies | | RelationshipMapStore | Separate relation-fact tables, sorted index permutations, global relationship-map identity, seal/version, eligible physical capabilities and optional relation tiles | Datalog syntax/AST, CE64 fields, per-thought graph copies | | ThoughtMapPaletteBinding | Thought slot and incarnation -> MapPaletteId under a witnessed frame; selected subset and order of maps | Relation-fact payload, evidence roots | -| MapPalette | Palette ID and 0..255 local map selectors -> globally stable MapId + generation | Global relationship truth or per-object row materialization | +| MapPalette | Palette ID **and its own palette generation**, plus 0..255 local map selectors -> globally stable MapId + map generation | Global relationship truth or per-object row materialization | | FocusBinding | Source/target global identities -> focus-local slots; lifetime, version and ACL attestation | Persistent semantic facts | | BIND | Resolves metadata and borrows native spans, masks, indexed ranges or permutations with a mapping witness | RelAlg rewrite rules, storage ownership, separate runtime evaluator | | RelAlg | Pure algebra and rule meaning: variables, set/bag semantics, joins, recursion contract, measures, normalization | Map tables, index build, cache eviction, DTO storage | @@ -30,10 +30,10 @@ The following are proposed **logical tables**, not physical record layouts or ma | RelationFacts | Canonical fact/statement identities, typed arguments, evidence roots, time/version/ACL | Source of truth | | RelationOrder | Sealed indexed permutations of original fact row references: e.g. predicate-subject-object, object-predicate-subject | Derived ordering; no source payload copy | | **RelationshipMap** | Separate MapId, map generation, underlying relation-order view handles, constraints and capability metadata | **Global shared table** | -| **MapPalette** | MapPaletteId, local map ordinal 0..255 to MapId and map generation | **Shared palette table** | +| **MapPalette** | MapPaletteId + **palette generation**, local map ordinal 0..255 to MapId and map generation. Reassigning any slot bumps the palette generation (or mints a new palette; palettes may also be immutable) | **Shared palette table** | | **ThoughtMapPaletteBinding** | (thought slot, incarnation, frame witness) to MapPaletteId; optional sparse palette visibility override | **Separate thought map** | | FocusBinding | Frame witness, source/target slot-to-global identity maps and authorization | Local map binding | -| RelationTile | Optional cached source-slot to local target mask for one MapId and frame generation | Disposable derived bits | +| RelationTile | Optional cached source-slot to local target mask, keyed by **global MapId + map generation (or index seal digest)** + FocusBinding generation + authorization scope. A frame id or local palette slot alone is never a sufficient key | Disposable derived bits | | RelationDelta | Separately typed fact changes, binding changes, tile invalidations, speculative thought claims | Incremental witnesses | **One map may be referenced by many palettes and many thoughts without copying its fact storage.** A local palette number is never a global map identity. Thought 0 is immutable givens; thoughts 1..63 select or overlay views without copying canonical relation tables. Any per-thought changing of map selection is a binding delta, not a mutation of relation truth. @@ -104,6 +104,23 @@ Typed selection of method or ActionDef targets is eligible for relational evalua Sequence if later approved: (a) audit existing OGAR DTO/ClassView and Quack physical binding seams, (b) prototype standalone RelationMap borrow semantics, (c) implement/test the thought-to-map-palette lookup using typed tables, (d) establish the existing Quack/RelAlg execution parity without a second evaluator, (e) only then consider optional cached tiles and incremental spatial frontier overlays. +### 6a. Generation witnesses (2026-10-19 correction, #1617 review) + +Two review findings, both correct. (1) A `RelationTile` keyed only by focus/frame keeps matching after its map's facts are appended, deleted, compacted or resealed, so it returns obsolete adjacency. Its key must name the global `MapId` and the map generation (or index seal digest). (2) `MapPalette` had no generation of its own, although §4 requires `MapPaletteId + Generation`; per-entry map generations cannot tell which slot-to-map assignment a thought bound. A palette carries its own generation, and reassigning a slot invalidates dependent bindings and tiles instead of silently reusing them. + +Falsifiers, each a refusal (never a plausible stale answer): + +| Change | Must refuse | +| --- | --- | +| Map regeneration (append / delete / compaction / reseal) | any tile or binding holding the old map generation or seal digest | +| Palette-slot reassignment | any binding or tile holding the old palette generation | +| Focus-slot reuse | a tile built for the previous FocusBinding generation | +| Thought incarnation reuse | a ThoughtMapPaletteBinding from the previous incarnation | +| Stale tile access | a tile whose key generations do not all match the current context | +| Cross-tenant / authorization change | a tile or binding minted under another access scope | + +Status: PROPOSED. Nothing here is implemented; RelationshipMap storage stays a proposal until a separately approved implementation establishes its legality (co-addressed operands, not a gather) and its economics. Map identity never enters CausalEdge64, and RelAlg never owns map tables. + **Stop condition:** any design that requires copying canonical map facts per thought, using RelAlg as a table store, or allocating new CE64 bits to identify MapId/MapPaletteId has chosen the wrong boundary. **Short form: RelationshipMapStore stores. OGAR types. ThoughtMapPalette selects. BIND borrows. RelAlg describes. Quack lowers. Mask-RISC executes. CE64 remains opaque.** From b2c5453cd8fed0e20d3862c23139a1ed47858a9c Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 19 Oct 2026 19:59:31 +0000 Subject: [PATCH 5/5] board: record #1601-#1617 and the post-merge recovery The 17 PRs merged with no board rows. Prepends arc entries for each, STATUS_BOARD rows (ACT-R crate, graph_hop quarantine, D-RMAP, D-SRAM with D-SRAM-4 BLOCKED, D-JCR, D-JCSBI, CPG, VSC), plan index entries for the seven plans, ISS-GATHER-HOP-1616, a LATEST_STATE section, and an entry with the review-thread reconciliation table. Entries index regenerated; the supersession index is unchanged. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_01VyWZYKycy6MoYDxHRVnV5K --- .claude/board/INTEGRATION_PLANS.md | 12 ++ .claude/board/ISSUES.md | 9 ++ .claude/board/LATEST_STATE.md | 6 + .claude/board/PR_ARC_INVENTORY.md | 119 ++++++++++++++++++ .claude/board/STATUS_BOARD.md | 45 +++++++ ...026-10-19-post-merge-recovery-1601-1617.md | 27 ++++ .claude/board/entries/README.md | 3 +- 7 files changed, 220 insertions(+), 1 deletion(-) create mode 100644 .claude/board/entries/2026-10-19-post-merge-recovery-1601-1617.md diff --git a/.claude/board/INTEGRATION_PLANS.md b/.claude/board/INTEGRATION_PLANS.md index afcfefe55..ef5673f7b 100644 --- a/.claude/board/INTEGRATION_PLANS.md +++ b/.claude/board/INTEGRATION_PLANS.md @@ -1,3 +1,15 @@ +## 2026-10-19 — catch-up: seven plans from #1605 and #1612–#1617 had no index entry + +**Status:** INDEX CATCH-UP (post-merge recovery, entry `2026-10-19-post-merge-recovery-1601-1617.md`). All PROPOSAL; nothing implemented. + +- `souffle-ram-64-thought-stack-v1.md` (#1612) — D-SRAM-0..7: Soufflé AST → RAM lowering per thought lifetime. D-SRAM-4 (recursive region scheduling) is BLOCKED: its target was the banned d′ gather driver. The optimizer gate is split: answers stay equal with a rewrite off; only disabling a semantic guard may fail. +- `jc-r-statistical-api-v1.md` (#1613) — D-JCR-0..8: a typed R-style frontend over JC estimators lowered to mask-risc. `jc::jirak` is NOT a calibration API (only `prove()`); both row limits (total input `2^32`, per group) are stated. +- `jc-sbi-counterfactual-integration-v1.md` (#1614) — D-JCSBI-0..9: SBI ladder (exact discrete → ABC → SBC → SMC → EIG) with DisMech validity gates; 48 preregistered fixtures, none run. +- `causal-pickaxe-resident-git-lance13-temporal-v1.md` (#1605) — CPG-0..6: Git porcelain over D-TGA. Prerequisite corrected to the pinned Lance `13.*` / LanceDB `0.40.*`; row identity reuses the H14c-5 measurement. +- `d-rmap-implicit-relationship-register-v1.md` (#1617) — D-RMAP-1; superseded on ownership by D-RMAP-1A. +- `d-rmap-separate-tables-thought-palettes-v1.md` (#1617) — D-RMAP-1A, the controlling contract. Palette and map generations added to the tile key 2026-10-19 (§6a falsifiers). +- `d-rmap-2-context-tile-algebra-probe-v1.md` (#1617) — D-RMAP-2: preregistered GraphBLAS vs BF16 tile probe; not run. + ## 2026-10-17 — thought-git-api-v1 — a git-like API over thought tables → `.claude/plans/thought-git-api-v1.md` **Status:** D-TGA-0..6 PROPOSAL, test-first; nothing built. diff --git a/.claude/board/ISSUES.md b/.claude/board/ISSUES.md index 14535ea18..b86696ab0 100644 --- a/.claude/board/ISSUES.md +++ b/.claude/board/ISSUES.md @@ -1,3 +1,12 @@ +## ISS-GATHER-HOP-1616 — the merged `OutgoingHop` reads positions taken from another lane's values (2026-10-19) + +**Status:** BLOCKED (quarantined; waits on GATHER-DECISION). **Basis:** VERIFIED-IN-CODE (`crates/lance-graph-mask-risc/src/graph_hop.rs`: two `MaskOp::Gather` over `frontier[sources[i]]` and `visible[targets[i]]`, then `ScatterOrU32` by `targets[i]`). + +- #1616 merged a hop of exactly the shape the 2026-10-16 no-gather ruling bans (D-HOLO H14c/H14d: the join is the layout). The remediation PR does not delete it and does not rename it into a BIND; it compiles only under the off-by-default feature `quarantined-gather-hop`. +- Default build: a `compile_fail` doctest proves `OutgoingHop` is unreachable (disable-verified). The six original tests run in CI with the feature on. +- The petgraph `experiments/lance-fold-hop` pins an older rev (`66636da`); bumping it past the quarantine must enable the feature explicitly. +- **What closes it:** a written GATHER-DECISION. Either the hop is rewritten as a co-addressed read (`Thought(t)[T_a[i] : T_b[i]]`) or the decision lists it as an admitted read and the feature is removed. + ## ISS-RELALG-ABSORPTION-AFTER-DE-MORGAN — `normalize` can leave a program wider than as written (2026-10-16) **Status:** OPEN. **Basis:** MEASURED (D-HOLO-H14d stage 1, `crates/holo-h14d-probe`, 2 of 2,000 generated programs). diff --git a/.claude/board/LATEST_STATE.md b/.claude/board/LATEST_STATE.md index 9b4068c3d..4335dea7d 100644 --- a/.claude/board/LATEST_STATE.md +++ b/.claude/board/LATEST_STATE.md @@ -1,3 +1,9 @@ +## 2026-10-19 — main after #1617 (merged `47697c77`); post-merge recovery in PR + +- **On main since #1597:** #1601–#1617 (17 PRs: research notes, plans, a qualia archive, the ACT-R crate, the mask-risc hop, the D-RMAP plans). None had board rows; the arc entries, STATUS_BOARD rows and plan index entries are added in this PR. +- **In PR (remediation):** `lance-graph-actr` → `lance-graph-act-r` with a stale-candidate refusal and CI; #1616's `OutgoingHop` quarantined behind `quarantined-gather-hop` (`ISS-GATHER-HOP-1616`); D-SRAM-4 BLOCKED; jirak gap and row limits; Lance 13 prerequisite; `Rejected` outcome; relative-pronoun case; qualia verifiers without `assert` and with a pinned digest; D-RMAP generations. +- Contract inventory delta: none. + ## 2026-10-17 — main after #1597; thinking-tables wiring in PR - **On main since #1594:** #1592 (ledger revision c), #1595 (CE64 one layout), #1596 (Simpson co-research, P-pool test), #1598 (Haiku cards read in full, output capped), #1597 (epistemic frontier capstone; 46..49 activation, W = thought layer). diff --git a/.claude/board/PR_ARC_INVENTORY.md b/.claude/board/PR_ARC_INVENTORY.md index b46e01cab..8ec3a0196 100644 --- a/.claude/board/PR_ARC_INVENTORY.md +++ b/.claude/board/PR_ARC_INVENTORY.md @@ -1,3 +1,122 @@ +## 2026-10-19 — lance-graph PR #1617 (merged `47697c77`, branch `design/relationship-map-implicit-register-v1`, head `55be2fed`, 7 commits) — D-RMAP: separate RelationshipMap tables and thought-selected palettes + +- **Added:** plans `.claude/plans/d-rmap-implicit-relationship-register-v1.md` (D-RMAP-1), `d-rmap-separate-tables-thought-palettes-v1.md` (D-RMAP-1A, the controlling contract for ownership and CE64 opacity) and `d-rmap-2-context-tile-algebra-probe-v1.md` (D-RMAP-2, a preregistered GraphBLAS vs BF16 tile comparison); entry `2026-10-19-d-rmap-implicit-relationship-register.md`; entries README row. Nothing implemented. +- **Locked:** none. Status PROPOSAL, not approved for implementation. CE64 is unchanged; S:P:O and W do not carry a MapId, palette id or frame id; the 2026-10-16 no-gather firewall stays in force. +- **Deferred / open:** two review findings (a relation tile key lacked the map generation; the palette mapping lacked its own generation) were fixed in the 2026-10-19 remediation PR. The amortization equation against direct sorted-index traversal is unmeasured. +- **Confidence:** doc only. No measurement and no benchmark result are claimed. + +## 2026-10-19 — lance-graph PR #1616 (merged `da3f5c6e`, branch `feat/mask-risc-scoped-frontier-20261019`, head `615fef73`, 3 commits) — mask-risc scoped outgoing graph hop + +- **Added:** `crates/lance-graph-mask-risc/src/graph_hop.rs` (`OutgoingHop`: one program of two `MaskOp::Gather` and `ScatterOrU32`, run over borrowed edge columns, a graph snapshot, a frontier mask and a result buffer; witness, shape and authorization checks first; six regression tests) and its export in `src/lib.rs`. +- **Locked:** none. One hop is an externally demanded terminal; iterative repeat/BFS continuation is not claimed. +- **Deferred / open:** quarantined behind the off-by-default `quarantined-gather-hop` feature in the 2026-10-19 remediation PR, because it reads positions taken from another lane's values (the 2026-10-16 no-gather ruling); `ISS-GATHER-HOP-1616`. The petgraph consumer PR is still to come. +- **Confidence:** probe-level code. The PR body lists its tests and fmt/clippy as not run in that session. + +## 2026-10-19 — lance-graph PR #1615 (merged `b10e46a1`, branch `feat/actr-production-kernel-20261019`, head `2daf0871`, 3 commits) — experimental witnessed ACT-R production arbitration crate + +- **Added:** crate `crates/lance-graph-actr` (`Cargo.toml`, `README.md`, `src/lib.rs`): deterministic conflict resolution over an externally evaluated eligibility mask, a local `Snapshot`, a witness, refusal on non-finite scores, six unit tests. It returns a proposal and executes no effect. Standalone workspace; no CI job built it. +- **Locked:** none. The local `Snapshot` is not the canonical ABI. +- **Deferred / open:** renamed to `lance-graph-act-r` and given a stale-witness refusal plus a CI job in the 2026-10-19 remediation PR. The review finding (candidates not bound to the evaluated snapshot) was valid. Typed buffers, Mask-RISC matching, utility learning and timing remain future work. +- **Confidence:** probe-level code. The PR body lists its tests as not run. + +## 2026-10-19 — lance-graph PR #1614 (merged `1b26d9c9`, branch `docs/jc-sbi-dismech-counterfactual-v1`, head `413cb780`, 8 commits) — JC simulation-based inference plan with DisMech counterfactual gates + +- **Added:** `.claude/plans/jc-sbi-counterfactual-integration-v1.md` (ownership, ABC/SMC/SBC/EIG ladder, DisMech validity gates, D-JCSBI-0..9, perturbation protocol, mechanical Sudoku and a small ACT-R policy) and `docs/research/jc-sbi-counterfactual-falsifiers-v1.md` (48 preregistered fixtures, none executed). Nothing implemented. +- **Locked:** none. `ogar-dismech` is a vocabulary, not a simulation engine; `chain_counterfactual.rs` edge-cut replay is not do-calculus. +- **Deferred / open:** the two review findings (EIG with current-design nonidentifiability; underflow vs zero prior support) were already corrected in the merged text (SB-24b/c, SB-02a/b). First follow-up is D-JCSBI-0/1/2. +- **Confidence:** doc only. No calibration, benchmark or test is claimed. + +## 2026-10-19 — lance-graph PR #1613 (merged `58b50fcb`, branch `docs/jc-r-statistical-api-plan-20261019`, head `48d02ccf`, 1 commit) — R statistical API and formula lowering over JC + +- **Added:** `.claude/plans/jc-r-statistical-api-v1.md`: a restricted typed R-style frontend and an external client binding, reuse of existing JC estimators, lowering through relalg/R2IL/Quack to mask-risc, D-JCR-0..8, an R differential-oracle strategy. Nothing implemented. +- **Locked:** none. No embedded R interpreter in the hot path. +- **Deferred / open:** fixed in the 2026-10-19 remediation PR: `jc::jirak` is not a calibration API (its only public function is `prove()`), and the plan now states the total-input row limit as well as the per-group bound. First implementation step is D-JCR-0/1. +- **Confidence:** doc only. No measurement is claimed. + +## 2026-10-19 — lance-graph PR #1612 (merged `18089704`, branch `docs/souffle-ram-64-thought-stack-20261019`, head `ad428a80`, 2 commits) — Soufflé AST to RAM lowering plan across 64 thought lifetimes + +- **Added:** `.claude/plans/souffle-ram-64-thought-stack-v1.md` (D-SRAM-0..7) and `docs/research/souffle-ram-64-thought-falsifiers.md` (32 preregistered cases, none executed). Nothing implemented. +- **Locked:** none. Fixpoint iterations run inside a thought; the W field does not cap recursion. +- **Deferred / open:** fixed in the 2026-10-19 remediation PR: D-SRAM-4 retargeted to BLOCKED (it pointed at the prohibited d′ gather driver), and the optimizer negative controls now keep semantic parity when a rewrite is disabled. The minimum D-SRAM-0/1 probe is not written. +- **Confidence:** doc only. No compilation, benchmark or parity run is claimed. + +## 2026-10-19 — lance-graph PR #1611 (merged `1d18b872`, branch `docs/arxiv-mul-meta-uncertainty-hyperon-reading-queue-20261019`, head `f588d7e3`, 8 commits) — .arxiv notes: MUL meta-uncertainty, Hyperon, dialectics, joins, semantic maps + +- **Added:** eight `.arxiv/` files: reading notes for 2210.07278 (meta-uncertainty vs the CE64 MUL contract), 2502.20233 (SMASH, mask-first thought coordinates) and 2512.17373 (dialectics, excess information); bookmarks for 2310.18318 (Hyperon), 2510.24941, 2610.12692, 2409.20212 and 2412.01423. +- **Locked:** none. Paraphrases and bookmarks, not full transcriptions. Nothing implemented. +- **Deferred / open:** the Hyperon paper's detailed review is deferred; the proposed tests in the notes are not run. +- **Confidence:** doc only; no measurement. + +## 2026-10-19 — lance-graph PR #1610 (merged `23b612c0`, branch `docs/arxiv-dialectics-philosophy-md-20261019`, head `6fc2bfd1`, 4 commits) — .arxiv archive of three Hegel / Leibniz / AI sources + +- **Added:** `.arxiv/plevrakis_2024_can_ai_be_a_subject_like_us_hegelian_approach.md`, `.arxiv/van_tuinen_2020_philosophy_in_the_light_of_ai_hegel_or_leibniz.md`, `.arxiv/hung_vo_2025_the_dialectic_of_ai_hegel_geist_machine_freedom.md`, with provenance and licence notices. +- **Locked:** none. Archived transcriptions only; no claim about AI consciousness or implementation. +- **Deferred / open:** none. +- **Confidence:** doc only. No measurement is claimed. + +## 2026-10-19 — lance-graph PR #1609 (merged `ae15ea90`, branch `docs/34-reasoning-recipes-source-and-wiring`, head `24919b17`, 1 commit) — 34 reasoning recipes over the 64-thought substrate + +- **Added:** `docs/research/34-reasoning-recipes-lance-graph-plan.md`: placement of the 34 recipes over 64 thought slots, semantic Git witnesses, RelAlg/Datalog, R2IL/mask-risc, NAL/ONA and Hyperon/Atomese adapters. Nothing implemented. +- **Locked:** none. No code modified or deleted. +- **Deferred / open:** the next PR should show one typed derivation with an ablation. +- **Confidence:** doc only. The PR claims no measurement. + +## 2026-10-19 — lance-graph PR #1608 (merged `d8da13b8`, branch `docs/qualia-1571-music-enrichment`, head `78c9a9d5`, 3 commits) — music enrichment sidecar for the 219 qualia + +- **Added:** `data/qualia/calibrated_219.music_enriched.json` (219 records: `melodic_motions`, `harmonic_bias`, `truth_anchor_candidates`, `neighbors`), `data/qualia/MUSIC_ENRICHMENT.md`, `data/qualia/verify_music_enrichment.py`. +- **Locked:** none. Archival data only; `calibrated_219.json`, `calibrated_219.bin1024` and the contracts are untouched. +- **Deferred / open:** fixed in the 2026-10-19 remediation PR: the verifier used `assert` and passed under `python -O`; it now raises explicit errors. +- **Confidence:** measured as a comparison: 219/219 IDs, vectors, tags and labels equal to the #1571 data, as the PR body states. + +## 2026-10-19 — lance-graph PR #1607 (merged `ca4d742b`, branch `docs/qualia-219-musical-anchors-20261018`, head `8d5345cb`, 3 commits) — original 219 musical anchors beside the #1571 corpus + +- **Added:** `data/qualia/calibrated_219.musical_anchors.json` (219 original records, verbatim from the upstream blob), `data/qualia/MUSICAL_ANCHORS.md`, `data/qualia/verify_musical_anchors.py`. +- **Locked:** none. Cold-path archive; no production relabelling; the 806 placeholder states are excluded. +- **Deferred / open:** fixed in the 2026-10-19 remediation PR: the verifier's `assert` checks were stripped under `python -O`; they now raise explicit errors, and the four musical fields are compared against a pinned SHA-256 (`MUSICAL_FIELDS_SHA256`), so a corrupted value fails even when its type is right. +- **Confidence:** measured as a comparison: 219/219 IDs, labels, families, 17D values and tags equal to the #1571 fixture. The musical fields were checked only for type until the remediation PR. + +## 2026-10-18 — lance-graph PR #1606 (merged `31e0d4db`, branch `research/semantic-ring-oracle-c01-c02-20261018`, head `af058caf`, 9 commits) — executable C-01/C-02 semantic ring oracle + +- **Added:** `tools/semantic_ring_oracle/ring_reference.py`, `test_ring_reference.py` (15 adversarial tests), `README.md`; `docs/research/semantic-ring-bound-gold-v1.json`; workflow `.github/workflows/semantic-ring-oracle.yml`. +- **Locked:** the coreference claim is a versioned claim at one symbolic address, visible from sealed revision v17 and not at v16. Wrong branch, dataset or version cannot witness it. +- **Deferred / open:** this is a manually bound Python reference oracle, not a parser, a Lance commit, an R2IL join or source authentication. Connecting DeepNSM/UD bindings and versioned thought writes is the next gate. No Rust path changed. +- **Confidence:** probe. The CI check passed on the head commit (run 39147776033). + +## 2026-10-18 — lance-graph PR #1605 (merged `4b5d9711`, branch `docs/causal-pickaxe-resident-git-lance13-temporal-20261018`, head `42c65b7c`, 5 commits) — Git porcelain, causal Pickaxe and Lance 13 history plan + +- **Added:** `.claude/plans/causal-pickaxe-resident-git-lance13-temporal-v1.md` (Git verbs mapped to existing D-TGA operations; identity and temporal boundaries; grades; landing order) and `docs/research/causal-pickaxe-version-temporal-fixtures.json` (26 preregistered symbolic falsifiers, not executed). Nothing implemented. +- **Locked:** none. Git is porcelain, not a VM; commit ancestry does not certify cause. +- **Deferred / open:** fixed in the 2026-10-19 remediation PR: the prerequisite text still said Lance 7 / LanceDB 0.30 although the workspace pins Lance 13 / LanceDB 0.40. The 64k-row benchmark cited is a Lance 11 figure, not a Lance 13 one. +- **Confidence:** doc only. No new measurement. + +## 2026-10-18 — lance-graph PR #1604 (merged `1e713851`, branch `docs/versioned-semantic-candidate-resolution-20261018`, head `6cadb6a8`, 3 commits) — versioned semantic candidate resolution across 64 thoughts + +- **Added:** `docs/research/versioned-semantic-candidates-64-thoughts-rfc.md` (logical vocabulary: claim identity, candidate set, evidence base, perspective, outcome, receipt) and `docs/research/versioned-semantic-candidates-fixtures.json` (15 symbolic oracle cases, expectations preregistered only). Nothing implemented. +- **Locked:** none. Distinct propositions get distinct candidate NodeGuids; no new Rust types or storage. +- **Deferred / open:** fixed in the 2026-10-19 remediation PR: `CandidateOutcome` gained a `Rejected` outcome, and the premise-deletion fixture now admits DRed. Implementation is gated on D-TGA-1/3/4 and a canonical NodeGuid binding. +- **Confidence:** doc only. No result is claimed. + +## 2026-10-18 — lance-graph PR #1603 (merged `b1c2ed8a`, branch `docs/linguistic-lego-ud-koral-query-abi-20261018`, head `96747ac5`, 2 commits) — language LEGO grammar ABI to multilingual graph queries + +- **Added:** `docs/research/linguistic-lego-grammar-to-query-rfc.md` (corpus priors, UD/KorAP operators, Haspelmath masks, semantic question AST, gated L-0..L-8) and `docs/research/linguistic-lego-corpus-and-falsification-matrix.md` (corpus links, licence cautions, adversarial fixtures). Nothing implemented. +- **Locked:** none. No new width or layout; UD labels grammar, not semantic truth; no gather hidden as a mask. +- **Deferred / open:** fixed in the 2026-10-19 remediation PR: the fixture treated relative-pronoun case as agreement with the antecedent (only gender and number agree). Suggested next: L-1 (UD/CoNLL-U round trip) and L-2 (Krill differential harness). +- **Confidence:** doc only. No benchmark or test is claimed. + +## 2026-10-18 — lance-graph PR #1602 (merged `9f83aa66`, branch `docs/cartesian-epistemic-self-model-20261017`, head `ddc5cb62`, 4 commits) — Cartesian epistemic self-model architecture docs + +- **Added:** `.claude/architecture/README.md`, `.claude/architecture/cartesian-epistemic-self-model.md` (thought-first addressing, occupancy duality, presence planes, self-model and replay) and `.claude/architecture/neurofunctional-rubicon-moore-plasticity.md`. Nothing implemented. +- **Locked:** none. The PR lists what it does not claim: the CE64 migration is not complete, and no new layout, opcode or store is introduced. +- **Deferred / open:** proposed oracle gates (occupancy, source-root independence, Datalog parity, replay, blinded self-prediction) are not built. +- **Confidence:** doc only. The body notes that no runtime tests were run; links were checked. + +## 2026-10-18 — lance-graph PR #1601 (merged `fc527a47`, branch `docs/arxiv-hologram-two-mechanisms-2026-10-17`, head `bc73c8df`, 2 commits) — .arxiv notes: HGR theorem patterns and HRR retrieval bottleneck + +- **Added:** `.arxiv/2408.10592_hologram_is_a_graph_theorem_matches_must_preserve_witnesses.md` and `.arxiv/2606.24948_superposition_capacity_breaks_two_hop_retrieval.md`; each separates published findings from lance-graph hypotheses and tests not run. Nothing implemented. +- **Locked:** none. The notes keep composability, recoverability and certification apart; no claim of a VF3 replacement or a speedup. +- **Deferred / open:** the 2606.24948 full text was unavailable, so some configuration details are marked pending. Follow-ups: match-set parity on a small geometry corpus and an independent FHRR reproduction. +- **Confidence:** doc only. No code or benchmark run. + ## 2026-10-17 — lance-graph PR #1597 (merged `dd00245b`, branch `ccr-9f3b8075-74u47l-epistemic-capstone`, head `134a4d29`, 7 commits) — epistemic frontier capstone; O1/O3 decisions - **Added:** `.claude/knowledge/epistemic-frontier-capstone.md`; entry `2026-10-17-epistemic-frontier-clicks.md`; D-HL-1 note in `ce64-hypothesis-layers-v1.md`, plateau §4 note, STATUS_BOARD row; CLAUDE.md links to `docs/architecture/` and the capstone. diff --git a/.claude/board/STATUS_BOARD.md b/.claude/board/STATUS_BOARD.md index 70b9f1d3c..8f8877377 100644 --- a/.claude/board/STATUS_BOARD.md +++ b/.claude/board/STATUS_BOARD.md @@ -1,3 +1,48 @@ +## Post-merge recovery for #1601–#1617 (2026-10-19) + +These PRs merged with no board rows. Every row below is a PROPOSAL (documents and fixtures) unless it says otherwise. Entry: `entries/2026-10-19-post-merge-recovery-1601-1617.md` (review-thread reconciliation). + +| D-id | scope | status | gate / falsifier | +|---|---|---|---| +| **ACT-R crate** (#1615) | `crates/lance-graph-act-r` (renamed from `lance-graph-actr`): deterministic ACT-R production arbitration over externally evaluated candidates; never executes effects | SHIPPED as experimental crate (standalone, excluded, own CI job `act-r.yml`) | `Refusal::StaleCandidate` on any candidate evaluated at another snapshot; 10 tests, guard disable-verified (3 red) | +| **graph_hop quarantine** (#1616) | `lance-graph-mask-risc::graph_hop::OutgoingHop` (two `MaskOp::Gather` + `ScatterOrU32`) | BLOCKED — compiled only under the off-by-default `quarantined-gather-hop` feature | default build: `compile_fail` doctest proves `OutgoingHop` unreachable (disable-verified); `ISS-GATHER-HOP-1616` | +| D-RMAP-1 | implicit RelationshipMap and focus-relative registers (`d-rmap-implicit-relationship-register-v1.md`) | PROPOSAL (superseded on ownership by D-RMAP-1A) | falsifier matrix F0–F10 in the plan | +| D-RMAP-1A | separate map tables, borrowed projections, thought-selected palettes (`d-rmap-separate-tables-thought-palettes-v1.md`) | PROPOSAL; generation witnesses corrected 2026-10-19 (§6a) | refusal on map regeneration, palette-slot reassignment, focus-slot reuse, incarnation reuse, stale tile, cross-tenant change | +| D-RMAP-2 | context-declaration reuse and GraphBLAS/BF16 tile probe (`d-rmap-2-context-tile-algebra-probe-v1.md`) | PROPOSAL; not run | arms 1–5 in the plan; 297× (D-GTM-0j) is not evidence | +| D-SRAM-0 | inventory Soufflé AST/ast2ram/RAM passes against D-ASM/D-RA/D-TGA owners | Queued | evidence per mapped pass; no code imported | +| D-SRAM-1 | bound AST → RAM-like schedule for pure conjunctive selection | Queued | same answers and read sets on hand-built fixtures; unsupported ops typed-refused | +| D-SRAM-2 | cold optimizer rewrites (SCC/strata, magic sets, ordering, dedup) | Queued (research until D-ASM AST placement and D-RA-2) | optimized == unoptimized == oracle; rewrite off removes only the plan shape; disabling a semantic guard fails | +| D-SRAM-3 | co-addressed physical selection, R2IL `Program` reproducibility | Queued | P1/P2 == scalar reference; P3 refuses; no foreign gather | +| **D-SRAM-4** | recursive region scheduling | **BLOCKED** — its target (D-RA-4's d′ driver) is a banned gather; no lawful driver exists | waits for a co-addressed recursion design | +| D-SRAM-5 | speculative-thought liveness over 0+63 slots | Queued (after D-TGA-1/3) | exhaustion refused; no tombstoned branch reused before receipt | +| D-SRAM-6 | candidate resolution + Git porcelain under pinned horizon | Queued (after D-TGA-1/3, #1605 gates) | deleted support removes only dependent proofs | +| D-SRAM-7 | chunk promotion as compile optimization | Queued (after correctness gates) | unfold from cold source + receipts; no confidence inflation | +| D-JCR-0 | freeze JC + Quack/Mask-RISC type inventory for R calls | Queued | executable call-to-owner map | +| D-JCR-1 | typed `StatisticalRequest` (no parser) | Queued | valid and invalid requests constructed; total-input and per-group row limits both validated | +| D-JCR-2 | correlation over CrossPowerSums via resident masks | Queued | == materialized-vector Pearson | +| D-JCR-3 | one-way ANOVA / eta² / simple OLS over PowerSums | Queued | parity to JC slice methods | +| D-JCR-4 | whitelisted R-style formula parser | Queued | arbitrary evaluation refused | +| D-JCR-5 | external R parity harness (reference only) | Queued | differential vs base `stats` | +| D-JCR-6 | optional R package / native ABI | Queued | no R runtime dependency in `jc` | +| D-JCR-7 | SoA-handle mode and wider lanes | Queued (after substrate gates) | no duplicate evaluator | +| D-JCR-8 | research consumers / notebooks | Queued | reproducible with witnessed datasets | +| — | weak-dependence calibration API | OPEN (GAP) | `jc::jirak` has only `prove()`; nothing to call yet | +| D-JCSBI-0 | SBI source/API inventory | Queued | actual methods listed | +| D-JCSBI-1 | cold `SimulationSpec`/`SBIRequest`/`SBIReport` contracts | Queued | refusal matrix | +| D-JCSBI-2 | exact discrete posterior fixture, log-domain normalization | Queued | zero support refuses; underflow-prone finite weights normalize (SB-02a/b) | +| D-JCSBI-3 | bounded ABC rejection | Queued | coverage / recovery on held-out data | +| D-JCSBI-4 | SBC + posterior predictive diagnostics | Queued | uniform ranks under the correct generator | +| D-JCSBI-5 | DisMech cut replay harness (not SCM) | Queued | same replay source both arms | +| D-JCSBI-6 | ABC-SMC if earlier probes justify | Queued | ESS / held-out stability | +| D-JCSBI-7 | EIG over permitted designs | Queued | design-relative nonidentifiability (plan §148) | +| D-JCSBI-8 | R-style typed SBI adapter | Queued | no arbitrary R evaluation | +| D-JCSBI-9 | ndarray SIMD candidate audit | Queued | multi-consumer insufficiency proof | +| CPG-0 | confirm Lance 13 / LanceDB 0.40 branch, tag and row-lineage API in the integrated workspace | Queued | reuses H14c-5 row-identity measurement; no repeat probe | +| CPG-1..6 | causal pickaxe: DurableRef adapter, resident history, Pickaxe read plan, counterfactual replay, porcelain | Queued (design only; `causal-pickaxe-resident-git-lance13-temporal-v1.md` §7) | fixtures CPG-00..25 | +| VSC-0 | versioned semantic candidates RFC + fixture oracle (#1604, #1606) | SHIPPED as docs + Python reference oracle (`semantic-ring-oracle.yml`) | C-01/C-02 and negative controls; `Rejected` outcome added 2026-10-19 | +| VSC-1..5 | candidate proposals, thought carriers, rebase/land, RelAlg → R2IL, 64-perspective benchmark | Queued | RFC §7 table | +| — | language LEGO grammar → query RFC (#1603), Cartesian self-model (#1602), 34 recipes (#1609), arXiv extracts (#1601, #1610, #1611), qualia archives (#1607, #1608) | docs / data only | no D-ids; qualia verifiers run in `qualia-verify.yml` | + ## D-CGW — CE64 grammar wiring: every upper-half field of a parsed triple from its source (2026-10-16) Plan: `.claude/plans/ce64-grammar-wiring-v1.md`. Entry: `entries/2026-10-16-grammar-coordinates-annotation-wiring.md` §7–§11. Related: D-SMD-2 (grammar topology from Haspelmath maps), D-SAG-CF-1 (counterfactual contract), D-LXC-29 (8 rails), EW64 OD-5. diff --git a/.claude/board/entries/2026-10-19-post-merge-recovery-1601-1617.md b/.claude/board/entries/2026-10-19-post-merge-recovery-1601-1617.md new file mode 100644 index 000000000..985cf0641 --- /dev/null +++ b/.claude/board/entries/2026-10-19-post-merge-recovery-1601-1617.md @@ -0,0 +1,27 @@ +# Post-merge recovery for #1601–#1617 (2026-10-19) + +**Status:** RECONCILED (remediation PR from main `47697c77`). The 17 PRs merged with 17 unresolved review threads and no board coverage. They are not reopened; one PR fixes what exists. + +## Review-thread reconciliation + +| PR | threads | finding | disposition | fixed in | +|---|---|---|---|---| +| #1603 | 1 | relative-pronoun case taken from the antecedent | valid | docs commit: case comes from inside the clause, gender/number agree | +| #1604 | 2 | no rejected outcome; premise deletion said "rederive from scratch" | valid | docs commit: `Rejected` (witnessed); C-09 admits DRed | +| #1605 | 1 | prerequisite named Lance 7 / LanceDB 0.30 | valid | docs commit: Lance 13.* / LanceDB 0.40.*, reuse H14c-5 | +| #1607 | 2 | `assert` stripped under `-O`; musical fields checked only by type | valid | qualia commit: explicit checks, pinned field digest, `-O` negative controls, CI | +| #1608 | 1 | `assert` stripped under `-O` | valid | qualia commit: explicit checks; sidecar compared to the archived values | +| #1612 | 2 | D-SRAM-4 targets the banned d′ driver; negative control would fail a correct optimizer | valid | docs commit: D-SRAM-4 BLOCKED; gate split | +| #1613 | 2 | `jirak` is not a calibration API; total-input row limit missing | valid | docs commit | +| #1614 | 2 | EIG nonidentifiability; underflow vs zero support | outdated: already fixed in the merged text (plan §148; SB-02a/b, SB-24b/c) | none needed | +| #1615 | 1 | candidates not bound to the evaluated snapshot | valid | act-r commit: `Refusal::StaleCandidate`, 10 tests, disable-verified | +| #1617 | 2 | tile key lacks map generation; palette lacks its own generation | valid | d-rmap commit: §6a generations and falsifiers | +| #1616 | 0 | (no review) gather-shaped hop | architectural | mask-risc commit: quarantine; `ISS-GATHER-HOP-1616` | + +PRs #1601, #1602, #1606, #1609, #1610, #1611 had no review findings. + +## Open + +- GATHER-DECISION (which reads are admitted) is still open; the quarantine does not decide it. +- The ACT-R `Snapshot` is a local type; binding it to canonical contract types is future work. +- D-RMAP amortization against direct sorted-index traversal is unmeasured. diff --git a/.claude/board/entries/README.md b/.claude/board/entries/README.md index 2218ff586..baac29fee 100644 --- a/.claude/board/entries/README.md +++ b/.claude/board/entries/README.md @@ -25,10 +25,11 @@ 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. -369 entries, 2026-08-06 .. 2026-10-19. +370 entries, 2026-08-06 .. 2026-10-19. | date | entry id | finding | file | |---|---|---|---| +| 2026-10-19 | `post-merge-recovery-1601-1617` | | [2026-10-19-post-merge-recovery-1601-1617.md](2026-10-19-post-merge-recovery-1601-1617.md) | | 2026-10-19 | `D-RMAP-1` | | [2026-10-19-d-rmap-implicit-relationship-register.md](2026-10-19-d-rmap-implicit-relationship-register.md) | | 2026-10-17 | `thinking-tables-wiring` | | [2026-10-17-thinking-tables-wiring.md](2026-10-17-thinking-tables-wiring.md) | | 2026-10-17 | `D-ASM-11` | | [2026-10-17-pgring-idea-catalogue.md](2026-10-17-pgring-idea-catalogue.md) |