From ba58c21a92966fe098988e528020d5528978d06c Mon Sep 17 00:00:00 2001 From: Seongho Bae Date: Mon, 31 Aug 2026 05:36:09 +0000 Subject: [PATCH] feat(reports): leftover-map axis share on leftover-map comparison leftover-axis ticks independently of leftover-map singular values (v2.90.0) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Caption leftover-map comparison leftover-axis ticks with persisted leftover-map axis share through leftoverMapCompareAxisTickBadge independently of leftover-map singular values (ADR 0333). Share and σ omit independently. Rank-0 unused axes still name leftover-map axis share 0%. Leftover-axis ticks stay σ-only. Do not invent leftover-map axis share from σ_k. Do not invent σ_k from leftover-map axis share. Never invent a leftover score or a theta. No new columns. --- AGENTS.md | 13 ++ ARCHITECTURE.md | 6 +- ...tover-map-compare-axis-tick-share-badge.md | 27 ++++ CHANGELOG.md | 27 ++++ CLAUDE.md | 2 +- docs/adr/0148-leftover-map-axis-share.md | 4 +- ...29-leftover-map-compare-axis-tick-badge.md | 4 +- docs/adr/0330-leftover-map-axis-tick-badge.md | 4 +- ...tover-map-compare-plot-tick-share-badge.md | 4 +- ...0332-leftover-map-plot-tick-share-badge.md | 8 +- ...tover-map-compare-axis-tick-share-badge.md | 132 ++++++++++++++++++ docs/product-technical-gap-baseline.md | 21 +++ frontend/package.json | 2 +- frontend/src/App.test.tsx | 25 ++-- frontend/src/App.tsx | 1 + frontend/src/i18n.test.ts | 41 ++++++ frontend/src/i18n.ts | 16 +++ frontend/src/leftoverMapAxisBadge.test.ts | 3 + frontend/src/leftoverMapAxisBadge.ts | 2 + .../src/leftoverMapPlotAxisSingular.test.ts | 110 +++++++++++++++ frontend/src/leftoverMapPlotAxisSingular.ts | 29 +++- frontend/src/leftoverMapPlotLayout.test.ts | 6 + frontend/src/leftoverMapPlotLayout.ts | 3 + pyproject.toml | 2 +- 24 files changed, 469 insertions(+), 23 deletions(-) create mode 100644 CHANGELOG.d/2.90.0-leftover-map-compare-axis-tick-share-badge.md create mode 100644 docs/adr/0333-leftover-map-compare-axis-tick-share-badge.md diff --git a/AGENTS.md b/AGENTS.md index 1b861150d..db4ff2d0a 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -728,6 +728,15 @@ graphic leftover-map axis tick leftover-map axis share `0%`. Do not invent lefto axis share from leftover-map singular values. Do not invent leftover-map singular values from leftover-map axis share. Leftover-map comparison graphic leftover-map axis ticks, leftover-map comparison leftover-axis ticks, and leftover-axis ticks never name leftover-map axis share this increment. +ADR 0333 captions leftover-map comparison leftover-axis ticks with persisted leftover-map +axis share when leftoverMapCompareAxisTickBadge returns a usable leftover-axis tick leftover-map +axis share caption. Distinct accessible names +`leftover map comparison leftover axis {axis} tick {value} {share}%` and +`leftover map comparison leftover axis {axis} tick {value} σ {singular} {share}%`. +Share and singular value omit independently. Rank-0 unused axes still name leftover-map +comparison leftover-axis tick leftover-map axis share `0%`. Do not invent leftover-map +axis share from leftover-map singular values. Do not invent leftover-map singular values from leftover-map +axis share. Leftover-axis ticks never name leftover-map axis share 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 @@ -861,6 +870,10 @@ Leftover-map graphic leftover-map axis tick leftover-map axis share independentl (ADR 0332) captions leftover-map graphic leftover-map axis ticks with persisted leftover-map axis share when leftoverMapPlotTickAxisBadge returns a usable leftover-map axis tick leftover-map axis share caption. +Leftover-map comparison leftover-axis tick leftover-map axis share independently of leftover-map singular values +(ADR 0333) captions leftover-map comparison leftover-axis ticks with persisted leftover-map +axis share when leftoverMapCompareAxisTickBadge returns a usable leftover-axis tick leftover-map +axis share 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 c5d1adf8d..151f4a5e0 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -779,6 +779,9 @@ axis share caption independently of leftover-map singular values. ADR 0332 captions leftover-map graphic leftover-map axis ticks with persisted leftover-map axis share when leftoverMapPlotTickAxisBadge returns a usable leftover-map axis tick leftover-map axis share caption independently of leftover-map singular values. +ADR 0333 captions leftover-map comparison leftover-axis ticks with persisted leftover-map +axis share when leftoverMapCompareAxisTickBadge returns a usable leftover-axis tick leftover-map +axis share caption independently of leftover-map singular values. 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 @@ -841,7 +844,8 @@ comparison graphic leftover-map axis leftover-map singular values as leftoverMap (ADR 0329), leftover-axis tick leftover-map singular values independently of leftover-map axis share (ADR 0330), leftover-map comparison graphic leftover-map axis tick leftover-map axis share independently of leftover-map singular values (ADR 0331), leftover-map graphic leftover-map axis tick leftover-map axis share independently of leftover-map singular values -(ADR 0332); +(ADR 0332), leftover-map comparison leftover-axis tick leftover-map axis share independently of leftover-map singular values +(ADR 0333); `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.90.0-leftover-map-compare-axis-tick-share-badge.md b/CHANGELOG.d/2.90.0-leftover-map-compare-axis-tick-share-badge.md new file mode 100644 index 000000000..6ab963c97 --- /dev/null +++ b/CHANGELOG.d/2.90.0-leftover-map-compare-axis-tick-share-badge.md @@ -0,0 +1,27 @@ +## 2.90.0 — Leftover-map axis share on leftover-map comparison leftover-axis ticks independently of leftover-map singular values + +- Caption leftover-map comparison leftover-axis ticks with persisted leftover-map + axis share through leftoverMapCompareAxisTickBadge independently of leftover-map + singular values (ADR 0333). After `make seed`, leftover-map comparison leftover-axis + ticks name persisted leftover-map axis share when leftoverMapCompareAxisTickBadge + returns a usable leftover-axis tick leftover-map axis share caption even when leftover-map + singular values are omitted; click a leftover pair opens that post. A missing or + non-finite leftover-map axis share omits that leftover-map axis share tick caption and keeps + `leftover map comparison leftover axis {k} tick {value}` or + `leftover map comparison leftover axis {k} tick {value} σ {singular}`. Rank-0 unused + axes still name leftover-map axis share `0%`. Leftover-map comparison leftover-axis ticks stay + `leftover map comparison leftover axis {k} tick {value} {share}%` when leftover-map + axis share is finite and `σ_k` omits, and + `leftover map comparison leftover axis {k} tick {value} σ {singular} {share}%` + when both are finite so they stay distinct from leftover-map graphic leftover-map axis ticks + `leftover-map axis {k} tick {value} σ {singular} {share}%`, from leftover-map comparison graphic leftover-map axis ticks + `leftover map comparison graphic leftover-map axis {k} tick {value} σ {singular} {share}%`, from leftover-axis + `leftover axis {k} {share}%`, from comparison leftover-axis + `leftover map comparison leftover axis {k} {share}%`, from leftover-axis ticks + `leftover axis {k} tick {value} σ {singular}`, and from leftover-map comparison leftover-axis ticks + `leftover map comparison leftover axis {k} tick {value} σ {singular}`. Do not invent + leftover-map axis share from `σ_k`. Do not invent `σ_k` from leftover-map axis + share. This increment does not change leftover-axis ticks, leftover-map graphic leftover-map 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 42b1298ae..656681fd1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,33 @@ All notable changes to this project are documented here. Format follows ### Added +- Period leftover pairs now caption leftover-map comparison leftover-axis + ticks with persisted leftover-map axis share through leftoverMapCompareAxisTickBadge + independently of leftover-map singular values (ADR 0333 / v2.90.0). After `make seed`, + leftover-map comparison leftover-axis ticks name persisted leftover-map + axis share when leftoverMapCompareAxisTickBadge returns a usable leftover-axis + tick leftover-map axis share caption even when leftover-map singular values are + omitted; click a leftover pair opens that post. A missing or non-finite leftover-map + axis share omits that leftover-map axis share tick caption and keeps + `leftover map comparison leftover axis {k} tick {value}` or + `leftover map comparison leftover axis {k} tick {value} σ {singular}`. + Rank-0 unused axes still name leftover-map axis share `0%`. Leftover-map comparison + leftover-axis ticks stay + `leftover map comparison leftover axis {k} tick {value} {share}%` when leftover-map + axis share is finite and `σ_k` omits, and + `leftover map comparison leftover axis {k} tick {value} σ {singular} {share}%` + when both are finite so they stay distinct from leftover-map graphic leftover-map axis ticks + `leftover-map axis {k} tick {value} σ {singular} {share}%`, from leftover-map comparison graphic leftover-map + axis ticks `leftover map comparison graphic leftover-map axis {k} tick {value} σ {singular} {share}%`, from leftover-axis + `leftover axis {k} {share}%`, from comparison leftover-axis + `leftover map comparison leftover axis {k} {share}%`, from leftover-axis ticks + `leftover axis {k} tick {value} σ {singular}`, and from leftover-map comparison leftover-axis ticks + `leftover map comparison leftover axis {k} tick {value} σ {singular}`. Do not invent + leftover-map axis share from `σ_k`. Do not invent `σ_k` from leftover-map axis + share. This increment does not change leftover-axis ticks, leftover-map graphic leftover-map 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 axis ticks with persisted leftover-map axis share through leftoverMapPlotTickAxisBadge independently of leftover-map singular values (ADR 0332 / v2.89.0). After `make seed`, diff --git a/CLAUDE.md b/CLAUDE.md index 7089fea23..f213eb9a8 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), 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), 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/0148-leftover-map-axis-share.md b/docs/adr/0148-leftover-map-axis-share.md index cf77642d6..59557b606 100644 --- a/docs/adr/0148-leftover-map-axis-share.md +++ b/docs/adr/0148-leftover-map-axis-share.md @@ -25,7 +25,9 @@ [ADR 0331](0331-leftover-map-compare-plot-tick-share-badge.md) (leftover-map comparison 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) -(leftover-map graphic leftover-map axis tick leftover-map axis share independently of leftover-map singular values) +(leftover-map graphic leftover-map axis tick leftover-map axis share independently of leftover-map singular values); +[ADR 0333](0333-leftover-map-compare-axis-tick-share-badge.md) +(leftover-map comparison leftover-axis tick leftover-map axis share independently of leftover-map singular values) ## Context diff --git a/docs/adr/0329-leftover-map-compare-axis-tick-badge.md b/docs/adr/0329-leftover-map-compare-axis-tick-badge.md index 0ac963c60..8f0accbf6 100644 --- a/docs/adr/0329-leftover-map-compare-axis-tick-badge.md +++ b/docs/adr/0329-leftover-map-compare-axis-tick-badge.md @@ -122,7 +122,9 @@ tick leftover-map singular values independently of leftover-map axis share 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 leftover-map axis tick leftover-map axis share independently of leftover-map -singular values ([ADR 0332](0332-leftover-map-plot-tick-share-badge.md)). +singular values ([ADR 0332](0332-leftover-map-plot-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)). ## References diff --git a/docs/adr/0330-leftover-map-axis-tick-badge.md b/docs/adr/0330-leftover-map-axis-tick-badge.md index 73a18f7c3..dd0122a01 100644 --- a/docs/adr/0330-leftover-map-axis-tick-badge.md +++ b/docs/adr/0330-leftover-map-axis-tick-badge.md @@ -102,7 +102,9 @@ coordinate ticks on the leftover-map graphic ([ADR 0270](0270-leftover-map-coord 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 leftover-map axis tick leftover-map axis share independently of leftover-map -singular values ([ADR 0332](0332-leftover-map-plot-tick-share-badge.md)). +singular values ([ADR 0332](0332-leftover-map-plot-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)). ## References diff --git a/docs/adr/0331-leftover-map-compare-plot-tick-share-badge.md b/docs/adr/0331-leftover-map-compare-plot-tick-share-badge.md index f4389071f..208e9df4e 100644 --- a/docs/adr/0331-leftover-map-compare-plot-tick-share-badge.md +++ b/docs/adr/0331-leftover-map-compare-plot-tick-share-badge.md @@ -140,7 +140,9 @@ coordinate ticks on the grouping comparison leftover-map graphic ([ADR 0320](0320-leftover-map-compare-plot-ticks.md)). Independent of leftover-map axis share persistence ([ADR 0148](0148-leftover-map-axis-share.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)). +singular values ([ADR 0332](0332-leftover-map-plot-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)). ## References diff --git a/docs/adr/0332-leftover-map-plot-tick-share-badge.md b/docs/adr/0332-leftover-map-plot-tick-share-badge.md index a2f0691d2..1d860ae89 100644 --- a/docs/adr/0332-leftover-map-plot-tick-share-badge.md +++ b/docs/adr/0332-leftover-map-plot-tick-share-badge.md @@ -16,7 +16,9 @@ singular values ([ADR 0331](0331-leftover-map-compare-plot-tick-share-badge.md)) comparison leftover-axis tick leftover-map singular values independently of leftover-map axis share ([ADR 0329](0329-leftover-map-compare-axis-tick-badge.md)). Independent of leftover-axis tick leftover-map singular values independently of leftover-map axis share -([ADR 0330](0330-leftover-map-axis-tick-badge.md)). +([ADR 0330](0330-leftover-map-axis-tick-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)). ## Context @@ -136,7 +138,9 @@ graphic leftover-map axis leftover-map singular values as leftoverMapPlotAxisBad ([ADR 0324](0324-leftover-map-plot-axis-singular.md)). Independent of leftover-map coordinate ticks on the leftover-map graphic ([ADR 0270](0270-leftover-map-coordinate-ticks.md)). Independent of leftover-map -axis share persistence ([ADR 0148](0148-leftover-map-axis-share.md)). +axis share persistence ([ADR 0148](0148-leftover-map-axis-share.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)). ## References diff --git a/docs/adr/0333-leftover-map-compare-axis-tick-share-badge.md b/docs/adr/0333-leftover-map-compare-axis-tick-share-badge.md new file mode 100644 index 000000000..be9da06ac --- /dev/null +++ b/docs/adr/0333-leftover-map-compare-axis-tick-share-badge.md @@ -0,0 +1,132 @@ +# ADR 0333 — Name leftover-map axis share on leftover-map comparison leftover-axis ticks independently of leftover-map singular values + +**Decision status:** Accepted +**Date:** 2026-08-31 + +Amends leftover-map comparison leftover-axis tick leftover-map singular +values independently of leftover-map axis share +([ADR 0329](0329-leftover-map-compare-axis-tick-badge.md)), leftover-map +axis share persistence ([ADR 0148](0148-leftover-map-axis-share.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-axis +tick leftover-map singular values independently of leftover-map axis share +([ADR 0330](0330-leftover-map-axis-tick-badge.md)). + +## Context + +ADR 0148 already persists leftover-map singular values `σ_k` and leftover-map +axis share `σ_k² / Σ_j σ_j²`. ADR 0329 already captions leftover-map comparison leftover-axis +ticks with `σ_k` through leftoverMapCompareAxisTickBadge independently of leftover-map +axis share. Those leftover-map comparison leftover-axis ticks still omit leftover-map +axis share, so a buyer who reads leftover-map comparison leftover-axis ticks can treat leftover-map +coordinate ticks or leftover-map singular values as leftover-map structure without +a next action. A missing or non-finite leftover-map axis share is not a leftover +score and must omit independently of leftover-map singular values. Rank-0 unused +axes still persist leftover-map axis share `0`. A finite negative leftover is +shown, never clamped. Do not invent leftover-map axis share from `σ_k`. Do not +invent `σ_k` from leftover-map axis share. Leftover-map graphic leftover-map axis +ticks already name leftover-map axis share (ADR 0332). Leftover-map comparison graphic leftover-map +axis ticks already name leftover-map axis share (ADR 0331). Leftover-axis +ticks (ADR 0330) never name leftover-map axis share this increment. + +This increment names leftover-map comparison leftover-axis ticks leftover-map +axis share as leftoverMapCompareAxisTickBadge, matching leftoverMapCompareAxisBadge, +leftoverMapComparePlotTickAxisBadge leftover-map axis share, leftoverMapPlotTickAxisBadge leftover-map axis share, +and leftoverMapCompareAxisTickBadge leftover-map singular values. +Leftover-map comparison leftover-axis ticks stay +`leftover map comparison leftover axis {k} tick {value} {share}%` when leftover-map +axis share is finite and `σ_k` omits, and +`leftover map comparison leftover axis {k} tick {value} σ {singular} {share}%` +when both are finite, so they stay distinct from leftover-map graphic leftover-map axis ticks +`leftover-map axis {k} tick {value} σ {singular} {share}%` (ADR 0332), +from leftover-map comparison graphic leftover-map axis ticks +`leftover map comparison graphic leftover-map axis {k} tick {value} σ {singular} {share}%` (ADR 0331), +from leftover-map comparison leftover-axis `leftover map comparison leftover axis {k} {share}%` (ADR 0323), +from leftover-axis `leftover axis {k} {share}%` (ADR 0325), from leftover-axis ticks +`leftover axis {k} tick {value} σ {singular}` (ADR 0330), and from leftover-map comparison leftover-axis ticks +`leftover map comparison leftover axis {k} tick {value} σ {singular}` (ADR 0329). +It does not add columns. Do not invent a leftover score. Do not invent a theta. + +This protected increment uses **0333** so it does not collide with 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-axis tick leftover-map singular values independently of leftover-map axis share +(0330), leftover-map comparison leftover-axis tick leftover-map singular values independently of leftover-map axis share +(0329), leftover-map axis share persistence (0148), or the dashboard stacks. + +## Decision + +On leftover-map comparison leftover-axis ticks, caption leftover-map axis `k` +with persisted leftover-map axis share when leftoverMapCompareAxisTickBadge +returns a usable leftover-axis tick caption that includes that share. +Share and singular value omit independently through that helper: no `σ_k` and no +share keeps `leftover map comparison leftover axis {k} tick {value}`; +`σ_k` only is `leftover map comparison leftover axis {k} tick {value} σ {singular}`; +share only is `leftover map comparison leftover axis {k} tick {value} {share}%`; +both are `leftover map comparison leftover axis {k} tick {value} σ {singular} {share}%`. +A missing or non-finite leftover-map axis share omits that share tick caption and +keeps a usable leftover-map comparison leftover-axis tick coordinate caption, +including any leftover-map singular value. Rank-0 unused axes still name leftover-map +axis share `0%`. Click a leftover pair to open that post. + +Leftover-map comparison leftover-axis tick leftover-map axis share omits +independently of leftover-map graphic leftover-map axis tick leftover-map axis share, +leftover-map comparison graphic leftover-map axis tick leftover-map axis share, leftover-axis +tick leftover-map singular values, leftover-map comparison leftover-axis leftover-map axis share, +and leftover-axis report badge leftover-map axis share. A missing leftover-map singular value omits leftover-map singular +values and keeps a usable leftover-map comparison leftover-axis tick leftover-map +axis share caption. + +This increment does not change leftover-axis ticks. Those leftover-axis +ticks stay `leftover axis {axis} tick {value}` and +`leftover axis {axis} tick {value} σ {singular}` (ADR 0330). This increment does not change leftover-map +graphic leftover-map 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 leftover-axis ticks name persisted +leftover-map axis share when leftoverMapCompareAxisTickBadge returns a usable +leftover-axis tick leftover-map axis share caption even when leftover-map singular +values are omitted; click a leftover pair opens that post. Hidden posts stay hidden. Rank-0 unused +axes still name leftover-map comparison leftover-axis tick leftover-map axis share `0%`. 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 comparison leftover-axis tick leftover-map singular values independently of leftover-map axis share +(ADR 0329), leftover-axis tick leftover-map singular values independently of leftover-map axis share +(ADR 0330), leftover-map comparison leftover-axis leftover-map singular values (ADR 0323), leftover-axis report badge +leftover-map singular values independently of leftover-map axis share (ADR 0325), +and leftover-map graphic leftover-map axis ticks (ADR 0270) +remain. + +## Related + +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 +comparison leftover-axis tick leftover-map singular values independently of leftover-map axis share +([ADR 0329](0329-leftover-map-compare-axis-tick-badge.md)). Independent of leftover-axis +tick leftover-map singular values independently of leftover-map axis share +([ADR 0330](0330-leftover-map-axis-tick-badge.md)). Independent of leftover-map +singular values on leftover-axis report badges on the grouping comparison strip +([ADR 0323](0323-leftover-map-compare-axis-singular.md)). Independent of leftover-map +axis share persistence ([ADR 0148](0148-leftover-map-axis-share.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 a3e041a07..0ffba74fd 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -1,5 +1,26 @@ # Product & Technical Gap Baseline +> Exact-head loop overlay: 2026-08-31 14:35 KST. Protected `main` is +> `cb187cadee5fb6c46d8a944815ccc154a1e028d1`. Writes work. Do not +> self-approve. #873 leftover-map axis share on leftover-map graphic leftover-map +> axis ticks independently of leftover-map singular values (v2.89.0 / ADR 0332) is +> `923bcfe`, stacked on #872 @ `7bdc562`. Independent APPROVE is missing. Next +> buyer increment on this cycle: leftover-map comparison leftover-axis +> ticks naming persisted leftover-map axis share independently of leftover-map +> singular values (ADR 0333 / v2.90.0) delivered locally on +> `feat/leftover-map-compare-axis-tick-share-badge-v2900`. Caption persisted leftover-map +> axis share on leftover-map comparison leftover-axis ticks when leftoverMapCompareAxisTickBadge +> returns a usable leftover-axis tick leftover-map axis share caption even when leftover-map +> singular values omit. Distinct accessible names +> `leftover map comparison leftover axis {axis} tick {value} {share}%` and +> `leftover map comparison leftover axis {axis} tick {value} σ {singular} {share}%`. +> Rank-0 unused axes still name leftover-map axis share `0%`. Share omits independently of +> leftover-map singular values. Leftover-axis ticks never name leftover-map axis share this +> increment. Do not invent leftover-map axis share from `σ_k`. Do not invent `σ_k` from leftover-map +> axis share. Do not persist leftover-map inner product, cosine, or length. Stack onto #873. +> 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 14:11 KST. Protected `main` is > `cb187cadee5fb6c46d8a944815ccc154a1e028d1`. Writes work. Do not > self-approve. #872 leftover-map axis share on leftover-map comparison graphic leftover-map diff --git a/frontend/package.json b/frontend/package.json index 2742a5cce..51b467928 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "frontend", "private": true, - "version": "2.89.0", + "version": "2.90.0", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/src/App.test.tsx b/frontend/src/App.test.tsx index 285b6033a..694667c64 100644 --- a/frontend/src/App.test.tsx +++ b/frontend/src/App.test.tsx @@ -4183,10 +4183,10 @@ describe("App, authenticated", () => { expect(screen.queryByText("leftover axis 2 σ 0.86")).not.toBeInTheDocument(); expect(screen.getByText("leftover map comparison leftover axis 1 σ 1.84 82%")).toBeInTheDocument(); expect(screen.getByText("leftover map comparison leftover axis 2 σ 0.86 18%")).toBeInTheDocument(); - expect(screen.getByText("leftover map comparison leftover axis 1 tick +0.50 σ 1.84")).toBeInTheDocument(); - expect(screen.getByText("leftover map comparison leftover axis 2 tick −0.02 σ 0.86")).toBeInTheDocument(); - expect(screen.getByText("leftover map comparison leftover axis 1 tick 0.00 σ 1.84")).toBeInTheDocument(); - expect(screen.getByText("leftover map comparison leftover axis 2 tick 0.00 σ 0.86")).toBeInTheDocument(); + expect(screen.getByText("leftover map comparison leftover axis 1 tick +0.50 σ 1.84 82%")).toBeInTheDocument(); + expect(screen.getByText("leftover map comparison leftover axis 2 tick −0.02 σ 0.86 18%")).toBeInTheDocument(); + expect(screen.getByText("leftover map comparison leftover axis 1 tick 0.00 σ 1.84 82%")).toBeInTheDocument(); + expect(screen.getByText("leftover map comparison leftover axis 2 tick 0.00 σ 0.86 18%")).toBeInTheDocument(); expect(screen.getByText("leftover axis 1 tick +0.50 σ 1.84")).toBeInTheDocument(); expect(screen.getByText("leftover axis 2 tick −0.02 σ 0.86")).toBeInTheDocument(); expect(screen.getByText("leftover axis 1 tick 0.00 σ 1.84")).toBeInTheDocument(); @@ -4373,22 +4373,22 @@ describe("App, authenticated", () => { ).toBeInTheDocument(); expect( within(screen.getByLabelText("Grouping comparison")).getByText( - "leftover map comparison leftover axis 1 tick +0.50 σ 1.84", + "leftover map comparison leftover axis 1 tick +0.50 σ 1.84 82%", ), ).toBeInTheDocument(); expect( within(screen.getByLabelText("Grouping comparison")).getByText( - "leftover map comparison leftover axis 2 tick −0.02 σ 0.86", + "leftover map comparison leftover axis 2 tick −0.02 σ 0.86 18%", ), ).toBeInTheDocument(); expect( within(screen.getByLabelText("Grouping comparison")).getByText( - "leftover map comparison leftover axis 1 tick 0.00 σ 1.84", + "leftover map comparison leftover axis 1 tick 0.00 σ 1.84 82%", ), ).toBeInTheDocument(); expect( within(screen.getByLabelText("Grouping comparison")).getByText( - "leftover map comparison leftover axis 2 tick 0.00 σ 0.86", + "leftover map comparison leftover axis 2 tick 0.00 σ 0.86 18%", ), ).toBeInTheDocument(); expect( @@ -4396,6 +4396,11 @@ describe("App, authenticated", () => { "leftover axis 1 tick +0.50 σ 1.84", ), ).not.toBeInTheDocument(); + expect( + within(screen.getByLabelText("Grouping comparison")).queryByText( + "leftover map comparison leftover axis 1 tick +0.50 σ 1.84", + ), + ).not.toBeInTheDocument(); expect( within(screen.getByLabelText("Grouping comparison")).queryByText( /leftover map comparison leftover axis 1 tick \+0\.50 82%/, @@ -4756,12 +4761,12 @@ describe("App, authenticated", () => { ).not.toBeInTheDocument(); expect( within(screen.getByLabelText("Grouping comparison")).getByText( - "leftover map comparison leftover axis 1 tick +0.50 σ 1.84", + "leftover map comparison leftover axis 1 tick +0.50 σ 1.84 82%", ), ).toBeInTheDocument(); expect( within(screen.getByLabelText("Grouping comparison")).queryByLabelText( - "leftover map comparison leftover axis 1 tick +0.50 σ 1.84", + "leftover map comparison leftover axis 1 tick +0.50 σ 1.84 82%", ), ).not.toBeInTheDocument(); expect( diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index e4558d4e5..ec8a1b3ee 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -4159,6 +4159,7 @@ function ReportsPanel({ tick.axis, tick.label, leftoverSingularForAxis(row.leftover_map_axes, tick.axis), + leftoverShareForAxis(row.leftover_map_axes, tick.axis), ); return ( diff --git a/frontend/src/i18n.test.ts b/frontend/src/i18n.test.ts index f984daf03..abb973607 100644 --- a/frontend/src/i18n.test.ts +++ b/frontend/src/i18n.test.ts @@ -124,6 +124,8 @@ describe("i18n", () => { "leftover map comparison leftover axis {axis} {share}%", "leftover map comparison leftover axis {axis} tick {value}", "leftover map comparison leftover axis {axis} tick {value} σ {singular}", + "leftover map comparison leftover axis {axis} tick {value} {share}%", + "leftover map comparison leftover axis {axis} tick {value} σ {singular} {share}%", "Leftover map comparison leftover axis", "Leftover map comparison leftover-axis share is Gabriel inertia of residual SVD axes 1 and 2. Open a leftover pair to read the post–criterion cell. The shares do not invent a leftover score.", "Leftover map comparison coordinates", @@ -910,6 +912,45 @@ describe("i18n", () => { }, ); + it.each([ + ["ko", "잔여 지도 비교 잔차 축 1 눈금 +0.50 82%"], + ["zh", "残差地图比较残差轴 1 刻度 +0.50 82%"], + ["ja", "残差マップの比較残差軸 1 目盛 +0.50 82%"], + ["vi", "vạch trục phần dư so sánh bản đồ phần dư 1 +0.50 82%"], + ] as const)( + "formats leftover map comparison leftover-axis tick leftover-map axis share in %s", + (locale, expected) => { + setLocale(locale); + expect( + tf("leftover map comparison leftover axis {axis} tick {value} {share}%", { + axis: 1, + value: "+0.50", + share: "82", + }), + ).toBe(expected); + }, + ); + + it.each([ + ["ko", "잔여 지도 비교 잔차 축 1 눈금 +0.50 σ 1.84 82%"], + ["zh", "残差地图比较残差轴 1 刻度 +0.50 σ 1.84 82%"], + ["ja", "残差マップの比較残差軸 1 目盛 +0.50 σ 1.84 82%"], + ["vi", "vạch trục phần dư so sánh bản đồ phần dư 1 +0.50 σ 1.84 82%"], + ] as const)( + "formats leftover map comparison leftover-axis tick leftover-map singular values and leftover-map axis share in %s", + (locale, expected) => { + setLocale(locale); + expect( + tf("leftover map comparison leftover axis {axis} tick {value} σ {singular} {share}%", { + axis: 1, + value: "+0.50", + singular: "1.84", + share: "82", + }), + ).toBe(expected); + }, + ); + it.each([ ["ko", "잔여 지도 비교 잔차 축 1 σ 1.84 82%"], ["zh", "残差地图比较残差轴 1 σ 1.84 82%"], diff --git a/frontend/src/i18n.ts b/frontend/src/i18n.ts index edf1a927c..44d4906e5 100644 --- a/frontend/src/i18n.ts +++ b/frontend/src/i18n.ts @@ -313,6 +313,10 @@ const TRANSLATIONS: Partial>> = { "leftover map comparison leftover axis {axis} tick {value}": "잔여 지도 비교 잔차 축 {axis} 눈금 {value}", "leftover map comparison leftover axis {axis} tick {value} σ {singular}": "잔여 지도 비교 잔차 축 {axis} 눈금 {value} σ {singular}", + "leftover map comparison leftover axis {axis} tick {value} {share}%": + "잔여 지도 비교 잔차 축 {axis} 눈금 {value} {share}%", + "leftover map comparison leftover axis {axis} tick {value} σ {singular} {share}%": + "잔여 지도 비교 잔차 축 {axis} 눈금 {value} σ {singular} {share}%", "Leftover map comparison leftover axis": "잔여 지도 비교 잔차 축", "Leftover map comparison leftover-axis share is Gabriel inertia of residual SVD axes 1 and 2. Open a leftover pair to read the post–criterion cell. The shares do not invent a leftover score.": "잔여 지도 비교 잔차 축 비율은 잔차 SVD 축 1과 2의 Gabriel 관성입니다. 글–기준 셀을 읽으려면 잔차 쌍을 여세요. 이 비율은 잔차 점수를 만들어내지 않습니다.", @@ -985,6 +989,10 @@ const TRANSLATIONS: Partial>> = { "leftover map comparison leftover axis {axis} tick {value}": "残差地图比较残差轴 {axis} 刻度 {value}", "leftover map comparison leftover axis {axis} tick {value} σ {singular}": "残差地图比较残差轴 {axis} 刻度 {value} σ {singular}", + "leftover map comparison leftover axis {axis} tick {value} {share}%": + "残差地图比较残差轴 {axis} 刻度 {value} {share}%", + "leftover map comparison leftover axis {axis} tick {value} σ {singular} {share}%": + "残差地图比较残差轴 {axis} 刻度 {value} σ {singular} {share}%", "Leftover map comparison leftover axis": "残差地图比较残差轴", "Leftover map comparison leftover-axis share is Gabriel inertia of residual SVD axes 1 and 2. Open a leftover pair to read the post–criterion cell. The shares do not invent a leftover score.": "残差地图比较残差轴份额是残差 SVD 轴 1 和 2 的 Gabriel 惯性。打开残差对以阅读帖文–准则单元格。这些份额不编造残差分数。", @@ -1678,6 +1686,10 @@ const TRANSLATIONS: Partial>> = { "leftover map comparison leftover axis {axis} tick {value}": "残差マップの比較残差軸 {axis} 目盛 {value}", "leftover map comparison leftover axis {axis} tick {value} σ {singular}": "残差マップの比較残差軸 {axis} 目盛 {value} σ {singular}", + "leftover map comparison leftover axis {axis} tick {value} {share}%": + "残差マップの比較残差軸 {axis} 目盛 {value} {share}%", + "leftover map comparison leftover axis {axis} tick {value} σ {singular} {share}%": + "残差マップの比較残差軸 {axis} 目盛 {value} σ {singular} {share}%", "Leftover map comparison leftover axis": "残差マップの比較残差軸", "Leftover map comparison leftover-axis share is Gabriel inertia of residual SVD axes 1 and 2. Open a leftover pair to read the post–criterion cell. The shares do not invent a leftover score.": "残差マップの比較残差軸の割合は残差 SVD 軸 1 と 2 の Gabriel 慣性です。投稿–基準セルを読むには残差ペアを開いてください。この割合は残差スコアを作りません。", @@ -2354,6 +2366,10 @@ const TRANSLATIONS: Partial>> = { "vạch trục phần dư so sánh bản đồ phần dư {axis} {value}", "leftover map comparison leftover axis {axis} tick {value} σ {singular}": "vạch trục phần dư so sánh bản đồ phần dư {axis} {value} σ {singular}", + "leftover map comparison leftover axis {axis} tick {value} {share}%": + "vạch trục phần dư so sánh bản đồ phần dư {axis} {value} {share}%", + "leftover map comparison leftover axis {axis} tick {value} σ {singular} {share}%": + "vạch trục phần dư so sánh bản đồ phần dư {axis} {value} σ {singular} {share}%", "Leftover map comparison leftover axis": "Trục phần dư so sánh bản đồ phần dư", "Leftover map comparison leftover-axis share is Gabriel inertia of residual SVD axes 1 and 2. Open a leftover pair to read the post–criterion cell. The shares do not invent a leftover score.": "Tỷ phần trục phần dư so sánh bản đồ phần dư là quán tính Gabriel của trục SVD phần dư 1 và 2. Mở cặp phần dư để đọc ô bài–tiêu chí. Các tỷ phần này không tạo ra điểm phần dư.", diff --git a/frontend/src/leftoverMapAxisBadge.test.ts b/frontend/src/leftoverMapAxisBadge.test.ts index dc1331d99..751dd5b04 100644 --- a/frontend/src/leftoverMapAxisBadge.test.ts +++ b/frontend/src/leftoverMapAxisBadge.test.ts @@ -195,6 +195,9 @@ describe("leftover-axis leftover-axis tick leftover-map singular values", () => expect(leftoverMapAxisTickBadge(1, "+0.50", 1.84).key).not.toBe( leftoverMapCompareAxisTickBadge(1, "+0.50", 1.84).key, ); + expect(leftoverMapAxisTickBadge(1, "+0.50", 1.84).key).not.toBe( + leftoverMapCompareAxisTickBadge(1, "+0.50", 1.84, 0.82).key, + ); expect(leftoverMapAxisTickBadge(1, "+0.50", 1.84).key).not.toBe( leftoverMapPlotTickAxisBadge(1, "+0.50", 1.84).key, ); diff --git a/frontend/src/leftoverMapAxisBadge.ts b/frontend/src/leftoverMapAxisBadge.ts index 8dec811fa..a0b97bf4d 100644 --- a/frontend/src/leftoverMapAxisBadge.ts +++ b/frontend/src/leftoverMapAxisBadge.ts @@ -18,6 +18,8 @@ * axis share as leftoverMapComparePlotTickAxisBadge, not this helper. * ADR 0332 captions leftover-map graphic leftover-map axis ticks leftover-map * axis share as leftoverMapPlotTickAxisBadge, not this helper. + * ADR 0333 captions leftover-map comparison leftover-axis ticks leftover-map + * axis share as leftoverMapCompareAxisTickBadge, not this helper. */ import type { LeftoverMapAxis } from "./api"; diff --git a/frontend/src/leftoverMapPlotAxisSingular.test.ts b/frontend/src/leftoverMapPlotAxisSingular.test.ts index cc2daf1df..ad5168165 100644 --- a/frontend/src/leftoverMapPlotAxisSingular.test.ts +++ b/frontend/src/leftoverMapPlotAxisSingular.test.ts @@ -14,7 +14,9 @@ import { LEFTOVER_MAP_COMPARE_AXIS_SINGULAR, LEFTOVER_MAP_COMPARE_AXIS_SINGULAR_SHARE, LEFTOVER_MAP_COMPARE_AXIS_TICK, + LEFTOVER_MAP_COMPARE_AXIS_TICK_SHARE, LEFTOVER_MAP_COMPARE_AXIS_TICK_SINGULAR, + LEFTOVER_MAP_COMPARE_AXIS_TICK_SINGULAR_SHARE, LEFTOVER_MAP_COMPARE_PLOT_AXIS_SINGULAR, LEFTOVER_MAP_COMPARE_PLOT_AXIS_SINGULAR_SHARE, LEFTOVER_MAP_COMPARE_PLOT_TICK_SHARE, @@ -761,5 +763,113 @@ describe("leftover-map graphic leftover-map axis tick leftover-map axis share", expect(leftoverMapPlotTickAxisBadge(1, "+0.50", 1.84, 0.82).key).not.toBe( leftoverMapCompareAxisTickBadge(1, "+0.50", 1.84).key, ); + expect(leftoverMapPlotTickAxisBadge(1, "+0.50", 1.84, 0.82).key).not.toBe( + leftoverMapCompareAxisTickBadge(1, "+0.50", 1.84, 0.82).key, + ); + }); +}); + +describe("leftover-map comparison leftover-axis tick leftover-map axis share", () => { + it("names persisted leftover-map axis share on leftover-map comparison leftover-axis ticks independently of leftover-map singular values", () => { + expect(leftoverMapCompareAxisTickBadge(1, "+0.50", 1.84, 0.82)).toEqual({ + key: LEFTOVER_MAP_COMPARE_AXIS_TICK_SINGULAR_SHARE, + values: { axis: 1, value: "+0.50", singular: "1.84", share: "82" }, + }); + expect(leftoverMapCompareAxisTickBadge(2, "−0.02", 0.86, 0.18)).toEqual({ + key: LEFTOVER_MAP_COMPARE_AXIS_TICK_SINGULAR_SHARE, + values: { axis: 2, value: "−0.02", singular: "0.86", share: "18" }, + }); + }); + + it("names leftover-map axis share on leftover-map comparison leftover-axis ticks when leftover-map singular values omit", () => { + expect(leftoverMapCompareAxisTickBadge(1, "+0.50", Number.NaN, 0.82)).toEqual({ + key: LEFTOVER_MAP_COMPARE_AXIS_TICK_SHARE, + values: { axis: 1, value: "+0.50", share: "82" }, + }); + expect(leftoverMapCompareAxisTickBadge(2, "−0.02", -0.01, 0.18)).toEqual({ + key: LEFTOVER_MAP_COMPARE_AXIS_TICK_SHARE, + values: { axis: 2, value: "−0.02", share: "18" }, + }); + expect(leftoverMapCompareAxisTickBadge(1, "+0.50", null, 0.82).values.singular).toBeUndefined(); + }); + + it("names rank-0 zero leftover-map axis share on leftover-map comparison leftover-axis ticks", () => { + expect(leftoverMapCompareAxisTickBadge(1, "0.00", 0, 0)).toEqual({ + key: LEFTOVER_MAP_COMPARE_AXIS_TICK_SINGULAR_SHARE, + values: { axis: 1, value: "0.00", singular: "0.00", share: "0" }, + }); + expect(leftoverMapCompareAxisTickBadge(1, "0.00", null, 0)).toEqual({ + key: LEFTOVER_MAP_COMPARE_AXIS_TICK_SHARE, + values: { axis: 1, value: "0.00", share: "0" }, + }); + }); + + it("omits leftover-map axis share independently of leftover-map singular values", () => { + expect(leftoverMapCompareAxisTickBadge(1, "+0.50", 1.84, Number.NaN)).toEqual({ + key: LEFTOVER_MAP_COMPARE_AXIS_TICK_SINGULAR, + values: { axis: 1, value: "+0.50", singular: "1.84" }, + }); + expect(leftoverMapCompareAxisTickBadge(1, "+0.50", 1.84, null)).toEqual({ + key: LEFTOVER_MAP_COMPARE_AXIS_TICK_SINGULAR, + values: { axis: 1, value: "+0.50", singular: "1.84" }, + }); + expect(leftoverMapCompareAxisTickBadge(1, "+0.50", Number.NaN, Number.NaN)).toEqual({ + key: LEFTOVER_MAP_COMPARE_AXIS_TICK, + values: { axis: 1, value: "+0.50" }, + }); + }); + + it("does not invent leftover-map axis share from leftover-map singular values", () => { + expect(leftoverMapCompareAxisTickBadge(1, "+0.50", 1.84, undefined).key).toBe( + LEFTOVER_MAP_COMPARE_AXIS_TICK_SINGULAR, + ); + expect(leftoverMapCompareAxisTickBadge(1, "+0.50", 1.84, undefined).values.share).toBeUndefined(); + }); + + it("does not invent leftover-map singular values from leftover-map axis share", () => { + expect(leftoverMapCompareAxisTickBadge(1, "+0.50", undefined, 0.82).key).toBe( + LEFTOVER_MAP_COMPARE_AXIS_TICK_SHARE, + ); + expect(leftoverMapCompareAxisTickBadge(1, "+0.50", undefined, 0.82).values.singular).toBeUndefined(); + }); + + it("does not name leftover-map axis share on leftover-axis ticks", () => { + expect(leftoverMapCompareAxisTickBadge(1, "+0.50", 1.84, 0.82).key).not.toBe( + leftoverMapPlotTickAxisBadge(1, "+0.50", 1.84, 0.82).key, + ); + expect(leftoverMapCompareAxisTickBadge(1, "+0.50", 1.84, 0.82).key).not.toBe( + leftoverMapComparePlotTickAxisBadge(1, "+0.50", 1.84, 0.82).key, + ); + }); + + it("stays distinct from leftover-axis, leftover-map graphic axis, leftover-map graphic tick, leftover-map comparison graphic tick, and leftover-map comparison leftover-axis copy", () => { + expect(LEFTOVER_MAP_COMPARE_AXIS_TICK_SHARE).toBe( + "leftover map comparison leftover axis {axis} tick {value} {share}%", + ); + expect(LEFTOVER_MAP_COMPARE_AXIS_TICK_SINGULAR_SHARE).toBe( + "leftover map comparison leftover axis {axis} tick {value} σ {singular} {share}%", + ); + expect(LEFTOVER_MAP_COMPARE_AXIS_TICK_SHARE).not.toBe(LEFTOVER_MAP_COMPARE_AXIS_TICK); + expect(LEFTOVER_MAP_COMPARE_AXIS_TICK_SHARE).not.toBe(LEFTOVER_MAP_COMPARE_AXIS_TICK_SINGULAR); + expect(LEFTOVER_MAP_COMPARE_AXIS_TICK_SHARE).not.toBe(LEFTOVER_MAP_COMPARE_AXIS_TICK_SINGULAR_SHARE); + expect(LEFTOVER_MAP_COMPARE_AXIS_TICK_SINGULAR_SHARE).not.toBe(LEFTOVER_MAP_COMPARE_AXIS_TICK_SINGULAR); + expect(LEFTOVER_MAP_COMPARE_AXIS_TICK_SHARE).not.toBe(LEFTOVER_MAP_PLOT_TICK_SHARE); + expect(LEFTOVER_MAP_COMPARE_AXIS_TICK_SINGULAR_SHARE).not.toBe(LEFTOVER_MAP_PLOT_TICK_SINGULAR_SHARE); + expect(LEFTOVER_MAP_COMPARE_AXIS_TICK_SHARE).not.toBe(LEFTOVER_MAP_COMPARE_PLOT_TICK_SHARE); + expect(LEFTOVER_MAP_COMPARE_AXIS_TICK_SINGULAR_SHARE).not.toBe(LEFTOVER_MAP_COMPARE_PLOT_TICK_SINGULAR_SHARE); + expect(LEFTOVER_MAP_COMPARE_AXIS_TICK_SHARE).not.toBe(LEFTOVER_MAP_COMPARE_AXIS_SHARE); + expect(LEFTOVER_MAP_COMPARE_AXIS_TICK_SINGULAR_SHARE).not.toBe(LEFTOVER_MAP_COMPARE_AXIS_SINGULAR_SHARE); + expect(leftoverMapCompareAxisTickBadge(1, "+0.50", 1.84, 0.82).key).not.toBe( + leftoverMapCompareAxisBadge(1, 1.84, 0.82)?.key, + ); + expect(leftoverMapCompareAxisTickBadge(1, "+0.50", null, 0.82).key).not.toBe( + leftoverMapCompareAxisBadge(1, null, 0.82)?.key, + ); + expect(leftoverMapCompareAxisTickBadge(1, "+0.50", 1.84, 0.82).key).not.toBe( + leftoverMapComparePlotTickAxisBadge(1, "+0.50", 1.84, 0.82).key, + ); + expect(leftoverMapCompareAxisTickBadge(1, "+0.50", 1.84, 0.82).key).not.toBe( + leftoverMapPlotTickAxisBadge(1, "+0.50", 1.84, 0.82).key, + ); }); }); diff --git a/frontend/src/leftoverMapPlotAxisSingular.ts b/frontend/src/leftoverMapPlotAxisSingular.ts index a3487dc71..bf7947b5a 100644 --- a/frontend/src/leftoverMapPlotAxisSingular.ts +++ b/frontend/src/leftoverMapPlotAxisSingular.ts @@ -23,6 +23,9 @@ * ADR 0332 names leftover-map graphic leftover-map axis ticks leftover-map * axis share as leftoverMapPlotTickAxisBadge independently of leftover-map * singular values. + * ADR 0333 names leftover-map comparison leftover-axis ticks leftover-map + * axis share as leftoverMapCompareAxisTickBadge independently of leftover-map + * singular values. */ import type { LeftoverMapAxis } from "./api"; @@ -80,6 +83,12 @@ export const LEFTOVER_MAP_COMPARE_AXIS_TICK = export const LEFTOVER_MAP_COMPARE_AXIS_TICK_SINGULAR = "leftover map comparison leftover axis {axis} tick {value} σ {singular}"; +export const LEFTOVER_MAP_COMPARE_AXIS_TICK_SHARE = + "leftover map comparison leftover axis {axis} tick {value} {share}%"; + +export const LEFTOVER_MAP_COMPARE_AXIS_TICK_SINGULAR_SHARE = + "leftover map comparison leftover axis {axis} tick {value} σ {singular} {share}%"; + export const LEFTOVER_MAP_COMPARE_AXIS_LABEL = "Leftover map comparison leftover axis"; export const LEFTOVER_MAP_COMPARE_AXIS_CAPTION = @@ -251,13 +260,27 @@ export function leftoverMapCompareAxisTickBadge( axisIndex: number, tickLabel: string, leftoverSingular: number | null | undefined, + leftoverShare?: number | null, ): LeftoverMapCompareAxisBadge { const singular = formatLeftoverMapPlotAxisSingular(leftoverSingular); - if (singular === null) { + const percent = formatLeftoverMapPlotAxisShare(leftoverShare); + if (singular === null && percent === null) { return { key: LEFTOVER_MAP_COMPARE_AXIS_TICK, values: { axis: axisIndex, value: tickLabel } }; } + if (singular === null && percent !== null) { + return { + key: LEFTOVER_MAP_COMPARE_AXIS_TICK_SHARE, + values: { axis: axisIndex, value: tickLabel, share: percent }, + }; + } + if (singular !== null && percent === null) { + return { + key: LEFTOVER_MAP_COMPARE_AXIS_TICK_SINGULAR, + values: { axis: axisIndex, value: tickLabel, singular }, + }; + } return { - key: LEFTOVER_MAP_COMPARE_AXIS_TICK_SINGULAR, - values: { axis: axisIndex, value: tickLabel, singular }, + key: LEFTOVER_MAP_COMPARE_AXIS_TICK_SINGULAR_SHARE, + values: { axis: axisIndex, value: tickLabel, singular: singular as string, share: percent as string }, }; } diff --git a/frontend/src/leftoverMapPlotLayout.test.ts b/frontend/src/leftoverMapPlotLayout.test.ts index 1d6b80a1b..f7d2b8455 100644 --- a/frontend/src/leftoverMapPlotLayout.test.ts +++ b/frontend/src/leftoverMapPlotLayout.test.ts @@ -1394,6 +1394,12 @@ describe("leftover map comparison graphic labels", () => { expect(LEFTOVER_MAP_COMPARE_PLOT_TICK).not.toBe( "leftover map comparison leftover axis {axis} tick {value} σ {singular}", ); + expect(LEFTOVER_MAP_COMPARE_PLOT_TICK).not.toBe( + "leftover map comparison leftover axis {axis} tick {value} {share}%", + ); + expect(LEFTOVER_MAP_COMPARE_PLOT_TICK).not.toBe( + "leftover map comparison leftover axis {axis} tick {value} σ {singular} {share}%", + ); expect(LEFTOVER_MAP_COMPARE_PLOT_TICK).not.toBe("leftover axis {axis} tick {value}"); expect(LEFTOVER_MAP_COMPARE_PLOT_TICK).not.toBe("leftover axis {axis} tick {value} σ {singular}"); expect(LEFTOVER_MAP_COMPARE_PLOT_TICK).not.toBe( diff --git a/frontend/src/leftoverMapPlotLayout.ts b/frontend/src/leftoverMapPlotLayout.ts index 1422b5501..364ecc72c 100644 --- a/frontend/src/leftoverMapPlotLayout.ts +++ b/frontend/src/leftoverMapPlotLayout.ts @@ -109,6 +109,9 @@ * ADR 0332 fail-closes leftover-map graphic leftover-map axis ticks leftover-map * axis share through leftoverMapPlotTickAxisBadge independently of leftover-map * singular values. + * ADR 0333 fail-closes leftover-map comparison leftover-axis ticks leftover-map + * axis share through leftoverMapCompareAxisTickBadge independently of leftover-map + * singular values, not this graphic. */ import { formatLeftoverMapCoordinatePair } from "./leftoverMapCoordinates"; diff --git a/pyproject.toml b/pyproject.toml index c373ed6a1..4988f67c9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "lineageweave" -version = "2.89.0" +version = "2.90.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" }