diff --git a/AGENTS.md b/AGENTS.md
index ccf5a3160..d571f5d26 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -591,6 +591,35 @@ and leftover-map comparison graphic incomplete items when those helpers return u
leftover-map rank, leftover-map axis share, leftover-map post coverage, leftover-map item coverage,
leftover-map incomplete post coverage, leftover-map incomplete item coverage, leftover pair
count, or the count of unused axes.
+ADR 0316 captions leftover observed on that grouping comparison leftover-map
+graphic when formatLeftoverMapObserved returns a usable badge; a missing or
+non-finite `Y` omits that leftover-map comparison graphic leftover observed caption and keeps
+leftover residual `R`, leftover-map unexplained leftover `U`, leftover-map cross share `x`, leftover-map unexplained leftover share `s`, leftover-map explained leftover share `e`, leftover-map reconstruction `R̂`, leftover-map distance `d`, leftover-map comparison graphic coverage,
+leftover-map comparison graphic item coverage, leftover-map comparison graphic incomplete posts,
+and leftover-map comparison graphic incomplete items when those helpers return usable integers. Do not invent
+`Y` from `R` and `E`, leftover residual, leftover-map unexplained leftover, leftover-map reconstruction, leftover-map distance, plotted coordinates,
+leftover-map rank, leftover-map axis share, leftover-map post coverage, leftover-map item coverage,
+leftover-map incomplete post coverage, leftover-map incomplete item coverage, leftover pair
+count, or the count of unused axes.
+ADR 0317 captions leftover expected on that grouping comparison leftover-map
+graphic when formatLeftoverMapExpected returns a usable badge; a missing or
+non-finite `E` omits that leftover-map comparison graphic leftover expected caption and keeps
+leftover observed `Y`, leftover residual `R`, leftover-map unexplained leftover `U`, leftover-map cross share `x`, leftover-map unexplained leftover share `s`, leftover-map explained leftover share `e`, leftover-map reconstruction `R̂`, leftover-map distance `d`, leftover-map comparison graphic coverage,
+leftover-map comparison graphic item coverage, leftover-map comparison graphic incomplete posts,
+and leftover-map comparison graphic incomplete items when those helpers return usable integers. Do not invent
+`E` from `Y` and `R`, leftover observed, leftover residual, leftover-map unexplained leftover, leftover-map reconstruction, leftover-map distance, plotted coordinates,
+leftover-map rank, leftover-map axis share, leftover-map post coverage, leftover-map item coverage,
+leftover-map incomplete post coverage, leftover-map incomplete item coverage, leftover pair
+count, or the count of unused axes.
+ADR 0318 captions leftover-map rank on that grouping comparison leftover-map
+graphic when formatLeftoverMapRank returns a usable badge; a missing,
+negative, or non-integer rank omits that leftover-map comparison graphic leftover-map rank caption and keeps
+leftover expected `E`, leftover observed `Y`, leftover residual `R`, leftover-map unexplained leftover `U`, leftover-map cross share `x`, leftover-map unexplained leftover share `s`, leftover-map explained leftover share `e`, leftover-map reconstruction `R̂`, leftover-map distance `d`, leftover-map comparison graphic coverage,
+leftover-map comparison graphic item coverage, leftover-map comparison graphic incomplete posts,
+and leftover-map comparison graphic incomplete items when those helpers return usable integers. Do not invent
+leftover-map rank from plotted coordinates, leftover-map distance, leftover expected, leftover observed, leftover residual, leftover-map unexplained leftover, leftover-map reconstruction, leftover-map axis share, leftover-map post coverage, leftover-map item coverage,
+leftover-map incomplete post coverage, leftover-map incomplete item coverage, leftover pair
+count, or the count of unused axes.
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
@@ -671,6 +700,15 @@ that grouping comparison leftover-map graphic with persisted leftover-map unexpl
Grouping comparison leftover residual (ADR 0315) captions
that grouping comparison leftover-map graphic with persisted leftover residual
`R` when formatLeftoverMapResidual returns a usable badge.
+Grouping comparison leftover observed (ADR 0316) captions
+that grouping comparison leftover-map graphic with persisted leftover observed
+`Y` when formatLeftoverMapObserved returns a usable badge.
+Grouping comparison leftover expected (ADR 0317) captions
+that grouping comparison leftover-map graphic with persisted leftover expected
+`E` when formatLeftoverMapExpected returns a usable badge.
+Grouping comparison leftover-map rank (ADR 0318) captions
+that grouping comparison leftover-map graphic with persisted leftover-map rank
+when formatLeftoverMapRank returns a usable badge.
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 3f2860b71..a800e9bd2 100644
--- a/ARCHITECTURE.md
+++ b/ARCHITECTURE.md
@@ -734,6 +734,15 @@ badge.
ADR 0315 captions leftover residual on that grouping
comparison leftover-map graphic when formatLeftoverMapResidual returns a usable
badge.
+ADR 0316 captions leftover observed on that grouping
+comparison leftover-map graphic when formatLeftoverMapObserved returns a usable
+badge.
+ADR 0317 captions leftover expected on that grouping
+comparison leftover-map graphic when formatLeftoverMapExpected returns a usable
+badge.
+ADR 0318 captions leftover-map rank on that grouping
+comparison leftover-map graphic when formatLeftoverMapRank returns a usable
+badge.
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
@@ -778,7 +787,10 @@ graphic (ADR 0311), leftover-map unexplained leftover share on the grouping comp
graphic (ADR 0312), leftover-map cross share on the grouping comparison leftover-map
graphic (ADR 0313), leftover-map unexplained leftover on the grouping comparison leftover-map
graphic (ADR 0314), leftover residual on the grouping comparison leftover-map
-graphic (ADR 0315);
+graphic (ADR 0315), leftover observed on the grouping comparison leftover-map
+graphic (ADR 0316), leftover expected on the grouping comparison leftover-map
+graphic (ADR 0317), leftover-map rank on the grouping comparison leftover-map
+graphic (ADR 0318);
`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.73.0-leftover-map-compare-plot-observed.md b/CHANGELOG.d/2.73.0-leftover-map-compare-plot-observed.md
new file mode 100644
index 000000000..3cd596b5c
--- /dev/null
+++ b/CHANGELOG.d/2.73.0-leftover-map-compare-plot-observed.md
@@ -0,0 +1,39 @@
+## 2.73.0 — Leftover observed on grouping comparison leftover-map graphic
+
+- Caption leftover observed on the grouping comparison leftover-map
+ graphic (ADR 0316). 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 complete-case
+ coverage when leftoverMapCoverageCounts returns usable complete-case integers,
+ leftover-map item complete-case coverage when leftoverMapItemCoverageCounts
+ returns usable complete-case integers, leftover-map incomplete post coverage
+ when leftoverMapIncompletePostCount returns a usable dropped integer,
+ leftover-map incomplete item coverage when leftoverMapIncompleteItemCount
+ returns a usable dropped integer, leftover-map reconstruction `R̂` when
+ formatLeftoverMapReconstruction returns a usable signed badge, leftover-map
+ explained leftover share `e` when formatLeftoverMapExplainedShare returns a
+ usable badge, leftover-map unexplained leftover share `s` when
+ formatLeftoverMapUnexplainedShare returns a usable badge, leftover-map
+ cross share `x` when formatLeftoverMapCrossShare returns a usable badge, leftover-map
+ unexplained leftover `U` when formatLeftoverMapUnexplained returns a usable badge,
+ leftover residual `R` when formatLeftoverMapResidual returns a usable badge,
+ and leftover observed `Y` on that grouping comparison leftover-map graphic; click a
+ post marker or a pair button opens that post. A missing or non-finite `Y`
+ omits that leftover-map comparison graphic leftover observed caption and keeps
+ leftover residual `R`, leftover-map unexplained leftover `U`, leftover-map cross share `x`, leftover-map unexplained leftover share `s`, leftover-map explained leftover
+ share `e`, leftover-map reconstruction `R̂`, leftover-map distance `d`, leftover-map
+ comparison graphic coverage, leftover-map comparison graphic item coverage,
+ leftover-map comparison graphic incomplete posts, and leftover-map comparison
+ graphic incomplete items when those helpers return usable integers. Rank-0 origin
+ cells still name `Y 0.00` when that persisted leftover observed is
+ finite. Comparison copy uses `leftover map comparison graphic leftover observed
+ {label}` so it stays distinct from `leftover observed
+ {label}` and from strip `Leftover map comparison observed`.
+ This increment does not caption leftover expected on the comparison graphic
+ with a distinct name. Do not invent `Y` from `R` and `E`, leftover residual, leftover-map reconstruction,
+ leftover-map unexplained leftover, leftover-map distance, plotted coordinates, leftover-map rank,
+ leftover-map axis share, leftover-map post coverage, leftover-map item coverage,
+ leftover-map incomplete post coverage, leftover-map incomplete item coverage,
+ leftover pair count, or the count of unused axes. A finite negative leftover
+ observed is shown, never clamped. Never invent a leftover score.
+ Never invent a theta. No new columns.
diff --git a/CHANGELOG.d/2.74.0-leftover-map-compare-plot-expected.md b/CHANGELOG.d/2.74.0-leftover-map-compare-plot-expected.md
new file mode 100644
index 000000000..e9f778ad2
--- /dev/null
+++ b/CHANGELOG.d/2.74.0-leftover-map-compare-plot-expected.md
@@ -0,0 +1,16 @@
+## 2.74.0 — Leftover expected on grouping comparison leftover-map graphic
+
+- Caption leftover expected on the grouping comparison leftover-map
+ graphic (ADR 0317). After `make seed`, closest and farthest leftover pairs
+ sit above the member list with leftover expected `E` on that grouping
+ comparison leftover-map graphic when formatLeftoverMapExpected returns a usable
+ badge; click a post marker or a pair button opens that post. A missing or
+ non-finite `E` omits that leftover-map comparison graphic leftover expected
+ caption and keeps leftover observed `Y` and leftover residual `R`. Rank-0 origin
+ cells still name `E 0.00` when that persisted leftover expected is finite.
+ Comparison copy uses `leftover map comparison graphic leftover expected {label}`
+ so it stays distinct from `leftover expected {label}` and from strip
+ `Leftover map comparison expected`. This increment does not caption leftover-map
+ rank on the comparison graphic with a distinct name. Do not invent `E` from
+ `Y` and `R`. A finite negative leftover expected is shown, never clamped.
+ Never invent a leftover score. Never invent a theta. No new columns.
diff --git a/CHANGELOG.d/2.75.0-leftover-map-compare-plot-rank.md b/CHANGELOG.d/2.75.0-leftover-map-compare-plot-rank.md
new file mode 100644
index 000000000..b719216dc
--- /dev/null
+++ b/CHANGELOG.d/2.75.0-leftover-map-compare-plot-rank.md
@@ -0,0 +1,16 @@
+## 2.75.0 — Leftover-map rank on grouping comparison leftover-map graphic
+
+- Caption leftover-map rank on the grouping comparison leftover-map
+ graphic (ADR 0318). After `make seed`, closest and farthest leftover pairs
+ sit above the member list with leftover-map rank on that grouping
+ comparison leftover-map graphic when formatLeftoverMapRank returns a usable
+ badge; click a post marker or a pair button opens that post. A missing,
+ negative, or non-integer rank omits that leftover-map comparison graphic leftover-map
+ rank caption and keeps leftover expected `E` and leftover observed `Y`. Rank-0 origin
+ cells still name `rank 0` when that persisted leftover-map rank is a non-negative integer.
+ Comparison copy uses `leftover map comparison graphic leftover-map rank {label}`
+ so it stays distinct from `leftover-map rank {label}` and from strip
+ `Leftover map comparison rank`. This increment does not caption leftover-map
+ distance on the comparison graphic with a distinct name. Do not invent leftover-map
+ rank from plotted coordinates or leftover-map distance. Never invent a leftover score.
+ Never invent a theta. No new columns.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index eacbaf474..50d1ad9c6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,81 @@ All notable changes to this project are documented here. Format follows
### Added
+- Period leftover pairs now name leftover-map rank on the grouping
+ comparison leftover-map graphic (ADR 0318 / v2.75.0). After `make seed`,
+ closest and farthest leftover pairs sit above the member list with leftover-map
+ rank on that grouping comparison leftover-map graphic when
+ formatLeftoverMapRank returns a usable badge; click a post marker or a pair
+ button opens that post. A missing, negative, or non-integer rank omits that leftover-map
+ comparison graphic leftover-map rank caption and keeps leftover expected `E`
+ and leftover observed `Y`. Rank-0 origin cells still name `rank 0` when that
+ persisted leftover-map rank is a non-negative integer. Comparison copy uses
+ `leftover map comparison graphic leftover-map rank {label}` so it stays
+ distinct from `leftover-map rank {label}` and from strip
+ `Leftover map comparison rank`. This increment does not caption leftover-map
+ distance on the comparison graphic with a distinct name. Do not invent leftover-map
+ rank from plotted coordinates or leftover-map distance. Never invent a leftover score
+ or a theta. No new columns.
+
+- Period leftover pairs now name leftover expected on the grouping
+ comparison leftover-map graphic (ADR 0317 / v2.74.0). After `make seed`,
+ closest and farthest leftover pairs sit above the member list with leftover
+ expected `E` on that grouping comparison leftover-map graphic when
+ formatLeftoverMapExpected returns a usable badge; click a post marker or a pair
+ button opens that post. A missing or non-finite `E` omits that leftover-map
+ comparison graphic leftover expected caption and keeps leftover observed `Y`
+ and leftover residual `R`. Rank-0 origin cells still name `E 0.00` when that
+ persisted leftover expected is finite. Comparison copy uses
+ `leftover map comparison graphic leftover expected {label}` so it stays
+ distinct from `leftover expected {label}` and from strip
+ `Leftover map comparison expected`. This increment does not caption leftover-map
+ rank on the comparison graphic with a distinct name. Do not invent `E` from
+ `Y` and `R`. A finite negative leftover expected is shown, never clamped.
+ Never invent a leftover score or a theta. No new columns.
+
+- Period leftover pairs now name leftover observed on the grouping
+ comparison leftover-map graphic (ADR 0316 / v2.73.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 complete-case coverage when leftoverMapCoverageCounts
+ returns usable complete-case integers, leftover-map item complete-case
+ coverage when leftoverMapItemCoverageCounts returns usable complete-case
+ integers, leftover-map incomplete post coverage when leftoverMapIncompletePostCount
+ returns a usable dropped integer, leftover-map incomplete item coverage when
+ leftoverMapIncompleteItemCount returns a usable dropped integer, leftover-map
+ reconstruction `R̂` when formatLeftoverMapReconstruction returns a usable signed
+ badge, leftover-map explained leftover share `e` when formatLeftoverMapExplainedShare
+ returns a usable badge, leftover-map unexplained leftover share `s` when
+ formatLeftoverMapUnexplainedShare returns a usable badge, leftover-map
+ cross share `x` when formatLeftoverMapCrossShare returns a usable badge, leftover-map
+ unexplained leftover `U` when formatLeftoverMapUnexplained returns a usable badge,
+ leftover residual `R` when formatLeftoverMapResidual returns a usable badge,
+ and leftover observed `Y` on that grouping comparison leftover-map graphic when
+ formatLeftoverMapObserved returns a usable badge; click a post marker or a pair
+ button opens that post. A missing or non-finite `Y` omits that leftover-map
+ comparison graphic leftover observed caption and keeps leftover residual
+ `R`, leftover-map unexplained leftover `U`, leftover-map cross share `x`, leftover-map unexplained leftover share `s`, leftover-map explained leftover
+ share `e`, leftover-map reconstruction `R̂`, leftover-map distance `d`, leftover-map
+ comparison graphic coverage, leftover-map comparison graphic item coverage,
+ leftover-map comparison graphic incomplete posts, and leftover-map comparison
+ graphic incomplete items when those helpers return usable integers. Rank-0 origin
+ cells still plot at `(0, 0)` and still name `Y 0.00` when that persisted leftover
+ observed is finite. Comparison copy uses `leftover map comparison graphic
+ leftover observed {label}` so it stays distinct from
+ `leftover observed {label}` and from strip `Leftover map comparison observed`.
+ Leftover observed omits independently of leftover residual, leftover-map unexplained leftover,
+ leftover-map cross share, leftover-map unexplained leftover share, leftover-map explained leftover share,
+ leftover-map reconstruction, leftover-map distance, and coverage notes. This
+ increment does not caption leftover expected on the comparison
+ graphic with a distinct name. Do not invent `Y` from `R` and `E`, leftover residual, leftover-map
+ reconstruction, leftover-map unexplained leftover, leftover-map distance, plotted coordinates,
+ leftover-map rank, leftover-map axis share, leftover expected,
+ leftover-map post coverage, leftover-map item coverage, leftover-map incomplete
+ post coverage, leftover-map incomplete item coverage, leftover pair count, or the
+ count of unused axes. A finite negative leftover observed 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 residual on the grouping
comparison leftover-map graphic (ADR 0315 / v2.72.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 6afe7c990..7a7e3b8c3 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 / 0306 / 0307 / 0308 / 0309 / 0310 / 0311 / 0312 / 0313 / 0314 / 0315), 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 / 0307 / 0308 / 0309 / 0310 / 0311 / 0312 / 0313 / 0314 / 0315 / 0316 / 0317 / 0318), 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/0315-leftover-map-compare-plot-residual.md b/docs/adr/0315-leftover-map-compare-plot-residual.md
index a770fc040..b14ad095b 100644
--- a/docs/adr/0315-leftover-map-compare-plot-residual.md
+++ b/docs/adr/0315-leftover-map-compare-plot-residual.md
@@ -3,6 +3,9 @@
**Decision status:** Accepted
**Date:** 2026-08-31
+**Amended by:** [ADR 0316](0316-leftover-map-compare-plot-observed.md)
+(leftover observed on the grouping comparison leftover-map graphic)
+
Amends leftover residual on graphic-display pair segments
([ADR 0277](0277-leftover-map-segment-residual.md)), leftover residual
on grouping comparison strip pair rows
@@ -193,9 +196,9 @@ a usable leftover-map unexplained leftover caption, a usable leftover-map cross
distance caption, a usable post caption, a usable item caption, a usable incomplete
posts caption, and a usable incomplete items caption.
-This increment does not caption leftover observed `Y` on the comparison graphic
-with a distinct comparison-graphic name. That leftover observed already sits on
-the strip through ADR 0299. A finite negative leftover on neighbouring fields is shown,
+This increment does not caption leftover expected `E` on the comparison graphic
+with a distinct comparison-graphic name. Leftover observed `Y` on that comparison
+graphic is [ADR 0316](0316-leftover-map-compare-plot-observed.md). 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
diff --git a/docs/adr/0316-leftover-map-compare-plot-observed.md b/docs/adr/0316-leftover-map-compare-plot-observed.md
new file mode 100644
index 000000000..9a59ec390
--- /dev/null
+++ b/docs/adr/0316-leftover-map-compare-plot-observed.md
@@ -0,0 +1,187 @@
+# ADR 0316 — Name leftover observed on the grouping comparison leftover-map graphic
+
+**Decision status:** Accepted
+**Date:** 2026-08-31
+
+**Amended by:** [ADR 0317](0317-leftover-map-compare-plot-expected.md)
+(leftover expected on the grouping comparison leftover-map graphic)
+
+Amends leftover observed on graphic-display pair segments
+([ADR 0278](0278-leftover-map-segment-observed.md)), leftover observed
+on grouping comparison strip pair rows
+([ADR 0299](0299-leftover-map-compare-observed.md)), leftover residual
+on the grouping comparison leftover-map graphic
+([ADR 0315](0315-leftover-map-compare-plot-residual.md)), leftover-map
+unexplained leftover on the grouping comparison leftover-map graphic
+([ADR 0314](0314-leftover-map-compare-plot-unexplained-leftover.md)), leftover-map
+cross share on the grouping comparison leftover-map graphic
+([ADR 0313](0313-leftover-map-compare-plot-cross-share.md)), leftover-map
+unexplained leftover share on the grouping comparison leftover-map graphic
+([ADR 0312](0312-leftover-map-compare-plot-unexplained-share.md)), leftover-map
+explained leftover share on the grouping comparison leftover-map graphic
+([ADR 0311](0311-leftover-map-compare-plot-explained-share.md)), leftover-map
+reconstruction on the grouping comparison leftover-map graphic
+([ADR 0310](0310-leftover-map-compare-plot-reconstruction.md)), leftover-map
+incomplete item coverage on the grouping comparison leftover-map graphic
+([ADR 0309](0309-leftover-map-compare-plot-incomplete-item.md)), leftover-map
+incomplete post coverage on the grouping comparison leftover-map graphic
+([ADR 0308](0308-leftover-map-compare-plot-incomplete-post.md)), leftover-map item
+complete-case coverage on the grouping comparison leftover-map graphic
+([ADR 0307](0307-leftover-map-compare-plot-item-coverage.md)), leftover-map
+complete-case coverage on the grouping comparison leftover-map graphic
+([ADR 0306](0306-leftover-map-compare-plot-coverage.md)), leftover-map axis share
+on the grouping comparison leftover-map graphic
+([ADR 0305](0305-leftover-map-compare-plot-axis-share.md)), leftover-map graphic
+display on the grouping comparison strip
+([ADR 0304](0304-leftover-map-compare-graphic.md)), leftover observed
+disclosure ([ADR 0163](0163-leftover-observed-expected.md)), leftover pairs on
+the grouping comparison strip
+([ADR 0149](0149-leftover-pairs-on-comparison-strip.md)), leftover residual
+on grouping comparison strip pair rows
+([ADR 0298](0298-leftover-map-compare-residual.md)), leftover residual
+on pair segments ([ADR 0277](0277-leftover-map-segment-residual.md)), leftover-map
+graphic display ([ADR 0268](0268-leftover-map-graphic-display.md)), leftover-map
+coordinates ([ADR 0267](0267-leftover-map-coordinates.md)). Independent of leftover
+expected on the grouping comparison leftover-map graphic.
+
+## Context
+
+ADR 0163 already persists leftover observed `Y` and leftover expected
+`E[Y|θ, item]`. ADR 0278 already captions period-report leftover-map pair
+segments with `leftover observed {label}` when that leftover observed is
+finite. ADR 0299 already captions grouping comparison leftover-pair
+buttons with that same persisted leftover observed under accessible name
+`Leftover map comparison observed`. ADR 0315 already captions leftover
+residual on the grouping comparison leftover-map graphic. The comparison
+graphic still reuses `leftover observed {label}`, so a buyer who compares leftover
+pairs can treat the period-report graphic caption as the comparison graphic
+leftover observed even after the strip names `Y`. Hiding a distinct
+comparison-graphic leftover observed caption lets leftover residual `R` or leftover expected
+`E` be read as leftover observed without a next action. When `Y`, `E`, and `R` are
+finite, `Y − E = R`; the comparison graphic must name the same
+persisted `Y` the pair row and strip already show. A finite negative leftover is
+shown, never clamped.
+
+This increment captions leftover observed on the grouping
+comparison leftover-map graphic from already-named leftover observed
+through formatLeftoverMapObserved. Comparison copy uses the accessible
+name `leftover map comparison graphic leftover observed {label}` so it stays
+distinct from `leftover observed {label}` on the
+period-report graphic and from strip `Leftover map comparison observed`.
+It does not add columns. It does not recompute leftover observed
+from `R` and `E`, leftover residual, leftover-map unexplained leftover, leftover-map reconstruction, leftover-map distance,
+plotted coordinates, leftover-map rank, leftover-map axis share, leftover-map post
+coverage, leftover-map item coverage, leftover-map incomplete post coverage,
+leftover-map incomplete item coverage, leftover pair count, or the count of unused
+axes. 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 **0316** so it does not collide with
+leftover residual on the grouping comparison leftover-map graphic
+(0315), leftover-map unexplained leftover on the grouping comparison leftover-map graphic
+(0314), leftover-map cross share on the grouping comparison leftover-map graphic
+(0313), leftover residual on grouping comparison strip pair rows
+(0298), leftover residual on pair segments (0277), leftover observed
+on grouping comparison strip pair rows (0299), leftover observed
+on pair segments (0278), leftover observed / expected disclosure (0163), leftover-map
+graphic display (0268), leftover-map coordinates (0267), or the dashboard stacks.
+
+## Decision
+
+On the grouping comparison leftover-map graphic, caption each pair segment
+with persisted leftover observed when formatLeftoverMapObserved
+returns a usable badge, next to leftover residual `R`. Use the
+distinct accessible name `leftover map comparison graphic leftover observed {label}`
+so the graphic caption is not the strip badge (`Leftover map comparison observed`)
+and is not the period-report graphic caption (`leftover observed {label}`).
+A missing or non-finite `Y` omits that leftover-map comparison graphic
+leftover observed caption and keeps leftover residual `R` when
+formatLeftoverMapResidual returns a usable badge, leftover-map unexplained leftover `U` when
+formatLeftoverMapUnexplained returns a usable badge, leftover-map cross share `x` when
+formatLeftoverMapCrossShare returns a usable badge, leftover-map unexplained leftover share `s` when
+formatLeftoverMapUnexplainedShare returns a usable badge, leftover-map explained leftover share `e` when
+formatLeftoverMapExplainedShare returns a usable badge, leftover-map reconstruction `R̂` when
+formatLeftoverMapReconstruction returns a usable signed badge, leftover-map distance `d`, leftover map comparison
+axis share when finite, leftover map comparison axis text, leftover-map comparison
+graphic coverage when leftoverMapCoverageCounts returns usable complete-case
+integers, leftover-map comparison graphic item coverage when leftoverMapItemCoverageCounts
+returns usable complete-case integers, leftover-map comparison graphic incomplete
+posts when leftoverMapIncompletePostCount returns a usable dropped integer,
+leftover-map comparison graphic incomplete items when leftoverMapIncompleteItemCount
+returns a usable dropped integer, leftover-map rank when that rank is a non-negative
+integer, leftover expected `E` when finite, leftover-map reconstruction `R̂` when
+finite, leftover-map distance `d`, plus the strip leftover observed badge.
+Rank-0 origin cells still name `Y 0.00` when that persisted leftover
+observed is finite. A finite negative leftover is shown, never clamped. Do not invent `Y` from
+`R` and `E`, leftover residual, leftover-map reconstruction, leftover-map unexplained leftover, leftover-map distance,
+plotted coordinates, leftover-map rank, leftover-map axis share, leftover-map post
+coverage, leftover-map item coverage, leftover-map incomplete post coverage,
+leftover-map incomplete item coverage, leftover pair count, or the count of unused
+axes. Click a post marker to open that post.
+
+Leftover observed omits independently of leftover residual captions,
+leftover-map unexplained leftover captions,
+leftover-map cross share captions,
+unexplained leftover share captions, explained leftover share captions, reconstruction captions,
+coverage notes, and leftover-map distance. A missing leftover
+observed omits leftover-map comparison graphic leftover observed and keeps
+a usable leftover residual caption, a usable leftover-map unexplained leftover caption, a usable leftover-map cross share caption, a usable unexplained leftover share caption, a usable explained leftover share caption, a usable reconstruction caption, a usable
+distance caption, a usable post caption, a usable item caption, a usable incomplete
+posts caption, and a usable incomplete items caption.
+
+This increment does not caption leftover-map rank on the comparison graphic
+with a distinct comparison-graphic name. Leftover expected `E` on that comparison
+graphic is [ADR 0317](0317-leftover-map-compare-plot-expected.md). 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
+observed on that graphic when formatLeftoverMapObserved
+returns a usable badge. Rank-0 unused axes still plot at
+the origin and still name `Y 0.00` when that persisted leftover
+observed is finite. 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 residual on grouping comparison strip pair rows, leftover
+expected on grouping comparison strip pair rows, leftover observed
+on grouping comparison strip pair rows, leftover residual
+on pair segments, leftover observed on pair segments, leftover expected on
+pair segments, leftover-map unexplained leftover on the grouping
+comparison leftover-map graphic, leftover residual on the grouping
+comparison leftover-map graphic, leftover-map graphic display, leftover-map
+coordinates, leftover-map coordinate ticks, leftover-map complete-case
+coverage on the grouping comparison leftover-map graphic, leftover-map
+axis share on the grouping comparison leftover-map graphic,
+and leftover expected 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. Observed
+category after IRT main effects is persisted `Y`. Grouping comparison leftover
+observed captions that persisted leftover on the grouping comparison leftover-map
+graphic only when formatLeftoverMapObserved returns a usable badge.
+Rank-0 unused axes still name `Y 0.00` when that leftover
+observed is stored. A finite negative leftover is shown, never clamped.)
+
+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/adr/0317-leftover-map-compare-plot-expected.md b/docs/adr/0317-leftover-map-compare-plot-expected.md
new file mode 100644
index 000000000..10cbe587a
--- /dev/null
+++ b/docs/adr/0317-leftover-map-compare-plot-expected.md
@@ -0,0 +1,105 @@
+# ADR 0317 — Name leftover expected on the grouping comparison leftover-map graphic
+
+**Decision status:** Accepted
+**Date:** 2026-08-31
+
+**Amended by:** [ADR 0318](0318-leftover-map-compare-plot-rank.md)
+(leftover-map rank on the grouping comparison leftover-map graphic)
+
+Amends leftover expected on graphic-display pair segments
+([ADR 0279](0279-leftover-map-segment-expected.md)), leftover expected
+on grouping comparison strip pair rows
+([ADR 0300](0300-leftover-map-compare-expected.md)), leftover observed
+on the grouping comparison leftover-map graphic
+([ADR 0316](0316-leftover-map-compare-plot-observed.md)), leftover residual
+on the grouping comparison leftover-map graphic
+([ADR 0315](0315-leftover-map-compare-plot-residual.md)), leftover observed `Y` /
+expected `E` ([ADR 0163](0163-leftover-observed-expected.md)), leftover-map graphic
+display on the grouping comparison strip
+([ADR 0304](0304-leftover-map-compare-graphic.md)). Independent of leftover-map
+rank on the grouping comparison leftover-map graphic.
+
+## Context
+
+ADR 0163 already persists leftover expected `E[Y|θ, item]`. ADR 0279 already
+captions period-report leftover-map pair segments with
+`leftover expected {label}` when that leftover expected is finite. ADR 0300
+already captions grouping comparison leftover-pair buttons with that same
+persisted leftover expected under accessible name
+`Leftover map comparison expected`. ADR 0316 already captions leftover
+observed on the grouping comparison leftover-map graphic. The comparison
+graphic still reuses `leftover expected {label}`, so a buyer who compares leftover
+pairs can treat the period-report graphic caption as the comparison graphic
+leftover expected even after the strip names `E`. Hiding a distinct
+comparison-graphic leftover expected caption lets leftover observed `Y` or leftover residual
+`R` be read as leftover expected without a next action. When `Y`, `E`, and `R` are
+finite, `Y − E = R`; the comparison graphic must name the same
+persisted `E` the pair row and strip already show. A finite negative leftover is
+shown, never clamped.
+
+This increment captions leftover expected on the grouping
+comparison leftover-map graphic from already-named leftover expected
+through formatLeftoverMapExpected. Comparison copy uses the accessible
+name `leftover map comparison graphic leftover expected {label}` so it stays
+distinct from `leftover expected {label}` on the
+period-report graphic and from strip `Leftover map comparison expected`.
+It does not add columns. It does not recompute leftover expected
+from `Y` and `R`. Do not invent a leftover score. Do not invent a theta.
+
+This protected increment uses **0317** so it does not collide with leftover
+observed on the grouping comparison leftover-map graphic (0316), leftover residual
+on that graphic (0315), leftover expected on grouping comparison strip pair rows
+(0300), leftover expected on pair segments (0279), leftover observed / expected
+disclosure (0163), leftover-map graphic display (0268), or the dashboard stacks.
+
+## Decision
+
+On the grouping comparison leftover-map graphic, caption each pair segment
+with persisted leftover expected when formatLeftoverMapExpected
+returns a usable badge, next to leftover observed `Y`. Use the
+distinct accessible name `leftover map comparison graphic leftover expected {label}`
+so the graphic caption is not the strip badge (`Leftover map comparison expected`)
+and is not the period-report graphic caption (`leftover expected {label}`).
+A missing or non-finite `E` omits that leftover-map comparison graphic
+leftover expected caption and keeps leftover observed `Y` when
+formatLeftoverMapObserved returns a usable badge, leftover residual `R` when
+formatLeftoverMapResidual returns a usable badge, leftover-map unexplained leftover `U`, leftover-map cross share `x`, leftover-map unexplained leftover share `s`, leftover-map explained leftover share `e`, leftover-map reconstruction `R̂`, leftover-map distance `d`, leftover-map comparison graphic coverage notes, leftover-map rank, leftover observed `Y`, plus the strip leftover expected badge.
+Rank-0 origin cells still name `E 0.00` when that persisted leftover
+expected is finite. A finite negative leftover is shown, never clamped. Do not invent `E` from
+`Y` and `R`. Click a post marker to open that post.
+
+Leftover expected omits independently of leftover observed captions and leftover residual captions.
+A missing leftover expected omits leftover-map comparison graphic leftover expected and keeps
+a usable leftover observed caption and a usable leftover residual caption.
+
+This increment does not caption leftover-map distance on the comparison graphic
+with a distinct comparison-graphic name. Leftover-map rank on that comparison
+graphic is [ADR 0318](0318-leftover-map-compare-plot-rank.md). That leftover-map rank already sits on
+the strip through ADR 0301.
+
+Do not add SQL migrations. Do not edit shipped migrations. 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
+expected on that graphic when formatLeftoverMapExpected
+returns a usable badge. Rank-0 unused axes still plot at
+the origin and still name `E 0.00` when that persisted leftover
+expected is finite. Click a post marker or a pair button opens that post. When `Y`, `E`, and `R` are finite, `Y − E = R`.
+
+## Related
+
+Independent of leftover-map rank 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
+
+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/adr/0318-leftover-map-compare-plot-rank.md b/docs/adr/0318-leftover-map-compare-plot-rank.md
new file mode 100644
index 000000000..7120ba08c
--- /dev/null
+++ b/docs/adr/0318-leftover-map-compare-plot-rank.md
@@ -0,0 +1,109 @@
+# ADR 0318 — Name leftover-map rank on the grouping comparison leftover-map graphic
+
+**Decision status:** Accepted
+**Date:** 2026-08-31
+
+Amends leftover-map rank on graphic-display pair segments
+([ADR 0280](0280-leftover-map-segment-rank.md)), leftover-map rank
+on grouping comparison strip pair rows
+([ADR 0301](0301-leftover-map-compare-rank.md)), leftover expected
+on the grouping comparison leftover-map graphic
+([ADR 0317](0317-leftover-map-compare-plot-expected.md)), leftover observed
+on the grouping comparison leftover-map graphic
+([ADR 0316](0316-leftover-map-compare-plot-observed.md)), leftover residual
+on the grouping comparison leftover-map graphic
+([ADR 0315](0315-leftover-map-compare-plot-residual.md)), leftover-map rank
+([ADR 0164](0164-leftover-map-rank.md)), leftover-map graphic
+display on the grouping comparison strip
+([ADR 0304](0304-leftover-map-compare-graphic.md)). Independent of leftover-map
+distance on the grouping comparison leftover-map graphic.
+
+## Context
+
+ADR 0164 already persists leftover-map rank — the number of Gabriel
+singular values above the leftover singular floor. A rank-0 residual still
+emits a stable closest/farthest pair so `make seed` is not empty; the stored
+distance is then zero, not a fabricated interaction. ADR 0280 already captions
+period-report leftover-map pair segments with `leftover-map rank {label}` when
+that leftover-map rank is a non-negative integer. ADR 0301 already captions
+grouping comparison leftover-pair buttons with that same persisted leftover-map
+rank under accessible name `Leftover map comparison rank`. ADR 0317 already
+captions leftover expected on the grouping comparison leftover-map graphic.
+The comparison graphic still reuses `leftover-map rank {label}`, so a buyer who
+compares leftover pairs can treat the period-report graphic caption as the
+comparison graphic leftover-map rank even after the strip names `rank n`.
+Hiding a distinct comparison-graphic leftover-map rank caption lets leftover
+expected `E` or leftover-map distance `d` be read as leftover-map rank without
+a next action. The comparison graphic must name the same persisted rank the
+pair row and strip already show. Rank-0 origin cells still name `rank 0` when
+that persisted leftover-map rank is a non-negative integer.
+
+This increment captions leftover-map rank on the grouping comparison leftover-map
+graphic from already-named leftover-map rank through formatLeftoverMapRank.
+Comparison copy uses the accessible name
+`leftover map comparison graphic leftover-map rank {label}` so it stays
+distinct from `leftover-map rank {label}` on the period-report graphic and from
+strip `Leftover map comparison rank`. It does not add columns. It does not
+recompute leftover-map rank from plotted coordinates, leftover-map distance, or
+the count of unused axes. Do not invent a leftover score. Do not invent a theta.
+
+This protected increment uses **0318** so it does not collide with leftover
+expected on the grouping comparison leftover-map graphic (0317), leftover observed
+on that graphic (0316), leftover residual on that graphic (0315), leftover-map
+rank on grouping comparison strip pair rows (0301), leftover-map rank on pair
+segments (0280), leftover-map rank persistence (0164), leftover-map graphic
+display (0268), or the dashboard stacks.
+
+## Decision
+
+On the grouping comparison leftover-map graphic, caption each pair segment
+with persisted leftover-map rank when formatLeftoverMapRank returns a usable
+badge, next to leftover expected `E`. Use the distinct accessible name
+`leftover map comparison graphic leftover-map rank {label}` so the graphic
+caption is not the strip badge (`Leftover map comparison rank`) and is not the
+period-report graphic caption (`leftover-map rank {label}`). A missing rank, a
+negative rank, or a non-integer rank omits that leftover-map comparison graphic
+leftover-map rank caption and keeps leftover expected `E` when
+formatLeftoverMapExpected returns a usable badge, leftover observed `Y` when
+formatLeftoverMapObserved returns a usable badge, leftover residual `R` when
+formatLeftoverMapResidual returns a usable badge, leftover-map unexplained leftover `U`, leftover-map cross share `x`, leftover-map unexplained leftover share `s`, leftover-map explained leftover share `e`, leftover-map reconstruction `R̂`, leftover-map distance `d`, leftover-map comparison graphic coverage notes, leftover expected `E`, leftover observed `Y`, plus the strip leftover-map rank badge.
+Rank-0 origin cells still name `rank 0` when that persisted leftover-map rank is
+a non-negative integer. Do not invent leftover-map rank from plotted coordinates,
+leftover-map distance, leftover expected, leftover observed, leftover residual, leftover-map reconstruction, leftover-map unexplained leftover, leftover-map axis share, leftover-map post coverage, leftover-map item coverage, leftover-map incomplete post coverage, leftover-map incomplete item coverage, leftover pair count, or the count of unused axes. Click a post marker to open that post.
+
+Leftover-map rank omits independently of leftover expected captions and leftover observed captions.
+A missing leftover-map rank omits leftover-map comparison graphic leftover-map rank and keeps
+a usable leftover expected caption and a usable leftover observed caption.
+
+This increment does not caption leftover-map distance on the comparison graphic
+with a distinct comparison-graphic name. That leftover-map distance already sits
+on the period-report graphic through ADR 0271.
+
+Do not add SQL migrations. Do not edit shipped migrations. 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
+rank on that graphic when formatLeftoverMapRank returns a usable badge.
+Rank-0 unused axes still plot at the origin and still name `rank 0` when that
+persisted leftover-map rank is a non-negative integer. Click a post marker or a
+pair button opens that post. When `Y`, `E`, and `R` are finite, `Y − E = R`.
+When `R`, `R̂`, and `U` are finite, `U + R̂ = R`. When coordinates,
+reconstruction, and distance are finite, `R̂ = ξ · ζ` and `d = ‖ξ − ζ‖`.
+
+## Related
+
+Independent of leftover-map distance 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
+
+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 5594209eb..14a20d511 100644
--- a/docs/product-technical-gap-baseline.md
+++ b/docs/product-technical-gap-baseline.md
@@ -1,5 +1,59 @@
# Product & Technical Gap Baseline
+> Exact-head loop overlay: 2026-08-31 09:19 KST. Protected `main` is
+> `cb187cadee5fb6c46d8a944815ccc154a1e028d1`. Writes work. Do not
+> self-approve. #857 leftover expected on the grouping comparison leftover-map
+> graphic (v2.74.0 / ADR 0317) is `9f34d2c`, stacked on #856. Independent
+> APPROVE is missing. Next buyer increment on this
+> cycle: leftover-map rank on the grouping comparison leftover-map
+> graphic (ADR 0318 / v2.75.0) delivered locally on
+> `feat/leftover-map-compare-plot-rank-v2750`. Caption persisted leftover-map
+> rank on that comparison graphic from already-named leftover_map_rank.
+> Distinct accessible name `leftover map comparison graphic leftover-map
+> rank {label}`. Omit when formatLeftoverMapRank fail-closes.
+> Do not caption leftover-map distance on that comparison graphic with a distinct name this
+> increment. Do not invent leftover-map rank from plotted coordinates or leftover-map
+> distance. Stack onto #857. Leave open for independent review. Do not squash-merge. Do not
+> self-approve. Issues #79 and #87 stay open. Do not merge #808 without independent APPROVE.
+> Never self-approve.
+
+> Exact-head loop overlay: 2026-08-31 09:05 KST. Protected `main` is
+> `cb187cadee5fb6c46d8a944815ccc154a1e028d1`. Writes work. Do not
+> self-approve. #856 leftover observed on the grouping comparison leftover-map
+> graphic (v2.73.0 / ADR 0316) is `c7a8680`, stacked on #855 @ `1087b16`.
+> Independent APPROVE is missing. Next buyer increment on this
+> cycle: leftover expected on the grouping comparison leftover-map
+> graphic (ADR 0317 / v2.74.0) delivered locally on
+> `feat/leftover-map-compare-plot-expected-v2740`. Caption persisted leftover
+> expected `E` on that comparison graphic from already-named
+> expected_response. Distinct accessible name `leftover map comparison graphic
+> leftover expected {label}`. Omit when formatLeftoverMapExpected fail-closes.
+> Do not caption leftover-map rank on that comparison graphic with a distinct name this
+> increment. Do not invent `E` from `Y` and `R`. Stack onto #856. Leave open for
+> independent review. Do not squash-merge. Do not self-approve. Issues #79 and #87
+> stay open. Do not merge #808 without independent APPROVE. Never self-approve.
+
+> Exact-head loop overlay: 2026-08-31 08:50 KST. Protected `main` is
+> `cb187cadee5fb6c46d8a944815ccc154a1e028d1`. Writes work. Do not
+> self-approve. #855 leftover residual on the grouping comparison leftover-map
+> graphic (v2.72.0 / ADR 0315) is `1087b16` (a11y name
+> `leftover map comparison graphic leftover residual {label}`), stacked on #854 @
+> `935cdea`. Independent APPROVE is missing. Next buyer increment on this
+> cycle: leftover observed on the grouping comparison leftover-map
+> graphic (ADR 0316 / v2.73.0) delivered locally on
+> `feat/leftover-map-compare-plot-observed-v2730`. Caption persisted leftover
+> observed `Y` on that comparison graphic from already-named
+> observed_response. Distinct accessible name `leftover map comparison graphic
+> leftover observed {label}`. Omit when formatLeftoverMapObserved fail-closes.
+> Do not caption leftover expected on that comparison graphic with a distinct name this
+> increment. Do not invent `Y` from `R` and `E`, leftover residual, leftover-map reconstruction, leftover-map unexplained leftover,
+> leftover-map distance, plotted coordinates, leftover-map rank, leftover-map axis share,
+> leftover-map post coverage, leftover-map item coverage, leftover-map incomplete post coverage,
+> leftover-map incomplete item coverage, leftover pair count, or the count of unused
+> axes. Stack onto #855. Leave open for independent review. Do not squash-merge. Do not
+> self-approve. Issues #79 and #87 stay open. Do not merge #808 without independent APPROVE.
+> Closed #96 this cycle (weaker duplicate of #91). Never self-approve.
+
> Exact-head loop overlay: 2026-08-31 08:20 KST. Protected `main` is
> `cb187cadee5fb6c46d8a944815ccc154a1e028d1`. Writes work. Do not
> self-approve. #854 leftover-map unexplained leftover on the grouping comparison leftover-map
diff --git a/frontend/package.json b/frontend/package.json
index 4ac282897..bf600eb93 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,7 +1,7 @@
{
"name": "frontend",
"private": true,
- "version": "2.72.0",
+ "version": "2.75.0",
"type": "module",
"scripts": {
"dev": "vite",
diff --git a/frontend/src/App.test.tsx b/frontend/src/App.test.tsx
index f7f212f1f..3efd4e53a 100644
--- a/frontend/src/App.test.tsx
+++ b/frontend/src/App.test.tsx
@@ -4594,10 +4594,15 @@ describe("App, authenticated", () => {
)[1],
).toHaveTextContent("R +0.40");
expect(
- within(screen.getByLabelText("Grouping comparison")).queryByLabelText(
- /leftover observed/,
+ within(screen.getByLabelText("Grouping comparison")).getByLabelText(
+ "leftover map comparison graphic leftover observed Y 2.40",
),
).toHaveTextContent("Y 2.40");
+ expect(
+ within(screen.getByLabelText("Grouping comparison")).queryByLabelText(
+ "leftover observed Y 2.40",
+ ),
+ ).not.toBeInTheDocument();
expect(
within(screen.getByLabelText("Grouping comparison")).getByLabelText(
"Leftover map comparison observed",
@@ -4609,10 +4614,15 @@ describe("App, authenticated", () => {
),
).toHaveLength(1);
expect(
- within(screen.getByLabelText("Grouping comparison")).queryByLabelText(
- /leftover expected/,
+ within(screen.getByLabelText("Grouping comparison")).getByLabelText(
+ "leftover map comparison graphic leftover expected E 2.00",
),
).toHaveTextContent("E 2.00");
+ expect(
+ within(screen.getByLabelText("Grouping comparison")).queryByLabelText(
+ "leftover expected E 2.00",
+ ),
+ ).not.toBeInTheDocument();
expect(
within(screen.getByLabelText("Grouping comparison")).getByLabelText(
"Leftover map comparison expected",
@@ -4624,10 +4634,15 @@ describe("App, authenticated", () => {
),
).toHaveLength(1);
expect(
- within(screen.getByLabelText("Grouping comparison")).queryByLabelText(
- /leftover-map rank/,
+ within(screen.getByLabelText("Grouping comparison")).getByLabelText(
+ "leftover map comparison graphic leftover-map rank rank 1",
),
).toHaveTextContent("rank 1");
+ expect(
+ within(screen.getByLabelText("Grouping comparison")).queryByLabelText(
+ "leftover-map rank rank 1",
+ ),
+ ).not.toBeInTheDocument();
expect(
within(screen.getByLabelText("Grouping comparison")).getByLabelText(
"Leftover map comparison rank",
diff --git a/frontend/src/components/LeftoverMapPlot.test.tsx b/frontend/src/components/LeftoverMapPlot.test.tsx
index 23902ab2b..a86a35c39 100644
--- a/frontend/src/components/LeftoverMapPlot.test.tsx
+++ b/frontend/src/components/LeftoverMapPlot.test.tsx
@@ -2024,4 +2024,400 @@ describe("LeftoverMapPlot", () => {
);
expect(screen.getByText("leftover map comparison axis 1 (0%)")).toBeInTheDocument();
});
+
+ it("names leftover observed on the comparison graphic with a distinct accessible name", () => {
+ render(
+ ,
+ );
+ expect(
+ screen.getByLabelText("leftover map comparison graphic leftover observed Y 2.40"),
+ ).toHaveTextContent("Y 2.40");
+ expect(
+ screen.getByLabelText("leftover map comparison graphic leftover observed Y 0.90"),
+ ).toHaveTextContent("Y 0.90");
+ expect(screen.queryByLabelText("leftover observed Y 2.40")).not.toBeInTheDocument();
+ expect(screen.queryByLabelText("leftover observed Y 0.90")).not.toBeInTheDocument();
+ expect(screen.queryByLabelText("Leftover map comparison observed")).not.toBeInTheDocument();
+ expect(
+ screen.getByLabelText("leftover map comparison graphic leftover residual R +0.40"),
+ ).toHaveTextContent("R +0.40");
+ expect(
+ screen.getByLabelText("leftover map comparison graphic unexplained leftover U +0.05"),
+ ).toHaveTextContent("U +0.05");
+ expect(
+ screen.getByLabelText("leftover map comparison graphic reconstruction R̂ +0.25"),
+ ).toHaveTextContent("R̂ +0.25");
+ expect(screen.getByText("leftover map comparison axis 1 (82%)")).toBeInTheDocument();
+ });
+
+ it("omits leftover-map comparison graphic leftover observed when Y is missing or not usable", () => {
+ render(
+ ,
+ );
+ expect(screen.queryByLabelText(/leftover map comparison graphic leftover observed Y/)).not.toBeInTheDocument();
+ expect(screen.queryByLabelText(/^leftover observed Y/)).not.toBeInTheDocument();
+ expect(
+ screen.getByLabelText("leftover map comparison graphic leftover residual R +0.40"),
+ ).toHaveTextContent("R +0.40");
+ expect(
+ screen.getByLabelText("leftover map comparison graphic unexplained leftover U +0.05"),
+ ).toHaveTextContent("U +0.05");
+ expect(
+ screen.getByLabelText("leftover map comparison graphic reconstruction R̂ +0.25"),
+ ).toBeInTheDocument();
+ expect(screen.getByLabelText("leftover-map distance d 0.12")).toBeInTheDocument();
+ expect(screen.getByLabelText("Leftover map comparison graphic coverage")).toHaveTextContent(
+ "Leftover map used 2 of 3 scored posts (complete-case)",
+ );
+ expect(screen.getByText("leftover map comparison axis 1 (82%)")).toBeInTheDocument();
+ });
+
+ it("names rank-0 origin leftover observed on the comparison graphic when that persisted value is finite", () => {
+ render(
+ ,
+ );
+ expect(
+ screen.getByLabelText("leftover map comparison graphic leftover observed Y 0.00"),
+ ).toHaveTextContent("Y 0.00");
+ expect(screen.queryByLabelText("leftover observed Y 0.00")).not.toBeInTheDocument();
+ expect(
+ screen.getByLabelText("leftover map comparison graphic leftover residual R 0.00"),
+ ).toHaveTextContent("R 0.00");
+ expect(
+ screen.getByLabelText("leftover map comparison graphic unexplained leftover U 0.00"),
+ ).toHaveTextContent("U 0.00");
+ expect(
+ screen.getByLabelText("leftover map comparison graphic reconstruction R̂ 0.00"),
+ ).toHaveTextContent("R̂ 0.00");
+ expect(screen.getByLabelText("Leftover map comparison graphic coverage")).toHaveTextContent(
+ "Leftover map used 0 of 3 scored posts (complete-case)",
+ );
+ expect(screen.getByText("leftover map comparison axis 1 (0%)")).toBeInTheDocument();
+ });
+
+ it("names leftover expected on the comparison graphic with a distinct accessible name", () => {
+ render(
+ ,
+ );
+ expect(
+ screen.getAllByLabelText("leftover map comparison graphic leftover expected E 2.00"),
+ ).toHaveLength(2);
+ expect(screen.queryByLabelText("leftover expected E 2.00")).not.toBeInTheDocument();
+ expect(screen.queryByLabelText("Leftover map comparison expected")).not.toBeInTheDocument();
+ expect(
+ screen.getByLabelText("leftover map comparison graphic leftover observed Y 2.40"),
+ ).toHaveTextContent("Y 2.40");
+ expect(
+ screen.getByLabelText("leftover map comparison graphic leftover residual R +0.40"),
+ ).toHaveTextContent("R +0.40");
+ expect(screen.getByText("leftover map comparison axis 1 (82%)")).toBeInTheDocument();
+ });
+
+ it("omits leftover-map comparison graphic leftover expected when E is missing or not usable", () => {
+ render(
+ ,
+ );
+ expect(screen.queryByLabelText(/leftover map comparison graphic leftover expected E/)).not.toBeInTheDocument();
+ expect(screen.queryByLabelText(/^leftover expected E/)).not.toBeInTheDocument();
+ expect(
+ screen.getByLabelText("leftover map comparison graphic leftover observed Y 2.40"),
+ ).toHaveTextContent("Y 2.40");
+ expect(
+ screen.getByLabelText("leftover map comparison graphic leftover residual R +0.40"),
+ ).toHaveTextContent("R +0.40");
+ expect(screen.getByLabelText("leftover-map distance d 0.12")).toBeInTheDocument();
+ expect(screen.getByText("leftover map comparison axis 1 (82%)")).toBeInTheDocument();
+ });
+
+ it("names rank-0 origin leftover expected on the comparison graphic when that persisted value is finite", () => {
+ render(
+ ,
+ );
+ expect(
+ screen.getByLabelText("leftover map comparison graphic leftover expected E 0.00"),
+ ).toHaveTextContent("E 0.00");
+ expect(screen.queryByLabelText("leftover expected E 0.00")).not.toBeInTheDocument();
+ expect(
+ screen.getByLabelText("leftover map comparison graphic leftover observed Y 0.00"),
+ ).toHaveTextContent("Y 0.00");
+ expect(
+ screen.getByLabelText("leftover map comparison graphic leftover residual R 0.00"),
+ ).toHaveTextContent("R 0.00");
+ expect(screen.getByText("leftover map comparison axis 1 (0%)")).toBeInTheDocument();
+ });
+
+ it("names leftover-map rank on the comparison graphic with a distinct accessible name", () => {
+ render(
+ ,
+ );
+ expect(
+ screen.getAllByLabelText("leftover map comparison graphic leftover-map rank rank 1"),
+ ).toHaveLength(2);
+ expect(screen.queryByLabelText("leftover-map rank rank 1")).not.toBeInTheDocument();
+ expect(screen.queryByLabelText("Leftover map comparison rank")).not.toBeInTheDocument();
+ expect(
+ screen.getAllByLabelText("leftover map comparison graphic leftover expected E 2.00"),
+ ).toHaveLength(2);
+ expect(
+ screen.getByLabelText("leftover map comparison graphic leftover observed Y 2.40"),
+ ).toHaveTextContent("Y 2.40");
+ expect(
+ screen.getByLabelText("leftover map comparison graphic leftover residual R +0.40"),
+ ).toHaveTextContent("R +0.40");
+ expect(screen.getByText("leftover map comparison axis 1 (82%)")).toBeInTheDocument();
+ });
+
+ it("omits leftover-map comparison graphic leftover-map rank when rank is missing or not usable", () => {
+ render(
+ ,
+ );
+ expect(screen.queryByLabelText(/leftover map comparison graphic leftover-map rank/)).not.toBeInTheDocument();
+ expect(screen.queryByLabelText(/^leftover-map rank/)).not.toBeInTheDocument();
+ expect(
+ screen.getAllByLabelText("leftover map comparison graphic leftover expected E 2.00"),
+ ).toHaveLength(2);
+ expect(
+ screen.getByLabelText("leftover map comparison graphic leftover observed Y 2.40"),
+ ).toHaveTextContent("Y 2.40");
+ expect(
+ screen.getByLabelText("leftover map comparison graphic leftover residual R +0.40"),
+ ).toHaveTextContent("R +0.40");
+ expect(screen.getByLabelText("leftover-map distance d 0.12")).toBeInTheDocument();
+ expect(screen.getByText("leftover map comparison axis 1 (82%)")).toBeInTheDocument();
+ });
+
+ it("names rank-0 origin leftover-map rank on the comparison graphic when that persisted value is a non-negative integer", () => {
+ render(
+ ,
+ );
+ expect(
+ screen.getByLabelText("leftover map comparison graphic leftover-map rank rank 0"),
+ ).toHaveTextContent("rank 0");
+ expect(screen.queryByLabelText("leftover-map rank rank 0")).not.toBeInTheDocument();
+ expect(
+ screen.getByLabelText("leftover map comparison graphic leftover expected E 0.00"),
+ ).toHaveTextContent("E 0.00");
+ expect(
+ screen.getByLabelText("leftover map comparison graphic leftover observed Y 0.00"),
+ ).toHaveTextContent("Y 0.00");
+ expect(
+ screen.getByLabelText("leftover map comparison graphic leftover residual R 0.00"),
+ ).toHaveTextContent("R 0.00");
+ expect(screen.getByText("leftover map comparison axis 1 (0%)")).toBeInTheDocument();
+ });
});
diff --git a/frontend/src/components/LeftoverMapPlot.tsx b/frontend/src/components/LeftoverMapPlot.tsx
index d6f26adb8..a2ee23e3f 100644
--- a/frontend/src/components/LeftoverMapPlot.tsx
+++ b/frontend/src/components/LeftoverMapPlot.tsx
@@ -39,6 +39,9 @@ import {
LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_CROSS_SHARE,
LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_UNEXPLAINED,
LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_RESIDUAL,
+ LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_OBSERVED,
+ LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_EXPECTED,
+ LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_RANK,
LEFTOVER_MAP_PLOT_CAPTION,
LEFTOVER_MAP_PLOT_POST_ACTION,
LEFTOVER_MAP_PLOT_SEGMENT_CROSS_SHARE,
@@ -161,6 +164,15 @@ function leftoverMapPlotAxisText(
* labels. ADR 0315 captions leftover residual on that
* comparison graphic from already-named leftover residual
* with distinct leftover map comparison graphic leftover residual
+ * labels. ADR 0316 captions leftover observed on that
+ * comparison graphic from already-named leftover observed
+ * with distinct leftover map comparison graphic leftover observed
+ * labels. ADR 0317 captions leftover expected on that
+ * comparison graphic from already-named leftover expected
+ * with distinct leftover map comparison graphic leftover expected
+ * labels. ADR 0318 captions leftover-map rank on that
+ * comparison graphic from already-named leftover-map rank
+ * with distinct leftover map comparison graphic leftover-map rank
* labels.
* Never invent a leftover score.
*/
@@ -426,9 +438,12 @@ export function LeftoverMapPlot({
x={segment.observedX}
y={segment.observedY}
textAnchor="middle"
- aria-label={tf(LEFTOVER_MAP_PLOT_SEGMENT_OBSERVED, {
- label: segment.observedLabel,
- })}
+ aria-label={tf(
+ variant === "comparison"
+ ? LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_OBSERVED
+ : LEFTOVER_MAP_PLOT_SEGMENT_OBSERVED,
+ { label: segment.observedLabel },
+ )}
>
{segment.observedLabel}
@@ -439,9 +454,12 @@ export function LeftoverMapPlot({
x={segment.expectedX}
y={segment.expectedY}
textAnchor="middle"
- aria-label={tf(LEFTOVER_MAP_PLOT_SEGMENT_EXPECTED, {
- label: segment.expectedLabel,
- })}
+ aria-label={tf(
+ variant === "comparison"
+ ? LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_EXPECTED
+ : LEFTOVER_MAP_PLOT_SEGMENT_EXPECTED,
+ { label: segment.expectedLabel },
+ )}
>
{segment.expectedLabel}
@@ -452,9 +470,12 @@ export function LeftoverMapPlot({
x={segment.rankX}
y={segment.rankY}
textAnchor="middle"
- aria-label={tf(LEFTOVER_MAP_PLOT_SEGMENT_RANK, {
- label: segment.rankLabel,
- })}
+ aria-label={tf(
+ variant === "comparison"
+ ? LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_RANK
+ : LEFTOVER_MAP_PLOT_SEGMENT_RANK,
+ { label: segment.rankLabel },
+ )}
>
{segment.rankLabel}
diff --git a/frontend/src/components/LeftoverPairList.tsx b/frontend/src/components/LeftoverPairList.tsx
index f0e60a47c..9ec439bff 100644
--- a/frontend/src/components/LeftoverPairList.tsx
+++ b/frontend/src/components/LeftoverPairList.tsx
@@ -124,7 +124,11 @@ export type LeftoverPairListProps = {
* pair list. ADR 0314 captions leftover-map unexplained leftover on that
* grouping comparison leftover-map graphic, not this pair list. ADR 0315
* captions leftover residual on that grouping comparison leftover-map graphic,
- * not this pair list. Every badge still
+ * not this pair list. ADR 0316 captions leftover observed on that grouping
+ * comparison leftover-map graphic, not this pair list. ADR 0317 captions leftover
+ * expected on that grouping comparison leftover-map graphic, not this pair list. ADR 0318
+ * captions leftover-map rank on that grouping comparison leftover-map graphic, not this
+ * pair list. Every badge still
* renders together before opening the named post.
*/
export function LeftoverPairList({
diff --git a/frontend/src/i18n.test.ts b/frontend/src/i18n.test.ts
index 09d6d6115..19c2964d9 100644
--- a/frontend/src/i18n.test.ts
+++ b/frontend/src/i18n.test.ts
@@ -97,8 +97,11 @@ describe("i18n", () => {
"Leftover map comparison unexplained leftover",
"leftover map comparison graphic leftover residual {label}",
"Leftover map comparison residual",
+ "leftover map comparison graphic leftover observed {label}",
"Leftover map comparison observed",
+ "leftover map comparison graphic leftover expected {label}",
"Leftover map comparison expected",
+ "leftover map comparison graphic leftover-map rank {label}",
"Leftover map comparison rank",
"Leftover map comparison coordinates",
"Leftover map comparison graphic",
@@ -597,6 +600,57 @@ describe("i18n", () => {
},
);
+ it.each([
+ ["ko", "잔여 지도 비교 그림 관측 Y 2.40"],
+ ["zh", "残差地图比较图形观测 Y 2.40"],
+ ["ja", "残差マップの比較図観測 Y 2.40"],
+ ["vi", "quan sát đồ họa so sánh bản đồ phần dư Y 2.40"],
+ ] as const)(
+ "formats leftover map comparison graphic leftover observed in %s",
+ (locale, expected) => {
+ setLocale(locale);
+ expect(
+ tf("leftover map comparison graphic leftover observed {label}", {
+ label: "Y 2.40",
+ }),
+ ).toBe(expected);
+ },
+ );
+
+ it.each([
+ ["ko", "잔여 지도 비교 그림 기대 E 2.00"],
+ ["zh", "残差地图比较图形期望 E 2.00"],
+ ["ja", "残差マップの比較図期待 E 2.00"],
+ ["vi", "kỳ vọng đồ họa so sánh bản đồ phần dư E 2.00"],
+ ] as const)(
+ "formats leftover map comparison graphic leftover expected in %s",
+ (locale, expected) => {
+ setLocale(locale);
+ expect(
+ tf("leftover map comparison graphic leftover expected {label}", {
+ label: "E 2.00",
+ }),
+ ).toBe(expected);
+ },
+ );
+
+ it.each([
+ ["ko", "잔여 지도 비교 그림 순위 rank 1"],
+ ["zh", "残差地图比较图形秩 rank 1"],
+ ["ja", "残差マップの比較図階数 rank 1"],
+ ["vi", "hạng đồ họa so sánh bản đồ phần dư rank 1"],
+ ] as const)(
+ "formats leftover map comparison graphic leftover-map rank in %s",
+ (locale, expected) => {
+ setLocale(locale);
+ expect(
+ tf("leftover map comparison graphic leftover-map rank {label}", {
+ label: "rank 1",
+ }),
+ ).toBe(expected);
+ },
+ );
+
it.each([
["ko", "잔여 지도 비교 설명 잔여 점유율"],
["zh", "残差地图比较已解释残差份额"],
diff --git a/frontend/src/i18n.ts b/frontend/src/i18n.ts
index 7452be173..1c7b9525d 100644
--- a/frontend/src/i18n.ts
+++ b/frontend/src/i18n.ts
@@ -289,8 +289,11 @@ const TRANSLATIONS: Partial>> = {
"Leftover map comparison unexplained leftover": "잔여 지도 비교 미설명 잔여",
"leftover map comparison graphic leftover residual {label}": "잔여 지도 비교 그림 잔여 {label}",
"Leftover map comparison residual": "잔여 지도 비교 잔여",
+ "leftover map comparison graphic leftover observed {label}": "잔여 지도 비교 그림 관측 {label}",
"Leftover map comparison observed": "잔여 지도 비교 관측",
+ "leftover map comparison graphic leftover expected {label}": "잔여 지도 비교 그림 기대 {label}",
"Leftover map comparison expected": "잔여 지도 비교 기대",
+ "leftover map comparison graphic leftover-map rank {label}": "잔여 지도 비교 그림 순위 {label}",
"Leftover map comparison rank": "잔여 지도 비교 순위",
"Leftover map comparison coordinates": "잔여 지도 비교 좌표",
"Leftover map comparison graphic": "잔여 지도 비교 그림",
@@ -927,8 +930,11 @@ const TRANSLATIONS: Partial>> = {
"Leftover map comparison unexplained leftover": "残差地图比较未解释残差",
"leftover map comparison graphic leftover residual {label}": "残差地图比较图形残差 {label}",
"Leftover map comparison residual": "残差地图比较残差",
+ "leftover map comparison graphic leftover observed {label}": "残差地图比较图形观测 {label}",
"Leftover map comparison observed": "残差地图比较观测",
+ "leftover map comparison graphic leftover expected {label}": "残差地图比较图形期望 {label}",
"Leftover map comparison expected": "残差地图比较期望",
+ "leftover map comparison graphic leftover-map rank {label}": "残差地图比较图形秩 {label}",
"Leftover map comparison rank": "残差地图比较秩",
"Leftover map comparison coordinates": "残差地图比较坐标",
"Leftover map comparison graphic": "残差地图比较图形",
@@ -1586,8 +1592,11 @@ const TRANSLATIONS: Partial>> = {
"Leftover map comparison unexplained leftover": "残差マップの比較未説明残差",
"leftover map comparison graphic leftover residual {label}": "残差マップの比較図残差 {label}",
"Leftover map comparison residual": "残差マップの比較残差",
+ "leftover map comparison graphic leftover observed {label}": "残差マップの比較図観測 {label}",
"Leftover map comparison observed": "残差マップの比較観測",
+ "leftover map comparison graphic leftover expected {label}": "残差マップの比較図期待 {label}",
"Leftover map comparison expected": "残差マップの比較期待",
+ "leftover map comparison graphic leftover-map rank {label}": "残差マップの比較図階数 {label}",
"Leftover map comparison rank": "残差マップの比較階数",
"Leftover map comparison coordinates": "残差マップの比較座標",
"Leftover map comparison graphic": "残差マップの比較図",
@@ -2224,8 +2233,11 @@ const TRANSLATIONS: Partial>> = {
"Leftover map comparison unexplained leftover": "Phần dư chưa giải thích so sánh",
"leftover map comparison graphic leftover residual {label}": "phần dư đồ họa so sánh bản đồ phần dư {label}",
"Leftover map comparison residual": "Phần dư so sánh bản đồ phần dư",
+ "leftover map comparison graphic leftover observed {label}": "quan sát đồ họa so sánh bản đồ phần dư {label}",
"Leftover map comparison observed": "Quan sát so sánh bản đồ phần dư",
+ "leftover map comparison graphic leftover expected {label}": "kỳ vọng đồ họa so sánh bản đồ phần dư {label}",
"Leftover map comparison expected": "Kỳ vọng so sánh bản đồ phần dư",
+ "leftover map comparison graphic leftover-map rank {label}": "hạng đồ họa so sánh bản đồ phần dư {label}",
"Leftover map comparison rank": "Hạng so sánh bản đồ phần dư",
"Leftover map comparison coordinates": "Tọa độ so sánh bản đồ phần dư",
"Leftover map comparison graphic": "Đồ họa so sánh bản đồ phần dư",
diff --git a/frontend/src/leftoverMapPlotLayout.test.ts b/frontend/src/leftoverMapPlotLayout.test.ts
index 44a55a220..958adc229 100644
--- a/frontend/src/leftoverMapPlotLayout.test.ts
+++ b/frontend/src/leftoverMapPlotLayout.test.ts
@@ -13,6 +13,9 @@ import {
LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_CROSS_SHARE,
LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_UNEXPLAINED,
LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_RESIDUAL,
+ LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_OBSERVED,
+ LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_EXPECTED,
+ LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_RANK,
LEFTOVER_MAP_COMPARE_PLOT_SVG,
PLOT_HEIGHT,
PLOT_PADDING,
@@ -1288,4 +1291,49 @@ describe("leftover map comparison graphic labels", () => {
LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_UNEXPLAINED,
);
});
+
+ it("stays distinct from leftover observed copy", () => {
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_OBSERVED).toBe(
+ "leftover map comparison graphic leftover observed {label}",
+ );
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_OBSERVED).not.toBe(
+ "leftover observed {label}",
+ );
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_OBSERVED).not.toBe(
+ "Leftover map comparison observed",
+ );
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_OBSERVED).not.toBe(
+ LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_RESIDUAL,
+ );
+ });
+
+ it("stays distinct from leftover expected copy", () => {
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_EXPECTED).toBe(
+ "leftover map comparison graphic leftover expected {label}",
+ );
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_EXPECTED).not.toBe(
+ "leftover expected {label}",
+ );
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_EXPECTED).not.toBe(
+ "Leftover map comparison expected",
+ );
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_EXPECTED).not.toBe(
+ LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_OBSERVED,
+ );
+ });
+
+ it("stays distinct from leftover-map rank copy", () => {
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_RANK).toBe(
+ "leftover map comparison graphic leftover-map rank {label}",
+ );
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_RANK).not.toBe(
+ "leftover-map rank {label}",
+ );
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_RANK).not.toBe(
+ "Leftover map comparison rank",
+ );
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_RANK).not.toBe(
+ LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_EXPECTED,
+ );
+ });
});
diff --git a/frontend/src/leftoverMapPlotLayout.ts b/frontend/src/leftoverMapPlotLayout.ts
index 77728d5ca..1bcafbc94 100644
--- a/frontend/src/leftoverMapPlotLayout.ts
+++ b/frontend/src/leftoverMapPlotLayout.ts
@@ -43,7 +43,10 @@
* unexplained leftover share on that graphic (ADR 0312), grouping comparison leftover-map
* cross share on that graphic (ADR 0313), and grouping comparison leftover-map
* unexplained leftover on that graphic (ADR 0314), and grouping comparison leftover
- * residual on that graphic (ADR 0315) caption the pair list or the grouping comparison
+ * residual on that graphic (ADR 0315), and grouping comparison leftover
+ * observed on that graphic (ADR 0316), and grouping comparison leftover
+ * expected on that graphic (ADR 0317), and grouping comparison leftover-map
+ * rank on that graphic (ADR 0318) 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. ADR 0306 captions leftover-map
@@ -63,6 +66,12 @@
* comparison graphic from already-named leftover-map unexplained leftover.
* ADR 0315 captions leftover residual on that comparison graphic from
* already-named leftover residual.
+ * ADR 0316 captions leftover observed on that comparison graphic from
+ * already-named leftover observed.
+ * ADR 0317 captions leftover expected on that comparison graphic from
+ * already-named leftover expected.
+ * ADR 0318 captions leftover-map rank on that comparison graphic from
+ * already-named leftover-map rank.
*/
import { formatLeftoverMapCoordinatePair } from "./leftoverMapCoordinates";
@@ -131,12 +140,18 @@ export { LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_RESIDUAL } from "./leftoverResidual";
export const LEFTOVER_MAP_PLOT_SEGMENT_OBSERVED =
"leftover observed {label}";
+export { LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_OBSERVED } from "./leftoverObservedExpected";
+
export const LEFTOVER_MAP_PLOT_SEGMENT_EXPECTED =
"leftover expected {label}";
+export { LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_EXPECTED } from "./leftoverObservedExpected";
+
export const LEFTOVER_MAP_PLOT_SEGMENT_RANK =
"leftover-map rank {label}";
+export { LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_RANK } from "./leftoverMapRank";
+
export const PLOT_WIDTH = 480;
export const PLOT_HEIGHT = 320;
export const PLOT_PADDING = 40;
diff --git a/frontend/src/leftoverMapRank.test.ts b/frontend/src/leftoverMapRank.test.ts
index 334d24c60..3338e8090 100644
--- a/frontend/src/leftoverMapRank.test.ts
+++ b/frontend/src/leftoverMapRank.test.ts
@@ -1,5 +1,9 @@
import { describe, expect, it } from "vitest";
-import { formatLeftoverMapRank, LEFTOVER_MAP_COMPARE_RANK_LABEL } from "./leftoverMapRank";
+import {
+ formatLeftoverMapRank,
+ LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_RANK,
+ LEFTOVER_MAP_COMPARE_RANK_LABEL,
+} from "./leftoverMapRank";
describe("formatLeftoverMapRank", () => {
it("names leftover-map rank without inventing leftover structure", () => {
@@ -20,4 +24,17 @@ describe("formatLeftoverMapRank", () => {
expect(LEFTOVER_MAP_COMPARE_RANK_LABEL).toBe("Leftover map comparison rank");
expect(LEFTOVER_MAP_COMPARE_RANK_LABEL).not.toBe("leftover-map rank {label}");
});
+
+ it("keeps the grouping comparison graphic leftover-map rank label distinct from the graphic and strip labels", () => {
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_RANK).toBe(
+ "leftover map comparison graphic leftover-map rank {label}",
+ );
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_RANK).not.toBe("leftover-map rank {label}");
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_RANK).not.toBe(
+ LEFTOVER_MAP_COMPARE_RANK_LABEL,
+ );
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_RANK).not.toBe(
+ "leftover map comparison graphic leftover expected {label}",
+ );
+ });
});
diff --git a/frontend/src/leftoverMapRank.ts b/frontend/src/leftoverMapRank.ts
index d2b706167..3fce5258a 100644
--- a/frontend/src/leftoverMapRank.ts
+++ b/frontend/src/leftoverMapRank.ts
@@ -7,6 +7,9 @@ export const LEFTOVER_RANK_STRUCTURE_ACTION =
export const LEFTOVER_MAP_COMPARE_RANK_LABEL = "Leftover map comparison rank";
+export const LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_RANK =
+ "leftover map comparison graphic leftover-map rank {label}";
+
export function formatLeftoverMapRank(rank: number | null | undefined): string | null {
if (rank == null || !Number.isInteger(rank) || rank < 0) {
return null;
diff --git a/frontend/src/leftoverObservedExpected.test.ts b/frontend/src/leftoverObservedExpected.test.ts
index 561a599b4..f58e0a6d8 100644
--- a/frontend/src/leftoverObservedExpected.test.ts
+++ b/frontend/src/leftoverObservedExpected.test.ts
@@ -5,6 +5,8 @@ import {
formatLeftoverObservedExpected,
LEFTOVER_MAP_COMPARE_OBSERVED_LABEL,
LEFTOVER_MAP_COMPARE_EXPECTED_LABEL,
+ LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_OBSERVED,
+ LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_EXPECTED,
} from "./leftoverObservedExpected";
describe("formatLeftoverObservedExpected", () => {
@@ -41,6 +43,19 @@ describe("formatLeftoverMapObserved", () => {
expect(LEFTOVER_MAP_COMPARE_OBSERVED_LABEL).toBe("Leftover map comparison observed");
expect(LEFTOVER_MAP_COMPARE_OBSERVED_LABEL).not.toBe("leftover observed {label}");
});
+
+ it("keeps the grouping comparison graphic leftover observed label distinct from the graphic and strip labels", () => {
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_OBSERVED).toBe(
+ "leftover map comparison graphic leftover observed {label}",
+ );
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_OBSERVED).not.toBe("leftover observed {label}");
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_OBSERVED).not.toBe(
+ LEFTOVER_MAP_COMPARE_OBSERVED_LABEL,
+ );
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_OBSERVED).not.toBe(
+ "leftover map comparison graphic leftover residual {label}",
+ );
+ });
});
describe("formatLeftoverMapExpected", () => {
@@ -62,4 +77,17 @@ describe("formatLeftoverMapExpected", () => {
expect(LEFTOVER_MAP_COMPARE_EXPECTED_LABEL).toBe("Leftover map comparison expected");
expect(LEFTOVER_MAP_COMPARE_EXPECTED_LABEL).not.toBe("leftover expected {label}");
});
+
+ it("keeps the grouping comparison graphic leftover expected label distinct from the graphic and strip labels", () => {
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_EXPECTED).toBe(
+ "leftover map comparison graphic leftover expected {label}",
+ );
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_EXPECTED).not.toBe("leftover expected {label}");
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_EXPECTED).not.toBe(
+ LEFTOVER_MAP_COMPARE_EXPECTED_LABEL,
+ );
+ expect(LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_EXPECTED).not.toBe(
+ LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_OBSERVED,
+ );
+ });
});
diff --git a/frontend/src/leftoverObservedExpected.ts b/frontend/src/leftoverObservedExpected.ts
index a647dae15..d9751978a 100644
--- a/frontend/src/leftoverObservedExpected.ts
+++ b/frontend/src/leftoverObservedExpected.ts
@@ -6,6 +6,12 @@ export const LEFTOVER_MAP_COMPARE_OBSERVED_LABEL =
export const LEFTOVER_MAP_COMPARE_EXPECTED_LABEL =
"Leftover map comparison expected";
+export const LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_OBSERVED =
+ "leftover map comparison graphic leftover observed {label}";
+
+export const LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_EXPECTED =
+ "leftover map comparison graphic leftover expected {label}";
+
export function formatLeftoverObservedExpected(
observed: number | null | undefined,
expected: number | null | undefined,
diff --git a/pyproject.toml b/pyproject.toml
index f0016537b..9d6139217 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "lineageweave"
-version = "2.72.0"
+version = "2.75.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 e04d99617..39b7853f1 100644
--- a/uv.lock
+++ b/uv.lock
@@ -685,7 +685,7 @@ wheels = [
[[package]]
name = "lineageweave"
-version = "2.72.0"
+version = "2.75.0"
source = { editable = "." }
dependencies = [
{ name = "certifi" },