Skip to content

feat(psychometric): posterior ESEM input gates with true-parameter RMSE - #49

Merged
seonghobae merged 97 commits into
mainfrom
agent/psychometric-posterior-esem-input
Aug 25, 2026
Merged

feat(psychometric): posterior ESEM input gates with true-parameter RMSE#49
seonghobae merged 97 commits into
mainfrom
agent/psychometric-posterior-esem-input

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 13, 2026

Copy link
Copy Markdown
Contributor

Summary

ADR 0005 first executable slice. No new migration (0007 remains owned by #45).

Test plan

  • RED: esem_input_recovery_contract failed to compile (E0432) before the public API existed
  • cargo test -p psychometric_core --offline (lib + contract tests)
  • cargo clippy --workspace --all-targets --offline -- -D warnings
  • python3 scripts/validate_documentation.py, check_docstrings.py, check_workspace_contract.py
  • cargo test --workspace --offline --lib --tests
  • exact-head required Checks on this PR (do not treat queued/stale evidence as passed)

Do not self-approve or merge until exact-head required checks and a qualifying independent review pass. Prefer merging #37 then #45 when those become eligible.


Open in Devin Review

Summary by CodeRabbit

  • 새 기능

    • 심리측정 분석 기능을 추가했습니다.
    • OLS 로딩, 사후 추정치 평균, Rubin 총분산, 군집 내·간 효과 및 Kish 가중 회귀를 지원합니다.
    • 지표 유형, 구성개념, 측정불변성 및 잠재평균 비교를 검증합니다.
    • 이벤트 시간 기반 평균·분산·공분산과 예측변수 효과를 계산합니다.
    • 부적절한 인과 해석과 잘못된 입력을 자동으로 거부합니다.
  • 문서

    • 지원 범위, 제한 사항, 연구 근거 및 검증 기준을 보강했습니다.
    • 구현 상태와 추적성 정보를 최신화했습니다.
  • 품질 개선

    • 비유한 값, 특이 설계, 오버플로·언더플로에 대한 안전한 오류 처리를 강화했습니다.
    • 주요 분석 결과와 오류 조건에 대한 검증을 확대했습니다.

ADR 0005 first production slice: construct classification, refusal of
raw-proportion Pearson, CPU f64 OLS and plausible-value loading recovery,
invariance-gated mean comparison, and causal-heuristic refusal. No new
migration.
@coderabbitai

coderabbitai Bot commented Aug 13, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

psychometric_core가 워크스페이스에 추가되었습니다. 새 crate는 입력 검증, OLS 및 Rubin 복원, 다층 효과, 측정 불변성, event-time 경계, 오류 계약을 공개합니다. 관련 테스트와 문서도 함께 갱신되었습니다.

Changes

psychometric_core 구현

Layer / File(s) Summary
크레이트 기반과 오류 계약
Cargo.toml, crates/psychometric_core/Cargo.toml, crates/psychometric_core/src/error.rs, crates/psychometric_core/src/lib.rs, scripts/check_workspace_contract.py, tests/quality/*
psychometric_core를 워크스페이스와 품질 계약에 등록했습니다. 공개 모듈과 PsychometricError를 구성했습니다.
입력 및 해석 게이트
crates/psychometric_core/src/indicator.rs, construct.rs, causality.rs, crates/psychometric_core/tests/esem_input_recovery_contract.rs
허용된 좌표를 검증합니다. raw proportion, formative 재해석, 미식별 인과 주장 및 불변성 없는 비교를 거부합니다.
OLS 및 posterior loading 복원
crates/psychometric_core/src/loading.rs, plausible.rs, rubin_total.rs, crates/psychometric_core/tests/*
OLS loading, posterior 점추정 평균 및 Rubin total variance를 계산합니다. 빈 입력, 비유한 수치 및 특이 설계를 거부합니다.
다층 효과와 잠재평균 불변성
crates/psychometric_core/src/cluster_mean.rs, latent_mean.rs, crates/psychometric_core/tests/rubin_and_mean_gate_contract.rs, docs/research/multilevel-multiple-membership-measurement.md, docs/research/strong-invariance-latent-means.md
CWC within/between/contextual 효과와 Kish 가중 기울기를 계산합니다. strong 또는 strict 불변성에서만 잠재평균 차이를 복원합니다.
Event-time 계산과 주장 경계
crates/psychometric_core/src/lib.rs, crates/psychometric_core/tests/scientific_claim_boundary_contract.rs, CHANGELOG.md, docs/adr/0005-posterior-esem-dsem.md, docs/research/multilevel-event-time-recovery.md
event-time 동역학, predictor 효과, 모멘트, 정상상태 계산 및 개념별 거부 경계를 공개하고 검증합니다.
문서 및 범위 추적
ARCHITECTURE.md, README.md, CLAUDE.md, DOCUMENTATION.md, docs/TRACEABILITY.md, docs/adr/README.md, docs/connectors/*, docs/research/posterior-esem-input-gates.md, docs/research/rubin-total-variance.md, docs/research/standards-and-literature.md, docs/validation/*
crate 책임, 구현 성숙도, 연구 근거, 검증 범위 및 변경 기록을 갱신했습니다.

Estimated code review effort: 5 (Critical) | ~120 minutes

Merge Risk: 🟡 Moderate · up to d634f

This PR adds posterior ESEM input gates and true-parameter RMSE, but the current head still contains a bypassable invariance assertion, a mismatched uncertainty-coverage threshold, and documentation/ADR claims that do not consistently match the supported scope. These can lead to unsupported scientific interpretations, and exact-head required checks are still incomplete, so merge should wait for fixes or explicit owner acceptance.

Sequence Diagram(s)

sequenceDiagram
  participant Caller
  participant IndicatorGate
  participant LoadingRecovery
  participant RubinCombiner
  Caller->>IndicatorGate: IndicatorKind 및 입력 검증
  IndicatorGate->>LoadingRecovery: 허용된 factor scores와 indicators 전달
  LoadingRecovery-->>RubinCombiner: draw별 OLS loading과 sampling variance 전달
  RubinCombiner-->>Caller: mean loading과 total variance 반환
Loading
🚥 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 제목은 posterior ESEM 입력 게이트와 true-parameter RMSE라는 PR의 주요 변경 사항을 간결하고 구체적으로 설명합니다.
Docstring Coverage ✅ Passed Docstring check was indeterminate for this PR — some files could not be analyzed in time. Not blocking.
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 💡 1
🛠️ Fix failing CI checks 💡
  • Create stacked PR
  • Commit on current branch
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch agent/psychometric-posterior-esem-input

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.

@seonghobae
seonghobae marked this pull request as ready for review August 15, 2026 09:25
…n T and strong means

Stacked on #49 psychometric_core. Not a second invariance crate. Not DSEM, RI-CLPM, MGCFA, or Mislevy PVs.

- CWC within/between OLS and Kish ESS WLS (Enders & Tofighi, 2007; Curran & Bauer, 2011; Hamaker et al., 2015; Kish, 1965)
- Event-time discrete lag-1 and exact scalar log-rate a = ln(φ)/Δt (Voelkle et al., 2012, Eq. 7; Driver et al., 2017, Eq. 3); difference quotient refused
- CWC-then-event-time residual lag, still not DSEM
- Rubin T_m = Ū_m + (1+1/m) B_m on draw-level OLS loadings (Rubin, 1996, p. 473)
- Two-group OLS latent means only under strong/strict; metric/weak is not enough. #84 metric licenses shared metric meaning only.
…re-centering

Curran and Bauer (2011, pp. 607–608) show that subtracting the
person-specific mean from a raw autoregressive series does not isolate
the lagged within-person effect. Caller-supplied residuals with irregular
event intervals recover a = ln(φ)/Δt. Still not DSEM. Meredith (1993)
and Mislevy (1991) remain unread (Unpaywall closed).
seonghobae added a commit that referenced this pull request Aug 23, 2026
Bind GAP current-head SHAs to the 2026-08-23T18:48:36Z REST inventory.
#49 unique-fold nightly is green on dd6cf43 and is not implemented-main.
Queued Checks remain off protected-main.
seonghobae added a commit that referenced this pull request Aug 23, 2026
Bind GAP current-head SHAs to the 2026-08-23T19:48:22Z REST inventory.
#49 unique-fold nightly remains green on dd6cf43 and is not
implemented-main. Queued Checks remain off protected-main.
@seonghobae
seonghobae enabled auto-merge (squash) August 24, 2026 00:59
@github-actions
github-actions Bot disabled auto-merge August 24, 2026 01:56
@seonghobae
seonghobae enabled auto-merge August 24, 2026 07:08

@devin-ai-integration devin-ai-integration 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.

Devin Review found 0 new potential issues.

Open in Devin Review

seonghobae added a commit that referenced this pull request Aug 24, 2026
* docs: add live product technical gap baseline

* docs: refresh live delivery baseline

* docs: record psychometric draft state

* docs: refresh temporal and image delivery queue

* docs: record Unicode identity PR in gap baseline

* docs: refresh buyer gap baseline for psychometric PR

* docs: refresh baseline for branch coverage repair

* docs: refresh baseline with current PR heads

* docs: record validation claim promotion head

* docs: refresh live PR baseline

* docs: bind baseline to refresh head

* docs: refresh gap baseline current heads

* docs: refresh live pull request evidence

* docs: expand TEPP completion gaps and issue roadmap

* docs: add product and technical gap baseline

* docs: normalize buyer gap maturity

* docs: remove duplicate gap baseline index entry

* docs(gap): refresh live queue snapshot

* docs(gap): split executable product capabilities

* docs(gap): align queue snapshot timestamp

* docs(gap): normalize maturity and authority fields

* docs: refresh live pull request gap evidence

* docs: record hot partition readiness gap

* docs: refresh live product gap snapshot

* docs: route Strix gap evidence to canonical owner

* docs: link exact Strix failure records

* docs: bound Strix evidence to public records

* docs(gaps): refresh live PR snapshot

* docs(gaps): bind snapshot to refreshed head

* docs: refresh live buyer-gap baseline

* docs: refresh live PR head register

* docs: require dated exact-head gap baseline

Refresh the live 2026-08-23 GitHub inventory, add a structure validator
that rejects queued-Checks-as-shipped claims, and cover it with quality
tests. PR #164 remains the single gap-baseline authority.

* docs: drop closed duplicate #179 from live register

Refresh the exact-head inventory to 93 open PRs after closing the
duplicate gap-baseline snapshot. PR #164 remains the single authority.

* docs: bind gap heads to the live 95-PR register

Refresh the exact-head inventory to 2026-08-23T13:31:34Z and set each
buyer-gap current head SHA to that snapshot, including #164, #48, #50,
#63, and #157. Queued Checks remain not implemented-main.

* fix(docs): honor negated queued-Checks wording in the gap validator

The promotion guard treated any same-line 'queued Checks'...'implemented-main'
window as a shipped claim, so correct negation failed and a wrapped
affirmative claim could evade. Require an un-negated match, including
across a line break.

* docs: refresh 96-PR exact-head gap register

Bind the live 2026-08-23T13:57:34Z inventory, including #49 extra-lag
underflow coverage and hourly #180/#164 repairs. Buyer-gap current
heads match that snapshot. Queued Checks are not implemented-main.

* docs: replace Buyer language in the live gap register

TEPP is not a purchase catalog. The gap baseline, validator, and
CHANGELOG now name operator-visible gaps and operator-gap closure
evidence.

* docs: refresh 96-PR exact-head gap register after #49 90b08bb

Bind GAP current-head SHA prefixes to the 2026-08-23T14:08:41Z live
inventory, including #49 extra-process lag underflow and #164 8b78797.
Queued Checks remain not implemented-main.

* docs: refresh 98-PR exact-head operator-gap register

Snapshot 2026-08-23T14:52:16Z. GAP-015 records this register's prior
exact head 33bf824. TEPP remains an operator-gap register, not a
purchase catalog.

* docs: refresh 97-PR exact-head gap register after stacked #191

Drop closed stacked #191, bind GAP current-head SHAs to the
2026-08-23T15:07:33Z REST inventory, and keep queued Checks off
implemented-main.

* docs: refresh 97-PR exact-head gap register after #49 1e3e2eb

Bind GAP current-head SHAs to the 2026-08-23T15:57:48Z REST inventory,
including #49 exp/expm1 overflow rewrites. Queued Checks remain off
implemented-main.

* docs: refresh 99-PR exact-head gap register after stacked #193/#194

Bind GAP current-head SHAs to the 2026-08-23T16:52:27Z REST inventory.
#49 nightly 1701/1702 on 1e3e2eb is logged, not treated as
implemented-main. Queued Checks remain off protected-main.

* docs: refresh 101-PR exact-head gap register after #49 dd6cf43

Bind GAP current-head SHAs to the 2026-08-23T17:59:26Z REST inventory,
including unique-fold coverage on #49 and stacked drafts #195/#196.
Queued Checks remain off implemented-main.

* fix(docs): require promotion-denial wording for queued-Checks guard

An unrelated `not` in `queued Checks are not required; this PR is
implemented-main` was treated as negation. Only never/do not/does not/
cannot/must not plus promote/treat/make/mean licenses the span.

* docs: refresh 103-PR exact-head gap register after stacked #197/#198

Bind GAP current-head SHAs to the 2026-08-23T18:48:36Z REST inventory.
#49 unique-fold nightly is green on dd6cf43 and is not implemented-main.
Queued Checks remain off protected-main.

* docs: refresh 105-PR exact-head gap register after stacked #199/#200

Bind GAP current-head SHAs to the 2026-08-23T19:48:22Z REST inventory.
#49 unique-fold nightly remains green on dd6cf43 and is not
implemented-main. Queued Checks remain off protected-main.

* docs: refresh 106-PR exact-head gap register after #201 span units

Bind GAP-005 to #201 5344729 as a first span-unit slice only, not
concept alignment and not implemented-main. Queued Checks remain off
protected-main.

* docs: refresh 109-PR exact-head gap register after #201 6afd650

Bind GAP-005 to the RFC 5646-once citation head and include stacked
drafts #202#204. Queued Checks remain off implemented-main.

* fix(docs): deny queued-Checks promotion by governed negation

Replace the fixed-window denial regex with sentence-scoped negation
governance: a claim passes only when a negation cue directly governs a
promotion verb inside the same sentence and no adversative conjunction
separates that pair from the maturity assertion. Honest wordings whose
negation precedes the phrase are accepted, while unrelated negated
clauses joined by 'but' can no longer license an implemented-main claim.

* docs: refresh 117-PR exact-head gap register after #205-#212

Eight new draft PRs opened in the Driver-recovery psychometric series
since the last snapshot. Protected-main SHA and non-draft count (70)
are unchanged -- no new mergeable work landed, this is a pure register
refresh.

* docs: refresh live product gap evidence

* docs(changelog): align gap-baseline snapshot entry with committed register

The Changed entry still described the predecessor 2026-08-23T21:46:37Z
snapshot (109 open / 39 drafts) while the committed baseline document
records the refreshed 2026-08-24T05:41:54Z snapshot (118 open / 48
drafts). Align the changelog narrative with the register the validator
enforces so the exact-head evidence stays internally consistent.

---------

Co-authored-by: seonghobae <seonghobae@users.noreply.github.com>
Co-authored-by: opencode-agent <agent@contextualwisdomlab.dev>
@github-actions
github-actions Bot disabled auto-merge August 24, 2026 07:52
@seonghobae
seonghobae enabled auto-merge August 25, 2026 01:30
Comment thread scripts/check_coverage.py
return merged


def load_union_branch_totals(files: Sequence[object]) -> Mapping[str, int | float]:

@devin-ai-integration devin-ai-integration 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.

Devin Review found 1 new potential issue.

Open in Devin Review

Comment thread scripts/check_coverage.py
Comment on lines +40 to +76
def load_union_branch_totals(files: Sequence[object]) -> Mapping[str, int | float]:
"""Merge LLVM branch outcomes by source coordinate across test binaries."""

outcomes: dict[tuple[str, int, int, int, int], list[int]] = {}
for file_record in files:
if not isinstance(file_record, Mapping):
raise ValueError("coverage file record must be an object")
filename = file_record.get("filename")
if "branches" not in file_record:
raise ValueError("coverage file record must contain branches")
branches = file_record["branches"]
if not isinstance(filename, str) or not filename:
raise ValueError("coverage file record must contain a filename")
if not isinstance(branches, list):
raise ValueError("coverage branches must be a list")
for branch in branches:
if not isinstance(branch, list) or len(branch) < 6:
raise ValueError("coverage branch record is malformed")
coordinates = branch[:4]
counts = branch[4:6]
if not all(
isinstance(value, int) and not isinstance(value, bool) and value >= 0
for value in coordinates
):
raise ValueError("coverage branch coordinates are invalid")
if not all(
isinstance(value, int) and not isinstance(value, bool) and value >= 0
for value in counts
):
raise ValueError("coverage branch counts are invalid")
key = (filename, *coordinates)
outcome = outcomes.setdefault(key, [0, 0])
outcome[0] += counts[0]
outcome[1] += counts[1]
count = len(outcomes) * 2
covered = sum(outcome > 0 for counts in outcomes.values() for outcome in counts)
return {"count": count, "covered": covered}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Duplicate coverage helper left after incomplete refactor

load_union_branch_totals is defined twice, identically, in check_coverage.py and check_coverage.py. The rewrite pointed load_totals at the new fold_unique_branch_totals, so the first copy is dead code shadowed by the second. Behavior is unchanged because the bodies match, but the redundant definition should be removed.

Prompt for agents
The function load_union_branch_totals is now defined twice with identical bodies in scripts/check_coverage.py (around lines 40-76 and again around lines 152-188). Remove one of the two duplicate definitions, keeping a single canonical definition. Confirm the remaining definition is still the one referenced by tests/quality/test_check_coverage.py (coverage_contract.load_union_branch_totals). Note that load_totals no longer calls this helper (it uses fold_unique_branch_totals), so verify the helper is only needed for the test path before deciding placement.
Open in Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

@github-actions
github-actions Bot disabled auto-merge August 25, 2026 02:03
@seonghobae
seonghobae enabled auto-merge August 25, 2026 02:13
# Conflicts:
#	Cargo.toml
#	README.md
#	docs/TRACEABILITY.md
#	docs/adr/README.md
#	docs/research/standards-and-literature.md

@devin-ai-integration devin-ai-integration 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.

Devin Review found 0 new potential issues.

Open in Devin Review

@opencode-agent
opencode-agent Bot disabled auto-merge August 25, 2026 02:22
@seonghobae
seonghobae merged commit 2da039f into main Aug 25, 2026
23 of 26 checks passed
cursor Bot pushed a commit that referenced this pull request Aug 25, 2026
The #49/#58/#65 merge reopened a second text fence and left historical
crate-list fragments inside Current implementation state. Keep one even
fence pair and list all 54 workspace members, including
psychometric_core.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.com>
cursor Bot pushed a commit that referenced this pull request Aug 25, 2026
The #49 merge left two load_union_branch_totals definitions, so the first
body was dead and the live success path had no test. Keep one helper and
cover valid multi-file True/False unions.

Co-authored-by: Seongho Bae <seonghobae@users.noreply.github.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.

1 participant