diff --git a/AGENTS.md b/AGENTS.md index c5983c441..75791e501 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) 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) 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 @@ -373,6 +373,12 @@ every scored post entering the map; a missing, non-integer, or negative dropped count, or a dropped count that contradicts usable complete-case integers, omits that leftover-map incomplete post note and does not invent dropped posts from scored minus used or from plotted marker count. +ADR 0287 captions the leftover pair list with persisted leftover-map +incomplete item coverage so a `used N of M scored criteria` note is not read as +every scored criterion entering the map; a missing, non-integer, or negative +dropped count, or a dropped count that contradicts usable item complete-case +integers, omits that leftover-map incomplete item note and does not invent +dropped criteria from scored minus used or from plotted criterion marker count. 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 @@ -393,6 +399,8 @@ graphic with how many scored posts stayed out of the factorization. Incomplete post coverage on the pair list (ADR 0286) captions the pair list with how many scored posts stayed out of the factorization. Incomplete item coverage (ADR 0284) captions the leftover-map graphic with how many +scored criteria stayed out of the factorization. Incomplete +item coverage on the pair list (ADR 0287) captions the pair list with how many scored criteria stayed out of the factorization. Authorized occupational construct catalog search (ADR 0257) matches official diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index e5a075d0b..aab40280e 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -637,7 +637,7 @@ information at the group's mean θ (Lord, 1980 max-info CAT). Rankings persist to `report_item_information`. After those IRT main effects, residual SVD leftover pairs on two Gabriel axes (Jeon et al., 2021; ADR 0017 / 0048 / 0049 / 0119 / 0148 / 0158 / 0162 / 0163 / 0164 / 0168 / -0182 / 0185 / 0201 / 0233 / 0266 / 0267 / 0268 / 0269 / 0270 / 0271 / 0272 / 0273 / 0274 / 0275 / 0276 / 0277 / 0278 / 0279 / 0280 / 0281 / 0282 / 0283 / 0284 / 0285 / 0286) persist to `report_leftover_pair` with signed residual `R`, +0182 / 0185 / 0201 / 0233 / 0266 / 0267 / 0268 / 0269 / 0270 / 0271 / 0272 / 0273 / 0274 / 0275 / 0276 / 0277 / 0278 / 0279 / 0280 / 0281 / 0282 / 0283 / 0284 / 0285 / 0286 / 0287) persist to `report_leftover_pair` with signed residual `R`, observed `Y`, expected `E[Y|θ, item]`, full leftover-map rank, unexplained leftover, ADR 0201 reconstruction evidence, ADR 0185 cross-share evidence, ADR 0233 unexplained leftover share `s`, ADR 0266 explained leftover @@ -665,7 +665,8 @@ graphic display with persisted leftover-map incomplete post coverage. ADR 0284 captions the leftover-map graphic display with persisted leftover-map incomplete item coverage. ADR 0285 captions the leftover pair list with persisted leftover-map item complete-case coverage. ADR 0286 captions the leftover pair list with persisted leftover-map -incomplete post coverage. Click a post marker or a pair button +incomplete post coverage. ADR 0287 captions the leftover pair list with persisted leftover-map +incomplete item coverage. 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 (Gabriel inertia of residual SVD axes 1 and 2; ADR 0148) persists to @@ -676,7 +677,8 @@ and how many scored criteria entered the factorization on the graphic and on the pair list, and how many scored posts stayed incomplete and out of the factorization, including on the pair list, -and how many scored criteria stayed incomplete and out of the factorization. Results persist to +and how many scored criteria stayed incomplete and out of the factorization, +including on the pair list. Results persist to `report_period_score` / `report_member_score`. `GET /api/reports/{grouping}` lists the trend; `GET /api/reports/{grouping}/{period}` is ABAC-filtered; diff --git a/CHANGELOG.d/2.44.0-leftover-map-list-incomplete-item.md b/CHANGELOG.d/2.44.0-leftover-map-list-incomplete-item.md new file mode 100644 index 000000000..e66a125c1 --- /dev/null +++ b/CHANGELOG.d/2.44.0-leftover-map-list-incomplete-item.md @@ -0,0 +1,30 @@ +## 2.44.0 — Leftover-map incomplete item coverage on the pair list + +- Caption the leftover pair list with persisted leftover-map incomplete + item coverage (ADR 0287). 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 item + complete-case coverage, a pair-list note that matches leftover-map + incomplete post coverage, and a pair-list note that matches leftover-map + incomplete item coverage; click a post marker or a pair button opens + that post. A missing, non-integer, or negative dropped count, or a + dropped count that contradicts usable item complete-case integers, omits + that leftover-map 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, 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. Never invent a leftover score. Never invent a + theta. No new columns. diff --git a/CHANGELOG.md b/CHANGELOG.md index 7b47f6dbc..6079ba373 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,36 @@ All notable changes to this project are documented here. Format follows ### Added +- Period leftover pairs now caption the leftover pair list with persisted + leftover-map incomplete item coverage (ADR 0287 / v2.44.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 item complete-case coverage, a pair-list note that + matches leftover-map incomplete post coverage, and a pair-list note + that matches leftover-map incomplete item coverage; click a post + marker or a pair button opens that post. A missing, non-integer, or + negative dropped count, or a dropped count that contradicts usable item + complete-case integers, omits that leftover-map 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, 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. Never invent a leftover score or a theta. No new columns. + - Period leftover pairs now caption the leftover pair list with persisted leftover-map incomplete post coverage (ADR 0286 / v2.43.0). After `make seed`, closest and farthest leftover pairs sit above the member diff --git a/CLAUDE.md b/CLAUDE.md index 49709f27e..347626b38 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), 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), 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/0287-leftover-map-list-incomplete-item.md b/docs/adr/0287-leftover-map-list-incomplete-item.md new file mode 100644 index 000000000..04e9a1919 --- /dev/null +++ b/docs/adr/0287-leftover-map-list-incomplete-item.md @@ -0,0 +1,190 @@ +# ADR 0287 — Name leftover-map incomplete item coverage on the pair list + +**Decision status:** Proposed +**Date:** 2026-08-30 + +Amends [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 +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` and captions the pair list with post +complete-case coverage. ADR 0284 already names persisted leftover-map +incomplete item coverage on the leftover-map graphic display. ADR 0285 already +names item complete-case coverage on the pair list. ADR 0286 already names +incomplete post coverage on the pair list. The pair-list note still does not +name dropped incomplete criteria, so a buyer who reads `used N of M scored +criteria (complete-case)` above the pair buttons can treat those N criteria +as the full scored census even after incomplete columns were dropped. +Incomplete columns are dropped from Gabriel factorization; hiding dropped +criteria on the pair list lets a sparse criterion with one missing post vanish +without a next action. + +This increment names leftover-map incomplete item coverage on the pair-list +note. It does not add columns. It does not recompute dropped criteria from +scored minus used, 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. It does not land Post quality on the leftover +criterion. Leftover-map distance stays two-axis Euclidean. 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 **0287** so it does not collide with +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), leftover +expected on pair segments (0279), leftover observed on pair segments (0278), +leftover residual on pair segments (0277), leftover-map unexplained leftover on +pair segments (0276), leftover-map cross share on pair segments (0275), +leftover-map unexplained leftover share on pair segments (0274), leftover-map +explained leftover share on pair segments (0273), leftover-map reconstruction +on pair segments (0272), leftover-map distance on pair segments (0271), +leftover-map coordinate ticks (0270), leftover-map axis share on the graphic +display (0269), leftover-map graphic display (0268), leftover-map coordinates +(0267 / migration 0245), leftover-map explained leftover share persistence +(0266 / migration 0244), leftover-map unexplained leftover share persistence +(0233 / migration 0233), leftover-map reconstruction persistence (0201 / +migration 0206), leftover-map cross share persistence (0185), leftover-map +unexplained leftover persistence (0182), leftover residual disclosure (0162), +leftover observed `Y` / expected `E` persistence (0163), leftover-map rank +persistence (0164), leftover coverage persistence (0168), two-axis leftover-map +distance persistence, leftover-map axis share persistence (0148), leftover +interaction-map persistence, occupational construct catalog search (0265), or +the dashboard stacks. + +## Decision + +On the leftover pair list, caption persisted leftover-map incomplete item +coverage as `Leftover map dropped {dropped} incomplete criteria`, using the +persisted `incomplete_item_count` integer. 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 +incomplete item note and keeps the pair-list post coverage note, the pair-list +item coverage note, the pair-list incomplete post note, and any leftover-map +distance, reconstruction, explained leftover share, unexplained leftover share, +leftover-map cross share, unexplained leftover, leftover residual, leftover +observed, leftover expected, leftover-map rank, leftover-map post coverage, +leftover-map item coverage, leftover-map incomplete post, or leftover-map +incomplete item caption on the graphic. Dropped `0` is shown when that +persisted dropped count is a non-negative integer. Do not invent dropped +criteria from scored minus used, 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. +Click a pair button to open that post. The grouping comparison strip +(ADR 0149) stays on its reduced leftover payload and does not gain this +leftover-map incomplete item caption. + +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`, closest and farthest leftover pairs sit above the member +list with the leftover-map graphic display of persisted `ξ` and `ζ`, +leftover-map axes name persisted Gabriel inertia share when finite, +leftover-map axis ticks name the same coordinates shown on the pair row, +pair segments name persisted leftover-map distance `d`, persisted leftover-map +reconstruction `R̂`, persisted leftover-map explained leftover share `e`, +persisted leftover-map unexplained leftover share `s`, persisted leftover-map +cross share `x`, persisted leftover-map unexplained leftover `U`, persisted +leftover residual `R`, persisted leftover observed `Y`, persisted leftover +expected `E`, persisted leftover-map rank, the plot names persisted leftover-map +complete-case coverage, the plot names persisted leftover-map item +complete-case coverage, the plot names persisted leftover-map incomplete +post coverage, the plot names persisted leftover-map incomplete item +coverage, the pair list names persisted leftover-map item complete-case +coverage, the pair list names persisted leftover-map incomplete post +coverage, and the pair list names persisted leftover-map incomplete item +coverage; click a post marker or a pair button opens that post. +Hidden posts stay hidden. Rank-0 unused axes still plot at the origin and still +name incomplete criteria on the pair list when that dropped count is persisted. + +## 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, two-axis leftover-map +distance persistence, leftover-map rank persistence, leftover-map inner +product, leftover-map cosine, leftover-map length, leftover-map +reconstruction persistence, leftover-map unexplained leftover persistence, +leftover-map cross share persistence, leftover-map unexplained leftover +share persistence, leftover-map explained leftover share persistence, +leftover-map coordinate persistence, leftover-map graphic display, +leftover-map axis share on the graphic display, leftover-map coordinate +ticks, leftover-map distance on pair segments, leftover-map reconstruction +on pair segments, leftover-map explained leftover share on pair segments, +leftover-map unexplained leftover share on pair segments, leftover-map +cross share on pair segments, leftover-map unexplained leftover on pair +segments, leftover residual on pair segments, leftover observed on pair +segments, leftover expected on pair segments, leftover-map rank on pair +segments, leftover-map complete-case coverage on the graphic display, +leftover-map item complete-case coverage on the graphic display, +leftover-map incomplete post coverage on the graphic display, +leftover-map incomplete item coverage on the graphic display, +leftover-map item complete-case coverage on the pair list, and leftover-map +incomplete post coverage 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. Gabriel +reconstruction of the leftover cell is the two-axis inner product +`R̂ = ξ_{1:2} · ζ_{1:2}`. Incomplete columns are dropped from the +complete-case residual rectangle; pair-list incomplete item coverage names +how many scored criteria stayed out of that factorization.) diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md index a5dea6d13..6eaf49e5b 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -1,5 +1,62 @@ # Product & Technical Gap Baseline +> Exact-head loop overlay: 2026-08-30 22:18 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`. Leave +> #782/#802/#803/#804/#805/#806/#808/#809/#810/#811/#812/#813/#814/#815/#816/#817 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 pair list (ADR 0287 / v2.44.0) delivered locally on +> `feat/leftover-map-list-incomplete-item-v2440`. Caption the pair-list +> note with persisted leftover-map incomplete item coverage so a +> `used N of M scored criteria` note is not read as every scored +> criterion entering the map. 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 +> incomplete item note. Dropped `0` is shown when persisted. Do not invent +> dropped criteria from scored minus used, 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 invent leftover scores. Stack onto +> leftover branch `feat/leftover-map-list-incomplete-post-v2430` / #817; +> leave the PR open for independent review. Do not squash-merge onto the +> leftover base. Do not persist leftover-map inner product, cosine, or +> length as separate columns. Grouping comparison strip (ADR 0149) does +> not gain this caption. + > Exact-head loop overlay: 2026-08-30 21:35 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 3a167c760..12ea76430 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, leftover-map item complete-case coverage, and leftover-map incomplete post coverage when persisted. | `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, leftover-map item complete-case coverage, leftover-map incomplete post coverage, and leftover-map incomplete item coverage when persisted. | `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 bf7b7e2f8..4850829ac 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "frontend", "private": true, - "version": "2.43.0", + "version": "2.44.0", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/src/App.test.tsx b/frontend/src/App.test.tsx index 08a3204a0..60859037b 100644 --- a/frontend/src/App.test.tsx +++ b/frontend/src/App.test.tsx @@ -4160,6 +4160,9 @@ describe("App, authenticated", () => { expect(screen.getByLabelText("Leftover map incomplete posts")).toHaveTextContent( "Leftover map dropped 1 incomplete posts", ); + expect(screen.getByLabelText("Leftover map incomplete items")).toHaveTextContent( + "Leftover map dropped 0 incomplete criteria", + ); expect(screen.getByLabelText("Leftover-map graphic coverage")).toHaveTextContent( "Leftover map used 2 of 3 scored posts (complete-case)", ); @@ -4243,6 +4246,9 @@ describe("App, authenticated", () => { expect( within(screen.getByLabelText("Grouping comparison")).queryByLabelText("Leftover map incomplete posts"), ).not.toBeInTheDocument(); + expect( + within(screen.getByLabelText("Grouping comparison")).queryByLabelText("Leftover map 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 5fa9e07da..1fbfafabe 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -120,10 +120,13 @@ import { useLocale, } from "./i18n"; import { + leftoverMapIncompleteItemCount, leftoverMapIncompletePostCount, leftoverMapItemCoverageCounts, + LEFTOVER_MAP_LIST_INCOMPLETE_ITEM_LABEL, LEFTOVER_MAP_LIST_INCOMPLETE_POST_LABEL, LEFTOVER_MAP_LIST_ITEM_COVERAGE_LABEL, + LEFTOVER_MAP_PLOT_INCOMPLETE_ITEM, LEFTOVER_MAP_PLOT_INCOMPLETE_POST, LEFTOVER_MAP_PLOT_ITEM_COVERAGE, } from "./leftoverMapCoverage"; @@ -3822,6 +3825,7 @@ function ReportsPanel({ {orderedReports.map((report) => { const itemCoverageCounts = leftoverMapItemCoverageCounts(report.leftover_map_coverage); const incompletePostCount = leftoverMapIncompletePostCount(report.leftover_map_coverage); + const incompleteItemCount = leftoverMapIncompleteItemCount(report.leftover_map_coverage); return (
+ {tf(LEFTOVER_MAP_PLOT_INCOMPLETE_ITEM, incompleteItemCount)} +
+ ) : null} {report.leftover_map_axes?.map((axis) => ( {tf("leftover axis {axis} {share}%", { diff --git a/frontend/src/components/LeftoverPairList.tsx b/frontend/src/components/LeftoverPairList.tsx index a026e7954..94e489e40 100644 --- a/frontend/src/components/LeftoverPairList.tsx +++ b/frontend/src/components/LeftoverPairList.tsx @@ -78,7 +78,8 @@ export type LeftoverPairListProps = { * incomplete post coverage on the graphic. ADR 0284 names persisted leftover-map * incomplete item coverage on the graphic. ADR 0285 names persisted leftover-map * item complete-case coverage on the pair-list note. ADR 0286 names persisted leftover-map - * incomplete post coverage on the pair-list note. Every badge still + * incomplete post coverage on the pair-list note. ADR 0287 names persisted leftover-map + * incomplete item coverage on the pair-list note. Every badge still * renders together before opening the named post. */ export function LeftoverPairList({ diff --git a/frontend/src/i18n.test.ts b/frontend/src/i18n.test.ts index e1ae28ac2..06fe63f7f 100644 --- a/frontend/src/i18n.test.ts +++ b/frontend/src/i18n.test.ts @@ -80,6 +80,7 @@ describe("i18n", () => { "Leftover-map graphic item coverage", "Leftover map item coverage", "Leftover map incomplete posts", + "Leftover map incomplete items", "Leftover-map graphic incomplete posts", "Leftover-map graphic incomplete items", "Leftover map used {used} of {scored} scored criteria (complete-case)", @@ -409,6 +410,16 @@ describe("i18n", () => { expect(t("Leftover map incomplete posts")).toBe(expected); }); + it.each([ + ["ko", "잔여 지도 불완전 기준"], + ["zh", "残差地图不完整准则"], + ["ja", "残差マップの不完全基準"], + ["vi", "Tiêu chí không đầy đủ trên bản đồ phần dư"], + ] as const)("formats leftover map incomplete items label in %s", (locale, expected) => { + setLocale(locale); + expect(t("Leftover map incomplete items")).toBe(expected); + }); + it.each([ ["ko", "잔여 지도 그림 불완전 글"], ["zh", "残差图图形不完整帖文"], diff --git a/frontend/src/i18n.ts b/frontend/src/i18n.ts index 02a8ffffe..3ba3dcb79 100644 --- a/frontend/src/i18n.ts +++ b/frontend/src/i18n.ts @@ -270,6 +270,7 @@ const TRANSLATIONS: Partial