diff --git a/.claude/board/EPIPHANIES.md b/.claude/board/EPIPHANIES.md index 1bde71b..57d4c9f 100644 --- a/.claude/board/EPIPHANIES.md +++ b/.claude/board/EPIPHANIES.md @@ -7,6 +7,21 @@ --- +## 2026-07-01 — E-OSINT-SUBSTRATE-CONVERGES-PER-SOA — the massive cognitive stack converges into the V3 2+14 tenant SoA; the dedup IS the convergence + +**Status:** FRAMING (`[G]` for the shipped crates + the tenant carve + the sole-writer canon E-CE64-MB-4; `[H]` for the convergence *program* — the deltas + baby-step probes P0–P8 are unrun). Operator-framed 2026-07-01 (*"massive codebase massive entropy … the V3 2+14 tenants converge the awareness massively per SoA"*). + +The lance-graph cognitive stack (`causal-edge`, `thinking-engine`, planner `nars_engine`/`causal_distance`, `cognitive-shader-driver` MailboxSoA, `symbiont`, `arm-discovery`, the `elixir-template`+`template-runtime` reflex cluster, the `jc` pillars) is ~80% of an OSINT reasoning substrate already. The V3 **2+14 tenant node is the convergence vessel**: every awareness facet = one typed tenant column on one 512-B row (Meta / Qualia / MaterializedEdges=`CausalEdge64` / Fingerprint / Energy / Plasticity / EntityType / Kanban). Each duplicate type deleted (4× `CausalEdge64`, 4× `ThinkingStyle`, N× fingerprint/qualia) = one crate re-pointed at its tenant — **the dedup IS the convergence**. The sole-writer sandbox (SoA's own owner only; ractor single-`&mut self`; **E-CE64-MB-4**) is what makes it race-free by compile error. + +- **One distance format:** `causal_distance` = Pearl-masked Σ of 3×256² palette = the same palette256 shared by `arm-discovery`'s oracle (ρ=0.9973), `deepnsm` (→6×8:8), and the V3 6×(8:8) GUID tiers. Keystone probe **P1** = distance identity across the three. +- **Formal gate = `jc` pillars:** D-ARM-7 (`arm-discovery`→SpoStore) = Pillar 5 (`jirak.rs`, `I-NOISE-FLOOR-JIRAK`); Pearl masks = Pillar 5b (`pearl.rs`); the `syllogize` multi-hop chain = Pillars 6/9 (EWA-sandwich); ℓ²-fingerprint geometry = Pillars 7/8. +- **OSINT deltas (small):** mint `0x0700`/`0x0701` (DONE) · dedup `thinking-engine` `CausalEdge64`→canonical · retarget `osint_bridge`→ClassView · register OGAR action bodies · `deepnsm`→6×(8:8) · gate SPO promotion on D-ARM-7. +- **GoBD-clean:** no LLM on the hot path — rig/spider teach at learn-time → `cognitive-compiler` compiles an `ElixirTemplate` → `template-runtime` runs OGAR actions deterministically on the OSINT ClassView. + +**Full map + convergence baby-step roadmap (P0–P8) + pillar gates:** `docs/OSINT-SUBSTRATE-REUSE-MAP.md`. + +--- + ## 2026-06-30 — E-KEEP-AR-REMOVE-ORM — the consumer open-heart op KEEPS ActiveRecord and removes the ORM; OGAR is named after AR **Status:** FRAMING (`[G]` for the name origin + the keep/remove split, operator-stated 2026-06-30; the convergence wiring it implies is `[H]`, gated per the OP assessment). Corrects a session inversion (mine) that read the consumer pivot as "castrate the hand-rolled Rails ActiveRecord betrayal" — **backwards**. diff --git a/crates/ogar-class-view/src/lib.rs b/crates/ogar-class-view/src/lib.rs index 75defa2..b401a8d 100644 --- a/crates/ogar-class-view/src/lib.rs +++ b/crates/ogar-class-view/src/lib.rs @@ -71,7 +71,8 @@ use ogar_vocab::{ canonical_concept_id, commercial_document, commercial_line_item, currency_policy, diagnosis, hr_department, hr_employee, hr_employment_contract, hr_job, joint, knowledge_item, lab_value, mars_application, mars_machine, mars_node_template, mars_resource, mars_software, medication, - patient, payment_record, pricelist, pricelist_rule, priority, product, project, project_actor, + osint_person, osint_system, patient, payment_record, pricelist, pricelist_rule, priority, + product, project, project_actor, project_attachment, project_changeset, project_comment, project_custom_field, project_custom_value, project_enabled_module, project_forum, project_journal, project_member_role, project_membership, project_message, project_news, project_query, @@ -127,6 +128,9 @@ fn all_canonical_classes() -> Vec<(&'static str, Class)> { ("pricelist", pricelist()), ("pricelist_rule", pricelist_rule()), ("unit_of_measure", unit_of_measure()), + // ── 0x07XX — OSINT (AIRO/AIwar dual-use intelligence) ── + ("osint_system", osint_system()), + ("osint_person", osint_person()), // ── 0x09XX — health (OGIT Healthcare) ── ("patient", patient()), ("diagnosis", diagnosis()), diff --git a/crates/ogar-vocab/src/lib.rs b/crates/ogar-vocab/src/lib.rs index cd74e0f..7430783 100644 --- a/crates/ogar-vocab/src/lib.rs +++ b/crates/ogar-vocab/src/lib.rs @@ -1122,6 +1122,16 @@ const CODEBOOK: &[(&str, u16)] = &[ ("pricelist", 0x0209), ("pricelist_rule", 0x020A), ("unit_of_measure", 0x020B), + // ── 0x07XX — OSINT domain (AIRO/AIwar dual-use intelligence) ── + // Minted from the q2 cockpit V3 SoA bake (`data/osint-v3/`, harvested from + // `AdaWorldAPI/aiwar-neo4j-harvest`). The low u16 is the FROZEN canonical + // concept (07xx is operator-ratified canonical; the slot is the owner's); + // the render-skin APP_PREFIX (`0x1000`, the V3 format signal) is the + // consumer's half (`classid = (APP_PREFIX << 16) | concept`). Two concepts: + // the AI-system card (GUID1, 12 AIRO dims) and the person card (GUID2, 5 + // McClelland/Rubicon dims — the Epstein-archetype implicit-motive lens). + ("osint_system", 0x0700), + ("osint_person", 0x0701), // ── 0x09XX — Health domain (clinical / patient / care) ── // medcare-rs Healthcare-namespace promotion (Northstar T9). The 7 // entities the OGIT `NTO/Healthcare/entities/` TTL ships, projected @@ -1642,6 +1652,15 @@ pub mod class_ids { /// (`ogit.Automation:Trigger`). pub const AUTOMATION_TRIGGER: u16 = 0x0C09; + // ── 0x07XX — OSINT domain (AIRO/AIwar dual-use intelligence) ── + + /// `osint_system` (`0x0700`) — AI system profiled on the 12 AIRO/VAIR + /// dual-use dims (V3 SoA GUID1 `6×(8:8)` tier cascade). + pub const OSINT_SYSTEM: u16 = 0x0700; + /// `osint_person` (`0x0701`) — person profiled on McClelland motive + + /// Rubicon stage (V3 SoA GUID2; the Epstein-archetype implicit-motive lens). + pub const OSINT_PERSON: u16 = 0x0701; + /// Every `(canonical_concept_name, id)` pair the constants vouch for. /// Drift-guarded against [`super::CODEBOOK`] by tests in this module. pub const ALL: &[(&str, u16)] = &[ @@ -1684,6 +1703,9 @@ pub mod class_ids { ("pricelist", PRICELIST), ("pricelist_rule", PRICELIST_RULE), ("unit_of_measure", UNIT_OF_MEASURE), + // 0x07XX — OSINT (AIRO/AIwar dual-use intelligence) + ("osint_system", OSINT_SYSTEM), + ("osint_person", OSINT_PERSON), // 0x09XX — health ("patient", PATIENT), ("diagnosis", DIAGNOSIS), @@ -2443,6 +2465,18 @@ pub fn canonical_concept(name: &str) -> String { ) { return "priority".to_string(); } + // OSINT domain (0x07XX) — the canonical class-name spellings must + // round-trip so ordinary PascalCase model-name inputs (`OsintSystem` / + // `OsintPerson`, the builders' `Class::new(...)` names) recover their + // codebook ids; without this arm they lexically land on `osintsystem` / + // `osintperson`, which are NOT in the codebook (`osint_system` / + // `osint_person` are). Codex P2 on PR #145, mirrors the PR #60 pattern. + if matches!(lower.as_str(), "osintsystem" | "osint_system") { + return "osint_system".to_string(); + } + if matches!(lower.as_str(), "osintperson" | "osint_person") { + return "osint_person".to_string(); + } // ── Layer 2: lexical fallback ── lexical_concept(name) } @@ -2575,6 +2609,10 @@ pub fn all_promoted_classes() -> Vec { pricelist(), pricelist_rule(), unit_of_measure(), + // 0x07XX — OSINT arm (AIRO/AIwar dual-use: system + person cards), + // in class_ids::ALL order. + osint_system(), + osint_person(), // 0x09XX — health arm (7 OGIT Healthcare concepts), in // class_ids::ALL order. patient(), @@ -3684,6 +3722,88 @@ pub fn treatment() -> Class { c } +// ───────────────────────────────────────────────────────────────────── +// 0x07XX — OSINT domain (AIRO/AIwar dual-use intelligence) +// +// Minted from the q2 cockpit V3 SoA bake (`data/osint-v3/`, harvested from +// `AdaWorldAPI/aiwar-neo4j-harvest`). Two concepts mirror the two GUIDs of a +// baked node: GUID1 (the AI system, 12 AIRO/VAIR dims) and GUID2 (the person, +// 5 McClelland/Rubicon dims). Field order IS the SoA tier order — the FieldMask +// bit basis. The low u16 is the frozen canonical concept; the render-skin +// APP_PREFIX (`0x1000`, a V3 format signal) is the consumer's half. +// ───────────────────────────────────────────────────────────────────── + +/// OSINT **AI system** — the AIRO/AIwar dual-use system card (`osint_system`, +/// `0x0700`). The 12 dims the V3 SoA bake packs into GUID1's `6×(8:8)` tier +/// cascade: HEEL `current_status:type`, HIP `military_use:civic_use`, +/// TWIG `ml_task:ml_type`, LEAF `purpose:capacity`, family `output:impact`, +/// identity `stakeholder:airo_role`. Attribute declaration order IS the tier +/// order, so the lifted `ObjectView` FieldMask bit `i` == tier byte `i`. The +/// reasoning roles (Demand `offer⟷need`, Causality `intent⟷impact`) are a +/// consumer-side overlay on these names (see q2 `osint_classview.rs`). +#[must_use] +pub fn osint_system() -> Class { + let mut c = Class::new("OsintSystem"); + c.language = Language::Unknown; + c.canonical_concept = Some("osint_system".to_string()); + c.description = + Some("An AI system profiled on the AIRO/AIwar dual-use dimensions".to_string()); + c.source_domain = Some("osint".to_string()); + c.source_curator = Some("aiwar".to_string()); + let mut attrs = Vec::with_capacity(12); + for name in [ + "current_status", // HEEL.hi — state + "type", // HEEL.lo — identity + "military_use", // HIP.hi — dual-use need + "civic_use", // HIP.lo — dual-use need + "ml_task", // TWIG.hi — the task (need) + "ml_type", // TWIG.lo — the technique (offer) + "purpose", // LEAF.hi — intent (explicit) + "capacity", // LEAF.lo — offer + "output", // family.hi — offer + "impact", // family.lo — causality (implicit) + "stakeholder", // identity.hi — relation + "airo_role", // identity.lo — actor role (person) + ] { + let mut a = Attribute::new(name); + a.type_name = Some("string".to_string()); + attrs.push(a); + } + c.attributes = attrs; + c +} + +/// OSINT **person** — the McClelland / Rubicon actor card (`osint_person`, +/// `0x0701`). The 5 dims the V3 SoA bake packs into GUID2: HEEL `stage:need`, +/// HIP `receptor:rubicon`, TWIG `motive`. This is the Epstein-archetype lens — +/// implicit motive (`nPow`/`nAch`/`nAff`) × Rubicon crossing × power receptor — +/// the Person side of the Person×Situation split (the system card carries the +/// Situation). Attribute order IS the GUID2 tier order (the FieldMask bit basis). +#[must_use] +pub fn osint_person() -> Class { + let mut c = Class::new("OsintPerson"); + c.language = Language::Unknown; + c.canonical_concept = Some("osint_person".to_string()); + c.description = + Some("A person profiled on McClelland motives and the Rubicon action stage".to_string()); + c.source_domain = Some("osint".to_string()); + c.source_curator = Some("aiwar".to_string()); + let mut attrs = Vec::with_capacity(5); + for name in [ + "stage", // HEEL.hi — Rubicon stage I..IV + "need", // HEEL.lo — McClelland nPow/nAch/nAff + "receptor", // HIP.hi — power receptor + "rubicon", // HIP.lo — Rubicon crossing + "motive", // TWIG.hi — dominant motive + ] { + let mut a = Attribute::new(name); + a.type_name = Some("string".to_string()); + attrs.push(a); + } + c.attributes = attrs; + c +} + /// Visit — a clinical encounter (OGIT `Visit`, `0x0906`). The temporal /// container diagnoses / labs / treatments / vitals are recorded within. #[must_use] @@ -4138,6 +4258,24 @@ mod tests { assert!(wire_synergies(&[a, b, c]).is_empty()); } + #[test] + fn canonical_concept_promotes_osint_classes_deterministically() { + // OSINT domain (0x07XX): the builders' PascalCase class names must + // round-trip to their codebook ids, like every other promoted class + // (codex P2 on PR #145). Without the resolver arm, `OsintSystem` + // lexically lands on `osintsystem`, which is NOT in the codebook. + assert_eq!(canonical_concept("OsintSystem"), "osint_system"); + assert_eq!(canonical_concept("OsintPerson"), "osint_person"); + assert_eq!(canonical_concept("osint_system"), "osint_system"); + assert_eq!(canonical_concept("osint_person"), "osint_person"); + // Full round-trip through the codebook resolver. + assert_eq!(ogar_codebook("OsintSystem"), Some(0x0700)); + assert_eq!(ogar_codebook("OsintPerson"), Some(0x0701)); + // The class builder's own `.name` resolves to its codebook id. + assert_eq!(ogar_codebook(&osint_system().name), Some(0x0700)); + assert_eq!(ogar_codebook(&osint_person().name), Some(0x0701)); + } + #[test] fn canonical_concept_promotes_billable_work_entry_deterministically() { // Promoted cross-domain invariant — OpenProject `TimeEntry` and @@ -4829,8 +4967,8 @@ mod tests { ], "Automation domain set drift — re-sync the consumer coverage gate", ); - // An empty (reserved-but-unpopulated) domain yields nothing. - assert_eq!(concepts_in_domain(ConceptDomain::Osint).count(), 0); + // The OSINT domain carries the two AIRO/AIwar cards (system + person). + assert_eq!(concepts_in_domain(ConceptDomain::Osint).count(), 2); } #[test] diff --git a/docs/OSINT-SUBSTRATE-REUSE-MAP.md b/docs/OSINT-SUBSTRATE-REUSE-MAP.md new file mode 100644 index 0000000..b78abd6 --- /dev/null +++ b/docs/OSINT-SUBSTRATE-REUSE-MAP.md @@ -0,0 +1,212 @@ +# OSINT reasoning substrate — reuse/wiring map + +> Durable capture of the 2026-07-01 crate tour. What's already built in +> `lance-graph` for OSINT reasoning, what to reuse vs rewire, and the small +> OSINT-specific deltas. Everything below is shipped unless marked. + +## The point: entropy → converged awareness per SoA + +Massive codebase → massive entropy: the same awareness facet is re-implemented +across crates (4× `CausalEdge64`, 4× `ThinkingStyle`, N× fingerprint/qualia). The +**V3 `2+14` tenant node is the convergence vessel** — every facet becomes **one +typed tenant column on one 512-B SoA row**, and each crate stops owning its own +state-type and instead reads/writes the shared tenant: + +``` +key (2) classid (identity/route) | EdgeBlock (16 in/out-family adjacency) +value (14+, ValueTenant): + Meta(0) MetaWord: thinking + awareness + NARS⟨f,c⟩ + free-energy ← the vertical mantissa + Qualia(1) 16×i4 chroma (felt sense) + MaterializedEdges(2) 4× CausalEdge64 (causal steps) ← causal-edge converges here + Fingerprint(3) identity print HelixResidue(4) · TurbovecResidue(5) codec residues + Energy(6) accumulator Plasticity(7) Hebbian counter + EntityType(8) classid discriminator Kanban(9) Rubicon phase cursor +``` + +So "converge the awareness massively per SoA" = **the dedup work IS the convergence**: +each duplicate type deleted is one crate re-pointed at its tenant. The `CausalEdge64` +dedup below is the first, smallest instance of the whole program. + +**Write-sandbox invariant (load-bearing — this is what makes convergence sound).** +The SoA is sandboxed from external writers: the **only writer is the SoA's own owner** +(`MailboxSoaOwner` / ractor single-`&mut self`, compile-time-proven exclusive — +E-CE64-MB-4). Every other crate **reads** (readonly `&view`) or **proposes**; the owner +**disposes**. No cross-writer race on the shared tenants is possible because aliasing is +a compile error. External "writes" are cycle-aware *proposals* the owner mediates +(`WriteOutcome::{Accepted, Stale, Future}`) — never a direct `value[..]` mutation. Convergence +works *because* the sole writer is the SoA itself. + +## One view + +``` +LEARN (offline, LLM ok) spider → Reader-LM → osint_bridge → rig/rs-graph-llm → cognitive-compiler +REFLEX (hot, no LLM) elixir-template ◄─ compiled ┘ + └ template-runtime runs OGAR actions +DISTANCE (one format) causal_distance = Σ Pearl-planes · 256×256 palette ── shared by: + arm-discovery oracle · deepnsm(→6×8:8) · V3 GUID tiers · SpoHead +EDGE causal_edge::CausalEdge64 (SPO palette + NARS⟨f,c⟩ + Pearl mask + mantissa) +RUNTIME (central) cognitive-shader-driver: shader cycle step[5] emits CausalEdge64 → + MailboxSoA EdgeColumn, via the owner (ractor compile-time fence) +CARRIER MailboxSoA: Morton palette tiles (address) + MetaWord awareness + (vertical mantissa, rolls cycle→cycle until F descends) + cycle stamps +REASON causal_distance → 8 Pearl projections → thinking/style weights → + nars_dispatch → ir/logical_op ; syllogize() chains ; + Pearl PO/SPO = osint_person Intervention/Counterfactual +KANBAN KanbanColumn Rubicon DAG ; tenant Kanban(9) phase ; owner-advanced +STORE ValueTenant: MaterializedEdges(2)=full CausalEdge64 · Kanban(9)=phase +``` + +## Reuse verdicts + +| Crate | Verdict | Note | +|---|---|---| +| `causal-edge` | REUSE | `CausalEdge64` = SPO edge; **`syllogize()`** = is_a/part_of chainer; Pearl `CausalMask` = intervention/counterfactual. SKIP `CausalNetwork` (re-owns CSR, breaks borrow rule). | +| `lance-graph-planner` `cache/nars_engine` | REUSE | `causal_distance` (Pearl-masked Σ of 3×256² palette), `nars_infer`, 8 Pearl projections; styles weight them | +| `lance-graph-planner` `thinking/` + `ir/` | REUSE | `style.rs` = weight vectors; `nars_dispatch`; `logical_op` plan | +| `cognitive-shader-driver` | REUSE | central causal-edge runtime; MailboxSoA owner; uses canonical `CausalEdge64` | +| `symbiont` | REUSE | SoA kanban loop; each `NodeRow` = one board | +| `elixir-template` + `template-runtime` + `template-equivalence` + `cognitive-compiler` + `cognitive-stack` | REUSE | deterministic reflex (LLM at learn-time only). `source_ranking_v1` + `OsintGuardrail` already OSINT-native | +| `lance-graph-arm-discovery` | REUSE | Aerial+ transcode; mines NARS-truth SPO rules from tabular OSINT dims (deterministic). **Gate: D-ARM-7 Jirak floor before live SpoStore** | +| `spider` | REUSE | external OSINT crawler = the learn-time front-end, behind `OsintGuardrail` | +| `thinking-engine` | MIXED | REUSE `think.rs`/`dto`/`awareness_dto`/`bridge_gate`/`f32_engine`; REWIRE `osint_bridge`/`cognitive_trace`; **dedup its local `CausalEdge64`** (below) | +| `deepnsm` | REWIRE | adopt 2×48-bit / 6×(8:8) palette256² tenant = the V3 format (one distance shape) | + +## OSINT-specific deltas (the only new work) + +1. **Done** — mint `osint_system`(0x0700) + `osint_person`(0x0701) in OGAR (tests green). +2. **Dedup** — thinking-engine's local `CausalEdge64` (in `layered.rs`/`domino.rs`) is an + 8-channel cascade accumulator shadowing the canonical name; it already `to_spo()`-collapses + to `causal_edge::CausalEdge64` at L3. Rename it → `CascadeChannels8` so the canonical is the + sole `CausalEdge64`. Crate-internal (4 files, not re-exported). *(needs a compile-checkable pass)* +3. **Emit path** — cascade `to_spo()` → write to `ValueTenant::MaterializedEdges(2)` **via the + `MailboxSoaOwner`** (never raw `value[..]`); phase in `Kanban(9)`, owner-advanced. +4. **Retarget `osint_bridge`** — its output is crawler text; point it at the OSINT ClassView so + entities land as classid-keyed nodes; feed `cognitive_trace` SPO → AriGraph. +5. **Register OSINT `OgarAction` bodies** in the `template-runtime` `ActionRegistry` + an OSINT + Rubicon/source-ranking template. +6. **deepnsm** — re-express its 4096² u8 distance as the 6×(8:8) palette256² code. +7. **AriGraph reference tenant + cold KV blob table (hot/cold split).** Add an AriGraph + value tenant holding a small fixed-size **`path:documentid` reference** (not text). A + **second KV table** (cold; `surreal_container`/kv-lance) maps `documentid → {wiki + profile, links, blobs}`. The 6×(8:8) tiers stay the hot structured OSINT format; **raw + text/links never touch the hot path** — the SIMD sweep / `causal_distance` / kanban / + `syllogize` read only structured tenants; the profile resolves cold, off-path, for + render/LLM/human. One-way: hot→cold read-only reference, cold never writes hot (the + ladybug HOT/COLD invariant). Node stays 512 B; Lance compresses the cold value while the + key stays addressable. → rich wiki node-profiles at zero hot-path cost. + +## Why it's GoBD-clean +No LLM on the hot path → deterministic → replayable/auditable. The LLM (rig/spider) teaches at +learn-time; `cognitive-compiler` compiles to an `ElixirTemplate`; `template-runtime` runs OGAR +actions on the OSINT ClassView. Discovery (`arm-discovery`) and distance (`causal_distance`) are +integer/palette, float-free. + +--- + +# Research roadmap — convergence baby steps (V3 format) + +V3 is integer/palette + float-free, so every probe is an **exact** assertion (no +tolerance except at the f32 NARS edge). Each step is one small `#[test]` against +shipped code. Order = dependency order; stop at the first red — a red step means +the "one format" claim breaks there. + +**Keystone first:** + +- **P1 · distance identity (THE convergence test).** For N random index pairs + `(a,b)`, assert the 256×256 palette distance agrees across the three sources: + `SpoDistances.{s,p,o}_dist(a,b)` (nars_engine) == `arm-discovery::CodebookDistance(a,b)` + == `deepnsm` distance. If these diverge, deepnsm/arm-discovery/causal_distance are + NOT one format — everything downstream is suspect. Fix deepnsm→6×(8:8) here. + +**Then, small steps up the stack:** + +- **P0 · tenant round-trip.** Pack 12 AIRO dims → 6×(8:8) GUID1 tiers → read back + via `ValueTenant` offsets = identity. (Bake exists; assert the carve.) +- **P2 · edge round-trip.** OSINT AIRO dims → `CausalEdge64::pack_v2` → `to_spo`/ + `from_spo` round-trips (already tested in `layered.rs`); `causal_distance` of the + packed edge = expected Pearl-masked sum. +- **P3 · Pearl ladder.** `causal_distance(mask=PO)` drops the `s_dist` term (Intervention + excludes the Subject confounder); `mask=SPO` keeps all three (Counterfactual). Direct + from the code — one assert each, on an `osint_person` pair. +- **P4 · discovery determinism.** `AerialProposer` over a tiny synthetic OSINT table + (3–4 dual-use rows) mines a known rule (`militaryUse=X ⟹ impact=Y`) → `CandidateRule` + with exact support/confidence ppm → `arm_to_truth_u8` → `CausalEdge64`. Same data+θ ⇒ + identical rules (no seed). *(live SpoStore promotion still gated on D-ARM-7.)* +- **P5 · syllogize chain.** Two SPO edges sharing a term → `syllogize()` → derived edge + with `Figure::Chain` + expected NARS truth (`is_a(A,B)∧is_a(B,C) ⊢ is_a(A,C)`). +- **P6 · awareness rollover.** Write an OSINT node's `MetaWord` awareness; `tick()` a + cycle with no consumption → awareness persists (`last_active_cycle` unchanged); consume → + stamped, skipped next cycle. (MailboxSoA test.) +- **P7 · owner fence.** `write_row` with a stale cycle → `WriteOutcome::Stale` (no mutation); + `current_cycle` → `Accepted`. Proves the ractor single-owner cycle-aware write on an OSINT row. +- **P8 · reflex determinism.** An OSINT `ElixirTemplate` through `template-runtime` with stub + OGAR actions: same input ⇒ same output; `template-equivalence` (rank_tolerance, no_new_claims) + green. Closes the GoBD replay loop. +- **P9 · hot/cold isolation.** Attach a large wiki text profile to a node's AriGraph tenant + (`documentid` ref). Assert: (a) the node stays 512 B; (b) `causal_distance` / the SIMD sweep + is byte-identical with and without the profile (raw text never touches the hot path); (c) + resolving the reference fetches the profile from the cold KV. The HOT/COLD invariant, tested. + +**Milestone (convergence proven):** P1 green + P2–P3 green = the V3 palette format is one +metric across discovery/distance/edge. Then P4–P5 = deterministic OSINT reasoning; P6–P8 = +the awareness/owner/reflex loop. Only after P1–P8 green do we wire the external `spider`→OSINT +learn path (the operator's "only if it works without" gate). + +## Probe status ledger (append-only; regrade in place) + +| Probe | Status | Receipt | +|---|---|---| +| **P0** · edge-type dedup (pre-req) | **GREEN** 2026-07-01 | lance-graph `thinking-engine`: local `CausalEdge64` → `CascadeChannels8`; canonical `causal_edge::CausalEdge64` is now the sole `CausalEdge64` in the crate. `cargo check -p thinking-engine` green. Commit `7e31cd7`; EPIPHANIES `E-CE64-NAME-COLLISION-DEDUP`. | +| **P1** · distance identity (keystone) | **GREEN** 2026-07-01 | `crates/lance-graph-osint/tests/p1_distance_identity.rs` (2 passed): deepnsm `subspace_distance_table` (f32 source) → quantizer → u16 palette → `SpoDistances::s_dist` (planner) ≡ `MatrixDistance::distance` (arm-discovery), byte-exact over 4096 pairs; `causal_distance(0b111)` == plane sum. Commit `3c79f29`; EPIPHANIES `E-P1-DISTANCE-IDENTITY-GREEN`. **deepnsm already ships 6×256 CAM-PQ — no re-bake needed.** | +| **P2** · edge round-trip | **GREEN** 2026-07-01 | `crates/lance-graph-osint/tests/p2_p3_edge_pearl.rs` (2 of 3 tests): `CausalEdge64::pack_v2` round-trips `s_idx/p_idx/o_idx/causal_mask/frequency/confidence`; `causal_distance` of two edges' heads == per-plane palette sum. Commit `23aff55`; EPIPHANIES `E-P2-P3-EDGE-PEARL-GREEN`. | +| **P3** · Pearl ladder | **GREEN** 2026-07-01 | same test (3rd): `causal_edge::CausalMask` ≡ `SpoDistances::causal_distance` mask byte (S=0b100,P=0b010,O=0b001); each mask keeps exactly its planes; `PO < SPO` when Subject term > 0 (do-calculus confounder projection). Commit `23aff55`. | +| **P4** · discovery determinism | **GREEN** 2026-07-01 | `crates/lance-graph-osint/tests/p4_discovery_edge.rs` (3 passed): OSINT `militaryUse⟹impact` fixture, `AerialProposer` mines the known rule with exact `support_ppm=500_000`/`confidence_ppm=1_000_000`; two mines byte-identical (no seed); `arm_to_truth_u8` → `TruthU8{255,254}` → `CausalEdge64::pack_v2` round-trips. Commit `c2c0dd8`; EPIPHANIES `E-P4-DISCOVERY-EDGE-GREEN`. Live-SpoStore promotion still gated on D-ARM-7. | +| **P5** · syllogize chain | **GREEN** 2026-07-01 | `crates/lance-graph-osint/tests/p5_syllogize.rs` (4 passed): `is_a(A,B).syllogize(is_a(B,C))` → `Figure::Chain`, conclusion `is_a(A,C)`, deduction truth exact (f=255, c=163), mantissa +1, mask SPO&SPO=SPO; no-shared-term and identical-(S,O) ⇒ `None`; deterministic. Commit `a3820df`; EPIPHANIES `E-P5-SYLLOGIZE-GREEN`. | +| P6–P8 · MailboxSoA runtime loop | queued (needs wiring) | awareness rollover / owner fence / reflex determinism — exercise the `MailboxSoA` + `template-runtime` runtime; `lance-graph-osint` does not yet dep those. | +| P9 · hot/cold isolation | blocked | needs the AriGraph cold-KV reference tenant; `arigraph` feature still commented out in `lance-graph-osint`. | + +**Convergence milestone PROVEN across FIVE vertices:** P1 (distance identity) + +P2 (edge round-trip) + P3 (Pearl ladder) + P4 (discovery determinism) + P5 +(syllogize reasoning) all green ⇒ the V3 palette is ONE integer-exact metric +across distance sources, the edge carrier, the causal-mask semantics, ARM +discovery, and multi-hop NAL reasoning — on shipped code, no new production +deps (only an `arm-discovery` dev-dep + 4 test files). The "static" convergence +(how a fact is *encoded*, *compared*, *discovered*, *chained*) is proven. The +remaining probes (P6–P8 awareness/owner/reflex loop, P9 hot/cold) are the +*runtime* convergence (how facts *roll over between cycles* under single-owner +writes) and require `MailboxSoA`/`template-runtime`/AriGraph wiring into +`lance-graph-osint` that does not yet exist — the next wiring milestone, gated on +the operator's "only if it works without" external-OSINT sequencing. + +**Rung-ladder framing (operator, 2026-07-01).** The probes are not a flat menu — +they are a climb of the 0–9 `RungLevel` ladder +(`lance_graph_contract::cognitive_shader::RungLevel`), which gates higher +reasoning on grounded lower rungs (`ShaderDispatch.rung` *elevates on sustained +BLOCK*, bottom-up): observation (0–1) ← P1; hypothesis (2–5) ← P3-`PO` + P4; +counterfactual (6, *on top*) ← P3-`SPO` + P5; the D-ARM-7 Jirak floor is the +stack guard (no counterfactual promotion of a discovery without observation +evidence). Consequence: **P6 (awareness rollover) IS the rung-elevation +mechanism** — unresolved surprise carried in the MailboxSoA `MetaWord` awareness +bits across cycles is what pushes `rung` up toward Counterfactual and rests it +back down on FLOW. P6 must assert the *elevation order*, not just bit +persistence. Full invariant: lance-graph EPIPHANIES +`E-RUNG-LADDER-IS-A-DEPENDENCY-STACK`. + +## Formal pillars (`jc`) — the math the baby steps rest on + +The `jc` crate PROVES the substrate's statistical/geometric foundations, one +`prove() -> PillarResult` per pillar. Baby steps test the *wiring*; the pillars +certify the *math* above them: + +- **Pillar 5 (`jirak.rs`)** — Berry-Esseen under weak dependence = the **D-ARM-7 + Jirak noise floor** (`I-NOISE-FLOOR-JIRAK`) gating `arm-discovery` → SpoStore. + P4's promotion gate *is* this pillar; wire P4's threshold to `jirak::prove()`. +- **Pillar 5b (`pearl.rs`)** — Pearl 2³ mask-classification accuracy = the + `causal_distance` PO/SPO masks (P3). +- **Pillars 6/9 (`ewa_sandwich[_3d]`)** — Σ push-forward as EWA-sandwich along + `CausalEdge64` edge paths (SPD cone) = the multi-hop `syllogize` chain (P5). +- **Pillars 7/8 (`koestenberger`/`dueker_zoubouloglou`)** — Hadamard / separable + Hilbert fingerprint geometry (the ℓ²-fingerprint convergence). + +Run `jc`'s `prove()`s as the formal gate above the probes: a baby step may pass on +one dataset; the matching pillar certifies it holds under weak dependence at scale. diff --git a/docs/UNIFIED-VERB-FACADE-v1.md b/docs/UNIFIED-VERB-FACADE-v1.md new file mode 100644 index 0000000..a62d365 --- /dev/null +++ b/docs/UNIFIED-VERB-FACADE-v1.md @@ -0,0 +1,77 @@ +# Unified Verb Facade — one small set of verbs over the ClassView + +> **Status:** council-hardened v1 (5+3 ran 2026-07-01, 8/8 → REVISE, land the +> safe subset). Renamed from `UNIFIED-EMITTER-API-v1.md`. +> **Under:** #546, #137 ("the spine is the compiled ClassView, not SurrealQL"), +> `SURREAL-AST-AS-ADAPTER.md`. + +## The idea, plainly + +Give consumers **six verbs** — `define · query · relate · act · subscribe · +authorize` — as `step_type` names on the **existing** `OrchestrationBridge` / +`UnifiedStep`. Nothing new underneath. These are just the natural things you do +to a ClassView node. + +SurrealDB happens to have the same-looking verbs (`DEFINE`, `SELECT`, `RELATE`, +`LIVE`, …). That's a **familiar shape we borrow, not the engine.** The engine is +the compiled ClassView. Think "same silhouette, different body." + +## What SurrealQL is (and isn't) + +SurrealQL is **only the API shape** — the verb names. Nothing structural. + +The real knowledge transfer is our own stack: +- **ClassView + askama** (the Redmine-ERB ViewFilter shape) — the view/render + surface; ClassView carries the schema and inherits it (knowledge transfer). +- **the transpiler** — ingests Active Record / Rails → an OGAR `Class`, plus + **SPO triplets** and **part_of / is_a** relations. +- **the 3×4 GUID cascade** — pulled in **only when a domain needs it** (Odoo or + similar); not universal. + +## The one honest rule the council found + +Only **`define` really matches** SurrealDB (schema in → schema out, no runtime). +The other five just **borrow the name** — underneath they're OGAR's own things +(EdgeBlock, ActionDef, the scheduler, RBAC). So: + +- Direction is always **OGAR → SurrealQL (out)**, never SurrealQL → behavior (in). +- **`authorize` is two verbs, never one**: `authorize.filter` (who can *see*) and + `authorize.admit` (who can *do*). Merging them is a bug. +- Ship only what's built: `define`, `query`, `relate`, `subscribe`, and basic + `act`. Leave `authorize.*` and lifecycle-`act` as **reserved names** until the + Core pieces (`Authorization`, `StateMachineDecl`) land. + +## What's actually built vs. borrowed + +| Verb | Built? | +|---|---| +| `define` | **yes** — `OgarClassView` (ClassView × FieldMask), tested | +| `query` | mostly — `Backend::MailboxSoa` scans work; no Cypher entry point yet | +| `relate` | partly — `EdgeBlock` struct decodes; write/traverse not done | +| `act` | data yes (`ActionDef`), runtime later (via `CommitHook`, not "CommitGate" — that name doesn't exist) | +| `subscribe` | trait yes (`VersionScheduler`), live binding later | +| `authorize` | RBAC exists (`ClassRbac`/`OgarRbac`), but the two-plane split is not built | + +## First step (safe now) + +A `step_type` name list + a `UnifiedStep` builder. **No new code that runs**, no +SurrealQL, no OSINT state machine yet. It's a **proposal, not proven**, until the +parity tests (F1/F3 below) pass. + +Tests to pass later: **F1** a `query` step returns the same nodes as the raw scan; +**F2** filter-rules never hit the admit-gate and vice-versa; **F3** with SurrealQL +off, behaviour is identical; **F4** no new type beyond a builder; **F5** every verb +names a real symbol in code (fixed the two fake ones this pass). + +## Council (5+3), one line each + +- **convergence** — only `define` truly converges; the rest just share a name. +- **core-first** — the ClassView is the authority, not SurrealDB; drop "two spines". +- **integration-lead** — 4 verbs are safe today; reserve `authorize`/lifecycle-`act`. +- **cross-domain** — an API over a running DB ≠ an API over emitted code; home is the bridge. +- **runtime-archaeologist** — `CommitGate` and `Authorization{enforcement_phase}` don't exist yet; point at the real types. +- **overclaim** — don't call unbuilt things "shipped"; one backend is live, not two. +- **doctrine** — split `authorize`; `act` is egress-only; rename off "SurrealQL-shaped"; add ADR-026. +- **dilution/collapse** — keep it "silhouette, not spine"; split `authorize` in the table itself. + +**Verdict: revise, land the safe subset, keep the big claim as a proposal until tested.**