Skip to content

feat(ux): humanize backend wire values in the UI#616

Merged
SoundMindsAI merged 2 commits into
mainfrom
feat_ux_wire_value_humanization
Jul 11, 2026
Merged

feat(ux): humanize backend wire values in the UI#616
SoundMindsAI merged 2 commits into
mainfrom
feat_ux_wire_value_humanization

Conversation

@SoundMindsAI

Copy link
Copy Markdown
Owner

First of a series of UX-audit fix PRs. Scope: wire-value humanization — several surfaces rendered raw snake_case/lowercase enum values to users.

Changes

  • New ui/src/lib/labels.ts — single source of display labels for backend wire values (never widens types; wire values still come from @/lib/enums).
  • StatusBadge renders human labels: explicit LABEL_TABLE for acronym casing (pr_opened→"PR opened", pr_merged→"PR merged"), else a snake_case→Title-case humanizer. Raw value preserved in data-value for tests/automation.
  • Judgment "Source" column — new judgment_source badge kind maps llm/human/click→"LLM-as-judge"/"Human"/"Click (UBI)". Also fixes a latent color bug: it used kind="judgment_list" whose variant table has no source keys, so every source fell through to the secondary variant.
  • Study wizard dropdowns — metric/sampler/pruner show "NDCG"/"TPE (learns from prior trials)"/"Median (early-stop weak trials)" instead of ndcg/tpe/median. Wire values still come from *_VALUES.map — form-select discipline preserved.
  • Shared formatMetricLabel — a metric now reads "NDCG@10" everywhere (dedup'd the private copy in the confidence panel).
  • Stale copy fix — judgments empty state no longer points at the removed "calibration modal".

Testing

labels.ts unit tests (humanizer, formatMetricLabel, enum-coverage so no value can leak unlabeled); StatusBadge tests updated + a regression test that judgment_source gets a real (non-secondary) variant. Full suite 1315 green; tsc + eslint clean.

🤖 Generated with Claude Code

UX audit finding: several surfaces rendered raw snake_case/lowercase enum
values to users. Add a single source of display labels (ui/src/lib/labels.ts)
and apply it:

- StatusBadge now renders a human label (explicit LABEL_TABLE for acronym
  casing like `pr_opened` -> "PR opened"/`pr_merged` -> "PR merged", else a
  snake_case -> Title-case humanizer). Raw value stays in data-value.
- Judgment "Source" column: new `judgment_source` StatusBadge kind maps
  llm/human/click -> "LLM-as-judge"/"Human"/"Click (UBI)". Fixes a latent
  color bug too — it previously used kind="judgment_list", whose variant
  table has no source keys, so every source fell through to the secondary
  variant.
- Study wizard metric/sampler/pruner dropdowns show "NDCG"/"TPE (learns from
  prior trials)"/"Median (early-stop weak trials)" instead of ndcg/tpe/median
  (wire values still come from @/lib/enums via *_VALUES.map — form-select
  discipline preserved).
- Shared formatMetricLabel so a metric reads "NDCG@10" everywhere (confidence
  panel + wizard caption) instead of "ndcg" one place, "NDCG@10" another.
- Fix stale judgments empty-state copy ("via the calibration modal" ->
  generate from a query set or UBI).

Tests: labels.ts unit tests (humanizer, formatMetricLabel, enum-coverage);
StatusBadge tests updated for labels + a regression test that judgment_source
gets a real variant. Full suite 1315 green; tsc + lint clean.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: SoundMindsAI <eric.starr@soundminds.ai>

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request centralizes the management of human-readable labels for backend wire values into a new labels.ts utility, ensuring consistent formatting across components like StatusBadge, CreateStudyModal, and ConfidencePanel, supported by comprehensive unit tests. The review feedback is highly constructive, pointing out opportunities to simplify the code by removing a redundant mapping in LABEL_TABLE that is already handled by the fallback humanizer, and cleaning up an unnecessary type assertion and unreachable fallback in CreateStudyModal.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment on lines +62 to +73
const LABEL_TABLE: Record<string, Record<string, string>> = {
proposal: {
pr_opened: 'PR opened',
pr_merged: 'PR merged',
},
proposal_pr: {
open: 'Open',
closed: 'Closed',
merged: 'Merged',
},
judgment_source: JUDGMENT_SOURCE_LABELS,
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

The proposal_pr mapping in LABEL_TABLE is redundant because humanizeWireValue already converts 'open', 'closed', and 'merged' to 'Open', 'Closed', and 'Merged' respectively. Removing this redundant mapping simplifies the code and reduces maintenance overhead.

const LABEL_TABLE: Record<string, Record<string, string>> = {
  proposal: {
    pr_opened: 'PR opened',
    pr_merged: 'PR merged',
  },
  judgment_source: JUDGMENT_SOURCE_LABELS,
};

Comment on lines +1292 to +1293
{METRIC_LABELS[metric as ObjectiveMetric] ?? metric.toUpperCase()}{' '}
evaluates the full ranked list — no cutoff used.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

medium

Since metric is already typed as ObjectiveMetric (watched from FormValues), the type assertion as ObjectiveMetric is redundant. Additionally, because METRIC_LABELS is a complete mapping of ObjectiveMetric to string, the value is guaranteed to be defined, making the nullish coalescing fallback ?? metric.toUpperCase() unreachable. We can simplify this expression to just METRIC_LABELS[metric].

Suggested change
{METRIC_LABELS[metric as ObjectiveMetric] ?? metric.toUpperCase()}{' '}
evaluates the full ranked list no cutoff used.
{METRIC_LABELS[metric]}{' '}
evaluates the full ranked list no cutoff used.

- Drop the redundant proposal_pr entry from StatusBadge LABEL_TABLE —
  humanizeWireValue already yields Open/Closed/Merged.
- Simplify METRIC_LABELS[metric] access — `metric` is already typed
  ObjectiveMetric and the map is total, so the cast + fallback were dead.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: SoundMindsAI <eric.starr@soundminds.ai>
@SoundMindsAI

Copy link
Copy Markdown
Owner Author

Review adjudication

Gemini — 2 findings, both accepted + fixed in 4fb4de21:

Finding Verdict Action
status-badge.tsxproposal_pr LABEL_TABLE entry redundant (humanizer already yields Open/Closed/Merged) Accept Removed; comment left explaining why it's intentionally omitted.
create-study-modal.tsxMETRIC_LABELS[metric as ObjectiveMetric] ?? … cast + fallback are dead (metric is typed, map is total) Accept Simplified to METRIC_LABELS[metric].

Pre-existing red check (not this PR): the backend (contract+integration) UBI test documented in #610.

@SoundMindsAI
SoundMindsAI merged commit b8fec65 into main Jul 11, 2026
17 of 20 checks passed
@SoundMindsAI
SoundMindsAI deleted the feat_ux_wire_value_humanization branch July 11, 2026 12:25
SoundMindsAI added a commit that referenced this pull request Jul 11, 2026
…621)

* docs(ux): capture deferred UX-audit polish as a tracked idea file

Follow-up remainder of the 2026-07-11 UX audit whose high/medium findings
shipped in PRs #616-#620: dark-mode long-tail color sweep + chart theming +
human dark-mode QA, empty-state CTA parity, breadcrumb consistency, reverse
"used by" links, wizard form-error association, and a centralized date
formatter. All low-severity; split out to keep each fix PR reviewable.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Signed-off-by: SoundMindsAI <eric.starr@soundminds.ai>

* docs(ux): clarify date vs number formatting in follow-up idea (Gemini review)

Signed-off-by: SoundMindsAI <eric.starr@soundminds.ai>

---------

Signed-off-by: SoundMindsAI <eric.starr@soundminds.ai>
Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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