From 7c026df8d85f9eeae9850f44cdf5e1bc6d644aa7 Mon Sep 17 00:00:00 2001 From: seonghobae Date: Sun, 30 Aug 2026 19:39:07 +0000 Subject: [PATCH 1/3] feat(reports): leftover-map coverage on grouping comparison graphic (v2.63.0) Caption leftover-map complete-case coverage on the grouping comparison leftover-map graphic from already-named leftover_map_coverage (ADR 0306). Distinct accessible name Leftover map comparison graphic coverage. Omit item/incomplete notes on that comparison plot. Never invent a leftover score or a theta. --- AGENTS.md | 16 +- ARCHITECTURE.md | 9 +- ...63.0-leftover-map-compare-plot-coverage.md | 22 ++ CHANGELOG.md | 68 +++++ CLAUDE.md | 2 +- docs/adr/0281-leftover-map-plot-coverage.md | 3 + docs/adr/0304-leftover-map-compare-graphic.md | 4 +- ...05-leftover-map-compare-plot-axis-share.md | 3 + ...0306-leftover-map-compare-plot-coverage.md | 244 ++++++++++++++++++ docs/product-technical-gap-baseline.md | 19 ++ docs/storybook-inventory.md | 2 +- frontend/package.json | 2 +- frontend/src/App.test.tsx | 18 ++ frontend/src/App.tsx | 1 + .../components/LeftoverMapPlot.stories.tsx | 13 + .../src/components/LeftoverMapPlot.test.tsx | 116 +++++++++ frontend/src/components/LeftoverMapPlot.tsx | 22 +- frontend/src/components/LeftoverPairList.tsx | 4 +- frontend/src/i18n.test.ts | 11 + frontend/src/i18n.ts | 4 + frontend/src/leftoverMapCoverage.test.ts | 8 + frontend/src/leftoverMapCoverage.ts | 5 +- frontend/src/leftoverMapPlotLayout.ts | 10 +- pyproject.toml | 2 +- uv.lock | 2 +- 25 files changed, 589 insertions(+), 21 deletions(-) create mode 100644 CHANGELOG.d/2.63.0-leftover-map-compare-plot-coverage.md create mode 100644 docs/adr/0306-leftover-map-compare-plot-coverage.md diff --git a/AGENTS.md b/AGENTS.md index eeba070b6..ef3a9a1eb 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 / 0293 / 0294 / 0295 / 0296 / 0297 / 0298 / 0299 / 0300 / 0301 / 0302 / 0303 / 0304 / 0305) 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 / 0294 / 0295 / 0296 / 0297 / 0298 / 0299 / 0300 / 0301 / 0302 / 0303 / 0304 / 0305 / 0306) 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 @@ -494,6 +494,17 @@ non-finite share omits that leftover-map comparison axis share badge and keeps leftover map comparison axis text. Do not invent leftover-map axis share from leftover-map rank, leftover-map distance, leftover-map reconstruction, leftover residual, leftover pair count, or the count of unused axes. +ADR 0306 captions leftover-map complete-case coverage on that grouping +comparison leftover-map graphic when leftoverMapCoverageCounts returns usable +complete-case integers; a missing, non-integer, negative-used, non-positive-scored, +or used-greater-than-scored coverage omits that leftover-map comparison graphic +coverage caption and keeps leftover map comparison axis share when finite. +Do not invent leftover-map coverage from plotted marker count, leftover pair +count, leftover-map rank, leftover-map distance, leftover-map axis share, +leftover-map reconstruction, leftover residual, leftover-map item coverage, +leftover-map incomplete post coverage, leftover-map incomplete item coverage, +or the count of unused axes. This increment does not caption leftover-map item +coverage or leftover-map incomplete coverage on the comparison 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 @@ -543,6 +554,9 @@ graphic of those already-named coordinates above grouping comparison leftover-pa buttons when four leftover-map axes are finite. Grouping comparison leftover-map axis share (ADR 0305) captions that grouping comparison leftover-map graphic with persisted leftover-map axis share. +Grouping comparison leftover-map complete-case coverage (ADR 0306) captions that +grouping comparison leftover-map graphic with persisted leftover-map complete-case +coverage when leftoverMapCoverageCounts returns usable complete-case integers. 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 527a5e0e9..6dbd73d35 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -704,6 +704,10 @@ ADR 0305 returns persisted leftover-map axes on `GET /api/reports/compare/{period}` and captions leftover-map axis share on that grouping comparison leftover-map graphic when the persisted share is finite. +ADR 0306 captions leftover-map complete-case coverage on that grouping +comparison leftover-map graphic when leftoverMapCoverageCounts returns usable +complete-case integers and does not caption leftover-map item coverage or +leftover-map incomplete coverage on that comparison plot. 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 @@ -736,8 +740,9 @@ incomplete item coverage (ADR 0292), leftover-map reconstruction `R̂` (ADR 0301), leftover-map coordinates `ξ` / `ζ` (ADR 0302), leftover-map coordinates on the compare leftover-pair payload (ADR 0303), leftover-map graphic display on the grouping comparison strip -(ADR 0304), and leftover-map axis share on the grouping comparison leftover-map -graphic (ADR 0305); +(ADR 0304), leftover-map axis share on the grouping comparison leftover-map +graphic (ADR 0305), and leftover-map complete-case coverage on the grouping +comparison leftover-map graphic (ADR 0306); `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 diff --git a/CHANGELOG.d/2.63.0-leftover-map-compare-plot-coverage.md b/CHANGELOG.d/2.63.0-leftover-map-compare-plot-coverage.md new file mode 100644 index 000000000..cf85e614a --- /dev/null +++ b/CHANGELOG.d/2.63.0-leftover-map-compare-plot-coverage.md @@ -0,0 +1,22 @@ +## 2.63.0 — Leftover-map complete-case coverage on grouping comparison leftover-map graphic + +- Caption leftover-map complete-case coverage on the grouping comparison + leftover-map graphic (ADR 0306). 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, and a + plot caption that matches leftover-map complete-case coverage on the + grouping comparison leftover-map graphic; 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 graphic coverage caption and keeps leftover map + comparison axis share when finite. Coverage `0 of M` is shown when that + persisted used count is a non-negative integer. Comparison copy uses + `Leftover map comparison graphic coverage` so it stays distinct from + hyphen `Leftover-map graphic coverage` and from strip + `Leftover map comparison coverage`. This increment does not caption + leftover-map item coverage, leftover-map incomplete post coverage, or + leftover-map incomplete item coverage on the comparison graphic. Do not + invent coverage from plotted marker count, leftover pair count, leftover-map + rank, leftover-map distance, leftover-map axis share, or leftover-map + reconstruction. Never invent a leftover score. Never invent a theta. No + new columns. diff --git a/CHANGELOG.md b/CHANGELOG.md index c16d24665..60549a04c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,74 @@ All notable changes to this project are documented here. Format follows ### Added +- Period leftover pairs now name leftover-map complete-case coverage on the + grouping comparison leftover-map graphic (ADR 0306 / v2.63.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 axis share on the grouping comparison leftover-map + graphic 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, grouping comparison leftover-pair buttons that match + leftover-map reconstruction `R̂` on the pair row, grouping comparison leftover-pair + buttons that match leftover-map explained leftover share `e` on the pair row, + grouping comparison leftover-pair buttons that match leftover-map unexplained + leftover share `s` on the pair row, grouping comparison leftover-pair buttons + that match leftover-map cross share `x` on the pair row, grouping comparison + leftover-pair buttons that match leftover-map unexplained leftover `U` on the + pair row, grouping comparison leftover-pair buttons that match leftover residual + `R` on the pair row, grouping comparison leftover-pair buttons that match leftover + observed `Y` on the pair row, grouping comparison leftover-pair buttons that match + leftover expected `E` on the pair row, grouping comparison leftover-pair buttons + that match leftover-map rank on the pair row, grouping comparison leftover-pair + buttons that match leftover-map coordinates `ξ` / `ζ` on the pair row, a live + compare payload that carries those persisted leftover-map coordinates, the + grouping comparison leftover-map graphic of those already-named coordinates when + four leftover-map axes are finite, leftover-map axis share on that grouping + comparison leftover-map graphic when the persisted share is finite, and leftover-map + complete-case coverage on that grouping comparison leftover-map graphic when + leftoverMapCoverageCounts returns usable complete-case integers; 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 graphic coverage caption and keeps leftover map comparison axis share + when finite, leftover map comparison axis text, leftover-map rank when that rank + is a non-negative integer, leftover expected `E` when finite, leftover observed + `Y` when finite, leftover residual `R` when finite, leftover-map unexplained leftover + `U` when finite, leftover-map cross share `x` when finite, leftover-map unexplained leftover + share `s` when finite, leftover-map explained leftover share `e` when finite, + leftover-map reconstruction `R̂` when finite, leftover-map distance `d`, plus + the strip coverage notes. Coverage `0 of M` is shown when that persisted used + count is a non-negative integer. Rank-0 origin cells still plot at `(0, 0)` and + still name coverage when that coverage is persisted. Comparison copy uses + `Leftover map comparison graphic coverage` so it stays distinct from hyphen + `Leftover-map graphic coverage` and from strip `Leftover map comparison coverage`. + This increment does not caption leftover-map item coverage, leftover-map incomplete + post coverage, or leftover-map incomplete item coverage on the comparison graphic. + Do not invent leftover-map coverage from plotted marker count, leftover pair count, + leftover-map rank, leftover-map distance, leftover-map axis share, leftover expected, + leftover observed, leftover residual, leftover-map reconstruction, leftover-map + unexplained leftover, leftover-map item coverage, leftover-map incomplete post + coverage, leftover-map incomplete item coverage, or the count of unused axes. A + finite negative leftover is shown, never clamped. Omit the comparison graphic + when no leftover pair has four finite leftover-map coordinates. Never invent + a leftover score or a theta. No new columns. + - Period leftover pairs now name leftover-map axis share on the grouping comparison leftover-map graphic (ADR 0305 / v2.62.0). After `make seed`, closest and farthest leftover pairs sit above the member list with the diff --git a/CLAUDE.md b/CLAUDE.md index faac96d2c..03e1db9a3 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 / 0295 / 0296 / 0297 / 0298 / 0299 / 0300 / 0301 / 0302 / 0303 / 0304 / 0305), 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 / 0295 / 0296 / 0297 / 0298 / 0299 / 0300 / 0301 / 0302 / 0303 / 0304 / 0305 / 0306), 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/docs/adr/0281-leftover-map-plot-coverage.md b/docs/adr/0281-leftover-map-plot-coverage.md index 2d66236b5..55deb400d 100644 --- a/docs/adr/0281-leftover-map-plot-coverage.md +++ b/docs/adr/0281-leftover-map-plot-coverage.md @@ -3,6 +3,9 @@ **Decision status:** Accepted **Date:** 2026-08-30 +**Amended by:** [ADR 0306](0306-leftover-map-compare-plot-coverage.md) +(leftover-map complete-case coverage on the grouping comparison leftover-map graphic) + Amends [ADR 0268](0268-leftover-map-graphic-display.md), [ADR 0049](0049-leftover-pair-report-ui.md), and leftover-map complete-case coverage ([ADR 0168](0168-leftover-map-complete-case-coverage.md)). Independent of diff --git a/docs/adr/0304-leftover-map-compare-graphic.md b/docs/adr/0304-leftover-map-compare-graphic.md index f0cbd192c..bff105cf4 100644 --- a/docs/adr/0304-leftover-map-compare-graphic.md +++ b/docs/adr/0304-leftover-map-compare-graphic.md @@ -4,7 +4,9 @@ **Date:** 2026-08-31 **Amended by:** [ADR 0305](0305-leftover-map-compare-plot-axis-share.md) -(leftover-map axis share on the grouping comparison leftover-map graphic) +(leftover-map axis share on the grouping comparison leftover-map graphic), +[ADR 0306](0306-leftover-map-compare-plot-coverage.md) +(leftover-map complete-case coverage on the grouping comparison leftover-map graphic) Amends leftover pairs on the grouping comparison strip ([ADR 0149](0149-leftover-pairs-on-comparison-strip.md)), leftover-map diff --git a/docs/adr/0305-leftover-map-compare-plot-axis-share.md b/docs/adr/0305-leftover-map-compare-plot-axis-share.md index 84245f236..ed6c53c79 100644 --- a/docs/adr/0305-leftover-map-compare-plot-axis-share.md +++ b/docs/adr/0305-leftover-map-compare-plot-axis-share.md @@ -3,6 +3,9 @@ **Decision status:** Accepted **Date:** 2026-08-31 +**Amended by:** [ADR 0306](0306-leftover-map-compare-plot-coverage.md) +(leftover-map complete-case coverage on the grouping comparison leftover-map graphic) + Amends leftover-map axis share on the graphic display ([ADR 0269](0269-leftover-map-axis-share-plot.md)), leftover-map graphic display on the grouping comparison strip diff --git a/docs/adr/0306-leftover-map-compare-plot-coverage.md b/docs/adr/0306-leftover-map-compare-plot-coverage.md new file mode 100644 index 000000000..97009bd32 --- /dev/null +++ b/docs/adr/0306-leftover-map-compare-plot-coverage.md @@ -0,0 +1,244 @@ +# ADR 0306 — Name leftover-map complete-case coverage on the grouping comparison leftover-map graphic + +**Decision status:** Accepted +**Date:** 2026-08-31 + +Amends leftover-map complete-case coverage on the graphic display +([ADR 0281](0281-leftover-map-plot-coverage.md)), leftover-map graphic +display on the grouping comparison strip +([ADR 0304](0304-leftover-map-compare-graphic.md)), leftover-map axis share +on the grouping comparison leftover-map graphic +([ADR 0305](0305-leftover-map-compare-plot-axis-share.md)), leftover-map +complete-case coverage persistence +([ADR 0168](0168-leftover-map-complete-case-coverage.md)), leftover pairs on +the grouping comparison strip +([ADR 0149](0149-leftover-pairs-on-comparison-strip.md)), leftover-map +coordinates on the compare leftover-pair payload +([ADR 0303](0303-leftover-map-compare-coordinates-payload.md)), leftover-map +coordinates on grouping comparison strip pair rows +([ADR 0302](0302-leftover-map-compare-coordinates.md)), leftover-map +rank on grouping comparison strip pair rows +([ADR 0301](0301-leftover-map-compare-rank.md)), leftover expected on grouping +comparison strip pair rows +([ADR 0300](0300-leftover-map-compare-expected.md)), leftover observed on +grouping comparison strip pair rows +([ADR 0299](0299-leftover-map-compare-observed.md)), leftover residual +on grouping comparison strip pair rows +([ADR 0298](0298-leftover-map-compare-residual.md)), leftover-map unexplained leftover +on grouping comparison strip pair rows +([ADR 0297](0297-leftover-map-compare-unexplained.md)), leftover-map cross share +on grouping comparison strip pair rows +([ADR 0296](0296-leftover-map-compare-cross-share.md)), leftover-map unexplained +leftover share on grouping comparison strip pair rows +([ADR 0295](0295-leftover-map-compare-unexplained-share.md)), leftover-map +explained leftover share on grouping comparison strip pair rows +([ADR 0294](0294-leftover-map-compare-explained-share.md)), leftover-map +reconstruction on grouping comparison strip pair rows +([ADR 0293](0293-leftover-map-compare-reconstruction.md)), leftover-map +incomplete item coverage on the grouping comparison strip +([ADR 0292](0292-leftover-map-compare-incomplete-item.md)), leftover-map +incomplete post coverage on the grouping comparison strip +([ADR 0291](0291-leftover-map-compare-incomplete-post.md)), leftover-map item +complete-case coverage on the grouping comparison strip +([ADR 0290](0290-leftover-map-compare-item-coverage.md)), leftover-map +complete-case coverage on the grouping comparison strip +([ADR 0289](0289-leftover-map-compare-coverage.md)), leftover residual +disclosure ([ADR 0162](0162-leftover-residual-disclosure.md)), leftover +observed `Y` / expected `E` ([ADR 0163](0163-leftover-observed-expected.md)), leftover-map unexplained leftover persistence ([ADR 0182](0182-leftover-map-unexplained.md)), +leftover-map reconstruction persistence +([ADR 0201](0201-leftover-map-reconstruction.md)), leftover-map rank +([ADR 0164](0164-leftover-map-rank.md)), leftover-map rank on pair segments +([ADR 0280](0280-leftover-map-segment-rank.md)), leftover-map coordinate ticks +([ADR 0270](0270-leftover-map-coordinate-ticks.md)), leftover-map graphic display +([ADR 0268](0268-leftover-map-graphic-display.md)), leftover-map axis share on +the graphic display ([ADR 0269](0269-leftover-map-axis-share-plot.md)), and leftover-map coordinates +([ADR 0267](0267-leftover-map-coordinates.md)). Independent of leftover-map +post complete-case coverage fail-closed on the pair list +([ADR 0288](0288-leftover-map-list-post-coverage-helper.md)), leftover-map +incomplete item coverage on the pair list +([ADR 0287](0287-leftover-map-list-incomplete-item.md)), leftover-map incomplete +post coverage on the pair list +([ADR 0286](0286-leftover-map-list-incomplete-post.md)), leftover-map item +complete-case coverage on the pair list +([ADR 0285](0285-leftover-map-list-item-coverage.md)), leftover-map incomplete +item coverage on the graphic display +([ADR 0284](0284-leftover-map-plot-incomplete-item.md)), leftover-map incomplete +post coverage on the graphic display +([ADR 0283](0283-leftover-map-plot-incomplete.md)), leftover-map item +complete-case coverage on the graphic display +([ADR 0282](0282-leftover-map-plot-item-coverage.md)), leftover expected on pair +segments ([ADR 0279](0279-leftover-map-segment-expected.md)), leftover observed +on pair segments ([ADR 0278](0278-leftover-map-segment-observed.md)), leftover +residual on pair segments ([ADR 0277](0277-leftover-map-segment-residual.md)), +leftover-map unexplained leftover on pair segments +([ADR 0276](0276-leftover-map-segment-unexplained-leftover.md)), leftover-map +cross share on pair segments ([ADR 0275](0275-leftover-map-segment-cross-share.md)), +leftover-map unexplained leftover share on pair segments +([ADR 0274](0274-leftover-map-segment-unexplained-share.md)), leftover-map +explained leftover share on pair segments +([ADR 0273](0273-leftover-map-segment-explained-share.md)), leftover-map +reconstruction on pair segments +([ADR 0272](0272-leftover-map-segment-reconstruction.md)), leftover-map +distance on pair segments ([ADR 0271](0271-leftover-map-segment-distance.md)), +leftover-map cross share persistence ([ADR 0185](0185-leftover-map-cross-share.md)), leftover-map +unexplained leftover share persistence +([ADR 0233](0233-leftover-map-unexplained-share.md)), leftover-map explained leftover +share persistence ([ADR 0266](0266-leftover-map-explained-share.md)), leftover-map +item complete-case coverage on the grouping comparison leftover-map graphic, leftover-map +incomplete post coverage on the grouping comparison leftover-map graphic, and leftover-map +incomplete item coverage on the grouping comparison leftover-map graphic. + +## Context + +ADR 0168 already persists one `report_leftover_map_coverage` row per period +report. ADR 0281 already captions the period-report leftover-map graphic with +`Leftover map used N of M scored posts (complete-case)` under accessible name +`Leftover-map graphic coverage`. ADR 0289 already captions the grouping +comparison strip with that same body under accessible name +`Leftover map comparison coverage`. ADR 0304 already draws the leftover-map +graphic of persisted `ξ_{1:2}` / `ζ_{1:2}` above grouping comparison leftover-pair +buttons. ADR 0305 already captions leftover-map axis share on that graphic. +The comparison graphic still omits leftover-map coverage, so a buyer who reads +two pair markers can treat those markers as the scored-post census even after +the strip note names `2 of 3`. Incomplete rows are dropped from Gabriel +factorization; hiding coverage on the comparison graphic lets a sparse post +with one missing criterion vanish without a next action. + +This increment captions leftover-map complete-case coverage on the grouping +comparison leftover-map graphic from already-named `leftover_map_coverage`. +Comparison copy uses the accessible name +`Leftover map comparison graphic coverage` so it stays distinct from hyphen +`Leftover-map graphic coverage` on the period-report graphic and from strip +`Leftover map comparison coverage`. It does not add columns. It does not +recompute leftover-map coverage from leftover-map rank, leftover-map +distance, leftover expected, leftover observed, leftover residual, +leftover-map reconstruction, leftover-map unexplained leftover, +leftover-map axis share, leftover-map item coverage, leftover-map +incomplete post coverage, leftover-map incomplete item coverage, plotted +marker count, leftover pair count, 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. + +The dashboard stack already used neighbouring leftover facts under other +numbers. This protected increment uses **0306** so it does not collide with +leftover-map axis share on the grouping comparison leftover-map graphic (0305), leftover-map +graphic display on the grouping comparison strip (0304), leftover-map +coordinates on the compare leftover-pair payload (0303), leftover-map +coordinates on grouping comparison strip pair rows (0302), leftover-map +rank on grouping comparison strip pair rows (0301), leftover-map complete-case +coverage on the graphic display (0281), leftover-map complete-case coverage +on the grouping comparison strip (0289), leftover-map graphic display (0268), leftover-map coordinates (0267), or +the dashboard stacks. + +## Decision + +On the grouping comparison leftover-map graphic, caption persisted leftover-map +complete-case coverage as `Leftover map used N of M scored posts +(complete-case)`, using the same `map_post_count` / `scored_post_count` +integers the strip note already shows through leftoverMapCoverageCounts. +Use the distinct accessible name `Leftover map comparison graphic coverage` +so the graphic caption is not the strip note (`Leftover map comparison coverage`) +and is not the period-report graphic caption (`Leftover-map graphic coverage`). +A missing coverage row, a non-integer count, a negative used count, a +non-positive scored count, or used greater than scored omits that leftover-map +comparison graphic coverage caption and keeps leftover map comparison axis +share when finite, leftover map comparison axis text, leftover-map rank when +that rank is a non-negative integer, leftover expected `E` when finite, +leftover observed `Y` when finite, leftover residual `R` when finite, +leftover-map unexplained leftover `U` when finite, leftover-map cross share +`x` when finite, leftover-map unexplained leftover share `s` when finite, +leftover-map explained leftover share `e` when finite, leftover-map +reconstruction `R̂` when finite, leftover-map distance `d`, plus the strip +coverage notes. Coverage `0 of M` is shown when that persisted used count +is a non-negative integer and scored is a positive integer. Rank-0 origin +cells still name coverage when that coverage is persisted. Do not invent +coverage from plotted marker count, leftover pair count, leftover-map rank, +leftover-map distance, leftover-map axis share, leftover expected, leftover +observed, leftover residual, leftover-map reconstruction, leftover-map +unexplained leftover, leftover-map item coverage, leftover-map incomplete +post coverage, leftover-map incomplete item coverage, or the count of unused +axes. Click a post marker to open that post. + +This increment does not caption leftover-map item complete-case coverage, +leftover-map incomplete post coverage, or leftover-map incomplete item +coverage on the comparison graphic. Those notes already sit on the strip +through ADR 0290–0292. A finite negative leftover on neighbouring fields is +shown, never clamped. + +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`, grouping comparison leftover pairs that already show +the leftover-map graphic of persisted `ξ` / `ζ` also name leftover-map +complete-case coverage on that graphic when leftoverMapCoverageCounts +returns usable complete-case integers. Rank-0 unused axes still plot at +the origin and still name coverage when that coverage is persisted. Click +a post marker or a pair button opens that post. Hidden posts stay hidden. +When `Y`, `E`, and `R` are finite, `Y − E = R`. When `R`, `R̂`, and `U` +are finite, `U + R̂ = R`. When `R`, `R̂`, `U`, `x`, `s`, and `e` are +finite, `e + s + x = 1`. When coordinates, reconstruction, and distance +are finite, `R̂ = ξ · ζ` and `d = ‖ξ − ζ‖`. + +## Related + +Independent of leftover interaction-map persistence, leftover-criterion +evaluation landing, leftover residual disclosure, leftover-map +complete-case coverage 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 reconstruction on grouping comparison strip pair rows, +leftover-map explained leftover share on grouping comparison strip pair rows, +leftover-map unexplained leftover share on grouping comparison strip pair rows, +leftover-map cross share on grouping comparison strip pair rows, +leftover-map unexplained leftover on grouping comparison strip pair rows, +leftover residual on grouping comparison strip pair rows, leftover observed +on grouping comparison strip pair rows, leftover expected on grouping +comparison strip pair rows, leftover-map rank on grouping comparison strip +pair rows, leftover-map coordinates on grouping comparison strip pair rows, +leftover-map coordinates on the compare leftover-pair payload, leftover-map +inner product, leftover-map cosine, leftover-map length, leftover residual +on pair segments, leftover observed on pair segments, leftover expected on +pair segments, leftover-map rank on pair segments, leftover-map unexplained +leftover on pair segments, leftover-map unexplained leftover persistence, +leftover-map cross share on pair segments, leftover-map cross share +persistence, leftover-map unexplained leftover share on pair segments, +leftover-map unexplained leftover share persistence, leftover-map explained +leftover share on pair segments, leftover-map explained leftover share +persistence, leftover-map reconstruction on pair segments, leftover-map +reconstruction persistence, leftover-map item complete-case coverage on the +graphic display, leftover-map item complete-case coverage on the pair list, +leftover-map incomplete post coverage on the graphic display, leftover-map +incomplete post coverage on the pair list, leftover-map incomplete item +coverage on the graphic display, leftover-map incomplete item coverage on +the pair list, leftover-map post complete-case coverage fail-closed on the +pair list, leftover-map rank persistence, leftover-map coordinate +persistence, leftover-map coordinate ticks, leftover-map complete-case +coverage on the graphic display, leftover-map axis share on the grouping +comparison leftover-map graphic, leftover-map item complete-case coverage +on the grouping comparison leftover-map graphic, leftover-map incomplete +post coverage on the grouping comparison leftover-map graphic, and leftover-map +incomplete item coverage on the grouping comparison leftover-map graphic. + +## References + +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. Incomplete rows +are dropped from the complete-case residual rectangle; coverage names how +many scored posts entered that factorization. Grouping comparison leftover-map +complete-case coverage captions those persisted used/scored post counts on +the grouping comparison leftover-map graphic only when leftoverMapCoverageCounts +returns usable complete-case integers. Rank-0 unused axes still name coverage +when that coverage is stored.) + +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 diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index d204a40eb..06757c23d 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -1,5 +1,24 @@ # Product & Technical Gap Baseline +> Exact-head loop overlay: 2026-08-31 04:23 KST. Protected `main` is +> `cb187cadee5fb6c46d8a944815ccc154a1e028d1`. Writes work. Do not +> self-approve. #844 leftover-map axis share on the grouping comparison leftover-map +> graphic (v2.62.0 / ADR 0305) is `95538f9`, stacked on #841 @ `ee467df`. +> Next buyer increment on this cycle: leftover-map complete-case coverage on +> the grouping comparison leftover-map graphic (ADR 0306 / v2.63.0) delivered +> locally on `feat/leftover-map-compare-plot-coverage-v2630`. Caption leftover +> map used N of M scored posts (complete-case) on that comparison graphic from +> already-named leftover_map_coverage. Distinct accessible name `Leftover map +> comparison graphic coverage`. Omit when leftoverMapCoverageCounts fail-closes. +> Do not caption leftover-map item coverage or leftover-map incomplete coverage +> on that comparison graphic this increment. Do not invent leftover-map coverage +> from plotted marker count, leftover pair count, leftover-map rank, leftover-map +> distance, leftover-map axis share, or leftover-map reconstruction. Stack onto +> #844. Leave open for independent review. Do not squash-merge. Issues #79 and +> #87 stay open. #96 is already closed. Do not merge #808 without independent +> APPROVE. + + > Exact-head loop overlay: 2026-08-31 03:45 KST. Protected `main` is > `cb187cadee5fb6c46d8a944815ccc154a1e028d1`. Writes work. Do not > self-approve. #841 leftover-map graphic on the grouping comparison strip diff --git a/docs/storybook-inventory.md b/docs/storybook-inventory.md index 485085734..dc41941d6 100644 --- a/docs/storybook-inventory.md +++ b/docs/storybook-inventory.md @@ -5,7 +5,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/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. The comparison variant names leftover-map complete-case coverage under `Leftover map comparison graphic coverage` and omits leftover-map item coverage and leftover-map incomplete coverage on that comparison plot. `ClosestAndFarthest`, `RankZeroOrigin`, `MissingCoordinates`, `MissingAxisShare`, `Comparison`, and `ComparisonMissingCoverage` 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, missing share that keeps existing leftover-map axis text, grouping comparison leftover-map graphic coverage that matches leftover map used N of M scored posts, and omitted comparison graphic coverage when leftoverMapCoverageCounts fail-closes. 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, and leftover-map incomplete item coverage with distinct comparison labels when leftoverMapCoverageCounts / leftoverMapItemCoverageCounts / leftoverMapIncompletePostCount / leftoverMapIncompleteItemCount return usable integers. | `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` | diff --git a/frontend/package.json b/frontend/package.json index fbbea5673..3c312155a 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "frontend", "private": true, - "version": "2.62.0", + "version": "2.63.0", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/src/App.test.tsx b/frontend/src/App.test.tsx index c18eb3abc..e3fb40521 100644 --- a/frontend/src/App.test.tsx +++ b/frontend/src/App.test.tsx @@ -4219,6 +4219,9 @@ describe("App, authenticated", () => { expect(screen.getByLabelText("Leftover-map graphic coverage")).toHaveTextContent( "Leftover map used 2 of 3 scored posts (complete-case)", ); + expect(screen.getByLabelText("Leftover map comparison graphic coverage")).toHaveTextContent( + "Leftover map used 2 of 3 scored posts (complete-case)", + ); expect(screen.getByLabelText("Leftover-map graphic item coverage")).toHaveTextContent( "Leftover map used 2 of 2 scored criteria (complete-case)", ); @@ -4342,6 +4345,21 @@ describe("App, authenticated", () => { "Leftover map comparison coverage", ), ).toHaveLength(1); + expect( + within(screen.getByLabelText("Grouping comparison")).getByLabelText( + "Leftover map comparison graphic coverage", + ), + ).toHaveTextContent("Leftover map used 2 of 3 scored posts (complete-case)"); + expect( + within(screen.getByLabelText("Grouping comparison")).getAllByLabelText( + "Leftover map comparison graphic coverage", + ), + ).toHaveLength(1); + expect( + within(screen.getByLabelText("Grouping comparison")).queryByLabelText( + "Leftover-map graphic coverage", + ), + ).not.toBeInTheDocument(); expect( within(screen.getByLabelText("Grouping comparison")).queryByLabelText("Leftover map item coverage"), ).not.toBeInTheDocument(); diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 0370acc97..dfa30ed1b 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -4094,6 +4094,7 @@ function ReportsPanel({ { diff --git a/frontend/src/components/LeftoverMapPlot.stories.tsx b/frontend/src/components/LeftoverMapPlot.stories.tsx index 8a1d58015..7d2b4fe20 100644 --- a/frontend/src/components/LeftoverMapPlot.stories.tsx +++ b/frontend/src/components/LeftoverMapPlot.stories.tsx @@ -137,3 +137,16 @@ export const MissingAxisShare: Story = { ], }, }; + +export const Comparison: Story = { + args: { + variant: "comparison", + }, +}; + +export const ComparisonMissingCoverage: Story = { + args: { + variant: "comparison", + leftoverMapCoverage: undefined, + }, +}; diff --git a/frontend/src/components/LeftoverMapPlot.test.tsx b/frontend/src/components/LeftoverMapPlot.test.tsx index 3a239b484..93e3b9955 100644 --- a/frontend/src/components/LeftoverMapPlot.test.tsx +++ b/frontend/src/components/LeftoverMapPlot.test.tsx @@ -893,4 +893,120 @@ describe("LeftoverMapPlot", () => { expect(screen.getByText("leftover map comparison axis 1 (0%)")).toBeInTheDocument(); expect(screen.getByText("leftover map comparison axis 2 (0%)")).toBeInTheDocument(); }); + + it("names leftover-map coverage on the comparison graphic with a distinct accessible name", () => { + render( + , + ); + expect(screen.getByLabelText("Leftover map comparison graphic coverage")).toHaveTextContent( + "Leftover map used 2 of 3 scored posts (complete-case)", + ); + expect(screen.queryByLabelText("Leftover-map graphic coverage")).not.toBeInTheDocument(); + expect(screen.queryByLabelText("Leftover map comparison coverage")).not.toBeInTheDocument(); + expect(screen.queryByLabelText("Leftover-map graphic item coverage")).not.toBeInTheDocument(); + expect(screen.queryByLabelText("Leftover-map graphic incomplete posts")).not.toBeInTheDocument(); + expect(screen.queryByLabelText("Leftover-map graphic incomplete items")).not.toBeInTheDocument(); + expect(screen.getByText("leftover map comparison axis 1 (82%)")).toBeInTheDocument(); + expect(screen.getByText("leftover map comparison axis 2 (18%)")).toBeInTheDocument(); + }); + + it("omits leftover-map comparison graphic coverage when coverage is missing or not usable", () => { + const { rerender } = render( + , + ); + expect(screen.queryByLabelText("Leftover map comparison graphic coverage")).not.toBeInTheDocument(); + expect(screen.getByLabelText("Leftover map comparison graphic")).toBeInTheDocument(); + expect(screen.getByText("leftover map comparison axis 1 (82%)")).toBeInTheDocument(); + rerender( + , + ); + expect(screen.queryByLabelText("Leftover map comparison graphic coverage")).not.toBeInTheDocument(); + expect(screen.queryByLabelText("Leftover-map graphic coverage")).not.toBeInTheDocument(); + expect(screen.getByText("leftover map comparison axis 1 (82%)")).toBeInTheDocument(); + }); + + it("names leftover-map comparison graphic coverage 0 of M on a rank-0 origin when that persisted used count is a non-negative integer", () => { + render( + , + ); + expect(screen.getByLabelText("Leftover map comparison graphic coverage")).toHaveTextContent( + "Leftover map used 0 of 3 scored posts (complete-case)", + ); + expect(screen.queryByLabelText("Leftover-map graphic coverage")).not.toBeInTheDocument(); + expect(screen.queryByLabelText("Leftover-map graphic item coverage")).not.toBeInTheDocument(); + expect(screen.getByText("leftover map comparison axis 1 (0%)")).toBeInTheDocument(); + expect(screen.getByText("leftover map comparison axis 2 (0%)")).toBeInTheDocument(); + }); }); diff --git a/frontend/src/components/LeftoverMapPlot.tsx b/frontend/src/components/LeftoverMapPlot.tsx index 375e4d5a2..6c0a82d26 100644 --- a/frontend/src/components/LeftoverMapPlot.tsx +++ b/frontend/src/components/LeftoverMapPlot.tsx @@ -6,6 +6,7 @@ import { leftoverMapIncompleteItemCount, leftoverMapIncompletePostCount, leftoverMapItemCoverageCounts, + LEFTOVER_MAP_COMPARE_PLOT_COVERAGE_LABEL, LEFTOVER_MAP_PLOT_COVERAGE, LEFTOVER_MAP_PLOT_COVERAGE_LABEL, LEFTOVER_MAP_PLOT_INCOMPLETE_ITEM, @@ -118,10 +119,13 @@ function leftoverMapPlotAxisText( * missing or non-finite and keep the existing leftover-map axis text. * Omit the plot when no pair has four finite leftover-map coordinates. * ADR 0304 reuses this graphic on the grouping comparison strip from - * already-named leftover-map coordinates and does not caption leftover-map - * coverage on that comparison plot. ADR 0305 captions leftover-map axis + * already-named leftover-map coordinates. ADR 0305 captions leftover-map axis * share on that comparison graphic from already-named leftover-map axes - * with distinct leftover map comparison axis labels. + * with distinct leftover map comparison axis labels. ADR 0306 captions leftover-map + * complete-case coverage on that comparison graphic from already-named + * leftover-map coverage with distinct leftover map comparison graphic coverage + * labels and does not caption leftover-map item coverage or leftover-map + * incomplete coverage on that comparison plot. * Never invent a leftover score. */ export function LeftoverMapPlot({ @@ -160,12 +164,16 @@ export function LeftoverMapPlot({

{tf(LEFTOVER_MAP_PLOT_COVERAGE, coverageCounts)}

) : null} - {itemCoverageCounts !== null ? ( + {variant !== "comparison" && itemCoverageCounts !== null ? (

) : null} - {incompletePostCount !== null ? ( + {variant !== "comparison" && incompletePostCount !== null ? (

) : null} - {incompleteItemCount !== null ? ( + {variant !== "comparison" && incompleteItemCount !== null ? (

{ "leftover-map rank {label}", "Leftover-map graphic coverage", "Leftover map comparison coverage", + "Leftover map comparison graphic coverage", "Leftover map comparison item coverage", "Leftover map comparison incomplete posts", "Leftover map comparison incomplete items", @@ -410,6 +411,16 @@ describe("i18n", () => { expect(t("Leftover map comparison coverage")).toBe(expected); }); + it.each([ + ["ko", "잔여 지도 비교 그림 포함 범위"], + ["zh", "残差地图比较图形覆盖范围"], + ["ja", "残差マップの比較図対象範囲"], + ["vi", "Phạm vi đồ họa so sánh bản đồ phần dư"], + ] as const)("formats leftover map comparison graphic coverage label in %s", (locale, expected) => { + setLocale(locale); + expect(t("Leftover map comparison graphic coverage")).toBe(expected); + }); + it.each([ ["ko", "잔여 지도 비교 기준 포함 범위"], ["zh", "残差地图比较准则覆盖范围"], diff --git a/frontend/src/i18n.ts b/frontend/src/i18n.ts index ef1999fdc..27baa3d25 100644 --- a/frontend/src/i18n.ts +++ b/frontend/src/i18n.ts @@ -269,6 +269,7 @@ const TRANSLATIONS: Partial>> = { "Period reports": "기간 리포트", "Leftover map coverage": "잔여 지도 포함 범위", "Leftover map comparison coverage": "잔여 지도 비교 포함 범위", + "Leftover map comparison graphic coverage": "잔여 지도 비교 그림 포함 범위", "Leftover map comparison item coverage": "잔여 지도 비교 기준 포함 범위", "Leftover map comparison incomplete posts": "잔여 지도 비교 불완전 글", "Leftover map comparison incomplete items": "잔여 지도 비교 불완전 기준", @@ -896,6 +897,7 @@ const TRANSLATIONS: Partial>> = { "Period reports": "周期报告", "Leftover map coverage": "残差地图覆盖范围", "Leftover map comparison coverage": "残差地图比较覆盖范围", + "Leftover map comparison graphic coverage": "残差地图比较图形覆盖范围", "Leftover map comparison item coverage": "残差地图比较准则覆盖范围", "Leftover map comparison incomplete posts": "残差地图比较不完整帖文", "Leftover map comparison incomplete items": "残差地图比较不完整准则", @@ -1544,6 +1546,7 @@ const TRANSLATIONS: Partial>> = { "Period reports": "期間レポート", "Leftover map coverage": "残差マップの対象範囲", "Leftover map comparison coverage": "残差マップの比較対象範囲", + "Leftover map comparison graphic coverage": "残差マップの比較図対象範囲", "Leftover map comparison item coverage": "残差マップの比較基準対象範囲", "Leftover map comparison incomplete posts": "残差マップの比較不完全投稿", "Leftover map comparison incomplete items": "残差マップの比較不完全基準", @@ -2171,6 +2174,7 @@ const TRANSLATIONS: Partial>> = { "Period reports": "Báo cáo theo kỳ", "Leftover map coverage": "Phạm vi bản đồ phần dư", "Leftover map comparison coverage": "Phạm vi so sánh bản đồ phần dư", + "Leftover map comparison graphic coverage": "Phạm vi đồ họa so sánh bản đồ phần dư", "Leftover map comparison item coverage": "Phạm vi so sánh tiêu chí bản đồ phần dư", "Leftover map comparison incomplete posts": "Bài không đầy đủ so sánh trên bản đồ phần dư", "Leftover map comparison incomplete items": "Tiêu chí không đầy đủ so sánh trên bản đồ phần dư", diff --git a/frontend/src/leftoverMapCoverage.test.ts b/frontend/src/leftoverMapCoverage.test.ts index 82f575c17..72fd9fdbf 100644 --- a/frontend/src/leftoverMapCoverage.test.ts +++ b/frontend/src/leftoverMapCoverage.test.ts @@ -9,6 +9,7 @@ import { LEFTOVER_MAP_COMPARE_ITEM_COVERAGE_LABEL, LEFTOVER_MAP_COMPARE_INCOMPLETE_POST_LABEL, LEFTOVER_MAP_COMPARE_INCOMPLETE_ITEM_LABEL, + LEFTOVER_MAP_COMPARE_PLOT_COVERAGE_LABEL, LEFTOVER_MAP_LIST_COVERAGE_LABEL, LEFTOVER_MAP_LIST_INCOMPLETE_ITEM_LABEL, LEFTOVER_MAP_LIST_INCOMPLETE_POST_LABEL, @@ -80,6 +81,13 @@ describe("leftoverMapCoverageCounts", () => { expect(LEFTOVER_MAP_COMPARE_COVERAGE_LABEL).not.toBe(LEFTOVER_MAP_LIST_COVERAGE_LABEL); expect(LEFTOVER_MAP_COMPARE_COVERAGE_LABEL).not.toBe(LEFTOVER_MAP_PLOT_COVERAGE_LABEL); }); + + it("keeps the grouping comparison graphic coverage label distinct from the pair-list, graphic, and strip labels", () => { + expect(LEFTOVER_MAP_COMPARE_PLOT_COVERAGE_LABEL).toBe("Leftover map comparison graphic coverage"); + expect(LEFTOVER_MAP_COMPARE_PLOT_COVERAGE_LABEL).not.toBe(LEFTOVER_MAP_LIST_COVERAGE_LABEL); + expect(LEFTOVER_MAP_COMPARE_PLOT_COVERAGE_LABEL).not.toBe(LEFTOVER_MAP_PLOT_COVERAGE_LABEL); + expect(LEFTOVER_MAP_COMPARE_PLOT_COVERAGE_LABEL).not.toBe(LEFTOVER_MAP_COMPARE_COVERAGE_LABEL); + }); }); describe("leftoverMapItemCoverageCounts", () => { diff --git a/frontend/src/leftoverMapCoverage.ts b/frontend/src/leftoverMapCoverage.ts index 67d7d9496..9f9366662 100644 --- a/frontend/src/leftoverMapCoverage.ts +++ b/frontend/src/leftoverMapCoverage.ts @@ -1,4 +1,4 @@ -/** Leftover-map complete-case coverage after IRT main effects (ADR 0168 / ADR 0281 / ADR 0282 / ADR 0283 / ADR 0284 / ADR 0285 / ADR 0286 / ADR 0287 / ADR 0288 / ADR 0289 / ADR 0290 / ADR 0291 / ADR 0292). */ +/** Leftover-map complete-case coverage after IRT main effects (ADR 0168 / ADR 0281 / ADR 0282 / ADR 0283 / ADR 0284 / ADR 0285 / ADR 0286 / ADR 0287 / ADR 0288 / ADR 0289 / ADR 0290 / ADR 0291 / ADR 0292 / ADR 0306). */ import type { LeftoverMapCoverage } from "./api"; @@ -8,6 +8,9 @@ export const LEFTOVER_MAP_LIST_COVERAGE_LABEL = "Leftover map coverage"; export const LEFTOVER_MAP_COMPARE_COVERAGE_LABEL = "Leftover map comparison coverage"; +export const LEFTOVER_MAP_COMPARE_PLOT_COVERAGE_LABEL = + "Leftover map comparison graphic coverage"; + export const LEFTOVER_MAP_COMPARE_ITEM_COVERAGE_LABEL = "Leftover map comparison item coverage"; export const LEFTOVER_MAP_COMPARE_INCOMPLETE_POST_LABEL = "Leftover map comparison incomplete posts"; diff --git a/frontend/src/leftoverMapPlotLayout.ts b/frontend/src/leftoverMapPlotLayout.ts index 7681dfdd7..5705428be 100644 --- a/frontend/src/leftoverMapPlotLayout.ts +++ b/frontend/src/leftoverMapPlotLayout.ts @@ -32,11 +32,15 @@ * (ADR 0301), grouping comparison leftover-map coordinates * (ADR 0302), grouping comparison leftover-map coordinates payload * (ADR 0303), grouping comparison leftover-map graphic display - * (ADR 0304), and grouping comparison leftover-map axis share on that - * graphic (ADR 0305) caption the pair list or the grouping comparison + * (ADR 0304), grouping comparison leftover-map axis share on that + * graphic (ADR 0305), and grouping comparison leftover-map complete-case + * coverage on that graphic (ADR 0306) caption the pair list or the grouping comparison * strip. ADR 0304 reuses this graphic layout on the grouping comparison * strip. ADR 0305 captions leftover-map axis share on that comparison - * graphic from already-named leftover-map axes. + * graphic from already-named leftover-map axes. ADR 0306 captions leftover-map + * complete-case coverage on that comparison graphic from already-named leftover-map + * coverage and does not caption leftover-map item coverage or leftover-map + * incomplete coverage on that comparison plot. */ import { formatLeftoverMapCoordinatePair } from "./leftoverMapCoordinates"; diff --git a/pyproject.toml b/pyproject.toml index f9750f557..f1c5adf9e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "lineageweave" -version = "2.62.0" +version = "2.63.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" } diff --git a/uv.lock b/uv.lock index 6a91f195f..872aba222 100644 --- a/uv.lock +++ b/uv.lock @@ -685,7 +685,7 @@ wheels = [ [[package]] name = "lineageweave" -version = "2.62.0" +version = "2.63.0" source = { editable = "." } dependencies = [ { name = "certifi" }, From b9e39096546a3176f81c3502c27fd7a367f3eb58 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 6 Sep 2026 10:52:34 +0900 Subject: [PATCH 2/3] chore(stack): inherit #841 ADR status contract --- tests/test_compare_graphic_adr_status.py | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 tests/test_compare_graphic_adr_status.py diff --git a/tests/test_compare_graphic_adr_status.py b/tests/test_compare_graphic_adr_status.py new file mode 100644 index 000000000..641399a49 --- /dev/null +++ b/tests/test_compare_graphic_adr_status.py @@ -0,0 +1,19 @@ +"""Governance contract for the grouping-comparison graphic ADR state.""" + +from pathlib import Path + + +_ADR = ( + Path(__file__).parents[1] + / "docs" + / "adr" + / "0304-leftover-map-compare-graphic.md" +) + + +def test_compare_graphic_adr_remains_proposed_until_independent_acceptance() -> None: + """A Draft candidate cannot claim an accepted architecture decision.""" + text = _ADR.read_text(encoding="utf-8") + assert text.startswith("# ADR 0304") + assert "**Decision status:** Proposed" in text + assert "**Decision status:** Accepted" not in text From d88ad97ca2520844314a47e1fd5a8a5657c94551 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 6 Sep 2026 10:53:09 +0900 Subject: [PATCH 3/3] chore(stack): preserve #841 ADR governance in #845 --- docs/adr/0304-leftover-map-compare-graphic.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/adr/0304-leftover-map-compare-graphic.md b/docs/adr/0304-leftover-map-compare-graphic.md index bff105cf4..0a51c4b4c 100644 --- a/docs/adr/0304-leftover-map-compare-graphic.md +++ b/docs/adr/0304-leftover-map-compare-graphic.md @@ -1,6 +1,6 @@ # ADR 0304 — Show leftover-map graphic display on grouping comparison strip -**Decision status:** Accepted +**Decision status:** Proposed **Date:** 2026-08-31 **Amended by:** [ADR 0305](0305-leftover-map-compare-plot-axis-share.md)