From bca6baabd917478bf4f6b688ec2755cde95e3575 Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Sun, 30 Aug 2026 14:28:58 +0000 Subject: [PATCH] feat(reports): leftover-map incomplete item coverage on grouping comparison strip (v2.49.0) Caption persisted leftover-map incomplete item coverage on GET /api/reports/compare/{period} through leftoverMapIncompleteItemCount (ADR 0292). Distinct aria-label Leftover map comparison incomplete items. Omit when dropped counts are unusable. Do not invent dropped criteria from scored minus used. No SQL. No leftover score or theta. --- AGENTS.md | 12 +- ARCHITECTURE.md | 5 +- ....0-leftover-map-compare-incomplete-item.md | 37 ++++ CHANGELOG.md | 37 ++++ CLAUDE.md | 2 +- ...92-leftover-map-compare-incomplete-item.md | 172 ++++++++++++++++++ docs/product-technical-gap-baseline.md | 70 +++++++ docs/storybook-inventory.md | 2 +- frontend/package.json | 2 +- frontend/src/App.test.tsx | 15 ++ frontend/src/App.tsx | 9 + frontend/src/components/LeftoverPairList.tsx | 3 +- frontend/src/i18n.test.ts | 11 ++ frontend/src/i18n.ts | 4 + frontend/src/leftoverMapCoverage.test.ts | 7 + frontend/src/leftoverMapCoverage.ts | 4 +- frontend/src/leftoverMapPlotLayout.ts | 5 +- pyproject.toml | 2 +- 18 files changed, 389 insertions(+), 10 deletions(-) create mode 100644 CHANGELOG.d/2.49.0-leftover-map-compare-incomplete-item.md create mode 100644 docs/adr/0292-leftover-map-compare-incomplete-item.md diff --git a/AGENTS.md b/AGENTS.md index 6259ca10b..30380bc66 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) 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) 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 @@ -408,6 +408,14 @@ dropped count that contradicts usable complete-case integers, omits that leftove 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. 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 @@ -428,6 +436,8 @@ 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. 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 657d89a9d..346afb687 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -673,6 +673,8 @@ through leftoverMapCoverageCounts. ADR 0290 captions the grouping comparison str 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. 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 @@ -692,7 +694,8 @@ including on the pair list. Results persist to `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), and leftover-map incomplete post coverage (ADR 0291); +coverage (ADR 0290), leftover-map incomplete post coverage (ADR 0291), and leftover-map +incomplete item coverage (ADR 0292); `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.49.0-leftover-map-compare-incomplete-item.md b/CHANGELOG.d/2.49.0-leftover-map-compare-incomplete-item.md new file mode 100644 index 000000000..3ebdb7020 --- /dev/null +++ b/CHANGELOG.d/2.49.0-leftover-map-compare-incomplete-item.md @@ -0,0 +1,37 @@ +## 2.49.0 — Leftover-map incomplete item coverage on the grouping comparison strip + +- Caption leftover-map incomplete item coverage on the grouping comparison + strip through leftoverMapIncompleteItemCount (ADR 0292). 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. Never invent a theta. No new columns. diff --git a/CHANGELOG.md b/CHANGELOG.md index bd5ad3396..a416d2f8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,43 @@ 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 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. + - 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`, diff --git a/CLAUDE.md b/CLAUDE.md index ed11730d7..3a6fbb514 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), 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), 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/0292-leftover-map-compare-incomplete-item.md b/docs/adr/0292-leftover-map-compare-incomplete-item.md new file mode 100644 index 000000000..977749229 --- /dev/null +++ b/docs/adr/0292-leftover-map-compare-incomplete-item.md @@ -0,0 +1,172 @@ +# ADR 0292 — Name leftover-map incomplete item coverage on the grouping comparison strip + +**Decision status:** Accepted +**Date:** 2026-08-30 + +Amends leftover pairs on the grouping comparison strip +([ADR 0149](0149-leftover-pairs-on-comparison-strip.md)), leftover-map +complete-case coverage ([ADR 0168](0168-leftover-map-complete-case-coverage.md)), +leftover-map complete-case coverage on the grouping comparison strip +([ADR 0289](0289-leftover-map-compare-coverage.md)), leftover-map item +complete-case coverage on the grouping comparison strip +([ADR 0290](0290-leftover-map-compare-item-coverage.md)), and leftover-map +incomplete post coverage on the grouping comparison strip +([ADR 0291](0291-leftover-map-compare-incomplete-post.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-map complete-case +coverage on the graphic display +([ADR 0281](0281-leftover-map-plot-coverage.md)), leftover-map rank on pair +segments ([ADR 0280](0280-leftover-map-segment-rank.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 coordinate ticks ([ADR 0270](0270-leftover-map-coordinate-ticks.md)), +leftover-map axis share on the graphic display +([ADR 0269](0269-leftover-map-axis-share-plot.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 explained leftover share persistence +([ADR 0266](0266-leftover-map-explained-share.md)), leftover-map +unexplained leftover share persistence +([ADR 0233](0233-leftover-map-unexplained-share.md)), leftover-map +reconstruction persistence ([ADR 0201](0201-leftover-map-reconstruction.md)), +leftover-map cross share persistence +([ADR 0185](0185-leftover-map-cross-share.md)), leftover-map unexplained leftover +persistence ([ADR 0182](0182-leftover-map-unexplained.md)), leftover-map rank +persistence ([ADR 0164](0164-leftover-map-rank.md)), and leftover-map axis +share persistence ([ADR 0148](0148-leftover-map-axis-share.md)). + +## Context + +ADR 0168 already persists `incomplete_item_count` on +`report_leftover_map_coverage`. ADR 0290 already captions leftover-map item +complete-case coverage on the grouping comparison strip. ADR 0291 already +captions leftover-map incomplete post coverage on the grouping comparison +strip. ADR 0284 already names persisted leftover-map incomplete item coverage +on the leftover-map graphic display. ADR 0287 already names it on the pair +list. The strip still does not name dropped incomplete criteria, so a buyer who +compares leftover pairs can treat `used N of M scored criteria (complete-case)` +on a grouping row as the full scored census even after incomplete columns were +dropped. Incomplete columns are dropped from Gabriel factorization; hiding +dropped criteria on the strip lets a sparse criterion vanish without a next +action. + +This increment captions persisted leftover-map incomplete item coverage on +each grouping comparison row through leftoverMapIncompleteItemCount. It does +not add columns. It does not recompute dropped criteria from scored minus used, +leftover pair count, plotted criterion marker count, leftover-map distance, or +leftover-map rank. 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 **0292** so it does not collide with +leftover-map incomplete post coverage on the grouping comparison strip (0291), +leftover-map item complete-case coverage on the grouping comparison strip +(0290), leftover-map complete-case coverage on the grouping comparison strip +(0289), leftover-map post complete-case coverage fail-closed on the pair list +(0288), leftover-map incomplete item coverage on the pair list (0287), +leftover-map incomplete post coverage on the pair list (0286), leftover-map +item complete-case coverage on the pair list (0285), leftover-map incomplete +item coverage on the graphic display (0284), leftover-map incomplete post +coverage on the graphic display (0283), leftover-map item complete-case +coverage on the graphic display (0282), leftover-map complete-case coverage +on the graphic display (0281), leftover-map rank on pair segments (0280), +or the dashboard stacks. + +## Decision + +On the grouping comparison strip, caption leftover-map incomplete item +coverage as `Leftover map dropped {dropped} incomplete criteria` only when +leftoverMapIncompleteItemCount returns a usable dropped integer from +persisted `incomplete_item_count`. Use the distinct accessible name +`Leftover map comparison incomplete items` so the strip caption is not the +pair-list note (`Leftover map incomplete items`) and is not the graphic +caption (`Leftover-map graphic incomplete items`). A missing coverage row, a +non-integer dropped count, a negative dropped count, or a dropped count that +contradicts usable item complete-case integers (`dropped !== scored − used` +when `map_item_count` / `scored_item_count` are usable) omits that leftover-map +comparison incomplete item note and keeps the strip leftover-map post +coverage note, leftover-map item coverage note, leftover-map incomplete post +note, leftover pairs, leftover-map distance `d`, and any leftover-map +captions on the pair list and graphic. 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. Do not add the leftover-map graphic to the strip. +Click a leftover pair on the strip to open that post. + +Do not add SQL. 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, and persisted +leftover-map incomplete item coverage on each grouping row when +leftoverMapCoverageCounts / leftoverMapItemCoverageCounts / +leftoverMapIncompletePostCount / leftoverMapIncompleteItemCount return usable +integers, 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 inner product, +leftover-map cosine, leftover-map length, leftover-map graphic display, +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, and leftover-map post +complete-case coverage fail-closed on the pair list. + +## 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. Incomplete +columns are dropped from the complete-case residual rectangle; grouping +comparison incomplete item coverage names how many scored criteria stayed out +of that factorization for that grouping only when leftoverMapIncompleteItemCount +returns a usable dropped integer.) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index b797a8add..f0befa176 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -1,5 +1,75 @@ # Product & Technical Gap Baseline +> 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 diff --git a/docs/storybook-inventory.md b/docs/storybook-inventory.md index 51d77b8d5..485085734 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, and leftover-map incomplete post coverage with distinct comparison labels when leftoverMapCoverageCounts / leftoverMapItemCoverageCounts / leftoverMapIncompletePostCount return usable integers. | `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, 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` | | `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 887c52179..8fa819fcf 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "frontend", "private": true, - "version": "2.48.0", + "version": "2.49.0", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/src/App.test.tsx b/frontend/src/App.test.tsx index fd65467da..283e671ac 100644 --- a/frontend/src/App.test.tsx +++ b/frontend/src/App.test.tsx @@ -4308,6 +4308,21 @@ describe("App, authenticated", () => { expect( within(screen.getByLabelText("Grouping comparison")).queryByLabelText("Leftover map incomplete items"), ).not.toBeInTheDocument(); + expect( + within(screen.getByLabelText("Grouping comparison")).getAllByLabelText( + "Leftover map comparison incomplete items", + ), + ).toHaveLength(2); + expect( + within(screen.getByLabelText("Grouping comparison")).getAllByLabelText( + "Leftover map comparison incomplete items", + )[0], + ).toHaveTextContent("Leftover map dropped 0 incomplete criteria"); + expect( + within(screen.getByLabelText("Grouping comparison")).queryByLabelText( + "Leftover-map graphic incomplete items", + ), + ).not.toBeInTheDocument(); expect( screen.getByRole("button", { name: "Compare Business unit (PU): Demo Report High, mean θ 0.81" }), ).toHaveTextContent("mean θ 0.81"); diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 39dd56e18..1255ff43c 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -127,6 +127,7 @@ import { LEFTOVER_MAP_COMPARE_COVERAGE_LABEL, LEFTOVER_MAP_COMPARE_ITEM_COVERAGE_LABEL, LEFTOVER_MAP_COMPARE_INCOMPLETE_POST_LABEL, + LEFTOVER_MAP_COMPARE_INCOMPLETE_ITEM_LABEL, LEFTOVER_MAP_LIST_COVERAGE_LABEL, LEFTOVER_MAP_LIST_INCOMPLETE_ITEM_LABEL, LEFTOVER_MAP_LIST_INCOMPLETE_POST_LABEL, @@ -3995,6 +3996,9 @@ function ReportsPanel({ const comparisonIncompletePostCount = leftoverMapIncompletePostCount( row.leftover_map_coverage, ); + const comparisonIncompleteItemCount = leftoverMapIncompleteItemCount( + row.leftover_map_coverage, + ); return (