Skip to content

alpha: make the AlphaMask::zip length guard hold in release (+ #1198 post-merge board hygiene) - #1199

Merged
AdaWorldAPI merged 1 commit into
mainfrom
claude/great-curie-d2ufyl
Sep 6, 2026
Merged

alpha: make the AlphaMask::zip length guard hold in release (+ #1198 post-merge board hygiene)#1199
AdaWorldAPI merged 1 commit into
mainfrom
claude/great-curie-d2ufyl

Conversation

@AdaWorldAPI

@AdaWorldAPI AdaWorldAPI commented Sep 6, 2026

Copy link
Copy Markdown
Owner

Stage 1b of .claude/temporal/09-plan.md, plus the post-merge board records #1198 owes now that it has merged.

The defect

AlphaMask::zip's only length guard was debug_assert_eq! — compiled out of a release build, which is the build where the damage is silent.

The failure is worse than a truncation. Iterator zip stops at the shorter operand while len is copied from self, so wide.and(&narrow) returned a mask claiming self.len addresses backed by other.words.len() words. That is not a smaller mask, it is an invalid one, and it fails two different ways at a distance from the call that made it:

  • count / is_empty sum the short slice and under-report silently;
  • contains / materialize_ordinals pass the ordinal < self.len check, then index past the slice and panic somewhere else entirely.

Measured before it was fixed

In release, against the unfixed code, the runner said exactly what a reproduced defect looks like:

combining_masks_of_different_lengths_is_refused_in_every_build - should panic ... FAILED
note: test did not panic as expected at alpha.rs:765

wide.and(&narrow) had returned successfully. Fixed, both falsifiers pass in release and debug.

The fix

assert_eq!, not debug_assert_eq!. A length mismatch is a caller mixing two allocations — a programming error, not a data condition — so it fails closed at the operation that made it rather than becoming a wrong answer read later. Cost is one u32 comparison against a loop over every word.

No API change. and/or/xor/and_not have no external callers yet (the only .and( hits elsewhere in the repo are wiremock), so this carries no ripple.

Falsifiers — two-sided, both disable-verified

assertion disable observed
mismatched lengths are refused in every build revert to debug_assert_eq! release: "test did not panic as expected"
equal lengths still combine, silently — (silence half) passes; a guard that rejected everything could not pass both

The silence half runs len = 200 (% 64 != 0, so the tail word is partial) across all four ops and additionally asserts and().count() + and().not().count() == 200 — that every product carries a full-width word slice, which is the invariant the guard actually protects.

Board hygiene for #1198 (post-merge trigger)

This is the record I said on the #1198 review thread would land after merge rather than in the PR under review, and the merge has now fired that trigger:

  • PR_ARC_INVENTORY.md — prepended entry for temporal: the audit reference, and D-LNC-5a measured — the insert delta needs stable row ids #1198 (3797237b): the falsified hypothesis, all three probe results with their controls, the four self-corrections, and the when_matched defect the review round exposed.
  • LATEST_STATE.md — merged-PR table entry; contract inventory net delta none (that arc minted nothing).
  • STATUS_BOARD.mdD-ALPHA-1b row.
  • .claude/temporal/09-plan.md — Stage 1b marked DONE with the measurement.
  • Supersession index regenerated after the board writes, per the ordering rule; output byte-identical.

Gates

  • cargo test --release -p lance-graph-contract --lib alpha:: — 10/10 (the release path is the point)
  • cargo test -p lance-graph-contract --lib — 1318/1318
  • cargo fmt -p lance-graph-contract -- --check — clean
  • cargo clippy -p lance-graph-contract --all-targets -- -D warnings — clean

Draft: the fix and its evidence are complete, but the remaining temporal stages are still gated (Stage 3 on P1's red, Stage 2 unstarted), so there is no rush to merge this ahead of a look.

🤖 Generated with Claude Code

https://claude.ai/code/session_01EfrUJH3UNnv5NpDH4jDGHq


Generated by Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Alpha mask operations now reject mismatched-length inputs in release builds, preventing invalid results and delayed runtime failures.
    • Added coverage to verify correct behavior for equal-length masks, including partially filled masks.

The only guard on `zip`'s operands was `debug_assert_eq!`, which is compiled
out of a release build — the build where the damage is silent.

The failure is worse than a truncation. Iterator `zip` stops at the shorter
operand while `len` is copied from `self`, so `wide.and(&narrow)` returned a
mask claiming `self.len` addresses backed by `other.words.len()` words. That is
not a smaller mask, it is an invalid one, and it fails two different ways at a
distance from the call that made it: `count`/`is_empty` under-report silently,
while `contains`/`materialize_ordinals` index past the slice and panic
somewhere else entirely.

Measured before it was fixed, in release: the `should_panic` falsifier reported
"test did not panic as expected" — the defect, reproduced rather than argued.

A length mismatch is a caller mixing two allocations: a programming error, not
a data condition. So it fails closed at the operation that made it, which costs
one u32 comparison against a loop over every word. No API change, and the ops
have no external callers yet, so this carries no ripple.

Two falsifiers, both disable-verified red-then-green. They are two-sided on
purpose: the mismatch case proves the guard fires in release, the equal-length
case proves it stays silent on ordinary input (including len % 64 != 0, where
the tail word is partial), so a guard that rejected everything could not pass
both. The silent half also asserts each product carries a full-width word
slice, which is the invariant the guard actually protects.

Board hygiene for #1198, now that it has merged and the post-merge trigger has
fired: PR_ARC_INVENTORY entry and the LATEST_STATE merged-PR table, both
prepended. This is the record I said on the review thread would land after
merge rather than in the PR under review. Stage 1b of the temporal plan is
marked DONE with the measurement, and STATUS_BOARD carries D-ALPHA-1b.

Supersession index regenerated after the board writes, per the ordering rule;
output byte-identical.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EfrUJH3UNnv5NpDH4jDGHq
@coderabbitai

coderabbitai Bot commented Sep 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: Essentials

Run ID: e00fe966-3a6d-4571-83c6-d68b42a14129

📥 Commits

Reviewing files that changed from the base of the PR and between 3797237 and 5fe1ffa.

📒 Files selected for processing (5)
  • .claude/board/LATEST_STATE.md
  • .claude/board/PR_ARC_INVENTORY.md
  • .claude/board/STATUS_BOARD.md
  • .claude/temporal/09-plan.md
  • crates/lance-graph-contract/src/alpha.rs

Included review availability: 0 reviews are currently available. Your included PR review attempts over the past 7 days set your current allowance at 1 review per hour.


📝 Walkthrough

Walkthrough

AlphaMask::zip now enforces equal mask lengths in release builds. Tests cover mismatched lengths and equal-length operations. Project records document the fix and related probe results.

Changes

AlphaMask validation

Layer / File(s) Summary
Enforce and test mask lengths
crates/lance-graph-contract/src/alpha.rs
AlphaMask::zip uses an unconditional length assertion. Tests cover mismatch rejection and and, or, xor, and and_not behavior.
Record validation completion
.claude/board/STATUS_BOARD.md, .claude/temporal/09-plan.md, .claude/board/LATEST_STATE.md, .claude/board/PR_ARC_INVENTORY.md
Project records document the completed AlphaMask fix, audit results, and absence of public API changes.

Estimated code review effort: 2 (Simple) | ~10 minutes

Merge Risk: ⚪ Minimal · up to 5fe1f

Mask operations now reject mismatched lengths in release builds instead of producing invalid results, while equal-length operations remain covered. No current merge-blocking risk remains.

Suggested reviewers: claude

Poem

A rabbit checks each mask with care
No mismatched bits escape the snare
Equal words hop clean and bright
Tests guard left and right
The board records the fix tonight

🚥 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 primary change to make the AlphaMask::zip length guard active in release builds. It also accurately references the related post-merge board updates.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 1 files. (4 skipped: 4 …
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

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

@cursor

cursor Bot commented Sep 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_2961f202-0d5c-4fba-aa64-487b731ff8fb)

@AdaWorldAPI
AdaWorldAPI marked this pull request as ready for review September 6, 2026 09:02
@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.
To continue using code reviews, you can upgrade your account or add credits to your account and enable them for code reviews in your settings.

@AdaWorldAPI
AdaWorldAPI merged commit ef72487 into main Sep 6, 2026
12 checks passed
AdaWorldAPI pushed a commit that referenced this pull request Sep 6, 2026
The post-merge trigger fired when #1199 merged as ef72487. #1199 was a MIXED
PR — it landed the AlphaMask::zip guard as well as #1198's hygiene — so the
rule's own terms give it an entry: the non-hygiene half is what the entry is
for.

The arc entry keeps what a future session would otherwise have to re-derive:
that the defect was reproduced in release BEFORE the fix (the should_panic
falsifier reporting "test did not panic as expected" IS the reproduction), that
the failure was an invalid mask rather than a truncated one, and that the blast
radius was measured — and/or/xor/and_not have zero external callers — before a
hard assert was committed to a contract crate.

It also records what the clean review was and was not worth: CodeRabbit
returned no actionable comments on the correct range, but Cursor Bugbot and
Codex were both budget non-results, so the arc had one live reviewer rather
than three. The evidence this rests on is the release repro, not the review.

This commit is hygiene-only. Per CLAUDE.md's termination clause it therefore
generates NO further obligations — no arc entry and no LATEST_STATE row of its
own — and the chain stops here rather than recursing.

Supersession index regenerated after the board writes, per the ordering rule;
output byte-identical.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EfrUJH3UNnv5NpDH4jDGHq
AdaWorldAPI added a commit that referenced this pull request Sep 6, 2026
board: record #1199's merge (hygiene-only — the chain stops here)
AdaWorldAPI pushed a commit that referenced this pull request Sep 7, 2026
…EPIPHANIES entry

All three verified against the files before fixing; all three were right.

1. LATEST_STATE's #1201 heading still read "#1199's records + the council SPEC
   v1" directly above the row correcting exactly that claim. A reader scanning
   by heading received the false merge history the commit exists to repair —
   the sharpest of the three, because the correction was sitting one line under
   the thing it contradicted.

2. STATUS_BOARD's D-NGN-AUDIT row still read "Phase 1 cast; v2 consolidation +
   3 reviewers pending". Phase 1 has RETURNED; the council is held at Phase 2 on
   a VIOLATES against F5 that is the operator's to rule. The dashboard is what a
   later session reads first, so a stale phase there invites re-casting five
   savants that already reported. The row now says HELD, why, and — explicitly —
   do not re-cast Phase 1 and do not cast the reviewers until the ruling lands.

3. No EPIPHANIES entry for the correction. CLAUDE.md's board-hygiene table
   requires a finding/correction to prepend one in the SAME commit, and the
   generalizable half was living only in an arc entry, which is organized by PR
   rather than by finding. Added
   E-AN-EMPTY-RANGE-AFTER-A-RESET-IS-NOT-EVIDENCE-1: `origin/main..<branch>`
   answers a question about the branch's CURRENT tip, so after a reset it is
   empty by construction — the symptom of the loss is indistinguishable from the
   all-clear. Verify unmerged work against a ref the operation cannot move.

   It carries the second half too, which no gate catches today: the board cited
   a PATH, not a symbol, so a plan file that existed nowhere read as a valid
   reference for a day. An absent symbol fails citation-decay; an absent path
   does not.

Gates run locally: plan_dids exit 0; append-only verified by line count
(EPIPHANIES 27617 -> 27661, PR_ARC unchanged); supersession index regenerated
AFTER the board writes — EPIPHANIES is one of its inputs — and byte-identical.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01EfrUJH3UNnv5NpDH4jDGHq
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