feat: persist leftover observed Y and expected E (v2.12.20) - #526
feat: persist leftover observed Y and expected E (v2.12.20)#526seonghobae wants to merge 2 commits into
Conversation
Name leftover_observed_score and leftover_expected_score on leftover pairs so leftover residual R = Y − E is checkable (ADR 0168). Missing cells stay out of the factorization. Do not invent a leftover score or a second theta.
|
Warning Review limit reachedNext included review available in 2 minutes. View limit detailsLimit details: You’ve used the included review currently available. You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository. Review configuration: ⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (21)
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 |
| return ( | ||
| LeftoverPair( | ||
| pair_kind=PAIR_KIND_CLOSEST, | ||
| post_id=closest[1], | ||
| criterion_code=closest[2], | ||
| leftover_distance=closest[0], | ||
| leftover_residual=closest[3], | ||
| ), | ||
| LeftoverPair( | ||
| pair_kind=PAIR_KIND_FARTHEST, | ||
| post_id=farthest[1], | ||
| criterion_code=farthest[2], | ||
| leftover_distance=farthest[0], | ||
| leftover_residual=farthest[3], | ||
| ), | ||
| max(distance, 0.0), | ||
| post_ids[person], | ||
| item_codes[item], | ||
| float(residual[person, item]), | ||
| float(matrix[person, item]), | ||
| float(expected[person, item]), | ||
| ) |
There was a problem hiding this comment.
📝 Info: Residual identity check is float-safe
The check constraint leftover_pair_residual_identity requires abs(R-(Y-E))<1e-9. In leftover_pairs.py, R is matrix-expected while Y and E are the same operands, so R and Y-E differ only by float epsilon (~1e-16). Rebuild/seed inserts cannot spuriously fail the constraint.
Was this helpful? React with 👍 or 👎 to provide feedback.
|
Do not merge this PR onto protected This head (
The independent reconstruction onto protected |
…pair login build migrations/0001_initial_schema.sql is shipped, baked into the Postgres image for fresh installs only. This PR had duplicated the new leftover_observed_score/leftover_expected_score columns (plus their residual-identity check constraint) directly into 0001 as well as into the correctly idempotent 0108_report_leftover_observed_expected.sql migration. Reverts 0001 to its shipped form (byte-identical to origin/main) so 0108 is the single source on every install path, and wires 0108 into the two hand-enumerated migration fixtures (tests/test_schema.py::schema_db, backend/tests/test_api.py::seeded_db) so removing it from 0001 doesn't silently stop creating the columns. Also repairs this branch's build: the login button still built an unsanitized returnUrl inline instead of using returnUrlFromLocation()/rememberOidcReturnUrl(), and an unreachable login-screen AdminPanel render (accessToken is string | undefined pre-login) failed the TypeScript build. Same root cause and fix as every other branch that inherited this from before the canonical fix landed on main.
Buyer next action
After
make seed, leftover closest/farthest pairs still sit above the period-report member list. Each pair now names observed scoreY, expected scoreE[Y|θ, item], leftover residualR = Y − E, and leftover-map distanced. Read those badges, check leftover residual equals observed minus expected, then click the pair to open that post.Never invent a leftover score. Never invent a theta.
Exact unique scope
Independent leftover honesty slice on protected
main@ef6f5a5(v2.12.6). Exact head:60ec4e1e0731f624c5c1a75710fbdf82776c3f94.leftover_observed_scoreandleftover_expected_scoreonreport_leftover_pair(3NF, two-or-more-wordsnake_case).leftover_pair_residual_identity:abs(R − (Y − E)) < 1e-9.0108upgrades existing volumes. Existing leftover rows are derived; incomplete rows are deleted so rebuild/seed rewrites honestYandEinstead of fabricating them.GET /api/reports/{grouping}/{period}returnsYandE.Why this is independent
Does not mix into leftover persist-map (#481), leftover criterion landing (#485), leftover residual UI (#502), leftover complete-case coverage (#518), leftover-map axis share (#519), leftover comparison-strip (#521), or two-axis leftover-map distance (#522). Closed #511 shipped Y/E onto the unprotected
#426stack, not protectedmain.Issues #79 and #87 stay open.
Merge contract
Independent exact-head APPROVE required. Do not self-approve. Squash-merge only with independent APPROVE + exact-head required success.
Tests
uv run pytest tests/test_leftover_pairs.py tests/test_migration_replay.py: 8 passed (Y=4/1, E=3/2 residual identity; observed ≠ residual; 0108 replay).pnpm exec vitest run src/App.test.tsx: 78 passed, including observed/expected/leftover badges and next-action copy.Papers
Gabriel, K. R. (1971). The biplot graphic display of matrices with application to principal component analysis. Biometrika, 58(3), 453–467. https://doi.org/10.1093/biomet/58.3.453
Jeon, M., Jin, I. H., Schweinberger, M., & Baugh, S. (2021). Mapping unobserved item–respondent interactions: A latent space item response model with interaction map. Psychometrika, 86(2), 378–403. https://doi.org/10.1007/s11336-021-09762-5