Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
89ed56b
feat(reports): leftover-map item coordinates on leftover-map graphic …
seonghobae Aug 31, 2026
bfe919c
test(red): reconstruct report criterion item-coordinate contract
seonghobae Sep 11, 2026
043f6bd
chore(stack): converge #876 onto repaired #875 head
seonghobae Sep 12, 2026
bd1b01d
chore(stack): converge #876 onto repaired #875
seonghobae Sep 12, 2026
259e2d1
chore(stack): converge #876 onto repaired ancestry
seonghobae Sep 13, 2026
3e93787
fix(reports): name report criterion coordinates
seonghobae Sep 15, 2026
d8b7f42
fix(reports): wire report criterion coordinate badge
seonghobae Sep 15, 2026
7fbcc5e
fix(i18n): compose localized report criterion name
seonghobae Sep 15, 2026
2c12c30
chore(stack): converge repaired #875 into #876
seonghobae Sep 15, 2026
f461f50
merge: converge v2.92.0 onto current v2.91.0 parent
seonghobae Sep 15, 2026
4290b15
merge: converge v2.92.0 onto repaired v2.91.0 parent
seonghobae Sep 15, 2026
a9cefd5
chore(stack): converge #876 onto repaired #875
seonghobae Sep 15, 2026
3479620
chore(stack): converge #876 onto current #875
seonghobae Sep 15, 2026
fd855ab
merge(reports): converge report-axis missingness repair into criterio…
seonghobae Sep 15, 2026
f900c55
merge(reports): converge #876 onto #875 RED contract head
seonghobae Sep 15, 2026
5dd5152
chore(stack): converge current #875 into #876
seonghobae Sep 15, 2026
6a1c465
chore(stack): converge current #875 into #876
seonghobae Sep 15, 2026
c2de3bf
chore(stack): converge semantic RED harness onto #876
seonghobae Sep 16, 2026
6ef9d15
chore(stack): converge #875 product repair into #876
seonghobae Sep 16, 2026
944f3ba
chore(stack): converge #876 on repaired tick foundation
seonghobae Sep 16, 2026
1425887
chore(stack): converge #876 on repaired comparison tick foundation
seonghobae Sep 16, 2026
bdacc01
chore(stack): converge #876 on repaired comparison-strip tick foundation
seonghobae Sep 16, 2026
22ad26b
chore(stack): converge #876 on repaired report-axis tick foundation
seonghobae Sep 16, 2026
517c38a
chore(stack): converge #876 on repaired comparison tick share foundation
seonghobae Sep 16, 2026
88b6d22
chore(stack): converge #876 on repaired tick-share foundation
seonghobae Sep 16, 2026
ac19cbc
chore(stack): converge #876 on repaired #875 contracts
seonghobae Sep 16, 2026
4be3c38
Merge parent #875 convergence into #876
seonghobae Sep 17, 2026
36063a0
merge: converge buyer-visible tick evidence into criterion-coordinate…
seonghobae Sep 18, 2026
a8ba471
merge: converge report-axis tick contract repair into criterion-coord…
seonghobae Sep 19, 2026
eb08ef6
chore(stack): converge v2.84 comparison tick contract repair
seonghobae Sep 19, 2026
1dc3cec
merge: converge #876 on report contract repairs
seonghobae Sep 19, 2026
52542e2
chore(stack): converge #876 onto #875 owner stack
seonghobae Sep 20, 2026
473d5f2
chore(reports): converge #876 onto repaired #875 ancestry
seonghobae Sep 20, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 20 additions & 3 deletions frontend/src/components/LeftoverMapPlot.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ import {
import {
firstPlottablePairForPost,
layoutLeftoverMapPlot,
leftoverMapPlotCriterionBadge,
LEFTOVER_MAP_COMPARE_PLOT_CAPTION,
LEFTOVER_MAP_COMPARE_PLOT_LABEL,
LEFTOVER_MAP_COMPARE_PLOT_SVG,
Expand Down Expand Up @@ -128,11 +129,27 @@ function leftoverMapPlotAxisText(
});
}

function leftoverMapPlotCriterionText(
marker: { label: string; axis1: number; axis2: number },
variant: LeftoverMapPlotVariant,
): string {
if (variant === "comparison") {
return `${t("Criterion ζ")} ${marker.label}`;
}
const badge = leftoverMapPlotCriterionBadge(marker.label, marker.axis1, marker.axis2);
if (badge === null) {
return `${t("Criterion ζ")} ${marker.label}`;
}
return `${t("Criterion ζ")} ${badge.values.label} · ζ ${badge.values.item}`;
}

/**
* Gabriel leftover-map graphic display of persisted ``ξ_{1:2}`` / ``ζ_{1:2}``.
*
* Person markers are posts; item markers are leftover criteria. Click a
* post marker to open that post. Caption leftover-map axes with persisted
* Person markers are posts; item markers are leftover criteria. Report criterion
* markers name persisted item coordinates by composing the already-localized
* criterion label with persisted ζ; comparison criterion naming remains generic.
* Click a post marker to open that post. Caption leftover-map axes with persisted
* Gabriel inertia share when finite, including rank-0 zero-share axes.
* Report and comparison graphic axes additionally name finite, non-negative
* persisted Gabriel singular values independently of axis share; never derive
Expand Down Expand Up @@ -576,7 +593,7 @@ export function LeftoverMapPlot({
</g>
))}
{layout.items.map((marker) => (
<g key={`item:${marker.id}`} aria-label={`${t("Criterion ζ")} ${marker.label}`}>
<g key={`item:${marker.id}`} aria-label={leftoverMapPlotCriterionText(marker, variant)}>
<polygon className="leftover-map-plot-item" points={diamondPoints(marker.x, marker.y, 7)} />
<text className="leftover-map-plot-label" x={marker.x + 10} y={marker.y + 14}>
{marker.label}
Expand Down
21 changes: 21 additions & 0 deletions frontend/src/leftoverMapPlotLayout.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,27 @@ export const LEFTOVER_MAP_COMPARE_PLOT_SVG = "Leftover map comparison";
export const LEFTOVER_MAP_PLOT_POST_ACTION =
"Open leftover-map post {title} at ξ {person}";

export const LEFTOVER_MAP_PLOT_CRITERION =
"leftover-map criterion {label} at ζ {item}";

export type LeftoverMapPlotCriterionBadge = {
key: string;
values: { label: string; item: string };
};

/** Builds report-graphic criterion copy only from the persisted item-axis pair. */
export function leftoverMapPlotCriterionBadge(
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_PLOT_CRITERION, values: { label, item } };
}

export const LEFTOVER_MAP_PLOT_TICK =
"leftover-map axis {axis} tick {value}";

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
"""Executable contract for report-graphic criterion item-coordinate captions."""

from pathlib import Path
import re


ROOT = Path(__file__).resolve().parents[1]
LAYOUT_SOURCE = ROOT / "frontend" / "src" / "leftoverMapPlotLayout.ts"
PLOT_SOURCE = ROOT / "frontend" / "src" / "components" / "LeftoverMapPlot.tsx"


def test_report_graphic_criterion_names_persisted_item_coordinates() -> None:
"""Report criterion markers use distinct ζ copy while comparison markers retain generic copy."""
layout_source = LAYOUT_SOURCE.read_text(encoding="utf-8")
plot_source = PLOT_SOURCE.read_text(encoding="utf-8")

assert 'LEFTOVER_MAP_PLOT_CRITERION =\n "leftover-map criterion {label} at ζ {item}";' in layout_source
assert "leftoverMapPlotCriterionBadge" in layout_source
assert "leftoverMapPlotCriterionBadge" in plot_source
assert re.search(
r'variant\s*===\s*"comparison".*?Criterion ζ.*?leftoverMapPlotCriterionBadge',
plot_source,
re.DOTALL,
)


def test_criterion_badge_consumes_item_axes_fail_closed_without_person_inference() -> None:
"""ζ comes only from a finite persisted item coordinate pair; zero remains representable."""
layout_source = LAYOUT_SOURCE.read_text(encoding="utf-8")
helper = re.search(
r"export function leftoverMapPlotCriterionBadge\(.*?\n}\n",
layout_source,
re.DOTALL,
)
assert helper is not None
helper_source = helper.group(0)

assert "formatLeftoverMapCoordinatePair(axis1, axis2)" in helper_source
assert "item === null" in helper_source
assert "return null" in helper_source
assert "leftover_map_person_axis" not in helper_source
assert "Math.sqrt" not in helper_source
assert "Math.abs" not in helper_source
Loading