Skip to content

Commit 2cf36ad

Browse files
committed
feat(shader-driver): wire content-plane Hamming cascade
Adds a content-plane Hamming pre-pass to ShaderDriver::run() before the existing palette cascade. For every pair of rows surviving the meta prefilter, popcount the XOR of their content fingerprints; if resonance = 1 - Hamming/16384 meets the style's resonance_threshold, emit a ShaderHit with predicates=0x01 (content-match flag). Why this matters: the palette cascade probes a pre-computed distance table built from synthetic Base17 entries unrelated to actual content. Before this change, dispatch() on encoded text returned 0 hits, 0 resonance, admit_ignorance=true regardless of semantic similarity. The content plane was read only for cycle_fp XOR folding, never compared. Threshold model: resonance vs style.resonance_threshold (density- agnostic). Analytical (0.85) is strict; creative (0.35) is loose; focused (0.90) strictest; peripheral (0.20) loosest. See EPIPHANIES 2026-04-24 "Jirak noise floor calibrated for DeepNSM-tiled 16K-bit fingerprints" for the Jirak-derived 3sigma reference point. Guard: skip the N^2 sweep when passed_rows.len() > 256 (4096 rows -> 16M popcount x 256 comparisons = heavy). Live verification (encode 3 rows, dispatch rows 0..3): "Palantir develops surveillance systems" (row 0) "Palantir Gotham is a surveillance platform" (row 1) "Israel deploys military AI" (row 2) Analytical (0.85): 0 hits (all pairs resonance < 0.85) - correct. Creative (0.35): 6 hits, all predicates=0x01. rows 0<->1 (Palantir / Palantir) resonance 0.598 <- strongest rows 1<->2 (Palantir / Israel) resonance 0.559 rows 0<->2 (Palantir / Israel) resonance 0.496 <- weakest Confidence rose from 0 -> 0.598; admit_ignorance flipped to false. Tests: 3 new (content_hamming_finds_similar_rows, content_hamming_skips_dissimilar, content_hamming_respects_style_threshold). All 45 tests pass (43 lib + 2 e2e). https://claude.ai/code/session_01SbYsmmbPf9YQuYbHZN52Zh
1 parent 00a5f8e commit 2cf36ad

1 file changed

Lines changed: 194 additions & 0 deletions

File tree

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

Lines changed: 194 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,70 @@ impl ShaderDriver {
9090
let max_dist = (self.semiring.k as f32) * (self.semiring.k as f32);
9191
let mut hits = Vec::<ShaderHit>::with_capacity(passed_rows.len().min(64));
9292

93+
// ═══════════════════════════════════════════════════════════════
94+
// Content-plane Hamming pre-pass (PR: hamming-content-cascade).
95+
// Compare content fingerprint of each passed row against every
96+
// other passed row. If Hamming-resonance exceeds the style's
97+
// resonance_threshold, emit a content-match hit. This is the
98+
// wire that lets dispatch() see real text similarity, not just
99+
// edge palette distance.
100+
//
101+
// Resonance model: resonance = 1 - Hamming/16384. Rows that
102+
// share content words land at higher resonance; fully disjoint
103+
// rows land near 0.5 (density ≈ 0.48 after 32× DeepNSM tiling).
104+
// Style thresholds (UNIFIED_STYLES):
105+
// analytical 0.85 (strict) focused 0.90 (strictest)
106+
// creative 0.35 (loose) peripheral 0.20 (loosest)
107+
// Jirak-calibrated 3σ reference: Hamming < 454 at density 0.016
108+
// (untiled). For tiled encodings (current DeepNSM path) the
109+
// density-dependent baseline shifts; resonance-over-threshold
110+
// is the density-agnostic reading. See EPIPHANIES 2026-04-24
111+
// "Jirak noise floor calibrated for DeepNSM-tiled 16K-bit
112+
// fingerprints".
113+
//
114+
// Guard: skip the N² sweep if passed_rows.len() > 256 — at
115+
// 4096 rows that is 16M popcount × 256 comparisons.
116+
// ═══════════════════════════════════════════════════════════════
117+
const CONTENT_MATCH_PREDICATE: u8 = 0x01;
118+
const MAX_CONTENT_PREPASS_ROWS: usize = 256;
119+
const FP_BITS: f32 = (WORDS_PER_FP * 64) as f32;
120+
if passed_rows.len() <= MAX_CONTENT_PREPASS_ROWS {
121+
let style_cfg = &crate::engine_bridge::UNIFIED_STYLES[(style_ord % 12) as usize];
122+
let min_resonance = style_cfg.resonance_threshold;
123+
124+
for (i, &row_i) in passed_rows.iter().enumerate() {
125+
let fp_i = self.bindspace.fingerprints.content_row(row_i as usize);
126+
for (j_off, &row_j) in passed_rows.iter().enumerate().skip(i + 1) {
127+
let fp_j = self.bindspace.fingerprints.content_row(row_j as usize);
128+
// Hamming = popcount of XOR across all 256 u64 words.
129+
let hamming: u32 = fp_i.iter().zip(fp_j.iter())
130+
.map(|(a, b)| (a ^ b).count_ones())
131+
.sum();
132+
// Resonance: normalized to full bit-width; higher = more similar.
133+
let resonance = 1.0 - (hamming as f32 / FP_BITS);
134+
if resonance >= min_resonance {
135+
// Record both directions so either row can surface via top-k.
136+
hits.push(ShaderHit {
137+
row: row_i,
138+
distance: hamming.min(u16::MAX as u32) as u16,
139+
predicates: CONTENT_MATCH_PREDICATE,
140+
_pad: 0,
141+
resonance,
142+
cycle_index: i as u32,
143+
});
144+
hits.push(ShaderHit {
145+
row: row_j,
146+
distance: hamming.min(u16::MAX as u32) as u16,
147+
predicates: CONTENT_MATCH_PREDICATE,
148+
_pad: 0,
149+
resonance,
150+
cycle_index: j_off as u32,
151+
});
152+
}
153+
}
154+
}
155+
}
156+
93157
for (cycle_idx, &row) in passed_rows.iter().enumerate() {
94158
if cycle_idx as u16 >= req.max_cycles.saturating_mul(4) { break; }
95159
// Use the SPO `s_idx` of the row's edge as the query palette index.
@@ -444,6 +508,136 @@ mod tests {
444508
assert!(crystal.bus.resonance.cycles_used <= 1);
445509
}
446510

511+
/// Build a BindSpace of `n` rows with caller-supplied content fingerprints.
512+
/// Meta confidence set to (200, 200) so everything passes the prefilter.
513+
fn bindspace_with_content(rows: &[[u64; WORDS_PER_FP]]) -> BindSpace {
514+
let q = [0.0f32; QUALIA_DIMS];
515+
let mut builder = BindSpaceBuilder::new(rows.len());
516+
for (idx, content) in rows.iter().enumerate() {
517+
let meta = MetaWord::new((idx as u8).wrapping_add(1), (idx as u8).wrapping_add(1), 200, 200, 5);
518+
builder = builder.push(content, meta, 0, &q, 0, 0);
519+
}
520+
builder.build()
521+
}
522+
523+
#[test]
524+
fn content_hamming_finds_similar_rows() {
525+
// Two rows with near-identical content (differ in only 4 bits)
526+
// → resonance ≈ 0.9998, well above any style threshold.
527+
let mut a = [0u64; WORDS_PER_FP];
528+
for i in 0..250 { a[i / 64] |= 1u64 << (i % 64); }
529+
let mut b = a;
530+
b[0] ^= 0xF; // 4-bit difference → Hamming = 4
531+
// A third row with substantially different content.
532+
let mut c = [0u64; WORDS_PER_FP];
533+
for i in 8000..8250 { c[i / 64] |= 1u64 << (i % 64); }
534+
535+
let bs = Arc::new(bindspace_with_content(&[a, b, c]));
536+
let sr = Arc::new(demo_semiring());
537+
let driver = CognitiveShaderBuilder::new()
538+
.bindspace(bs).semiring(sr).planes(demo_planes()).build();
539+
540+
let req = ShaderDispatch {
541+
rows: ColumnWindow::new(0, 3),
542+
meta_prefilter: MetaFilter::ALL,
543+
layer_mask: 0xFF,
544+
radius: u16::MAX,
545+
style: StyleSelector::Ordinal(auto_style::ANALYTICAL),
546+
..Default::default()
547+
};
548+
let crystal = driver.dispatch(&req);
549+
// Top-k must contain at least one content-match hit (predicates=0x01).
550+
let content_hits: Vec<_> = crystal.bus.resonance.top_k.iter()
551+
.filter(|h| h.predicates & 0x01 != 0 && h.resonance > 0.0)
552+
.collect();
553+
assert!(!content_hits.is_empty(),
554+
"expected at least one content-match hit, got top_k={:?}",
555+
crystal.bus.resonance.top_k);
556+
// Similarity should be very high (differ in only 4/16384 bits).
557+
assert!(content_hits.iter().any(|h| h.resonance > 0.5),
558+
"content-match resonance should be > 0.5 for near-identical rows");
559+
}
560+
561+
#[test]
562+
fn content_hamming_skips_dissimilar() {
563+
// Two rows with ~10000 Hamming distance → resonance ≈ 0.39, which
564+
// is BELOW analytical threshold (0.85). Analytical must not emit
565+
// a content-match hit.
566+
let mut a = [0u64; WORDS_PER_FP];
567+
for i in 0..5000 { a[i / 64] |= 1u64 << (i % 64); }
568+
let mut b = [0u64; WORDS_PER_FP];
569+
for i in 8000..13000 { b[i / 64] |= 1u64 << (i % 64); }
570+
// Disjoint ranges → Hamming ≈ 10000.
571+
572+
let bs = Arc::new(bindspace_with_content(&[a, b]));
573+
let sr = Arc::new(demo_semiring());
574+
let driver = CognitiveShaderBuilder::new()
575+
.bindspace(bs).semiring(sr).planes(demo_planes()).build();
576+
577+
let req = ShaderDispatch {
578+
rows: ColumnWindow::new(0, 2),
579+
meta_prefilter: MetaFilter::ALL,
580+
layer_mask: 0xFF,
581+
radius: u16::MAX,
582+
style: StyleSelector::Ordinal(auto_style::ANALYTICAL),
583+
..Default::default()
584+
};
585+
let crystal = driver.dispatch(&req);
586+
let content_hits: Vec<_> = crystal.bus.resonance.top_k.iter()
587+
.filter(|h| h.predicates & 0x01 != 0 && h.resonance > 0.0)
588+
.collect();
589+
assert!(content_hits.is_empty(),
590+
"analytical style should not emit content hits when resonance < 0.85; got {:?}",
591+
content_hits);
592+
}
593+
594+
#[test]
595+
fn content_hamming_respects_style_threshold() {
596+
// Design Hamming ≈ 5000 so resonance ≈ 0.695:
597+
// * below analytical (0.85) → 0 content hits
598+
// * above creative (0.35) → ≥ 1 content hits
599+
// a = bits [0..5000), b = bits [2500..7500) → overlap 2500 bits,
600+
// disjoint 2500+2500 = 5000, Hamming ≈ 5000.
601+
let mut a = [0u64; WORDS_PER_FP];
602+
for i in 0..5000 { a[i / 64] |= 1u64 << (i % 64); }
603+
let mut b = [0u64; WORDS_PER_FP];
604+
for i in 2500..7500 { b[i / 64] |= 1u64 << (i % 64); }
605+
606+
// Use empty planes so the palette cascade produces no hits —
607+
// isolates the content pre-pass so it cannot be drowned out by
608+
// synthetic palette matches that dominate top-k truncate(8).
609+
let empty_planes = [[0u64; 64]; 8];
610+
let mk_driver = || {
611+
let bs = Arc::new(bindspace_with_content(&[a, b]));
612+
let sr = Arc::new(demo_semiring());
613+
CognitiveShaderBuilder::new()
614+
.bindspace(bs).semiring(sr).planes(empty_planes).build()
615+
};
616+
let mk_req = |style_ord: u8| ShaderDispatch {
617+
rows: ColumnWindow::new(0, 2),
618+
meta_prefilter: MetaFilter::ALL,
619+
layer_mask: 0xFF,
620+
radius: u16::MAX,
621+
style: StyleSelector::Ordinal(style_ord),
622+
..Default::default()
623+
};
624+
625+
let strict = mk_driver().dispatch(&mk_req(auto_style::ANALYTICAL));
626+
let loose = mk_driver().dispatch(&mk_req(auto_style::CREATIVE));
627+
let strict_hits = strict.bus.resonance.top_k.iter()
628+
.filter(|h| h.predicates & 0x01 != 0 && h.resonance > 0.0).count();
629+
let loose_hits = loose.bus.resonance.top_k.iter()
630+
.filter(|h| h.predicates & 0x01 != 0 && h.resonance > 0.0).count();
631+
// Monotonicity: loosening the style cannot reduce the set of
632+
// content-match hits. This is the load-bearing invariant.
633+
assert!(strict_hits <= loose_hits,
634+
"creative (loose) should emit >= analytical (strict) content hits: strict={} loose={}",
635+
strict_hits, loose_hits);
636+
assert!(loose_hits > 0,
637+
"creative (threshold 0.35) should emit content hits for resonance ≈ 0.695\nloose top_k: {:?}",
638+
loose.bus.resonance.top_k);
639+
}
640+
447641
#[test]
448642
fn sink_short_circuits_on_false() {
449643
struct Stop;

0 commit comments

Comments
 (0)