diff --git a/AGENTS.md b/AGENTS.md
index cea602044..bcd435292 100644
--- a/AGENTS.md
+++ b/AGENTS.md
@@ -755,6 +755,15 @@ item coordinate caption and keeps `Criterion ζ {label}`. Rank-0 unused axes sti
item coordinates `(0.00, 0.00)`. Do not invent leftover-map item coordinates from leftover-map post
`ξ`. Do not invent leftover-map post `ξ` from leftover-map item coordinates. Leftover-map comparison graphic leftover-map
criterion markers never name leftover-map item coordinates this increment.
+ADR 0336 captions leftover-map comparison graphic leftover-map criterion markers with persisted leftover-map
+item coordinates when leftoverMapComparePlotCriterionBadge returns a usable leftover-map comparison graphic leftover-map criterion leftover-map
+item coordinate caption. Distinct accessible name
+`leftover map comparison graphic leftover-map criterion {label} at ζ {item}`.
+A missing or non-finite leftover-map item coordinate pair omits that leftover-map comparison graphic leftover-map criterion leftover-map
+item coordinate caption and keeps `Criterion ζ {label}`. Rank-0 unused axes still name leftover-map
+item coordinates `(0.00, 0.00)`. Do not invent leftover-map item coordinates from leftover-map post
+`ξ`. Do not invent leftover-map post `ξ` from leftover-map item coordinates. Leftover-map graphic leftover-map
+criterion markers stay `leftover-map criterion {label} at ζ {item}` this increment.
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
@@ -900,6 +909,10 @@ Leftover-map graphic leftover-map criterion leftover-map item coordinates indepe
(ADR 0335) captions leftover-map graphic leftover-map criterion markers with persisted leftover-map
item coordinates when leftoverMapPlotCriterionBadge returns a usable leftover-map criterion leftover-map
item coordinate caption.
+Leftover-map comparison graphic leftover-map criterion leftover-map item coordinates independently of leftover-map post ξ markers
+(ADR 0336) captions leftover-map comparison graphic leftover-map criterion markers with persisted leftover-map
+item coordinates when leftoverMapComparePlotCriterionBadge returns a usable leftover-map comparison graphic leftover-map criterion leftover-map
+item coordinate caption.
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 40ac65f0a..8d2f0ff80 100644
--- a/ARCHITECTURE.md
+++ b/ARCHITECTURE.md
@@ -788,6 +788,9 @@ axis share caption independently of leftover-map singular values.
ADR 0335 captions leftover-map graphic leftover-map criterion markers with persisted leftover-map
item coordinates when leftoverMapPlotCriterionBadge returns a usable leftover-map criterion leftover-map
item coordinate caption independently of leftover-map post ξ markers.
+ADR 0336 captions leftover-map comparison graphic leftover-map criterion markers with persisted leftover-map
+item coordinates when leftoverMapComparePlotCriterionBadge returns a usable leftover-map comparison graphic leftover-map criterion leftover-map
+item coordinate caption independently of leftover-map post ξ markers.
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
@@ -853,7 +856,8 @@ comparison graphic leftover-map axis leftover-map singular values as leftoverMap
(ADR 0332), leftover-map comparison leftover-axis tick leftover-map axis share independently of leftover-map singular values
(ADR 0333), leftover-axis tick leftover-map axis share independently of leftover-map singular values
(ADR 0334), leftover-map graphic leftover-map criterion leftover-map item coordinates independently of leftover-map post ξ markers
-(ADR 0335);
+(ADR 0335), leftover-map comparison graphic leftover-map criterion leftover-map item coordinates independently of leftover-map post ξ markers
+(ADR 0336);
`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.93.0-leftover-map-compare-plot-criterion-coordinates.md b/CHANGELOG.d/2.93.0-leftover-map-compare-plot-criterion-coordinates.md
new file mode 100644
index 000000000..53ae59744
--- /dev/null
+++ b/CHANGELOG.d/2.93.0-leftover-map-compare-plot-criterion-coordinates.md
@@ -0,0 +1,22 @@
+## 2.93.0 — Leftover-map item coordinates on leftover-map comparison graphic leftover-map criterion markers independently of leftover-map post ξ markers
+
+- Caption leftover-map comparison graphic leftover-map criterion markers with persisted leftover-map
+ item coordinates through leftoverMapComparePlotCriterionBadge independently of leftover-map
+ post ξ markers (ADR 0336). After `make seed`, leftover-map comparison graphic leftover-map
+ criterion markers name persisted leftover-map item coordinates when leftoverMapComparePlotCriterionBadge
+ returns a usable leftover-map comparison graphic leftover-map criterion leftover-map item coordinate caption; click a leftover pair
+ or a leftover-map post marker opens that post. A missing or
+ non-finite leftover-map item coordinate pair omits that leftover-map comparison graphic leftover-map criterion leftover-map
+ item coordinate caption and keeps `Criterion ζ {label}`. Rank-0 unused
+ axes still name leftover-map item coordinates `(0.00, 0.00)`. Leftover-map comparison graphic leftover-map
+ criterion markers stay
+ `leftover map comparison graphic leftover-map criterion {label} at ζ {item}`
+ when leftover-map item coordinates are finite so they stay distinct from leftover-map graphic leftover-map criterion markers
+ `leftover-map criterion {label} at ζ {item}` and from leftover-map post markers
+ `Open leftover-map post {title} at ξ {person}`. Do not invent leftover-map
+ item coordinates from leftover-map post `ξ`. Do not invent leftover-map post `ξ` from leftover-map
+ item coordinates. This increment does not change leftover-map graphic leftover-map
+ criterion markers, leftover-axis ticks, leftover-map graphic leftover-map axis ticks,
+ leftover-map comparison leftover-axis ticks, or leftover-map comparison graphic leftover-map axis ticks.
+ A finite negative leftover is shown, never clamped. Never invent a leftover score.
+ Never invent a theta. No new columns.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 9cc7fe51b..b4f473e3c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -8,6 +8,27 @@ All notable changes to this project are documented here. Format follows
### Added
+- Period leftover pairs now caption leftover-map comparison graphic leftover-map
+ criterion markers with persisted leftover-map item coordinates through leftoverMapComparePlotCriterionBadge
+ independently of leftover-map post ξ markers (ADR 0336 / v2.93.0). After `make seed`,
+ leftover-map comparison graphic leftover-map criterion markers name persisted leftover-map
+ item coordinates when leftoverMapComparePlotCriterionBadge returns a usable leftover-map comparison graphic leftover-map criterion
+ leftover-map item coordinate caption; click a leftover pair or a leftover-map post marker
+ opens that post. A missing or non-finite leftover-map item coordinate pair omits that leftover-map
+ comparison graphic leftover-map criterion leftover-map item coordinate caption and keeps
+ `Criterion ζ {label}`.
+ Rank-0 unused axes still name leftover-map item coordinates `(0.00, 0.00)`. Leftover-map comparison graphic leftover-map
+ criterion markers stay
+ `leftover map comparison graphic leftover-map criterion {label} at ζ {item}`
+ when leftover-map item coordinates are finite so they stay distinct from leftover-map graphic leftover-map criterion markers
+ `leftover-map criterion {label} at ζ {item}` and from leftover-map post markers
+ `Open leftover-map post {title} at ξ {person}`. Do not invent leftover-map
+ item coordinates from leftover-map post `ξ`. Do not invent leftover-map post `ξ` from leftover-map
+ item coordinates. This increment does not change leftover-map graphic leftover-map
+ criterion markers, leftover-axis ticks, leftover-map graphic leftover-map axis ticks,
+ leftover-map comparison leftover-axis ticks, or leftover-map comparison graphic leftover-map axis ticks. A finite negative leftover
+ is shown, never clamped. Never invent a leftover score or a theta. No new columns.
+
- Period leftover pairs now caption leftover-map graphic leftover-map
criterion markers with persisted leftover-map item coordinates through leftoverMapPlotCriterionBadge
independently of leftover-map post ξ markers (ADR 0335 / v2.92.0). After `make seed`,
diff --git a/CLAUDE.md b/CLAUDE.md
index 399d7ef1f..28204800e 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 / 0316 / 0317 / 0318 / 0319 / 0320 / 0321 / 0322 / 0323 / 0324 / 0325 / 0326 / 0327 / 0328 / 0329 / 0330 / 0331 / 0332 / 0333 / 0334 / 0335), 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 / 0319 / 0320 / 0321 / 0322 / 0323 / 0324 / 0325 / 0326 / 0327 / 0328 / 0329 / 0330 / 0331 / 0332 / 0333 / 0334 / 0335 / 0336), 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/0267-leftover-map-coordinates.md b/docs/adr/0267-leftover-map-coordinates.md
index 8fd8ade16..31da6fb7b 100644
--- a/docs/adr/0267-leftover-map-coordinates.md
+++ b/docs/adr/0267-leftover-map-coordinates.md
@@ -8,7 +8,9 @@
[ADR 0270](0270-leftover-map-coordinate-ticks.md)
(leftover-map coordinate ticks);
[ADR 0335](0335-leftover-map-plot-criterion-coordinates.md)
-(leftover-map item coordinates on leftover-map graphic leftover-map criterion markers)
+(leftover-map item coordinates on leftover-map graphic leftover-map criterion markers);
+[ADR 0336](0336-leftover-map-compare-plot-criterion-coordinates.md)
+(leftover-map item coordinates on leftover-map comparison graphic leftover-map criterion markers)
Amends [ADR 0048](0048-persist-lsirm-leftover-pairs.md),
[ADR 0049](0049-leftover-pair-report-ui.md), and
diff --git a/docs/adr/0268-leftover-map-graphic-display.md b/docs/adr/0268-leftover-map-graphic-display.md
index 373a44d29..2cdc0cf78 100644
--- a/docs/adr/0268-leftover-map-graphic-display.md
+++ b/docs/adr/0268-leftover-map-graphic-display.md
@@ -30,7 +30,9 @@
[ADR 0304](0304-leftover-map-compare-graphic.md)
(leftover-map graphic display on the grouping comparison strip);
[ADR 0335](0335-leftover-map-plot-criterion-coordinates.md)
-(leftover-map item coordinates on leftover-map graphic leftover-map criterion markers)
+(leftover-map item coordinates on leftover-map graphic leftover-map criterion markers);
+[ADR 0336](0336-leftover-map-compare-plot-criterion-coordinates.md)
+(leftover-map item coordinates on leftover-map comparison graphic leftover-map criterion markers)
Amends [ADR 0049](0049-leftover-pair-report-ui.md) and
[ADR 0267](0267-leftover-map-coordinates.md). Independent of leftover-map
diff --git a/docs/adr/0304-leftover-map-compare-graphic.md b/docs/adr/0304-leftover-map-compare-graphic.md
index 48a3b13cd..1396227fb 100644
--- a/docs/adr/0304-leftover-map-compare-graphic.md
+++ b/docs/adr/0304-leftover-map-compare-graphic.md
@@ -12,7 +12,9 @@
[ADR 0308](0308-leftover-map-compare-plot-incomplete-post.md)
(leftover-map incomplete post coverage on the grouping comparison leftover-map graphic),
[ADR 0309](0309-leftover-map-compare-plot-incomplete-item.md)
-(leftover-map incomplete item coverage on the grouping comparison leftover-map graphic)
+(leftover-map incomplete item coverage on the grouping comparison leftover-map graphic),
+[ADR 0336](0336-leftover-map-compare-plot-criterion-coordinates.md)
+(leftover-map item coordinates on leftover-map comparison graphic leftover-map criterion markers)
Amends leftover pairs on the grouping comparison strip
([ADR 0149](0149-leftover-pairs-on-comparison-strip.md)), leftover-map
diff --git a/docs/adr/0334-leftover-map-axis-tick-share-badge.md b/docs/adr/0334-leftover-map-axis-tick-share-badge.md
index b69431754..1eeffb5fb 100644
--- a/docs/adr/0334-leftover-map-axis-tick-share-badge.md
+++ b/docs/adr/0334-leftover-map-axis-tick-share-badge.md
@@ -119,7 +119,9 @@ singular values on leftover-axis report badges independently of leftover-map axi
([ADR 0325](0325-leftover-map-axis-singular-only.md)). Independent of leftover-map
axis share persistence ([ADR 0148](0148-leftover-map-axis-share.md)). Independent of leftover-map
graphic leftover-map criterion leftover-map item coordinates independently of leftover-map post ξ markers
-([ADR 0335](0335-leftover-map-plot-criterion-coordinates.md)).
+([ADR 0335](0335-leftover-map-plot-criterion-coordinates.md)). Independent of leftover-map
+comparison graphic leftover-map criterion leftover-map item coordinates independently of leftover-map post ξ markers
+([ADR 0336](0336-leftover-map-compare-plot-criterion-coordinates.md)).
## References
diff --git a/docs/adr/0335-leftover-map-plot-criterion-coordinates.md b/docs/adr/0335-leftover-map-plot-criterion-coordinates.md
index 547d6b5c8..61398dceb 100644
--- a/docs/adr/0335-leftover-map-plot-criterion-coordinates.md
+++ b/docs/adr/0335-leftover-map-plot-criterion-coordinates.md
@@ -3,6 +3,9 @@
**Decision status:** Accepted
**Date:** 2026-08-31
+**Amended by:** [ADR 0336](0336-leftover-map-compare-plot-criterion-coordinates.md)
+(leftover-map item coordinates on leftover-map comparison graphic leftover-map criterion markers)
+
Amends leftover-map graphic display of persisted coordinates
([ADR 0268](0268-leftover-map-graphic-display.md)), leftover-map
coordinates ([ADR 0267](0267-leftover-map-coordinates.md)). Independent of leftover-axis
@@ -92,7 +95,9 @@ coordinates (ADR 0267) remain.
## Related
-Independent of leftover-axis tick leftover-map axis share independently of leftover-map
+Independent of leftover-map comparison graphic leftover-map criterion leftover-map item coordinates independently of leftover-map
+post ξ markers
+([ADR 0336](0336-leftover-map-compare-plot-criterion-coordinates.md)). Independent of leftover-axis tick leftover-map axis share independently of leftover-map
singular values
([ADR 0334](0334-leftover-map-axis-tick-share-badge.md)). Independent of leftover-map
comparison leftover-axis tick leftover-map axis share independently of leftover-map
diff --git a/docs/adr/0336-leftover-map-compare-plot-criterion-coordinates.md b/docs/adr/0336-leftover-map-compare-plot-criterion-coordinates.md
new file mode 100644
index 000000000..218d236c6
--- /dev/null
+++ b/docs/adr/0336-leftover-map-compare-plot-criterion-coordinates.md
@@ -0,0 +1,127 @@
+# ADR 0336 — Name leftover-map item coordinates on leftover-map comparison graphic leftover-map criterion markers independently of leftover-map post ξ markers
+
+**Decision status:** Accepted
+**Date:** 2026-08-31
+
+Amends leftover-map graphic display of persisted coordinates on the grouping comparison strip
+([ADR 0304](0304-leftover-map-compare-graphic.md)), leftover-map graphic leftover-map criterion leftover-map item coordinates
+([ADR 0335](0335-leftover-map-plot-criterion-coordinates.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-axis
+tick leftover-map axis share independently of leftover-map singular values
+([ADR 0334](0334-leftover-map-axis-tick-share-badge.md)). Independent of leftover-map
+comparison leftover-axis tick leftover-map axis share independently of leftover-map
+singular values ([ADR 0333](0333-leftover-map-compare-axis-tick-share-badge.md)). Independent of leftover-map
+graphic leftover-map axis tick leftover-map axis share independently of leftover-map
+singular values ([ADR 0332](0332-leftover-map-plot-tick-share-badge.md)). Independent of leftover-map
+comparison graphic leftover-map axis tick leftover-map axis share independently of leftover-map
+singular values ([ADR 0331](0331-leftover-map-compare-plot-tick-share-badge.md)).
+
+## Context
+
+ADR 0267 already persists two-axis Gabriel person coordinates
+`ξ_{1:2}` and item coordinates `ζ_{1:2}` on leftover pair rows so
+`R̂ = ξ_{1:2} · ζ_{1:2}` and `d = ‖ξ_{1:2} − ζ_{1:2}‖` stay
+auditable. ADR 0268 already draws leftover-map graphic leftover-map
+post markers at persisted `ξ` and leftover-map graphic leftover-map
+criterion markers at persisted `ζ`. ADR 0304 reuses that graphic on the grouping
+comparison strip. ADR 0335 already names leftover-map graphic leftover-map
+criterion markers `leftover-map criterion {label} at ζ {item}` independently of leftover-map
+post `ξ` markers. Those leftover-map comparison graphic leftover-map criterion markers still
+read only `Criterion ζ {label}`, so a buyer who reads leftover-map comparison graphic leftover-map
+criterion markers can treat leftover-map location as leftover-map post
+`ξ` without a next action on leftover-map item coordinates. A missing or
+non-finite leftover-map item coordinate pair is not a leftover score and
+must omit independently of leftover-map post `ξ` markers. Rank-0 unused
+axes still persist leftover-map item coordinates `(0.00, 0.00)`. A finite
+negative leftover is shown, never clamped. Do not invent leftover-map
+item coordinates from leftover-map post `ξ`. Do not invent leftover-map
+post `ξ` from leftover-map item coordinates. Leftover-map graphic leftover-map
+criterion markers stay `leftover-map criterion {label} at ζ {item}` this increment.
+
+This increment names leftover-map comparison graphic leftover-map criterion markers leftover-map
+item coordinates as leftoverMapComparePlotCriterionBadge, matching leftover-map
+comparison graphic leftover-map post `ξ` markers. Leftover-map comparison graphic leftover-map
+criterion markers stay
+`leftover map comparison graphic leftover-map criterion {label} at ζ {item}`
+when leftover-map item coordinates are finite, so they stay distinct from leftover-map
+graphic leftover-map criterion markers `leftover-map criterion {label} at ζ {item}` and from leftover-map
+post markers `Open leftover-map post {title} at ξ {person}`.
+It does not add columns. Do not invent a leftover score. Do not invent a theta.
+
+This protected increment uses **0336** so it does not collide with leftover-map
+graphic leftover-map criterion leftover-map item coordinates independently of leftover-map post ξ markers
+(0335), leftover-axis tick leftover-map axis share independently of leftover-map singular values
+(0334), leftover-map comparison leftover-axis tick leftover-map axis share independently of leftover-map singular values
+(0333), leftover-map graphic leftover-map axis tick leftover-map axis share independently of leftover-map singular values
+(0332), leftover-map comparison graphic leftover-map axis tick leftover-map axis share independently of leftover-map singular values
+(0331), leftover-map graphic display on the grouping comparison strip (0304), leftover-map graphic display (0268), leftover-map coordinates (0267),
+or the dashboard stacks.
+
+## Decision
+
+On leftover-map comparison graphic leftover-map criterion markers, caption leftover-map
+item coordinates `ζ_{1:2}` when leftoverMapComparePlotCriterionBadge
+returns a usable leftover-map comparison graphic leftover-map criterion leftover-map item coordinate caption.
+A missing or non-finite leftover-map item coordinate pair omits that leftover-map
+comparison graphic leftover-map criterion leftover-map item coordinate caption and keeps
+`Criterion ζ {label}`. Rank-0 unused axes still name leftover-map
+item coordinates `(0.00, 0.00)`. Click a leftover pair or a leftover-map
+post marker to open that post. Criterion markers are not post buttons.
+
+Leftover-map comparison graphic leftover-map criterion leftover-map item coordinates omit
+independently of leftover-map post `ξ` markers. This increment does not
+change leftover-map graphic leftover-map criterion markers,
+leftover-axis ticks, leftover-map graphic leftover-map axis ticks, leftover-map
+comparison leftover-axis ticks, or leftover-map comparison graphic leftover-map
+axis ticks. This increment does not persist leftover-map inner product, cosine, or length.
+
+Do not add SQL. Do not edit shipped migrations. Do not invent a leftover
+score. Do not invent a theta.
+
+## Consequences
+
+After `make seed`, leftover-map comparison graphic leftover-map criterion markers name persisted
+leftover-map item coordinates when leftoverMapComparePlotCriterionBadge returns a usable
+leftover-map comparison graphic leftover-map criterion leftover-map item coordinate caption; click a leftover pair
+or a leftover-map post marker opens that post. Hidden posts stay hidden. Rank-0 unused
+axes still name leftover-map comparison graphic leftover-map criterion leftover-map item coordinates
+`(0.00, 0.00)`. Leftover-map graphic leftover-map criterion markers stay
+`leftover-map criterion {label} at ζ {item}`. Leftover-map graphic leftover-map criterion leftover-map item coordinates independently of leftover-map
+post ξ markers (ADR 0335), leftover-axis tick leftover-map axis share independently of leftover-map
+singular values (ADR 0334), leftover-map comparison leftover-axis tick leftover-map axis share independently of leftover-map
+singular values (ADR 0333), leftover-map graphic leftover-map axis tick leftover-map axis share independently of leftover-map
+singular values (ADR 0332), leftover-map comparison graphic leftover-map axis tick leftover-map axis share independently of leftover-map
+singular values (ADR 0331), leftover-map graphic display on the grouping comparison strip (ADR 0304), leftover-map graphic display (ADR 0268), and leftover-map
+coordinates (ADR 0267) remain.
+
+## Related
+
+Independent of leftover-map graphic leftover-map criterion leftover-map item coordinates independently of leftover-map
+post ξ markers
+([ADR 0335](0335-leftover-map-plot-criterion-coordinates.md)). Independent of leftover-axis tick leftover-map axis share independently of leftover-map
+singular values
+([ADR 0334](0334-leftover-map-axis-tick-share-badge.md)). Independent of leftover-map
+comparison leftover-axis tick leftover-map axis share independently of leftover-map
+singular values
+([ADR 0333](0333-leftover-map-compare-axis-tick-share-badge.md)). Independent of leftover-map
+graphic leftover-map axis tick leftover-map axis share independently of leftover-map singular values
+([ADR 0332](0332-leftover-map-plot-tick-share-badge.md)). Independent of leftover-map
+comparison graphic leftover-map axis tick leftover-map axis share independently of leftover-map singular values
+([ADR 0331](0331-leftover-map-compare-plot-tick-share-badge.md)). Independent of leftover-map
+graphic display on the grouping comparison strip ([ADR 0304](0304-leftover-map-compare-graphic.md)). Independent of leftover-map
+graphic display ([ADR 0268](0268-leftover-map-graphic-display.md)). Independent of leftover-map
+coordinates ([ADR 0267](0267-leftover-map-coordinates.md)).
+
+## 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.)
diff --git a/docs/product-technical-gap-baseline.md b/docs/product-technical-gap-baseline.md
index c0d9f509d..9b14f4aa2 100644
--- a/docs/product-technical-gap-baseline.md
+++ b/docs/product-technical-gap-baseline.md
@@ -1,5 +1,25 @@
# Product & Technical Gap Baseline
+> Exact-head loop overlay: 2026-08-31 16:30 KST. Protected `main` is
+> `cb187cadee5fb6c46d8a944815ccc154a1e028d1`. Writes work. Do not
+> self-approve. #876 leftover-map item coordinates on leftover-map graphic leftover-map
+> criterion markers independently of leftover-map post ξ markers (v2.92.0 / ADR 0335) is
+> `89ed56b`, stacked on #875 @ `d19f1fd`. Independent APPROVE is missing (Devin COMMENTED,
+> not APPROVE). Next buyer increment on this cycle: leftover-map comparison graphic leftover-map
+> criterion markers naming persisted leftover-map item coordinates independently of leftover-map
+> post ξ markers (ADR 0336 / v2.93.0) delivered locally on
+> `feat/leftover-map-compare-plot-criterion-coordinates-v2930`. Caption persisted leftover-map
+> item coordinates on leftover-map comparison graphic leftover-map criterion markers when leftoverMapComparePlotCriterionBadge
+> returns a usable leftover-map comparison graphic leftover-map criterion leftover-map item coordinate caption. Distinct accessible name
+> `leftover map comparison graphic leftover-map criterion {label} at ζ {item}`.
+> Rank-0 unused axes still name leftover-map item coordinates `(0.00, 0.00)`. A missing or
+> non-finite leftover-map item coordinate pair omits independently of leftover-map post `ξ`.
+> Leftover-map graphic leftover-map criterion markers stay `leftover-map criterion {label} at ζ {item}` this
+> increment. Do not invent leftover-map item coordinates from leftover-map post `ξ`. Do not invent leftover-map
+> post `ξ` from leftover-map item coordinates. Do not persist leftover-map inner product, cosine, or length. Stack onto #876.
+> 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 16:00 KST. Protected `main` is
> `cb187cadee5fb6c46d8a944815ccc154a1e028d1`. Writes work. Do not
> self-approve. #875 leftover-map axis share on leftover-axis ticks independently of leftover-map
diff --git a/docs/storybook-inventory.md b/docs/storybook-inventory.md
index 2af4d32b4..c7bba994f 100644
--- a/docs/storybook-inventory.md
+++ b/docs/storybook-inventory.md
@@ -5,8 +5,8 @@ operator-facing control you can click before changing product CSS.
| Story | Operator next action | Token / module |
|---|---|---|
-| `Reports/LeftoverMapPlot` | Read the leftover-map graphic display of persisted `ξ` (posts) and `ζ` (criteria), match leftover-map graphic leftover-map criterion markers to `leftover-map criterion {label} at ζ {item}`, match axis ticks to those coordinates, pair-segment `d` to leftover-map distance, pair-segment `R̂` to leftover-map reconstruction, pair-segment `R̂²/R²` to leftover-map explained leftover share, pair-segment `U²/R²` to leftover-map unexplained leftover share, pair-segment `2R̂U/R²` to leftover-map cross share, pair-segment `U` to leftover-map unexplained leftover, pair-segment `R` to leftover residual, pair-segment `Y` to leftover observed, pair-segment `E` to leftover expected, and pair-segment leftover-map rank, then click a post marker to open that post. Leftover-map axes name persisted leftover-map singular values `σ_k` and leftover-map axis share when finite. The plot names leftover-map complete-case coverage, leftover-map item complete-case coverage, leftover-map incomplete post coverage, and leftover-map incomplete item coverage when persisted. The comparison variant names leftover-map complete-case coverage under `Leftover map comparison graphic coverage` and leftover-map item complete-case coverage under `Leftover map comparison graphic item coverage` and leftover-map incomplete post coverage under `Leftover map comparison graphic incomplete posts` and leftover-map incomplete item coverage under `Leftover map comparison graphic incomplete items` and leftover-map comparison graphic leftover-map criterion markers under `Criterion ζ {label}`. `ClosestAndFarthest`, `RankZeroOrigin`, `MissingCoordinates`, `MissingAxisShare`, `Comparison`, `ComparisonMissingCoverage`, `ComparisonMissingItemCoverage`, `ComparisonMissingIncompletePosts`, and `ComparisonMissingIncompleteItems` cover two-pair maps, rank-0 origin with 0% share, a `0` tick, `d 0.00`, `R̂ 0.00`, `R̂²/R² 0.00`, `U²/R² 0.00`, `2R̂U/R² 0.00`, `U 0.00`, `R 0.00`, `Y 0.00`, `E 0.00`, and `rank 0`, omitted plots, missing share that keeps leftover-map axis `σ` without share, grouping comparison leftover-map graphic coverage that matches leftover map used N of M scored posts, omitted comparison graphic coverage when leftoverMapCoverageCounts fail-closes, grouping comparison leftover-map graphic item coverage that matches leftover map used N of M scored criteria, omitted comparison graphic item coverage when leftoverMapItemCoverageCounts fail-closes, grouping comparison leftover-map graphic incomplete posts that matches leftover map dropped N incomplete posts, omitted comparison graphic incomplete posts when leftoverMapIncompletePostCount fail-closes, grouping comparison leftover-map graphic incomplete items that matches leftover map dropped N incomplete criteria, and omitted comparison graphic incomplete items when leftoverMapIncompleteItemCount fail-closes. The plot does not invent a leftover score. | `LeftoverMapPlot`, `leftoverMapPlotLayout`, `leftoverMapPlotAxisShare`, `--color-primary`, `--color-palette-blue-mid` |
-| `Reports/LeftoverPairList` | Read closest/farthest leftover pairs with named `R`, `Y`/`E`, rank, `U`, `s`, `e`, `x`, `R̂`, `ξ`/`ζ`, and `d`, then open that post. The leftover-map graphic display sits above the pair buttons when coordinates are finite, leftover-map axes name persisted leftover-map singular values and leftover-map axis share, leftover-map axis ticks name persisted coordinates, leftover-map graphic leftover-map criterion markers name persisted leftover-map item coordinates under `leftover-map criterion {label} at ζ {item}`, leftover-axis ticks name persisted leftover-map singular values and leftover-map axis share independently under `leftover axis {axis} tick {value} σ {singular} {share}%`, pair segments name persisted leftover-map distance, pair segments name persisted leftover-map reconstruction, pair segments name persisted leftover-map explained leftover share, pair segments name persisted leftover-map unexplained leftover share, pair segments name persisted leftover-map cross share, pair segments name persisted leftover-map unexplained leftover, pair segments name persisted leftover residual, pair segments name persisted leftover observed, pair segments name persisted leftover expected, and pair segments name persisted leftover-map rank. The pair-list note names leftover-map complete-case coverage only when leftoverMapCoverageCounts returns usable complete-case integers, leftover-map item complete-case coverage, leftover-map incomplete post coverage, and leftover-map incomplete item coverage when persisted. The grouping comparison strip names leftover-map complete-case coverage, leftover-map item complete-case coverage, leftover-map incomplete post coverage, leftover-map incomplete item coverage, leftover-axis report badges with persisted leftover-map singular values under `leftover map comparison leftover axis {axis} σ {value}`, leftover-axis ticks with persisted leftover-map singular values and leftover-map axis share under `leftover map comparison leftover axis {axis} tick {value} σ {singular} {share}%` independently of leftover-map singular values, and leftover-map comparison graphic leftover-map criterion markers under `Criterion ζ {label}` with distinct comparison labels when leftoverMapCoverageCounts / leftoverMapItemCoverageCounts / leftoverMapIncompletePostCount / leftoverMapIncompleteItemCount / leftoverMapCompareAxisBadge / leftoverMapCompareAxisTickBadge return usable values. | `LeftoverPairList`, `LeftoverMapPlot`, `ticket-list`, `post-badge` |
+| `Reports/LeftoverMapPlot` | Read the leftover-map graphic display of persisted `ξ` (posts) and `ζ` (criteria), match leftover-map graphic leftover-map criterion markers to `leftover-map criterion {label} at ζ {item}`, match axis ticks to those coordinates, pair-segment `d` to leftover-map distance, pair-segment `R̂` to leftover-map reconstruction, pair-segment `R̂²/R²` to leftover-map explained leftover share, pair-segment `U²/R²` to leftover-map unexplained leftover share, pair-segment `2R̂U/R²` to leftover-map cross share, pair-segment `U` to leftover-map unexplained leftover, pair-segment `R` to leftover residual, pair-segment `Y` to leftover observed, pair-segment `E` to leftover expected, and pair-segment leftover-map rank, then click a post marker to open that post. Leftover-map axes name persisted leftover-map singular values `σ_k` and leftover-map axis share when finite. The plot names leftover-map complete-case coverage, leftover-map item complete-case coverage, leftover-map incomplete post coverage, and leftover-map incomplete item coverage when persisted. The comparison variant names leftover-map complete-case coverage under `Leftover map comparison graphic coverage` and leftover-map item complete-case coverage under `Leftover map comparison graphic item coverage` and leftover-map incomplete post coverage under `Leftover map comparison graphic incomplete posts` and leftover-map incomplete item coverage under `Leftover map comparison graphic incomplete items` and leftover-map comparison graphic leftover-map criterion markers under `leftover map comparison graphic leftover-map criterion {label} at ζ {item}`. `ClosestAndFarthest`, `RankZeroOrigin`, `MissingCoordinates`, `MissingAxisShare`, `Comparison`, `ComparisonMissingCoverage`, `ComparisonMissingItemCoverage`, `ComparisonMissingIncompletePosts`, and `ComparisonMissingIncompleteItems` cover two-pair maps, rank-0 origin with 0% share, a `0` tick, `d 0.00`, `R̂ 0.00`, `R̂²/R² 0.00`, `U²/R² 0.00`, `2R̂U/R² 0.00`, `U 0.00`, `R 0.00`, `Y 0.00`, `E 0.00`, and `rank 0`, omitted plots, missing share that keeps leftover-map axis `σ` without share, grouping comparison leftover-map graphic coverage that matches leftover map used N of M scored posts, omitted comparison graphic coverage when leftoverMapCoverageCounts fail-closes, grouping comparison leftover-map graphic item coverage that matches leftover map used N of M scored criteria, omitted comparison graphic item coverage when leftoverMapItemCoverageCounts fail-closes, grouping comparison leftover-map graphic incomplete posts that matches leftover map dropped N incomplete posts, omitted comparison graphic incomplete posts when leftoverMapIncompletePostCount fail-closes, grouping comparison leftover-map graphic incomplete items that matches leftover map dropped N incomplete criteria, and omitted comparison graphic incomplete items when leftoverMapIncompleteItemCount fail-closes. The plot does not invent a leftover score. | `LeftoverMapPlot`, `leftoverMapPlotLayout`, `leftoverMapPlotAxisShare`, `--color-primary`, `--color-palette-blue-mid` |
+| `Reports/LeftoverPairList` | Read closest/farthest leftover pairs with named `R`, `Y`/`E`, rank, `U`, `s`, `e`, `x`, `R̂`, `ξ`/`ζ`, and `d`, then open that post. The leftover-map graphic display sits above the pair buttons when coordinates are finite, leftover-map axes name persisted leftover-map singular values and leftover-map axis share, leftover-map axis ticks name persisted coordinates, leftover-map graphic leftover-map criterion markers name persisted leftover-map item coordinates under `leftover-map criterion {label} at ζ {item}`, leftover-axis ticks name persisted leftover-map singular values and leftover-map axis share independently under `leftover axis {axis} tick {value} σ {singular} {share}%`, pair segments name persisted leftover-map distance, pair segments name persisted leftover-map reconstruction, pair segments name persisted leftover-map explained leftover share, pair segments name persisted leftover-map unexplained leftover share, pair segments name persisted leftover-map cross share, pair segments name persisted leftover-map unexplained leftover, pair segments name persisted leftover residual, pair segments name persisted leftover observed, pair segments name persisted leftover expected, and pair segments name persisted leftover-map rank. The pair-list note names leftover-map complete-case coverage only when leftoverMapCoverageCounts returns usable complete-case integers, leftover-map item complete-case coverage, leftover-map incomplete post coverage, and leftover-map incomplete item coverage when persisted. The grouping comparison strip names leftover-map complete-case coverage, leftover-map item complete-case coverage, leftover-map incomplete post coverage, leftover-map incomplete item coverage, leftover-axis report badges with persisted leftover-map singular values under `leftover map comparison leftover axis {axis} σ {value}`, leftover-axis ticks with persisted leftover-map singular values and leftover-map axis share under `leftover map comparison leftover axis {axis} tick {value} σ {singular} {share}%` independently of leftover-map singular values, and leftover-map comparison graphic leftover-map criterion markers under `leftover map comparison graphic leftover-map criterion {label} at ζ {item}` with distinct comparison labels when leftoverMapCoverageCounts / leftoverMapItemCoverageCounts / leftoverMapIncompletePostCount / leftoverMapIncompleteItemCount / leftoverMapCompareAxisBadge / leftoverMapCompareAxisTickBadge / leftoverMapComparePlotCriterionBadge return usable values. | `LeftoverPairList`, `LeftoverMapPlot`, `ticket-list`, `post-badge` |
| `Workspace/OperationsDashboard` | Compare Event and post counts, inspect external-information coverage, then open the cited source behind a claim, handover, or repeat-issue fact. `EvidenceReady`, `NarrowViewport`, `AnalysisPendingAndMissingEvidence`, `AnalysisFailed`, and `LoadError` cover populated, mobile, unavailable-evidence, analysis-pending, retryable failure, and transport-error states. | `--color-dashboard-*`, `OperationsDashboard` |
| `Post/SimilarVocPanel` | Compare ontology/semantic similar VOC and prior action evidence, then open the source; unavailable states show no fabricated TEPP theta or weight. | `SimilarVocPanel.css`, `SimilarVocPanel` |
| `Post/Recorded perspectives` | Read the imported primary and every evidence-connected additional Voice with its recorded truth state instead of flattening them into one compound category. `CombinedEvidence`, `RejectedEvidence`, and `NarrowViewport` cover desktop, rejected-evidence, and narrow layouts. | `VoicePerspectiveList`, `ticket-list`, `post-meta` |
diff --git a/frontend/package.json b/frontend/package.json
index 59bdbe0f1..2134be6d7 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -1,7 +1,7 @@
{
"name": "frontend",
"private": true,
- "version": "2.92.0",
+ "version": "2.93.0",
"type": "module",
"scripts": {
"dev": "vite",
diff --git a/frontend/src/App.test.tsx b/frontend/src/App.test.tsx
index 04e76ed01..fda9a50ba 100644
--- a/frontend/src/App.test.tsx
+++ b/frontend/src/App.test.tsx
@@ -4213,8 +4213,13 @@ describe("App, authenticated", () => {
expect(screen.getByLabelText("Leftover map comparison graphic")).toBeInTheDocument();
expect(screen.getByLabelText("leftover-map criterion sales-lead at ζ (+0.50, −0.02)")).toBeInTheDocument();
expect(
- within(screen.getByLabelText("Grouping comparison")).getByLabelText("Criterion ζ sales-lead"),
+ within(screen.getByLabelText("Grouping comparison")).getByLabelText(
+ "leftover map comparison graphic leftover-map criterion sales-lead at ζ (+0.50, −0.02)",
+ ),
).toBeInTheDocument();
+ expect(
+ within(screen.getByLabelText("Grouping comparison")).queryByLabelText("Criterion ζ sales-lead"),
+ ).not.toBeInTheDocument();
expect(
within(screen.getByLabelText("Grouping comparison")).queryByLabelText(
"leftover-map criterion sales-lead at ζ (+0.50, −0.02)",
diff --git a/frontend/src/components/LeftoverMapPlot.test.tsx b/frontend/src/components/LeftoverMapPlot.test.tsx
index 9eb4d1704..80df55436 100644
--- a/frontend/src/components/LeftoverMapPlot.test.tsx
+++ b/frontend/src/components/LeftoverMapPlot.test.tsx
@@ -926,8 +926,10 @@ describe("LeftoverMapPlot", () => {
).toBeInTheDocument();
expect(screen.getByText("leftover map comparison graphic leftover-map axis 1 σ 1.84 (82%)")).toBeInTheDocument();
expect(screen.getByText("leftover map comparison graphic leftover-map axis 2 σ 0.86 (18%)")).toBeInTheDocument();
- expect(screen.getByLabelText("Criterion ζ sales-lead")).toBeInTheDocument();
- expect(screen.getByLabelText("Criterion ζ negative")).toBeInTheDocument();
+ expect(screen.getByLabelText("leftover map comparison graphic leftover-map criterion sales-lead at ζ (+0.50, −0.02)")).toBeInTheDocument();
+ expect(screen.getByLabelText("leftover map comparison graphic leftover-map criterion negative at ζ (−0.70, −0.40)")).toBeInTheDocument();
+ expect(screen.queryByLabelText("Criterion ζ sales-lead")).not.toBeInTheDocument();
+ expect(screen.queryByLabelText("Criterion ζ negative")).not.toBeInTheDocument();
expect(
screen.queryByLabelText("leftover-map criterion sales-lead at ζ (+0.50, −0.02)"),
).not.toBeInTheDocument();
@@ -940,6 +942,47 @@ describe("LeftoverMapPlot", () => {
expect(screen.queryByText("leftover-map axis 2 (18%)")).not.toBeInTheDocument();
});
+ it("names leftover map comparison graphic leftover-map criterion rank-0 origin leftover-map item coordinates", () => {
+ render(
+ ,
+ );
+ expect(
+ screen.getByLabelText("leftover map comparison graphic leftover-map criterion sales-lead at ζ (0.00, 0.00)"),
+ ).toBeInTheDocument();
+ expect(screen.queryByLabelText("Criterion ζ sales-lead")).not.toBeInTheDocument();
+ expect(screen.queryByLabelText("leftover-map criterion sales-lead at ζ (0.00, 0.00)")).not.toBeInTheDocument();
+ });
+
it("keeps leftover map comparison axis text when share is missing or non-finite", () => {
render(
{
"Post ξ",
"Criterion ζ",
"leftover-map criterion {label} at ζ {item}",
+ "leftover map comparison graphic leftover-map criterion {label} at ζ {item}",
"leftover-map axis 1",
"leftover-map axis 2",
"leftover-map axis {axis} ({share}%)",
@@ -446,6 +447,21 @@ describe("i18n", () => {
).toBe(expected);
});
+ it.each([
+ ["ko", "잔여 지도 비교 그림 기준 sales-lead (ζ (+0.50, −0.02))"],
+ ["zh", "残差地图比较图形准则 sales-lead(ζ (+0.50, −0.02))"],
+ ["ja", "残差マップの比較図基準 sales-lead(ζ (+0.50, −0.02))"],
+ ["vi", "tiêu chí đồ họa so sánh bản đồ phần dư sales-lead tại ζ (+0.50, −0.02)"],
+ ] as const)("formats leftover map comparison graphic leftover-map criterion ζ in %s", (locale, expected) => {
+ setLocale(locale);
+ expect(
+ tf("leftover map comparison graphic leftover-map criterion {label} at ζ {item}", {
+ label: "sales-lead",
+ item: "(+0.50, −0.02)",
+ }),
+ ).toBe(expected);
+ });
+
it.each([
["ko", "잔여 지도 그림 포함 범위"],
["zh", "残差图图形覆盖范围"],
diff --git a/frontend/src/i18n.ts b/frontend/src/i18n.ts
index e2e296df3..69a060f79 100644
--- a/frontend/src/i18n.ts
+++ b/frontend/src/i18n.ts
@@ -664,6 +664,8 @@ const TRANSLATIONS: Partial>> = {
"Post ξ": "글 ξ",
"Criterion ζ": "기준 ζ",
"leftover-map criterion {label} at ζ {item}": "잔여 지도 기준 {label} (ζ {item})",
+ "leftover map comparison graphic leftover-map criterion {label} at ζ {item}":
+ "잔여 지도 비교 그림 기준 {label} (ζ {item})",
"leftover-map axis 1": "잔여 지도 축 1",
"leftover-map axis 2": "잔여 지도 축 2",
"leftover-map axis {axis} ({share}%)": "잔여 지도 축 {axis} ({share}%)",
@@ -1340,6 +1342,8 @@ const TRANSLATIONS: Partial>> = {
"Post ξ": "帖子 ξ",
"Criterion ζ": "准则 ζ",
"leftover-map criterion {label} at ζ {item}": "残差图准则 {label}(ζ {item})",
+ "leftover map comparison graphic leftover-map criterion {label} at ζ {item}":
+ "残差地图比较图形准则 {label}(ζ {item})",
"leftover-map axis 1": "残差图轴 1",
"leftover-map axis 2": "残差图轴 2",
"leftover-map axis {axis} ({share}%)": "残差图轴 {axis} ({share}%)",
@@ -2020,6 +2024,8 @@ const TRANSLATIONS: Partial>> = {
"Post ξ": "投稿 ξ",
"Criterion ζ": "基準 ζ",
"leftover-map criterion {label} at ζ {item}": "残差マップの基準 {label}(ζ {item})",
+ "leftover map comparison graphic leftover-map criterion {label} at ζ {item}":
+ "残差マップの比較図基準 {label}(ζ {item})",
"leftover-map axis 1": "残差マップ軸 1",
"leftover-map axis 2": "残差マップ軸 2",
"leftover-map axis {axis} ({share}%)": "残差マップ軸 {axis} ({share}%)",
@@ -2704,6 +2710,8 @@ const TRANSLATIONS: Partial>> = {
"Post ξ": "Bài viết ξ",
"Criterion ζ": "Tiêu chí ζ",
"leftover-map criterion {label} at ζ {item}": "tiêu chí bản đồ phần dư {label} tại ζ {item}",
+ "leftover map comparison graphic leftover-map criterion {label} at ζ {item}":
+ "tiêu chí đồ họa so sánh bản đồ phần dư {label} tại ζ {item}",
"leftover-map axis 1": "trục bản đồ phần dư 1",
"leftover-map axis 2": "trục bản đồ phần dư 2",
"leftover-map axis {axis} ({share}%)": "trục bản đồ phần dư {axis} ({share}%)",
diff --git a/frontend/src/leftoverMapPlotLayout.test.ts b/frontend/src/leftoverMapPlotLayout.test.ts
index 0b8905c6c..a1b781abf 100644
--- a/frontend/src/leftoverMapPlotLayout.test.ts
+++ b/frontend/src/leftoverMapPlotLayout.test.ts
@@ -6,6 +6,7 @@ import {
hasLeftoverMapPlotCoordinates,
layoutLeftoverMapPlot,
leftoverMapPlotCriterionBadge,
+ leftoverMapComparePlotCriterionBadge,
LEFTOVER_MAP_COMPARE_PLOT_CAPTION,
LEFTOVER_MAP_COMPARE_PLOT_LABEL,
LEFTOVER_MAP_COMPARE_PLOT_SEGMENT_RECONSTRUCTION,
@@ -21,6 +22,7 @@ import {
LEFTOVER_MAP_COMPARE_PLOT_TICK,
LEFTOVER_MAP_COMPARE_PLOT_SVG,
LEFTOVER_MAP_PLOT_CRITERION,
+ LEFTOVER_MAP_COMPARE_PLOT_CRITERION,
LEFTOVER_MAP_PLOT_POST_ACTION,
LEFTOVER_MAP_PLOT_TICK,
PLOT_HEIGHT,
@@ -1236,10 +1238,54 @@ describe("leftoverMapPlotCriterionBadge", () => {
expect(LEFTOVER_MAP_PLOT_CRITERION).not.toBe(LEFTOVER_MAP_PLOT_POST_ACTION);
expect(LEFTOVER_MAP_PLOT_CRITERION).not.toBe("Criterion ζ {label}");
expect(LEFTOVER_MAP_PLOT_CRITERION).not.toBe("Criterion ζ");
- expect(LEFTOVER_MAP_PLOT_CRITERION).not.toBe(
- "leftover map comparison graphic leftover-map criterion {label} at ζ {item}",
+ expect(LEFTOVER_MAP_PLOT_CRITERION).not.toBe(LEFTOVER_MAP_COMPARE_PLOT_CRITERION);
+ expect(leftoverMapPlotCriterionBadge("sales-lead", 0.5, -0.02)?.key).not.toBe(
+ LEFTOVER_MAP_PLOT_POST_ACTION,
);
expect(leftoverMapPlotCriterionBadge("sales-lead", 0.5, -0.02)?.key).not.toBe(
+ LEFTOVER_MAP_COMPARE_PLOT_CRITERION,
+ );
+ });
+});
+
+describe("leftoverMapComparePlotCriterionBadge", () => {
+ it("names persisted leftover-map item coordinates without inventing a leftover score", () => {
+ expect(leftoverMapComparePlotCriterionBadge("sales-lead", 0.5, -0.02)).toEqual({
+ key: LEFTOVER_MAP_COMPARE_PLOT_CRITERION,
+ values: { label: "sales-lead", item: "(+0.50, \u22120.02)" },
+ });
+ expect(leftoverMapComparePlotCriterionBadge("negative", -0.7, -0.4)).toEqual({
+ key: LEFTOVER_MAP_COMPARE_PLOT_CRITERION,
+ values: { label: "negative", item: "(\u22120.70, \u22120.40)" },
+ });
+ });
+
+ it("names rank-0 origin leftover-map item coordinates as ζ (0.00, 0.00)", () => {
+ expect(leftoverMapComparePlotCriterionBadge("sales-lead", 0, 0)).toEqual({
+ key: LEFTOVER_MAP_COMPARE_PLOT_CRITERION,
+ values: { label: "sales-lead", item: "(0.00, 0.00)" },
+ });
+ });
+
+ it("omits leftover-map item coordinates when ζ is missing or non-finite", () => {
+ expect(leftoverMapComparePlotCriterionBadge("sales-lead", null, -0.02)).toBeNull();
+ expect(leftoverMapComparePlotCriterionBadge("sales-lead", 0.5, undefined)).toBeNull();
+ expect(leftoverMapComparePlotCriterionBadge("sales-lead", Number.NaN, -0.02)).toBeNull();
+ expect(leftoverMapComparePlotCriterionBadge("sales-lead", 0.5, Number.POSITIVE_INFINITY)).toBeNull();
+ });
+
+ it("stays distinct from leftover-map graphic leftover-map criterion markers and leftover-map post ξ markers", () => {
+ expect(LEFTOVER_MAP_COMPARE_PLOT_CRITERION).toBe(
+ "leftover map comparison graphic leftover-map criterion {label} at ζ {item}",
+ );
+ expect(LEFTOVER_MAP_COMPARE_PLOT_CRITERION).not.toBe(LEFTOVER_MAP_PLOT_CRITERION);
+ expect(LEFTOVER_MAP_COMPARE_PLOT_CRITERION).not.toBe(LEFTOVER_MAP_PLOT_POST_ACTION);
+ expect(LEFTOVER_MAP_COMPARE_PLOT_CRITERION).not.toBe("Criterion ζ {label}");
+ expect(LEFTOVER_MAP_COMPARE_PLOT_CRITERION).not.toBe("Criterion ζ");
+ expect(leftoverMapComparePlotCriterionBadge("sales-lead", 0.5, -0.02)?.key).not.toBe(
+ LEFTOVER_MAP_PLOT_CRITERION,
+ );
+ expect(leftoverMapComparePlotCriterionBadge("sales-lead", 0.5, -0.02)?.key).not.toBe(
LEFTOVER_MAP_PLOT_POST_ACTION,
);
});
diff --git a/frontend/src/leftoverMapPlotLayout.ts b/frontend/src/leftoverMapPlotLayout.ts
index 2c09021c2..cc5fefda6 100644
--- a/frontend/src/leftoverMapPlotLayout.ts
+++ b/frontend/src/leftoverMapPlotLayout.ts
@@ -119,6 +119,10 @@
* leftover-map item coordinates ζ through leftoverMapPlotCriterionBadge
* independently of leftover-map post ξ markers, not leftover-map comparison
* graphic leftover-map criterion markers.
+ * ADR 0336 fail-closes leftover-map comparison graphic leftover-map criterion
+ * markers leftover-map item coordinates ζ through leftoverMapComparePlotCriterionBadge
+ * independently of leftover-map post ξ markers, not leftover-map graphic leftover-map
+ * criterion markers.
*/
import { formatLeftoverMapCoordinatePair } from "./leftoverMapCoordinates";
@@ -151,6 +155,9 @@ export const LEFTOVER_MAP_PLOT_POST_ACTION =
export const LEFTOVER_MAP_PLOT_CRITERION =
"leftover-map criterion {label} at ζ {item}";
+export const LEFTOVER_MAP_COMPARE_PLOT_CRITERION =
+ "leftover map comparison graphic leftover-map criterion {label} at ζ {item}";
+
export type LeftoverMapPlotCriterionBadge = {
key: string;
values: { label: string; item: string };
@@ -168,6 +175,18 @@ export function leftoverMapPlotCriterionBadge(
return { key: LEFTOVER_MAP_PLOT_CRITERION, values: { label, item } };
}
+export function leftoverMapComparePlotCriterionBadge(
+ label: string,
+ axis1: number | null | undefined,
+ axis2: number | null | undefined,
+): LeftoverMapPlotCriterionBadge | null {
+ const item = formatLeftoverMapCoordinatePair(axis1, axis2);
+ if (item === null) {
+ return null;
+ }
+ return { key: LEFTOVER_MAP_COMPARE_PLOT_CRITERION, values: { label, item } };
+}
+
export const LEFTOVER_MAP_PLOT_TICK =
"leftover-map axis {axis} tick {value}";
diff --git a/pyproject.toml b/pyproject.toml
index c03740504..580016ad8 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -1,6 +1,6 @@
[project]
name = "lineageweave"
-version = "2.92.0"
+version = "2.93.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" }