Skip to content

Commit 1d020e4

Browse files
committed
symbiont: D1 bridge — perturbation Grid -> canonical SoA NodeRow (first runtime edge)
The 5+3 council's headline was "five crates linked, ZERO runtime edges." This builds the first one. crates/symbiont/src/bridge.rs: in-tree 8x8 lattice -> simulate_outage (DC-flow cascade) -> encode each bus's node_field into one canonical NodeRow (key=NodeGuid::local(bus), value[0..8]=f64 LE) -> assert every decoded f64 finite -> NodeRowPacket proves the 512-B/row zero-copy SoA stride. - cargo test -p symbiont: 2/2 (bit-exact finite round-trip + 512-B stride). - cargo run: "D1 bridge: 64 buses -> 64 NodeRows ... all finite ... max 0.814452". - Cargo.toml gains a lance-graph-contract path-dep (NodeRow lives there, not in lance-graph, and isn't re-exported). symbiont is the bridge's correct home: the only crate that sees BOTH NodeRow and perturbation-sim's Grid. The golden image now RUNS a genuine cross-crate edge, not just links. Board: EPIPHANIES E-FIRST-RUNTIME-EDGE-GREEN; AGENT_LOG D1; STATUS_BOARD symbiont-golden-image-harness (D0/D1 Shipped, D2/E1/BT Queued); PR_ARC #555 flipped to MERGED. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01CcpLeEC3XK8Eye53GKBVvi
1 parent 37cc21b commit 1d020e4

7 files changed

Lines changed: 185 additions & 1 deletion

File tree

.claude/board/AGENT_LOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
## 2026-06-20 (cont.) — D1 bridge GREEN: perturbation-sim Grid → canonical SoA NodeRow (first runtime edge)
2+
3+
**Main thread (Opus), autoattended autonomous** (operator: "go ahead autoattended autonomous decision making and auto resolve using the new architecture"). Mapped the bridge surface with an Opus explorer subagent (NodeRow API in `lance-graph-contract::canonical_node`; perturbation-sim `Grid`/`simulate_outage`), then implemented.
4+
5+
`crates/symbiont/src/bridge.rs` (+ `main.rs` calls it, + `Cargo.toml` gains a `lance-graph-contract` path-dep — NodeRow isn't re-exported by lance-graph). Build green; `cargo test --manifest-path crates/symbiont/Cargo.toml` **2/2 pass** (bit-exact finite round-trip through the SoA value slab + 512-B stride); `cargo run` prints `D1 bridge: 64 buses → 64 NodeRows ... all node_field finite ... max |perturbation| 0.814452`. **First real runtime edge** between two of the five crates (perturbation-sim ↔ lance-graph-contract). The golden image now RUNS, not just links. See EPIPHANIES `E-FIRST-RUNTIME-EDGE-GREEN`; STATUS_BOARD `symbiont-golden-image-harness` D1 = Shipped. Next: real Spain fixture (E1), kanban loop (D2).
6+
7+
---
8+
19
## 2026-06-20 — golden-image (symbiont) integration harness + jirak-stale finding + TD-SURREALDB-KVLANCE-LANCE7 PAID
210

311
**Main thread (Opus).** Operator framing: "a Dockerfile + Cargo that actually RUNS the future AGI/Foundry-aspiring substrate — all in one binary, *pending integration*" — explicitly NOT a pinned snapshot.

.claude/board/EPIPHANIES.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,21 @@
1+
## 2026-06-20 — E-FIRST-RUNTIME-EDGE-GREEN — the golden image now RUNS one genuine cross-crate edge: perturbation-sim `Grid` → canonical SoA `NodeRow`, cascade NaN-free, zero-copy 512-B stride (D1, the degenerate Spain-grid gate)
2+
3+
**Status:** FINDING (green — 2 probes pass + the harness runs).
4+
5+
The 5+3 council's headline was "five crates linked into one binary with ZERO runtime edges." This builds the FIRST edge. `crates/symbiont/src/bridge.rs`: an in-tree 8×8 lattice → `simulate_outage` (DC-flow cascade) → encode each bus's `node_field[i]` (`|θ perturbation|`) into one canonical `NodeRow` (`key = NodeGuid::local(bus)`, `value[0..8]` = f64 LE) → assert every decoded f64 finite → `NodeRowPacket` proves the 512-B/row zero-copy SoA stride. Demo: 64 buses → 64 NodeRows, all finite, 32768-byte packet, max |perturbation| 0.814452. `cargo test -p symbiont` 2/2 (bit-exact round-trip + stride).
6+
7+
**Architecture facts banked (verified against source):**
8+
- `NodeRow`/`NodeGuid`/`EdgeBlock` live in **`lance-graph-contract::canonical_node`**, NOT `lance-graph`, and are NOT re-exported by lance-graph — a consumer names them via a direct dep on the contract crate. `NodeRowPacket::as_le_bytes` is a `SoaEnvelope` trait method (import the trait).
9+
- `NodeRow` has NO constructor — struct-literal only (`key`/`edges`/`value` pub). `NodeGuid::local(id)` = the bootstrap address (classid=0, family=0, identity=id<2²⁴).
10+
- **symbiont is the correct home for the bridge** — it is the only crate that sees BOTH the contract `NodeRow` and perturbation-sim's `Grid` (lance-graph core can't dep perturbation-sim). The golden image stops being a link-only probe.
11+
- The cascade runs ON `Grid` (owns its f64 buffers); only the RESULT is encoded into the SoA — one-directional, no live state in `NodeRow` during compute (respects the readonly-substrate + owned-microcopy borrow doctrine).
12+
13+
**Next edges:** Grid→NodeRow over a REAL Spain fixture (E1 acceptance gate); the kanban loop (D2: `LanceVersionScheduler` → `KanbanMove` → SoA write → Lance commit).
14+
15+
Cross-ref: PR #555 INTEGRATION_PLAN D1; battle-test plan probes A1/B-series; STATUS_BOARD symbiont-golden-image-harness; `crates/symbiont/src/bridge.rs`.
16+
17+
---
18+
119
## 2026-06-20 — E-GOLDEN-IMAGE-IS-A-LIVING-HARNESS — the all-in-one substrate binary is an integration HARNESS that tracks each fork's LIVING canonical branch, NOT a pinned snapshot; and every per-session "jirak" branch is a stale checkout name (HEAD ⊂ the fork's main/master, 0 unique commits)
220

321
**Status:** FINDING (verified by `git fetch` + `merge-base` across all four forks, by direct manifest reads, and by a real git-deps build resolving to the lockstep pins).

.claude/board/PR_ARC_INVENTORY.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@
5151

5252
## #555 lance-graph: symbiont golden-image plan (5+3 council ledger) + the living-harness reframe
5353

54-
**Status:** OPEN 2026-06-20, branch `claude/symbiont-golden-image-plan`. Adds `crates/symbiont/INTEGRATION_PLAN.md` (the council loose-end ledger → Spain-grid acceptance gate). The golden-image crate itself landed **direct on `main`** (`82013145` crate → `e24b8626` OGAR→main → surrealdb→main fix): a workspace-`exclude`d probe that compiles+links the full stack into ONE binary.
54+
**Status:** MERGED 2026-06-20 (merge commit `37cc21b2`), branch `claude/symbiont-golden-image-plan`. Adds `crates/symbiont/INTEGRATION_PLAN.md` (the council loose-end ledger → Spain-grid acceptance gate). The golden-image crate itself landed **direct on `main`** (`82013145` crate → `e24b8626` OGAR→main → `d0a59e4e` surrealdb→main fix, verified green): a workspace-`exclude`d probe that compiles+links the full stack into ONE binary.
5555

5656
**Added:** `crates/symbiont/{Cargo.toml (portable git-deps), Dockerfile (rust:1.95 → debian-slim, build/CI validation), README, src/main.rs, INTEGRATION_PLAN.md}`. Root `Cargo.toml` exclude entry.
5757

.claude/board/STATUS_BOARD.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,17 @@
1+
## symbiont-golden-image-harness — the living all-in-one substrate binary + the first runtime edges
2+
3+
The golden image (`crates/symbiont`, workspace-`exclude`d): the full Ada stack in ONE binary, then real cross-crate edges onto the canonical SoA. Plan: `crates/symbiont/INTEGRATION_PLAN.md` (PR #555, merged `37cc21b2`).
4+
5+
| D-id | Title | Crate(s) | Status | Evidence |
6+
|---|---|---|---|---|
7+
| D0 | Golden image compiles+links (lockstep lance-7) | symbiont | **Shipped** | git-deps build `CARGO_EXIT=0`, unified `lance 7.0.0 / lancedb 0.30.0 / df 53.1 / arrow 58`, binary runs |
8+
| D1 | Grid→NodeRow bridge (perturbation cascade onto SoA) | symbiont/bridge.rs | **Shipped** | 2 probes green; demo 64 buses→64 NodeRows finite, 512-B zero-copy stride |
9+
| D2 | Kanban loop (`LanceVersionScheduler``KanbanMove`→SoA write→Lance commit) | symbiont + lance-graph-supervisor | Queued ||
10+
| E1 | Spain-grid acceptance gate (real fixture, NaN-free, clippy+machete clean) | symbiont | Queued | the north star — first N *real* nodes on the SoA in parallel |
11+
| BT | Battle-test plan (probes A1–E3, gated behind singleton-BindSpace→SoA) | workspace | Queued | drafted; land as `BATTLE_TEST_PLAN.md` |
12+
13+
---
14+
115
## entropy-ladder-spo-rung-v1 — Staunen↔Wisdom entropy coordinate unifies SPO rungs + NARS reliability (R1 shipped; R2–R6 roadmap)
216

317
Plan path: `.claude/plans/entropy-ladder-spo-rung-v1.md`. Foundation: `ndarray::hpc::{reliability, edge_codec, entropy_ladder}`. Selector: `lance-graph-contract::EdgeCodecFlavor`.

crates/symbiont/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,9 @@ path = "src/main.rs"
3636
# ── same-repo crates: path deps ──
3737
lance-graph = { path = "../lance-graph" }
3838
perturbation-sim = { path = "../perturbation-sim" }
39+
# canonical SoA node (NodeRow/NodeGuid/EdgeBlock) — NOT re-exported by lance-graph,
40+
# so the D1 bridge names it directly. Zero-dep, already in the graph.
41+
lance-graph-contract = { path = "../lance-graph-contract" }
3942

4043
# ── external AdaWorldAPI forks: git deps ──
4144
# ractor: jirak branch (carries this session's MessagingErr::Saturated fix; on github).

crates/symbiont/src/bridge.rs

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
//! D1 — the first real runtime edge: perturbation-sim `Grid` → canonical SoA `NodeRow`.
2+
//!
3+
//! Runs the DC-power-flow cascade over a small in-tree lattice and encodes each
4+
//! bus's final perturbation magnitude (`|θ_final − θ_base|`) into one canonical
5+
//! `NodeRow` (key = `NodeGuid::local(bus)`, `value[0..8]` = f64 little-endian).
6+
//!
7+
//! This is the degenerate first case of the Spain-grid acceptance gate: real
8+
//! nodes, on the actual SoA substrate, NaN-free. It turns the golden image from
9+
//! a link-only probe into a harness that exercises one genuine runtime edge
10+
//! between two of the five crates (perturbation-sim ↔ lance-graph-contract).
11+
//!
12+
//! `NodeRow` carries no live simulation state — the cascade owns its `Vec<f64>`
13+
//! working buffers; we encode only the *result* into the SoA. One-directional.
14+
15+
use lance_graph_contract::canonical_node::NodeRowPacket;
16+
use lance_graph_contract::soa_envelope::SoaEnvelope; // brings `as_le_bytes` into scope
17+
use lance_graph_contract::{EdgeBlock, NodeGuid, NodeRow};
18+
use perturbation_sim::{simulate_outage, CascadeConfig, Edge, Grid};
19+
20+
/// Stride of one canonical node on the wire / in the SoA backing store.
21+
const NODE_ROW_STRIDE: usize = 512;
22+
/// Slab offset for the encoded perturbation magnitude (raw f64, not the named
23+
/// `ValueTenant::Energy` carve — honest and decode-trivial).
24+
const NODE_FIELD_OFFSET: usize = 0;
25+
26+
/// Build a `rows × cols` lattice with a corner-to-corner dipole injection.
27+
/// Returns the grid plus a balanced injection vector `p` (Σ = 0, one bus per
28+
/// node). Pure in-tree — no network, no files.
29+
pub fn build_demo_grid(rows: usize, cols: usize) -> (Grid, Vec<f64>) {
30+
let n = rows * cols;
31+
let idx = |r: usize, c: usize| r * cols + c;
32+
let mut edges = Vec::new();
33+
for r in 0..rows {
34+
for c in 0..cols {
35+
if c + 1 < cols {
36+
edges.push(Edge::new(idx(r, c), idx(r, c + 1), 1.0, 5.0));
37+
}
38+
if r + 1 < rows {
39+
edges.push(Edge::new(idx(r, c), idx(r + 1, c), 1.0, 5.0));
40+
}
41+
}
42+
}
43+
let grid = Grid::new(n, edges);
44+
let mut p = vec![0.0_f64; n];
45+
p[0] = 1.0; // source at one corner
46+
p[n - 1] = -1.0; // sink at the opposite corner
47+
(grid, p)
48+
}
49+
50+
/// Run the cascade over `grid` and encode the result into one canonical
51+
/// `NodeRow` per bus: identity = bus index, `value[0..8]` = `node_field[i]` f64 LE.
52+
pub fn grid_to_noderows(grid: &Grid, p: &[f64], seed_line: usize) -> Vec<NodeRow> {
53+
let result = simulate_outage(grid, p, seed_line, CascadeConfig::default());
54+
(0..grid.n)
55+
.map(|i| {
56+
let mut value = [0u8; 480];
57+
value[NODE_FIELD_OFFSET..NODE_FIELD_OFFSET + 8]
58+
.copy_from_slice(&result.shape.node_field[i].to_le_bytes());
59+
NodeRow {
60+
key: NodeGuid::local(i as u32),
61+
edges: EdgeBlock::default(),
62+
value,
63+
}
64+
})
65+
.collect()
66+
}
67+
68+
/// Decode a bus's perturbation magnitude back out of its `NodeRow` value slab.
69+
#[inline]
70+
pub fn decode_node_field(row: &NodeRow) -> f64 {
71+
let bytes: [u8; 8] = row.value[NODE_FIELD_OFFSET..NODE_FIELD_OFFSET + 8]
72+
.try_into()
73+
.expect("8 bytes");
74+
f64::from_le_bytes(bytes)
75+
}
76+
77+
/// The acceptance-gate demo (first real instance): build → cascade → encode →
78+
/// assert finite → report. Returns the encoded rows so callers can sweep them.
79+
pub fn run_demo() -> Vec<NodeRow> {
80+
let (grid, p) = build_demo_grid(8, 8); // 64 buses
81+
let rows = grid_to_noderows(&grid, &p, 0);
82+
83+
// The acceptance-gate invariant, at SoA scale: no NaN reaches a node.
84+
assert!(
85+
rows.iter().all(|r| decode_node_field(r).is_finite()),
86+
"NaN escaped into a NodeRow value slab"
87+
);
88+
89+
// Prove the zero-copy SoA stride (512 B/row) without re-serializing.
90+
let packet = NodeRowPacket::new(&rows, 0);
91+
let bytes = packet.as_le_bytes().len();
92+
93+
let max = rows
94+
.iter()
95+
.map(decode_node_field)
96+
.fold(0.0_f64, f64::max);
97+
println!(
98+
"D1 bridge: {} buses → {} NodeRows (key=NodeGuid::local), all node_field finite; \
99+
SoA packet {bytes} bytes ({} B/row); max |perturbation| = {max:.6}",
100+
grid.n,
101+
rows.len(),
102+
bytes / rows.len().max(1),
103+
);
104+
rows
105+
}
106+
107+
#[cfg(test)]
108+
mod tests {
109+
use super::*;
110+
111+
/// The probe: every bus encodes a finite f64 that round-trips bit-exactly
112+
/// through the canonical SoA value slab. (Phase-A finiteness + B-series
113+
/// over-the-SoA, from the battle-test plan.)
114+
#[test]
115+
fn grid_to_noderows_is_always_finite_and_roundtrips() {
116+
let (grid, p) = build_demo_grid(6, 6);
117+
let result = simulate_outage(&grid, &p, 0, CascadeConfig::default());
118+
let rows = grid_to_noderows(&grid, &p, 0);
119+
assert_eq!(rows.len(), grid.n);
120+
for (i, row) in rows.iter().enumerate() {
121+
let decoded = decode_node_field(row);
122+
// bit-exact round-trip through the SoA value slab
123+
assert_eq!(decoded.to_bits(), result.shape.node_field[i].to_bits());
124+
assert!(decoded.is_finite());
125+
}
126+
}
127+
128+
/// The SoA backing store is a flat 512-B stride — zero-copy to Lance.
129+
#[test]
130+
fn soa_packet_stride_is_512() {
131+
let (grid, p) = build_demo_grid(5, 5);
132+
let rows = grid_to_noderows(&grid, &p, 0);
133+
let packet = NodeRowPacket::new(&rows, 0);
134+
assert_eq!(packet.as_le_bytes().len(), rows.len() * NODE_ROW_STRIDE);
135+
}
136+
}

crates/symbiont/src/main.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,13 @@
88
//! Build: cargo build --manifest-path crates/symbiont/Cargo.toml
99
//! Or: docker build -f crates/symbiont/Dockerfile -t symbiont .
1010
11+
mod bridge;
12+
1113
fn main() {
1214
println!(
1315
"symbiont golden image: lance-graph + lance7/lancedb0.30 + ndarray + ractor + surrealdb(kv-lance) + OGAR linked"
1416
);
17+
// D1 — the first real runtime edge: run the perturbation cascade and encode
18+
// the result onto canonical SoA NodeRows (the degenerate Spain-grid gate).
19+
bridge::run_demo();
1520
}

0 commit comments

Comments
 (0)