fix(value_compare): keep non-finite numeric slots out of the comparator (#1227) - #1228
Conversation
There was a problem hiding this comment.
Sorry @robotrocketscience, you have reached your weekly rate limit of 500000 diff characters.
Please try again later or upgrade to continue using Sourcery
|
Warning Review limit reached
Next review available in: 39 minutes Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available. How can I continue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews. How do review limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window. Please refer docs for additional details. Review details⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughWalkthroughThe value comparison logic now rejects non-finite extracted numbers and safely formats infinity and NaN. Regression tests cover overflowed literals, numeric extraction, formatter behavior, conflict detection, and preservation of genuine conflicts. The v4.2.0 changelog documents the fix. ChangesNon-finite numeric handling
Estimated code review effort: 2 (Simple) | ~10 minutes 🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
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. Comment |
Reviewer's GuidePrevent non-finite numeric values (inf, -inf, nan) from reaching the comparator, and harden the numeric formatter and tests so SHA-shaped literals cannot crash contradiction detection while preserving legitimate numeric extraction and conflict detection. Sequence diagram for non-finite numeric handling in value comparatorsequenceDiagram
actor User
participant aelf_search as aelf_search_cli
participant Comparator as _slot_conflict_preextracted
participant Extractor as _extract_numerics
participant Formatter as _format_number
participant Math as math_isfinite
User->>aelf_search: run_search_with_conflicts
aelf_search->>Comparator: _slot_conflict_preextracted(belief_text)
Comparator->>Extractor: _extract_numerics(belief_text)
loop numeric_matches
Extractor->>Math: math_isfinite(value)
alt [non_finite_value]
Math-->>Extractor: False
Extractor-->>Extractor: continue # drop slot
else [finite_value]
Math-->>Extractor: True
Extractor-->>Comparator: add NumericSlot(key, value)
end
end
loop numeric_slots
Comparator->>Formatter: _format_number(x)
Formatter->>Math: math_isfinite(x)
alt [non_finite_input]
Math-->>Formatter: False
Formatter-->>Comparator: return f"{x:g}"
else [finite_input]
Math-->>Formatter: True
Formatter-->>Comparator: return str(int(x)) or f"{x:g}"
end
end
Comparator-->>aelf_search: slot_conflict_results
aelf_search-->>User: show_conflicts_without_crash
File-Level Changes
Assessment against linked issues
Possibly linked issues
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
[claim:review:Setr:2026-07-31T03:21:47Z] |
Review: approveVerified independently rather than taken from the body. The mutation table reproduces exactly. Checked out the head commit and ran the file three ways:
So both halves carry a distinguishing assert, and neither is covered incidentally by the other. That is the property that matters here, because a two-site fix is exactly the shape where one site can be dead weight and nothing notices. The latency claim holds. Blast radius of the extractor guard is nil.
Two signed commits, FF on One thing to route, not a blockerThe deferred half is real and currently has no home: the extractor still admits a bare I did not file it: no open issue covers it (searched), but the surface belongs to #1175, which is sitting at |
|
[release:review:Setr:2026-07-31T03:24:46Z] |
|
Correction to my previous comment: the The approval stands. Nothing about the fix changed; the conflict is packaging only. Scope, checked with Both sides insert a new bullet at the top of the same Resolve it insert-only. Keep both bullets, add yours, delete nothing and reorder nothing. Re-sorting the Flagging |
`float()` saturates to infinity rather than raising, and the exponent branch of the numeric-slot pattern matches abbreviated git SHAs — `592e701` is a hex string holding one `e` between digits, so read as scientific notation it becomes `inf`. `_format_number` then narrowed with a bare `int(x)`, which raises OverflowError on infinity and ValueError on NaN. Found on a live 44,584-belief store where three beliefs carried such a literal; reachable via `aelf search` under AELF_SHOW_CONFLICTS=1, the only wiring this comparator has, which defaults off. Fixed at both ends. The extractor no longer admits a non-finite value as a slot at all — an overflowed SHA is a parse artifact, not a measurement, and comparing against it manufactures a disagreement with a number no belief asserts. The formatter guards its own narrowing regardless, so a caller arriving by another route cannot resurrect the crash. Each half is pinned by tests that fail when only the other is applied, since either alone leaves the other path live. The extractor test carries a control asserting an ordinary numeric in the same sentence still extracts, so a fix that dropped every numeric slot would not pass. Closes #1227
2a044be to
a163040
Compare
|
[claim:review:Kulili:2026-07-31T03:45:58Z] |
Review — approved, mergingVerified the diagnosis, the fix, and the mutation table independently. All Verified
The residual case is reachable, and worse at the display layer than the note impliesThe "Not covered" section is correct to scope out narrowing Two six-character SHAs under the same key produce a reported numeric That branch is the one this PR just guarded, which is why it is worth Note
Adding |
|
merge-train: merged a163040 → |
|
[release:review:Kulili:2026-07-31T03:49:26Z] |
Closes #1227. Found while measuring #1175's lock-consistency proposal against the live store — the measurement script died partway through the scan.
The defect
float()does not raise on overflow, it saturates to infinity. The exponent branch of_NUMERIC_REmatches abbreviated git commit SHAs —592e701is a hex string that happens to hold oneebetween digits — so parsed as scientific notation it yieldsinf. The extractor'sexcept ValueErrornever fires, because nothing was raised._format_numberthen narrowed with a bareint(x):Confirmed on the live 44,584-belief store: three beliefs carry such a literal (
592e701,1e124732), and driving the exact shipped call path over them givesReachable through
aelf searchwhenAELF_SHOW_CONFLICTS=1(cli.py:915/922/932/938). That flag defaults to"0", so this was latent rather than a live break — which is why it survived to be found by a scan rather than by a user.Fixed at both ends, deliberately
The extractor drops it. An overflowed SHA is a parse artifact, not a measurement. Admitting it as a slot manufactures a comparison against a value no belief asserts — and #1175's data shows junk slots are not hypothetical there, where a single version-string lock accounts for 45% of all detected conflicts.
The formatter guards its own narrowing anyway. Defence in depth for any caller that reaches the comparator by another route.
Either fix alone leaves the other path live, so both are pinned by tests that fail when only the other is applied:
test_extractor_drops_the_non_finite_slot[…]test_format_number_survives_a_non_finite_input[…]Two controls keep the tests honest.
test_the_literal_really_does_overflowasserts the premise, so that iffloat()ever stopped saturating the rest of the file could not pass vacuously against a finite value.test_a_finite_neighbour_is_still_extractedasserts an ordinary numeric in the same sentence still extracts — without it, a "fix" that dropped every numeric slot would pass everything else in the file.test_a_real_conflict_is_still_detected_alongside_a_shacovers the same risk end to end.Verified against the store that crashed
The whole-store scan now completes: 44,559 beliefs, 5,552 slot-conflicts, no exception. One fewer than the format-guard-only count, which is the extractor correctly declining the false slot.
Full suite: 6538 passed, 69 skipped, 71 xfailed.
Why it was worth doing before #1175
#1175's build-first item proposes promoting
_slot_conflict_preextractedfrom that env-gated display path intoretrieve_with_tiers— the injection path that runs on everyUserPromptSubmit. There the hook's never-raise contract would most likely have absorbed the exception, which is worse than a crash: retrieval degrades silently.Not in this PR
The extractor still admits a bare
\d+e\d+token as a numeric slot when it does not overflow, so a short SHA can still become a finite false slot. Narrowing that pattern changes what counts as a numeric across the whole comparator and has a wider blast radius than this crash fix; it deserves its own decision. Noted in the changelog entry rather than left implicit.Summary by Sourcery
Prevent non-finite numeric values extracted from belief text from crashing contradiction detection and ensure they are safely formatted across the comparator path.
Bug Fixes:
Documentation:
Tests:
Summary by CodeRabbit
Bug Fixes
Documentation