Skip to content

test(d-ign-b): the corpus produced nothing to read — fix the fixture, not the digest - #903

Merged
AdaWorldAPI merged 1 commit into
mainfrom
claude/fix-d-ign-b-lens-corpus
Aug 6, 2026
Merged

test(d-ign-b): the corpus produced nothing to read — fix the fixture, not the digest#903
AdaWorldAPI merged 1 commit into
mainfrom
claude/fix-d-ign-b-lens-corpus

Conversation

@AdaWorldAPI

@AdaWorldAPI AdaWorldAPI commented Aug 6, 2026

Copy link
Copy Markdown
Owner

The failure

cargo test -p lance-graph-supervisor --features cycle-driver --test d_ign_b_lenses

d_ign_b_lens_selection_over_byte_identical_rows panicked at L1's can-fire half — two different lenses over byte-identical rows produced the same digest:

assertion `left != right` failed: L1 can-fire: distinct lenses (z=3 Kant vs z=4 Wittgenstein) …
  left: 15130871412783076140
 right: 15130871412783076140

That constant is DefaultHasher::new().finish() — the hash of zero bytes. Both readouts were empty.

Root cause: the corpus, not the lenses

load_or_synthesize_corpus reads $BLW_KJV_TSV or /tmp/kjv_verses.tsv; neither exists in CI, so it fell back to synthetic_corpus, which emitted:

format!("d-ign-b synthetic verse {i} token{salt}")

That text carries no copula, no auxiliary, no modal, no typed relational verb and no -ed morphology, so stance::stream never sets armed and emits zero statements. Empty arena + empty ReadOut ⇒ all four stance_panel arms empty ⇒ every lens digests identically. stance.rs is untouched — the lenses were never at fault.

The test's own risk-check line had been printing Hegel empty = true, Nietzsche empty = true the whole time.

Pre-existing, and newly visible rather than newly broken

Reproduced identically at f9206fc. Without --features cycle-driver the module is #[cfg]-ed out and the binary runs 0 tests while reporting ok — the gate was recorded as standing but was unarmed. Arming it ended a vacuous pass; it did not cause a regression.

What was explicitly not done

Folding a variant-discriminant tag into digest() turns the collision green instantly — and makes the cross-lens != pass by construction of the tag alone, for any input, forever. That is the vacuous-assertion shape CLAUDE.md's falsifiability rule rejects, and digest()'s own doc comment forbade it in advance (module-doc deviation 3 records an earlier draft being talked out of exactly this). The untagged digest is what made the empty corpus observable at all.

What each lens actually extracts

Lens Needs Source
Hegel a belief with contradiction > 0.05; revise_at sets that to |f₁−f₂| on a disjoint-stamp revision stance.rs:418-427, belief.rs:191-205
Nietzsche Hegel's output, partitioned by FIRST vs LAST provenance negated flag — so both flip directions must be legible stance.rs:483-496
Kant ReadOut::lifts — perception verb + subject + that within the 3-content-token window + an emission stance.rs:500-510, :237-243, :302-364
Wittgenstein distinct language games per concept over observed Inh, lift knower/object, Impl cause/effect stance.rs:512-532

The fix

synthetic_window(w) builds each 48-verse owner slice from templates the shipped clause machine genuinely extracts from — affirm-then-negate and negate-then-affirm pairs on one term (Hegel + both Nietzsche directions), they knew that they were X (Kant), <effect> because <cause> (Wittgenstein's impl games on top of the Inh games every emission feeds), padded with plain affirmations. Predicates are {stem}{window:02}{n:02} nonsense syllables, chosen to collide with no catalogue the machine consults (STOP/AUX/negation/copula/modal/causal/perception/FAMILY_LEXICON).

The non-obvious constraint

Three of the four arms fold interned u16 ids, never the strings behind them, and the Interner assigns ids by order of first appearance. Two slices with identical structure therefore digest identically however their tokens are spelled — renaming the vocabulary buys nothing, and L4's "≥2 distinct digests across the in-scope owners" half would have stayed unfalsifiable. So the window shape is driven by w % 5|3|7, deliberately coprime with the stride-4 arming cycle ((id - SPREAD_LO) % 4 + 1) so each lens's own owner set spans several shapes instead of landing on one residue class.

The diagnostic the failure lacked

L1 now asserts each readout is non-empty before comparing digests, naming the corpus provenance. An empty corpus reports "the corpus produced no extractable content … this is a CORPUS defect, not a lens collision" — the original message was not merely unhelpful, it named a conclusion the evidence did not support.

The pre-registered z=3/z=4 witness pair is kept, and deliberately not re-picked now that Hegel/Nietzsche also fire.

Falsifiability — verified in both directions, not asserted

  1. Mutation: run_lens(4, …) returns the Kant arm → L1 fails on 1790839806321388433, a non-empty digest. The assertion still discriminates content; it did not merely become unreachable.
  2. Mutation: restore the pre-fix filler corpus → the new precondition fires with the corpus-defect message, not the collision message.

Measured after the fix:

L1.risk-check: Hegel empty = false, Nietzsche empty = false
L4.can-fire:   4 distinct of 4 lens digests over one owner
L3 z=1..4:     empty=0/8, 0/8, 0/7, 0/7
L4 z=1..4:     4, 7, 6, 6 distinct digests across the in-scope owners

Full -p lance-graph-supervisor --features cycle-driver suite green (30 tests, no regressions); cargo fmt --check clean; clippy clean for this target.

Honest gap

The $BLW_KJV_TSV branch has never executed here — the file is absent from this environment and CI. The two corpora do not exercise the arms alike: the synthetic corpus plants a reversal in every window by construction, whereas in the real corpus reversals are rare and localized (the module doc records Hegel as measured constant-false on that shape), so setting BLW_KJV_TSV could make L3 fail for z=1/z=2. Recorded rather than papered over.

Board hygiene (same commit)

  • EPIPHANIES.mdE-D-IGN-B-CORPUS-PRODUCED-NOTHING-TO-READ-1 (prepended)
  • ISSUES.mdISS-D-IGN-B-REAL-CORPUS-PATH-IS-UNVERIFIED (prepended)

Scope: test fixture + board only. No production behaviour changed.


Generated by Claude Code

Summary by CodeRabbit

  • Tests

    • Improved lens testing with structured synthetic data that produces meaningful, varied readouts.
    • Added checks to distinguish empty test data from genuine digest collisions.
    • Added validation that generated test data aligns with expected ownership.
    • Documented feature requirements and limitations for testing with real corpus data.
  • Documentation

    • Recorded findings about prior test failures and an open issue for validating behavior against real corpus data.

@cursor

cursor Bot commented Aug 6, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_38a4fc5d-ccd3-40d6-80b8-86394de19432)

@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 3aa4fd48-f709-4ec5-b813-624e0f784d55

📥 Commits

Reviewing files that changed from the base of the PR and between feddd52 and 7f18d79.

📒 Files selected for processing (3)
  • .claude/board/EPIPHANIES.md
  • .claude/board/ISSUES.md
  • crates/lance-graph-supervisor/tests/d_ign_b_lenses.rs
🚧 Files skipped from review as they are similar to previous changes (3)
  • .claude/board/ISSUES.md
  • .claude/board/EPIPHANIES.md
  • crates/lance-graph-supervisor/tests/d_ign_b_lenses.rs

📝 Walkthrough

Walkthrough

Changes

The lens test now uses structured synthetic windows with varied extraction patterns and owner-aligned sizing. L1 checks for non-empty readouts before comparing digests. Project notes document the prior collision and the unverified real-corpus path.

Lens test corpus validation

Layer / File(s) Summary
Structured synthetic corpus generation
crates/lance-graph-supervisor/tests/d_ign_b_lenses.rs
The fallback corpus now generates deterministic predicates, negations, perception clauses, causal clauses, and varied padding. Corpus sizes must align with populated owner slices.
Readout and corpus-path witnesses
crates/lance-graph-supervisor/tests/d_ign_b_lenses.rs, .claude/board/EPIPHANIES.md, .claude/board/ISSUES.md
L1 asserts non-empty Kant and Wittgenstein readouts before digest comparison. Documentation records the empty-digest collision, falsifiability checks, and unverified real-corpus branch.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

Poem

A rabbit checks each window’s shape,
With clauses clear from edge to edge.
No empty digest hides its trace,
Each lens now leaves a distinct mark.
The corpus hops through every case. 🐇

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the empty test corpus as the cause and the fixture-focused fix as the main change.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@crates/lance-graph-supervisor/tests/d_ign_b_lenses.rs`:
- Around line 925-943: Update the assertion in the L1 precondition loop over
r_kant and r_witt so its failure message identifies the specific failing lens
readout and states that the corpus lacked the structures required by that lens,
rather than claiming the corpus produced no extractable content overall or that
the digest comparison must be empty-vs-empty. Keep the per-readout non-empty
assertion and its behavior unchanged.
🪄 Autofix

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: f2d74d51-b671-486f-8382-a79394572fbb

📥 Commits

Reviewing files that changed from the base of the PR and between f9206fc and 50e0ea7.

📒 Files selected for processing (3)
  • .claude/board/EPIPHANIES.md
  • .claude/board/ISSUES.md
  • crates/lance-graph-supervisor/tests/d_ign_b_lenses.rs

Comment thread crates/lance-graph-supervisor/tests/d_ign_b_lenses.rs
… not the digest

`cargo test -p lance-graph-supervisor --features cycle-driver --test
d_ign_b_lenses` failed at L1's can-fire half: z=3 (Kant) and z=4
(Wittgenstein) over byte-identical rows digested identically to
15130871412783076140. That constant is `DefaultHasher::new().finish()`
— the hash of zero bytes. Both readouts were EMPTY.

Root cause is the corpus, not the lenses. `synthetic_corpus` emitted
"d-ign-b synthetic verse {i} token{salt}", which carries no copula, no
auxiliary, no modal, no typed relational verb and no `-ed` morphology,
so `stance::stream` never arms a predicate and emits zero statements.
Empty arena + empty ReadOut => all four `stance_panel` arms empty =>
every lens digests the same. `stance.rs` is untouched: it was never at
fault.

Pre-existing at f9206fc, and newly VISIBLE rather than newly broken —
without `--features cycle-driver` the module is cfg'd out and the
binary runs 0 tests while reporting ok. Arming that CI gate ended a
vacuous pass; it did not cause a regression.

Explicitly NOT fixed by tagging the digest with a variant
discriminant. That turns it green instantly and makes the cross-lens
`!=` pass by construction of the tag alone, for any input — the
vacuous-assertion shape the falsifiability rule rejects, which
`digest()`'s own doc comment forbade in advance.

The fix — `synthetic_window(w)` builds each 48-verse owner slice from
templates the shipped clause machine genuinely extracts from:
  * affirm-then-negate / negate-then-affirm pairs on one term
    (`revise_at` records |f1-f2| = 0.85, clearing Hegel's 0.05 floor,
    with both flip directions legible from the provenance endpoints
    for Nietzsche's Transvaluation/Devaluation);
  * "they knew that they were X" (perception verb + complementizer
    inside the 3-token window) for Kant's ReadOut::lifts;
  * "<effect> because <cause>" for Wittgenstein's impl-cause/
    impl-effect games, on top of the Inh games every emission feeds.
Predicates are `{stem}{window:02}{n:02}` nonsense syllables, chosen to
collide with no catalogue the machine consults.

The window SHAPE varies with w % 5|3|7, coprime with the stride-4
arming cycle. Three of the four arms fold interned u16 ids, never the
strings, so structurally identical slices digest identically however
their tokens are spelled — renaming the vocabulary would have left
L4's ">=2 distinct digests" half unfalsifiable.

L1 also gains a non-emptiness precondition checked BEFORE the digest
comparison, naming the corpus provenance. An empty corpus now reports
itself as a corpus defect instead of accusing the lenses.

Falsifiability verified in both directions, not asserted:
  * `run_lens(4, ..)` returning the Kant arm => L1 fails on
    1790839806321388433, a NON-empty digest, so the assertion still
    discriminates content;
  * restoring the pre-fix filler => the new precondition fires with
    the corpus-defect message.
Measured after the fix: all four arms non-empty on the twin base,
4/4 distinct digests over one owner, 4/7/6/6 across each lens's owner
set. Full `-p lance-graph-supervisor --features cycle-driver` suite
green (30 tests), fmt + clippy clean.

Board hygiene in the same commit:
  * EPIPHANIES  E-D-IGN-B-CORPUS-PRODUCED-NOTHING-TO-READ-1
  * ISSUES      ISS-D-IGN-B-REAL-CORPUS-PATH-IS-UNVERIFIED — the
    $BLW_KJV_TSV branch has never executed here, and the two corpora
    do NOT exercise the Hegel/Nietzsche arms alike.
@AdaWorldAPI
AdaWorldAPI force-pushed the claude/fix-d-ign-b-lens-corpus branch from 50e0ea7 to 7f18d79 Compare August 6, 2026 18:12
@coderabbitai

coderabbitai Bot commented Aug 6, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@cursor

cursor Bot commented Aug 6, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_dd802a7b-2e3d-4c0b-a7f1-55634f592bdc)

@AdaWorldAPI
AdaWorldAPI merged commit 48f5591 into main Aug 6, 2026
2 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants