feat: causal diff engine — reverse-engineer reasoning from weight-space#56
Conversation
Diff two bgz7 indexes by tensor name + row, emit CausalEdges with NARS truth values. Classifies edges by attention projection (Q/K/V/O/Gate/FFN), clusters by block, finds reasoning scaffold circuits (Q+O shift, K stable). Includes NARS revision across multiple diff runs for integrated evidence about structural reasoning patterns. Test: test_full_reasoning_reverse_eng indexes 5 Qwen3.5 Q8_0 models (105 GB), diffs 4 pairs, revises across all.
Deserializer for bgz7 files — reads back the per-tensor Base17 rows written by stream_index_gguf/stream_index_gguf_bf16. Required by causal_diff to load and compare indexed models.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 11fffd123c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| let n_tensors = u32::from_le_bytes(u32_buf) as usize; | ||
|
|
||
| let mut tensors = Vec::with_capacity(n_tensors); | ||
| for _ in 0..n_tensors { | ||
| tensors.push(CompressedTensor::read_from(&mut reader)?); |
There was a problem hiding this comment.
Align BGZ7 tensor count with serialized entries
read_bgz7_file trusts the header tensor count and unconditionally reads that many CompressedTensor records, but this repository’s writers (stream_index_gguf / stream_index_gguf_bf16) write gguf.tensors.len() before skipping Norm/Skip tensors, so many .bgz7 files contain fewer records than the header claims. In that common case, this loop will hit EOF and causal_diff fails even on valid indexes produced by our own indexer; either the writer must store indexed count or the reader must tolerate shorter payloads.
Useful? React with 👍 / 👎.
| let key = (block, format!("{:?}", e.projection)); | ||
| let entry = clusters.entry(key).or_insert((0, 0, 0)); | ||
| entry.0 += 1; | ||
| entry.1 = entry.1.max(e.row_idx + 1); |
There was a problem hiding this comment.
Compute shift ratios from real row totals
This uses max(shifted_row_idx)+1 as total_rows, but cluster_by_head only receives shifted edges, so sparse shifts undercount the true denominator and inflate q_pct/k_pct/o_pct in find_reasoning_scaffold. For example, if only early rows shift, percentages can cross shift_threshold even when most rows are stable, producing false scaffold detections.
Useful? React with 👍 / 👎.
What
New
causal_diff.rsmodule +CompressedTensor::read_fromdeserializer.Diff two bgz7 model indexes by matching tensor names, comparing per-row Base17 fingerprints, and emitting NARS-truthed causal edges for every row that structurally shifted.
Pipeline
Key types
WeightEdge: tensor_name + row + block + projection(Q/K/V/O/Gate/FFN) + verb(BECOMES/SUPPORTS) + L1 + NarsTruthDiffStats: per-projection shift counts + mean L1classify_projection(): maps tensor names to Q/K/V/O/Gate/FFN/Embeddingfind_reasoning_scaffold(): blocks where Q+O shifted but K stayed stablerevise_across_diffs(): NARS revision integrating evidence from multiple model pairsIntegration test
test_full_reasoning_reverse_engindexes 5 Qwen3.5 Q8_0 models (105 GB total), diffs 4 pairs, finds reasoning scaffold, revises truth across all:Files
src/hpc/causal_diff.rs— new (319 lines)src/hpc/gguf_indexer.rs— addedCompressedTensor::read_from+read_bgz7_filesrc/hpc/mod.rs— registeredcausal_diffWhy
First real observed evidence for the NARS stack. Every truth value so far was manufactured by construction. This pipeline generates truth values from actual weight-space transformations between a base model and its reasoning-distilled variant. The NARS stack goes from theoretical to empirical.