Skip to content

P5a: jc reliability/validity metric battery (Pearson / Spearman / Cronbach α / ICC)#709

Merged
AdaWorldAPI merged 1 commit into
mainfrom
claude/review-claude-board-files-nhqgx1
Jul 17, 2026
Merged

P5a: jc reliability/validity metric battery (Pearson / Spearman / Cronbach α / ICC)#709
AdaWorldAPI merged 1 commit into
mainfrom
claude/review-claude-board-files-nhqgx1

Conversation

@AdaWorldAPI

@AdaWorldAPI AdaWorldAPI commented Jul 17, 2026

Copy link
Copy Markdown
Owner

What

Adds crates/jc/src/reliability.rs — the four reliability/validity measures the workspace repeatedly names but had no callable implementation of:

  • pearson(x, y) — product-moment correlation.
  • spearman(x, y) — Pearson on the average-rank (tie-corrected) transform.
  • cronbach_alpha(items) — internal-consistency reliability of a k-item scale (α = (k/(k-1))(1 − Σσ²ᵢ/σ²_total)).
  • icc(ratings, IccForm::{Icc2_1, Icc3_1}) — Shrout-Fleiss 1979 two-way ANOVA ICC, single-measure absolute-agreement and consistency forms.

All return Option<f64> (None on degenerate input — too few observations, zero variance, ragged matrices — no panics/NaN, per the no-unwrap guideline).

Why

The chess-seam orientation surfaced that crates/jc is a FORMAL-SCAFFOLD pillar-prover (ten prove() -> PillarResult pillars) with no callable ICC/Pearson/Cronbach-α/Spearman — only a private spearman_rho on rankings in probe_p1_gamma_phase.rs, and a separately hand-rolled one in the stockfish-rs chess probe. The D-TRI measurement gates all name a battery that didn't exist as an API:

  • D-TRI-2 — 12-family ↔ 12-step reading agreement.
  • D-TRI-4 — chess ↔ thinking transfer (validity + reliability).
  • D-TRI-5 — emulation vs resonance on opponent prediction.

Operator brief: "measure with lance-graph/crates/JC ICC Pearson Cronbach alpha spearman."

Correctness

Point estimates ONLY — significance calibration stays jc::jirak's job under I-NOISE-FLOOR-JIRAK (the fingerprint bits are weakly dependent by construction; classical IID Berry-Esseen is wrong). Formulas pinned to reference values:

  • Shrout-Fleiss (1979) worked example (6 subjects × 4 judges): ICC(2,1) = 0.290, ICC(3,1) = 0.715 — matches R psych::ICC / Python pingouin.
  • Pearson perfect/anti (±1), a textbook r ≈ 0.7746, Spearman monotone-nonlinear = 1, tie-correction ρ ≈ 0.9487, Cronbach α = 1 for identical items + a hand-verified 0.9846.

12 unit tests + 3 doctests green; cargo clippy --lib exit 0.

Follow-up (not in this PR)

The two existing hand-rolled spearman_rho copies (probe_p1, stockfish-rs) can migrate to jc::reliability::spearman; thinking-engine/src/cronbach.rs (excluded crate) is separate prior art. Left as a follow-up, not forced here.

Board

EPIPHANIES E-JC-IS-NOT-A-METRIC-BATTERY-1 (same commit).

🤖 Generated with Claude Code

https://claude.ai/code/session_01Awg6TXocHcwTtc6eGsHcdD


Generated by Claude Code

Summary by CodeRabbit

  • New Features

    • Added reliability metrics for Pearson correlation, tie-corrected Spearman correlation, Cronbach’s alpha, and intraclass correlation.
    • Added support for absolute-agreement and consistency ICC calculations.
    • Metrics now safely indicate undefined or insufficient-input results instead of producing invalid values.
  • Documentation

    • Documented the newly available reliability metrics and shader rung-ascent milestone.

…h α/ICC)

crates/jc was a FORMAL-SCAFFOLD pillar-prover with NO callable
reliability/validity metrics — only a private spearman_rho on rankings
in probe_p1, and a separately hand-rolled one in the stockfish chess
probe. The D-TRI-2 (12-family vs 12-step agreement), D-TRI-4
(chess<->thinking transfer) and D-TRI-5 (emulation vs resonance) gates
all name a battery that did not exist as an API.

New jc::reliability module:
- pearson(x, y): product-moment correlation.
- spearman(x, y): Pearson on average-rank (tie-corrected) transform.
- cronbach_alpha(items): internal-consistency reliability of a k-item scale.
- icc(ratings, IccForm::{Icc2_1, Icc3_1}): Shrout-Fleiss 1979 two-way ANOVA
  ICC — absolute-agreement and consistency single-measure forms.

All return Option<f64> (None on degenerate input — no panics/NaN, per the
no-unwrap guideline). Point estimates ONLY; significance calibration stays
jc::jirak's job (I-NOISE-FLOOR-JIRAK: weak dependence, not IID Berry-Esseen).

Formula correctness pinned to reference values: Shrout-Fleiss worked example
ICC(2,1)=0.290 / ICC(3,1)=0.715 (matches R psych::ICC / pingouin), plus
Pearson/Spearman/Cronbach textbook checks. 12 unit tests + 3 doctests green;
clippy exit 0.

Board: EPIPHANIES E-JC-IS-NOT-A-METRIC-BATTERY-1.

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

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Changes

Reliability metrics

Layer / File(s) Summary
Public module wiring and API contract
crates/jc/src/lib.rs, crates/jc/src/reliability.rs
Exports the reliability module and defines option-based metric APIs, alongside formatting-only updates to existing reporting and pillar registration.
Metric implementations
crates/jc/src/reliability.rs
Adds Pearson, tie-corrected Spearman, Cronbach’s alpha, and ICC(2,1)/ICC(3,1) calculations with input validation.
Metric validation tests
crates/jc/src/reliability.rs, .claude/board/EPIPHANIES.md
Tests reference values, tie handling, bias penalties, and degenerate inputs, and records the shipped metric battery.

Shipped board notes

Layer / File(s) Summary
Shader-driver milestone note
.claude/board/EPIPHANIES.md
Records rung ascent wiring, RungLevel deduplication, and the axis-mismatch correction.

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

Suggested reviewers: claude

Poem

A rabbit checks the numbers bright,
With ranks that tie and means just right.
ICC hops through every rung,
While shipped notes hum a song well-sung.
Reliability blooms—thump, thump!

🚥 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 accurately summarizes the main change: adding a jc reliability/validity metric battery with Pearson, Spearman, Cronbach α, and ICC.
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.

@cursor

cursor Bot commented Jul 17, 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_c5aeccd3-fd89-44f5-9473-acd94ca9aa65)

@AdaWorldAPI
AdaWorldAPI marked this pull request as ready for review July 17, 2026 13:11

@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: 2

🤖 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/jc/src/reliability.rs`:
- Line 7: The documented pillar count is stale: update the “ten pillars”
reference in crates/jc/src/reliability.rs at lines 7-7 to reflect the 12
registered pillars or remove the hard-coded count, and correct the shipped
inventory in .claude/board/EPIPHANIES.md at lines 5-5 without reordering its
ledger.
- Around line 76-96: Update pearson, the rank-correlation API, and the
reliability APIs at crates/jc/src/reliability.rs lines 76-96, 102-149, 181-203,
and 239-287 to reject non-finite inputs before calculations and return None
whenever intermediate values or the final result are non-finite. Add regression
tests covering NaN, positive and negative infinity, and large finite values for
all four APIs, ensuring none can return Some(NaN).
🪄 Autofix (Beta)

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: 746501cd-c336-42cc-8d1e-2af1150f036f

📥 Commits

Reviewing files that changed from the base of the PR and between 8d3209c and 08f96b8.

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

//!
//! # Why this lives in `jc`
//!
//! `jc` is otherwise a proof-in-code harness (the ten pillars). But the

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Synchronize the documented pillar count with the 12 registered pillars.

  • crates/jc/src/reliability.rs#L7-L7: replace “ten pillars” with the current count or avoid a hard-coded count.
  • .claude/board/EPIPHANIES.md#L5-L5: correct the shipped inventory without reordering the ledger.
📍 Affects 2 files
  • crates/jc/src/reliability.rs#L7-L7 (this comment)
  • .claude/board/EPIPHANIES.md#L5-L5
🤖 Prompt for 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.

In `@crates/jc/src/reliability.rs` at line 7, The documented pillar count is
stale: update the “ten pillars” reference in crates/jc/src/reliability.rs at
lines 7-7 to reflect the 12 registered pillars or remove the hard-coded count,
and correct the shipped inventory in .claude/board/EPIPHANIES.md at lines 5-5
without reordering its ledger.

Comment on lines +76 to +96
pub fn pearson(x: &[f64], y: &[f64]) -> Option<f64> {
if x.len() != y.len() || x.len() < 2 {
return None;
}
let mx = mean(x)?;
let my = mean(y)?;
let mut sxy = 0.0;
let mut sxx = 0.0;
let mut syy = 0.0;
for (&xi, &yi) in x.iter().zip(y.iter()) {
let dx = xi - mx;
let dy = yi - my;
sxy += dx * dy;
sxx += dx * dx;
syy += dy * dy;
}
let denom = (sxx * syy).sqrt();
if denom == 0.0 {
return None; // at least one series is constant
}
Some(sxy / denom)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Enforce the promised no-NaN API contract.

All four APIs can currently return Some(NaN) for non-finite inputs or overflowing intermediate calculations.

  • crates/jc/src/reliability.rs#L76-L96: validate both vectors and require a finite Pearson result.
  • crates/jc/src/reliability.rs#L102-L149: reject non-finite values before sorting ranks.
  • crates/jc/src/reliability.rs#L181-L203: validate every item score and require finite variances/result.
  • crates/jc/src/reliability.rs#L239-L287: validate every rating and require finite mean squares/denominator/result.

Add regression tests using NaN, infinities, and large finite values.

📍 Affects 1 file
  • crates/jc/src/reliability.rs#L76-L96 (this comment)
  • crates/jc/src/reliability.rs#L102-L149
  • crates/jc/src/reliability.rs#L181-L203
  • crates/jc/src/reliability.rs#L239-L287
🤖 Prompt for 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.

In `@crates/jc/src/reliability.rs` around lines 76 - 96, Update pearson, the
rank-correlation API, and the reliability APIs at crates/jc/src/reliability.rs
lines 76-96, 102-149, 181-203, and 239-287 to reject non-finite inputs before
calculations and return None whenever intermediate values or the final result
are non-finite. Add regression tests covering NaN, positive and negative
infinity, and large finite values for all four APIs, ensuring none can return
Some(NaN).

@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: 08f96b8882

ℹ️ 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 on lines +107 to +110
idx.sort_by(|&a, &b| {
xs[a]
.partial_cmp(&xs[b])
.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 Reject non-finite measurements before ranking

When an upstream metric vector contains a non-finite value (for example a missing/overflow score encoded as NaN), this comparator treats it as equal for sorting, but the later tie grouping uses ==, so the NaN receives an ordinary rank; spearman(&[1.0, f64::NAN, 2.0], &[1.0, 2.0, 3.0]) returns Some(1.0). Pearson/Cronbach/ICC similarly return Some(NaN), contradicting the module contract that undefined estimates return None rather than NaN/garbage and allowing a bad measurement to falsely pass or poison agreement gates.

Useful? React with 👍 / 👎.

@AdaWorldAPI
AdaWorldAPI merged commit 5249feb into main Jul 17, 2026
8 checks passed
AdaWorldAPI pushed a commit that referenced this pull request Jul 17, 2026
The battery's module doc promised `None` "rather than returning NaN", but
non-finite input slipped through: spearman(&[1.0, NAN, 2.0], ...) returned
Some(1.0) (average_ranks maps NaN to a finite rank, so it never reached the
delegated pearson guard) and pearson/cronbach_alpha/icc returned Some(NaN).

Add an `all_finite` helper + up-front finite guards on all four public APIs
(spearman guards the raw values before ranking), plus trailing result guards
so finite-but-overflowing magnitudes (deviations -> +/-inf -> ratio NaN) also
return None. Two regression tests cover NaN/+/-inf (incl. the reported
reproducer) and 1e308-overflow inputs.

Also soften the "ten pillars" aside in the module doc to "registered pillars"
(the registry holds 12; a hard count in a doc-comment is a drift magnet).

Found post-merge by CodeRabbit (Major) and Codex independently on #709.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Awg6TXocHcwTtc6eGsHcdD
AdaWorldAPI added a commit that referenced this pull request Jul 17, 2026
…iles-nhqgx1

jc reliability: enforce the no-NaN contract on non-finite input (follow-up to #709)
AdaWorldAPI pushed a commit that referenced this pull request Jul 17, 2026
…::reliability)

D-TRI-2 (12-step ↔ 12-family agreement) is NO-GO pre-mint: both 12-vectors are
codebook views of the unbuilt minted register (D-TRI-1). Scoped and recorded
(E-D-TRI-2-MINT-BLOCKED-1) so no future session re-attempts it.

The mint-free cousin: measure whether the three SHIPPED 12-family param tables
actually agree — the exact D-TSC-1 "five tables diverged silently" failure mode,
using the jc::reliability battery (#709/#710).

New probe crates/jc/examples/style_table_agreement.rs (transcribes UNIFIED_STYLES,
thinking-engine StyleParams, planner FieldModulation with per-value // SOURCE
provenance; verified against source). Runs ICC(2,1)/ICC(3,1)/Cronbach α/pairwise
Pearson-Spearman per shared dim in all-12 and 7-explicit modes; pre-registered
ICC bands 0.75/0.50; exit-0 (DISTINCT is a valid finding, never a build failure).

Measured verdict:
- UNIFIED_STYLES ≡ thinking-engine StyleParams: PERFECT (r=ρ=1.0) — M9-dedup
  confirmed, the two are one table in two homes.
- Planner FieldModulation's 7 explicitly-calibrated families: IDENTITY (ICC 0.90-0.98).
- ONLY drift: the 5 planner default_modulation fallbacks (convergent/systematic/
  divergent/diffuse/peripheral → flat 0.7/6/0.3) drop all-12 ICC to 0.71 (AMBIGUOUS).
  → TD-PLANNER-STYLE-DEFAULT-DRIFT-1: fill them from the canonical table.

Board: EPIPHANIES E-D-TRI-2-MINT-BLOCKED-1, STATUS_BOARD D-TSC-1b, TECH_DEBT,
triangle plan §6 annotation, AGENT_LOG. Measurement-only, no behavior change.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Awg6TXocHcwTtc6eGsHcdD
AdaWorldAPI pushed a commit that referenced this pull request Jul 17, 2026
IMPLEMENT — arigraph/community.rs: TripletGraph::communities() — multi-level
Louvain modularity over the triplet adjacency (NARS-confidence-weighted edges,
self-loops dropped), a carrier method (litmus-compliant), deterministic
(BTreeMap-ordered moves + sorted-entity index), 5 inline tests. The STRUCTURAL
partition complementing the episodic/family (part_of:is_a) basins AriGraph owns.
Louvain core verified standalone before the in-crate build (two-triangle -> 2
comms Q=0.357, clique -> 1, determinism, empty-safe, weighted-cohesion); built
against jc/examples/splat_louvain_modularity.rs (parallel-session reference).
Leiden refinement pass + PPR/community fusion into retrieval.rs are D-GR-3b.

WRITE — plan v1.2:
- The base is a MEANING MEASUREMENT: COCA + NARS are co-equal core faculties;
  agnosticism is scoped to raw data + consumer modelling only (NOT meaning). The
  12-byte facet is 6x2x8bit (CLAM), never f32 (f32 is build-time source only);
  256 = ranking (needs cosine-replacement), 256^2 = distribution (as accurate as
  content-blind f32); the 6x(8:8) register is polymorphically part_of:is_a
  family-identity OR palette256^2 centroid (one register, two lenses) (S3a).
- Leiden community synergies: distributional-meaning modes, NARS-truth-weighted
  (6 axes; the rung-3 layer of the ascent) (S3b).
- DocumentID-KV / witness-handle seam: a stable DocumentID keys the consumer KV;
  the witness/node hold handles only, never raw bytes (S4a, D-GR-6).
- New probes: P-COMMUNITY-BASIN-AGREE, P-HIER-LEIDEN-HHTL,
  P-MEASUREMENT-DETERMINISM, P-PQ-RANK (all via jc::reliability, merged #709/#710).
- Meaning-substrate hazard (S7.6): do not reintroduce "keep language out"; the
  only real constraint is crate-layering (core can't dep the downstream deepnsm
  crate; use the in-core nsm/ copy).

Board hygiene: INTEGRATION_PLANS entry updated to v1.2.

Co-Authored-By: Claude <noreply@anthropic.com>
AdaWorldAPI pushed a commit that referenced this pull request Jul 17, 2026
IMPLEMENT — arigraph/community.rs: TripletGraph::communities() — multi-level
Louvain modularity over the triplet adjacency (NARS-confidence-weighted edges,
self-loops dropped), a carrier method (litmus-compliant), deterministic
(BTreeMap-ordered moves + sorted-entity index), 5 inline tests. The STRUCTURAL
partition complementing the episodic/family (part_of:is_a) basins AriGraph owns.
Louvain core verified standalone before the in-crate build (two-triangle -> 2
comms Q=0.357, clique -> 1, determinism, empty-safe, weighted-cohesion); built
against jc/examples/splat_louvain_modularity.rs (parallel-session reference).
Leiden refinement pass + PPR/community fusion into retrieval.rs are D-GR-3b.

WRITE — plan v1.2:
- The base is a MEANING MEASUREMENT: COCA + NARS are co-equal core faculties;
  agnosticism is scoped to raw data + consumer modelling only (NOT meaning). The
  12-byte facet is 6x2x8bit (CLAM), never f32 (f32 is build-time source only);
  256 = ranking (needs cosine-replacement), 256^2 = distribution (as accurate as
  content-blind f32); the 6x(8:8) register is polymorphically part_of:is_a
  family-identity OR palette256^2 centroid (one register, two lenses) (S3a).
- Leiden community synergies: distributional-meaning modes, NARS-truth-weighted
  (6 axes; the rung-3 layer of the ascent) (S3b).
- DocumentID-KV / witness-handle seam: a stable DocumentID keys the consumer KV;
  the witness/node hold handles only, never raw bytes (S4a, D-GR-6).
- New probes: P-COMMUNITY-BASIN-AGREE, P-HIER-LEIDEN-HHTL,
  P-MEASUREMENT-DETERMINISM, P-PQ-RANK (all via jc::reliability, merged #709/#710).
- Meaning-substrate hazard (S7.6): do not reintroduce "keep language out"; the
  only real constraint is crate-layering (core can't dep the downstream deepnsm
  crate; use the in-core nsm/ copy).

Board hygiene: INTEGRATION_PLANS entry updated to v1.2.

Co-Authored-By: Claude <noreply@anthropic.com>
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