From ef5fcf63b6bcc2f6b451cb22b277116fb10fe138 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 30 Aug 2026 15:40:10 +0000 Subject: [PATCH 1/4] feat(reports): leftover-map singular values on grouping comparison strip (v2.51.0) Caption persisted leftover-map singular values on GET /api/reports/compare/{period} through leftoverMapCompareAxisSingular (ADR 0294). Distinct aria-label Leftover map comparison axis singular. Omit missing, non-finite, or negative leftover-map singular value independently of leftover-map comparison axis share. Do not invent leftover-map singular value from leftover-map axis share. No SQL. No leftover score or theta. --- AGENTS.md | 14 ++- ARCHITECTURE.md | 2 + ...51.0-leftover-map-compare-axis-singular.md | 18 +++ CHANGELOG.md | 39 +++++++ CLAUDE.md | 2 +- backend/tests/test_api.py | 8 ++ ...0294-leftover-map-compare-axis-singular.md | 108 ++++++++++++++++++ docs/product-technical-gap-baseline.md | 32 ++++++ docs/storybook-inventory.md | 2 +- frontend/package.json | 2 +- frontend/src/App.test.tsx | 25 +++- frontend/src/App.tsx | 33 ++++-- frontend/src/components/LeftoverPairList.tsx | 3 +- frontend/src/i18n.test.ts | 2 + frontend/src/i18n.ts | 8 ++ frontend/src/leftoverMapCompareAxis.test.ts | 66 +++++++++++ frontend/src/leftoverMapCompareAxis.ts | 37 +++++- frontend/src/leftoverMapPlotLayout.ts | 5 +- pyproject.toml | 2 +- 19 files changed, 389 insertions(+), 19 deletions(-) create mode 100644 CHANGELOG.d/2.51.0-leftover-map-compare-axis-singular.md create mode 100644 docs/adr/0294-leftover-map-compare-axis-singular.md diff --git a/AGENTS.md b/AGENTS.md index 9f55e640a..9dbe6db7d 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -422,8 +422,16 @@ pairs can read Gabriel inertia of residual SVD axes 1 and 2 for that grouping; a missing or non-finite share omits that leftover-map comparison axis share badge and does not invent leftover-map axis share from leftover-map singular value, leftover pair count, or plotted marker count. Share `0` is shown when -persisted, including rank-0 unused axes. The strip does not gain leftover-map +persisted, including rank-0 unused axes. ADR 0293 does not caption leftover-map singular values or the leftover-map graphic. +ADR 0294 captions the grouping comparison strip with persisted leftover-map +singular values through leftoverMapCompareAxisSingular so a buyer who compares leftover +pairs can read the Gabriel scale of residual SVD axes 1 and 2 for that grouping; +a missing, non-finite, or negative leftover-map singular value omits that leftover-map +comparison axis singular badge independently of leftover-map comparison axis share +and does not invent leftover-map singular value from leftover-map axis share, leftover +pair count, or plotted marker count. Rank-0 leftover-map singular value `0` is shown +when persisted. The strip does not gain the leftover-map graphic. When `R`, `R̂`, `U`, `x`, `s`, and `e` are finite, `e + s + x = 1`. When `Y`, `E`, and `R` are finite, `Y − E = R`. When `R`, `R̂`, and `U` are @@ -446,6 +454,10 @@ Grouping comparison incomplete post coverage (ADR 0291) captions the grouping comparison strip with how many scored posts stayed out of each grouping's map. Grouping comparison incomplete item coverage (ADR 0292) captions the grouping comparison strip with how many scored criteria stayed out of each grouping's map. +Grouping comparison leftover-map axis share (ADR 0293) captions the grouping +comparison strip with Gabriel inertia of residual SVD axes. +Grouping comparison leftover-map singular values (ADR 0294) captions the grouping +comparison strip with the Gabriel scale of those axes. Item complete-case coverage (ADR 0282) captions the leftover-map graphic with how many scored criteria entered the map. Item complete-case coverage on the pair list (ADR 0285) diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index dd6bc8a4e..35f815e56 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -677,6 +677,8 @@ ADR 0292 captions the grouping comparison strip with persisted leftover-map inco item coverage through leftoverMapIncompleteItemCount. ADR 0293 captions the grouping comparison strip with persisted leftover-map axis share through leftoverMapCompareAxisShare. +ADR 0294 captions the grouping comparison strip with persisted leftover-map singular +values through leftoverMapCompareAxisSingular. Click a post marker or a pair button opens that post. Those ADRs are the normative mathematical, storage, and display contracts. Leftover-map axis share diff --git a/CHANGELOG.d/2.51.0-leftover-map-compare-axis-singular.md b/CHANGELOG.d/2.51.0-leftover-map-compare-axis-singular.md new file mode 100644 index 000000000..f73c7aa67 --- /dev/null +++ b/CHANGELOG.d/2.51.0-leftover-map-compare-axis-singular.md @@ -0,0 +1,18 @@ +## 2.51.0 — Leftover-map singular values on the grouping comparison strip + +- Caption leftover-map singular values on the grouping comparison strip through + leftoverMapCompareAxisSingular (ADR 0294). After `make seed`, closest and + farthest leftover pairs sit above the member list with the Gabriel biplot + of already-named coordinates, leftover-map axis share when finite, + leftover-map singular values when finite and nonnegative, axis ticks that + match `ξ (x, y) ζ (x, y)` on the pair row, and leftover pairs with leftover-map + distance `d`; click a post marker or a pair button opens that post. A missing, + non-finite, or negative leftover-map singular value omits that leftover-map + comparison axis singular badge independently of leftover-map comparison axis + share. Rank-0 leftover-map singular value `0` is shown when persisted. Do not + invent leftover-map singular value from leftover-map axis share, leftover pair + count, plotted marker count, leftover-map distance, leftover-map rank, + leftover-map post coverage, leftover-map item coverage, leftover-map incomplete + post coverage, leftover-map incomplete item coverage, or the count of unused + axes. The strip does not gain the leftover-map graphic. Never invent a leftover + score. Never invent a theta. No new columns. diff --git a/CHANGELOG.md b/CHANGELOG.md index 2706f7c31..4cfd2e6ec 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,45 @@ All notable changes to this project are documented here. Format follows ### Added +- Period leftover pairs now caption the grouping comparison strip with + persisted leftover-map singular values through leftoverMapCompareAxisSingular + (ADR 0294 / v2.51.0). After `make seed`, closest and farthest leftover + pairs sit above the member list with the Gabriel biplot of already-named + coordinates, leftover-map axis share when finite, leftover-map singular + values when finite and nonnegative, axis ticks that match `ξ (x, y) ζ (x, y)` + on the pair row, pair segments that match `d` on the pair row, pair segments + that match `R̂` on the pair row, pair segments that match `R̂²/R²` on the pair + row, pair segments that match `U²/R²` on the pair row, pair segments that + match `2R̂U/R²` on the pair row, pair segments that match `U` on the pair row, + pair segments that match `R` on the pair row, pair segments that match `Y` on + the pair row, pair segments that match `E` on the pair row, pair segments that + match leftover-map rank on the pair row, a plot caption that matches leftover-map + complete-case coverage above the pair list, a plot caption that matches + leftover-map item complete-case coverage, a plot caption that matches + leftover-map incomplete post coverage, a plot caption that matches + leftover-map incomplete item coverage, a pair-list note that matches + leftover-map post complete-case coverage, a pair-list note that matches + leftover-map item complete-case coverage, a pair-list note that matches + leftover-map incomplete post coverage, a pair-list note that matches + leftover-map incomplete item coverage, a grouping comparison note that + matches leftover-map post complete-case coverage, a grouping comparison + note that matches leftover-map item complete-case coverage, a grouping + comparison note that matches leftover-map incomplete post coverage, a + grouping comparison note that matches leftover-map incomplete item + coverage, a grouping comparison leftover-map axis share badge that + matches leftover-axis report badges, and a grouping comparison leftover-map + singular-value badge; click a post marker or a pair button opens that post. + A missing, non-finite, or negative leftover-map singular value omits that + leftover-map comparison axis singular badge independently of leftover-map + comparison axis share. Rank-0 leftover-map singular value `0` is shown when + that persisted value is a finite nonnegative number. Do not invent leftover-map + singular value from leftover-map axis share, leftover pair count, plotted + marker count, leftover-map distance, leftover-map rank, leftover-map post + coverage, leftover-map item coverage, leftover-map incomplete post coverage, + leftover-map incomplete item coverage, or the count of unused axes. The strip + does not gain the leftover-map graphic. Never invent a leftover score. Never + invent a theta. No new columns. + - Period leftover pairs now caption the grouping comparison strip with persisted leftover-map axis share through leftoverMapCompareAxisShare (ADR 0293 / v2.50.0). After `make seed`, closest and farthest leftover diff --git a/CLAUDE.md b/CLAUDE.md index 1963b8114..6993e4098 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -49,7 +49,7 @@ cutoff. Global Ask optional `knowledge_cutoff` uses the same cover Create/start endpoint rules (ADR 0017 / 0021), tie-vs-miss similarity (ADR 0026), R&R catalog ids (ADR 0019 / 0027), leftover pairs -(ADR 0048–0164 / 0182 / 0185 / 0201 / 0233 / 0266 / 0267 / 0268 / 0269 / 0270 / 0271 / 0272 / 0273 / 0274 / 0275 / 0276 / 0277 / 0278 / 0279 / 0280 / 0281 / 0282 / 0283 / 0284 / 0285 / 0286 / 0287 / 0288 / 0289 / 0290 / 0291 / 0292 / 0293), occupational construct catalog search +(ADR 0048–0164 / 0182 / 0185 / 0201 / 0233 / 0266 / 0267 / 0268 / 0269 / 0270 / 0271 / 0272 / 0273 / 0274 / 0275 / 0276 / 0277 / 0278 / 0279 / 0280 / 0281 / 0282 / 0283 / 0284 / 0285 / 0286 / 0287 / 0288 / 0289 / 0290 / 0291 / 0292 / 0293 / 0294), occupational construct catalog search (ADR 0257), the text-channel embedding swap and cosine clamp (ADR 0190), per-edge channel-score persistence (ADR 0195), token-backed status notices (ADR 0220), diff --git a/backend/tests/test_api.py b/backend/tests/test_api.py index 95431c425..c20a110fc 100644 --- a/backend/tests/test_api.py +++ b/backend/tests/test_api.py @@ -5845,6 +5845,14 @@ def test_seed_period_report_surfaces_on_get_reports(client, demo_analyst_token, assert leftover_compare_axes[0]["leftover_share"] != leftover_compare_axes[0][ "leftover_singular_value" ] or leftover_compare_axes[0]["leftover_share"] in {0, 1} + assert all( + isinstance(axis["leftover_singular_value"], (int, float)) for axis in leftover_compare_axes + ) + assert all( + axis["leftover_singular_value"] == axis["leftover_singular_value"] + and axis["leftover_singular_value"] >= 0 + for axis in leftover_compare_axes + ) assert leftover_compare_coverage["map_item_count"] <= leftover_compare_coverage["scored_item_count"] assert leftover_compare_coverage["map_post_count"] != len( leftover_thread.get("leftover_pairs", []) diff --git a/docs/adr/0294-leftover-map-compare-axis-singular.md b/docs/adr/0294-leftover-map-compare-axis-singular.md new file mode 100644 index 000000000..07e52fa5a --- /dev/null +++ b/docs/adr/0294-leftover-map-compare-axis-singular.md @@ -0,0 +1,108 @@ +# ADR 0294 — Name leftover-map singular values on the grouping comparison strip + +**Decision status:** Accepted +**Date:** 2026-08-30 + +Amends leftover-map axis share on the grouping comparison strip +([ADR 0293](0293-leftover-map-compare-axis-share.md)) and leftover-map +axis share persistence ([ADR 0148](0148-leftover-map-axis-share.md)). +Independent of leftover-map incomplete item coverage on the grouping +comparison strip ([ADR 0292](0292-leftover-map-compare-incomplete-item.md)) +and leftover-map axis share on the graphic display +([ADR 0269](0269-leftover-map-axis-share-plot.md)). The dashboard plot stack +already named leftover-map singular values on graphic axes and leftover-axis +badges under other numbers; this protected increment uses **0294**. + +## Context + +ADR 0148 already persists leftover-map singular values `σ_k` and leftover-map +axis share `σ_k² / Σ_j σ_j²` on `report_leftover_map_axis`. ADR 0293 already +includes those persisted axes on `GET /api/reports/compare/{period}` and +captions leftover-map axis share on the grouping comparison strip. The strip +still names share without naming leftover-map singular value for that +grouping, so a buyer who compares PU / corp / thread leftover pairs can treat +an 82% first axis as if it had the same Gabriel scale as a rank-0 unused axis. + +This increment captions each grouping row through leftoverMapCompareAxisSingular. +It does not add columns. It does not invent leftover-map singular value from +leftover-map axis share, leftover pair count, plotted marker count, leftover-map +distance, leftover-map rank, leftover-map post coverage, leftover-map item +coverage, leftover-map incomplete post coverage, leftover-map incomplete item +coverage, or the count of unused axes. It does not persist leftover-map inner +product, cosine, or length as separate columns. Do not invent a leftover +score. Do not invent a theta. + +## Decision + +On the grouping comparison strip, caption leftover-map axis `k` as +`leftover map comparison axis {k} σ {value}` only when leftoverMapCompareAxisSingular +returns a usable leftover-map singular value from persisted +`leftover_singular_value`. Use the distinct accessible name +`Leftover map comparison axis singular` so the strip caption is not the +leftover-axis report badge (`leftover axis {k} σ {value} {share}%`) and is not +the graphic caption (`leftover-map axis {k} σ {value}`). A missing, non-finite, +or negative leftover-map singular value omits that leftover-map comparison axis +singular badge independently of leftover-map comparison axis share, leftover-map +post coverage notes, leftover-map item coverage notes, leftover-map incomplete +post notes, leftover-map incomplete item notes, leftover pairs, leftover-map +distance `d`, and any leftover-map captions on the pair list and graphic. +Rank-0 leftover-map singular value `0` is shown when that persisted value is a +finite nonnegative number. Do not invent leftover-map singular value from +leftover-map axis share, leftover pair count, plotted marker count, leftover-map +distance, leftover-map rank, leftover-map post coverage, leftover-map item +coverage, leftover-map incomplete post coverage, leftover-map incomplete item +coverage, or the count of unused axes. Do not add the leftover-map graphic to +the strip in this increment. Click a leftover pair on the strip to open that +post. + +Do not add SQL migrations. Do not edit shipped migrations. Do not persist inner +product, cosine, or length as separate columns. Do not invent a leftover +score. Do not invent a theta. + +## Consequences + +After `make seed`, the grouping comparison strip names persisted leftover-map +post complete-case coverage, persisted leftover-map item complete-case +coverage, persisted leftover-map incomplete post coverage, persisted +leftover-map incomplete item coverage, persisted leftover-map axis share, and +persisted leftover-map singular values on each grouping row when +leftoverMapCoverageCounts / leftoverMapItemCoverageCounts / +leftoverMapIncompletePostCount / leftoverMapIncompleteItemCount / +leftoverMapCompareAxisShare / leftoverMapCompareAxisSingular return usable +values, then names leftover pairs with leftover-map distance `d`. Closest +and farthest leftover pairs still sit above the member list with the +leftover-map graphic display; click a post marker or a pair button opens that +post. +Hidden posts stay hidden. + +## Related + +Independent of leftover interaction-map persistence, leftover-criterion +evaluation landing, leftover residual disclosure, leftover-map +complete-case coverage persistence, leftover-map axis share persistence, +leftover pairs on the grouping comparison strip, leftover-map complete-case +coverage on the grouping comparison strip, leftover-map item complete-case +coverage on the grouping comparison strip, leftover-map incomplete post +coverage on the grouping comparison strip, leftover-map incomplete item +coverage on the grouping comparison strip, leftover-map axis share on the +grouping comparison strip, leftover-map inner product, leftover-map cosine, +leftover-map length, leftover-map graphic display, leftover-map axis share +on the graphic display, leftover-map singular values on graphic axes, and +leftover-map singular values on leftover-axis badges. + +## 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 +(LSIRM interaction `−γ‖ξ_j − ζ_i‖` after main effects +`α_j − β_i`; typically `p = 2` for the interaction map. Leftover-map +singular values are the Gabriel scale `σ_k` of residual SVD axes; +grouping comparison leftover-map singular values name that persisted +`σ_k` for that grouping only when leftoverMapCompareAxisSingular returns +a usable value.) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index 6958ec3d1..f7ee5868a 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -1,5 +1,37 @@ # Product & Technical Gap Baseline +> Exact-head loop overlay: 2026-08-31 00:35 KST. Protected `main` is +> `cb187cadee5fb6c46d8a944815ccc154a1e028d1` after unauthorized squash +> of leftover-map coordinates (v2.24.0 / #782). Revert #808 +> (`revert-pr782-unauthorized` @ `1af3e53e`) restores `main` toward +> `fc13acaa` (v2.23.0) and still needs independent APPROVE. GitHub +> writes work (comment/close/create-PR/push). Token still has empty +> `X-OAuth-Scopes`; repo permission is ADMIN. Open leftover stack +> still lacks independent APPROVE. Do not self-approve. +> #825 leftover-map incomplete item coverage on the grouping comparison +> strip (v2.49.0 / ADR 0292) is `bca6baa`. #828 leftover-map axis share +> on the grouping comparison strip (v2.50.0 / ADR 0293) is `e791376`. +> Leave #782/#802/#803/#804/#805/#806/#808/#809/#810/#811/#812/#813/#814/#815/#816/#817/#818/#819/#821/#822/#823/#824/#825/#828 open for +> independent review. Do not squash-merge stacked leftover PRs onto an +> unprotected leftover base. Do not merge #808 without independent APPROVE. +> Copilot review is not independent APPROVE. Issues #79 and #87 stay open. +> #96 is already closed. Only collaborator is `seonghobae`. +> +> Next buyer increment on this cycle: leftover-map singular values on the +> grouping comparison strip (ADR 0294 / v2.51.0) on +> `feat/leftover-map-compare-axis-singular-v2510`. Caption persisted +> leftover_singular_value already on GET /api/reports/compare/{period} +> through leftoverMapCompareAxisSingular with distinct aria-label +> `Leftover map comparison axis singular` and copy +> `leftover map comparison axis {axis} σ {value}`. UI-only; no new columns. +> Missing, non-finite, or negative leftover-map singular value omits that +> badge independently of leftover-map comparison axis share. Rank-0 `0` +> is shown when persisted. Do not invent leftover-map singular value from +> leftover-map axis share. Do not add the leftover-map graphic. Stack onto +> leftover branch `feat/leftover-map-compare-axis-share-v2500` / #828; +> leave the PR open for independent review. Do not squash-merge onto the +> leftover base. Do not invent leftover scores. +> > Exact-head loop overlay: 2026-08-30 23:45 KST. Protected `main` is > `cb187cadee5fb6c46d8a944815ccc154a1e028d1` after unauthorized squash > of leftover-map coordinates (v2.24.0 / #782). Revert #808 diff --git a/docs/storybook-inventory.md b/docs/storybook-inventory.md index 6852fca40..5141ecec1 100644 --- a/docs/storybook-inventory.md +++ b/docs/storybook-inventory.md @@ -6,7 +6,7 @@ operator-facing control you can click before changing product CSS. | Story | Operator next action | Token / module | |---|---|---| | `Reports/LeftoverMapPlot` | Read the leftover-map graphic display of persisted `ξ` (posts) and `ζ` (criteria), match axis ticks to those coordinates, pair-segment `d` to leftover-map distance, pair-segment `R̂` to leftover-map reconstruction, pair-segment `R̂²/R²` to leftover-map explained leftover share, pair-segment `U²/R²` to leftover-map unexplained leftover share, pair-segment `2R̂U/R²` to leftover-map cross share, pair-segment `U` to leftover-map unexplained leftover, pair-segment `R` to leftover residual, pair-segment `Y` to leftover observed, pair-segment `E` to leftover expected, and pair-segment leftover-map rank, then click a post marker to open that post. Leftover-map axes name persisted leftover-map axis share when finite. The plot names leftover-map complete-case coverage, leftover-map item complete-case coverage, leftover-map incomplete post coverage, and leftover-map incomplete item coverage when persisted. `ClosestAndFarthest`, `RankZeroOrigin`, `MissingCoordinates`, and `MissingAxisShare` cover two-pair maps, rank-0 origin with 0% share, a `0` tick, `d 0.00`, `R̂ 0.00`, `R̂²/R² 0.00`, `U²/R² 0.00`, `2R̂U/R² 0.00`, `U 0.00`, `R 0.00`, `Y 0.00`, `E 0.00`, and `rank 0`, omitted plots, and missing share that keeps existing leftover-map axis text. The plot does not invent a leftover score. | `LeftoverMapPlot`, `leftoverMapPlotLayout`, `leftoverMapPlotAxisShare`, `--color-primary`, `--color-palette-blue-mid` | -| `Reports/LeftoverPairList` | Read closest/farthest leftover pairs with named `R`, `Y`/`E`, rank, `U`, `s`, `e`, `x`, `R̂`, `ξ`/`ζ`, and `d`, then open that post. The leftover-map graphic display sits above the pair buttons when coordinates are finite, leftover-map axes name persisted leftover-map axis share, leftover-map axis ticks name persisted coordinates, pair segments name persisted leftover-map distance, pair segments name persisted leftover-map reconstruction, pair segments name persisted leftover-map explained leftover share, pair segments name persisted leftover-map unexplained leftover share, pair segments name persisted leftover-map cross share, pair segments name persisted leftover-map unexplained leftover, pair segments name persisted leftover residual, pair segments name persisted leftover observed, pair segments name persisted leftover expected, and pair segments name persisted leftover-map rank. The pair-list note names leftover-map complete-case coverage only when leftoverMapCoverageCounts returns usable complete-case integers, leftover-map item complete-case coverage, leftover-map incomplete post coverage, and leftover-map incomplete item coverage when persisted. The grouping comparison strip names leftover-map complete-case coverage, leftover-map item complete-case coverage, leftover-map incomplete post coverage, leftover-map incomplete item coverage, and leftover-map axis share with distinct comparison labels when leftoverMapCoverageCounts / leftoverMapItemCoverageCounts / leftoverMapIncompletePostCount / leftoverMapIncompleteItemCount / leftoverMapCompareAxisShare return usable values. | `LeftoverPairList`, `LeftoverMapPlot`, `ticket-list`, `post-badge` | +| `Reports/LeftoverPairList` | Read closest/farthest leftover pairs with named `R`, `Y`/`E`, rank, `U`, `s`, `e`, `x`, `R̂`, `ξ`/`ζ`, and `d`, then open that post. The leftover-map graphic display sits above the pair buttons when coordinates are finite, leftover-map axes name persisted leftover-map axis share, leftover-map axis ticks name persisted coordinates, pair segments name persisted leftover-map distance, pair segments name persisted leftover-map reconstruction, pair segments name persisted leftover-map explained leftover share, pair segments name persisted leftover-map unexplained leftover share, pair segments name persisted leftover-map cross share, pair segments name persisted leftover-map unexplained leftover, pair segments name persisted leftover residual, pair segments name persisted leftover observed, pair segments name persisted leftover expected, and pair segments name persisted leftover-map rank. The pair-list note names leftover-map complete-case coverage only when leftoverMapCoverageCounts returns usable complete-case integers, leftover-map item complete-case coverage, leftover-map incomplete post coverage, and leftover-map incomplete item coverage when persisted. The grouping comparison strip names leftover-map complete-case coverage, leftover-map item complete-case coverage, leftover-map incomplete post coverage, leftover-map incomplete item coverage, leftover-map axis share, and leftover-map singular values with distinct comparison labels when leftoverMapCoverageCounts / leftoverMapItemCoverageCounts / leftoverMapIncompletePostCount / leftoverMapIncompleteItemCount / leftoverMapCompareAxisShare / leftoverMapCompareAxisSingular return usable values. | `LeftoverPairList`, `LeftoverMapPlot`, `ticket-list`, `post-badge` | | `Workspace/OperationsDashboard` | Compare Event and post counts, inspect external-information coverage, then open the cited source behind a claim, handover, or repeat-issue fact. `EvidenceReady`, `NarrowViewport`, `AnalysisPendingAndMissingEvidence`, `AnalysisFailed`, and `LoadError` cover populated, mobile, unavailable-evidence, analysis-pending, retryable failure, and transport-error states. | `--color-dashboard-*`, `OperationsDashboard` | | `Post/SimilarVocPanel` | Compare ontology/semantic similar VOC and prior action evidence, then open the source; unavailable states show no fabricated TEPP theta or weight. | `SimilarVocPanel.css`, `SimilarVocPanel` | | `Post/Recorded perspectives` | Read the imported primary and every evidence-connected additional Voice with its recorded truth state instead of flattening them into one compound category. `CombinedEvidence`, `RejectedEvidence`, and `NarrowViewport` cover desktop, rejected-evidence, and narrow layouts. | `VoicePerspectiveList`, `ticket-list`, `post-meta` | diff --git a/frontend/package.json b/frontend/package.json index 497940a94..2238b2b96 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "frontend", "private": true, - "version": "2.50.0", + "version": "2.51.0", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/src/App.test.tsx b/frontend/src/App.test.tsx index 129526d0f..a5e7bd6c3 100644 --- a/frontend/src/App.test.tsx +++ b/frontend/src/App.test.tsx @@ -4357,7 +4357,30 @@ describe("App, authenticated", () => { within(screen.getByLabelText("Grouping comparison")).queryByText(/leftover-map axis 1/), ).not.toBeInTheDocument(); expect( - within(screen.getByLabelText("Grouping comparison")).queryByText(/σ 1\.84/), + within(screen.getByLabelText("Grouping comparison")).getAllByLabelText( + "Leftover map comparison axis singular", + ), + ).toHaveLength(4); + expect( + within(screen.getByLabelText("Grouping comparison")).getAllByLabelText( + "Leftover map comparison axis singular", + )[0], + ).toHaveTextContent("leftover map comparison axis 1 σ 0.00"); + expect( + within(screen.getByLabelText("Grouping comparison")).getByText( + "leftover map comparison axis 1 σ 1.84", + ), + ).toBeInTheDocument(); + expect( + within(screen.getByLabelText("Grouping comparison")).getByText( + "leftover map comparison axis 2 σ 0.86", + ), + ).toBeInTheDocument(); + expect( + within(screen.getByLabelText("Grouping comparison")).queryByText("leftover axis 1 σ 1.84 82%"), + ).not.toBeInTheDocument(); + expect( + within(screen.getByLabelText("Grouping comparison")).queryByText("leftover-map axis 1 σ 1.84"), ).not.toBeInTheDocument(); expect( screen.getByRole("button", { name: "Compare Business unit (PU): Demo Report High, mean θ 0.81" }), diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 7d77c77eb..3db20507f 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,7 +1,7 @@ import { focusedGraphMustReset } from "./focusedGraphSelection"; import { canAuthorVoice, postPrimaryVoiceLabel } from "./voicePerspective"; -import { Component, lazy, Suspense, useCallback, useEffect, useEffectEvent, useRef, useState, type ReactNode } from "react"; +import { Component, Fragment, lazy, Suspense, useCallback, useEffect, useEffectEvent, useRef, useState, type ReactNode } from "react"; import { useAuth } from "react-oidc-context"; import { askPostChat, @@ -139,8 +139,11 @@ import { } from "./leftoverMapCoverage"; import { leftoverMapCompareAxisShare, + leftoverMapCompareAxisSingular, LEFTOVER_MAP_COMPARE_AXIS_SHARE, LEFTOVER_MAP_COMPARE_AXIS_SHARE_LABEL, + LEFTOVER_MAP_COMPARE_AXIS_SINGULAR, + LEFTOVER_MAP_COMPARE_AXIS_SINGULAR_LABEL, } from "./leftoverMapCompareAxis"; import "./App.css"; @@ -4056,17 +4059,29 @@ function ReportsPanel({ ) : null} {row.leftover_map_axes?.map((axis) => { const comparisonAxisShare = leftoverMapCompareAxisShare(axis); - if (comparisonAxisShare === null) { + const comparisonAxisSingular = leftoverMapCompareAxisSingular(axis); + if (comparisonAxisShare === null && comparisonAxisSingular === null) { return null; } return ( - - {tf(LEFTOVER_MAP_COMPARE_AXIS_SHARE, comparisonAxisShare)} - + + {comparisonAxisShare !== null ? ( + + {tf(LEFTOVER_MAP_COMPARE_AXIS_SHARE, comparisonAxisShare)} + + ) : null} + {comparisonAxisSingular !== null ? ( + + {tf(LEFTOVER_MAP_COMPARE_AXIS_SINGULAR, comparisonAxisSingular)} + + ) : null} + ); })} {row.leftover_pairs && row.leftover_pairs.length > 0 && ( diff --git a/frontend/src/components/LeftoverPairList.tsx b/frontend/src/components/LeftoverPairList.tsx index fed808ca9..5f0c4a23d 100644 --- a/frontend/src/components/LeftoverPairList.tsx +++ b/frontend/src/components/LeftoverPairList.tsx @@ -89,7 +89,8 @@ export type LeftoverPairListProps = { * grouping comparison strip, not this pair list. ADR 0292 names persisted leftover-map * incomplete item coverage on the grouping comparison strip, not this pair list. ADR 0293 * names persisted leftover-map axis share on the grouping comparison strip, not this pair - * list. Every badge still + * list. ADR 0294 names persisted leftover-map singular values on the grouping comparison + * strip, not this pair list. Every badge still * renders together before opening the named post. */ export function LeftoverPairList({ diff --git a/frontend/src/i18n.test.ts b/frontend/src/i18n.test.ts index c63d1b5b2..62e6e9fcc 100644 --- a/frontend/src/i18n.test.ts +++ b/frontend/src/i18n.test.ts @@ -44,6 +44,7 @@ describe("i18n", () => { "Answer", "leftover axis {axis} {share}%", "leftover map comparison axis {axis} {share}%", + "leftover map comparison axis {axis} σ {value}", "Leftover-map axis share", "Leftover-map axis share is Gabriel inertia of residual SVD axes 1 and 2. Open a leftover pair to read the post–criterion cell. The shares do not invent a leftover score.", "Leftover pairs", @@ -83,6 +84,7 @@ describe("i18n", () => { "Leftover map comparison incomplete posts", "Leftover map comparison incomplete items", "Leftover map comparison axis share", + "Leftover map comparison axis singular", "Leftover-map graphic item coverage", "Leftover map item coverage", "Leftover map incomplete posts", diff --git a/frontend/src/i18n.ts b/frontend/src/i18n.ts index 3f186c2c2..dfa41d366 100644 --- a/frontend/src/i18n.ts +++ b/frontend/src/i18n.ts @@ -274,6 +274,8 @@ const TRANSLATIONS: Partial>> = { "Leftover map comparison incomplete items": "잔여 지도 비교 불완전 기준", "Leftover map comparison axis share": "잔여 지도 비교 축 비율", "leftover map comparison axis {axis} {share}%": "잔여 지도 비교 축 {axis} {share}%", + "Leftover map comparison axis singular": "잔여 지도 비교 축 특이값", + "leftover map comparison axis {axis} σ {value}": "잔여 지도 비교 축 {axis} σ {value}", "Leftover map item coverage": "잔여 지도 기준 포함 범위", "Leftover map incomplete posts": "잔여 지도 불완전 글", "Leftover map incomplete items": "잔여 지도 불완전 기준", @@ -886,6 +888,8 @@ const TRANSLATIONS: Partial>> = { "Leftover map comparison incomplete items": "残差地图比较不完整准则", "Leftover map comparison axis share": "残差地图比较轴占比", "leftover map comparison axis {axis} {share}%": "残差地图比较轴 {axis} {share}%", + "Leftover map comparison axis singular": "残差地图比较轴奇异值", + "leftover map comparison axis {axis} σ {value}": "残差地图比较轴 {axis} σ {value}", "Leftover map item coverage": "残差地图准则覆盖范围", "Leftover map incomplete posts": "残差地图不完整帖文", "Leftover map incomplete items": "残差地图不完整准则", @@ -1519,6 +1523,8 @@ const TRANSLATIONS: Partial>> = { "Leftover map comparison incomplete items": "残差マップの比較不完全基準", "Leftover map comparison axis share": "残差マップの比較軸の比率", "leftover map comparison axis {axis} {share}%": "残差マップの比較軸 {axis} {share}%", + "Leftover map comparison axis singular": "残差マップの比較軸の特異値", + "leftover map comparison axis {axis} σ {value}": "残差マップの比較軸 {axis} σ {value}", "Leftover map item coverage": "残差マップの基準対象範囲", "Leftover map incomplete posts": "残差マップの不完全投稿", "Leftover map incomplete items": "残差マップの不完全基準", @@ -2131,6 +2137,8 @@ const TRANSLATIONS: Partial>> = { "Leftover map comparison incomplete items": "Tiêu chí không đầy đủ so sánh trên bản đồ phần dư", "Leftover map comparison axis share": "Tỷ trọng trục so sánh bản đồ phần dư", "leftover map comparison axis {axis} {share}%": "trục so sánh bản đồ phần dư {axis} {share}%", + "Leftover map comparison axis singular": "Giá trị singular trục so sánh bản đồ phần dư", + "leftover map comparison axis {axis} σ {value}": "trục so sánh bản đồ phần dư {axis} σ {value}", "Leftover map item coverage": "Phạm vi tiêu chí bản đồ phần dư", "Leftover map incomplete posts": "Bài không đầy đủ trên bản đồ phần dư", "Leftover map incomplete items": "Tiêu chí không đầy đủ trên bản đồ phần dư", diff --git a/frontend/src/leftoverMapCompareAxis.test.ts b/frontend/src/leftoverMapCompareAxis.test.ts index 1a9ac333d..858438d69 100644 --- a/frontend/src/leftoverMapCompareAxis.test.ts +++ b/frontend/src/leftoverMapCompareAxis.test.ts @@ -1,10 +1,15 @@ import { describe, expect, it } from "vitest"; import { leftoverMapCompareAxisShare, + leftoverMapCompareAxisSingular, LEFTOVER_MAP_COMPARE_AXIS_SHARE, LEFTOVER_MAP_COMPARE_AXIS_SHARE_LABEL, + LEFTOVER_MAP_COMPARE_AXIS_SINGULAR, + LEFTOVER_MAP_COMPARE_AXIS_SINGULAR_LABEL, LEFTOVER_MAP_LIST_AXIS_SHARE, + LEFTOVER_MAP_LIST_AXIS_SINGULAR, LEFTOVER_MAP_PLOT_AXIS_SHARE, + LEFTOVER_MAP_PLOT_AXIS_SINGULAR, } from "./leftoverMapCompareAxis"; describe("leftoverMapCompareAxisShare", () => { @@ -63,3 +68,64 @@ describe("leftoverMapCompareAxisShare", () => { expect(LEFTOVER_MAP_COMPARE_AXIS_SHARE).not.toBe(LEFTOVER_MAP_PLOT_AXIS_SHARE); }); }); + +describe("leftoverMapCompareAxisSingular", () => { + it("names persisted leftover-map singular values without inventing a leftover score", () => { + expect( + leftoverMapCompareAxisSingular({ axis_index: 1, leftover_singular_value: 1.84 }), + ).toEqual({ axis: 1, value: "1.84" }); + expect( + leftoverMapCompareAxisSingular({ axis_index: 2, leftover_singular_value: 0.86 }), + ).toEqual({ axis: 2, value: "0.86" }); + }); + + it("names a rank-0 zero leftover-map singular value", () => { + expect( + leftoverMapCompareAxisSingular({ axis_index: 1, leftover_singular_value: 0 }), + ).toEqual({ axis: 1, value: "0.00" }); + }); + + it("omits leftover-map singular values that are missing, non-finite, or negative", () => { + expect(leftoverMapCompareAxisSingular(null)).toBeNull(); + expect(leftoverMapCompareAxisSingular(undefined)).toBeNull(); + expect(leftoverMapCompareAxisSingular({ axis_index: 1 })).toBeNull(); + expect( + leftoverMapCompareAxisSingular({ axis_index: 1, leftover_singular_value: Number.NaN }), + ).toBeNull(); + expect( + leftoverMapCompareAxisSingular({ + axis_index: 1, + leftover_singular_value: Number.POSITIVE_INFINITY, + }), + ).toBeNull(); + expect( + leftoverMapCompareAxisSingular({ axis_index: 1, leftover_singular_value: -0.01 }), + ).toBeNull(); + }); + + it("does not invent leftover-map singular value from leftover-map axis share", () => { + expect( + leftoverMapCompareAxisSingular({ + axis_index: 1, + leftover_singular_value: Number.NaN, + }), + ).toBeNull(); + expect( + leftoverMapCompareAxisSingular({ axis_index: 1, leftover_singular_value: 1.84 }), + ).not.toEqual({ axis: 1, value: "82" }); + }); + + it("keeps the grouping comparison leftover-map singular caption distinct from leftover-axis badges and graphic axes", () => { + expect(LEFTOVER_MAP_COMPARE_AXIS_SINGULAR_LABEL).toBe( + "Leftover map comparison axis singular", + ); + expect(LEFTOVER_MAP_COMPARE_AXIS_SINGULAR_LABEL).not.toBe( + LEFTOVER_MAP_COMPARE_AXIS_SHARE_LABEL, + ); + expect(LEFTOVER_MAP_COMPARE_AXIS_SINGULAR).toBe( + "leftover map comparison axis {axis} σ {value}", + ); + expect(LEFTOVER_MAP_COMPARE_AXIS_SINGULAR).not.toBe(LEFTOVER_MAP_LIST_AXIS_SINGULAR); + expect(LEFTOVER_MAP_COMPARE_AXIS_SINGULAR).not.toBe(LEFTOVER_MAP_PLOT_AXIS_SINGULAR); + }); +}); diff --git a/frontend/src/leftoverMapCompareAxis.ts b/frontend/src/leftoverMapCompareAxis.ts index 0ce1c330e..f7d574c90 100644 --- a/frontend/src/leftoverMapCompareAxis.ts +++ b/frontend/src/leftoverMapCompareAxis.ts @@ -1,4 +1,4 @@ -/** Caption leftover-map axis share on the grouping comparison strip (ADR 0293). */ +/** Caption leftover-map axis share and singular values on the grouping comparison strip (ADR 0293 / ADR 0294). */ import type { LeftoverMapAxis } from "./api"; @@ -10,11 +10,24 @@ export const LEFTOVER_MAP_LIST_AXIS_SHARE = "leftover axis {axis} {share}%"; export const LEFTOVER_MAP_PLOT_AXIS_SHARE = "leftover-map axis {axis} ({share}%)"; +export const LEFTOVER_MAP_COMPARE_AXIS_SINGULAR_LABEL = "Leftover map comparison axis singular"; + +export const LEFTOVER_MAP_COMPARE_AXIS_SINGULAR = "leftover map comparison axis {axis} σ {value}"; + +export const LEFTOVER_MAP_LIST_AXIS_SINGULAR = "leftover axis {axis} σ {value} {share}%"; + +export const LEFTOVER_MAP_PLOT_AXIS_SINGULAR = "leftover-map axis {axis} σ {value}"; + export type LeftoverMapCompareAxisShare = { axis: number; share: string; }; +export type LeftoverMapCompareAxisSingular = { + axis: number; + value: string; +}; + export function leftoverMapCompareAxisShare( axis: Pick | null | undefined, ): LeftoverMapCompareAxisShare | null { @@ -32,3 +45,25 @@ export function leftoverMapCompareAxisShare( share: (axis.leftover_share * 100).toFixed(0), }; } + +export function leftoverMapCompareAxisSingular( + axis: Pick | null | undefined, +): LeftoverMapCompareAxisSingular | null { + if (axis == null) { + return null; + } + if (!Number.isInteger(axis.axis_index) || axis.axis_index < 1) { + return null; + } + if ( + axis.leftover_singular_value == null || + !Number.isFinite(axis.leftover_singular_value) || + axis.leftover_singular_value < 0 + ) { + return null; + } + return { + axis: axis.axis_index, + value: axis.leftover_singular_value.toFixed(2), + }; +} diff --git a/frontend/src/leftoverMapPlotLayout.ts b/frontend/src/leftoverMapPlotLayout.ts index 082764847..4da4f0cb5 100644 --- a/frontend/src/leftoverMapPlotLayout.ts +++ b/frontend/src/leftoverMapPlotLayout.ts @@ -20,8 +20,9 @@ * (ADR 0289), grouping comparison item complete-case coverage * (ADR 0290), grouping comparison incomplete post coverage * (ADR 0291), grouping comparison incomplete item coverage - * (ADR 0292), and grouping comparison leftover-map axis share - * (ADR 0293) caption the pair list or the grouping comparison strip, + * (ADR 0292), grouping comparison leftover-map axis share + * (ADR 0293), and grouping comparison leftover-map singular values + * (ADR 0294) caption the pair list or the grouping comparison strip, * not this graphic layout. */ diff --git a/pyproject.toml b/pyproject.toml index 1ed881f7d..33c2ed641 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "lineageweave" -version = "2.50.0" +version = "2.51.0" description = "Reconstructs git-branch-style lineage DAGs from scattered short records using multi-channel score fusion and LLM adjudication." readme = "README.md" license = { text = "MIT" } From ed7beafb0c9ba961aafc13571b413514d8b6a567 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 7 Sep 2026 19:59:44 +0900 Subject: [PATCH 2/4] chore(reports): sanitize historical #830 delta for current-parent reconstruction --- AGENTS.md | 91 +- ARCHITECTURE.md | 37 +- CHANGELOG.md | 254 +----- CLAUDE.md | 10 +- docs/product-technical-gap-baseline.md | 829 ++----------------- docs/storybook-inventory.md | 4 +- frontend/package.json | 2 +- frontend/src/components/LeftoverPairList.tsx | 16 +- frontend/src/i18n.test.ts | 50 +- frontend/src/i18n.ts | 52 +- frontend/src/leftoverMapCompareAxis.ts | 9 +- frontend/src/leftoverMapPlotLayout.ts | 115 ++- pyproject.toml | 2 +- 13 files changed, 369 insertions(+), 1102 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 9dbe6db7d..92dbcc403 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -273,7 +273,7 @@ stops startup instead of leaving a healthy-looking partial schema, and application code must not compensate for a missing table. Period leftover pairs (ADR 0017 / 0018 / 0048 / 0049 / 0119 / 0158 / 0162 / -0163 / 0164 / 0182 / 0185 / 0201 / 0233 / 0266 / 0267 / 0268 / 0269 / 0270 / 0271 / 0272 / 0273 / 0274 / 0275 / 0276 / 0277 / 0278 / 0279 / 0280 / 0281 / 0282 / 0283 / 0284 / 0285 / 0286 / 0287 / 0288 / 0289 / 0290 / 0291 / 0292) are computed in `lineageweave/leftover_pairs.py` from the +0163 / 0164 / 0182 / 0185 / 0201 / 0233 / 0266 / 0267 / 0268 / 0269 / 0270 / 0271 / 0272 / 0273 / 0274 / 0275 / 0276 / 0277 / 0278 / 0279 / 0280 / 0281 / 0282 / 0283 / 0284 / 0285 / 0286 / 0287 / 0288 / 0289 / 0290 / 0291 / 0292 / 0293) are computed in `lineageweave/leftover_pairs.py` from the residual after a real GRM/GPCM score, never invented. Distances are Euclidean on the two-dimensional Gabriel leftover map; missing cells stay out of the factorization. Closest and farthest post–criterion pairs @@ -294,7 +294,12 @@ buttons; omit the plot when coordinates are missing; click a post marker to open that post. ADR 0269 captions those leftover-map axes with persisted leftover-map axis share `σ_k² / Σ_j σ_j²` when finite, including rank-0 zero-share axes; a missing or non-finite share omits -that axis badge and keeps the existing leftover-map axis text. ADR 0270 +that axis badge and keeps the existing leftover-map axis text. ADR 0289 +captions those leftover-map axes with persisted leftover-map singular +values `σ_k` when finite and non-negative, including rank-0 zero +singular values; a missing, non-finite, or negative singular value omits +that `σ` badge independently of leftover-map axis share and does not +invent `σ_k` from leftover-map axis share. ADR 0270 ticks leftover-map axes at the origin and at each unique finite persisted `ξ` / `ζ` coordinate so the pair-row badge matches the plot; rank-0 unused axes name only `0` and do not invent drawing-scale @@ -385,53 +390,15 @@ non-integer payload cannot caption a contradictory `used N of M scored posts` note; a missing, non-integer, negative-used, non-positive-scored, or used-greater-than-scored coverage omits that leftover-map coverage note and does not invent post coverage from plotted marker count. -ADR 0289 captions the grouping comparison strip with persisted leftover-map -post complete-case coverage through leftoverMapCoverageCounts so a buyer who -compares leftover pairs can read how many scored posts entered each grouping's -Gabriel factorization; a missing, non-integer, negative-used, non-positive-scored, -or used-greater-than-scored coverage omits that leftover-map comparison coverage -note and does not invent post coverage from leftover pair count or plotted -marker count. The strip does not gain leftover-map incomplete post coverage, -leftover-map incomplete item coverage, or the leftover-map graphic. -ADR 0290 captions the grouping comparison strip with persisted leftover-map -item complete-case coverage through leftoverMapItemCoverageCounts so a buyer who -compares leftover pairs can read how many scored criteria entered each grouping's -Gabriel factorization; a missing, non-integer, negative-used, non-positive-scored, -or used-greater-than-scored item coverage omits that leftover-map comparison item -coverage note and does not invent item coverage from leftover pair count or plotted -criterion marker count. -ADR 0291 captions the grouping comparison strip with persisted leftover-map -incomplete post coverage through leftoverMapIncompletePostCount so a buyer who -compares leftover pairs can read how many scored posts stayed out of each grouping's -Gabriel factorization; a missing, non-integer, or negative dropped count, or a -dropped count that contradicts usable complete-case integers, omits that leftover-map -comparison incomplete post note and does not invent dropped posts from scored minus -used or from leftover pair count. Dropped `0` is shown when persisted. The strip -does not gain leftover-map incomplete item coverage or the leftover-map graphic. -ADR 0292 captions the grouping comparison strip with persisted leftover-map -incomplete item coverage through leftoverMapIncompleteItemCount so a buyer who -compares leftover pairs can read how many scored criteria stayed out of each grouping's -Gabriel factorization; a missing, non-integer, or negative dropped count, or a -dropped count that contradicts usable item complete-case integers, omits that leftover-map -comparison incomplete item note and does not invent dropped criteria from scored minus -used or from leftover pair count. Dropped `0` is shown when persisted. The strip -does not gain the leftover-map graphic. -ADR 0293 captions the grouping comparison strip with persisted leftover-map -axis share through leftoverMapCompareAxisShare so a buyer who compares leftover -pairs can read Gabriel inertia of residual SVD axes 1 and 2 for that grouping; -a missing or non-finite share omits that leftover-map comparison axis share -badge and does not invent leftover-map axis share from leftover-map singular -value, leftover pair count, or plotted marker count. Share `0` is shown when -persisted, including rank-0 unused axes. ADR 0293 does not caption leftover-map -singular values or the leftover-map graphic. -ADR 0294 captions the grouping comparison strip with persisted leftover-map -singular values through leftoverMapCompareAxisSingular so a buyer who compares leftover -pairs can read the Gabriel scale of residual SVD axes 1 and 2 for that grouping; -a missing, non-finite, or negative leftover-map singular value omits that leftover-map -comparison axis singular badge independently of leftover-map comparison axis share -and does not invent leftover-map singular value from leftover-map axis share, leftover -pair count, or plotted marker count. Rank-0 leftover-map singular value `0` is shown -when persisted. The strip does not gain the leftover-map graphic. +ADR 0289 captions leftover-map graphic axes with persisted leftover-map +singular values `σ_k` so leftover-map axis share is not read as leftover-map +structure without the Gabriel scale that produced it; a missing, non-finite, +or negative singular value omits that `σ` badge independently of leftover-map +axis share and does not invent `σ_k` from leftover-map axis share. +ADR 0292 captions leftover-axis report badges with persisted leftover-map singular values `σ_k` when finite and non-negative, including rank-0 zero singular values; missing, non-finite, or negative singular values omit only the `σ` caption and never derive `σ_k` from leftover-map axis share. +ADR 0290 captions the grouping comparison strip with persisted leftover-map post complete-case coverage only when the caller can see the full persisted grouping population. Partial-visibility groupings omit that aggregate; never reconstruct the psychometric denominator from visible members, leftover pairs, or plotted markers. +ADR 0291 captions the grouping comparison strip with persisted leftover-map item complete-case coverage through leftoverMapItemCoverageCounts only when the caller can see the full persisted grouping population. Partial-visibility rows inherit ADR 0290's fail-closed coverage boundary and never recompute psychometric coverage from visible members, leftover pairs, or plotted criterion markers. +ADR 0293 captions the grouping comparison strip with persisted leftover-map incomplete-post count only under the same full-visible-grouping authorization boundary. Partial-visibility groupings omit the aggregate and never derive dropped posts from the visible subset or scored-minus-used. Persisted valid dropped `0` remains visible. When `R`, `R̂`, `U`, `x`, `s`, and `e` are finite, `e + s + x = 1`. When `Y`, `E`, and `R` are finite, `Y − E = R`. When `R`, `R̂`, and `U` are @@ -442,22 +409,12 @@ list so a click opens that post with the leftover criterion current in Post quality (ADR 0158). Leftover-map axis share (ADR 0148) is Gabriel inertia of residual SVD axes 1 and 2 and persists to `report_leftover_map_axis`. Rank-0 residuals emit two zero-share axes; the shares are report-level -and are not a leftover score. Complete-case coverage (ADR 0168) persists to +and are not a leftover score. Leftover-map singular values on the graphic +display (ADR 0289) name persisted `σ_k` on those leftover-map axes when +finite. Complete-case coverage (ADR 0168) persists to `report_leftover_map_coverage` and captions the pair list and the leftover-map graphic with how many scored posts entered the map. Pair-list post complete-case coverage (ADR 0288) fail-closes that pair-list note through leftoverMapCoverageCounts. -Grouping comparison complete-case coverage (ADR 0289) captions the grouping -comparison strip with how many scored posts entered each grouping's map. -Grouping comparison item complete-case coverage (ADR 0290) captions the grouping -comparison strip with how many scored criteria entered each grouping's map. -Grouping comparison incomplete post coverage (ADR 0291) captions the grouping -comparison strip with how many scored posts stayed out of each grouping's map. -Grouping comparison incomplete item coverage (ADR 0292) captions the grouping -comparison strip with how many scored criteria stayed out of each grouping's map. -Grouping comparison leftover-map axis share (ADR 0293) captions the grouping -comparison strip with Gabriel inertia of residual SVD axes. -Grouping comparison leftover-map singular values (ADR 0294) captions the grouping -comparison strip with the Gabriel scale of those axes. Item complete-case coverage (ADR 0282) captions the leftover-map graphic with how many scored criteria entered the map. Item complete-case coverage on the pair list (ADR 0285) @@ -579,3 +536,13 @@ columns). Do not silently rewrite either historical form. The SHACL shapes graph (`docs/ontology/lineageweave-kg-shapes.ttl`) is the closed-world data-validation boundary for DB-to-RDF projections and is published beside the ontology. + +ADR 0294 keeps grouping-comparison incomplete-item coverage in the LineageWeave read-model boundary: consume only authorization-filtered persisted coverage for a full grouping, omit partial visibility, and never recompute psychometrics in the client. + +ADR 0295 keeps grouping-comparison reconstruction in the LineageWeave read-model/UI boundary: format only persisted `R̂`, expose the value in the pair button accessible name, and never derive psychometric reconstruction from UI-visible proxies. + +ADR 0296 adds persisted grouping-comparison explained-leftover share `e` in the LineageWeave read-model/UI boundary: expose it in the pair button accessible name, keep the duplicate visible badge presentation-only, and never derive or clamp psychometric values. + +ADR 0367 exposes persisted grouping-comparison leftover-map axis share only for a fully caller-visible persisted grouping. Partial visibility returns no axis aggregate; never recompute it from visible members. Missing/non-finite share omits only the badge; persisted zero and finite negative values remain explicit. + +ADR 0369 adds persisted grouping-comparison `U²/R²` only as a presentation/read-model consumer on exact #828. Never derive or clamp it, never recompute it from a visible subset, and include every finite buyer-visible comparison metric in the actionable pair button accessible name. diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 35f815e56..1e9cbde0d 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -637,14 +637,15 @@ information at the group's mean θ (Lord, 1980 max-info CAT). Rankings persist to `report_item_information`. After those IRT main effects, residual SVD leftover pairs on two Gabriel axes (Jeon et al., 2021; ADR 0017 / 0048 / 0049 / 0119 / 0148 / 0158 / 0162 / 0163 / 0164 / 0168 / -0182 / 0185 / 0201 / 0233 / 0266 / 0267 / 0268 / 0269 / 0270 / 0271 / 0272 / 0273 / 0274 / 0275 / 0276 / 0277 / 0278 / 0279 / 0280 / 0281 / 0282 / 0283 / 0284 / 0285 / 0286 / 0287 / 0288 / 0289 / 0290) persist to `report_leftover_pair` with signed residual `R`, +0182 / 0185 / 0201 / 0233 / 0266 / 0267 / 0268 / 0269 / 0270 / 0271 / 0272 / 0273 / 0274 / 0275 / 0276 / 0277 / 0278 / 0279 / 0280 / 0281 / 0282 / 0283 / 0284 / 0285 / 0286 / 0287 / 0288 / 0289 / 0290 / 0291 / 0292 / 0293) persist to `report_leftover_pair` with signed residual `R`, observed `Y`, expected `E[Y|θ, item]`, full leftover-map rank, unexplained leftover, ADR 0201 reconstruction evidence, ADR 0185 cross-share evidence, ADR 0233 unexplained leftover share `s`, ADR 0266 explained leftover share `e`, and ADR 0267 leftover-map coordinates `ξ_{1:2}` / `ζ_{1:2}`. ADR 0268 draws those persisted coordinates as the leftover-map graphic display above the pair buttons. ADR 0269 captions leftover-map axes 1 -and 2 with persisted leftover-map axis share. ADR 0270 ticks those +and 2 with persisted leftover-map axis share. ADR 0289 captions leftover-map +axes 1 and 2 with persisted leftover-map singular values `σ_k`. ADR 0270 ticks those leftover-map axes at persisted `ξ` / `ζ` coordinates so the pair-row badge matches the plot. ADR 0271 captions leftover-map pair segments with persisted leftover-map distance `d`. ADR 0272 captions leftover-map @@ -667,18 +668,11 @@ item coverage. ADR 0285 captions the leftover pair list with persisted leftover- item complete-case coverage. ADR 0286 captions the leftover pair list with persisted leftover-map incomplete post coverage. ADR 0287 captions the leftover pair list with persisted leftover-map incomplete item coverage. ADR 0288 fail-closes leftover-map post complete-case coverage -on the leftover pair list through leftoverMapCoverageCounts. ADR 0289 captions the -grouping comparison strip with persisted leftover-map post complete-case coverage -through leftoverMapCoverageCounts. ADR 0290 captions the grouping comparison strip -with persisted leftover-map item complete-case coverage through leftoverMapItemCoverageCounts. -ADR 0291 captions the grouping comparison strip with persisted leftover-map incomplete -post coverage through leftoverMapIncompletePostCount. -ADR 0292 captions the grouping comparison strip with persisted leftover-map incomplete -item coverage through leftoverMapIncompleteItemCount. -ADR 0293 captions the grouping comparison strip with persisted leftover-map axis share -through leftoverMapCompareAxisShare. -ADR 0294 captions the grouping comparison strip with persisted leftover-map singular -values through leftoverMapCompareAxisSingular. +on the leftover pair list through leftoverMapCoverageCounts. ADR 0289 captions leftover-map +graphic axes with persisted leftover-map singular values `σ_k`. ADR 0290 captions the grouping comparison strip with persisted leftover-map post complete-case coverage under a full-visible-grouping rule; partial-visibility groupings fail closed that aggregate to avoid disclosing a hidden population denominator. +ADR 0291 captions grouping-comparison persisted item complete-case coverage through leftoverMapItemCoverageCounts only under ADR 0290's full-visible-grouping authorization boundary. +ADR 0292 captions leftover-axis report badges with persisted finite, non-negative leftover-map singular values `σ_k`; missing or invalid singular values omit only that caption, and axis share remains a distinct persisted measure. +ADR 0293 captions grouping-comparison persisted incomplete-post count only for a fully caller-visible persisted grouping; partial visibility omits the aggregate rather than disclosing or recomputing a hidden-population count. Click a post marker or a pair button opens that post. Those ADRs are the normative mathematical, storage, and display contracts. Leftover-map axis share @@ -696,10 +690,7 @@ including on the pair list. Results persist to `GET /api/reports/{grouping}` lists the trend; `GET /api/reports/{grouping}/{period}` is ABAC-filtered; `GET /api/reports/compare/{period}` is the home-page grouping strip -and carries the same ABAC-filtered leftover pairs (ADR 0149) plus persisted -leftover-map complete-case coverage (ADR 0289), leftover-map item complete-case -coverage (ADR 0290), leftover-map incomplete post coverage (ADR 0291), and leftover-map -incomplete item coverage (ADR 0292); +and carries the same ABAC-filtered leftover pairs (ADR 0149) plus persisted leftover-map post complete-case coverage (ADR 0290) and item complete-case coverage (ADR 0291) only when the caller-visible member population equals the persisted grouping population; `POST .../rebuild` scores every grouping kind (post_admin). `make seed` folds A-100/B-200 Event Lineage fixtures (and the Riverbend calendar post) that already have constructed IRT cells into the same shared @@ -1098,3 +1089,13 @@ so it also covers the multi-entity opposite-order case a per-name lock would still deadlock on. Every already-cataloged entity still resolves through the unchanged, lock-free similarity-matching fast path; only the rare creation branch serializes. + +ADR 0294 adds persisted incomplete-item coverage to grouping comparison presentation while the API remains the full-group visibility authority; the frontend formats only an admitted persisted count. + +ADR 0295 adds persisted `R̂` to grouping-comparison pair buttons. The explicit button accessible name carries the reconstruction label/value; the visible duplicate badge is presentation-only. Psychometric computation remains owned by fast-mlsirm. + +ADR 0296 adds persisted explained-leftover share `e = R̂²/R²` to grouping-comparison pair actions; the button accessible name is authoritative for assistive technology and fast-mlsirm remains psychometric owner. + +ADR 0367 adds persisted `leftover_map_axes` to the grouping-comparison read model under the same whole-population authorization rule as other psychometric aggregates. The UI consumes persisted `leftover_share` through `leftoverMapCompareAxisShare`; no subset recomputation or singular-value derivation is permitted. + +ADR 0369 composes persisted finite grouping-comparison `leftover_map_unexplained_share` into pair actions. The parent button accessible name and visual badge share one formatter result; the visual duplicate is `aria-hidden`. Authorization and psychometric ownership remain upstream/current-parent contracts. diff --git a/CHANGELOG.md b/CHANGELOG.md index 4cfd2e6ec..524e9a4c1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,227 +8,49 @@ All notable changes to this project are documented here. Format follows ### Added -- Period leftover pairs now caption the grouping comparison strip with - persisted leftover-map singular values through leftoverMapCompareAxisSingular - (ADR 0294 / v2.51.0). After `make seed`, closest and farthest leftover - pairs sit above the member list with the Gabriel biplot of already-named - coordinates, leftover-map axis share when finite, leftover-map singular - values when finite and nonnegative, axis ticks that match `ξ (x, y) ζ (x, y)` - on the pair row, pair segments that match `d` on the pair row, pair segments - that match `R̂` on the pair row, pair segments that match `R̂²/R²` on the pair - row, pair segments that match `U²/R²` on the pair row, pair segments that - match `2R̂U/R²` on the pair row, pair segments that match `U` on the pair row, - pair segments that match `R` on the pair row, pair segments that match `Y` on - the pair row, pair segments that match `E` on the pair row, pair segments that - match leftover-map rank on the pair row, a plot caption that matches leftover-map - complete-case coverage above the pair list, a plot caption that matches - leftover-map item complete-case coverage, a plot caption that matches - leftover-map incomplete post coverage, a plot caption that matches - leftover-map incomplete item coverage, a pair-list note that matches - leftover-map post complete-case coverage, a pair-list note that matches - leftover-map item complete-case coverage, a pair-list note that matches - leftover-map incomplete post coverage, a pair-list note that matches - leftover-map incomplete item coverage, a grouping comparison note that - matches leftover-map post complete-case coverage, a grouping comparison - note that matches leftover-map item complete-case coverage, a grouping - comparison note that matches leftover-map incomplete post coverage, a - grouping comparison note that matches leftover-map incomplete item - coverage, a grouping comparison leftover-map axis share badge that - matches leftover-axis report badges, and a grouping comparison leftover-map - singular-value badge; click a post marker or a pair button opens that post. - A missing, non-finite, or negative leftover-map singular value omits that - leftover-map comparison axis singular badge independently of leftover-map - comparison axis share. Rank-0 leftover-map singular value `0` is shown when - that persisted value is a finite nonnegative number. Do not invent leftover-map - singular value from leftover-map axis share, leftover pair count, plotted - marker count, leftover-map distance, leftover-map rank, leftover-map post - coverage, leftover-map item coverage, leftover-map incomplete post coverage, - leftover-map incomplete item coverage, or the count of unused axes. The strip - does not gain the leftover-map graphic. Never invent a leftover score. Never - invent a theta. No new columns. - -- Period leftover pairs now caption the grouping comparison strip with - persisted leftover-map axis share through leftoverMapCompareAxisShare - (ADR 0293 / v2.50.0). After `make seed`, closest and farthest leftover - pairs sit above the member list with the Gabriel biplot of already-named - coordinates, leftover-map axis share when finite, axis ticks that match - `ξ (x, y) ζ (x, y)` on the pair row, pair segments that match `d` on the - pair row, pair segments that match `R̂` on the pair row, pair segments - that match `R̂²/R²` on the pair row, pair segments that match `U²/R²` on - the pair row, pair segments that match `2R̂U/R²` on the pair row, pair - segments that match `U` on the pair row, pair segments that match `R` on - the pair row, pair segments that match `Y` on the pair row, pair - segments that match `E` on the pair row, pair segments that match - leftover-map rank on the pair row, a plot caption that matches leftover-map - complete-case coverage above the pair list, a plot caption that matches - leftover-map item complete-case coverage, a plot caption that matches - leftover-map incomplete post coverage, a plot caption that matches - leftover-map incomplete item coverage, a pair-list note that matches - leftover-map post complete-case coverage, a pair-list note that matches - leftover-map item complete-case coverage, a pair-list note that matches - leftover-map incomplete post coverage, a pair-list note that matches - leftover-map incomplete item coverage, a grouping comparison note that - matches leftover-map post complete-case coverage, a grouping comparison - note that matches leftover-map item complete-case coverage, a grouping - comparison note that matches leftover-map incomplete post coverage, a - grouping comparison note that matches leftover-map incomplete item - coverage, and a grouping comparison leftover-map axis share badge that - matches leftover-axis report badges; click a post marker or a pair button - opens that post. A missing or non-finite share omits that leftover-map - comparison axis share badge. Share `0` is shown when that persisted share - is a finite number, including rank-0 unused axes. A finite negative share - is shown; do not clamp to nonnegative. Do not invent leftover-map axis - share from leftover-map singular value, leftover pair count, plotted - marker count, leftover-map distance, leftover-map rank, leftover-map post - coverage, leftover-map item coverage, leftover-map incomplete post - coverage, leftover-map incomplete item coverage, or the count of unused - axes. The strip does not gain leftover-map singular values or the - leftover-map graphic. Never invent a leftover score or a theta. No new - columns. +- Grouping comparison pair actions now surface persisted finite unexplained leftover share `U²/R²` under ADR 0369 / v2.55.0, including the metric in the button accessible name and never deriving it from other psychometric values. -- Period leftover pairs now caption the grouping comparison strip with - persisted leftover-map incomplete item coverage through - leftoverMapIncompleteItemCount (ADR 0292 / v2.49.0). After `make seed`, - closest and farthest leftover pairs sit above the member list with the - Gabriel biplot of already-named coordinates, leftover-map axis share when - finite, axis ticks that match `ξ (x, y) ζ (x, y)` on the pair row, pair - segments that match `d` on the pair row, pair segments that match `R̂` on - the pair row, pair segments that match `R̂²/R²` on the pair row, pair - segments that match `U²/R²` on the pair row, pair segments that match - `2R̂U/R²` on the pair row, pair segments that match `U` on the pair row, - pair segments that match `R` on the pair row, pair segments that match - `Y` on the pair row, pair segments that match `E` on the pair row, pair - segments that match leftover-map rank on the pair row, a plot caption - that matches leftover-map complete-case coverage above the pair list, a - plot caption that matches leftover-map item complete-case coverage, a - plot caption that matches leftover-map incomplete post coverage, a plot - caption that matches leftover-map incomplete item coverage, a pair-list - note that matches leftover-map post complete-case coverage, a pair-list - note that matches leftover-map item complete-case coverage, a pair-list - note that matches leftover-map incomplete post coverage, a pair-list - note that matches leftover-map incomplete item coverage, a grouping - comparison note that matches leftover-map post complete-case coverage, - a grouping comparison note that matches leftover-map item - complete-case coverage, a grouping comparison note that matches - leftover-map incomplete post coverage, and a grouping comparison note - that matches leftover-map incomplete item coverage; click a post marker - or a pair button opens that post. A missing, non-integer, or negative - dropped count, or a dropped count that contradicts usable item - complete-case integers, omits that leftover-map comparison incomplete - item note. Dropped `0` is shown when that persisted dropped count is a - non-negative integer. Do not invent dropped criteria from scored minus - used, leftover pair count, plotted criterion marker count, leftover-map - distance, leftover-map rank, leftover-map post coverage, leftover-map - item coverage, leftover-map incomplete post coverage, or the count of - unused axes. The strip does not gain the leftover-map graphic. Never - invent a leftover score or a theta. No new columns. +- Grouping comparison pair buttons now expose persisted explained-leftover share `e = R̂²/R²` (ADR 0296 / v2.53.0). The visible duplicate badge is accessibility-hidden while the actionable button name includes the localized label and formatted persisted value. Missing/non-finite `e` omits only the suffix; finite zero and values above 1 remain explicit without clamping or client-side derivation. -- Period leftover pairs now caption the grouping comparison strip with - persisted leftover-map incomplete post coverage through - leftoverMapIncompletePostCount (ADR 0291 / v2.48.0). After `make seed`, - closest and farthest leftover pairs sit above the member list with the - Gabriel biplot of already-named coordinates, leftover-map axis share when - finite, axis ticks that match `ξ (x, y) ζ (x, y)` on the pair row, pair - segments that match `d` on the pair row, pair segments that match `R̂` on - the pair row, pair segments that match `R̂²/R²` on the pair row, pair - segments that match `U²/R²` on the pair row, pair segments that match - `2R̂U/R²` on the pair row, pair segments that match `U` on the pair row, - pair segments that match `R` on the pair row, pair segments that match - `Y` on the pair row, pair segments that match `E` on the pair row, pair - segments that match leftover-map rank on the pair row, a plot caption - that matches leftover-map complete-case coverage above the pair list, a - plot caption that matches leftover-map item complete-case coverage, a - plot caption that matches leftover-map incomplete post coverage, a plot - caption that matches leftover-map incomplete item coverage, a pair-list - note that matches leftover-map post complete-case coverage, a pair-list - note that matches leftover-map item complete-case coverage, a pair-list - note that matches leftover-map incomplete post coverage, a pair-list - note that matches leftover-map incomplete item coverage, a grouping - comparison note that matches leftover-map post complete-case coverage, - a grouping comparison note that matches leftover-map item - complete-case coverage, and a grouping comparison note that matches - leftover-map incomplete post coverage; click a post marker or a pair - button opens that post. A missing, non-integer, or negative dropped - count, or a dropped count that contradicts usable complete-case - integers, omits that leftover-map comparison incomplete post note. - Dropped `0` is shown when that persisted dropped count is a - non-negative integer. Do not invent dropped posts from scored minus - used, leftover pair count, plotted marker count, leftover-map distance, - leftover-map rank, leftover-map post coverage, leftover-map item - coverage, leftover-map incomplete item coverage, or the count of unused - axes. The strip does not gain leftover-map incomplete item coverage or - the leftover-map graphic. Never invent a leftover score or a theta. No - new columns. +- Grouping comparison leftover-pair buttons now expose persisted leftover-map reconstruction `R̂` (ADR 0295 / v2.52.0). The visible badge is decorative to accessibility APIs; the button accessible name carries the reconstruction label and value, so the explicit button `aria-label` cannot suppress the metric. Missing/non-finite `R̂` omits only that value and no client-side proxy is invented. -- Period leftover pairs now caption the grouping comparison strip with - persisted leftover-map item complete-case coverage through - leftoverMapItemCoverageCounts (ADR 0290 / v2.47.0). After `make seed`, - closest and farthest leftover pairs sit above the member list with the - Gabriel biplot of already-named coordinates, leftover-map axis share when - finite, axis ticks that match `ξ (x, y) ζ (x, y)` on the pair row, pair - segments that match `d` on the pair row, pair segments that match `R̂` on - the pair row, pair segments that match `R̂²/R²` on the pair row, pair - segments that match `U²/R²` on the pair row, pair segments that match - `2R̂U/R²` on the pair row, pair segments that match `U` on the pair row, - pair segments that match `R` on the pair row, pair segments that match - `Y` on the pair row, pair segments that match `E` on the pair row, pair - segments that match leftover-map rank on the pair row, a plot caption - that matches leftover-map complete-case coverage above the pair list, a - plot caption that matches leftover-map item complete-case coverage, a - plot caption that matches leftover-map incomplete post coverage, a plot - caption that matches leftover-map incomplete item coverage, a pair-list - note that matches leftover-map post complete-case coverage, a pair-list - note that matches leftover-map item complete-case coverage, a pair-list - note that matches leftover-map incomplete post coverage, a pair-list - note that matches leftover-map incomplete item coverage, a grouping - comparison note that matches leftover-map post complete-case coverage, - and a grouping comparison note that matches leftover-map item - complete-case coverage; click a post marker or a pair button opens that - post. A missing, non-integer, negative used, non-positive scored, or - used-greater-than-scored item coverage omits that leftover-map comparison - item coverage note. Coverage `0 of M` is shown when that persisted used - count is a non-negative integer and scored is a positive integer. Do not - invent item coverage from leftover pair count, plotted criterion marker - count, leftover-map distance, leftover-map rank, leftover-map post - coverage, leftover-map incomplete post coverage, leftover-map incomplete - item coverage, or the count of unused axes. The strip does not gain - leftover-map incomplete post coverage, leftover-map incomplete item - coverage, or the leftover-map graphic. Never invent a leftover score or - a theta. No new columns. +- Grouping comparison rows now show persisted leftover-map incomplete-item count through `leftoverMapIncompleteItemCount` (ADR 0294 / v2.51.0) only for fully caller-visible persisted groupings. Partial visibility remains omitted by the API; valid zero stays visible, and the UI never derives dropped criteria from scored-minus-used. + +- Grouping comparison rows now show persisted leftover-map incomplete-post count through `leftoverMapIncompletePostCount` (ADR 0293 / v2.50.0) only for a fully caller-visible persisted grouping. Partial visibility omits the aggregate; valid persisted zero remains visible, and the UI never derives dropped posts from scored-minus-used. + +- Period leftover pairs now caption leftover-axis report badges with persisted leftover-map singular values `σ_k` (ADR 0292 / v2.49.0). Missing, non-finite, or negative singular values omit only that `σ` caption; rank-0 zero remains `σ 0.00`, and axis share remains distinct. + +- Grouping comparison rows now name persisted leftover-map item complete-case coverage (ADR 0291 / v2.48.0) only when the caller can see the full persisted grouping population; partial-visibility rows omit the aggregate rather than leaking a denominator or recomputing subset coverage. + +- Grouping comparison rows now expose persisted leftover-map post complete-case coverage through `leftoverMapCoverageCounts` (ADR 0290 / v2.47.0) only for fully visible grouping populations. Partial-visibility rows omit the aggregate instead of leaking the full-group denominator or recomputing psychometric coverage from the visible subset. -- Period leftover pairs now caption the grouping comparison strip with - persisted leftover-map post complete-case coverage through - leftoverMapCoverageCounts (ADR 0289 / v2.46.0). After `make seed`, +- Period leftover pairs now caption leftover-map graphic axes with persisted + leftover-map singular values `σ_k` (ADR 0289 / v2.46.0). After `make seed`, closest and farthest leftover pairs sit above the member list with the - Gabriel biplot of already-named coordinates, leftover-map axis share when - finite, axis ticks that match `ξ (x, y) ζ (x, y)` on the pair row, pair - segments that match `d` on the pair row, pair segments that match `R̂` on - the pair row, pair segments that match `R̂²/R²` on the pair row, pair - segments that match `U²/R²` on the pair row, pair segments that match - `2R̂U/R²` on the pair row, pair segments that match `U` on the pair row, - pair segments that match `R` on the pair row, pair segments that match - `Y` on the pair row, pair segments that match `E` on the pair row, pair - segments that match leftover-map rank on the pair row, a plot caption - that matches leftover-map complete-case coverage above the pair list, a - plot caption that matches leftover-map item complete-case coverage, a - plot caption that matches leftover-map incomplete post coverage, a plot - caption that matches leftover-map incomplete item coverage, a pair-list - note that matches leftover-map post complete-case coverage, a pair-list - note that matches leftover-map item complete-case coverage, a pair-list - note that matches leftover-map incomplete post coverage, a pair-list - note that matches leftover-map incomplete item coverage, and a grouping - comparison note that matches leftover-map post complete-case coverage; - click a post marker or a pair button opens that post. A missing, - non-integer, negative used, non-positive scored, or used-greater-than-scored - coverage omits that leftover-map comparison coverage note. Coverage `0 of - M` is shown when that persisted used count is a non-negative integer and - scored is a positive integer. Do not invent post coverage from leftover - pair count, plotted marker count, leftover-map distance, leftover-map - rank, leftover-map item coverage, leftover-map incomplete post coverage, - leftover-map incomplete item coverage, or the count of unused axes. The - strip does not gain leftover-map item coverage, leftover-map incomplete - post coverage, leftover-map incomplete item coverage, or the leftover-map - graphic. Never invent a leftover score or a theta. No new columns. + Gabriel biplot of already-named coordinates, leftover-map singular values + when finite, leftover-map axis share when finite, axis ticks that match + `ξ (x, y) ζ (x, y)` on the pair row, pair segments that match `d` on + the pair row, pair segments that match `R̂` on the pair row, pair + segments that match `R̂²/R²` on the pair row, pair segments that match + `U²/R²` on the pair row, pair segments that match `2R̂U/R²` on the pair + row, pair segments that match `U` on the pair row, pair segments that + match `R` on the pair row, pair segments that match `Y` on the pair + row, pair segments that match `E` on the pair row, pair segments that + match leftover-map rank on the pair row, a plot caption that matches + leftover-map complete-case coverage above the pair list, a plot caption + that matches leftover-map item complete-case coverage, a plot caption + that matches leftover-map incomplete post coverage, a plot caption that + matches leftover-map incomplete item coverage, a pair-list note that + matches leftover-map post complete-case coverage, a pair-list note that + matches leftover-map item complete-case coverage, a pair-list note that + matches leftover-map incomplete post coverage, and a pair-list note + that matches leftover-map incomplete item coverage; click a post marker + or a pair button opens that post. A missing, non-finite, or negative + singular value omits that `σ` badge independently of leftover-map axis + share. Rank-0 unused axes still name `σ 0.00`. Do not invent `σ_k` from + leftover-map axis share, leftover-map distance, leftover-map rank, or + plotted coordinates. Never invent a leftover score or a theta. No new + columns. - Period leftover pairs now fail-close leftover-map post complete-case coverage on the leftover pair list through leftoverMapCoverageCounts diff --git a/CLAUDE.md b/CLAUDE.md index 6993e4098..c86ebcb45 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -49,7 +49,7 @@ cutoff. Global Ask optional `knowledge_cutoff` uses the same cover Create/start endpoint rules (ADR 0017 / 0021), tie-vs-miss similarity (ADR 0026), R&R catalog ids (ADR 0019 / 0027), leftover pairs -(ADR 0048–0164 / 0182 / 0185 / 0201 / 0233 / 0266 / 0267 / 0268 / 0269 / 0270 / 0271 / 0272 / 0273 / 0274 / 0275 / 0276 / 0277 / 0278 / 0279 / 0280 / 0281 / 0282 / 0283 / 0284 / 0285 / 0286 / 0287 / 0288 / 0289 / 0290 / 0291 / 0292 / 0293 / 0294), occupational construct catalog search +(ADR 0048–0164 / 0182 / 0185 / 0201 / 0233 / 0266 / 0267 / 0268 / 0269 / 0270 / 0271 / 0272 / 0273 / 0274 / 0275 / 0276 / 0277 / 0278 / 0279 / 0280 / 0281 / 0282 / 0283 / 0284 / 0285 / 0286 / 0287 / 0288 / 0289 / 0290 / 0291 / 0292 / 0293), occupational construct catalog search (ADR 0257), the text-channel embedding swap and cosine clamp (ADR 0190), per-edge channel-score persistence (ADR 0195), token-backed status notices (ADR 0220), @@ -57,3 +57,11 @@ migration replay (ADR 0166), docstring coverage, and the measurement boundary are all stated in [AGENTS.md](AGENTS.md) -- read it before changing code, tests, or runtime policy rather than restating anything here. + +ADR 0294 is the Proposed grouping-comparison incomplete-item presentation contract; preserve server-side full-group visibility gating and do not infer dropped criteria in the frontend. + +ADR 0295 is the Proposed grouping-comparison reconstruction contract: persisted `R̂` only, no client inference, accessible-name exposure required despite the button's explicit aria-label. + +ADR 0296 is the Proposed grouping-comparison explained-share contract: persisted `e` only, accessible-name exposure required, no client derivation or clamping. + +Grouping-comparison unexplained-share presentation is ADR 0369: consume persisted finite `leftover_map_unexplained_share`, never derive it, and keep its value in the actionable button accessible name. diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index f7ee5868a..7ff09f08e 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -1,429 +1,25 @@ # Product & Technical Gap Baseline -> Exact-head loop overlay: 2026-08-31 00:35 KST. Protected `main` is -> `cb187cadee5fb6c46d8a944815ccc154a1e028d1` after unauthorized squash -> of leftover-map coordinates (v2.24.0 / #782). Revert #808 -> (`revert-pr782-unauthorized` @ `1af3e53e`) restores `main` toward -> `fc13acaa` (v2.23.0) and still needs independent APPROVE. GitHub -> writes work (comment/close/create-PR/push). Token still has empty -> `X-OAuth-Scopes`; repo permission is ADMIN. Open leftover stack -> still lacks independent APPROVE. Do not self-approve. -> #825 leftover-map incomplete item coverage on the grouping comparison -> strip (v2.49.0 / ADR 0292) is `bca6baa`. #828 leftover-map axis share -> on the grouping comparison strip (v2.50.0 / ADR 0293) is `e791376`. -> Leave #782/#802/#803/#804/#805/#806/#808/#809/#810/#811/#812/#813/#814/#815/#816/#817/#818/#819/#821/#822/#823/#824/#825/#828 open for -> independent review. Do not squash-merge stacked leftover PRs onto an -> unprotected leftover base. Do not merge #808 without independent APPROVE. -> Copilot review is not independent APPROVE. Issues #79 and #87 stay open. -> #96 is already closed. Only collaborator is `seonghobae`. -> -> Next buyer increment on this cycle: leftover-map singular values on the -> grouping comparison strip (ADR 0294 / v2.51.0) on -> `feat/leftover-map-compare-axis-singular-v2510`. Caption persisted -> leftover_singular_value already on GET /api/reports/compare/{period} -> through leftoverMapCompareAxisSingular with distinct aria-label -> `Leftover map comparison axis singular` and copy -> `leftover map comparison axis {axis} σ {value}`. UI-only; no new columns. -> Missing, non-finite, or negative leftover-map singular value omits that -> badge independently of leftover-map comparison axis share. Rank-0 `0` -> is shown when persisted. Do not invent leftover-map singular value from -> leftover-map axis share. Do not add the leftover-map graphic. Stack onto -> leftover branch `feat/leftover-map-compare-axis-share-v2500` / #828; -> leave the PR open for independent review. Do not squash-merge onto the -> leftover base. Do not invent leftover scores. -> -> Exact-head loop overlay: 2026-08-30 23:45 KST. Protected `main` is -> `cb187cadee5fb6c46d8a944815ccc154a1e028d1` after unauthorized squash -> of leftover-map coordinates (v2.24.0 / #782). Revert #808 -> (`revert-pr782-unauthorized` @ `1af3e53e`) restores `main` toward -> `fc13acaa` (v2.23.0) and still needs independent APPROVE. GitHub -> writes work (comment/close/create-PR/push). Token still has empty -> `X-OAuth-Scopes`; repo permission is ADMIN. Open leftover stack -> still lacks independent APPROVE. Do not self-approve. -> #782 leftover-map coordinates through pair-segment distance -> (v2.24.0–v2.28.0 / ADR 0267–0271) is `9bdd3e4d`. #802 explained -> leftover share on pair segments (v2.30.0 / ADR 0273, includes v2.29 -> reconstruction) is `79ec22f0`. #803 unexplained leftover share on pair -> segments (v2.31.0 / ADR 0274) is `089a1571`. #804 leftover-map cross -> share on pair segments (v2.32.0 / ADR 0275) is `c513002b`. #805 leftover-map -> unexplained leftover `U` on pair segments (v2.33.0 / ADR 0276) is -> `e3fdfd74`. #806 leftover residual `R` on pair segments (v2.34.0 / -> ADR 0277) is `33f6c3dd`. #809 leftover observed `Y` on pair segments -> (v2.35.0 / ADR 0278) is `b334b00e`. #810 leftover expected `E` on pair -> segments (v2.36.0 / ADR 0279) is `6e37757a`. #811 leftover-map rank on -> pair segments (v2.37.0 / ADR 0280) is `e626a1d0`. #812 leftover-map -> complete-case coverage on the graphic (v2.38.0 / ADR 0281) is `64964cb6`. -> #813 leftover-map item complete-case coverage on the graphic (v2.39.0 / -> ADR 0282) is `de2a8a8b`. #814 leftover-map incomplete post coverage on -> the graphic (v2.40.0 / ADR 0283) is `77292872`. #815 leftover-map -> incomplete item coverage on the graphic (v2.41.0 / ADR 0284) is -> `63092de`. #816 leftover-map item complete-case coverage on the pair -> list (v2.42.0 / ADR 0285) is `1e3d13e`. #817 leftover-map incomplete -> post coverage on the pair list (v2.43.0 / ADR 0286) is `ef30930`. -> #818 leftover-map incomplete item coverage on the pair list -> (v2.44.0 / ADR 0287) is `aa32089`. #819 leftover-map post complete-case -> coverage fail-closed on the pair list (v2.45.0 / ADR 0288) is `a2c96551`. -> #821 leftover-map complete-case coverage on the grouping comparison -> strip (v2.46.0 / ADR 0289) is `11a78553`. #822 leftover-map item -> complete-case coverage on the grouping comparison strip (v2.47.0 / -> ADR 0290) is `6726353a`. #823 leftover-map singular values on leftover-axis -> badges (v2.47.0 / ADR 0290, plot stack) is `eb172c40`. #824 leftover-map -> incomplete post coverage on the grouping comparison strip (v2.48.0 / -> ADR 0291) is `8b2ed95`. #825 leftover-map incomplete item coverage on -> the grouping comparison strip (v2.49.0 / ADR 0292) is `bca6baa`. Leave -> #782/#802/#803/#804/#805/#806/#808/#809/#810/#811/#812/#813/#814/#815/#816/#817/#818/#819/#821/#822/#823/#824/#825 open for -> independent review. Do not squash-merge stacked leftover PRs onto an -> unprotected leftover base. Do not merge #808 without independent APPROVE. -> Strix on #782 failed closed at `Run Strix (quick)`; do not weaken -> fail-closed on `Vulnerabilities [1-9]`. Org Strix `ModelBehaviorError` -> classifier is already on ContextualWisdomLab/.github. Copilot review is -> not independent APPROVE. Issues #79 and #87 stay open. #96 is already -> closed. Only collaborator is `seonghobae`; no independent reviewer can -> be requested from this token. -> -> Next buyer increment on this cycle: leftover-map axis share on the -> grouping comparison strip (ADR 0293 / v2.50.0) delivered locally on -> `feat/leftover-map-compare-axis-share-v2500`. Include persisted -> leftover_map_axes on GET /api/reports/compare/{period} and caption each -> grouping row through leftoverMapCompareAxisShare with distinct -> aria-label `Leftover map comparison axis share` and copy -> `leftover map comparison axis {axis} {share}%`. UI + compare payload; -> no new columns. Missing or non-finite share omits that leftover-map -> comparison axis share badge independently of coverage notes. Share `0` -> is shown when persisted, including rank-0 unused axes. Do not invent -> leftover-map axis share from leftover-map singular value, leftover pair -> count, plotted marker count, leftover-map distance, leftover-map rank, -> leftover-map post coverage, leftover-map item coverage, leftover-map -> incomplete post coverage, leftover-map incomplete item coverage, or the -> count of unused axes. Do not caption leftover-map singular values or the -> leftover-map graphic on the strip. Do not invent leftover scores. Stack -> onto leftover branch `feat/leftover-map-compare-incomplete-item-v2490` / -> #825; leave the PR open for independent review. Do not squash-merge onto -> the leftover base. Do not persist leftover-map inner product, cosine, or -> length as separate columns. - - -> Exact-head loop overlay: 2026-08-30 23:28 KST. Protected `main` is -> `cb187cadee5fb6c46d8a944815ccc154a1e028d1` after unauthorized squash -> of leftover-map coordinates (v2.24.0 / #782). Revert #808 -> (`revert-pr782-unauthorized` @ `1af3e53e`) restores `main` toward -> `fc13acaa` (v2.23.0) and still needs independent APPROVE. GitHub -> writes work (comment/close/create-PR/push). Token still has empty -> `X-OAuth-Scopes`; repo permission is ADMIN. Open leftover stack -> still lacks independent APPROVE. Do not self-approve. -> #782 leftover-map coordinates through pair-segment distance -> (v2.24.0–v2.28.0 / ADR 0267–0271) is `9bdd3e4d`. #802 explained -> leftover share on pair segments (v2.30.0 / ADR 0273, includes v2.29 -> reconstruction) is `79ec22f0`. #803 unexplained leftover share on pair -> segments (v2.31.0 / ADR 0274) is `089a1571`. #804 leftover-map cross -> share on pair segments (v2.32.0 / ADR 0275) is `c513002b`. #805 leftover-map -> unexplained leftover `U` on pair segments (v2.33.0 / ADR 0276) is -> `e3fdfd74`. #806 leftover residual `R` on pair segments (v2.34.0 / -> ADR 0277) is `33f6c3dd`. #809 leftover observed `Y` on pair segments -> (v2.35.0 / ADR 0278) is `b334b00e`. #810 leftover expected `E` on pair -> segments (v2.36.0 / ADR 0279) is `6e37757a`. #811 leftover-map rank on -> pair segments (v2.37.0 / ADR 0280) is `e626a1d0`. #812 leftover-map -> complete-case coverage on the graphic (v2.38.0 / ADR 0281) is `64964cb6`. -> #813 leftover-map item complete-case coverage on the graphic (v2.39.0 / -> ADR 0282) is `de2a8a8b`. #814 leftover-map incomplete post coverage on -> the graphic (v2.40.0 / ADR 0283) is `77292872`. #815 leftover-map -> incomplete item coverage on the graphic (v2.41.0 / ADR 0284) is -> `63092de`. #816 leftover-map item complete-case coverage on the pair -> list (v2.42.0 / ADR 0285) is `1e3d13e`. #817 leftover-map incomplete -> post coverage on the pair list (v2.43.0 / ADR 0286) is `ef30930`. -> #818 leftover-map incomplete item coverage on the pair list -> (v2.44.0 / ADR 0287) is `aa32089`. #819 leftover-map post complete-case -> coverage fail-closed on the pair list (v2.45.0 / ADR 0288) is `a2c96551`. -> #821 leftover-map complete-case coverage on the grouping comparison -> strip (v2.46.0 / ADR 0289) is `11a78553`. #822 leftover-map item -> complete-case coverage on the grouping comparison strip (v2.47.0 / -> ADR 0290) is `6726353a`. #823 leftover-map singular values on leftover-axis -> badges (v2.47.0 / ADR 0290, plot stack) is `eb172c40`. #824 leftover-map -> incomplete post coverage on the grouping comparison strip (v2.48.0 / -> ADR 0291) is `8b2ed95`. Leave -> #782/#802/#803/#804/#805/#806/#808/#809/#810/#811/#812/#813/#814/#815/#816/#817/#818/#819/#821/#822/#823/#824 open for -> independent review. Do not squash-merge stacked leftover PRs onto an -> unprotected leftover base. Do not merge #808 without independent APPROVE. -> Strix on #782 failed closed at `Run Strix (quick)`; do not weaken -> fail-closed on `Vulnerabilities [1-9]`. Org Strix `ModelBehaviorError` -> classifier is already on ContextualWisdomLab/.github. Copilot review is -> not independent APPROVE. Issues #79 and #87 stay open. #96 is already -> closed. Only collaborator is `seonghobae`; no independent reviewer can -> be requested from this token. -> -> Next buyer increment on this cycle: leftover-map incomplete item -> coverage on the grouping comparison strip (ADR 0292 / v2.49.0) delivered -> locally on `feat/leftover-map-compare-incomplete-item-v2490`. Caption each -> grouping row through leftoverMapIncompleteItemCount with distinct -> aria-label `Leftover map comparison incomplete items` and copy -> `Leftover map dropped {dropped} incomplete criteria`. UI-only; no new -> columns. Missing, non-integer, or negative dropped count, or a dropped -> count that contradicts usable item complete-case integers, omits that -> leftover-map comparison incomplete item note independently of post/item -> complete-case and incomplete post coverage. Dropped `0` is shown when -> persisted. Do not invent dropped criteria from scored minus used, -> leftover pair count, plotted criterion marker count, leftover-map -> distance, leftover-map rank, leftover-map post coverage, leftover-map -> item coverage, leftover-map incomplete post coverage, or the count of -> unused axes. Do not caption the leftover-map graphic on the strip. Do -> not invent leftover scores. Stack onto leftover branch -> `feat/leftover-map-compare-incomplete-post-v2480` / #824; leave the PR -> open for independent review. Do not squash-merge onto the leftover -> base. Do not persist leftover-map inner product, cosine, or length as -> separate columns. - - -> Exact-head loop overlay: 2026-08-30 23:20 KST. Protected `main` is -> `cb187cadee5fb6c46d8a944815ccc154a1e028d1` after unauthorized squash -> of leftover-map coordinates (v2.24.0 / #782). Revert #808 -> (`revert-pr782-unauthorized` @ `1af3e53e`) restores `main` toward -> `fc13acaa` (v2.23.0) and still needs independent APPROVE. GitHub -> writes work (comment/close/create-PR/push). Token still has empty -> `X-OAuth-Scopes`; repo permission is ADMIN. Open leftover stack -> still lacks independent APPROVE. Do not self-approve. -> #782 leftover-map coordinates through pair-segment distance -> (v2.24.0–v2.28.0 / ADR 0267–0271) is `9bdd3e4d`. #802 explained -> leftover share on pair segments (v2.30.0 / ADR 0273, includes v2.29 -> reconstruction) is `79ec22f0`. #803 unexplained leftover share on pair -> segments (v2.31.0 / ADR 0274) is `089a1571`. #804 leftover-map cross -> share on pair segments (v2.32.0 / ADR 0275) is `c513002b`. #805 leftover-map -> unexplained leftover `U` on pair segments (v2.33.0 / ADR 0276) is -> `e3fdfd74`. #806 leftover residual `R` on pair segments (v2.34.0 / -> ADR 0277) is `33f6c3dd`. #809 leftover observed `Y` on pair segments -> (v2.35.0 / ADR 0278) is `b334b00e`. #810 leftover expected `E` on pair -> segments (v2.36.0 / ADR 0279) is `6e37757a`. #811 leftover-map rank on -> pair segments (v2.37.0 / ADR 0280) is `e626a1d0`. #812 leftover-map -> complete-case coverage on the graphic (v2.38.0 / ADR 0281) is `64964cb6`. -> #813 leftover-map item complete-case coverage on the graphic (v2.39.0 / -> ADR 0282) is `de2a8a8b`. #814 leftover-map incomplete post coverage on -> the graphic (v2.40.0 / ADR 0283) is `77292872`. #815 leftover-map -> incomplete item coverage on the graphic (v2.41.0 / ADR 0284) is -> `63092de`. #816 leftover-map item complete-case coverage on the pair -> list (v2.42.0 / ADR 0285) is `1e3d13e`. #817 leftover-map incomplete -> post coverage on the pair list (v2.43.0 / ADR 0286) is `ef30930`. -> #818 leftover-map incomplete item coverage on the pair list -> (v2.44.0 / ADR 0287) is `aa32089`. #819 leftover-map post complete-case -> coverage fail-closed on the pair list (v2.45.0 / ADR 0288) is `a2c96551`. -> #821 leftover-map complete-case coverage on the grouping comparison -> strip (v2.46.0 / ADR 0289) is `11a78553`. #822 leftover-map item -> complete-case coverage on the grouping comparison strip (v2.47.0 / -> ADR 0290) is `6726353a`. #823 leftover-map singular values on leftover-axis -> badges (v2.47.0 / ADR 0290, plot stack) is `eb172c40`. Leave -> #782/#802/#803/#804/#805/#806/#808/#809/#810/#811/#812/#813/#814/#815/#816/#817/#818/#819/#821/#822/#823 open for -> independent review. Do not squash-merge stacked leftover PRs onto an -> unprotected leftover base. Do not merge #808 without independent APPROVE. -> Strix on #782 failed closed at `Run Strix (quick)`; do not weaken -> fail-closed on `Vulnerabilities [1-9]`. Org Strix `ModelBehaviorError` -> classifier is already on ContextualWisdomLab/.github. Copilot review is -> not independent APPROVE. Issues #79 and #87 stay open. #96 is already -> closed. Only collaborator is `seonghobae`; no independent reviewer can -> be requested from this token. -> -> Next buyer increment on this cycle: leftover-map incomplete post -> coverage on the grouping comparison strip (ADR 0291 / v2.48.0) delivered -> locally on `feat/leftover-map-compare-incomplete-post-v2480`. Caption each -> grouping row through leftoverMapIncompletePostCount with distinct -> aria-label `Leftover map comparison incomplete posts` and copy -> `Leftover map dropped {dropped} incomplete posts`. UI-only; no new -> columns. Missing, non-integer, or negative dropped count, or a dropped -> count that contradicts usable complete-case integers, omits that -> leftover-map comparison incomplete post note independently of post/item -> complete-case. Dropped `0` is shown when persisted. Do not invent -> dropped posts from scored minus used, leftover pair count, plotted -> marker count, leftover-map distance, leftover-map rank, leftover-map -> post coverage, leftover-map item coverage, leftover-map incomplete -> item coverage, or the count of unused axes. Do not caption leftover-map -> incomplete item coverage or the leftover-map graphic on the strip. Do -> not invent leftover scores. Stack onto leftover branch -> `feat/leftover-map-compare-item-coverage-v2470` / #822; leave the PR -> open for independent review. Do not squash-merge onto the leftover -> base. Do not persist leftover-map inner product, cosine, or length as -> separate columns. +> Current serialized repair (2026-09-07): #829 consumes exact promoted #828 `7b6dbbb99a09d0523bce43c6872bbd9fa382a43a` and preserves persisted `U²/R²` comparison presentation as ADR 0369 / v2.55.0. Finite values are present in the actionable button name and visible badge; missing/non-finite values are absent; values are never derived/clamped; current-parent whole-population authorization remains intact. Historical ADR0295/v2.52.0 is evidence only. Inline five-locale copy is compatibility presentation while #922/#929/#932 remain the eight-locale translation-ledger owner path. -> Exact-head loop overlay: 2026-08-30 23:12 KST. Protected `main` is -> `cb187cadee5fb6c46d8a944815ccc154a1e028d1` after unauthorized squash -> of leftover-map coordinates (v2.24.0 / #782). Revert #808 -> (`revert-pr782-unauthorized` @ `1af3e53e`) restores `main` toward -> `fc13acaa` (v2.23.0) and still needs independent APPROVE. GitHub -> writes work (comment/close/create-PR/push). Token still has empty -> `X-OAuth-Scopes`; repo permission is ADMIN. Open leftover stack -> still lacks independent APPROVE. Do not self-approve. -> #782 leftover-map coordinates through pair-segment distance -> (v2.24.0–v2.28.0 / ADR 0267–0271) is `9bdd3e4d`. #802 explained -> leftover share on pair segments (v2.30.0 / ADR 0273, includes v2.29 -> reconstruction) is `79ec22f0`. #803 unexplained leftover share on pair -> segments (v2.31.0 / ADR 0274) is `089a1571`. #804 leftover-map cross -> share on pair segments (v2.32.0 / ADR 0275) is `c513002b`. #805 leftover-map -> unexplained leftover `U` on pair segments (v2.33.0 / ADR 0276) is -> `e3fdfd74`. #806 leftover residual `R` on pair segments (v2.34.0 / -> ADR 0277) is `33f6c3dd`. #809 leftover observed `Y` on pair segments -> (v2.35.0 / ADR 0278) is `b334b00e`. #810 leftover expected `E` on pair -> segments (v2.36.0 / ADR 0279) is `6e37757a`. #811 leftover-map rank on -> pair segments (v2.37.0 / ADR 0280) is `e626a1d0`. #812 leftover-map -> complete-case coverage on the graphic (v2.38.0 / ADR 0281) is `64964cb6`. -> #813 leftover-map item complete-case coverage on the graphic (v2.39.0 / -> ADR 0282) is `de2a8a8b`. #814 leftover-map incomplete post coverage on -> the graphic (v2.40.0 / ADR 0283) is `77292872`. #815 leftover-map -> incomplete item coverage on the graphic (v2.41.0 / ADR 0284) is -> `63092de`. #816 leftover-map item complete-case coverage on the pair -> list (v2.42.0 / ADR 0285) is `1e3d13e`. #817 leftover-map incomplete -> post coverage on the pair list (v2.43.0 / ADR 0286) is `ef30930`. -> #818 leftover-map incomplete item coverage on the pair list -> (v2.44.0 / ADR 0287) is `aa32089`. #819 leftover-map post complete-case -> coverage fail-closed on the pair list (v2.45.0 / ADR 0288) is `a2c96551`. -> #821 leftover-map complete-case coverage on the grouping comparison -> strip (v2.46.0 / ADR 0289) is `11a78553`. Leave -> #782/#802/#803/#804/#805/#806/#808/#809/#810/#811/#812/#813/#814/#815/#816/#817/#818/#819/#821 open for -> independent review. Do not squash-merge stacked leftover PRs onto an -> unprotected leftover base. Do not merge #808 without independent APPROVE. -> Strix on #782 failed closed at `Run Strix (quick)`; do not weaken -> fail-closed on `Vulnerabilities [1-9]`. Org Strix `ModelBehaviorError` -> classifier is already on ContextualWisdomLab/.github. Copilot review is -> not independent APPROVE. Issues #79 and #87 stay open. #96 is already -> closed. Only collaborator is `seonghobae`; no independent reviewer can -> be requested from this token. -> -> Next buyer increment on this cycle: leftover-map item complete-case -> coverage on the grouping comparison strip (ADR 0290 / v2.47.0) delivered -> locally on `feat/leftover-map-compare-item-coverage-v2470`. Caption each -> grouping row through leftoverMapItemCoverageCounts with distinct -> aria-label `Leftover map comparison item coverage`. UI-only; no new -> columns. Missing, non-integer, negative used, non-positive scored, or -> used-greater-than-scored item coverage omits that leftover-map comparison -> item coverage note. Coverage `0 of M` is shown when persisted. Do not -> invent item coverage from leftover pair count, plotted criterion marker -> count, leftover-map distance, leftover-map rank, leftover-map post -> coverage, leftover-map incomplete post coverage, leftover-map incomplete -> item coverage, or the count of unused axes. Do not caption leftover-map -> incomplete post, leftover-map incomplete item, or the leftover-map graphic -> on the strip. Do not invent leftover scores. Stack onto leftover branch -> `feat/leftover-map-compare-coverage-v2460` / #821; leave the PR open for -> independent review. Do not squash-merge onto the leftover base. Do not -> persist leftover-map inner product, cosine, or length as separate columns. +> Current serialized repair (2026-09-07): #828 is reconstructed from exact #827 `0f9e9c8db37948041f39b4e68e4bbd808fa83752` as ADR 0367 / v2.54.0. The valid delta carries persisted grouping-comparison `leftover_map_axes` but exposes them only when the caller can see the entire persisted grouping population; partial visibility returns no aggregate and never recomputes psychometrics from the visible subset. Presentation consumes persisted `leftover_share` only, with zero and finite negative values explicit and missing/non-finite values omitted. Historical v2.50.0/ADR0293 identity is evidence only. Existing five-locale compatibility copy is preserved while the database-backed eight-locale translation-ledger authority remains #922/#929/#932; this Draft does not create a competing translation source. -> Exact-head loop overlay: 2026-08-30 22:52 KST. Protected `main` is -> `cb187cadee5fb6c46d8a944815ccc154a1e028d1` after unauthorized squash -> of leftover-map coordinates (v2.24.0 / #782). Revert #808 -> (`revert-pr782-unauthorized` @ `1af3e53e`) restores `main` toward -> `fc13acaa` (v2.23.0) and still needs independent APPROVE. GitHub -> writes work (comment/close/create-PR/push). Token still has empty -> `X-OAuth-Scopes`; repo permission is ADMIN. Open leftover stack -> still lacks independent APPROVE. Do not self-approve. -> #782 leftover-map coordinates through pair-segment distance -> (v2.24.0–v2.28.0 / ADR 0267–0271) is `9bdd3e4d`. #802 explained -> leftover share on pair segments (v2.30.0 / ADR 0273, includes v2.29 -> reconstruction) is `79ec22f0`. #803 unexplained leftover share on pair -> segments (v2.31.0 / ADR 0274) is `089a1571`. #804 leftover-map cross -> share on pair segments (v2.32.0 / ADR 0275) is `c513002b`. #805 leftover-map -> unexplained leftover `U` on pair segments (v2.33.0 / ADR 0276) is -> `e3fdfd74`. #806 leftover residual `R` on pair segments (v2.34.0 / -> ADR 0277) is `33f6c3dd`. #809 leftover observed `Y` on pair segments -> (v2.35.0 / ADR 0278) is `b334b00e`. #810 leftover expected `E` on pair -> segments (v2.36.0 / ADR 0279) is `6e37757a`. #811 leftover-map rank on -> pair segments (v2.37.0 / ADR 0280) is `e626a1d0`. #812 leftover-map -> complete-case coverage on the graphic (v2.38.0 / ADR 0281) is `64964cb6`. -> #813 leftover-map item complete-case coverage on the graphic (v2.39.0 / -> ADR 0282) is `de2a8a8b`. #814 leftover-map incomplete post coverage on -> the graphic (v2.40.0 / ADR 0283) is `77292872`. #815 leftover-map -> incomplete item coverage on the graphic (v2.41.0 / ADR 0284) is -> `63092de`. #816 leftover-map item complete-case coverage on the pair -> list (v2.42.0 / ADR 0285) is `1e3d13e`. #817 leftover-map incomplete -> post coverage on the pair list (v2.43.0 / ADR 0286) is `ef30930`. -> #818 leftover-map incomplete item coverage on the pair list -> (v2.44.0 / ADR 0287) is `aa32089`. #819 leftover-map post complete-case -> coverage fail-closed on the pair list (v2.45.0 / ADR 0288) is `a2c96551`. -> Leave -> #782/#802/#803/#804/#805/#806/#808/#809/#810/#811/#812/#813/#814/#815/#816/#817/#818/#819 open for -> independent review. Do not squash-merge stacked leftover PRs onto an -> unprotected leftover base. Do not merge #808 without independent APPROVE. -> Strix on #782 failed closed at `Run Strix (quick)`; do not weaken -> fail-closed on `Vulnerabilities [1-9]`. Org Strix `ModelBehaviorError` -> classifier is already on ContextualWisdomLab/.github. Copilot review is -> not independent APPROVE. Issues #79 and #87 stay open. #96 is already -> closed. Only collaborator is `seonghobae`; no independent reviewer can -> be requested from this token. -> -> Next buyer increment on this cycle: leftover-map complete-case coverage -> on the grouping comparison strip (ADR 0289 / v2.46.0) delivered -> locally on `feat/leftover-map-compare-coverage-v2460`. Include persisted -> leftover_map_coverage on GET /api/reports/compare/{period} and caption -> each grouping row through leftoverMapCoverageCounts with distinct -> aria-label `Leftover map comparison coverage`. UI + compare payload; -> no new columns. Missing, non-integer, negative used, non-positive scored, -> or used-greater-than-scored coverage omits that leftover-map comparison -> coverage note. Coverage `0 of M` is shown when persisted. Do not invent -> post coverage from leftover pair count, plotted marker count, leftover-map -> distance, leftover-map rank, leftover-map item coverage, leftover-map -> incomplete post coverage, leftover-map incomplete item coverage, or the -> count of unused axes. Do not caption leftover-map item coverage, -> leftover-map incomplete post, leftover-map incomplete item, or the -> leftover-map graphic on the strip. Do not invent leftover scores. Stack -> onto leftover branch `feat/leftover-map-list-post-coverage-helper-v2450` -> / #819; leave the PR open for independent review. Do not squash-merge -> onto the leftover base. Do not persist leftover-map inner product, cosine, -> or length as separate columns. - - -> Exact-head loop overlay: 2026-08-30 22:30 KST. Protected `main` is -> `cb187cadee5fb6c46d8a944815ccc154a1e028d1` after unauthorized squash -> of leftover-map coordinates (v2.24.0 / #782). Revert #808 -> (`revert-pr782-unauthorized` @ `1af3e53e`) restores `main` toward -> `fc13acaa` (v2.23.0) and still needs independent APPROVE. GitHub -> writes work (comment/close/create-PR/push). Token still has empty -> `X-OAuth-Scopes`; repo permission is ADMIN. Open leftover stack -> still lacks independent APPROVE. Do not self-approve. -> #782 leftover-map coordinates through pair-segment distance -> (v2.24.0–v2.28.0 / ADR 0267–0271) is `9bdd3e4d`. #802 explained -> leftover share on pair segments (v2.30.0 / ADR 0273, includes v2.29 -> reconstruction) is `79ec22f0`. #803 unexplained leftover share on pair -> segments (v2.31.0 / ADR 0274) is `089a1571`. #804 leftover-map cross -> share on pair segments (v2.32.0 / ADR 0275) is `c513002b`. #805 leftover-map -> unexplained leftover `U` on pair segments (v2.33.0 / ADR 0276) is -> `e3fdfd74`. #806 leftover residual `R` on pair segments (v2.34.0 / -> ADR 0277) is `33f6c3dd`. #809 leftover observed `Y` on pair segments -> (v2.35.0 / ADR 0278) is `b334b00e`. #810 leftover expected `E` on pair -> segments (v2.36.0 / ADR 0279) is `6e37757a`. #811 leftover-map rank on -> pair segments (v2.37.0 / ADR 0280) is `e626a1d0`. #812 leftover-map -> complete-case coverage on the graphic (v2.38.0 / ADR 0281) is `64964cb6`. -> #813 leftover-map item complete-case coverage on the graphic (v2.39.0 / -> ADR 0282) is `de2a8a8b`. #814 leftover-map incomplete post coverage on -> the graphic (v2.40.0 / ADR 0283) is `77292872`. #815 leftover-map -> incomplete item coverage on the graphic (v2.41.0 / ADR 0284) is -> `63092de`. #816 leftover-map item complete-case coverage on the pair -> list (v2.42.0 / ADR 0285) is `1e3d13e`. #817 leftover-map incomplete -> post coverage on the pair list (v2.43.0 / ADR 0286) is `ef30930`. -> #818 leftover-map incomplete item coverage on the pair list -> (v2.44.0 / ADR 0287) is `aa32089`. Leave -> #782/#802/#803/#804/#805/#806/#808/#809/#810/#811/#812/#813/#814/#815/#816/#817/#818 open for -> independent review. Do not squash-merge stacked leftover PRs onto an -> unprotected leftover base. Do not merge #808 without independent APPROVE. -> Strix on #782 failed closed at `Run Strix (quick)`; do not weaken -> fail-closed on `Vulnerabilities [1-9]`. Org Strix `ModelBehaviorError` -> classifier is already on ContextualWisdomLab/.github. Copilot review is -> not independent APPROVE. Issues #79 and #87 stay open. #96 is already -> closed. Only collaborator is `seonghobae`; no independent reviewer can -> be requested from this token. -> -> Next buyer increment on this cycle: leftover-map post complete-case -> coverage fail-closed on the pair list (ADR 0288 / v2.45.0) delivered -> locally on `feat/leftover-map-list-post-coverage-helper-v2450`. Caption -> the pair-list note with persisted leftover-map post complete-case -> coverage only when leftoverMapCoverageCounts returns usable complete-case -> integers so used-greater-than-scored, negative, or non-integer payloads -> cannot caption a contradictory `used N of M scored posts` note. UI-only; -> no new columns. Missing, non-integer, negative used, non-positive scored, -> or used-greater-than-scored coverage omits that leftover-map coverage -> note. Coverage `0 of M` is shown when persisted. Do not invent post -> coverage from plotted marker count, leftover-map distance, leftover-map -> rank, leftover-map item coverage, leftover-map incomplete post coverage, -> leftover-map incomplete item coverage, or the count of unused axes. Do -> not invent leftover scores. Stack onto leftover branch -> `feat/leftover-map-list-incomplete-item-v2440` / #818; leave the PR open -> for independent review. Do not squash-merge onto the leftover base. Do -> not persist leftover-map inner product, cosine, or length as separate -> columns. Grouping comparison strip (ADR 0149) does not gain this caption. +> 2026-09-07 #822 reconstruction: exact #821 `93eaa40f...` owns ADR 0290/v2.47.0 and the full-visible-grouping coverage boundary. Preserve historical item-coverage composition as ADR 0291/v2.48.0; partial-visibility rows omit the shared persisted coverage aggregate. #963 remains owner of broader current-vs-historical baseline governance. +> #821 current-parent reconstruction: preserve grouping-comparison leftover-map post complete-case coverage from historical `11a78553...` on exact #820 `503d043e...`, but move the decision to ADR 0290 / v2.47.0 and fail closed persisted coverage whenever ABAC hides any grouping member. Review 5126637582 is the authorization RED authority; #963 still owns the broader current-vs-historical baseline cleanup. +> #820 exact-current-parent reconstruction: persisted singular-value axis badges +> are reconstructed from #819 `f37ca315e3c48fa37bbcafe96e46c5d7dab991b7`. +> Preserve finite, non-negative persisted `σ_k`, including rank-0 `σ 0.00`; omit missing, +> non-finite, or negative singular values independently of axis share. Parent share-only +> regressions run with singular value unavailable so the contracts remain orthogonal. +> ADR 0289 stays Proposed while Draft; package/frontend/runtime identity is 2.46.0. + +> #819 current-parent reconstruction: v2.45 pair-list post coverage fail-close +> is being rebuilt from exact #818 `bc971a402ef9faecb2f0b4ffd743092f4779d76b`. +> Preserve only feature delta `a2c965511d26923bd878ec56d655fb8a0183c4d7`; +> historical convergence is evidence only. ADR 0288 remains Proposed while Draft, +> and package/frontend/runtime release identity must converge at 2.45.0 before promotion. > Exact-head loop overlay: 2026-08-30 22:18 KST. Protected `main` is > `cb187cadee5fb6c46d8a944815ccc154a1e028d1` after unauthorized squash @@ -462,7 +58,6 @@ > not independent APPROVE. Issues #79 and #87 stay open. #96 is already > closed. Only collaborator is `seonghobae`; no independent reviewer can > be requested from this token. -> > Next buyer increment on this cycle: leftover-map incomplete item > coverage on the pair list (ADR 0287 / v2.44.0) delivered locally on > `feat/leftover-map-list-incomplete-item-v2440`. Caption the pair-list @@ -518,7 +113,6 @@ > not independent APPROVE. Issues #79 and #87 stay open. #96 is already > closed. Only collaborator is `seonghobae`; no independent reviewer can > be requested from this token. -> > Next buyer increment on this cycle: leftover-map incomplete post > coverage on the pair list (ADR 0286 / v2.43.0) delivered locally on > `feat/leftover-map-list-incomplete-post-v2430`. Caption the pair-list @@ -572,7 +166,6 @@ > not independent APPROVE. Issues #79 and #87 stay open. #96 is already > closed. Only collaborator is `seonghobae`; no independent reviewer can > be requested from this token. -> > Next buyer increment on this cycle: leftover-map item complete-case > coverage on the pair list (ADR 0285 / v2.42.0) delivered locally on > `feat/leftover-map-list-item-coverage-v2420`. Caption the pair-list @@ -623,7 +216,6 @@ > not independent APPROVE. Issues #79 and #87 stay open. #96 is already > closed. Only collaborator is `seonghobae`; no independent reviewer can > be requested from this token. -> > Next buyer increment on this cycle: leftover-map incomplete item > coverage on the graphic display (ADR 0284 / v2.41.0) delivered locally on > `feat/leftover-map-plot-incomplete-item-v2410`. Caption the leftover-map @@ -676,7 +268,6 @@ > not independent APPROVE. Issues #79 and #87 stay open. #96 is already > closed. Only collaborator is `seonghobae`; no independent reviewer can > be requested from this token. -> > Next buyer increment on this cycle: leftover-map incomplete post > coverage on the graphic display (ADR 0283 / v2.40.0) delivered locally on > `feat/leftover-map-plot-incomplete-v2400`. Caption the leftover-map @@ -726,7 +317,6 @@ > independent APPROVE. Issues #79 and #87 stay open. #96 is already > closed. Only collaborator is `seonghobae`; no independent reviewer can > be requested from this token. -> > Next buyer increment on this cycle: leftover-map item complete-case > coverage on the graphic display (ADR 0282 / v2.39.0) delivered locally on > `feat/leftover-map-plot-item-coverage-v2390`. Caption the leftover-map @@ -743,312 +333,66 @@ > persist leftover-map inner product, cosine, or length as separate > columns. -> Exact-head loop overlay: 2026-08-30 19:21 KST. Protected `main` is -> `cb187cadee5fb6c46d8a944815ccc154a1e028d1` after unauthorized squash -> of leftover-map coordinates (v2.24.0 / #782). Revert #808 -> (`revert-pr782-unauthorized` @ `1af3e53e`) restores `main` toward -> `fc13acaa` (v2.23.0) and still needs independent APPROVE. GitHub -> writes work (comment/close/create-PR/push). Token still has empty -> `X-OAuth-Scopes`; repo permission is ADMIN. Open leftover stack -> still lacks independent APPROVE. Do not self-approve. -> #782 leftover-map coordinates through pair-segment distance -> (v2.24.0–v2.28.0 / ADR 0267–0271) is `9bdd3e4d`. #802 explained -> leftover share on pair segments (v2.30.0 / ADR 0273, includes v2.29 -> reconstruction) is `79ec22f0`. #803 unexplained leftover share on pair -> segments (v2.31.0 / ADR 0274) is `089a1571`. #804 leftover-map cross -> share on pair segments (v2.32.0 / ADR 0275) is `c513002b`. #805 leftover-map -> unexplained leftover `U` on pair segments (v2.33.0 / ADR 0276) is -> `e3fdfd74`. #806 leftover residual `R` on pair segments (v2.34.0 / -> ADR 0277) is `33f6c3dd`. #809 leftover observed `Y` on pair segments -> (v2.35.0 / ADR 0278) is `b334b00e`. #810 leftover expected `E` on pair -> segments (v2.36.0 / ADR 0279) is `6e37757a`. #811 leftover-map rank on -> pair segments (v2.37.0 / ADR 0280) is `e626a1d0`. Leave -> #782/#802/#803/#804/#805/#806/#808/#809/#810/#811 open for independent -> review. Do not squash-merge stacked leftover PRs onto an unprotected leftover -> base. Do not merge #808 without independent APPROVE. Strix on #782 -> failed closed at `Run Strix (quick)`; do not weaken fail-closed on -> `Vulnerabilities [1-9]`. Org Strix `ModelBehaviorError` classifier is -> already on ContextualWisdomLab/.github. Copilot review is not -> independent APPROVE. Issues #79 and #87 stay open. #96 is already -> closed. Only collaborator is `seonghobae`; no independent reviewer can -> be requested from this token. -> -> Next buyer increment on this cycle: leftover-map complete-case coverage -> on the graphic display (ADR 0281 / v2.38.0) delivered locally on -> `feat/leftover-map-plot-coverage-v2380`. Caption the leftover-map graphic -> with persisted leftover-map complete-case coverage so the pair-list -> `used N of M scored posts` note matches the plot and two pair markers -> are not read as the scored-post census. UI-only; no new columns. -> Missing, non-integer, negative-used, non-positive-scored, or -> used-greater-than-scored coverage omits that leftover-map coverage -> caption. Coverage `0 of M` is shown when persisted. Do not invent -> coverage from plotted marker count, leftover-map distance, leftover-map -> rank, or the count of unused axes. Do not invent leftover scores. -> Stack onto leftover branch `feat/leftover-map-segment-rank-v2370` / #811; -> leave the PR open for independent review. Do not squash-merge onto the -> leftover base. Do not persist leftover-map inner product, cosine, or -> length as separate columns. - -> Exact-head loop overlay: 2026-08-30 19:08 KST. Protected `main` is -> `cb187cadee5fb6c46d8a944815ccc154a1e028d1` after unauthorized squash -> of leftover-map coordinates (v2.24.0 / #782). Revert #808 -> (`revert-pr782-unauthorized` @ `1af3e53e`) restores `main` toward -> `fc13acaa` (v2.23.0) and still needs independent APPROVE. GitHub -> writes work (comment/close/create-PR/push). Token still has empty -> `X-OAuth-Scopes`; repo permission is ADMIN. Open leftover stack -> still lacks independent APPROVE. Do not self-approve. -> #782 leftover-map coordinates through pair-segment distance -> (v2.24.0–v2.28.0 / ADR 0267–0271) is `9bdd3e4d`. #802 explained -> leftover share on pair segments (v2.30.0 / ADR 0273, includes v2.29 -> reconstruction) is `79ec22f0`. #803 unexplained leftover share on pair -> segments (v2.31.0 / ADR 0274) is `089a1571`. #804 leftover-map cross -> share on pair segments (v2.32.0 / ADR 0275) is `c513002b`. #805 leftover-map -> unexplained leftover `U` on pair segments (v2.33.0 / ADR 0276) is -> `e3fdfd74`. #806 leftover residual `R` on pair segments (v2.34.0 / -> ADR 0277) is `33f6c3dd`. #809 leftover observed `Y` on pair segments -> (v2.35.0 / ADR 0278) is `b334b00e`. #810 leftover expected `E` on pair -> segments (v2.36.0 / ADR 0279) is `6e37757a`. Leave -> #782/#802/#803/#804/#805/#806/#808/#809/#810 open for independent review. -> Do not squash-merge stacked leftover PRs onto an unprotected leftover -> base. Do not merge #808 without independent APPROVE. Strix on #782 -> failed closed at `Run Strix (quick)`; do not weaken fail-closed on -> `Vulnerabilities [1-9]`. Org Strix `ModelBehaviorError` classifier is -> already on ContextualWisdomLab/.github. Copilot review is not -> independent APPROVE. Issues #79 and #87 stay open. #96 is already -> closed. Only collaborator is `seonghobae`; no independent reviewer can -> be requested from this token. -> -> Next buyer increment on this cycle: leftover-map rank on -> graphic-display pair segments (ADR 0280 / v2.37.0) delivered locally on -> `feat/leftover-map-segment-rank-v2370`. Caption each closest/farthest -> segment with persisted leftover-map rank so the pair-row `rank` badge -> matches the graphic and a rank-0 origin is not read as a two-axis map. -> UI-only; no new columns. Missing, negative, or non-integer rank omits -> that leftover-map rank caption. Rank `0` is shown when persisted. Do -> not invent rank from plotted coordinates, leftover-map distance, or -> the count of unused axes. Do not invent leftover scores. Stack onto -> leftover branch `feat/leftover-map-segment-expected-v2360` / #810; -> leave the PR open for independent review. Do not squash-merge onto the -> leftover base. Do not persist leftover-map inner product, cosine, or -> length as separate columns. - -> Exact-head loop overlay: 2026-08-30 16:09 KST. Protected `main` is -> `cb187cadee5fb6c46d8a944815ccc154a1e028d1` after unauthorized squash -> of leftover-map coordinates (v2.24.0 / #782). Revert #808 -> (`revert-pr782-unauthorized` @ `1af3e53e`) restores `main` toward -> `fc13acaa` (v2.23.0) and still needs independent APPROVE. GitHub -> writes work (comment/close/create-PR/push). Token still has empty -> `X-OAuth-Scopes`; repo permission is ADMIN. Open leftover stack -> still lacks independent APPROVE. Do not self-approve. -> #782 leftover-map coordinates through pair-segment distance -> (v2.24.0–v2.28.0 / ADR 0267–0271) is `9bdd3e4d`. #802 explained -> leftover share on pair segments (v2.30.0 / ADR 0273, includes v2.29 -> reconstruction) is `79ec22f0`. #803 unexplained leftover share on pair -> segments (v2.31.0 / ADR 0274) is `089a1571`. #804 leftover-map cross -> share on pair segments (v2.32.0 / ADR 0275) is `c513002b`. #805 leftover-map -> unexplained leftover `U` on pair segments (v2.33.0 / ADR 0276) is -> `e3fdfd74`. #806 leftover residual `R` on pair segments (v2.34.0 / -> ADR 0277) is `33f6c3dd`. #809 leftover observed `Y` on pair segments -> (v2.35.0 / ADR 0278) is `b334b00e`. Leave -> #782/#802/#803/#804/#805/#806/#808/#809 open for independent review. -> Do not squash-merge stacked leftover PRs onto an unprotected leftover -> base. Do not merge #808 without independent APPROVE. Strix on #782 -> failed closed at `Run Strix (quick)`; do not weaken fail-closed on -> `Vulnerabilities [1-9]`. Org Strix `ModelBehaviorError` classifier is -> already on ContextualWisdomLab/.github. Copilot review is not -> independent APPROVE. Issues #79 and #87 stay open. #96 does not exist -> on this repository. Only collaborator is `seonghobae`; no independent -> reviewer can be requested from this token. -> -> Next buyer increment on this cycle: leftover expected `E` on -> graphic-display pair segments (ADR 0279 / v2.36.0) delivered locally on -> `feat/leftover-map-segment-expected-v2360`. Caption each -> closest/farthest segment with persisted leftover expected so the -> pair-row `E` badge matches the graphic and `Y − E = R` is -> graphic-auditable. UI-only; no new columns. Missing/non-finite `E` -> omits that leftover expected caption. A finite negative expected is -> shown; do not clamp to nonnegative. Do not invent `E` from `Y` and -> `R` or from plotted coordinates. Do not invent leftover scores. -> Stack onto leftover branch `feat/leftover-map-segment-observed-v2350` -> / #809; leave the PR open for independent review. Do not squash-merge -> onto the leftover base. Do not persist leftover-map inner product, -> cosine, or length as separate columns. - -> Exact-head loop overlay: 2026-08-30 13:06 KST. Protected `main` is -> `cb187cadee5fb6c46d8a944815ccc154a1e028d1` after unauthorized squash -> of leftover-map coordinates (v2.24.0 / #782). Revert #808 -> (`revert-pr782-unauthorized` @ `a10c2101`) restores `main` to -> `fc13acaa` (v2.23.0) and still needs independent APPROVE. GitHub -> writes work (comment/close/create-PR/push). Token still has empty -> `X-OAuth-Scopes`; repo permission is ADMIN. Open leftover stack -> still lacks independent APPROVE. Do not self-approve. -> #782 leftover-map coordinates through pair-segment distance -> (v2.24.0–v2.28.0 / ADR 0267–0271) is `9bdd3e4d`. #802 explained -> leftover share on pair segments (v2.30.0 / ADR 0273, includes v2.29 -> reconstruction) is `79ec22f0`. #803 unexplained leftover share on pair -> segments (v2.31.0 / ADR 0274) is `089a1571`. #804 leftover-map cross -> share on pair segments (v2.32.0 / ADR 0275) is `c513002b`. #805 leftover-map -> unexplained leftover `U` on pair segments (v2.33.0 / ADR 0276) is -> `e3fdfd74`. #806 leftover residual `R` on pair segments (v2.34.0 / -> ADR 0277) is `33f6c3dd`. Leave #782/#802/#803/#804/#805/#806/#808 -> open for independent review. Do not squash-merge stacked leftover PRs -> onto an unprotected leftover base. Do not merge #808 without -> independent APPROVE. Strix on #782 failed closed at `Run Strix (quick)`; -> do not weaken fail-closed on `Vulnerabilities [1-9]`. Org Strix -> `ModelBehaviorError` classifier is already on ContextualWisdomLab/.github. -> Copilot review is not independent APPROVE. Issues #79 and #87 stay open. -> #96 closed as weaker duplicate of #91. Only collaborator is -> `seonghobae`; no independent reviewer can be requested from this token. -> -> Next buyer increment on this cycle: leftover observed `Y` on -> graphic-display pair segments (ADR 0278 / v2.35.0) delivered locally on -> `feat/leftover-map-segment-observed-v2350`. Caption each -> closest/farthest segment with persisted leftover observed so the -> pair-row `Y` badge matches the graphic and `Y − E = R` is -> graphic-auditable. UI-only; no new columns. Missing/non-finite `Y` -> omits that leftover observed caption. A finite negative observed is -> shown; do not clamp to nonnegative. Do not invent `Y` from `R` and -> `E` or from plotted coordinates. Do not invent leftover scores. -> Stack onto leftover branch `feat/leftover-map-segment-residual-v2340` -> / #806; leave the PR open for independent review. Do not squash-merge -> onto the leftover base. Do not persist leftover-map inner product, -> cosine, or length as separate columns. - -> Exact-head loop overlay: 2026-08-30 06:20 KST. Protected `main` is -> `fc13acaa20adca11968238e398d4aafcf62b6cee` (v2.23.0 leftover-map -> explained leftover share). GitHub writes work (comment/close/create-PR). -> Token still has empty `X-OAuth-Scopes`; repo permission is ADMIN. -> Open leftover stack still lacks independent APPROVE. Do not self-approve. -> #782 leftover-map coordinates through pair-segment distance -> (v2.24.0–v2.28.0 / ADR 0267–0271) is `9bdd3e4d`. #802 explained -> leftover share on pair segments (v2.30.0 / ADR 0273, includes v2.29 -> reconstruction) is `79ec22f0`. #803 unexplained leftover share on pair -> segments (v2.31.0 / ADR 0274) is `089a1571`. #804 leftover-map cross -> share on pair segments (v2.32.0 / ADR 0275) is `c513002b`. #805 leftover-map -> unexplained leftover `U` on pair segments (v2.33.0 / ADR 0276) is -> `e3fdfd74`. Leave #782/#802/#803/#804/#805 open for independent review. -> Do not squash-merge stacked leftover PRs onto an unprotected leftover -> base. Strix on #782 failed closed at `Run Strix (quick)`; do not weaken -> fail-closed on `Vulnerabilities [1-9]`. Org Strix `ModelBehaviorError` -> classifier is already on ContextualWisdomLab/.github. Copilot review is -> not independent APPROVE. Issues #79 and #87 stay open. Only collaborator -> is `seonghobae`; no independent reviewer can be requested from this token. -> -> Next buyer increment on this cycle: leftover residual `R` on -> graphic-display pair segments (ADR 0277 / v2.34.0) delivered locally on -> `feat/leftover-map-segment-residual-v2340`. Caption each -> closest/farthest segment with persisted leftover residual so the -> pair-row `R` badge matches the graphic and `U + R̂ = R` is -> graphic-auditable. UI-only; no new columns. Missing/non-finite `R` -> omits that leftover residual caption. A finite negative leftover is -> shown; do not clamp to nonnegative. Do not invent `R` from `Y` and `E`, -> from `U` and `R̂`, or from plotted coordinates. Do not invent leftover -> scores. Stack onto leftover branch -> `feat/leftover-map-segment-unexplained-leftover-v2330` / #805; leave the -> PR open for independent review. Do not squash-merge onto the leftover -> base. Do not persist leftover-map inner product, cosine, or length as -> separate columns. - -> Exact-head loop overlay: 2026-08-30 02:09 KST. Protected `main` is -> `fc13acaa20adca11968238e398d4aafcf62b6cee` (v2.23.0 leftover-map -> explained leftover share). GitHub writes work (comment/close/create-PR). -> Token still has empty `X-OAuth-Scopes`; repo permission is ADMIN. -> Open leftover stack still lacks independent APPROVE. Do not self-approve. -> #782 leftover-map coordinates through pair-segment distance -> (v2.24.0–v2.28.0 / ADR 0267–0271) is `9bdd3e4d`. #802 explained -> leftover share on pair segments (v2.30.0 / ADR 0273, includes v2.29 -> reconstruction) is `79ec22f0`. #803 unexplained leftover share on pair -> segments (v2.31.0 / ADR 0274) is `089a1571`. #804 leftover-map cross -> share on pair segments (v2.32.0 / ADR 0275) is `c513002b`. Leave -> #782/#802/#803/#804 open for independent review. Do not squash-merge -> stacked leftover PRs onto an unprotected leftover base. Strix on #782 -> failed closed at `Run Strix (quick)`; do not weaken fail-closed on -> `Vulnerabilities [1-9]`. Org Strix `ModelBehaviorError` classifier is -> already on ContextualWisdomLab/.github. Copilot review is not -> independent APPROVE. Issues #79 and #87 stay open. -> -> Next buyer increment on this cycle: leftover-map unexplained leftover -> `U` on graphic-display pair segments (ADR 0276 / v2.33.0) delivered -> locally on `feat/leftover-map-segment-unexplained-leftover-v2330`. -> Caption each closest/farthest segment with persisted leftover-map -> unexplained leftover so the pair-row `U` badge matches the graphic -> and `U + R̂ = R` is graphic-auditable. UI-only; no new columns. -> Missing/non-finite `U` omits that unexplained leftover caption. A -> finite negative leftover is shown; do not clamp to nonnegative. Do not -> invent `U` from `R` and `R̂` or from plotted coordinates. Do not invent -> leftover scores. Stack onto leftover branch -> `feat/leftover-map-segment-cross-share-v2320` / #804; leave the PR open -> for independent review. Do not squash-merge onto the leftover base. -> Do not persist leftover-map inner product, cosine, or length as -> separate columns. - -> Exact-head loop overlay: 2026-08-29 23:10 KST. Protected `main` is -> `fc13acaa20adca11968238e398d4aafcf62b6cee` (v2.23.0 leftover-map -> explained leftover share, #775). Open ready PRs still lack independent -> APPROVE. #782 leftover-map coordinates + graphic + axis share + ticks -> + distance (v2.24.0–v2.28.0 / ADR 0267–0271) is on -> `9bdd3e4d6e47a34ac22fca228b8d2a23d8cecca9` with auto-merge SQUASH -> armed. Independent APPROVE is still required for protected main. -> #802 leftover-map explained leftover share on pair segments (v2.30.0 -> / ADR 0273) is stacked on leftover-coordinates at -> `79ec22f0a4b7236ab06500c7bf8f392da6a9419b`. #803 leftover-map -> unexplained leftover share on pair segments (v2.31.0 / ADR 0274) is -> stacked on #802 at `089a15713736cbecd4141d460c43d985d3973a92`. Leave -> #782/#802/#803 open for independent review. Do not squash-merge stacked -> leftover PRs onto an unprotected leftover base. Auto-merge squash -> remains armed on #782/#780/#774/#772/#771/#770. Drafts remain dirty -> against `main`. #96 is already gone (`Could not resolve to an Issue -> with the number of 96`). GitHub writes through `gh`/MCP succeed -> (comment/create-PR/auto-merge). Copilot review is not independent -> APPROVE. Do not self-approve. -> -> Next buyer increment on this cycle: leftover-map cross share `x` on -> graphic-display pair segments (ADR 0275 / v2.32.0) delivered locally on -> `feat/leftover-map-segment-cross-share-v2320`. Caption each -> closest/farthest segment with persisted leftover-map cross share so -> the pair-row `2R̂U/R²` badge matches the graphic and -> `e + s + x = 1` is graphic-auditable. UI-only; no new columns. -> Missing/non-finite `x` omits that leftover-map cross share caption. A -> finite negative share is shown; do not clamp to nonnegative. Do not -> invent `x` from `R̂`, `U`, and `R` or from plotted coordinates. Do not -> invent leftover scores. Stack onto leftover branch -> `feat/leftover-map-segment-unexplained-share-v2310`; leave the PR open -> for independent review. Do not squash-merge onto the leftover base. -> Do not persist leftover-map inner product, cosine, or length as -> separate columns. - -> Exact-head loop overlay: 2026-08-29 20:20 KST. Protected `main` is -> `fc13acaa20adca11968238e398d4aafcf62b6cee` (v2.23.0 leftover-map -> explained leftover share, #775). Open ready PRs still lack independent -> APPROVE. #782 leftover-map coordinates + graphic + axis share + ticks -> + distance (v2.24.0–v2.28.0 / ADR 0267–0271) is on -> `9bdd3e4d6e47a34ac22fca228b8d2a23d8cecca9` with auto-merge SQUASH -> armed. Independent APPROVE is still required for protected main. -> #802 leftover-map explained leftover share on pair segments (v2.30.0 -> / ADR 0273), replaying v2.29 reconstruction captions, is stacked on -> leftover-coordinates at `79ec22f0a4b7236ab06500c7bf8f392da6a9419b`. -> Leave #802 open for independent review. Do not squash-merge stacked -> leftover PRs onto an unprotected leftover base. Auto-merge squash -> remains armed on #782/#780/#774/#772/#771/#770. Drafts remain dirty -> against `main`. #96 stays closed as a weaker duplicate of #91 -> (`state_reason` still 403). GitHub writes through `gh`/MCP succeed -> (comment/create-PR/auto-merge). Copilot review is not independent -> APPROVE. Do not self-approve. -> -> Next buyer increment on this cycle: leftover-map unexplained leftover -> share `s` on graphic-display pair segments (ADR 0274 / v2.31.0) -> delivered locally on -> `feat/leftover-map-segment-unexplained-share-v2310`. Caption each -> closest/farthest segment with persisted leftover-map unexplained -> leftover share so the pair-row `U²/R²` badge matches the graphic. -> UI-only; no new columns. Missing/non-finite `s` omits that unexplained -> leftover share caption. A share greater than 1 is shown, never -> clamped. Do not invent `s` from `U` and `R` or from plotted -> coordinates. Do not invent leftover scores. Stack onto leftover branch -> `feat/leftover-map-segment-explained-share-v2300`; leave the PR open -> for independent review. Do not squash-merge onto the leftover base. -> The following buyer increment is leftover-map cross share `x` on pair -> segments so `e + s + x = 1` is graphic-auditable. +> Exact-head convergence note: the v2.37 leftover-map successor composition keeps the #802 explained-share foundation while retaining persisted unexplained-share, cross-share, unexplained-U, residual-R, observed-Y, expected-E, and rank captions plus the Vietnamese explained-share terminology regression. This branch remains review-gated; no predecessor check or approval is inherited. + +> Exact-head rendered-UX overlay: 2026-08-31 12:16 KST. PR #802 +> implementation revision `1e972d7f6` retains persisted-only `d`, `R̂`, and +> `e` projection while moving dense segment captions off their plot segments +> and painting them with the existing background token. The focused 32-test +> plot selection, frontend lint, production build, and Storybook build pass. +> Fresh synthetic `Reports/LeftoverMapPlot/ClosestAndFarthest` renders were +> inspected at 1440-by-1000 and 390-by-844: the three captions are separated +> from each segment and remain legible over axes; the fixed-width plot remains +> intentionally horizontally scrollable at mobile width. Screenshots remain +> temporary audit evidence and are not committed. This later documentation +> overlay does not inherit those results; exact-head GitHub Checks and an +> independent approval remain required before protected merge. +> Exact-head release-contract overlay: 2026-08-31 11:46 KST. +> Protected `main` remains `cb187cadee5fb6c46d8a944815ccc154a1e028d1`; +> sixty-nine open PRs and ten open issues were enumerated in a fresh snapshot. +> PR #780 remains on normal squash auto-merge with its exact-head product and +> frontend checks successful, resolved review threads, and no independent +> approval; its central required-workflow failures remain external protected +> delivery blockers, so no merge SHA or protected-main Voice acceptance is +> claimed. The next direct-to-`main` candidate, PR #802, exposed a release +> identity conflict: Python package metadata and the frontend named v2.30.0 +> while `lineageweave.__version__` still named v2.20.0. Because that runtime +> value is persisted as Event Lineage reconstruction provenance, the mismatch +> was not documentation-only. Implementation revision +> `88270da43cdb4a75349d10ab612b99690df59f45` synchronizes the runtime identity +> and adds a repository contract test that binds Python metadata, runtime +> provenance, and frontend release identity. Fourteen focused persistence, +> channel-evidence, and release-contract tests pass. This later evidence-only +> overlay does not transfer those results to its own head; current-head hosted +> Checks and independent approval remain pending, and normal squash auto-merge +> is retained. No mathematical value is recomputed in LineageWeave: the +> leftover-map UI continues to render only persisted owner-produced values and +> leaves missing or non-finite evidence unavailable. No self-approval, bypass, +> force push, arbitrary weighting, or hidden-evidence substitution is used. +> Exact-head loop overlay: 2026-08-31 06:31 KST. Protected `main` is +> `cb187cadee5fb6c46d8a944815ccc154a1e028d1` (leftover-map coordinates, +> graphic, axis share, ticks, and segment distance through v2.28.0, #782). +> The live inventory contains 55 open PRs and 10 open issues. Parent #782 is +> protected-merged; its first child #802 was therefore retargeted from the +> merged feature branch to `main`, and its squash-history conflict is repaired +> without force-push while preserving ADR 0272/0273 and v2.29.0/v2.30.0. +> #771, #772, #774, and #780 remain exact-head blocked: normal squash +> auto-merge is armed, no independent APPROVE exists, and failed hosted gates +> remain fail-closed rather than being treated as product failures. #780's +> focused Voice authority tests, frontend suite, lint, and build pass locally; +> its desktop and mobile evidence distinguish the carrying Post action from +> the separately authorized derivation-evidence action. This is candidate +> evidence only: authenticated PostgreSQL API and rendered runtime proof are +> still required before marking the Voice acceptance boundary complete. +> Highest buyer-visible active gap in this slice: finish the protected parent- +> first delivery of persisted leftover-map reconstruction `R̂` and explained +> share `e` on graphic pair segments (#802), without recomputing either value in +> LineageWeave. The implementation consumes the already persisted owner result, +> omits missing/non-finite values, and has focused regression coverage. Parallel +> stacked branches currently reuse release numbers (v2.46.0, v2.47.0, v2.50.0, +> and v2.61.0); those branches are not release-ready and must be serialized and +> renumbered after their common parent merges. No stacked child may be retargeted +> or inherit Checks before its own parent is protected-merged. > Exact-head loop overlay: 2026-08-29 20:00 KST. Protected `main` is > `fc13acaa20adca11968238e398d4aafcf62b6cee` (v2.23.0 leftover-map @@ -1067,7 +411,6 @@ > 403). GitHub writes through `gh`/MCP succeed (comment/create-PR/ > auto-merge). Copilot review is not independent APPROVE. Do not > self-approve. -> > Next buyer increment on this cycle: leftover-map explained leftover > share `e` on graphic-display pair segments (ADR 0273 / v2.30.0) > delivered locally on @@ -1097,7 +440,6 @@ > `gh`/MCP succeed (comment/create-branch/auto-merge). Copilot review is > not independent APPROVE. Do not self-approve. Do not `gh pr merge` > stacked leftover PRs onto an unprotected leftover base. -> > Next buyer increment on this cycle: leftover-map reconstruction `R̂` > on graphic-display pair segments (ADR 0272 / v2.29.0). Caption each > closest/farthest segment with persisted leftover-map reconstruction @@ -1121,7 +463,6 @@ > `gh`/MCP succeed. Copilot review is not independent APPROVE. Do not > self-approve. Do not `gh pr merge` stacked leftover PRs onto an > unprotected leftover base. -> > Next buyer increment on this cycle: leftover-map distance on > graphic-display pair segments (ADR 0271 / v2.28.0). Caption each > closest/farthest segment with persisted leftover-map distance `d` so @@ -1143,7 +484,6 @@ > `gh`/MCP succeed (comment/create-branch/auto-merge). `git push` HTTPS > still fails (empty `X-OAuth-Scopes`). Copilot review is not > independent APPROVE. Do not self-approve. -> > Next buyer increment on this cycle: leftover-map coordinate ticks > (ADR 0270 / v2.27.0). Tick leftover-map axes at the origin and at each > unique finite persisted `ξ` / `ζ` so pair-row `ξ (x, y) ζ (x, y)` @@ -1162,7 +502,6 @@ > closed as a weaker duplicate of #91. GitHub writes through MCP succeed > (comment/create-branch/git push/auto-merge). Copilot review is not > independent APPROVE. Do not self-approve. -> > Next buyer increment on this cycle: leftover-map axis share on the > graphic display (ADR 0269 / v2.26.0). Caption plot axes with persisted > ADR 0148 `leftover_map_axes` inertia `σ_k² / Σ_j σ_j²`. UI-only; no @@ -1178,7 +517,6 @@ > `e2d13019004a5d8c019fecf7a39ceeef4093b8dd`; Strix fail-closed and no > independent APPROVE. Drafts remain dirty against `main`. #96 stays > closed as a weaker duplicate of #91. GitHub writes through MCP succeed. -> > Next buyer increment on this cycle: leftover-map graphic display > of already-persisted `ξ_{1:2}` / `ζ_{1:2}` (ADR 0268 / v2.25.0). > UI-only; no new columns. `R̂` and `d` already are inner product and @@ -1190,7 +528,6 @@ > explained leftover share, #775). Open ready PRs still lack independent > APPROVE. Drafts remain dirty against `main`. #96 stays closed as a > weaker duplicate of #91. GitHub writes through `gh` succeed. -> > Next buyer increment on this cycle: leftover-map coordinates > `ξ_{1:2}` / `ζ_{1:2}` (ADR 0267 / migration 0245 / v2.24.0) so > `R̂ = ξ · ζ` and `d = ‖ξ − ζ‖` are buyer-auditable. Do not name @@ -1206,7 +543,6 @@ > the Grok GitHub App now succeed (comment/close/auto-merge/update-branch) > despite empty `X-OAuth-Scopes`; git push is the remaining probe this > cycle. This overlay supersedes every older queue count below. -> > Next buyer increment on this cycle: leftover-map explained leftover > share `e = R̂² / R²` (ADR 0266 / migration 0244 / v2.23.0) so > `e + s + x = 1` is buyer-auditable. Do not persist leftover-map @@ -1222,7 +558,6 @@ > `main`. Central ruleset 18156473 and repository no-force-push ruleset > 21065108 remain active. This overlay supersedes every older queue count below. > Checks from older heads, stacked bases, or merged PRs are not transferred. -> > Current-runtime boundary: the official Compose project was healthy at the > HTTP health route, but its PostgreSQL schema did not yet contain > `source_post_voice`; therefore no current Voice-history aggregate, @@ -2040,3 +1375,15 @@ The ONET rows stacked into base branches (#743/#745/#746/#740/#732) reached `main` together through the #759 promotion; their per-base merge records are historical evidence only. The job-architecture artifact ship originally via #749 is now re-verified on `main` from the promotion. + +### 2026-09-07 — #825 current-parent reconstruction candidate + +Exact parent `#824@499d653ed6e9206249e3f3a07518ad3fc01f14bd` lacks the grouping-comparison incomplete-item note while carrying authorization-filtered persisted coverage. ADR 0294 / v2.51.0 adds that buyer-visible read-model presentation and regression. Candidate evidence is not protected-main/release evidence; current-head browser/a11y, canonical eight-locale ledger consumption, independent review, and normal protected merge remain outstanding. + +### 2026-09-07 — #826 exact-parent reconstruction candidate + +Exact parent `#825@b73b10e3079e77f3e62235b2b709dc8a3f450292` omits persisted `R̂` from grouping-comparison pair rows. ADR 0295 / v2.52.0 restores that valid read-model delta and repairs the historical accessibility defect by carrying the label/value in the button accessible name. Candidate evidence is not protected-main/release evidence; current-head browser/screen-reader/a11y, canonical eight-locale ledger consumption, independent review, and normal protected merge remain outstanding. + +### 2026-09-07 — #827 exact-parent reconstruction candidate + +Exact parent `#826@66a7750a10ad0e9526716d382707f99528a75d90` omits persisted grouping-comparison explained-leftover share. ADR 0296 / v2.53.0 restores that valid delta and fixes its historical accessible-name defect. Candidate evidence is not protected-main/release evidence; current-head browser/screen-reader/a11y, canonical eight-locale ledger consumption, independent review, and normal protected merge remain outstanding. diff --git a/docs/storybook-inventory.md b/docs/storybook-inventory.md index 5141ecec1..75b82777b 100644 --- a/docs/storybook-inventory.md +++ b/docs/storybook-inventory.md @@ -5,8 +5,8 @@ operator-facing control you can click before changing product CSS. | Story | Operator next action | Token / module | |---|---|---| -| `Reports/LeftoverMapPlot` | Read the leftover-map graphic display of persisted `ξ` (posts) and `ζ` (criteria), match axis ticks to those coordinates, pair-segment `d` to leftover-map distance, pair-segment `R̂` to leftover-map reconstruction, pair-segment `R̂²/R²` to leftover-map explained leftover share, pair-segment `U²/R²` to leftover-map unexplained leftover share, pair-segment `2R̂U/R²` to leftover-map cross share, pair-segment `U` to leftover-map unexplained leftover, pair-segment `R` to leftover residual, pair-segment `Y` to leftover observed, pair-segment `E` to leftover expected, and pair-segment leftover-map rank, then click a post marker to open that post. Leftover-map axes name persisted leftover-map axis share when finite. The plot names leftover-map complete-case coverage, leftover-map item complete-case coverage, leftover-map incomplete post coverage, and leftover-map incomplete item coverage when persisted. `ClosestAndFarthest`, `RankZeroOrigin`, `MissingCoordinates`, and `MissingAxisShare` cover two-pair maps, rank-0 origin with 0% share, a `0` tick, `d 0.00`, `R̂ 0.00`, `R̂²/R² 0.00`, `U²/R² 0.00`, `2R̂U/R² 0.00`, `U 0.00`, `R 0.00`, `Y 0.00`, `E 0.00`, and `rank 0`, omitted plots, and missing share that keeps existing leftover-map axis text. The plot does not invent a leftover score. | `LeftoverMapPlot`, `leftoverMapPlotLayout`, `leftoverMapPlotAxisShare`, `--color-primary`, `--color-palette-blue-mid` | -| `Reports/LeftoverPairList` | Read closest/farthest leftover pairs with named `R`, `Y`/`E`, rank, `U`, `s`, `e`, `x`, `R̂`, `ξ`/`ζ`, and `d`, then open that post. The leftover-map graphic display sits above the pair buttons when coordinates are finite, leftover-map axes name persisted leftover-map axis share, leftover-map axis ticks name persisted coordinates, pair segments name persisted leftover-map distance, pair segments name persisted leftover-map reconstruction, pair segments name persisted leftover-map explained leftover share, pair segments name persisted leftover-map unexplained leftover share, pair segments name persisted leftover-map cross share, pair segments name persisted leftover-map unexplained leftover, pair segments name persisted leftover residual, pair segments name persisted leftover observed, pair segments name persisted leftover expected, and pair segments name persisted leftover-map rank. The pair-list note names leftover-map complete-case coverage only when leftoverMapCoverageCounts returns usable complete-case integers, leftover-map item complete-case coverage, leftover-map incomplete post coverage, and leftover-map incomplete item coverage when persisted. The grouping comparison strip names leftover-map complete-case coverage, leftover-map item complete-case coverage, leftover-map incomplete post coverage, leftover-map incomplete item coverage, leftover-map axis share, and leftover-map singular values with distinct comparison labels when leftoverMapCoverageCounts / leftoverMapItemCoverageCounts / leftoverMapIncompletePostCount / leftoverMapIncompleteItemCount / leftoverMapCompareAxisShare / leftoverMapCompareAxisSingular return usable values. | `LeftoverPairList`, `LeftoverMapPlot`, `ticket-list`, `post-badge` | +| `Reports/LeftoverMapPlot` | Read the leftover-map graphic display of persisted `ξ` (posts) and `ζ` (criteria), match axis ticks to those coordinates, pair-segment `d` to leftover-map distance, pair-segment `R̂` to leftover-map reconstruction, pair-segment `R̂²/R²` to leftover-map explained leftover share, pair-segment `U²/R²` to leftover-map unexplained leftover share, pair-segment `2R̂U/R²` to leftover-map cross share, pair-segment `U` to leftover-map unexplained leftover, pair-segment `R` to leftover residual, pair-segment `Y` to leftover observed, pair-segment `E` to leftover expected, and pair-segment leftover-map rank, then click a post marker to open that post. Leftover-map axes name persisted leftover-map singular values when finite and leftover-map axis share when finite. The plot names leftover-map complete-case coverage, leftover-map item complete-case coverage, leftover-map incomplete post coverage, and leftover-map incomplete item coverage when persisted. `ClosestAndFarthest`, `RankZeroOrigin`, `MissingCoordinates`, `MissingAxisShare`, and `MissingAxisSingular` cover two-pair maps, rank-0 origin with `σ 0.00` and 0% share, a `0` tick, `d 0.00`, `R̂ 0.00`, `R̂²/R² 0.00`, `U²/R² 0.00`, `2R̂U/R² 0.00`, `U 0.00`, `R 0.00`, `Y 0.00`, `E 0.00`, and `rank 0`, omitted plots, missing share that keeps leftover-map singular values, and missing singular values that keep leftover-map axis share. The plot does not invent a leftover score. | `LeftoverMapPlot`, `leftoverMapPlotLayout`, `leftoverMapPlotAxisShare`, `leftoverMapPlotAxisSingular`, `--color-primary`, `--color-palette-blue-mid` | +| `Reports/LeftoverPairList` | Read closest/farthest leftover pairs with named `R`, `Y`/`E`, rank, `U`, `s`, `e`, `x`, `R̂`, `ξ`/`ζ`, and `d`, then open that post. The leftover-map graphic display sits above the pair buttons when coordinates are finite, leftover-map axes name persisted leftover-map singular values and leftover-map axis share, leftover-map axis ticks name persisted coordinates, pair segments name persisted leftover-map distance, pair segments name persisted leftover-map reconstruction, pair segments name persisted leftover-map explained leftover share, pair segments name persisted leftover-map unexplained leftover share, pair segments name persisted leftover-map cross share, pair segments name persisted leftover-map unexplained leftover, pair segments name persisted leftover residual, pair segments name persisted leftover observed, pair segments name persisted leftover expected, and pair segments name persisted leftover-map rank. The pair-list note names leftover-map complete-case coverage only when leftoverMapCoverageCounts returns usable complete-case integers, leftover-map item complete-case coverage, leftover-map incomplete post coverage, and leftover-map incomplete item coverage when persisted. The grouping comparison strip names persisted leftover-map post complete-case coverage only for fully visible grouping populations; partial-visibility rows omit that aggregate. The grouping comparison strip also names persisted item complete-case coverage only for fully visible grouping populations. The comparison axis-share label is independent of the coverage helpers: it appears only for a finite persisted `leftover_share`, including zero and finite negative values, and is omitted for missing/non-finite share. Partial-visibility grouping rows expose no persisted axis aggregate. | `LeftoverPairList`, `LeftoverMapPlot`, `ticket-list`, `post-badge` | | `Workspace/OperationsDashboard` | Compare Event and post counts, inspect external-information coverage, then open the cited source behind a claim, handover, or repeat-issue fact. `EvidenceReady`, `NarrowViewport`, `AnalysisPendingAndMissingEvidence`, `AnalysisFailed`, and `LoadError` cover populated, mobile, unavailable-evidence, analysis-pending, retryable failure, and transport-error states. | `--color-dashboard-*`, `OperationsDashboard` | | `Post/SimilarVocPanel` | Compare ontology/semantic similar VOC and prior action evidence, then open the source; unavailable states show no fabricated TEPP theta or weight. | `SimilarVocPanel.css`, `SimilarVocPanel` | | `Post/Recorded perspectives` | Read the imported primary and every evidence-connected additional Voice with its recorded truth state instead of flattening them into one compound category. `CombinedEvidence`, `RejectedEvidence`, and `NarrowViewport` cover desktop, rejected-evidence, and narrow layouts. | `VoicePerspectiveList`, `ticket-list`, `post-meta` | diff --git a/frontend/package.json b/frontend/package.json index 2238b2b96..228735341 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "frontend", "private": true, - "version": "2.51.0", + "version": "2.55.0", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/src/components/LeftoverPairList.tsx b/frontend/src/components/LeftoverPairList.tsx index 5f0c4a23d..6c8c549fa 100644 --- a/frontend/src/components/LeftoverPairList.tsx +++ b/frontend/src/components/LeftoverPairList.tsx @@ -59,7 +59,10 @@ export type LeftoverPairListProps = { * next action. When four finite coordinates exist, ADR 0268 draws the * leftover-map graphic display above the pair buttons; click a post * marker opens that post. ADR 0269 captions those leftover-map axes with - * persisted leftover-map axis share when finite. ADR 0270 ticks those + * persisted leftover-map axis share when finite. ADR 0289 captions those + * leftover-map axes with persisted leftover-map singular values when + * finite and non-negative, independently of leftover-map axis share, and + * does not invent ``σ_k`` from leftover-map axis share. ADR 0270 ticks those * leftover-map axes at persisted ``ξ`` / ``ζ`` so the pair-row badge matches * the plot. ADR 0271 names persisted leftover-map distance ``d`` on those * pair segments. ADR 0272 names persisted leftover-map reconstruction @@ -81,16 +84,11 @@ export type LeftoverPairListProps = { * incomplete post coverage on the pair-list note. ADR 0287 names persisted leftover-map * incomplete item coverage on the pair-list note. ADR 0288 fail-closes pair-list * leftover-map post complete-case coverage through leftoverMapCoverageCounts so - * used-greater-than-scored, negative, or non-integer counts omit that note. ADR 0289 + * used-greater-than-scored, negative, or non-integer counts omit that note. ADR 0290 * names persisted leftover-map post complete-case coverage on the grouping - * comparison strip, not this pair list. ADR 0290 names persisted leftover-map + * comparison strip, not this pair list. ADR 0291 names persisted leftover-map * item complete-case coverage on the grouping comparison strip, not this pair - * list. ADR 0291 names persisted leftover-map incomplete post coverage on the - * grouping comparison strip, not this pair list. ADR 0292 names persisted leftover-map - * incomplete item coverage on the grouping comparison strip, not this pair list. ADR 0293 - * names persisted leftover-map axis share on the grouping comparison strip, not this pair - * list. ADR 0294 names persisted leftover-map singular values on the grouping comparison - * strip, not this pair list. Every badge still + * list. Every badge still * renders together before opening the named post. */ export function LeftoverPairList({ diff --git a/frontend/src/i18n.test.ts b/frontend/src/i18n.test.ts index 62e6e9fcc..8597babd7 100644 --- a/frontend/src/i18n.test.ts +++ b/frontend/src/i18n.test.ts @@ -43,10 +43,9 @@ describe("i18n", () => { "Page", "Answer", "leftover axis {axis} {share}%", - "leftover map comparison axis {axis} {share}%", - "leftover map comparison axis {axis} σ {value}", + "leftover axis {axis} σ {value} {share}%", "Leftover-map axis share", - "Leftover-map axis share is Gabriel inertia of residual SVD axes 1 and 2. Open a leftover pair to read the post–criterion cell. The shares do not invent a leftover score.", + "Leftover-map axis share is Gabriel inertia of residual SVD axes 1 and 2. Leftover-map singular values are the Gabriel scale of those axes. Open a leftover pair to read the post–criterion cell. The shares and singular values do not invent a leftover score.", "Leftover pairs", "Closest leftover", "Farthest leftover", @@ -67,6 +66,8 @@ describe("i18n", () => { "leftover-map axis 1", "leftover-map axis 2", "leftover-map axis {axis} ({share}%)", + "leftover-map axis {axis} σ {value}", + "leftover-map axis {axis} σ {value} ({share}%)", "leftover-map axis {axis} tick {value}", "leftover-map distance {label}", "leftover-map reconstruction {label}", @@ -84,7 +85,10 @@ describe("i18n", () => { "Leftover map comparison incomplete posts", "Leftover map comparison incomplete items", "Leftover map comparison axis share", - "Leftover map comparison axis singular", + "leftover map comparison axis {axis} {share}%", + "Leftover map comparison reconstruction", + "Leftover map comparison explained leftover share", + "Leftover map comparison unexplained leftover share", "Leftover-map graphic item coverage", "Leftover map item coverage", "Leftover map incomplete posts", @@ -367,7 +371,7 @@ describe("i18n", () => { ], [ "vi", - "Bản đồ phần dư sau hiệu ứng chính IRT. Vạch trục ghi tọa độ bản đồ phần dư đã lưu. Đoạn cặp ghi khoảng cách bản đồ phần dư d, tái dựng bản đồ phần dư R̂, phần dư giải thích e, phần dư chưa giải thích s, phần giao x, phần dư chưa giải thích U, phần dư R, Y quan sát, E kỳ vọng và hạng bản đồ phần dư. Hình ghi phạm vi trường hợp đầy đủ của bài viết và tiêu chí cùng bài không đầy đủ và tiêu chí không đầy đủ khi đã lưu. Nhấn dấu bài viết để mở bài đó. Hình này không tạo ra điểm phần dư.", + "Bản đồ phần dư sau hiệu ứng chính IRT. Vạch trục ghi tọa độ bản đồ phần dư đã lưu. Đoạn cặp ghi khoảng cách bản đồ phần dư d, tái dựng bản đồ phần dư R̂, tỷ phần phần dư được giải thích e, phần dư chưa giải thích s, phần giao x, phần dư chưa giải thích U, phần dư R, Y quan sát, E kỳ vọng và hạng bản đồ phần dư. Hình ghi phạm vi trường hợp đầy đủ của bài viết và tiêu chí cùng bài không đầy đủ và tiêu chí không đầy đủ khi đã lưu. Nhấn dấu bài viết để mở bài đó. Hình này không tạo ra điểm phần dư.", ], ] as const)("formats leftover-map graphic display caption in %s", (locale, expected) => { setLocale(locale); @@ -522,7 +526,7 @@ describe("i18n", () => { ["ko", "잔여 지도 설명 잔여 점유율 R̂²/R² 0.76"], ["zh", "残差图已解释残差份额 R̂²/R² 0.76"], ["ja", "残差マップ説明済み残差割合 R̂²/R² 0.76"], - ["vi", "phần dư giải thích bản đồ phần dư R̂²/R² 0.76"], + ["vi", "tỷ phần phần dư được giải thích trên bản đồ phần dư R̂²/R² 0.76"], ] as const)("formats leftover-map segment explained leftover share in %s", (locale, expected) => { setLocale(locale); expect(tf("leftover-map explained leftover share {label}", { label: "R̂²/R² 0.76" })).toBe( @@ -612,6 +616,40 @@ describe("i18n", () => { expect(tf("leftover-map axis {axis} ({share}%)", { axis: 1, share: "82" })).toBe(expected); }); + it.each([ + ["ko", "잔여 지도 축 1 σ 1.84"], + ["zh", "残差图轴 1 σ 1.84"], + ["ja", "残差マップ軸 1 σ 1.84"], + ["vi", "trục bản đồ phần dư 1 σ 1.84"], + ] as const)("formats leftover-map plot axis singular value in %s", (locale, expected) => { + setLocale(locale); + expect(tf("leftover-map axis {axis} σ {value}", { axis: 1, value: "1.84" })).toBe(expected); + }); + + it.each([ + ["ko", "잔여 지도 축 1 σ 1.84 (82%)"], + ["zh", "残差图轴 1 σ 1.84 (82%)"], + ["ja", "残差マップ軸 1 σ 1.84 (82%)"], + ["vi", "trục bản đồ phần dư 1 σ 1.84 (82%)"], + ] as const)("formats leftover-map plot axis singular value with share in %s", (locale, expected) => { + setLocale(locale); + expect( + tf("leftover-map axis {axis} σ {value} ({share}%)", { axis: 1, value: "1.84", share: "82" }), + ).toBe(expected); + }); + + it.each([ + ["ko", "잔차 축 1 σ 1.84 82%"], + ["zh", "残差轴 1 σ 1.84 82%"], + ["ja", "残差軸 1 σ 1.84 82%"], + ["vi", "trục phần dư 1 σ 1.84 82%"], + ] as const)("formats leftover-axis badge singular value with share in %s", (locale, expected) => { + setLocale(locale); + expect( + tf("leftover axis {axis} σ {value} {share}%", { axis: 1, value: "1.84", share: "82" }), + ).toBe(expected); + }); + it.each([ ["ko", "IRT 주효과 이후 관측 Y 2.40와 기대 E 2.00를 읽은 다음, 이 글을 여세요."], ["zh", "阅读 IRT 主效应后的观测 Y 2.40 与期望 E 2.00,然后打开这篇帖子。"], diff --git a/frontend/src/i18n.ts b/frontend/src/i18n.ts index dfa41d366..ee6da0b6b 100644 --- a/frontend/src/i18n.ts +++ b/frontend/src/i18n.ts @@ -274,8 +274,9 @@ const TRANSLATIONS: Partial>> = { "Leftover map comparison incomplete items": "잔여 지도 비교 불완전 기준", "Leftover map comparison axis share": "잔여 지도 비교 축 비율", "leftover map comparison axis {axis} {share}%": "잔여 지도 비교 축 {axis} {share}%", - "Leftover map comparison axis singular": "잔여 지도 비교 축 특이값", - "leftover map comparison axis {axis} σ {value}": "잔여 지도 비교 축 {axis} σ {value}", + "Leftover map comparison reconstruction": "잔여 지도 비교 재구성", + "Leftover map comparison explained leftover share": "잔여 지도 비교 설명 잔여 비율", + "Leftover map comparison unexplained leftover share": "잔여 지도 비교 미설명 잔여 비율", "Leftover map item coverage": "잔여 지도 기준 포함 범위", "Leftover map incomplete posts": "잔여 지도 불완전 글", "Leftover map incomplete items": "잔여 지도 불완전 기준", @@ -574,9 +575,10 @@ const TRANSLATIONS: Partial>> = { "Valid from": "유효 시작", "Valid to": "유효 종료", "leftover axis {axis} {share}%": "잔차 축 {axis} {share}%", + "leftover axis {axis} σ {value} {share}%": "잔차 축 {axis} σ {value} {share}%", "Leftover-map axis share": "잔차 지도 축 비율", - "Leftover-map axis share is Gabriel inertia of residual SVD axes 1 and 2. Open a leftover pair to read the post–criterion cell. The shares do not invent a leftover score.": - "잔차 지도 축 비율은 잔차 SVD 축 1과 2의 Gabriel 관성입니다. 글–기준 셀을 읽으려면 잔차 쌍을 여세요. 이 비율은 잔차 점수를 만들어내지 않습니다.", + "Leftover-map axis share is Gabriel inertia of residual SVD axes 1 and 2. Leftover-map singular values are the Gabriel scale of those axes. Open a leftover pair to read the post–criterion cell. The shares and singular values do not invent a leftover score.": + "잔차 지도 축 비율은 잔차 SVD 축 1과 2의 Gabriel 관성입니다. 잔차 지도 특이값은 그 축의 Gabriel 척도입니다. 글–기준 셀을 읽으려면 잔차 쌍을 여세요. 이 비율과 특이값은 잔차 점수를 만들어내지 않습니다.", "Leftover pairs": "잔여 쌍", "Closest leftover": "가장 가까운 잔여", "Farthest leftover": "가장 먼 잔여", @@ -607,6 +609,8 @@ const TRANSLATIONS: Partial>> = { "leftover-map axis 1": "잔여 지도 축 1", "leftover-map axis 2": "잔여 지도 축 2", "leftover-map axis {axis} ({share}%)": "잔여 지도 축 {axis} ({share}%)", + "leftover-map axis {axis} σ {value}": "잔여 지도 축 {axis} σ {value}", + "leftover-map axis {axis} σ {value} ({share}%)": "잔여 지도 축 {axis} σ {value} ({share}%)", "leftover-map axis {axis} tick {value}": "잔여 지도 축 {axis} 눈금 {value}", "leftover-map distance {label}": "잔여 지도 거리 {label}", "leftover-map reconstruction {label}": "잔여 지도 재구성 {label}", @@ -888,8 +892,9 @@ const TRANSLATIONS: Partial>> = { "Leftover map comparison incomplete items": "残差地图比较不完整准则", "Leftover map comparison axis share": "残差地图比较轴占比", "leftover map comparison axis {axis} {share}%": "残差地图比较轴 {axis} {share}%", - "Leftover map comparison axis singular": "残差地图比较轴奇异值", - "leftover map comparison axis {axis} σ {value}": "残差地图比较轴 {axis} σ {value}", + "Leftover map comparison reconstruction": "残差地图比较重建", + "Leftover map comparison explained leftover share": "残差地图比较已解释残差占比", + "Leftover map comparison unexplained leftover share": "残差地图比较未解释残差占比", "Leftover map item coverage": "残差地图准则覆盖范围", "Leftover map incomplete posts": "残差地图不完整帖文", "Leftover map incomplete items": "残差地图不完整准则", @@ -1184,9 +1189,10 @@ const TRANSLATIONS: Partial>> = { "Valid from": "有效起始", "Valid to": "有效结束", "leftover axis {axis} {share}%": "残差轴 {axis} {share}%", + "leftover axis {axis} σ {value} {share}%": "残差轴 {axis} σ {value} {share}%", "Leftover-map axis share": "残差图轴占比", - "Leftover-map axis share is Gabriel inertia of residual SVD axes 1 and 2. Open a leftover pair to read the post–criterion cell. The shares do not invent a leftover score.": - "残差图轴占比是残差 SVD 第 1、2 轴的 Gabriel 惯量。打开一个残差配对可查看文章–准则单元格。这些占比不会虚构残差分数。", + "Leftover-map axis share is Gabriel inertia of residual SVD axes 1 and 2. Leftover-map singular values are the Gabriel scale of those axes. Open a leftover pair to read the post–criterion cell. The shares and singular values do not invent a leftover score.": + "残差图轴占比是残差 SVD 第 1、2 轴的 Gabriel 惯量。残差图奇异值是这些轴的 Gabriel 尺度。打开一个残差配对可查看文章–准则单元格。这些占比和奇异值不会虚构残差分数。", "Leftover pairs": "残余配对", "Closest leftover": "最近残余", "Farthest leftover": "最远残余", @@ -1217,6 +1223,8 @@ const TRANSLATIONS: Partial>> = { "leftover-map axis 1": "残差图轴 1", "leftover-map axis 2": "残差图轴 2", "leftover-map axis {axis} ({share}%)": "残差图轴 {axis} ({share}%)", + "leftover-map axis {axis} σ {value}": "残差图轴 {axis} σ {value}", + "leftover-map axis {axis} σ {value} ({share}%)": "残差图轴 {axis} σ {value} ({share}%)", "leftover-map axis {axis} tick {value}": "残差图轴 {axis} 刻度 {value}", "leftover-map distance {label}": "残差图距离 {label}", "leftover-map reconstruction {label}": "残差图重建 {label}", @@ -1523,8 +1531,9 @@ const TRANSLATIONS: Partial>> = { "Leftover map comparison incomplete items": "残差マップの比較不完全基準", "Leftover map comparison axis share": "残差マップの比較軸の比率", "leftover map comparison axis {axis} {share}%": "残差マップの比較軸 {axis} {share}%", - "Leftover map comparison axis singular": "残差マップの比較軸の特異値", - "leftover map comparison axis {axis} σ {value}": "残差マップの比較軸 {axis} σ {value}", + "Leftover map comparison reconstruction": "残差マップの比較再構成", + "Leftover map comparison explained leftover share": "残差マップの比較説明済み残差比率", + "Leftover map comparison unexplained leftover share": "残差マップの比較未説明残差比率", "Leftover map item coverage": "残差マップの基準対象範囲", "Leftover map incomplete posts": "残差マップの不完全投稿", "Leftover map incomplete items": "残差マップの不完全基準", @@ -1798,9 +1807,10 @@ const TRANSLATIONS: Partial>> = { "Valid from": "有効開始", "Valid to": "有効終了", "leftover axis {axis} {share}%": "残差軸 {axis} {share}%", + "leftover axis {axis} σ {value} {share}%": "残差軸 {axis} σ {value} {share}%", "Leftover-map axis share": "残差マップ軸の比率", - "Leftover-map axis share is Gabriel inertia of residual SVD axes 1 and 2. Open a leftover pair to read the post–criterion cell. The shares do not invent a leftover score.": - "残差マップ軸の比率は、残差 SVD の第1軸と第2軸の Gabriel 慣性です。投稿–基準セルを読むには残差ペアを開いてください。この比率から残差スコアを作りません。", + "Leftover-map axis share is Gabriel inertia of residual SVD axes 1 and 2. Leftover-map singular values are the Gabriel scale of those axes. Open a leftover pair to read the post–criterion cell. The shares and singular values do not invent a leftover score.": + "残差マップ軸の比率は、残差 SVD の第1軸と第2軸の Gabriel 慣性です。残差マップ特異値はそれらの軸の Gabriel 尺度です。投稿–基準セルを読むには残差ペアを開いてください。この比率と特異値から残差スコアを作りません。", "Leftover pairs": "残差ペア", "Closest leftover": "最も近い残差", "Farthest leftover": "最も遠い残差", @@ -1831,6 +1841,8 @@ const TRANSLATIONS: Partial>> = { "leftover-map axis 1": "残差マップ軸 1", "leftover-map axis 2": "残差マップ軸 2", "leftover-map axis {axis} ({share}%)": "残差マップ軸 {axis} ({share}%)", + "leftover-map axis {axis} σ {value}": "残差マップ軸 {axis} σ {value}", + "leftover-map axis {axis} σ {value} ({share}%)": "残差マップ軸 {axis} σ {value} ({share}%)", "leftover-map axis {axis} tick {value}": "残差マップ軸 {axis} 目盛 {value}", "leftover-map distance {label}": "残差マップ距離 {label}", "leftover-map reconstruction {label}": "残差マップ再構成 {label}", @@ -2137,8 +2149,9 @@ const TRANSLATIONS: Partial>> = { "Leftover map comparison incomplete items": "Tiêu chí không đầy đủ so sánh trên bản đồ phần dư", "Leftover map comparison axis share": "Tỷ trọng trục so sánh bản đồ phần dư", "leftover map comparison axis {axis} {share}%": "trục so sánh bản đồ phần dư {axis} {share}%", - "Leftover map comparison axis singular": "Giá trị singular trục so sánh bản đồ phần dư", - "leftover map comparison axis {axis} σ {value}": "trục so sánh bản đồ phần dư {axis} σ {value}", + "Leftover map comparison reconstruction": "Tái dựng so sánh bản đồ phần dư", + "Leftover map comparison explained leftover share": "Tỷ phần phần dư được giải thích khi so sánh bản đồ phần dư", + "Leftover map comparison unexplained leftover share": "Tỷ phần phần dư chưa được giải thích khi so sánh bản đồ phần dư", "Leftover map item coverage": "Phạm vi tiêu chí bản đồ phần dư", "Leftover map incomplete posts": "Bài không đầy đủ trên bản đồ phần dư", "Leftover map incomplete items": "Tiêu chí không đầy đủ trên bản đồ phần dư", @@ -2412,9 +2425,10 @@ const TRANSLATIONS: Partial>> = { "Valid from": "Hiệu lực từ", "Valid to": "Hiệu lực đến", "leftover axis {axis} {share}%": "trục phần dư {axis} {share}%", + "leftover axis {axis} σ {value} {share}%": "trục phần dư {axis} σ {value} {share}%", "Leftover-map axis share": "Tỷ trọng trục bản đồ phần dư", - "Leftover-map axis share is Gabriel inertia of residual SVD axes 1 and 2. Open a leftover pair to read the post–criterion cell. The shares do not invent a leftover score.": - "Tỷ trọng trục bản đồ phần dư là quán tính Gabriel của các trục SVD phần dư 1 và 2. Mở một cặp phần dư để đọc ô bài viết–tiêu chí. Các tỷ trọng này không tạo ra điểm phần dư.", + "Leftover-map axis share is Gabriel inertia of residual SVD axes 1 and 2. Leftover-map singular values are the Gabriel scale of those axes. Open a leftover pair to read the post–criterion cell. The shares and singular values do not invent a leftover score.": + "Tỷ trọng trục bản đồ phần dư là quán tính Gabriel của các trục SVD phần dư 1 và 2. Giá trị kỳ dị bản đồ phần dư là thang Gabriel của các trục đó. Mở một cặp phần dư để đọc ô bài viết–tiêu chí. Các tỷ trọng và giá trị kỳ dị này không tạo ra điểm phần dư.", "Leftover pairs": "Cặp phần dư", "Closest leftover": "Phần dư gần nhất", "Farthest leftover": "Phần dư xa nhất", @@ -2445,10 +2459,12 @@ const TRANSLATIONS: Partial>> = { "leftover-map axis 1": "trục bản đồ phần dư 1", "leftover-map axis 2": "trục bản đồ phần dư 2", "leftover-map axis {axis} ({share}%)": "trục bản đồ phần dư {axis} ({share}%)", + "leftover-map axis {axis} σ {value}": "trục bản đồ phần dư {axis} σ {value}", + "leftover-map axis {axis} σ {value} ({share}%)": "trục bản đồ phần dư {axis} σ {value} ({share}%)", "leftover-map axis {axis} tick {value}": "vạch trục bản đồ phần dư {axis} {value}", "leftover-map distance {label}": "khoảng cách bản đồ phần dư {label}", "leftover-map reconstruction {label}": "tái dựng bản đồ phần dư {label}", - "leftover-map explained leftover share {label}": "phần dư giải thích bản đồ phần dư {label}", + "leftover-map explained leftover share {label}": "tỷ phần phần dư được giải thích trên bản đồ phần dư {label}", "leftover-map unexplained leftover share {label}": "phần dư chưa giải thích bản đồ phần dư {label}", "leftover-map cross share {label}": "phần giao bản đồ phần dư {label}", "leftover-map unexplained leftover {label}": "phần dư chưa giải thích {label}", @@ -2461,7 +2477,7 @@ const TRANSLATIONS: Partial>> = { "Leftover-map graphic incomplete posts": "Bài không đầy đủ trên đồ họa bản đồ phần dư", "Leftover-map graphic incomplete items": "Tiêu chí không đầy đủ trên đồ họa bản đồ phần dư", "Leftover map after IRT main effects. Axis ticks name persisted leftover-map coordinates. Pair segments name leftover-map distance d, leftover-map reconstruction R̂, leftover-map explained leftover share e, leftover-map unexplained leftover share s, leftover-map cross share x, leftover-map unexplained leftover U, leftover residual R, leftover observed Y, leftover expected E, and leftover-map rank. The plot names leftover-map complete-case coverage, leftover-map item complete-case coverage, leftover-map incomplete post coverage, and leftover-map incomplete item coverage when persisted. Click a post marker to open that post. The plot does not invent a leftover score.": - "Bản đồ phần dư sau hiệu ứng chính IRT. Vạch trục ghi tọa độ bản đồ phần dư đã lưu. Đoạn cặp ghi khoảng cách bản đồ phần dư d, tái dựng bản đồ phần dư R̂, phần dư giải thích e, phần dư chưa giải thích s, phần giao x, phần dư chưa giải thích U, phần dư R, Y quan sát, E kỳ vọng và hạng bản đồ phần dư. Hình ghi phạm vi trường hợp đầy đủ của bài viết và tiêu chí cùng bài không đầy đủ và tiêu chí không đầy đủ khi đã lưu. Nhấn dấu bài viết để mở bài đó. Hình này không tạo ra điểm phần dư.", + "Bản đồ phần dư sau hiệu ứng chính IRT. Vạch trục ghi tọa độ bản đồ phần dư đã lưu. Đoạn cặp ghi khoảng cách bản đồ phần dư d, tái dựng bản đồ phần dư R̂, tỷ phần phần dư được giải thích e, phần dư chưa giải thích s, phần giao x, phần dư chưa giải thích U, phần dư R, Y quan sát, E kỳ vọng và hạng bản đồ phần dư. Hình ghi phạm vi trường hợp đầy đủ của bài viết và tiêu chí cùng bài không đầy đủ và tiêu chí không đầy đủ khi đã lưu. Nhấn dấu bài viết để mở bài đó. Hình này không tạo ra điểm phần dư.", "Open leftover-map post {title} at ξ {person}": "Mở bài viết bản đồ phần dư {title} tại ξ {person}", "Read observed Y {observed} and expected E {expected} after IRT main effects, then open this post.": diff --git a/frontend/src/leftoverMapCompareAxis.ts b/frontend/src/leftoverMapCompareAxis.ts index f7d574c90..540017a2a 100644 --- a/frontend/src/leftoverMapCompareAxis.ts +++ b/frontend/src/leftoverMapCompareAxis.ts @@ -1,4 +1,4 @@ -/** Caption leftover-map axis share and singular values on the grouping comparison strip (ADR 0293 / ADR 0294). */ +/** Caption persisted leftover-map axis share and singular values on the grouping comparison strip. */ import type { LeftoverMapAxis } from "./api"; @@ -46,6 +46,13 @@ export function leftoverMapCompareAxisShare( }; } +/** + * Format the canonical persisted singular value for one comparison axis. + * + * This deliberately does not derive a singular value from share, pair count, + * marker count, rank, distance, or coverage. Missing/invalid persisted values + * are omitted so the UI cannot invent psychometric output. + */ export function leftoverMapCompareAxisSingular( axis: Pick | null | undefined, ): LeftoverMapCompareAxisSingular | null { diff --git a/frontend/src/leftoverMapPlotLayout.ts b/frontend/src/leftoverMapPlotLayout.ts index 4da4f0cb5..bc23ed8b4 100644 --- a/frontend/src/leftoverMapPlotLayout.ts +++ b/frontend/src/leftoverMapPlotLayout.ts @@ -1,5 +1,8 @@ /** Gabriel leftover-map graphic display of persisted ``ξ_{1:2}`` / ``ζ_{1:2}``. * Leftover-map axis share captions axes 1 and 2 when finite (ADR 0269). + * Leftover-map singular values caption axes 1 and 2 when finite and + * non-negative (ADR 0289). Do not invent ``σ_k`` from leftover-map axis + * share. * Axis ticks name persisted leftover-map coordinates (ADR 0270). * Pair segments name persisted leftover-map distance ``d`` (ADR 0271), * persisted leftover-map reconstruction ``R̂`` (ADR 0272), persisted @@ -16,13 +19,8 @@ * complete-case coverage fail-closed through leftoverMapCoverageCounts * (ADR 0288), pair-list item complete-case coverage (ADR 0285), pair-list * incomplete post coverage (ADR 0286), pair-list incomplete item - * coverage (ADR 0287), grouping comparison complete-case coverage - * (ADR 0289), grouping comparison item complete-case coverage - * (ADR 0290), grouping comparison incomplete post coverage - * (ADR 0291), grouping comparison incomplete item coverage - * (ADR 0292), grouping comparison leftover-map axis share - * (ADR 0293), and grouping comparison leftover-map singular values - * (ADR 0294) caption the pair list or the grouping comparison strip, + * coverage (ADR 0287), and grouping comparison complete-case coverage (ADR 0290), and grouping comparison item + * complete-case coverage (ADR 0291) caption the pair list or the grouping comparison strip, * not this graphic layout. */ @@ -86,7 +84,10 @@ export const PLOT_TICK_LENGTH = 6; const UNIT_DISPLAY_SPAN = 2; const COLLAPSED_SPAN = 1e-12; const COINCIDENT_LABEL_OFFSET = 14; +const SEGMENT_LABEL_OFFSET = 24; const RECONSTRUCTION_LABEL_OFFSET = 12; +const SEGMENT_LABEL_TOP_INSET = 12; +const SEGMENT_LABEL_BOTTOM_INSET = 4; export type LeftoverMapPlottablePair = { pair_kind: LeftoverPair["pair_kind"]; @@ -225,17 +226,17 @@ function toSvg( } function uniqueCoordinateTicks(values: number[]): { value: number; label: string }[] { - const byLabel = new Map(); + const seen = new Set(); + const ticks: { value: number; label: string }[] = []; for (const value of values) { const label = formatSignedLeftoverValue(value); - if (label === null) { + if (label === null || seen.has(value)) { continue; } - if (!byLabel.has(label)) { - byLabel.set(label, value); - } + seen.add(value); + ticks.push({ value, label }); } - return [...byLabel.entries()].map(([label, value]) => ({ value, label })); + return ticks; } function leftoverMapCoordinateTicks( @@ -282,14 +283,43 @@ function leftoverMapSegmentLabelPosition( y2: number, ): { labelX: number; labelY: number } { const coincident = Math.abs(x1 - x2) < 0.01 && Math.abs(y1 - y2) < 0.01; + const midpointX = (x1 + x2) / 2; + const midpointY = (y1 + y2) / 2; + if (coincident) { + return { + labelX: midpointX, + labelY: midpointY - COINCIDENT_LABEL_OFFSET, + }; + } + const deltaX = x2 - x1; + const deltaY = y2 - y1; + const length = Math.hypot(deltaX, deltaY); return { - labelX: (x1 + x2) / 2, - labelY: coincident ? (y1 + y2) / 2 - COINCIDENT_LABEL_OFFSET : (y1 + y2) / 2, + labelX: midpointX - (deltaY / length) * SEGMENT_LABEL_OFFSET, + labelY: midpointY + (deltaX / length) * SEGMENT_LABEL_OFFSET, }; } -function leftoverMapStackedCaptionY(labelY: number, stackedAbove: number): number { - return stackedAbove > 0 ? labelY + stackedAbove * RECONSTRUCTION_LABEL_OFFSET : labelY; +function leftoverMapStackedCaptionY( + labelY: number, + stackedAbove: number, + captionSpacing = RECONSTRUCTION_LABEL_OFFSET, +): number { + return stackedAbove > 0 ? labelY + stackedAbove * captionSpacing : labelY; +} + +function leftoverMapCaptionSpacing(height: number, captionCount: number): number { + if (captionCount <= 1) { + return 0; + } + const availableStackHeight = Math.max( + 0, + height - SEGMENT_LABEL_TOP_INSET - SEGMENT_LABEL_BOTTOM_INSET, + ); + return Math.min( + RECONSTRUCTION_LABEL_OFFSET, + availableStackHeight / (captionCount - 1), + ); } export function layoutLeftoverMapPlot( @@ -397,46 +427,75 @@ export function layoutLeftoverMapPlot( itemPos.x, itemPos.y, ); + const captionCount = [ + distanceLabel, + reconstructionLabel, + explainedShareLabel, + unexplainedShareLabel, + crossShareLabel, + unexplainedLeftoverLabel, + residualLabel, + observedLabel, + expectedLabel, + rankLabel, + ].filter((label) => label !== null).length; + const captionSpacing = leftoverMapCaptionSpacing(height, captionCount); + const maximumLabelY = Math.max( + SEGMENT_LABEL_TOP_INSET, + height - + SEGMENT_LABEL_BOTTOM_INSET - + Math.max(0, captionCount - 1) * captionSpacing, + ); + const labelY = Math.min( + Math.max(labelPosition.labelY, SEGMENT_LABEL_TOP_INSET), + maximumLabelY, + ); const reconstructionY = leftoverMapStackedCaptionY( - labelPosition.labelY, + labelY, distanceLabel !== null && reconstructionLabel !== null ? 1 : 0, + captionSpacing, ); const explainedShareY = leftoverMapStackedCaptionY( - labelPosition.labelY, + labelY, (distanceLabel !== null ? 1 : 0) + (reconstructionLabel !== null ? 1 : 0), + captionSpacing, ); const unexplainedShareY = leftoverMapStackedCaptionY( - labelPosition.labelY, + labelY, (distanceLabel !== null ? 1 : 0) + (reconstructionLabel !== null ? 1 : 0) + (explainedShareLabel !== null ? 1 : 0), + captionSpacing, ); const crossShareY = leftoverMapStackedCaptionY( - labelPosition.labelY, + labelY, (distanceLabel !== null ? 1 : 0) + (reconstructionLabel !== null ? 1 : 0) + (explainedShareLabel !== null ? 1 : 0) + (unexplainedShareLabel !== null ? 1 : 0), + captionSpacing, ); const unexplainedLeftoverY = leftoverMapStackedCaptionY( - labelPosition.labelY, + labelY, (distanceLabel !== null ? 1 : 0) + (reconstructionLabel !== null ? 1 : 0) + (explainedShareLabel !== null ? 1 : 0) + (unexplainedShareLabel !== null ? 1 : 0) + (crossShareLabel !== null ? 1 : 0), + captionSpacing, ); const residualY = leftoverMapStackedCaptionY( - labelPosition.labelY, + labelY, (distanceLabel !== null ? 1 : 0) + (reconstructionLabel !== null ? 1 : 0) + (explainedShareLabel !== null ? 1 : 0) + (unexplainedShareLabel !== null ? 1 : 0) + (crossShareLabel !== null ? 1 : 0) + (unexplainedLeftoverLabel !== null ? 1 : 0), + captionSpacing, ); const observedY = leftoverMapStackedCaptionY( - labelPosition.labelY, + labelY, (distanceLabel !== null ? 1 : 0) + (reconstructionLabel !== null ? 1 : 0) + (explainedShareLabel !== null ? 1 : 0) + @@ -444,9 +503,10 @@ export function layoutLeftoverMapPlot( (crossShareLabel !== null ? 1 : 0) + (unexplainedLeftoverLabel !== null ? 1 : 0) + (residualLabel !== null ? 1 : 0), + captionSpacing, ); const expectedY = leftoverMapStackedCaptionY( - labelPosition.labelY, + labelY, (distanceLabel !== null ? 1 : 0) + (reconstructionLabel !== null ? 1 : 0) + (explainedShareLabel !== null ? 1 : 0) + @@ -455,9 +515,10 @@ export function layoutLeftoverMapPlot( (unexplainedLeftoverLabel !== null ? 1 : 0) + (residualLabel !== null ? 1 : 0) + (observedLabel !== null ? 1 : 0), + captionSpacing, ); const rankY = leftoverMapStackedCaptionY( - labelPosition.labelY, + labelY, (distanceLabel !== null ? 1 : 0) + (reconstructionLabel !== null ? 1 : 0) + (explainedShareLabel !== null ? 1 : 0) + @@ -467,6 +528,7 @@ export function layoutLeftoverMapPlot( (residualLabel !== null ? 1 : 0) + (observedLabel !== null ? 1 : 0) + (expectedLabel !== null ? 1 : 0), + captionSpacing, ); segments.push({ pairKind: pair.pair_kind === "farthest" ? "farthest" : "closest", @@ -505,6 +567,7 @@ export function layoutLeftoverMapPlot( rankX: labelPosition.labelX, rankY, ...labelPosition, + labelY, }); } diff --git a/pyproject.toml b/pyproject.toml index 33c2ed641..61be353ce 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "lineageweave" -version = "2.51.0" +version = "2.55.0" description = "Reconstructs git-branch-style lineage DAGs from scattered short records using multi-channel score fusion and LLM adjudication." readme = "README.md" license = { text = "MIT" } From 653330d8a56ddf7d751997a9ce19cafa70a8d6f2 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 7 Sep 2026 20:00:14 +0900 Subject: [PATCH 3/4] chore(reports): drop superseded historical ADR identity from #830 reconstruction --- ...0294-leftover-map-compare-axis-singular.md | 108 ------------------ 1 file changed, 108 deletions(-) delete mode 100644 docs/adr/0294-leftover-map-compare-axis-singular.md diff --git a/docs/adr/0294-leftover-map-compare-axis-singular.md b/docs/adr/0294-leftover-map-compare-axis-singular.md deleted file mode 100644 index 07e52fa5a..000000000 --- a/docs/adr/0294-leftover-map-compare-axis-singular.md +++ /dev/null @@ -1,108 +0,0 @@ -# ADR 0294 — Name leftover-map singular values on the grouping comparison strip - -**Decision status:** Accepted -**Date:** 2026-08-30 - -Amends leftover-map axis share on the grouping comparison strip -([ADR 0293](0293-leftover-map-compare-axis-share.md)) and leftover-map -axis share persistence ([ADR 0148](0148-leftover-map-axis-share.md)). -Independent of leftover-map incomplete item coverage on the grouping -comparison strip ([ADR 0292](0292-leftover-map-compare-incomplete-item.md)) -and leftover-map axis share on the graphic display -([ADR 0269](0269-leftover-map-axis-share-plot.md)). The dashboard plot stack -already named leftover-map singular values on graphic axes and leftover-axis -badges under other numbers; this protected increment uses **0294**. - -## Context - -ADR 0148 already persists leftover-map singular values `σ_k` and leftover-map -axis share `σ_k² / Σ_j σ_j²` on `report_leftover_map_axis`. ADR 0293 already -includes those persisted axes on `GET /api/reports/compare/{period}` and -captions leftover-map axis share on the grouping comparison strip. The strip -still names share without naming leftover-map singular value for that -grouping, so a buyer who compares PU / corp / thread leftover pairs can treat -an 82% first axis as if it had the same Gabriel scale as a rank-0 unused axis. - -This increment captions each grouping row through leftoverMapCompareAxisSingular. -It does not add columns. It does not invent leftover-map singular value from -leftover-map axis share, leftover pair count, plotted marker count, leftover-map -distance, leftover-map rank, leftover-map post coverage, leftover-map item -coverage, leftover-map incomplete post coverage, leftover-map incomplete item -coverage, or the count of unused axes. It does not persist leftover-map inner -product, cosine, or length as separate columns. Do not invent a leftover -score. Do not invent a theta. - -## Decision - -On the grouping comparison strip, caption leftover-map axis `k` as -`leftover map comparison axis {k} σ {value}` only when leftoverMapCompareAxisSingular -returns a usable leftover-map singular value from persisted -`leftover_singular_value`. Use the distinct accessible name -`Leftover map comparison axis singular` so the strip caption is not the -leftover-axis report badge (`leftover axis {k} σ {value} {share}%`) and is not -the graphic caption (`leftover-map axis {k} σ {value}`). A missing, non-finite, -or negative leftover-map singular value omits that leftover-map comparison axis -singular badge independently of leftover-map comparison axis share, leftover-map -post coverage notes, leftover-map item coverage notes, leftover-map incomplete -post notes, leftover-map incomplete item notes, leftover pairs, leftover-map -distance `d`, and any leftover-map captions on the pair list and graphic. -Rank-0 leftover-map singular value `0` is shown when that persisted value is a -finite nonnegative number. Do not invent leftover-map singular value from -leftover-map axis share, leftover pair count, plotted marker count, leftover-map -distance, leftover-map rank, leftover-map post coverage, leftover-map item -coverage, leftover-map incomplete post coverage, leftover-map incomplete item -coverage, or the count of unused axes. Do not add the leftover-map graphic to -the strip in this increment. Click a leftover pair on the strip to open that -post. - -Do not add SQL migrations. Do not edit shipped migrations. Do not persist inner -product, cosine, or length as separate columns. Do not invent a leftover -score. Do not invent a theta. - -## Consequences - -After `make seed`, the grouping comparison strip names persisted leftover-map -post complete-case coverage, persisted leftover-map item complete-case -coverage, persisted leftover-map incomplete post coverage, persisted -leftover-map incomplete item coverage, persisted leftover-map axis share, and -persisted leftover-map singular values on each grouping row when -leftoverMapCoverageCounts / leftoverMapItemCoverageCounts / -leftoverMapIncompletePostCount / leftoverMapIncompleteItemCount / -leftoverMapCompareAxisShare / leftoverMapCompareAxisSingular return usable -values, then names leftover pairs with leftover-map distance `d`. Closest -and farthest leftover pairs still sit above the member list with the -leftover-map graphic display; click a post marker or a pair button opens that -post. -Hidden posts stay hidden. - -## Related - -Independent of leftover interaction-map persistence, leftover-criterion -evaluation landing, leftover residual disclosure, leftover-map -complete-case coverage persistence, leftover-map axis share persistence, -leftover pairs on the grouping comparison strip, leftover-map complete-case -coverage on the grouping comparison strip, leftover-map item complete-case -coverage on the grouping comparison strip, leftover-map incomplete post -coverage on the grouping comparison strip, leftover-map incomplete item -coverage on the grouping comparison strip, leftover-map axis share on the -grouping comparison strip, leftover-map inner product, leftover-map cosine, -leftover-map length, leftover-map graphic display, leftover-map axis share -on the graphic display, leftover-map singular values on graphic axes, and -leftover-map singular values on leftover-axis badges. - -## 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 -(LSIRM interaction `−γ‖ξ_j − ζ_i‖` after main effects -`α_j − β_i`; typically `p = 2` for the interaction map. Leftover-map -singular values are the Gabriel scale `σ_k` of residual SVD axes; -grouping comparison leftover-map singular values name that persisted -`σ_k` for that grouping only when leftoverMapCompareAxisSingular returns -a usable value.) From 70221cc52dbf4c9e7bd0a9a328b7841eb5ae4abd Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 7 Sep 2026 20:01:13 +0900 Subject: [PATCH 4/4] chore(reports): drop superseded historical release identity from #830 reconstruction --- ....51.0-leftover-map-compare-axis-singular.md | 18 ------------------ 1 file changed, 18 deletions(-) delete mode 100644 CHANGELOG.d/2.51.0-leftover-map-compare-axis-singular.md diff --git a/CHANGELOG.d/2.51.0-leftover-map-compare-axis-singular.md b/CHANGELOG.d/2.51.0-leftover-map-compare-axis-singular.md deleted file mode 100644 index f73c7aa67..000000000 --- a/CHANGELOG.d/2.51.0-leftover-map-compare-axis-singular.md +++ /dev/null @@ -1,18 +0,0 @@ -## 2.51.0 — Leftover-map singular values on the grouping comparison strip - -- Caption leftover-map singular values on the grouping comparison strip through - leftoverMapCompareAxisSingular (ADR 0294). After `make seed`, closest and - farthest leftover pairs sit above the member list with the Gabriel biplot - of already-named coordinates, leftover-map axis share when finite, - leftover-map singular values when finite and nonnegative, axis ticks that - match `ξ (x, y) ζ (x, y)` on the pair row, and leftover pairs with leftover-map - distance `d`; click a post marker or a pair button opens that post. A missing, - non-finite, or negative leftover-map singular value omits that leftover-map - comparison axis singular badge independently of leftover-map comparison axis - share. Rank-0 leftover-map singular value `0` is shown when persisted. Do not - invent leftover-map singular value from leftover-map axis share, leftover pair - count, plotted marker count, leftover-map distance, leftover-map rank, - leftover-map post coverage, leftover-map item coverage, leftover-map incomplete - post coverage, leftover-map incomplete item coverage, or the count of unused - axes. The strip does not gain the leftover-map graphic. Never invent a leftover - score. Never invent a theta. No new columns.