Skip to content

Commit ea8c20d

Browse files
committed
fix(sprint-11/wave-D): D-CSV-7 — last_emission_cycle u32::MAX sentinel + lib re-export + ndarray hpc-extras
W-D1 worker completion notification (after the prior commit window) landed three improvements: 1. **MailboxSoA cycle-0 same-cycle false positive (real bug)** — the prior commit initialized `last_emission_cycle: [0u32; N]`, but `current_cycle` also starts at 0. The `last_emission_cycle[row] == self.current_cycle` guard in `emit()` would then incorrectly suppress emissions during cycle 0 (the first cycle of any MailboxSoA's lifetime). Fixed by initializing the array to `u32::MAX` (the "never-emitted" sentinel — distinct from any valid cycle stamp during normal operation). `reset_row()` also restores the sentinel; `test_mailbox_soa_new_zero` updated to assert `u32::MAX`. 2. **`lib.rs` re-export missing** — added `pub mod mailbox_soa;` and `pub use mailbox_soa::{MailboxSoA, DefaultMailboxSoA};` next to the existing bindspace re-exports. The prior commit had the file but didn't expose the types to downstream consumers. 3. **`Cargo.toml` ndarray hpc-extras feature** — adds `"hpc-extras"` to the ndarray feature list. Resolves the pre-existing blake3 compile failure that blocked `cargo test --manifest-path crates/cognitive-shader-driver/Cargo.toml` in this environment. Same fix W-C1 applied to PR #385's branch. Cross-spec inconsistency noted by W-D1 (no action needed): `CollapseGateEmission::new()` signature is `(source, chain_position, merge_mode)`, not `(source, current_cycle, merge_mode)` as the W-D1 prompt documented. The `chain_position` field semantically maps to `current_cycle` (per plan §8.1 "no explicit cycle_id field — provenance via (source_mailbox, chain_position)"); emit() correctly passes `self.current_cycle` as the `chain_position` arg. Naming mismatch is a doc-comment polish for a future iteration. Test status: **9/9 mailbox_soa tests pass; 65/65 lib tests pass total.** https://claude.ai/code/session_01UwJuKqP828qyX1VkLgGJFS
1 parent 19a650e commit ea8c20d

3 files changed

Lines changed: 17 additions & 6 deletions

File tree

crates/cognitive-shader-driver/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ lance-graph-ontology = { path = "../lance-graph-ontology", default-features = fa
4141
p64-bridge = { path = "../p64-bridge" }
4242
bgz17 = { path = "../bgz17" }
4343
causal-edge = { path = "../causal-edge" }
44-
ndarray = { path = "../../../ndarray", default-features = false, features = ["std"] }
44+
ndarray = { path = "../../../ndarray", default-features = false, features = ["std", "hpc-extras"] }
4545

4646
# Optional: real thinking-engine wiring behind a feature gate, matching
4747
# the EmbedAnything "default = runtime only; heavy deps behind features" rule.

crates/cognitive-shader-driver/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ pub mod driver;
9595
pub mod auto_style;
9696
pub mod engine_bridge;
9797
pub mod sigma_rosetta;
98+
pub mod mailbox_soa;
9899

99100
// ──────────────────────────────────────────────────────────────────────
100101
// LAB-ONLY modules — compiled only into the shader-lab binary. Never
@@ -195,3 +196,4 @@ pub use engine_bridge::{
195196
ingest_codebook_indices, dispatch_from_top_k,
196197
write_qualia_17d, read_qualia_17d, persist_cycle,
197198
};
199+
pub use mailbox_soa::{MailboxSoA, DefaultMailboxSoA};

crates/cognitive-shader-driver/src/mailbox_soa.rs

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,11 @@ impl<const N: usize> MailboxSoA<N> {
8080
mailbox_id,
8181
energy: [0.0f32; N],
8282
plasticity_counter: [0u8; N],
83-
last_emission_cycle: [0u32; N],
83+
// u32::MAX is the "never emitted" sentinel. current_cycle starts at 0
84+
// and advances via wrapping_add(1); in practice it never reaches
85+
// u32::MAX during a session, so the first emit on any cycle is always
86+
// permitted (u32::MAX != any valid cycle stamp).
87+
last_emission_cycle: [u32::MAX; N],
8488
current_cycle: 0,
8589
w_slot,
8690
threshold,
@@ -173,7 +177,9 @@ impl<const N: usize> MailboxSoA<N> {
173177
}
174178
self.energy[row] = 0.0;
175179
self.plasticity_counter[row] = 0;
176-
self.last_emission_cycle[row] = 0;
180+
// Restore the "never emitted" sentinel so the row can emit immediately
181+
// on the next cycle without triggering the same-cycle guard.
182+
self.last_emission_cycle[row] = u32::MAX;
177183
}
178184

179185
// ── Read-only inspectors ──────────────────────────────────────────────────
@@ -232,7 +238,10 @@ mod tests {
232238

233239
// ── test 1: new ───────────────────────────────────────────────────────────
234240

235-
/// New mailbox must have all per-row state zero, correct w_slot and threshold.
241+
/// New mailbox must have all per-row state initialised correctly.
242+
///
243+
/// energy and plasticity_counter are zero; last_emission_cycle is u32::MAX
244+
/// (the "never emitted" sentinel so cycle 0 can emit without false guard).
236245
#[test]
237246
fn test_mailbox_soa_new_zero() {
238247
let mb: MailboxSoA<8> = MailboxSoA::new(7, 5, 1.0);
@@ -249,8 +258,8 @@ mod tests {
249258
);
250259
assert_eq!(
251260
mb.last_emission_cycle[row],
252-
0,
253-
"last_emission_cycle[{row}] should be 0"
261+
u32::MAX,
262+
"last_emission_cycle[{row}] should be u32::MAX (never-emitted sentinel)"
254263
);
255264
}
256265
}

0 commit comments

Comments
 (0)