-
Notifications
You must be signed in to change notification settings - Fork 1
feat(reports): leftover-map singular values on leftover-axis report badges independently of leftover-map axis share (v2.82.0) #866
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
593b8d8
bae8103
265e91e
e26f523
39dd775
8cef532
198d682
e20200c
4b53924
d421c86
bb1c8c8
611636d
46c2c56
a87efee
e3cce38
7c570b4
3422a23
2efcf06
c267657
e98abe2
35f4b07
047cefc
6935ac4
6f75308
8d63271
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| ### Fixed | ||
|
|
||
| - Report leftover-axis evidence now has an explicit singular-only state so a valid persisted Gabriel `σ` remains visible when axis share is unavailable; share-only, combined, and empty states remain independent and missing evidence is not rendered as `NaN%`. |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| # ADR 0325 — Preserve singular-only and share-only report-axis evidence | ||
|
|
||
| **Decision status:** Proposed | ||
| **Date:** 2026-08-31 | ||
|
|
||
| ## Context | ||
|
|
||
| LineageWeave persists two different measurements for a leftover-map axis: Gabriel singular value `σ_k` and axis share. They have independent missingness. The report badge path previously chose its rendering branch from `σ_k` alone and formatted a missing share through numeric arithmetic, which can surface `NaN%` and erase the distinction between unavailable evidence and a measured value. | ||
|
|
||
| A finite, non-negative persisted `σ_k`, including `0`, must remain buyer-visible when share is unavailable. A finite persisted share must remain visible when `σ_k` is unavailable. Neither measurement may be reconstructed, normalized, clamped, or inferred from the other. | ||
|
|
||
| ## Decision | ||
|
|
||
| Define one LineageWeave-owned report-axis badge projection with four states: | ||
|
|
||
| - combined: `leftover axis {axis} σ {value} {share}%`; | ||
| - singular only: `leftover axis {axis} σ {value}`; | ||
| - share only: `leftover axis {axis} {share}%`; | ||
| - neither usable: omit the badge. | ||
|
|
||
| The projection consumes persisted axis values only. `σ_k` is accepted only when finite and non-negative; `σ=0` remains explicit. Share uses the existing finite-value formatter. Missing or invalid evidence fails closed independently. | ||
|
|
||
| This decision changes presentation composition only. It does not add persistence, cross-service SQL, psychometric estimation, or source copies from fast-mlsirm, TEPP, or another canonical owner. | ||
|
|
||
| ## Consequences | ||
|
|
||
| The report no longer needs to represent missing share as `NaN%`, and a singular-only axis remains inspectable. Existing combined and share-only buyer copy remains unchanged. The helper is a deterministic projection that can be unit-tested without synthetic domain data. | ||
|
|
||
| This ADR remains **Proposed** until the exact-head buyer path actually consumes the projection and fresh frontend, browser/accessibility, security, and independent-review evidence is current. | ||
|
|
||
| ## References | ||
|
|
||
| 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 |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,50 @@ | ||
| """Executable contract for the report-axis singular-only state.""" | ||
|
|
||
| from pathlib import Path | ||
|
|
||
|
|
||
| ROOT = Path(__file__).resolve().parents[1] | ||
| BADGE_SOURCE = ROOT / "frontend" / "src" / "leftoverMapAxisBadge.ts" | ||
| APP_SOURCE = ROOT / "frontend" / "src" / "App.tsx" | ||
|
|
||
|
|
||
| def test_report_axis_badge_preserves_singular_when_share_is_missing() -> None: | ||
| """A valid persisted σ remains visible when axis share is absent.""" | ||
| assert BADGE_SOURCE.exists(), "report-axis singular-value badge helper is missing" | ||
| source = BADGE_SOURCE.read_text(encoding="utf-8") | ||
|
|
||
| assert ( | ||
| 'LEFTOVER_MAP_AXIS_BADGE_SINGULAR_ONLY = "leftover axis {axis} σ {value}"' | ||
| in source | ||
| ) | ||
| assert 'LEFTOVER_MAP_AXIS_BADGE_SINGULAR = "leftover axis {axis} σ {value}{share}"' in source | ||
| assert "formatLeftoverMapPlotAxisShare" in source | ||
| assert 'return share === null ? "" : ` ${share}%`;' in source | ||
| assert "Number.NaN" not in source | ||
|
|
||
|
|
||
| def test_report_axis_badge_keeps_sigma_and_share_missingness_independent() -> None: | ||
| """σ-only, share-only, combined, and empty states must remain data-driven.""" | ||
| assert BADGE_SOURCE.exists(), "report-axis singular-value badge helper is missing" | ||
| source = BADGE_SOURCE.read_text(encoding="utf-8") | ||
|
|
||
| assert "formatLeftoverMapPlotAxisSingular" in source | ||
| assert "leftoverMapAxisBadgeShare" in source | ||
| assert "LEFTOVER_MAP_AXIS_BADGE_SINGULAR" in source | ||
| assert "LEFTOVER_MAP_AXIS_BADGE_SHARE" in source | ||
| assert "LEFTOVER_MAP_AXIS_BADGE_SINGULAR_ONLY" in source | ||
| assert 'singular === null && share === ""' in source | ||
| assert 'share === ""' in source | ||
| assert "Math.sqrt" not in source | ||
|
|
||
|
|
||
| def test_report_axis_rendering_consumes_the_four_state_projection() -> None: | ||
| """The report path must omit a badge when neither persisted axis datum is usable.""" | ||
| app_source = APP_SOURCE.read_text(encoding="utf-8") | ||
|
|
||
| assert "leftoverMapAxisBadge" in app_source | ||
| assert "const badge = leftoverMapAxisBadge(axis);" in app_source | ||
| assert "badge === null ? null" in app_source | ||
| assert "tf(badge.template, badge.values)" in app_source | ||
| assert "leftoverMapAxisBadgeShare" not in app_source | ||
| assert "leftoverMapAxisBadgeSingular" not in app_source | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This exact-head contract is now intentionally semantic rather than comma-sensitive, but production
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @coderabbitai autofix |
||
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
leftoverMapAxisBadge를 사용해 빈 배지를 생략하세요.frontend/src/App.tsx의 report-axis 렌더 루프는 개별 포매터를 직접 호출합니다. 두 값이 nullish 또는 non-finite이면singular는null,share는""이 되지만, 현재 분기는LEFTOVER_MAP_AXIS_BADGE_SHARE템플릿을 사용해leftover axis …배지를 렌더링합니다.leftoverMapAxisBadge(axis)의 non-null 결과만 렌더링하면 이 빈 상태를 생략할 수 있습니다.🤖 Prompt for AI Agents
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Finding verified against the live buyer path. I added an executable source-contract RED at
e98abe27eb01f40c2162bffedca14b0eb03516ec: production must import and consumeleftoverMapAxisBadge(axis), omit the badge when the projection isnull, and rendertf(badge.template, badge.values)otherwise. The production commit is not present yet, so this thread intentionally remains unresolved and the PR remains Draft. Repository Actions is currently pre-runner queued, so no predecessor receipt is being treated as GREEN.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@seonghobae, acknowledged. The source contract defines the required buyer-path behavior, but the production consumer change is still absent. The finding remains open untilApp.tsxconsumesleftoverMapAxisBadge(axis)and fresh validation provides a GREEN result.You are interacting with an AI system.