Skip to content

Dashboard visual redesign: make Mission Control deliver its value#286

Merged
Tyler-R-Kendrick merged 9 commits into
mainfrom
claude/webapp-design-review-oy27i1
Jul 17, 2026
Merged

Dashboard visual redesign: make Mission Control deliver its value#286
Tyler-R-Kendrick merged 9 commits into
mainfrom
claude/webapp-design-review-oy27i1

Conversation

@Tyler-R-Kendrick

@Tyler-R-Kendrick Tyler-R-Kendrick commented Jul 17, 2026

Copy link
Copy Markdown
Owner

What / why

A critical design review of the dashboard found the visual system solid (moss/ember tokens, shared primitives) but failing its stated value — "one pane of glass" grounded in honest evidence, dogfooding the OpenUI DSL:

  1. The homepage didn't answer the mission-control question. "Performance insights" led with a 7-column reference table; nothing said whether the current champion passes ship gates, what's running, or what to do next.
  2. The honesty signal was nearly invisible. ProvenanceBadge was 0.62rem muted text, and nothing said globally when everything on screen is committed-snapshot fallback (the default on a fresh checkout / Vercel).
  3. Mono-everything, table-everything. IBM Plex Mono as the body font made insight prose wrap into 2-word lines; nothing had visual weight over anything else.
  4. The documented ◈ Compiled / ◇ Interpreted toggle didn't exist. The parity skill describes it, but main.tsx always rendered interpreted mode — four compiled pages were dead code.
  5. Concrete defects: var(--bg), var(--danger), var(--radius-sm) referenced but undefined; sticky table-header background mismatch; tooltips set in the display font; sidebar nav <a> without href; bare empty states.

Changes

  • Typography — body text moves to IBM Plex Sans; mono stays pinned on tables, stats, ids, logs, and micro-labels; prose table columns (findings/mitigations, model-card status) render sans. Identity (Syne + mono + moss/ember) unchanged.
  • Provenance & gate hierarchy — live reads active (cyan fill), committed reads archival (amber fill + dot); bigger gate cells; new .verdict pill for ship-gate verdicts; focus-visible outlines; token bug fixes; --terminal-bg token.
  • Restored renderer toggleuseMode() (localStorage "slm-mode", data-mode on :root) exactly as the dashboard-openui-parity skill documents, with a sidebar segmented control. Interpreted stays the default; all six compiled pages smoke-loaded.
  • Freshness banner — when /api/system reports no live outputs/, an amber shell banner says the whole dashboard is committed-snapshot data.
  • Mission-control Overview — new HeroStrip answers the 5-second questions first: gate verdict for the current reference (GATES PASS/FAIL n/n, or an honest NO GATE EVIDENCE), run id + provenance + deployment state, in-flight job/dispatch counts, CTAs; then Live jobs / Remote dispatches cards; insights and comparisons follow. One shared fetch composition (hero.ts) and shared views feed both renderers, so parity holds by construction. overview.openui mirrors the structure.
  • Empty statesEmpty accepts an optional CTA chip; the gate editor's no-metrics empty links to Smoke, the dispatches empty links to Experiments, in both modes.
  • Committed SPA bundle rebuilt; MANIFEST.json regenerated.

Verification

  • scripts/validate_page_dsl.py --check ✅; pytest tests/test_web 72 passed, 1 skipped ✅; tsc --noEmit + vite build ✅.
  • Playwright e2e (desktop-chrome): 6/7 pass, including new assertions for the Mission control title, .verdict, and the mode toggle. The one failure ("editing a gate threshold re-evaluates live") expects the first run to initially show GATES PASS — it fails identically against the pre-change bundle from main on this host because the live outputs/ data genuinely fails gates; data-dependent and pre-existing, not a regression.
  • Screenshot matrix (6 pages × dark/light × compiled/interpreted + run detail) diffed against a pre-change baseline; compiled and interpreted Overview verified pixel-parallel.

🤖 Generated with Claude Code

https://claude.ai/code/session_01WLQiLHopeRPDhNgJ6Pwp8H


Generated by Claude Code

Summary by CodeRabbit

  • New Features

    • Added a Mission Control dashboard with live deployment verdicts, running jobs, and remote dispatches.
    • Added renderer mode switching between compiled and interpreted views.
    • Added freshness indicators for live versus committed data.
    • Dashboard metrics and smoke-test thresholds now reflect the active ship-gate policy.
    • Added helpful navigation CTAs and job cancellation actions.
  • Style

    • Updated typography, status indicators, tables, cards, and responsive dashboard styling.
  • Tests

    • Expanded end-to-end and metric coverage for Mission Control, renderer switching, and policy-driven metrics.

claude added 5 commits July 17, 2026 03:32
Body text moves to IBM Plex Sans (mono stays pinned on tables, stats,
ids, logs, micro-labels); prose table columns render sans. Provenance
badges scale up: live reads active, committed reads amber/archival.
Bigger gate cells and a .verdict pill class for ship-gate verdicts.
Fixes undefined var(--bg)/--danger/--radius-sm, sticky th background
mismatch, Syne-as-body tooltip font; adds focus-visible outlines and
a --terminal-bg token.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLQiLHopeRPDhNgJ6Pwp8H
The parity skill documents a compiled/interpreted sidebar toggle
(localStorage slm-mode) that main.tsx never implemented — the four
compiled pages were dead code. useMode() + a compiled page map bring
it back with interpreted as default. Adds an amber shell banner when
/api/system reports no live outputs/ (committed-snapshot cold start),
and makes sidebar nav real links (href + aria-current).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLQiLHopeRPDhNgJ6Pwp8H
Overview now answers the 5-second questions first: a HeroStrip with the
ship-gate verdict for the current reference (GATES PASS/FAIL n/n, or an
honest NO GATE EVIDENCE), run id + provenance + deployment state, live
job/dispatch counts, and CTAs — then Live jobs / Remote dispatches
cards, then the existing insight surfaces. One shared fetch composition
(hero.ts) and shared views (HeroStrip, JobLines, DispatchLines) feed
both renderers, so compiled and interpreted stay at parity by
construction; overview.openui mirrors the new structure and the e2e
spec asserts the new title, verdict, and mode toggle.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLQiLHopeRPDhNgJ6Pwp8H
Empty accepts an optional CTA chip; the gate editor's no-metrics empty
links to Smoke and the dispatches empty links to Experiments, in both
renderers. Checkpoints now actually uses its navigate prop.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLQiLHopeRPDhNgJ6Pwp8H
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLQiLHopeRPDhNgJ6Pwp8H
@vercel

vercel Bot commented Jul 17, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
slm-training Ready Ready Preview, Comment Jul 17, 2026 12:13pm

Request Review

@coderabbitai

coderabbitai Bot commented Jul 17, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@Tyler-R-Kendrick, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 33 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: adbbc486-6191-42ae-bc23-99372dab16e6

📥 Commits

Reviewing files that changed from the base of the PR and between 727a121 and 7d8d85e.

📒 Files selected for processing (12)
  • src/apps/dashboard/src/components.tsx
  • src/apps/dashboard/src/hero.ts
  • src/apps/dashboard/src/interpret/toolProvider.ts
  • src/apps/dashboard/src/main.tsx
  • src/apps/dashboard/src/pages/Smoke.tsx
  • src/slm_training/web/observability.py
  • src/slm_training/web/static/app/assets/index-CukobhE5.js
  • src/slm_training/web/static/app/index.html
  • src/slm_training/web/static/openui/MANIFEST.json
  • src/slm_training/web/static/openui/overview.openui
  • src/slm_training/web/static/openui/smoke.openui
  • tests/test_web/test_control_plane.py
📝 Walkthrough

Walkthrough

The dashboard now presents mission-control hero and in-flight status, derives comparison and smoke metrics from ship-gate policy, supports compiled/interpreted rendering, updates styling and generated assets, and expands end-to-end and backend coverage.

Changes

Dashboard metric contract

Layer / File(s) Summary
Policy-derived metric contract
src/slm_training/web/observability.py, tests/test_web/*
Performance insights now expose policy-derived metric columns and nested metric values, with tests covering ordering and legacy parse-rate fallback.

Mission control data and rendering

Layer / File(s) Summary
Hero data and shared views
src/apps/dashboard/src/hero.ts, src/apps/dashboard/src/components.tsx
Hero state polls overview, jobs, dispatches, and gate data; shared components render hero, job, dispatch, empty-state, and dynamic table-cell views.
Compiled dashboard integration
src/apps/dashboard/src/pages/Overview.tsx, src/apps/dashboard/src/main.tsx
Overview adds mission-control panels and dynamic metric columns; the app adds persisted compiled/interpreted mode selection and freshness status.
Interpreted views and smoke gates
src/apps/dashboard/src/interpret/*, src/apps/dashboard/src/pages/Smoke.tsx, src/apps/dashboard/src/pages/Checkpoints.tsx, src/apps/dashboard/src/metrics.ts
Interpreted components delegate to shared views, hero data becomes a tool, and smoke labels and thresholds use live gate policy values.

Frontend presentation and validation

Layer / File(s) Summary
Frontend styling and validation
src/apps/dashboard/index.html, src/apps/dashboard/src/styles.css, src/slm_training/web/static/*, tests/e2e/dashboard.spec.ts
Typography, mission-control styling, terminal tokens, generated assets, OpenUI pages, and renderer-mode end-to-end assertions are updated.

Estimated code review effort: 4 (Complex) | ~60 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Overview
  participant fetchHero
  participant DashboardAPIs
  participant HeroStrip
  Overview->>fetchHero: poll hero state
  fetchHero->>DashboardAPIs: fetch overview, jobs, and dispatches
  fetchHero->>DashboardAPIs: fetch gate verdict for primary run
  fetchHero-->>Overview: return HeroData
  Overview->>HeroStrip: render mission-control status
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: a Mission Control-focused dashboard redesign with broader visual and UX updates.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch claude/webapp-design-review-oy27i1

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.

The gate policy is the canonical statement of what training optimizes,
but the Overview aggregated a hardcoded four-metric set that silently
omitted component_type_recall — the semantic-density floor added so
empty programs can't game the gates — from the comparison table, the
aggregate score that crowns the strongest experiment, and the
weakest-metric insight. The smoke canary likewise hardcoded a 0.66
parse threshold.

gate_metric_keys() now derives the lever set from DEFAULT_SHIP_GATES;
comparison rows carry lever-keyed metrics plus metric_columns for the
UI, so adding or dropping a gate lever re-shapes every metric surface
without a dashboard edit (pinned by a new test). The smoke gate pill
reads its lever + threshold from /api/gates/policy, and the Overview
hero names the failing gate levers next to a FAIL verdict. Both
renderers share the same composition, keeping compiled/interpreted
parity.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLQiLHopeRPDhNgJ6Pwp8H

@coderabbitai coderabbitai 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.

Actionable comments posted: 9

🧹 Nitpick comments (2)
src/apps/dashboard/src/pages/Overview.tsx (1)

25-28: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Reuse one set of mission-control polls.

useHero() refetches /api/overview, /api/jobs, and /api/dispatches, duplicating all three polls already started here. Derive the compiled hero from these responses or expose one shared hook; reserve fetchHero() for interpreted/tool usage.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/apps/dashboard/src/pages/Overview.tsx` around lines 25 - 28, Remove the
duplicate useHero poll from Overview and derive the compiled hero data using the
existing data, jobsRaw, and dispRaw responses from the three usePoll calls.
Reuse the shared response interpretation logic where available, while keeping
fetchHero reserved for interpreted/tool usage.
src/apps/dashboard/src/pages/Smoke.tsx (1)

100-100: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Prefer the metricLabel helper for consistency.

Instead of manually replacing underscores with spaces, you can use the metricLabel helper introduced in metrics.ts to ensure consistent capitalization and to benefit from any future label overrides.

  • src/apps/dashboard/src/pages/Smoke.tsx#L100-L100: import metricLabel from ../metrics and change gate.lever.replace(/_/g, " ") to metricLabel(gate.lever).
  • src/apps/dashboard/src/interpret/toolProvider.ts#L219-L219: import metricLabel from ../metrics and change lever.replace(/_/g, " ") to metricLabel(lever).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/apps/dashboard/src/pages/Smoke.tsx` at line 100, Replace manual lever
label formatting with the shared metricLabel helper. In
src/apps/dashboard/src/pages/Smoke.tsx:100-100, import metricLabel from
../metrics and use it for gate.lever; make the same import and replacement for
lever in src/apps/dashboard/src/interpret/toolProvider.ts:219-219.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/apps/dashboard/src/components.tsx`:
- Around line 573-576: Update the cancellation button handler in the jobs
component to await the postJSON request, track its pending state to disable the
button during cancellation, and surface request failures to the user. Keep the
job in the displayed list when cancellation fails, and clear the pending state
after completion or error.
- Around line 509-514: The run reference anchor in the component should provide
native link behavior and keyboard accessibility. Update the `<a>` rendered
around `ref.run_id` to include an appropriate href using the encoded run ID,
while preserving the existing navigation behavior and placeholder rendering when
no run ID exists.

In `@src/apps/dashboard/src/hero.ts`:
- Around line 38-42: Update the Promise.all requests in the hero data-loading
flow to stop converting API failures into empty fallback objects. Let errors
propagate or use an explicit stale/unavailable state for getJSON calls to
/api/overview, /api/jobs, and /api/dispatches, ensuring the UI distinguishes
unavailable data from valid zero-state results.
- Around line 84-87: Update the inflight dispatch count in the hero data
construction to count only active remote dispatches, filtering the jobs returned
by dispatches() before calculating the length. Exclude completed and failed
historical jobs while preserving the existing activeJobs and execution values.

In `@src/apps/dashboard/src/main.tsx`:
- Around line 89-104: Update FreshnessBanner to use an API-provided
live-evidence/provenance signal rather than outputs_present, which only reflects
directory existence. Expose that signal from Readers.system() based on whether
displayed data has live evidence, return it from /api/system, and have
FreshnessBanner show the committed-snapshot banner when live evidence is absent
while preserving its loading and error behavior.
- Around line 143-149: Update the sidebar link onClick handler to intercept
navigation only for unmodified primary clicks; allow Ctrl/Cmd-clicks and other
modified clicks to retain the browser’s default link behavior for opening real
links in new tabs. Keep navigate(r.path) for intercepted clicks and preserve the
existing active-link rendering.

In `@src/apps/dashboard/src/pages/Smoke.tsx`:
- Around line 113-118: The missing-value checks in the Smoke.tsx gate renderer
and toolProvider.ts threshold logic must handle both null and undefined. Update
the checks at src/apps/dashboard/src/pages/Smoke.tsx lines 113-118 and
src/apps/dashboard/src/interpret/toolProvider.ts lines 229-234 to use == null
for r.parse/headline and gate.threshold/threshold, preserving the existing
placeholder behavior when either value is missing.

In `@src/slm_training/web/observability.py`:
- Around line 174-186: Update the insight cache fingerprint wherever it is
constructed to include both the current policy derived from gate_metric_keys()
and the comparison evidence, in addition to the existing reference fingerprint.
Ensure policy changes and new experiment evidence invalidate cached best-run,
failure-count, and signature findings while preserving the existing
displayed-row behavior.
- Line 195: Normalize reference metrics to the same gate_metric_keys() set used
by _suite_metrics(), and require every key to be present before calculating
scores or deltas. Withhold comparisons when either side lacks a required lever,
preventing averages across different metric dimensions and ensuring missing
component_type_recall data cannot be ranked as complete.

---

Nitpick comments:
In `@src/apps/dashboard/src/pages/Overview.tsx`:
- Around line 25-28: Remove the duplicate useHero poll from Overview and derive
the compiled hero data using the existing data, jobsRaw, and dispRaw responses
from the three usePoll calls. Reuse the shared response interpretation logic
where available, while keeping fetchHero reserved for interpreted/tool usage.

In `@src/apps/dashboard/src/pages/Smoke.tsx`:
- Line 100: Replace manual lever label formatting with the shared metricLabel
helper. In src/apps/dashboard/src/pages/Smoke.tsx:100-100, import metricLabel
from ../metrics and use it for gate.lever; make the same import and replacement
for lever in src/apps/dashboard/src/interpret/toolProvider.ts:219-219.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8f349aba-a31f-489f-a270-a4243c7cf6e3

📥 Commits

Reviewing files that changed from the base of the PR and between e15152d and 727a121.

📒 Files selected for processing (23)
  • src/apps/dashboard/index.html
  • src/apps/dashboard/src/components.tsx
  • src/apps/dashboard/src/hero.ts
  • src/apps/dashboard/src/interpret/library.tsx
  • src/apps/dashboard/src/interpret/toolProvider.ts
  • src/apps/dashboard/src/main.tsx
  • src/apps/dashboard/src/metrics.ts
  • src/apps/dashboard/src/pages/Checkpoints.tsx
  • src/apps/dashboard/src/pages/Overview.tsx
  • src/apps/dashboard/src/pages/Smoke.tsx
  • src/apps/dashboard/src/styles.css
  • src/slm_training/web/observability.py
  • src/slm_training/web/static/app/assets/index-BsLWuLmr.css
  • src/slm_training/web/static/app/assets/index-Dl3zSttZ.js
  • src/slm_training/web/static/app/assets/index-ONBBdknd.css
  • src/slm_training/web/static/app/index.html
  • src/slm_training/web/static/openui/MANIFEST.json
  • src/slm_training/web/static/openui/overview.openui
  • src/slm_training/web/static/openui/smoke.openui
  • src/slm_training/web/static/tokens.css
  • tests/e2e/dashboard.spec.ts
  • tests/test_web/test_control_plane.py
  • tests/test_web/test_overview_insights.py
👮 Files not reviewed due to content moderation or server errors (1)
  • src/slm_training/web/static/app/assets/index-Dl3zSttZ.js

Comment thread src/apps/dashboard/src/components.tsx
Comment thread src/apps/dashboard/src/components.tsx
Comment thread src/apps/dashboard/src/hero.ts
Comment thread src/apps/dashboard/src/hero.ts Outdated
Comment on lines +89 to +104
/** Amber shell banner when every read is committed-snapshot fallback. */
function FreshnessBanner() {
const [outputsPresent, setOutputsPresent] = useState<boolean | null>(null);
useEffect(() => {
getJSON<{ outputs_present?: boolean }>("/api/system")
.then((sys) => setOutputsPresent(sys.outputs_present !== false))
.catch(() => setOutputsPresent(null));
}, []);
if (outputsPresent !== false) return null;
return (
<div className="freshness-banner" role="status">
<span className="prov prov-committed">snapshot</span>
Committed snapshot data — no live <span className="mono">outputs/</span> on this host. Run{" "}
<span className="mono">serve_playground</span> locally for live evidence.
</div>
);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Base the freshness banner on live evidence, not directory existence.

Readers.system() sets outputs_present from self.outputs.exists(). An empty or stale outputs/ directory therefore suppresses this banner even when every displayed value is committed fallback. Expose an actual live-evidence/provenance signal and use that here.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/apps/dashboard/src/main.tsx` around lines 89 - 104, Update
FreshnessBanner to use an API-provided live-evidence/provenance signal rather
than outputs_present, which only reflects directory existence. Expose that
signal from Readers.system() based on whether displayed data has live evidence,
return it from /api/system, and have FreshnessBanner show the committed-snapshot
banner when live evidence is absent while preserving its loading and error
behavior.

Comment thread src/apps/dashboard/src/main.tsx
Comment on lines +113 to +118
gate: (r) =>
r.parse === undefined || gate.threshold === undefined ? (
<span className="hint">—</span>
) : (
<StatusPill value={r.parse >= gate.threshold} label={r.parse >= gate.threshold ? "pass" : "fail"} />
),

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use == null to properly catch missing metric values.

Metric values fetched from the server can be null if they were not computed. Using strict equality (=== undefined) fails to catch null, causing the threshold check to evaluate null >= threshold (which implicitly coerces null to 0 and evaluates to an incorrect pass or fail).

  • src/apps/dashboard/src/pages/Smoke.tsx#L113-L118: update the check to r.parse == null || gate.threshold == null.
  • src/apps/dashboard/src/interpret/toolProvider.ts#L229-L234: update the check to headline == null || threshold == null.
📍 Affects 2 files
  • src/apps/dashboard/src/pages/Smoke.tsx#L113-L118 (this comment)
  • src/apps/dashboard/src/interpret/toolProvider.ts#L229-L234
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/apps/dashboard/src/pages/Smoke.tsx` around lines 113 - 118, The
missing-value checks in the Smoke.tsx gate renderer and toolProvider.ts
threshold logic must handle both null and undefined. Update the checks at
src/apps/dashboard/src/pages/Smoke.tsx lines 113-118 and
src/apps/dashboard/src/interpret/toolProvider.ts lines 229-234 to use == null
for r.parse/headline and gate.threshold/threshold, preserving the existing
placeholder behavior when either value is missing.

Comment on lines +174 to +186
def gate_metric_keys() -> list[str]:
"""The aggregate metric levers, in ship-gate policy order.

The ship-gate policy is the canonical statement of what training is
optimizing; deriving the dashboard's metric set from it means a policy
change (adding/dropping a lever) propagates to every metric surface.
"""
keys: list[str] = []
for mins in DEFAULT_SHIP_GATES.values():
for key in mins:
if key not in keys:
keys.append(key)
return keys

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Invalidate cached insights when policy or comparison evidence changes.

These findings now depend on gate_metric_keys(), but the cache identity still includes only the reference fingerprint. A policy update or new experiment can leave best-run, failure-count, and signature findings stale while the displayed rows update. Include the policy and comparison evidence in the cache fingerprint.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/slm_training/web/observability.py` around lines 174 - 186, Update the
insight cache fingerprint wherever it is constructed to include both the current
policy derived from gate_metric_keys() and the comparison evidence, in addition
to the existing reference fingerprint. Ensure policy changes and new experiment
evidence invalidate cached best-run, failure-count, and signature findings while
preserving the existing displayed-row behavior.

Comment thread src/slm_training/web/observability.py
- Job cancel awaits the request, disables the chip while pending, and
  surfaces failures instead of dropping the promise.
- Hero run link gets a real href (keyboard-accessible); sidebar and hero
  links intercept only unmodified primary clicks so Ctrl/Cmd-click still
  opens a new tab.
- fetchHero flags failed core reads as 'EVIDENCE UNAVAILABLE' instead of
  rendering a fake zero state, and counts only running/queued dispatches
  as in flight.
- Smoke gate checks use == null so a null metric can't coerce to 0 and
  fabricate a verdict; smoke labels use the shared metricLabel helper.
- observability: reference metrics normalize onto the gate levers and
  vs-reference deltas compare only levers both sides report (no
  cross-vocabulary averages); the insight-cache fingerprint includes the
  gate policy so lever changes invalidate cached findings (row-evidence
  churn intentionally still does not, per the documented cache note);
  outputs_present treats an empty outputs/ as a cold start.

Deliberately skipped: deduplicating Overview's hero poll — the shared
fetch composition is what guarantees compiled/interpreted parity, and
the duplicate reads are cheap local GETs.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WLQiLHopeRPDhNgJ6Pwp8H
@Tyler-R-Kendrick
Tyler-R-Kendrick merged commit c936b96 into main Jul 17, 2026
2 of 4 checks passed
@Tyler-R-Kendrick
Tyler-R-Kendrick deleted the claude/webapp-design-review-oy27i1 branch July 17, 2026 12:12
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.

2 participants