Skip to content

feat(reports): leftover-map singular values on grouping comparison graphic (v2.78.0) - #861

Open
seonghobae wants to merge 1 commit into
feat/leftover-map-compare-plot-ticks-v2770from
feat/leftover-map-compare-plot-singular-v2780
Open

feat(reports): leftover-map singular values on grouping comparison graphic (v2.78.0)#861
seonghobae wants to merge 1 commit into
feat/leftover-map-compare-plot-ticks-v2770from
feat/leftover-map-compare-plot-singular-v2780

Conversation

@seonghobae

@seonghobae seonghobae commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Summary

  • Caption leftover-map singular values on the grouping comparison leftover-map graphic from already-named leftover-map axes (ADR 0321 / v2.78.0).
  • After make seed, closest and farthest leftover pairs sit above the member list with leftover-map singular values σ_k on that grouping comparison leftover-map graphic when those persisted singular values are finite and non-negative; click a post marker or a pair button opens that post.
  • Comparison copy uses accessible name leftover map comparison graphic leftover-map axis {axis} σ {value} so it stays distinct from hyphen leftover-map axis {axis} σ {value}, from pair-list leftover axis {axis} σ {value}, from comparison axis-share leftover map comparison axis {axis} ({share}%), and from comparison ticks leftover map comparison graphic leftover-map axis {axis} tick {value}.
  • Share and singular value omit independently: no share and no σ_k keeps leftover map comparison axis {k}; share only stays leftover map comparison axis {k} ({share}%); σ_k only is leftover map comparison graphic leftover-map axis {k} σ {value}; both is leftover map comparison graphic leftover-map axis {k} σ {value} ({share}%). A missing, non-finite, or negative singular value omits that σ badge and keeps leftover-map axis share when finite. Rank-0 origin cells still name σ 0.00 when that persisted singular value is a finite non-negative number.
  • Do not invent σ_k from leftover-map axis share, leftover-map coordinate ticks, leftover-map distance, leftover-map rank, leftover expected, leftover observed, leftover residual, leftover-map reconstruction, leftover-map unexplained leftover, leftover-map post coverage, leftover-map item coverage, leftover-map incomplete post coverage, leftover-map incomplete item coverage, leftover pair count, or the count of unused axes. A finite negative leftover is shown, never clamped.
  • UI-only; no SQL; no new columns. Never invent a leftover score. Never invent a theta. Do not persist leftover-map inner product, cosine, or length. This increment does not caption leftover-map singular values on leftover-axis report badges with a distinct comparison-strip name.
  • Stacked onto leftover-map coordinate ticks on grouping comparison leftover-map graphic (feat/leftover-map-compare-plot-ticks-v2770 / feat(reports): leftover-map coordinate ticks on grouping comparison graphic (v2.77.0) #860 @ 40fa5bd). Leave this PR open for independent review. Do not squash-merge onto the unprotected leftover base. Do not self-approve. After independent review, retarget onto leftover-coordinates (feat/leftover-map-coordinates-v2240 / feat(reports): persist leftover-map coordinates (v2.24.0) #782) rather than squash-merging here. Issues Milestone 2: port verified direct-PostgreSQL analysis into the protected product architecture #79 and Milestone 2.1: add normalized runtime-analysis schema bridge after v0.77 #87 stay open. Do not merge revert: undo #782 squash until independent APPROVE #808 without independent APPROVE.

Test plan

  • leftoverMapPlotAxisSingular.test.ts reads 1.84/0.86, names rank-0 0, omits NaN/Infinity/null/negative, does not invent σ from leftover-map axis share, keeps comparison copy distinct from hyphen graphic σ, pair-list σ, comparison axis share, and comparison ticks
  • LeftoverMapPlot.test.tsx comparison graphic: names σ 1.84 (82%) / σ 0.86 (18%); omits invented σ when share-only; names rank-0 σ 0.00; σ-only when share is NaN; does not use leftover-map axis 1 σ 1.84 or leftover axis 1 σ 1.84
  • App.test.tsx grouping comparison leftover-map graphic names leftover-map comparison graphic leftover-map axis σ; period-report graphic keeps leftover-map axis share copy
  • i18n.test.ts required keys for σ + σ-share in ko/zh/ja/vi
  • frontend oxlint on changed files: 0 warnings, 0 errors
  • frontend vitest: 588 tests passed (App.test.tsx, LeftoverMapPlot.test.tsx, LeftoverPairList.test.tsx, i18n.test.ts, leftover-map helpers)
  • CI Full test suite and Frontend lint, test, build on this exact head
  • After make seed, grouping comparison leftover pairs name leftover-map singular values on the comparison graphic; click opens that post.

Evidence boundary

Authenticated PostgreSQL API and k6 runtime acceptance are not claimed. No real records or credentials. Synthetic fixtures only.

Independent approval is required. No self-approval, admin bypass, or force push.

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.

Gabriel, K. R. (1971). The biplot graphic display of matrices with application to principal component analysis. Biometrika, 58(3), 453–467.


Devin Review

…aphic (v2.78.0)

Caption persisted leftover-map singular values σ_k on the grouping comparison leftover-map graphic from already-named leftover-map axes (ADR 0321). Share and singular value omit independently. Rank-0 unused axes still name σ 0.00. Do not invent σ from leftover-map axis share. Synthetic fixtures only.
@coderabbitai

coderabbitai Bot commented Aug 31, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 4b969e32-dbeb-40a0-a9cd-75d1f3ebbbfa

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

Copy link
Copy Markdown
Contributor Author

Stacked on #860 @ 40fa5bd. Head 3aac452 (v2.78.0 / ADR 0321). Independent APPROVE required on this exact head before squash-merge. Copilot/Devin COMMENT is not independent APPROVE. Do not self-approve. Do not squash-merge onto the unprotected leftover base. Issues #79 and #87 stay open. Synthetic fixtures only.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Devin Review found 3 potential issues.

Devin Review

Comment on lines +105 to +109
return tf(LEFTOVER_MAP_COMPARE_PLOT_AXIS_SINGULAR_SHARE, {
axis: axisIndex,
value: singular,
share: percent,
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Second-axis singular value is clipped

When axis 2 has a singular value, leftoverMapPlotAxisText expands its fixed-position label beyond the 480-pixel SVG. The value is visibly clipped.

Prompt for agents
The comparison variant now renders a substantially longer axis label, but axis 2 remains positioned at layout.originX + 8 with the default start anchor in frontend/src/components/LeftoverMapPlot.tsx. In the fixed 480px SVG, the English singular-value label already extends beyond the right boundary; translations can be longer. Adjust the axis-label rendering so the full singular value and optional share remain visible for both axes and all supported locales. Consider separate visible SVG text and accessible naming, wrapping, repositioning, or a compact visual format, while preserving the ADR 0321 accessible-name contract and the independent omission behavior.
Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines +21 to +34
export function leftoverSingularForAxis(
axes: ReadonlyArray<LeftoverMapPlotAxisSingular> | null | undefined,
axisIndex: number,
): number | null {
const axis = axes?.find((candidate) => candidate.axis_index === axisIndex);
if (
axis == null ||
axis.leftover_singular_value == null ||
!Number.isFinite(axis.leftover_singular_value) ||
axis.leftover_singular_value < 0
) {
return null;
}
return axis.leftover_singular_value;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Persisted values remain authoritative

leftoverSingularForAxis accepts only the matching persisted, finite, non-negative value. Missing or invalid values omit independently from axis share.

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Comment on lines 92 to 112
if (variant === "comparison") {
if (percent === null) {
const singular = formatLeftoverMapPlotAxisSingular(
leftoverSingularForAxis(leftoverMapAxes, axisIndex),
);
if (singular === null && percent === null) {
return t(axisIndex === 1 ? LEFTOVER_MAP_COMPARE_PLOT_AXIS_1 : LEFTOVER_MAP_COMPARE_PLOT_AXIS_2);
}
return tf(LEFTOVER_MAP_COMPARE_PLOT_AXIS_SHARE, { axis: axisIndex, share: percent });
if (singular === null) {
return tf(LEFTOVER_MAP_COMPARE_PLOT_AXIS_SHARE, { axis: axisIndex, share: percent });
}
if (percent === null) {
return tf(LEFTOVER_MAP_COMPARE_PLOT_AXIS_SINGULAR, { axis: axisIndex, value: singular });
}
return tf(LEFTOVER_MAP_COMPARE_PLOT_AXIS_SINGULAR_SHARE, {
axis: axisIndex,
value: singular,
share: percent,
});
}
if (percent === null) {
return t(axisIndex === 1 ? "leftover-map axis 1" : "leftover-map axis 2");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📝 Info: Report labels remain isolated

The singular-value branch runs only for comparison graphics. Report graphics retain their existing share-only labels.

(Refers to this code)

Devin Review

Was this helpful? React with 👍 or 👎 to provide feedback.

Copy link
Copy Markdown
Contributor Author

Exact head 3aac452eef781f3c1a5da258cd1c0c548e4930e6 still lacks independent APPROVE. Copilot/Devin review is not independent approval. Leave this PR open. Do not squash-merge. Do not self-approve. Issues #79 and #87 stay open.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant