feat: name leftover-map reconstruction on leftover pairs (v2.12.30) - #564
feat: name leftover-map reconstruction on leftover pairs (v2.12.30)#564seonghobae wants to merge 6 commits into
Conversation
Persist two-axis Gabriel reconstruction R̂ of centered leftover on closest and farthest leftover pairs so buyers can read reconstructed leftover next to distance d, then open that post.
|
Warning Review limit reachedNext included review available in 16 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 (27)
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 |
|
Cycle 2026-08-24: pushed exact head Local verification: leftover pair unit tests 13 passed; frontend leftover formatters + LeftoverPairList + i18n + App leftover surface 133 passed. Synthetic fixtures only. |
| def _leftover_map_reconstruction( | ||
| person_xy: np.ndarray, item_xy: np.ndarray | ||
| ) -> float | None: | ||
| """Return two-axis reconstruction ``R̂_c = ξ_{1:2} · ζ_{1:2}`` when finite. | ||
|
|
||
| Rank-0 origin coordinates store ``0.0``. A non-finite inner product | ||
| is omitted rather than invented. Negative finite reconstruction is | ||
| stored; do not clamp or take an absolute value. | ||
| """ | ||
| reconstruction = float(np.dot(person_xy, item_xy)) | ||
| if np.isfinite(reconstruction): | ||
| return reconstruction | ||
| return None |
There was a problem hiding this comment.
📝 Info: Rank-0 maps store R̂=0, fallback stores None
A rank-0 residual still yields zero coordinate arrays (not None), so the complete-case branch runs and _leftover_map_reconstruction returns 0.0, matching ADR 0186 and test_leftover_pairs.py. Only the no-complete-case fallback path passes None.
Was this helpful? React with 👍 or 👎 to provide feedback.
# 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
…onstruction-v21230 # 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 # 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
| } else if (reconstructionBadge !== null) { | ||
| nextAction = tf(LEFTOVER_RECONSTRUCTION_ACTION, { | ||
| reconstruction: reconstructionBadge.replace(/^R̂\s+/, ""), | ||
| }); |
There was a problem hiding this comment.
📝 Info: Reconstruction next-action text unreachable for real payloads
The reconstruction branch in LeftoverPairList sits below the unexplained branch. Backend code sets leftover_map_unexplained (U = R − R̂) whenever reconstruction is finite, so real payloads always take the unexplained branch and LEFTOVER_RECONSTRUCTION_ACTION renders only for synthetic fixtures where reconstruction is set but unexplained is null. The R̂ badge still renders independently, so this is display-text-only, not a defect.
Was this helpful? React with 👍 or 👎 to provide feedback.
|
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. |
|
Cycle 2026-08-25T07:05 KST: #564 stays independent. It must not mix with leftover stacks #485 / #518 / #521 / #537 / #539 / #563 / #579. Landed ADR 0182 already defines unexplained leftover as This cycle therefore opens a fresh main-based persist of leftover-map reconstruction so |
# Conflicts: # AGENTS.md # ARCHITECTURE.md # frontend/package.json # lineageweave/leftover_pairs.py # pyproject.toml # tests/test_leftover_pairs.py # uv.lock
|
Independent leftover stack — do not mix. This cycle implements uncentered leftover-map reconstruction R̂ = ξ_{1:2} · ζ_{1:2} on current main (ADR 0183 / v2.12.31) so landed U + R̂ = R stays auditable. #564 remains the centered-R̃ reconstruction (ADR 0186 / v2.12.30) and is not rebased, amended, or squash-merged into this increment. Do not substitute centered R̃ for the reconstruction used to form unexplained leftover U (ADR 0182). |
|
Independent leftover stack — do not mix. Uncentered leftover-map reconstruction persist is now #588 (ADR 0183 / v2.12.31) on current main so landed |
# Conflicts: # CHANGELOG.md
Buyer next action
After
make seed, leftover post–criterion pairs sit above the member list with leftover-map reconstructionR̂next to leftover-map distanced. Click the pair to open that post. The reconstruction badge is omitted when the pair has no complete-case leftover map (fallback rows do not invent a reconstruction). A signed reconstruction is shown, never clamped. Never invent leftover score or theta.A leftover residual
Ris not the leftover the two leftover-map axes reconstruct. Gabriel (1971) reconstructs a centered matrix as the inner product of person and item coordinates. Two leftover-map axes pad unused axes with zero and drop hidden SVD axes after the second, so reconstructionR̂_c = ξ_{1:2} · ζ_{1:2}recovers centered leftoverR̃ = R − center, not raw residualRand not leftover-map distanced. Rank-0 origin maps storeR̂ = 0. A rank-1 cell stores exact centered leftover. A rank-3+ cell stores truncated reconstruction, which is notRand notd.Scope (this PR only)
leftover_map_reconstructionon leftover pair rows (no nonnegative CHECK)leftover_map_reconstructionwhen complete-case ξ, ζ exist (R̂_c = ξ_{1:2} · ζ_{1:2}; unused axes pad with 0; hidden SVD axes after the second are dropped)R̂badge + named reconstruction next action; i18n en/ko/zh/ja/viR̂ ≠ R,≠ leftover_distance, and≠full-rank inner product; leftover_distance stays two-axis EuclideanR̂ = 0; fallback omits reconstruction; negative finite reconstruction is storedleftover_map_explained_share,leftover_map_unexplained_share,leftover_map_unexplained,leftover_map_cross_share, or leftover-map coordinatesIndependent of leftover stacks already in review
Do not mix into:
Independent exact-head APPROVE required. Do not self-approve. Squash-merge only with independent APPROVE + exact-head required success.
Verification
uv run --with pytest --with numpy pytest tests/test_leftover_pairs.py— 13 passedLeftoverPairList, i18n, andApp.testleftover report surface — 133 passed