Skip to content

jc: ω sign anchor + scale-invariant tolerances + independent oracle; CLAUDE.md: mark the V1 EdgeBlock reading - #889

Merged
AdaWorldAPI merged 5 commits into
mainfrom
claude/x265-x266-plans-review-h9osnl
Aug 4, 2026
Merged

jc: ω sign anchor + scale-invariant tolerances + independent oracle; CLAUDE.md: mark the V1 EdgeBlock reading#889
AdaWorldAPI merged 5 commits into
mainfrom
claude/x265-x266-plans-review-h9osnl

Conversation

@AdaWorldAPI

@AdaWorldAPI AdaWorldAPI commented Aug 4, 2026

Copy link
Copy Markdown
Owner

Three commits, two unrelated concerns — flagged rather than buried, since the session works on one branch and the canon fix was requested while this PR was open. Split on request.

118 lib + 13 doctests green; stats.rs clippy-clean.


Part 1 — jc::stats corrections (commits 1–2)

The anchor defect (commit 1, self-found)

Signs were read from item 0's covariance row. Under one factor σ_ij = λ_iλ_j, so a weakly-loaded item 0 gives a near-zero row, every sign defaults to +1, and the consistency check manufactures conflicts on valid one-factor data — measured with λ = [0,+1,+1,−1]: two false rejections.

And the can-it-fire test written to prove that guard alive was passing because of this bug. Across all four anchors: 2 conflicts from the weakest item, zero from the strongest. A valid assignment existed, so the fixture was consistent; the guard had never been shown to fire. A test written to prove feature X passed because of unnoticed defect Y in the same function — the pair was self-confirming, because the test reused the implementation's own anchor convention to define "inconsistent".

Fix: anchor on the strongest-loading item — correct under the model, since a near-zero covariance against the strongest item implies the other item's loading is ~0, whose sign then cannot matter.

The three review findings (commit 2 — review 4856837957, note 5181899915)

P1 — ω was still unit-dependent. Four absolute floors survived: .max(1.0) in the λ² guard, the ψ guard, and both sign cutoffs. Below unit variance they degrade to an absolute 1e-9, so on covariances ~1e-16 every comparison is vacuous and ω flips 0.25 → 0.75 purely by rescaling. All four removed; tolerances now relative to var_i and √(var_i·var_j). Constant items rejected explicitly.

This is the same defect class as the R² absolute pivot I fixed two commits earlier. I fixed the instance and left the class — in the very function I was editing.

P1 — the regressions blessed the old wrong answer. The zero-loading test asserted only (0.0..=1.0), which 0.75 satisfies. Worse: the invariance tests compared against a self-computed baseline, so a consistently-wrong implementation would pass at every scale and permutation. Both values are now pinned by hand:

ZERO_ANCHOR_OMEGA = 0.25     λ = [0,+1,−1,+1], ψ = [V,0,V,V]
CONGENERIC_OMEGA  = 18/19    exact rational — the 8-digit decimal is
                             1.05e-9 off, and the 1e-9 tolerance
                             correctly rejected my own constant

Invariance never pins a value.

P2 — the "independent" oracle mirrored the implementation. It reconstructed signs per anchor row — an anchor-shaped decision procedure, not the specification. Replaced with the literal predicate: fix the free global sign, enumerate all 2k−1 = 8 assignments, assert none satisfies every material covariance edge, plus an anti-vacuity assert of ≥ 4 material edges.

Also removed: the global-sign-flip test. cov(−x,−y) = cov(x,y), and omega_total consumes only that matrix, so it could not fail for any implementation. Replaced by common rescaling, item permutation (rotations that move the zero-loading item into index 0), and a single-item flip that must change ω.


Part 2 — CLAUDE.md: mark the V1 EdgeBlock reading (commit 3)

The CANON — Minimal SoA node block reads as locked canon; the V1 key tail carries a prominent supersession banner while the edge block carried none. CLAUDE.md is auto-loaded into every lance-graph session, so a reader had no signal.

Deliberately narrower than "remove the V1 references", because the obvious banner would be wrong. V3 does not retire the block:

  • .claude/v3/COMPONENT-MAP.mdNodeGuid/EdgeBlock/NodeRow 16|16|480 is REUSE — CANON, const-asserted
  • .claude/v3/soa_layout/le-contract.md §316 — the 512-byte row "stays authoritative"

So the 16-byte reservation and stride are canon and survive; the note says so explicitly — do not shrink, widen, or re-stride on the strength of it. A blanket "EdgeBlock is superseded" banner would have invited exactly the layout change V3 forbids.

What is V1 is presenting 12+4 one-byte slots as THE reading. Under V3 it is EdgeCodecFlavor::CoarseOnly — the zero-fallback default among three readings of the same bytes (Pq32x4 = 32 × 4-bit PQ codes; CoarseResidue = signed-4-bit residue in the value slab), resolved per class via ClassView::edge_codec_flavor, none changing NODE_ROW_STRIDE.

Marked at all four sites (node-layout line, edge-block definition, reference-impl pointer, Core-First relations = EdgeBlock), regraded in place, not deleted — matching the treatment the key tail already had.

Test plan

cargo test -p jc → 118 lib + 13 doctests. cargo clippy -p jc --lib --tests → 0 warnings in stats.rs. CLAUDE.md is prose.

🤖 Generated with Claude Code

https://claude.ai/code/session_01K3RyLEbuNSHxxB3NTTrGki

…its own can-it-fire test was firing on the bug)

Follow-up to the #888 corrective slice, from re-reading my own diff.

THE DEFECT. Signs were read from item 0's covariance row. Under one factor
sigma_ij = lambda_i*lambda_j, so if item 0 is weakly loaded its whole row is
near zero, every sign defaults to +1, and the new consistency check
manufactures conflicts on data that is perfectly one-factor. Measured with
lambda = [0,+1,+1,-1]: two false conflicts, valid data REJECTED.

THE WORSE PART. The can-it-fire test I wrote to prove that guard alive was
passing BECAUSE of this defect. Enumerating its fixture over every anchor:

    anchor 0 (|lambda|=0.47): 2 conflicts
    anchor 1 (|lambda|=1.32): 0 conflicts
    anchor 2 (|lambda|=0.82): 2 conflicts
    anchor 3 (|lambda|=1.84): 0 conflicts   <- strongest

A valid sign assignment exists, so the fixture is CONSISTENT and the guard was
never shown to fire — what fired was the anchor bug. A test written to prove
feature X correct passed because of unnoticed defect Y in the same function;
the pair was self-confirming. Root cause: the test reused the implementation's
own anchor convention to decide what "inconsistent" means, so it could only
ever agree with it.

THE FIX, which is principled rather than a patch: anchor on the
strongest-loading item. Under a true single factor a near-zero covariance
against the strongest item implies the OTHER item's loading is ~0 — whose sign
cannot matter, since it contributes ~0 to sum(lambda). So the strongest anchor
is correct under the model, not merely more robust.

THE TEST, rebuilt on a criterion independent of the implementation:
sign-consistency is a property of the PATTERN, not of a chosen reference. The
honest question is whether ANY assignment of item signs reproduces every
covariance sign; a pattern where none does is frustrated (an odd cycle of
negative edges). The new fixture is frustrated from EVERY anchor, so no
implementation convention can accidentally satisfy it, and the test still
pre-registers that neither the negative-lambda^2 nor the Heywood guard can be
the rejecter.

Plus a regression test that the lambda = [0,+1,+1,-1] set is accepted.

Recorded as E-THE-CAN-IT-FIRE-TEST-WAS-FIRING-ON-THE-BUG-1, with the carry-over
rule: a can-it-fire test must define its trigger from the SPECIFICATION, never
from the implementation's own decision procedure — and when a guard rejects,
ask whether the rejection is a property of the data or of an arbitrary choice
the code made along the way.

117 lib + 13 doctests green; stats.rs clippy-clean.

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

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@AdaWorldAPI, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 21 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 9644546c-a16d-4040-9967-019be4603b85

📥 Commits

Reviewing files that changed from the base of the PR and between d99abbb and 95b282e.

📒 Files selected for processing (3)
  • .claude/board/EPIPHANIES.md
  • CLAUDE.md
  • crates/jc/src/stats.rs

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.

@cursor

cursor Bot commented Aug 4, 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_8474e2c4-6594-4e5e-947d-201ecdd51760)

@AdaWorldAPI AdaWorldAPI left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

Two correctness gaps remain in the exact surface this PR is changing, and the rebuilt tests still do not independently prove the claims in the PR body.

P1 — the strongest anchor is still erased by unit rescaling

The anchor choice is better, but its sign read still uses:

sqrt(var_anchor * var_j).max(1.0)

so below unit variance the cutoff is the absolute 1e-9. Scale this PR's own zero-loading fixture by 1e-8: every covariance becomes O(1e-16), every sign defaults to +1, and the consistency loop skips every edge as "near zero". The result changes from the correct signed value to the unsigned value:

scale 1      -> ω = 0.25
scale 1e-8   -> ω = 0.75

Common rescaling cannot change ω. This was already reported on #888 and #889 edits the same cutoff without removing the floor, so the anchor fix is not complete. Use a dimensionless covariance-sign criterion (or otherwise preserve covariance units without .max(1.0)) and add a common-rescaling regression on the signed/zero-loading fixture.

The same absolute floor still exists in the λ² and ψ tolerances, so a material negative common/residual variance can likewise be made acceptable merely by changing units.

P1 — the new regression passes the old wrong answer

omega_sign_anchor_survives_a_zero_loading_item asserts only that the result lies in [0,1]. For its exact fixture the expected value is known:

  • loadings: [0,+1,+1,-1]
  • residual variances: [V,0,V,V]
  • common variance: (0+1+1-1)^2 V = V
  • therefore ω = V/(V+3V) = 0.25

The original unsigned implementation returns 0.75, which also satisfies the current assertion. Thus the test proves only "did not reject", not that the anchor/sign fix computes ω correctly. Assert 0.25, then assert the same value under common rescaling and item permutation. The existing global-observation-sign-flip test is covariance-identical and remains vacuous; permutation is the relevant anchor invariant.

P2 — the claimed specification-independent frustration test still uses anchor reconstruction

The prose says the criterion is whether any sign assignment satisfies the material covariance edges, but the test checks the implementation-shaped shortcut "construct signs from each anchor row and see a conflict". Those are not the same predicate in general on sparse sign graphs, and this fixture itself has zero edges.

At k=4 the literal independent oracle is tiny: fix one global sign and enumerate the remaining 2^(k-1) = 8 assignments, asserting that none satisfies every materially non-zero covariance sign. That directly encodes the specification and fully discharges the epiphany's own carry-over rule.

The strongest-loading anchor itself is a sound direction under the exact one-factor model. These findings are about the surviving absolute cutoff and tests that remain capable of blessing the wrong implementation.

claude added 2 commits August 4, 2026 16:46
…sign oracle

Addresses all three findings from the #889 review (4856837957) and the #888
post-merge note (5181899915). Each was reproduced before fixing.

P1 — omega was still UNIT-DEPENDENT. Four absolute floors survived in
omega_total: `.max(1.0)` in the lambda^2 guard, the psi guard, and both sign
cutoffs. Below unit variance those degrade to an absolute 1e-9, so on data
whose covariances are ~1e-16 every tolerance is enormous, every sign
comparison vacuous, and (measured) omega flips 0.25 -> 0.75 purely by
rescaling. All four removed; tolerances are now relative to the item's own
variance, and covariance cutoffs to sqrt(var_i * var_j).

This is the SAME defect class as the R-squared absolute pivot fixed two
commits earlier. I fixed the instance and left the class — the floors were in
the function I was actively editing.

Constant items (zero variance) are now rejected explicitly: they carry no
signal, leave the model unidentified, and would make every scale-relative
tolerance degenerate.

P1 — the regressions blessed the old wrong answer. The zero-loading test
asserted only `(0.0..=1.0).contains(&w)`, which 0.75 also satisfies, so it
proved "did not reject" rather than "computed the signed omega". Worse, the
invariance tests compared against a SELF-COMPUTED baseline, so a consistently
wrong implementation would satisfy them at every scale and permutation.

Both absolute values are now pinned as constants derived by hand:
  ZERO_ANCHOR_OMEGA = 0.25          (lambda = [0,+1,-1,+1], psi = [V,0,V,V])
  CONGENERIC_OMEGA  = 18/19         (exact rational; the 8-digit decimal is
                                     1.05e-9 off and a 1e-9 invariance
                                     tolerance correctly rejects it)
and the rescale/permutation tests assert against those, not against
themselves. Invariance alone never pins a value.

P2 — the "independent" frustration oracle mirrored the implementation. It
reconstructed signs from each anchor row and looked for conflicts, which is an
anchor-shaped decision procedure, not the specification. Replaced with the
literal predicate: fix the free global sign and enumerate all 2^(k-1) = 8
assignments, asserting NONE satisfies every materially non-zero covariance
edge, plus an anti-vacuity assert that the sign graph carries >= 4 material
edges.

Also removed (review): the global-observation-sign-flip test. Negating every
item leaves the covariance matrix bit-identical, and omega_total consumes only
that matrix, so the assertion could not fail for ANY implementation — the
workspace's own "assertion implied by the code it tests". Replaced by common
rescaling, item permutation (including rotations that move the zero-loading
item into index 0), and a single-item flip that must CHANGE omega.

118 lib + 13 doctests green; stats.rs clippy-clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K3RyLEbuNSHxxB3NTTrGki
…gnal)

The CANON — Minimal SoA node block reads as locked canon, and the V1 KEY tail
got a prominent supersession banner while the EDGE block got none. A session
landing in that block has no signal that "12 in-family + 4 out-of-family, one
byte per slot" is a retired reading, and CLAUDE.md is auto-loaded into every
lance-graph session.

Marked at all four sites: the node-layout line, the edge-block definition, the
reference-impl pointer, and the Core-First doctrine summary's
`relations = EdgeBlock`.

SCOPED DELIBERATELY, because the obvious banner would be wrong. V3 does NOT
retire the block:

  .claude/v3/COMPONENT-MAP.md  — NodeGuid/EdgeBlock/NodeRow 16|16|480 is
                                 "REUSE | CANON, const-asserted"
  .claude/v3/soa_layout/le-contract.md:316 — the 512-byte row "stays
                                 authoritative"

So the 16-byte reservation and the 512-byte stride are canon and survive
unchanged, and the note says so explicitly: do not shrink, widen, or re-stride
on the strength of it. A blanket "EdgeBlock is superseded" banner would have
invited exactly the layout change V3 forbids.

What IS V1 is presenting 12+4 one-byte slots as THE reading. Under V3 it is
one interpretation among several, selected per class via
ClassView::edge_codec_flavor: CoarseOnly (the literal 12+4 read) is merely the
zero-fallback default; Pq32x4 reads the same 16 bytes as 32 x 4-bit PQ codes;
CoarseResidue spills a signed-4-bit per-dimension residue into the value slab.
Every flavor leaves NODE_ROW_STRIDE untouched, so adopting one needs no
ENVELOPE_LAYOUT_VERSION bump.

Operational consequence stated for the reader: never assume a node's edge
bytes mean "12 in-family + 4 out-of-family" — resolve the flavor through the
class's ClassView first.

Append-only respected: the V1 line is regraded in place, not deleted, matching
the treatment the key tail already had.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K3RyLEbuNSHxxB3NTTrGki
@AdaWorldAPI AdaWorldAPI changed the title jc: fix ω's sign anchor — it rejected valid data, and its can-it-fire test was firing on the bug jc: ω sign anchor + scale-invariant tolerances + independent oracle; CLAUDE.md: mark the V1 EdgeBlock reading Aug 4, 2026

@AdaWorldAPI AdaWorldAPI left a comment

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

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

The three numerical findings from review 4856837957 are closed on this head. The relative tolerances, pinned absolute values, permutation/rescaling coverage, and exhaustive sign-assignment oracle now match the claims.

One documentation correction remains before ready:

  • omega_total's public rustdoc still says signs are read from the first row, anchored at s_0 = +1.
  • The nearby implementation comment repeats the same obsolete rule.
  • The code now anchors on the item with the largest estimated |λ|.

That is now a false public contract, and it describes exactly the defect this PR fixes. Please rewrite both passages around the strongest-loading anchor and global orientation.

Also add zero-variance items to the documented None conditions. The new rejection is currently code-only. I would phrase this as an explicit API degeneracy policy rather than "leaves the model unidentified": a constant item can be represented as λ=ψ=0 when enough other items identify the factor, but rejecting it is still a defensible contract because it carries no score information.

No split requested. The EdgeBlock change is a single prose-only commit, the PR body exposes the mixed scope, and the two review surfaces do not interact. Splitting now would add branch/PR hygiene without improving the correctness review.

…ally uses

Review 4856960046. The rustdoc still described the DEFECT this PR fixes as if
it were the design: "signs are read off the first row, anchored at s_0 = +1".
The code selects the strongest-loading item. A false public contract, and the
nearby implementation comment repeated it.

Both rewritten around the strongest-loading anchor and global orientation, with
the reason stated rather than asserted: under a single factor a near-zero
covariance against the anchor implies the OTHER item's loading is ~0, whose
sign then cannot matter since it contributes ~0 to sum(lambda). Anchoring on a
weakly-loaded item reads every sign off near-zero noise, and if its loading is
~0 the whole row is ~0, every sign defaults positive, and the consistency check
rejects valid one-factor data (measured with lambda = [0,+1,+1,-1]: two false
conflicts).

Zero-variance rejection added to the documented None conditions, phrased as an
explicit API DEGENERACY POLICY rather than as a mathematical necessity — the
reviewer's correction to my earlier reasoning, and it is right. A constant item
IS representable as lambda = psi = 0 whenever the remaining items identify the
factor, so "leaves the model unidentified" overstated the case. The honest
rationale: it carries no score information, cannot covary, contributes nothing
to either sum, and in practice signals a data-preparation fault (a dead column,
an all-same-answer item) far more often than an intentional model. Rejecting
surfaces that fault instead of silently averaging it away, and keeps every
scale-relative tolerance well defined since those are proportional to the
item's own variance.

Recording the rule this coil produced, because it is the generalisation of all
three rounds:

  A numerical correction is not closed when the faulty line changes. It is
  closed when the defect CLASS is searched, an absolute value is pinned,
  invariants vary the input rather than echo the output, the oracle is
  independent of the implementation, and the public contract is reread after
  the code moves.

Every clause of that names something this arc got wrong once: the absolute
pivot fixed in R-squared while four floors stayed in omega; a range assertion
that 0.75 satisfied; invariance tests compared against their own output; a
can-it-fire test borrowing the implementation's anchor logic; and now a
rustdoc left describing the pre-fix behaviour.

118 lib + 13 doctests green; stats.rs clippy-clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K3RyLEbuNSHxxB3NTTrGki
@AdaWorldAPI
AdaWorldAPI marked this pull request as ready for review August 4, 2026 16:56

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7926f512d0

ℹ️ 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".

Comment thread crates/jc/src/stats.rs
Comment on lines +483 to +489
let anchor = (0..k)
.max_by(|&a, &b| {
lambda[a]
.abs()
.partial_cmp(&lambda[b].abs())
.unwrap_or(std::cmp::Ordering::Equal)
})

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Normalize the loading used to select the sign anchor

When items have substantially different residual variances, the largest raw |λ| need not provide the strongest covariance signal because the subsequent materiality cutoff is correlation-scaled. For example, an exact one-factor covariance with loadings [0.9, 1.0, -0.8] and variances [1, 1e20, 1] has valid nonnegative residual variances, but this selects item 1; both covariances in its row fall below the 1e-9 * sqrt(var_i * var_j) cutoff, so every sign remains positive, while the material negative edge between items 0 and 2 then makes the consistency check return None. Selecting by standardized loading, such as |λ_i| / sqrt(cov[i][i]), aligns anchor strength with the cutoff and avoids rejecting this valid one-factor input.

Useful? React with 👍 / 👎.

…dex P2)

Third anchor iteration, and the third instance of one class.

THE DEFECT. The anchor was chosen by raw |lambda| while the materiality cutoff
below it is correlation-scaled (1e-9 * sqrt(var_i * var_j)). Different units.
An item with an enormous residual variance can therefore hold the largest raw
loading while every covariance in its own row falls BENEATH its own cutoff —
so every sign defaults positive and a material negative edge elsewhere forces
a false rejection.

Reproduced before fixing, on exact one-factor data:

    lambda = [0.9, 1.0, -0.8]   var = [1, 1e20, 1]
    raw-|lambda| picks item 1; its cutoff is 1e-9*sqrt(1e20) = 10
    against covariances of 0.9 and 0.8 -> all signs default +
    the material -0.72 edge between items 0 and 2 then conflicts
    -> omega_total returns None on a valid model

THE FIX. Select by COMMUNALITY, lambda_i^2 / var_i — the share of the item's
own variance the common factor explains. It is dimensionless, so the anchor
criterion and the cutoff finally measure the same thing. On the fixture it
picks item 0 (communality 0.81) over item 1 (1e-20), and item 0's row carries
real sign information.

The public rustdoc is updated in the same commit — it had just been corrected
one round earlier and was stale again, which is the same trap the previous
commit recorded.

THE CLASS, recorded as E-A-CRITERION-MUST-BE-IN-THE-SAME-UNITS-AS-THE-TEST-IT-
FEEDS-1. Three anchors have now rejected valid data: item 0 (arbitrary, breaks
when lambda_0 = 0), raw |lambda| (breaks on unequal residual variances), and
communality (dimensionless, correct). Anchor #2 was not wrong about loadings —
1.0 really is the largest |lambda|. It was wrong because "strongest" was
measured in covariance units while "material" was measured in correlation
units, so the anchor could be strong by one yardstick and invisible to the
other.

And this is the third form of ONE deeper error: the absolute pivot in
R-squared, the four .max(1.0) floors in omega, and now the raw-|lambda| anchor
are all scale-dependence — a number compared against a constant, or against a
quantity in different units. Each was fixed as an instance and the class
resurfaced one layer over. The rule that catches all three at once: every
comparison in a numerical routine has two operands; write down the units of
both, and if they differ the comparison is a bug regardless of what the tests
say.

119 lib + 13 doctests green; stats.rs clippy-clean.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01K3RyLEbuNSHxxB3NTTrGki
@AdaWorldAPI
AdaWorldAPI merged commit 3b2a937 into main Aug 4, 2026
7 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