feat: name leftover-map cross share on leftover pairs (v2.12.29) - #563
Conversation
Persist leftover-map cross share x = 2 R̂_c U_c / R̃² of centered leftover on leftover post–criterion pairs (ADR 0185). After make seed, closest and farthest leftover pairs sit above the member list with 2R̂U/R̃² next to leftover-map distance d; click opens that post. A signed remainder is shown, never clamped. Do not invent a leftover score. Do not persist explained leftover share e, unexplained leftover share s, unexplained leftover U, or reconstruction R̂.
|
Warning Review limit reachedNext included review available in 38 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 selected for processing (21)
📝 WalkthroughWalkthrough기간 보고서 leftover pair가 ChangesLeftover-map cross-share
AdminPanel 인증 가드
Estimated code review effort: 4 (Complex) | ~45 minutes Merge Risk: 🟡 Moderate · up to This PR adds and persists leftover-map cross-share values and exposes them in the UI, but the current implementation can omit valid shares for small finite inputs, and an unsafe rollback order can cause report queries to fail when the new column is removed before the application is downgraded. These bounded correctness and deployment risks should be fixed or explicitly accepted before merge. Sequence Diagram(s)sequenceDiagram
participant PeriodReport
participant leftover_pairs
participant report_ingestion
participant PostgreSQL
participant App
PeriodReport->>leftover_pairs: leftover pair 계산
leftover_pairs-->>PeriodReport: cross-share 포함 LeftoverPair 반환
PeriodReport->>report_ingestion: report 저장 요청
report_ingestion->>PostgreSQL: cross-share 저장
App->>PostgreSQL: leftover pair 조회
PostgreSQL-->>App: cross-share와 distance 반환
App-->>App: cross-share 포맷 및 post 링크 표시
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 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 |
Replace the self-comparison NaN check with math.isnan and the literal infinity comparison with math.isinf so the assertion intent is explicit (github-code-quality review thread).
# Conflicts: # AGENTS.md # ARCHITECTURE.md # CHANGELOG.md # CLAUDE.md # backend/app/report_ingestion.py # backend/tests/test_api.py # docker/postgres-init/migrate.sh # docs/adr/0048-persist-lsirm-leftover-pairs.md # docs/adr/0049-leftover-pair-report-ui.md # frontend/package.json # frontend/src/App.test.tsx # frontend/src/App.tsx # frontend/src/api.ts # frontend/src/components/AdminPanel.tsx # frontend/src/i18n.test.ts # frontend/src/i18n.ts # lineageweave/leftover_pairs.py # pyproject.toml # scripts/seed_demo_data.py # tests/test_leftover_pairs.py # tests/test_migration_replay.py # tests/test_period_report.py # tests/test_schema.py # uv.lock
The 3-way merge of feat/leftover-map-cross-share-v21229 into main silently dropped main's rememberOidcReturnUrl/returnUrlFromLocation import (git resolved the adjacent import-block edits without a conflict marker), breaking tsc with two TS2304 errors. Restore it.
Squaring before the 1e-12 comparison made the effective threshold
sqrt(1e-12) = 1e-6, so a small-but-finite centered leftover (R-tilde =
1e-7, reconstruction 5e-8, x = 0.5) collapsed to an omitted badge.
Compare absolute values first; regression test added.
Also rename the Vietnamese cross-term label from phần dư đồng nhất
(reads as 'identical residual') to phần giao ('cross part'), matching
the 2 R-hat_c U_c / R-tilde-squared quantity it names; i18n expectation
updated (coderabbit review threads).
# Conflicts: # AGENTS.md # ARCHITECTURE.md # CHANGELOG.md # CLAUDE.md # backend/tests/test_api.py # docs/adr/0003-fast-mlsirm-report-integration.md # frontend/package.json # lineageweave/leftover_pairs.py # pyproject.toml # tests/test_leftover_pairs.py # tests/test_period_report.py # tests/test_schema.py # uv.lock
seed() called _seed_demo_period_report, which persists rows into report_leftover_map_axis, but never ran migration 0169 that creates that table -- inherited from the leftover-map axis-share merge and would crash `make seed` on a fresh database. The seeded_db/schema_db pytest fixtures already ran 0169 directly, so no test caught this.
The merge changed _leftover_map_positions' third return value from an int rank (PR563's own contract, needed only a count) to the raw kept singular-value array (origin/main's axis-share contract, needed for Gabriel inertia) -- both callers now use the array. This test still unpacked it as a scalar and compared it directly to an int, which raised on any residual matrix with more than one kept singular value.
# Conflicts: # AGENTS.md # ARCHITECTURE.md # CHANGELOG.md # CLAUDE.md # backend/app/report_ingestion.py # backend/tests/test_api.py # docs/adr/0003-fast-mlsirm-report-integration.md # docs/adr/0048-persist-lsirm-leftover-pairs.md # docs/adr/0049-leftover-pair-report-ui.md # frontend/package.json # frontend/src/App.test.tsx # frontend/src/api.ts # frontend/src/components/LeftoverPairList.tsx # frontend/src/i18n.test.ts # frontend/src/i18n.ts # lineageweave/leftover_pairs.py # pyproject.toml # scripts/seed_demo_data.py # tests/test_leftover_pairs.py # tests/test_period_report.py # tests/test_schema.py # uv.lock
|
Cycle comment: leftover increment still waits for independent APPROVE + exact-head required success. Author must not self-approve. Do not squash-merge without that APPROVE. Recut leftover-map length onto protected main as independent v2.12.31 / ADR 0187 (0183–0186 claimed by open leftover share/reconstruction PRs). Do not mix leftover stacks. Issues #79 and #87 stay open. |
Merge commit only: two test-side gaps left by clean auto-merge. _candidate_row() gained leftover_map_cross_share upstream; one direct unit-test call site (the residual-boundary rejection test) wasn't updated to pass it, so importing the test module raised a TypeError. Separately, the API test's per-pair assertions both validated leftover_map_unexplained's shape (added by an already-merged main PR) and asserted its absence (this branch's original, now-stale expectation) side by side -- drop the stale negative assertion.
# Conflicts: # AGENTS.md # ARCHITECTURE.md # CHANGELOG.md # lineageweave/leftover_pairs.py # scripts/seed_demo_data.py # tests/test_leftover_pairs.py
The pushed merge resolution left "## [2.12.29] - 2026-08-24" as its own dated header positioned after "## [2.15.0] - 2026-08-25", which reads as though the lower version shipped after the higher one. Move its bullet into [Unreleased]/Added instead of leaving a stale dated header in the wrong chronological position, matching how the rest of this changelog sequences dated sections.
# Conflicts: # AGENTS.md
…1229' into HEAD # Conflicts: # CHANGELOG.md
# Conflicts: # ARCHITECTURE.md # docs/adr/0049-leftover-pair-report-ui.md
…588) * feat: name leftover-map reconstruction on leftover pairs (v2.12.31) Persist two-axis Gabriel reconstruction R̂ = ξ_{1:2} · ζ_{1:2} on period leftover pairs so landed unexplained leftover U = R − R̂ stays auditable as U + R̂ = R (ADR 0183). Reconstruction is the same internal two-axis inner product already used for U; do not substitute the centered R̃ reconstruction claimed by leftover stack #564. After make seed, closest and farthest leftover pairs sit above the member list with signed R̂ next to leftover-map distance d; click opens that post. Missing or non-finite reconstruction omits the badge rather than inventing a leftover score. Signed reconstruction is stored, never clamped. Complete-case coverage (ADR 0168) stays independent. Independent of leftover stacks #485, #518 (landed), #521, #537, #539, #563, #564, and #579. * fix(adr): allocate reconstruction decision 0201 * fix: restore R̂-persistence docs and finish ADR 0183→0201 renumbering The prior merge of origin/main into this branch (91d8e4f) resolved the AGENTS.md/ARCHITECTURE.md/CLAUDE.md conflicts by dropping this PR's own leftover-map reconstruction documentation: - AGENTS.md reverted to "Two-axis reconstruction R̂ is not persisted", contradicting the shipped migration/ADR 0201 that persists it, and dropped ADR 0201 from the governing-ADR list. - ARCHITECTURE.md kept a redundant "0183 / 0201" pair (0183 is this repo's real, unrelated ADR 0183 "GNB four Korean chrome"; the stale 0183 leftover-map reference should have been renumbered to 0201, not kept alongside it). - CLAUDE.md's "Where the rest lives" pointer never got the ADR 0201 cross-reference added. Also finishes the ADR-number renumbering the PR's own history had started (docs/adr/0201-leftover-map-reconstruction.md is the actual ADR; ADR 0183 already belongs to a different, already-landed decision on main): fixes remaining stale "ADR 0183" citations in docs/adr/0003, the 2.12.31 CHANGELOG.d fragment, and the migration 0183 SQL header comment, all of which should cite ADR 0201. docs/adr/0049's own conflict resolution (0158 + 0201 amendments) was already correct and is unchanged. * docs: reconcile ADR 0182 reconstruction context * test(leftover): cover reconstruction candidate contract * fix(leftover): prove rank-zero reconstruction identity --------- Co-authored-by: seonghobae <seonghobae@users.noreply.github.com>
Buyer next action
After
make seed, leftover post–criterion pairs sit above the member list with leftover-map cross share2R̂U/R̃²next to leftover-map distanced. Click the pair to open that post. The share badge is omitted when the pair has no complete-case leftover map (fallback rows do not invent a share). A signed remainder is shown, never clamped. Never invent leftover score or theta.A leftover residual
Ris not the leftover the two leftover-map axes reconstruct. Truncated two-axis reconstruction of a higher-rank cell keeps unexplained leftoverU_c = R̃ − R̂_cand a cross term2 R̂_c U_c. The cell identityR̃² = R̂_c² + U_c² + 2 R̂_c U_ctherefore yieldse + s + x = 1with explained leftover sharee = R̂_c² / R̃², unexplained leftover shares = U_c² / R̃², and leftover-map cross sharex = 2 R̂_c U_c / R̃². Hidingxlets a buyer reade + sas a complete leftover partition even though the truncated map leaves an identity remainder.xmay be negative when reconstruction and unexplained leftover have opposite signs.R̂_candU_cstay internal and are not persisted. This PR does not persisteors.A 0/0 origin cell (
R̃ = 0,R̂_c = 0,U_c = 0) storesx = 0, including the origin cell of a rank-1 map. A reconstructed nonzero rank-1 cell storesx = 0becauseU_c = 0even whenmean(R) ≠ 0.Scope (this PR only)
leftover_map_cross_shareon leftover pair rows (no nonnegative CHECK)leftover_map_cross_sharewhen complete-case ξ, ζ exist (x = 2 R̂_c U_c / R̃²; unused axes pad with 0; hidden SVD axes after the second are dropped)2R̂U/R̃²badge + named identity-remainder next action; i18n en/ko/zh/ja/vimean(R) ≠ 0; rank-3 synthetic residual provesx ≠ R,≠ leftover_distance, and internallye + s + x = 1without persistinge/s/R̂/U; leftover_distance stays full-rank Euclideanx = 0; fallback omits share; negative finite share is storedleftover_map_explained_share,leftover_map_unexplained_share,leftover_map_unexplained, orleftover_map_reconstructionaccessToken(login screen has no token) and drop unusedoidcReturnUrlimport so leftover UI typechecksIndependent of leftover stacks already in review
Do not mix into:
Merge contract
APPROVErequired (Copilot or human who is not the author)Summary by CodeRabbit
새 기능
버그 수정
문서