diff --git a/AGENTS.md b/AGENTS.md index 154addfbc..2755bcd17 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -846,6 +846,11 @@ returns a leftover-map origin tick caption independently of leftover-map axis sh `leftover axis {axis} origin tick {value}`. Rank-0 unused axes still name leftover-map origin `0.00`. Share and singular omit independently. Do not invent leftover-map origin from leftover-map axis share or leftover-map singular values `σ_k`. leftoverMapPlotTickAxisBadge stays leftover-map graphic leftover-map axis origin tick keys. leftoverMapComparePlotTickAxisBadge stays leftover-map comparison graphic leftover-map axis origin tick keys. leftoverMapCompareAxisTickBadge stays leftover-map comparison leftover-axis origin tick keys this increment. +ADR 0347 captions leftover-map graphic leftover-map origin with leftover-map origin when leftoverMapPlotOriginBadge +returns a leftover-map origin caption independently of leftover-map axis origin ticks, leftover-map axis share, and leftover-map singular values. Distinct accessible name +`leftover-map origin {origin}`. Rank-0 unused axes still name leftover-map origin `(0.00, 0.00)`. +Do not invent leftover-map origin from leftover-map axis share or leftover-map singular values `σ_k`. leftoverMapPlotTickAxisBadge stays leftover-map graphic leftover-map +axis origin tick keys. leftoverMapComparePlotTickAxisBadge stays leftover-map comparison graphic leftover-map axis origin tick keys. leftoverMapCompareAxisTickBadge stays leftover-map comparison leftover-axis origin tick keys. leftoverMapAxisTickBadge stays leftover-map leftover-axis origin tick keys this increment. leftover-map comparison graphic leftover-map origin stays unnamed 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 @@ -1027,6 +1032,8 @@ Leftover-map comparison leftover-axis origin ticks independently of leftover-map (ADR 0345) captions leftover-map comparison leftover-axis origin ticks when leftoverMapCompareAxisTickBadge returns a leftover-map origin tick caption. Leftover-map leftover-axis origin ticks independently of leftover-map axis share and leftover-map singular values (ADR 0346) captions leftover-map leftover-axis origin ticks when leftoverMapAxisTickBadge returns a leftover-map origin tick caption. +Leftover-map graphic leftover-map origin independently of leftover-map axis origin ticks, leftover-map axis share, and leftover-map singular values +(ADR 0347) captions leftover-map graphic leftover-map origin when leftoverMapPlotOriginBadge returns a leftover-map origin 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 9a6d0a627..81a5d2ce0 100644 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -817,6 +817,8 @@ ADR 0345 captions leftover-map comparison leftover-axis origin ticks when leftov returns a leftover-map origin tick caption independently of leftover-map axis share and leftover-map singular values. ADR 0346 captions leftover-map leftover-axis origin ticks when leftoverMapAxisTickBadge returns a leftover-map origin tick caption independently of leftover-map axis share and leftover-map singular values. +ADR 0347 captions leftover-map graphic leftover-map origin when leftoverMapPlotOriginBadge +returns a leftover-map origin caption independently of leftover-map axis origin ticks, leftover-map axis share, and 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 diff --git a/CHANGELOG.d/2.104.0-leftover-map-plot-origin-badge.md b/CHANGELOG.d/2.104.0-leftover-map-plot-origin-badge.md new file mode 100644 index 000000000..358d639ee --- /dev/null +++ b/CHANGELOG.d/2.104.0-leftover-map-plot-origin-badge.md @@ -0,0 +1,12 @@ +## 2.104.0 — Leftover-map origin on leftover-map graphic independently of leftover-map axis origin ticks, leftover-map axis share, and leftover-map singular values + +- Caption leftover-map graphic leftover-map origin through leftoverMapPlotOriginBadge + independently of leftover-map axis origin ticks, leftover-map axis share, and leftover-map singular values (ADR 0347). After `make seed`, leftover-map graphic leftover-map + origin names leftover-map origin when leftoverMapPlotOriginBadge returns a usable leftover-map origin caption. Distinct accessible name + `leftover-map origin {origin}`. Rank-0 unused axes still name leftover-map origin `(0.00, 0.00)`. leftoverMapPlotTickAxisBadge stays leftover-map graphic leftover-map + axis origin tick keys. leftoverMapComparePlotTickAxisBadge stays leftover-map comparison graphic leftover-map + axis origin tick keys. leftoverMapCompareAxisTickBadge stays leftover-map comparison leftover-axis origin tick keys. + leftoverMapAxisTickBadge stays leftover-map leftover-axis origin tick keys this increment. leftover-map comparison graphic leftover-map origin stays unnamed this increment. + Do not invent leftover-map origin from leftover-map axis share or leftover-map singular values `σ_k`. + Do not mix #877. 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 6d8896f3e..f6dc4583e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,16 @@ All notable changes to this project are documented here. Format follows ### Added +- Period leftover pairs now caption leftover-map graphic leftover-map origin + through leftoverMapPlotOriginBadge independently of leftover-map axis origin ticks, leftover-map axis share, and leftover-map singular values (ADR 0347 / v2.104.0). After `make seed`, leftover-map graphic leftover-map + origin names leftover-map origin when leftoverMapPlotOriginBadge returns a usable leftover-map origin caption. Distinct accessible name + `leftover-map origin {origin}`. Rank-0 unused axes still name leftover-map origin `(0.00, 0.00)`. leftoverMapPlotTickAxisBadge stays leftover-map graphic leftover-map + axis origin tick keys. leftoverMapComparePlotTickAxisBadge stays leftover-map comparison graphic leftover-map + axis origin tick keys. leftoverMapCompareAxisTickBadge stays leftover-map comparison leftover-axis origin tick keys. + leftoverMapAxisTickBadge stays leftover-map leftover-axis origin tick keys this increment. leftover-map comparison graphic leftover-map origin stays unnamed this increment. + Do not invent leftover-map origin from leftover-map axis share or leftover-map singular values `σ_k`. + Do not mix #877. 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 leftover-axis origin ticks through leftoverMapAxisTickBadge independently of leftover-map axis share and leftover-map singular values (ADR 0346 / v2.103.0). After `make seed`, leftover-map leftover-axis origin ticks name leftover-map origin when leftoverMapPlotTickIsOrigin returns true. Distinct accessible name diff --git a/CLAUDE.md b/CLAUDE.md index 4c09ad523..6b92d1ddf 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 / 0336 / 0337 / 0338 / 0339 / 0340 / 0341 / 0342 / 0343 / 0344 / 0345 / 0346), 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 / 0337 / 0338 / 0339 / 0340 / 0341 / 0342 / 0343 / 0344 / 0345 / 0346 / 0347), 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/0343-leftover-map-plot-tick-origin-badge.md b/docs/adr/0343-leftover-map-plot-tick-origin-badge.md index f2c1f24c2..bff363731 100644 --- a/docs/adr/0343-leftover-map-plot-tick-origin-badge.md +++ b/docs/adr/0343-leftover-map-plot-tick-origin-badge.md @@ -4,7 +4,9 @@ **Date:** 2026-08-31 **Amended by:** [ADR 0344](0344-leftover-map-compare-plot-tick-origin-badge.md) -(leftover-map origin on leftover-map comparison graphic leftover-map axis ticks independently of leftover-map axis share and leftover-map singular values) +(leftover-map origin on leftover-map comparison graphic leftover-map axis ticks independently of leftover-map axis share and leftover-map singular values); +[ADR 0347](0347-leftover-map-plot-origin-badge.md) +(leftover-map origin on leftover-map graphic independently of leftover-map axis origin ticks, leftover-map axis share, and leftover-map singular values) Amends leftover-map coordinate ticks ([ADR 0270](0270-leftover-map-coordinate-ticks.md)), leftover-map graphic leftover-map axis ticks leftover-map singular values diff --git a/docs/adr/0346-leftover-map-axis-tick-origin-badge.md b/docs/adr/0346-leftover-map-axis-tick-origin-badge.md index 931b4d15d..c5eafcb2b 100644 --- a/docs/adr/0346-leftover-map-axis-tick-origin-badge.md +++ b/docs/adr/0346-leftover-map-axis-tick-origin-badge.md @@ -3,6 +3,9 @@ **Decision status:** Accepted **Date:** 2026-08-31 +**Amended by:** [ADR 0347](0347-leftover-map-plot-origin-badge.md) +(leftover-map origin on leftover-map graphic independently of leftover-map axis origin ticks, leftover-map axis share, and leftover-map singular values) + Amends leftover-axis ticks leftover-map singular values ([ADR 0330](0330-leftover-map-axis-tick-badge.md)) and leftover-axis ticks leftover-map axis share ([ADR 0334](0334-leftover-map-axis-tick-share-badge.md)). Independent of leftover-map diff --git a/docs/adr/0347-leftover-map-plot-origin-badge.md b/docs/adr/0347-leftover-map-plot-origin-badge.md new file mode 100644 index 000000000..6913b1b75 --- /dev/null +++ b/docs/adr/0347-leftover-map-plot-origin-badge.md @@ -0,0 +1,96 @@ +# ADR 0347 — Name leftover-map origin on leftover-map graphic independently of leftover-map axis origin ticks, leftover-map axis share, and leftover-map singular values + +**Decision status:** Proposed +**Date:** 2026-08-31 + +**Numbering status:** provisional conflict. ADR 0347 is also claimed by the active leftover-map criterion-origin stack (#891). This proposal was retargeted behind the current #917 stack after that collision was detected and MUST receive a new non-conflicting ADR/version identity during conflict-preserving reconstruction before it can become Accepted or merge. + +**Amended by:** none yet + +Amends leftover-map graphic leftover-map axis origin ticks independently of leftover-map axis share and leftover-map singular values +([ADR 0343](0343-leftover-map-plot-tick-origin-badge.md)). Independent of leftover-map leftover-axis origin ticks independently of leftover-map axis share and leftover-map singular values +([ADR 0346](0346-leftover-map-axis-tick-origin-badge.md)). Independent of leftover-map +comparison leftover-axis origin ticks independently of leftover-map axis share and leftover-map singular values +([ADR 0345](0345-leftover-map-compare-axis-tick-origin-badge.md)). Independent of leftover-map +comparison graphic leftover-map axis origin ticks independently of leftover-map axis share and leftover-map singular values +([ADR 0344](0344-leftover-map-compare-plot-tick-origin-badge.md)). Independent of leftover-map +comparison graphic leftover-map origin (do not mix #877). + +## Context + +ADR 0343 already names leftover-map graphic leftover-map axis origin ticks +`leftover-map axis {axis} origin tick {value}` when leftoverMapPlotTickIsOrigin returns true. +Rank-0 unused axes still persist leftover-map origin `0.00` +(`formatSignedLeftoverValue(0)` emits no plus). Leftover-map origin on leftover-map +graphic still interpolates leftover-map origin only through leftover-map axis origin tick keys. +Share and singular omit independently. A finite negative leftover is shown, +never clamped. Do not invent leftover-map origin from leftover-map axis share +or leftover-map singular values `σ_k`. leftoverMapComparePlotTickAxisBadge stays leftover-map comparison graphic leftover-map +axis origin tick keys from ADR 0344. leftoverMapCompareAxisTickBadge stays leftover-map comparison leftover-axis origin tick keys from ADR 0345. +leftoverMapAxisTickBadge stays leftover-map leftover-axis origin tick keys from ADR 0346. + +This increment proposes naming leftover-map graphic leftover-map origin as +leftoverMapPlotOriginBadge. Leftover-map graphic leftover-map origin stays +`leftover-map origin {origin}` +when leftoverMapPlotOriginBadge returns a usable leftover-map origin caption, so it stays distinct from leftover-map +graphic leftover-map axis origin ticks +`leftover-map axis {axis} origin tick {value}`, +leftover-map comparison graphic leftover-map axis origin ticks +`leftover map comparison graphic leftover-map axis {axis} origin tick {value}`, +leftover-map comparison leftover-axis origin ticks +`leftover map comparison leftover axis {axis} origin tick {value}`, +and leftover-map leftover-axis origin ticks +`leftover axis {axis} origin tick {value}`. +Rank-0 unused axes still name leftover-map origin `(0.00, 0.00)` +(`formatLeftoverMapCoordinatePair(0, 0)`). leftoverMapComparePlotOriginBadge stays unnamed +this increment. It does not add columns. Do not invent a leftover score. Do not invent a theta. + +The original branch allocated **0347**, but the live queue now contains a separate active ADR 0347 in #891 and its descendants. That allocation is therefore not authoritative. Preserve the feature delta, keep this decision Proposed, and renumber/version it only after reconstructing it on the current predecessor without overwriting intervening stack changes. + +## Decision + +On leftover-map graphic, caption leftover-map origin +when leftoverMapPlotOriginBadge returns a usable leftover-map origin caption. Rank-0 unused axes still name leftover-map +origin `(0.00, 0.00)`. Do not invent leftover-map origin from leftover-map axis share or leftover-map singular values `σ_k`. +leftoverMapPlotTickAxisBadge, leftoverMapComparePlotTickAxisBadge, leftoverMapCompareAxisTickBadge, and leftoverMapAxisTickBadge +do not change leftover-map origin naming this increment. leftover-map comparison graphic leftover-map origin stays unnamed this increment. + +Do not add SQL. Do not edit shipped migrations. Do not invent a leftover +score. Do not invent a theta. + +## Consequences + +After the proposal is reconstructed with a unique ADR/version identity and accepted, leftover-map graphic leftover-map origin names +leftover-map origin independently of leftover-map axis origin ticks, leftover-map axis share, and leftover-map +singular values. Rank-0 unused axes still name leftover-map origin `(0.00, 0.00)`. +leftoverMapPlotTickAxisBadge stays leftover-map graphic leftover-map axis origin tick keys. +leftoverMapComparePlotTickAxisBadge stays leftover-map comparison graphic leftover-map axis origin tick keys. +leftoverMapCompareAxisTickBadge stays leftover-map comparison leftover-axis origin tick keys. +leftoverMapAxisTickBadge stays leftover-map leftover-axis origin tick keys. +leftover-map graphic leftover-map axis origin ticks independently of leftover-map axis share and leftover-map +singular values (ADR 0343) remain. + +## Related + +Independent of leftover-map leftover-axis origin ticks independently of leftover-map +axis share and leftover-map singular values +([ADR 0346](0346-leftover-map-axis-tick-origin-badge.md)). Independent of leftover-map +comparison leftover-axis origin ticks independently of leftover-map axis share and leftover-map singular values +([ADR 0345](0345-leftover-map-compare-axis-tick-origin-badge.md)). Independent of leftover-map +comparison graphic leftover-map axis origin ticks independently of leftover-map axis share and leftover-map singular values +([ADR 0344](0344-leftover-map-compare-plot-tick-origin-badge.md)). Independent of leftover-map +graphic leftover-map axis origin ticks independently of leftover-map axis share and leftover-map singular values +([ADR 0343](0343-leftover-map-plot-tick-origin-badge.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 401b1b5ac..723509df8 100644 --- a/docs/product-technical-gap-baseline.md +++ b/docs/product-technical-gap-baseline.md @@ -1,5 +1,15 @@ # Product & Technical Gap Baseline +> Exact-head loop overlay: 2026-08-31 20:05 KST. Protected `main` is +> `cb187cadee5fb6c46d8a944815ccc154a1e028d1`. Writes work. Do not +> self-approve. #889 leftover-map leftover-axis origin ticks independently of leftover-map +> axis share and leftover-map singular values (v2.103.0 / ADR 0346) is +> `4bfb490`, stacked on #887 @ `7637fc8`. Independent APPROVE is missing (Devin COMMENT is +> not APPROVE). Next buyer increment on this cycle: leftover-map graphic leftover-map +> origin independently of leftover-map axis origin ticks, leftover-map axis share, and leftover-map singular values as leftoverMapPlotOriginBadge (ADR 0347 / v2.104.0) delivered locally on +> `feat/leftover-map-plot-origin-badge-v21040`. Distinct accessible name +> `leftover-map origin {origin}`. Rank-0 unused axes still name leftover-map origin `(0.00, 0.00)`. leftoverMapPlotTickAxisBadge stays leftover-map graphic leftover-map axis origin tick keys. leftoverMapComparePlotTickAxisBadge stays leftover-map comparison graphic leftover-map axis origin tick keys. leftoverMapCompareAxisTickBadge stays leftover-map comparison leftover-axis origin tick keys. leftoverMapAxisTickBadge stays leftover-map leftover-axis origin tick keys. leftover-map comparison graphic leftover-map origin stays unnamed this increment. Do not invent leftover-map origin from leftover-map axis share or `σ_k`. Do not mix #877. Stack onto #889. 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. + > Exact-head loop overlay: 2026-08-31 19:32 KST. Protected `main` is > `cb187cadee5fb6c46d8a944815ccc154a1e028d1`. Writes work. Do not > self-approve. #887 leftover-map comparison leftover-axis origin ticks independently of leftover-map diff --git a/frontend/package.json b/frontend/package.json index 9aed0741c..8401b2758 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,7 +1,7 @@ { "name": "frontend", "private": true, - "version": "2.103.0", + "version": "2.104.0", "type": "module", "scripts": { "dev": "vite", diff --git a/frontend/src/components/LeftoverMapPlot.css b/frontend/src/components/LeftoverMapPlot.css index 45bfe213e..4c63f9fb0 100644 --- a/frontend/src/components/LeftoverMapPlot.css +++ b/frontend/src/components/LeftoverMapPlot.css @@ -73,6 +73,10 @@ stroke-width: 1; } +.leftover-map-plot-origin circle { + fill: var(--color-text); +} + .leftover-map-plot-tick line { stroke: var(--color-text); stroke-width: 1; diff --git a/frontend/src/components/LeftoverMapPlot.test.tsx b/frontend/src/components/LeftoverMapPlot.test.tsx index ddde84b74..4cbb80eae 100644 --- a/frontend/src/components/LeftoverMapPlot.test.tsx +++ b/frontend/src/components/LeftoverMapPlot.test.tsx @@ -74,6 +74,7 @@ describe("LeftoverMapPlot", () => { expect(screen.getByLabelText("leftover-map axis 1 tick +0.50")).toBeInTheDocument(); expect(screen.getByLabelText("leftover-map axis 2 tick −0.02")).toBeInTheDocument(); expect(screen.getByLabelText("leftover-map axis 1 origin tick 0.00")).toBeInTheDocument(); + expect(screen.getByLabelText("leftover-map origin (0.00, 0.00)")).toBeInTheDocument(); expect(screen.getByLabelText("leftover-map distance d 0.12")).toBeInTheDocument(); expect(screen.getByLabelText("leftover-map distance d 1.84")).toBeInTheDocument(); expect(screen.getByLabelText("leftover-map reconstruction R̂ +0.25")).toBeInTheDocument(); @@ -2824,6 +2825,10 @@ describe("LeftoverMapPlot", () => { expect( screen.getByLabelText("leftover map comparison graphic leftover-map axis 1 origin tick 0.00 σ 1.84 82%"), ).toBeInTheDocument(); + expect(screen.queryByLabelText("leftover-map origin (0.00, 0.00)")).not.toBeInTheDocument(); + expect( + screen.queryByLabelText("leftover map comparison graphic leftover-map origin (0.00, 0.00)"), + ).not.toBeInTheDocument(); expect( screen.queryByLabelText("leftover map comparison graphic leftover-map axis 1 tick +0.50"), ).not.toBeInTheDocument(); diff --git a/frontend/src/components/LeftoverMapPlot.tsx b/frontend/src/components/LeftoverMapPlot.tsx index fd6aea44a..bdd22acb3 100644 --- a/frontend/src/components/LeftoverMapPlot.tsx +++ b/frontend/src/components/LeftoverMapPlot.tsx @@ -27,6 +27,7 @@ import { leftoverMapComparePlotAxisBadge, leftoverMapComparePlotTickAxisBadge, leftoverMapPlotAxisBadge, + leftoverMapPlotOriginBadge, leftoverMapPlotTickAxisBadge, leftoverSingularForAxis, } from "../leftoverMapPlotAxisSingular"; @@ -101,6 +102,17 @@ function leftoverMapPlotAxisText( return tf(badge.key, badge.values); } +function leftoverMapPlotOriginText(variant: LeftoverMapPlotVariant): string | null { + if (variant === "comparison") { + return null; + } + const badge = leftoverMapPlotOriginBadge(); + if (badge === null) { + return null; + } + return tf(badge.key, badge.values); +} + function leftoverMapPlotTickText( axisIndex: number, tickLabel: string, @@ -293,6 +305,9 @@ function leftoverMapPlotPostText( * ADR 0346 fail-closes leftover-map leftover-axis origin ticks through * leftoverMapAxisTickBadge independently of leftover-map axis share and leftover-map * singular values. + * ADR 0347 fail-closes leftover-map graphic leftover-map origin through + * leftoverMapPlotOriginBadge independently of leftover-map axis origin ticks, leftover-map + * axis share, and leftover-map singular values. * Never invent a leftover score. */ export function LeftoverMapPlot({ @@ -311,6 +326,7 @@ export function LeftoverMapPlot({ const itemCoverageCounts = leftoverMapItemCoverageCounts(leftoverMapCoverage); const incompletePostCount = leftoverMapIncompletePostCount(leftoverMapCoverage); const incompleteItemCount = leftoverMapIncompleteItemCount(leftoverMapCoverage); + const originLabel = leftoverMapPlotOriginText(variant); const openPost = (postId: string) => { const pair = firstPlottablePairForPost(pairs, postId); @@ -416,6 +432,11 @@ export function LeftoverMapPlot({ {leftoverMapPlotAxisText(2, leftoverMapAxes, variant)} + {originLabel !== null ? ( + + + + ) : null} {layout.ticks.map((tick) => ( { "leftover-map axis {axis} origin tick {value} σ {singular}", "leftover-map axis {axis} origin tick {value} {share}%", "leftover-map axis {axis} origin tick {value} σ {singular} {share}%", + "leftover-map origin {origin}", "leftover-map distance {label}", "leftover-map reconstruction {label}", "leftover-map explained leftover share {label}", @@ -1486,6 +1487,16 @@ describe("i18n", () => { }, ); + it.each([ + ["ko", "잔여 지도 원점 (0.00, 0.00)"], + ["zh", "残差图原点 (0.00, 0.00)"], + ["ja", "残差マップ原点 (0.00, 0.00)"], + ["vi", "gốc bản đồ phần dư (0.00, 0.00)"], + ] as const)("formats leftover-map graphic leftover-map origin in %s", (locale, expected) => { + setLocale(locale); + expect(tf("leftover-map origin {origin}", { origin: "(0.00, 0.00)" })).toBe(expected); + }); + it.each([ ["ko", "잔여 지도 거리 d 0.12"], ["zh", "残差图距离 d 0.12"], diff --git a/frontend/src/i18n.ts b/frontend/src/i18n.ts index cfb8a4160..d0f7357fd 100644 --- a/frontend/src/i18n.ts +++ b/frontend/src/i18n.ts @@ -716,6 +716,7 @@ const TRANSLATIONS: Partial>> = { "잔여 지도 축 {axis} 원점 눈금 {value} {share}%", "leftover-map axis {axis} origin tick {value} σ {singular} {share}%": "잔여 지도 축 {axis} 원점 눈금 {value} σ {singular} {share}%", + "leftover-map origin {origin}": "잔여 지도 원점 {origin}", "leftover-map distance {label}": "잔여 지도 거리 {label}", "leftover-map reconstruction {label}": "잔여 지도 재구성 {label}", "leftover-map explained leftover share {label}": "잔여 지도 설명 잔여 점유율 {label}", @@ -1434,6 +1435,7 @@ const TRANSLATIONS: Partial>> = { "残差图轴 {axis} 原点刻度 {value} {share}%", "leftover-map axis {axis} origin tick {value} σ {singular} {share}%": "残差图轴 {axis} 原点刻度 {value} σ {singular} {share}%", + "leftover-map origin {origin}": "残差图原点 {origin}", "leftover-map distance {label}": "残差图距离 {label}", "leftover-map reconstruction {label}": "残差图重建 {label}", "leftover-map explained leftover share {label}": "残差图已解释残差份额 {label}", @@ -2156,6 +2158,7 @@ const TRANSLATIONS: Partial>> = { "残差マップ軸 {axis} 原点目盛 {value} {share}%", "leftover-map axis {axis} origin tick {value} σ {singular} {share}%": "残差マップ軸 {axis} 原点目盛 {value} σ {singular} {share}%", + "leftover-map origin {origin}": "残差マップ原点 {origin}", "leftover-map distance {label}": "残差マップ距離 {label}", "leftover-map reconstruction {label}": "残差マップ再構成 {label}", "leftover-map explained leftover share {label}": "残差マップ説明済み残差割合 {label}", @@ -2883,6 +2886,7 @@ const TRANSLATIONS: Partial>> = { "vạch gốc trục bản đồ phần dư {axis} {value} {share}%", "leftover-map axis {axis} origin tick {value} σ {singular} {share}%": "vạch gốc trục bản đồ phần dư {axis} {value} σ {singular} {share}%", + "leftover-map origin {origin}": "gốc bản đồ phần dư {origin}", "leftover-map distance {label}": "khoảng cách bản đồ phần dư {label}", "leftover-map reconstruction {label}": "tái dựng bản đồ phần dư {label}", "leftover-map explained leftover share {label}": "phần dư giải thích bản đồ phần dư {label}", diff --git a/frontend/src/leftoverMapAxisBadge.ts b/frontend/src/leftoverMapAxisBadge.ts index 76f74bdf2..eb0820ed1 100644 --- a/frontend/src/leftoverMapAxisBadge.ts +++ b/frontend/src/leftoverMapAxisBadge.ts @@ -30,6 +30,8 @@ * leftoverMapCompareAxisTickBadge, not this helper. * ADR 0346 names leftover-map leftover-axis origin ticks as leftoverMapAxisTickBadge * independently of leftover-map axis share and leftover-map singular values. + * ADR 0347 captions leftover-map graphic leftover-map origin as leftoverMapPlotOriginBadge, + * not this helper. */ import type { LeftoverMapAxis } from "./api"; diff --git a/frontend/src/leftoverMapPlotAxisSingular.test.ts b/frontend/src/leftoverMapPlotAxisSingular.test.ts index ba519a87e..ca922ede2 100644 --- a/frontend/src/leftoverMapPlotAxisSingular.test.ts +++ b/frontend/src/leftoverMapPlotAxisSingular.test.ts @@ -6,6 +6,7 @@ import { leftoverMapComparePlotAxisBadge, leftoverMapComparePlotTickAxisBadge, leftoverMapPlotAxisBadge, + leftoverMapPlotOriginBadge, leftoverMapPlotTickAxisBadge, leftoverMapPlotTickIsOrigin, leftoverSingularForAxis, @@ -33,6 +34,7 @@ import { LEFTOVER_MAP_COMPARE_PLOT_ORIGIN_TICK_SINGULAR_SHARE, LEFTOVER_MAP_PLOT_AXIS_SINGULAR, LEFTOVER_MAP_PLOT_AXIS_SINGULAR_SHARE, + LEFTOVER_MAP_PLOT_ORIGIN, LEFTOVER_MAP_PLOT_ORIGIN_TICK, LEFTOVER_MAP_PLOT_ORIGIN_TICK_SHARE, LEFTOVER_MAP_PLOT_ORIGIN_TICK_SINGULAR, @@ -1030,3 +1032,46 @@ describe("leftover-map comparison leftover-axis tick leftover-map axis share", ( ); }); }); + +describe("leftover-map graphic leftover-map origin independently of leftover-map axis origin ticks", () => { + it("names leftover-map origin independently of leftover-map axis share and leftover-map singular values", () => { + expect(leftoverMapPlotOriginBadge()).toEqual({ + key: LEFTOVER_MAP_PLOT_ORIGIN, + values: { origin: "(0.00, 0.00)" }, + }); + }); + + it("names rank-0 leftover-map origin (0.00, 0.00)", () => { + expect(leftoverMapPlotOriginBadge()?.values.origin).toBe("(0.00, 0.00)"); + }); + + it("does not invent leftover-map origin from leftover-map axis share or leftover-map singular values", () => { + expect(leftoverMapPlotOriginBadge()?.values).toEqual({ origin: "(0.00, 0.00)" }); + expect(leftoverMapPlotOriginBadge()?.key).toBe(LEFTOVER_MAP_PLOT_ORIGIN); + }); + + it("stays distinct from leftover-map graphic leftover-map axis origin ticks, leftover-map comparison graphic leftover-map axis origin ticks, leftover-map comparison leftover-axis origin ticks, and leftover-axis origin ticks", () => { + expect(LEFTOVER_MAP_PLOT_ORIGIN).toBe("leftover-map origin {origin}"); + expect(LEFTOVER_MAP_PLOT_ORIGIN).not.toBe(LEFTOVER_MAP_PLOT_ORIGIN_TICK); + expect(LEFTOVER_MAP_PLOT_ORIGIN).not.toBe(LEFTOVER_MAP_COMPARE_PLOT_ORIGIN_TICK); + expect(LEFTOVER_MAP_PLOT_ORIGIN).not.toBe(LEFTOVER_MAP_COMPARE_AXIS_ORIGIN_TICK); + expect(leftoverMapPlotOriginBadge()?.key).not.toBe( + leftoverMapPlotTickAxisBadge(1, "0.00", null).key, + ); + expect(leftoverMapPlotOriginBadge()?.key).not.toBe( + leftoverMapPlotTickAxisBadge(1, "0.00", 0, 0).key, + ); + expect(leftoverMapPlotOriginBadge()?.key).not.toBe( + leftoverMapComparePlotTickAxisBadge(1, "0.00", null).key, + ); + expect(leftoverMapPlotOriginBadge()?.key).not.toBe( + leftoverMapCompareAxisTickBadge(1, "0.00", null).key, + ); + expect(leftoverMapPlotOriginBadge()?.key).not.toBe( + leftoverMapAxisTickBadge(1, "0.00", null).key, + ); + expect(leftoverMapPlotOriginBadge()?.key).not.toBe( + leftoverMapPlotAxisBadge(1, 0, 0)?.key, + ); + }); +}); diff --git a/frontend/src/leftoverMapPlotAxisSingular.ts b/frontend/src/leftoverMapPlotAxisSingular.ts index 344bbdea7..657161fbc 100644 --- a/frontend/src/leftoverMapPlotAxisSingular.ts +++ b/frontend/src/leftoverMapPlotAxisSingular.ts @@ -40,9 +40,13 @@ * leftover-map singular values. * ADR 0346 names leftover-map leftover-axis origin ticks as leftoverMapAxisTickBadge * independently of leftover-map axis share and leftover-map singular values. + * ADR 0347 names leftover-map graphic leftover-map origin as leftoverMapPlotOriginBadge + * independently of leftover-map axis origin ticks, leftover-map axis share, and leftover-map + * singular values. */ import type { LeftoverMapAxis } from "./api"; +import { formatLeftoverMapCoordinatePair } from "./leftoverMapCoordinates"; import { formatLeftoverMapPlotAxisShare, LEFTOVER_MAP_COMPARE_PLOT_AXIS_SHARE, @@ -107,6 +111,8 @@ export const LEFTOVER_MAP_COMPARE_PLOT_ORIGIN_TICK_SHARE = export const LEFTOVER_MAP_COMPARE_PLOT_ORIGIN_TICK_SINGULAR_SHARE = "leftover map comparison graphic leftover-map axis {axis} origin tick {value} σ {singular} {share}%"; +export const LEFTOVER_MAP_PLOT_ORIGIN = "leftover-map origin {origin}"; + export const LEFTOVER_MAP_COMPARE_AXIS_SINGULAR = "leftover map comparison leftover axis {axis} σ {value}"; @@ -155,6 +161,11 @@ export type LeftoverMapCompareAxisBadge = { values: { axis: number; value?: string; share?: string; singular?: string }; }; +export type LeftoverMapPlotOriginBadge = { + key: string; + values: { origin: string }; +}; + export function leftoverSingularForAxis( axes: ReadonlyArray | null | undefined, axisIndex: number, @@ -185,6 +196,14 @@ export function leftoverMapPlotTickIsOrigin(tickLabel: string): boolean { return originLabel !== null && tickLabel === originLabel; } +export function leftoverMapPlotOriginBadge(): LeftoverMapPlotOriginBadge | null { + const origin = formatLeftoverMapCoordinatePair(0, 0); + if (origin === null) { + return null; + } + return { key: LEFTOVER_MAP_PLOT_ORIGIN, values: { origin } }; +} + export function leftoverMapPlotAxisBadge( axisIndex: number, leftoverSingular: number | null | undefined, diff --git a/frontend/src/leftoverMapPlotLayout.ts b/frontend/src/leftoverMapPlotLayout.ts index 3acd106c4..0c2c77afa 100644 --- a/frontend/src/leftoverMapPlotLayout.ts +++ b/frontend/src/leftoverMapPlotLayout.ts @@ -159,6 +159,9 @@ * ADR 0346 fail-closes leftover-map leftover-axis origin ticks through * leftoverMapAxisTickBadge independently of leftover-map axis share and leftover-map * singular values, not leftover-map comparison leftover-axis ticks. + * ADR 0347 fail-closes leftover-map graphic leftover-map origin through + * leftoverMapPlotOriginBadge independently of leftover-map axis origin ticks, leftover-map + * axis share, and leftover-map singular values, not leftover-map comparison graphic leftover-map origin. */ import { formatLeftoverMapCoordinatePair } from "./leftoverMapCoordinates"; diff --git a/pyproject.toml b/pyproject.toml index 8af048443..f82235b76 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "lineageweave" -version = "2.103.0" +version = "2.104.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" }