Skip to content

feat(studio): add experiment trace comparison view [ASE-186] - #641

Merged
walston merged 14 commits into
mainfrom
nwalston/ase-186-trace-comparison-view
Jul 22, 2026
Merged

feat(studio): add experiment trace comparison view [ASE-186]#641
walston merged 14 commits into
mainfrom
nwalston/ase-186-trace-comparison-view

Conversation

@walston

@walston walston commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Closes ASE-186

Screen.Recording.2026-07-22.at.08.50.28.mov

Recording above predates the run-based redesign — will refresh before merge.

Summary

Evaluation trace detail could only show one run of a test case at a time. This adds a side-by-side comparison of the same test case across different runs.

A "Compare against evaluation run" selector in the page header lists every run (session) of the current test case across the experiment group's evaluations. Because the sessions endpoint is scoped to a single evaluation, the list is built client-side by fanning out one query per evaluation (GET /apis/intake/v2/workspaces/{ws}/evaluations/{name}/sessions?filter[test_case_id]=<id>) and flattening — a group-scoped endpoint is the eventual replacement (fast-follow). Picking a run adds ?compareWith=<traceId> to the URL and splits into a "Test case comparison — Test case <id>" page with two columns.

Each column shows:

  • the run label — <evaluation-name> · Trial <last 5 of session id>
  • expand-all / collapse-all controls
  • a per-session metrics card: Cost, Latency, Tkns In, Tkns Out, Cached Tkns, and every evaluator score (not experiment rollups)
  • the trace in list mode

If the selected run has no matching session, the column shows "Test case not available".

Selector UX: single-trial evaluations collapse onto one selectable line; multi-trial evaluations render the evaluation as a subdued heading with each trial indented beneath (↳ Trial XXXXX). Every option carries an aria-label of the full <evaluation> · Trial XXXXX so screen readers get self-describing options. Loading shows a disabled control with "Loading other runs"; no siblings shows "No runs to compare to".

Rendering two trace views also required two supporting fixes:

  • TraceSpanAccordions is controlled — single view binds span selection to ?spanId= (deep links unchanged); compare columns render independently in list mode. Expand/collapse surface to the column header via a SlotHeaderRenderProp.
  • Refresh invalidation is scoped to the specific trace's query key (was invalidating every span-list query in the workspace).

Test plan

  • Open an evaluation trace (/workspaces/<ws>/experiment/<group>/<evaluation>/traces/<traceId>) → "Compare against evaluation run" selector appears in the page header (top right)
  • Open the selector → runs of this test case across the group's evaluations, grouped by evaluation; single-trial evals collapsed to one line, multi-trial evals nested with ; disabled + "Loading other runs" while loading, "No runs to compare to" when there are none
  • Pick a run → URL gains ?compareWith=<traceId>, page shows "Test case comparison — Test case <id>" and splits into two columns, each with the run label, per-session metrics (Cost, Latency, Tkns In/Out, Cached, evaluator scores), and the trace in list mode
  • Pick a different run → the compare column swaps (no backtracking); Clear returns to the single trace view
  • Pick a run whose session isn't found → right column shows "Test case not available"
  • Single-trace view: click spans → ?spanId= updates in the URL; reload the deep link → same span selected

Reviewer note (dev data): most experiment groups have a single trial per evaluation (all collapsed). For a dropdown showing both collapsed and nested entries, use workspace bugnemo-mc, group opt-97d7f6d1-02b5-4f34-82db-a09b3feefc0f, test case ttyb-028-...bug-432.

@walston
walston requested review from a team as code owners July 10, 2026 20:56
@github-actions github-actions Bot added the feat label Jul 10, 2026
@github-actions

Copy link
Copy Markdown
Contributor

@walston
walston force-pushed the nwalston/ase-186-trace-comparison-view branch from 1057ed0 to 8d296fc Compare July 10, 2026 21:07
@github-actions

github-actions Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 27113/34832 77.8% 62.1%
Integration Tests 15892/33443 47.5% 19.9%

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Changes

Experiment trace comparison

Layer / File(s) Summary
Controlled span selection
web/packages/studio/src/components/IntakeDetail/TraceDetailView.tsx, web/packages/studio/src/components/IntakeDetail/TraceSpanAccordions.tsx, web/packages/studio/src/routes/IntakeTraceDetailRoute/index.tsx
Span selection is parent-controlled, synchronized through spanId, and breadcrumb updates can be disabled for embedded traces.
Comparison session lookup
web/packages/studio/src/routes/ExperimentTraceDetailRoute/useCompareSession.ts, web/packages/studio/src/routes/ExperimentTraceDetailRoute/useCompareSession.test.ts
Sessions are queried by test case and represented as loading, missing-ID, not-found, or found states.
Comparison route and navigation
web/packages/studio/src/routes/ExperimentTraceDetailRoute/index.tsx, web/packages/studio/src/routes/ExperimentTraceDetailRoute/CompareExperimentSelect.tsx, web/packages/studio/src/routes/constants.ts, web/packages/studio/src/routes/utils.ts
The route filters comparable sibling experiments, adds compareWith navigation, and renders a controlled comparison selector.
Side-by-side comparison view
web/packages/studio/src/routes/ExperimentTraceDetailRoute/ExperimentTraceCompare.tsx, web/packages/studio/src/routes/ExperimentTraceDetailRoute/index.test.tsx
Primary and matched traces render in separate columns with loading, unavailable, and missing-test-case states covered by route tests.

Sequence Diagram(s)

sequenceDiagram
  participant Browser
  participant ExperimentTraceDetailRoute
  participant useCompareSession
  participant ExperimentTraceCompare
  participant IntakeTraceDetailView
  Browser->>ExperimentTraceDetailRoute: Select compareWith experiment
  ExperimentTraceDetailRoute->>useCompareSession: Query matching test_case_id
  useCompareSession->>ExperimentTraceCompare: Return comparison state
  ExperimentTraceCompare->>IntakeTraceDetailView: Render primary and matched traces
  IntakeTraceDetailView->>Browser: Update linked span selection
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% 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
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding an experiment trace comparison view.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch nwalston/ase-186-trace-comparison-view

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 11

🧹 Nitpick comments (3)
docs/superpowers/plans/2026-07-07-experiment-column-reordering.md (2)

1-33: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Align this page with the Markdown documentation guidelines.

The page mixes architecture explanation, implementation how-to steps, and reference material. It also lacks an explicit prerequisites section at the top and a Next Steps section at the end. Either classify this as an internal implementation-plan exception or restructure it into one Diataxis quadrant with the required sections.

Also applies to: 544-554

🤖 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 `@docs/superpowers/plans/2026-07-07-experiment-column-reordering.md` around
lines 1 - 33, Restructure the document into a single Diataxis category,
preferably an internal implementation plan, instead of mixing architecture,
procedural instructions, and reference material. Add an explicit Prerequisites
section near the top and a Next Steps section at the end, and reorganize or
remove content that does not fit the chosen category while preserving the
implementation plan’s actionable task structure.

Source: Coding guidelines


500-540: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Add focused automated coverage for the opt-in behavior.

Existing DataView tests and manual checks do not lock down the new contract. Add tests for the disabled default, pinned-column exclusion, reordered columnOrder, body-cell movement, sorting via the label, and column visibility.

🤖 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 `@docs/superpowers/plans/2026-07-07-experiment-column-reordering.md` around
lines 500 - 540, Add focused automated tests for the DataView column-reordering
contract, covering the disabled default, exclusion of pinned columns, reordered
columnOrder, corresponding body-cell movement, sorting through the column label,
and column visibility. Place the tests with the existing DataView test suite and
use the relevant TableColumnHeader, TableContent, and ExperimentGroupDataView
behaviors to verify both opt-in and unchanged default behavior.
web/packages/studio/src/routes/ExperimentTraceDetailRoute/index.test.tsx (1)

125-173: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Consider adding a test for the select → navigate flow.

Current compare-view tests assert rendered states but not that choosing an experiment from CompareExperimentSelect (or clicking "Clear") actually updates the URL/route via handleCompareChange/handleClearCompare.

🤖 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 `@web/packages/studio/src/routes/ExperimentTraceDetailRoute/index.test.tsx`
around lines 125 - 173, Add a compare-view interaction test that selects another
experiment through CompareExperimentSelect and verifies navigation updates the
compareWith query parameter via handleCompareChange; also cover the Clear action
and assert it removes the compare parameter or returns to the primary route via
handleClearCompare.
🤖 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 `@docs/superpowers/plans/2026-07-07-experiment-column-reordering.md`:
- Around line 180-185: Update the validation commands in the documented steps,
including the “Verify types pass” checks and the referenced validation sections,
to avoid masking failures through pipelines. Run typecheck/lint commands
directly where possible, or prepend `set -o pipefail` and ensure filtering
commands cannot replace the original command’s exit status.
- Around line 522-531: Update “Step 3: Run existing DataView tests to confirm
nothing regressed” to invoke the repository’s declared JavaScript test command
unconditionally, removing the uv run pytest fallback chain; retain the Vitest
command only if it is the documented web test runner, and ensure the command
targets packages/common/src/components/DataView.
- Around line 27-31: The column reordering logic must preserve pinned column IDs
in the table’s full column order. Update the DnD setup and reorder handler
around TableContent, SortableContext, and arrayMove so only non-pinned columns
are draggable while table.setColumnOrder() always receives the complete order;
merge reordered non-pinned IDs back with the original pinned IDs rather than
replacing the order with a filtered list.
- Around line 298-320: Update DragAlongCell to accept and forward the existing
TableDataCell props and children by extending ComponentProps<typeof
TableDataCell>; merge the sortable DnD styles with the incoming style rather
than replacing it, and render the provided children instead of reconstructing
content with flexRender. Apply the same forwarding pattern to the related
implementation noted around the second occurrence.
- Around line 82-109: Update the header drag wiring and DndContext setup to
configure KeyboardSensor with the required coordinate getter, pass
setActivatorNodeRef through DragProps, and apply it to the drag handle button.
Also set the handle’s type to "button" to prevent form submission, updating
related props and rendering paths such as TableColumnHeaderProps as needed.
- Around line 296-320: Wrap the body-cell rendering that contains DragAlongCell
in a SortableContext using items={columnOrder} and
horizontalListSortingStrategy, or move an equivalent context to a shared parent
that covers both headers and body cells. Ensure every DragAlongCell receives the
same column order and sorting strategy as the dragged headers so row cells
remain aligned during column reordering.

In `@scripts/seed_local_experiments.py`:
- Around line 34-36: Add a shared timeout constant and pass it to both
urllib.request.urlopen calls in the relevant request helpers, including get, so
endpoint requests cannot hang indefinitely.
- Around line 107-113: Update the session-selection logic in the experiment
seeding flow to fetch both experiment session lists, retain only sessions with
non-empty test_case_id values, and intersect them by shared test_case_id rather
than relying on page order or session_id fallback. Before seeding, fail
explicitly when fewer than three shared test cases remain, and use the matched
test_case_id values to select the corresponding sessions for both experiments.
- Around line 113-114: Update the agent.output construction in the
session-processing logic to derive its value from the already normalized `inp`
variable, using `inp[:500]` instead of calling `session.get("input", "")[:500]`,
so null inputs are handled safely and the existing truncation is reused.

In
`@web/packages/studio/src/routes/ExperimentTraceDetailRoute/ExperimentTraceCompare.tsx`:
- Around line 108-131: The compare column shows the no-test-case state while the
primary trace is still loading. Thread the primary trace loading flag from the
parent into the comparison logic, and update renderRightColumn and
useCompareSession usage to return the loading UI until the primary trace
resolves; only treat a falsy testCaseId as no-test-case-id after loading
completes. Use the existing renderRightColumn and useCompareSession symbols.

In
`@web/packages/studio/src/routes/ExperimentTraceDetailRoute/useCompareSession.test.ts`:
- Line 10: Replace the relative useCompareSession import in the test with the
project’s configured absolute alias path, preserving the existing symbol and
import behavior.

---

Nitpick comments:
In `@docs/superpowers/plans/2026-07-07-experiment-column-reordering.md`:
- Around line 1-33: Restructure the document into a single Diataxis category,
preferably an internal implementation plan, instead of mixing architecture,
procedural instructions, and reference material. Add an explicit Prerequisites
section near the top and a Next Steps section at the end, and reorganize or
remove content that does not fit the chosen category while preserving the
implementation plan’s actionable task structure.
- Around line 500-540: Add focused automated tests for the DataView
column-reordering contract, covering the disabled default, exclusion of pinned
columns, reordered columnOrder, corresponding body-cell movement, sorting
through the column label, and column visibility. Place the tests with the
existing DataView test suite and use the relevant TableColumnHeader,
TableContent, and ExperimentGroupDataView behaviors to verify both opt-in and
unchanged default behavior.

In `@web/packages/studio/src/routes/ExperimentTraceDetailRoute/index.test.tsx`:
- Around line 125-173: Add a compare-view interaction test that selects another
experiment through CompareExperimentSelect and verifies navigation updates the
compareWith query parameter via handleCompareChange; also cover the Clear action
and assert it removes the compare parameter or returns to the primary route via
handleClearCompare.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 34625f0e-0e3c-46f1-b783-ef1a39731a7e

📥 Commits

Reviewing files that changed from the base of the PR and between 9903a5f and 205203a.

📒 Files selected for processing (13)
  • docs/superpowers/plans/2026-07-07-experiment-column-reordering.md
  • scripts/seed_local_experiments.py
  • web/packages/studio/src/components/IntakeDetail/TraceDetailView.tsx
  • web/packages/studio/src/components/IntakeDetail/TraceSpanAccordions.tsx
  • web/packages/studio/src/routes/ExperimentTraceDetailRoute/CompareExperimentSelect.tsx
  • web/packages/studio/src/routes/ExperimentTraceDetailRoute/ExperimentTraceCompare.tsx
  • web/packages/studio/src/routes/ExperimentTraceDetailRoute/index.test.tsx
  • web/packages/studio/src/routes/ExperimentTraceDetailRoute/index.tsx
  • web/packages/studio/src/routes/ExperimentTraceDetailRoute/useCompareSession.test.ts
  • web/packages/studio/src/routes/ExperimentTraceDetailRoute/useCompareSession.ts
  • web/packages/studio/src/routes/IntakeTraceDetailRoute/index.tsx
  • web/packages/studio/src/routes/constants.ts
  • web/packages/studio/src/routes/utils.ts

Comment thread docs/superpowers/plans/2026-07-07-experiment-column-reordering.md Outdated
Comment thread docs/superpowers/plans/2026-07-07-experiment-column-reordering.md Outdated
Comment thread docs/superpowers/plans/2026-07-07-experiment-column-reordering.md Outdated
Comment thread docs/superpowers/plans/2026-07-07-experiment-column-reordering.md Outdated
Comment thread docs/superpowers/plans/2026-07-07-experiment-column-reordering.md Outdated
Comment thread scripts/seed_local_experiments.py Outdated
Comment thread scripts/seed_local_experiments.py Outdated
Comment thread scripts/seed_local_experiments.py Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
docs/superpowers/plans/2026-07-07-experiment-column-reordering.md (1)

1-9: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Keep this page in one Diátaxis quadrant.

This page mixes a HOW-TO, architecture explanation, reference table, and manual checklist. Add prerequisites before the goal, classify the page (likely HOW-TO), split reference/architecture material into linked pages if needed, and add a Next Steps section with cross-links.

As per coding guidelines, documentation pages must use one Diátaxis quadrant, list prerequisites first, apply progressive disclosure, and include Next Steps.

Also applies to: 544-554

🤖 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 `@docs/superpowers/plans/2026-07-07-experiment-column-reordering.md` around
lines 1 - 9, The implementation plan mixes Diátaxis content types instead of
staying in one quadrant. Rework this page as a HOW-TO: add prerequisites before
the Goal, keep the implementation steps and manual checklist as the primary
content, move architecture and reference details to linked documentation where
appropriate, and add a Next Steps section with relevant cross-links.

Source: Coding guidelines

🤖 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.

Nitpick comments:
In `@docs/superpowers/plans/2026-07-07-experiment-column-reordering.md`:
- Around line 1-9: The implementation plan mixes Diátaxis content types instead
of staying in one quadrant. Rework this page as a HOW-TO: add prerequisites
before the Goal, keep the implementation steps and manual checklist as the
primary content, move architecture and reference details to linked documentation
where appropriate, and add a Next Steps section with relevant cross-links.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: ffe3de71-8e4a-4c0d-8e2f-f7fa772f57df

📥 Commits

Reviewing files that changed from the base of the PR and between 205203a and 8d296fc.

📒 Files selected for processing (15)
  • docs/superpowers/plans/2026-07-07-experiment-column-reordering.md
  • scripts/seed_local_experiments.py
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/spanKeyValues.test.tsx
  • web/packages/studio/src/components/IntakeDetail/TraceDetailView.tsx
  • web/packages/studio/src/components/IntakeDetail/TraceSpanAccordions.tsx
  • web/packages/studio/src/routes/ExperimentTraceDetailRoute/CompareExperimentSelect.tsx
  • web/packages/studio/src/routes/ExperimentTraceDetailRoute/ExperimentTraceCompare.tsx
  • web/packages/studio/src/routes/ExperimentTraceDetailRoute/index.test.tsx
  • web/packages/studio/src/routes/ExperimentTraceDetailRoute/index.tsx
  • web/packages/studio/src/routes/ExperimentTraceDetailRoute/useCompareSession.test.ts
  • web/packages/studio/src/routes/ExperimentTraceDetailRoute/useCompareSession.ts
  • web/packages/studio/src/routes/IntakeTraceDetailRoute/index.tsx
  • web/packages/studio/src/routes/constants.ts
  • web/packages/studio/src/routes/utils.ts
  • web/packages/studio/src/util/intakeTelemetry.ts
✅ Files skipped from review due to trivial changes (3)
  • web/packages/studio/src/routes/utils.ts
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/spanKeyValues.test.tsx
  • web/packages/studio/src/routes/constants.ts
🚧 Files skipped from review as they are similar to previous changes (9)
  • web/packages/studio/src/routes/ExperimentTraceDetailRoute/CompareExperimentSelect.tsx
  • web/packages/studio/src/routes/IntakeTraceDetailRoute/index.tsx
  • web/packages/studio/src/routes/ExperimentTraceDetailRoute/useCompareSession.ts
  • web/packages/studio/src/routes/ExperimentTraceDetailRoute/useCompareSession.test.ts
  • web/packages/studio/src/routes/ExperimentTraceDetailRoute/index.test.tsx
  • web/packages/studio/src/routes/ExperimentTraceDetailRoute/ExperimentTraceCompare.tsx
  • web/packages/studio/src/components/IntakeDetail/TraceDetailView.tsx
  • web/packages/studio/src/components/IntakeDetail/TraceSpanAccordions.tsx
  • web/packages/studio/src/routes/ExperimentTraceDetailRoute/index.tsx

@walston
walston force-pushed the nwalston/ase-186-trace-comparison-view branch 2 times, most recently from 89c4ae1 to 92599ee Compare July 10, 2026 21:44

@walston walston left a comment

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

quick sync with @rrhyne has some UI and UX issues:

  1. The headers are wrong: use proper headings.
  2. Column layout doesn't have room for "Tree" view. switch to List view and hide/disable the toggle
  3. Breadcrumbs should render "[Experiment Name] > Compare > [Experiment Name]+"
  4. Compare To... dropdown should be in the page header (See figma).
  5. Compare To... dropdown should be populated by experiment names (it might be already, doublecheck).
  6. Columns need a "close" button
  7. Support 3-column layout
    • when closing 3rd column, switch to 2-column.
    • when closing last remaining column switch to an empty state view with "Compare To..." drop down

@walston
walston force-pushed the nwalston/ase-186-trace-comparison-view branch 2 times, most recently from c22fd2c to 8cd7540 Compare July 15, 2026 16:41
Side-by-side comparison of the same test case across two sibling
experiments on the experiment trace detail page.

- "Compare to..." selector in the page header lists same-dataset sibling
  experiments; picking one adds ?compareWith=<name> to the URL (preserving
  any active ?spanId= deep link) and splits into a two-column comparison
- Each column: heading row (experiment name, expand/collapse/close), a
  metrics card (Correctness, Latency, Tkns In/Out, Cached Tkns), and the
  trace in list mode; missing sessions show "Test case not available"
- TraceSpanAccordions is now controlled: single view binds selection to the
  URL, each compare column owns selection in local state keyed by traceId;
  expand/collapse surface to the column header via SlotHeaderRenderProp
- Refresh invalidation scoped to the specific trace's query key

Signed-off-by: Nathan Walston <nwalston@nvidia.com>
@walston
walston force-pushed the nwalston/ase-186-trace-comparison-view branch from 8cd7540 to bb0233c Compare July 21, 2026 18:21
walston added 13 commits July 21, 2026 12:20
Address Shanaia's review — the comparison axis is now runs of the same
test case, not experiments:

- Compare selector lists every run (session) of the test case across the
  group's evaluations (FE fan-out per evaluation via useTestCaseRuns),
  labeled '<evaluation-name> · Trial <session_id last 5>'; ?compareWith=
  now carries the selected run's trace_id
- Label above the selector: 'Compare against another run of this test case'
- Page header: 'Test case comparison — Test case <test_case_id>';
  subheader: 'See how this test case performed across different runs'
- Metrics card is now per-session (not experiment rollups): cost, latency,
  tokens in/out, cached tokens, and all evaluator scores
- Removed the per-column close buttons (kept the header Clear link)

Signed-off-by: Nathan Walston <nwalston@nvidia.com>
Refine the compare selector per design feedback (Rob/Shanaia):

- Replace the flat single-select with a grouped Dropdown menu: a panel
  title, each evaluation run as a section heading, its trials listed as
  'Trial XXXXX' rows (no repeated evaluation name per row)
- Descriptive text lives in the trigger ('Compare against evaluation run');
  removed the separate label above the control
- Picking a trial swaps the comparison column (cap stays 1 compare run for
  now); the primary run is a fixed anchor and never an option
- Add a test covering open -> grouped runs -> select -> enters comparison

Signed-off-by: Nathan Walston <nwalston@nvidia.com>
…ASE-186]

- Rebuild the selector on the Select control (nv-input styling) instead of
  the Dropdown menu, keeping grouped runs via DropdownSection/DropdownHeading
  inside the listbox — matches the mockup and other grouped selects
- Fixed trigger label via renderValue + placeholder (does not echo the
  selected run)
- Loading now shows a disabled control with 'Loading other runs' across the
  whole group->evaluations->trace->runs chain; 'No runs to compare to' only
  once loaded with no siblings
- Add CompareRunSelect state tests (loading/empty/ready)

Signed-off-by: Nathan Walston <nwalston@nvidia.com>
- Drop DropdownSection (the source of the divider rules between runs) and
  use compact listbox density for a tighter list
- Show hierarchy the way the mockup does: bold evaluation-run heading with
  its trials indented beneath as 'Trial XXXXX'
- a11y: each option carries an aria-label of the full '<evaluation> · Trial
  XXXXX' so screen readers get self-describing options rather than relying
  on visual weight/indent alone

Signed-off-by: Nathan Walston <nwalston@nvidia.com>
…-186]

- Fix vertically clipped evaluation headings: the scroll container was a
  flex Stack, so overflowing children were shrunk and clipped; use a block
  div with overflow-y-auto so rows keep their height
- Collapse evaluations with a single trial onto one selectable line
  ('<evaluation> · Trial XXXXX'); evaluations with multiple trials keep the
  nested heading + indented trials (per Shanaia)
- Cover both paths in CompareRunSelect tests

Signed-off-by: Nathan Walston <nwalston@nvidia.com>
TextInputSpinner forces className=h-full, which stretched its wrapper and
pinned the fixed-size spinner to the top of the trigger. Use a plain
size=small Spinner so the trigger's centered slot aligns it vertically.

Signed-off-by: Nathan Walston <nwalston@nvidia.com>
…E-186]

The loading affordance is the disabled control + 'Loading other runs'
placeholder; the extra slotEnd spinner sat off-center next to the chevron
and added nothing over the disabled state.

Signed-off-by: Nathan Walston <nwalston@nvidia.com>
…s, real indent [ASE-186]

- Clickable rows (collapsed lines + nested trials) are now bold; labels
  (panel title + evaluation group headings) are secondary/subdued, so weight
  reads as 'bold = actionable'
- Panel title gets extra bottom spacing to separate it from the list
- Fix trial indentation: SelectItem's own padding overrode a className on the
  item, so indent the content (inner Text) instead

Signed-off-by: Nathan Walston <nwalston@nvidia.com>
…E-186]

text-content-*/text-status-* aren't produced by the Foundations tailwind
plugin (it namespaces semantic text colors as text-color-*), so those class
names were silent no-ops and never subdued anything.

- Group headings -> text-color-subtle (most muted, per feedback)
- Panel title + Clear link + not-found body -> text-color-secondary
- Not-found heading -> text-color-primary; warning icon -> text-color-feedback-warning

Signed-off-by: Nathan Walston <nwalston@nvidia.com>
Signed-off-by: Nathan Walston <nwalston@nvidia.com>
… [ASE-186]

text-color-* is the CSS variable name (--text-color-*), not the generated
utility; Tailwind emits the short form (text-secondary, text-primary,
text-feedback-warning). Swap all compare-view text colors to those so they
actually apply — group headings + title + Clear link now text-secondary,
not-found heading text-primary, warning icon text-feedback-warning.

Signed-off-by: Nathan Walston <nwalston@nvidia.com>
Prefix nested trial options with a muted, decorative (aria-hidden) '↳' so
their child relationship to the evaluation heading reads at a glance. The
option's aria-label still carries the full '<evaluation> · Trial XXXXX'.

Signed-off-by: Nathan Walston <nwalston@nvidia.com>
The 'test case not available' branch is the terminal state, shown only
after the full group->evals->trace->run-fanout chain settles — the slowest
path. Anchor on the mounted compare view, then wait for the terminal text
with CI headroom, instead of relying on findByText's 1s default.

Signed-off-by: Nathan Walston <nwalston@nvidia.com>

@shanaiabuggy shanaiabuggy left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🚀

@walston
walston enabled auto-merge July 22, 2026 18:20
@walston
walston added this pull request to the merge queue Jul 22, 2026
Merged via the queue into main with commit 853919a Jul 22, 2026
60 checks passed
@walston
walston deleted the nwalston/ase-186-trace-comparison-view branch July 22, 2026 19:20
soluwalana pushed a commit that referenced this pull request Jul 22, 2026
* feat(studio): add experiment trace comparison view [ASE-186]

Side-by-side comparison of the same test case across two sibling
experiments on the experiment trace detail page.

- "Compare to..." selector in the page header lists same-dataset sibling
  experiments; picking one adds ?compareWith=<name> to the URL (preserving
  any active ?spanId= deep link) and splits into a two-column comparison
- Each column: heading row (experiment name, expand/collapse/close), a
  metrics card (Correctness, Latency, Tkns In/Out, Cached Tkns), and the
  trace in list mode; missing sessions show "Test case not available"
- TraceSpanAccordions is now controlled: single view binds selection to the
  URL, each compare column owns selection in local state keyed by traceId;
  expand/collapse surface to the column header via SlotHeaderRenderProp
- Refresh invalidation scoped to the specific trace's query key

Signed-off-by: Nathan Walston <nwalston@nvidia.com>

* feat(studio): compare test-case runs across a group [ASE-186]

Address Shanaia's review — the comparison axis is now runs of the same
test case, not experiments:

- Compare selector lists every run (session) of the test case across the
  group's evaluations (FE fan-out per evaluation via useTestCaseRuns),
  labeled '<evaluation-name> · Trial <session_id last 5>'; ?compareWith=
  now carries the selected run's trace_id
- Label above the selector: 'Compare against another run of this test case'
- Page header: 'Test case comparison — Test case <test_case_id>';
  subheader: 'See how this test case performed across different runs'
- Metrics card is now per-session (not experiment rollups): cost, latency,
  tokens in/out, cached tokens, and all evaluator scores
- Removed the per-column close buttons (kept the header Clear link)

Signed-off-by: Nathan Walston <nwalston@nvidia.com>

* feat(studio): grouped run selector for trace comparison [ASE-186]

Refine the compare selector per design feedback (Rob/Shanaia):

- Replace the flat single-select with a grouped Dropdown menu: a panel
  title, each evaluation run as a section heading, its trials listed as
  'Trial XXXXX' rows (no repeated evaluation name per row)
- Descriptive text lives in the trigger ('Compare against evaluation run');
  removed the separate label above the control
- Picking a trial swaps the comparison column (cap stays 1 compare run for
  now); the primary run is a fixed anchor and never an option
- Add a test covering open -> grouped runs -> select -> enters comparison

Signed-off-by: Nathan Walston <nwalston@nvidia.com>

* fix(studio): correct compare run selector styling and loading state [ASE-186]

- Rebuild the selector on the Select control (nv-input styling) instead of
  the Dropdown menu, keeping grouped runs via DropdownSection/DropdownHeading
  inside the listbox — matches the mockup and other grouped selects
- Fixed trigger label via renderValue + placeholder (does not echo the
  selected run)
- Loading now shows a disabled control with 'Loading other runs' across the
  whole group->evaluations->trace->runs chain; 'No runs to compare to' only
  once loaded with no siblings
- Add CompareRunSelect state tests (loading/empty/ready)

Signed-off-by: Nathan Walston <nwalston@nvidia.com>

* fix(studio): tighten compare run dropdown to match mockup [ASE-186]

- Drop DropdownSection (the source of the divider rules between runs) and
  use compact listbox density for a tighter list
- Show hierarchy the way the mockup does: bold evaluation-run heading with
  its trials indented beneath as 'Trial XXXXX'
- a11y: each option carries an aria-label of the full '<evaluation> · Trial
  XXXXX' so screen readers get self-describing options rather than relying
  on visual weight/indent alone

Signed-off-by: Nathan Walston <nwalston@nvidia.com>

* fix(studio): unclip run headings and collapse single-trial evals [ASE-186]

- Fix vertically clipped evaluation headings: the scroll container was a
  flex Stack, so overflowing children were shrunk and clipped; use a block
  div with overflow-y-auto so rows keep their height
- Collapse evaluations with a single trial onto one selectable line
  ('<evaluation> · Trial XXXXX'); evaluations with multiple trials keep the
  nested heading + indented trials (per Shanaia)
- Cover both paths in CompareRunSelect tests

Signed-off-by: Nathan Walston <nwalston@nvidia.com>

* fix(studio): center loading spinner in compare run trigger [ASE-186]

TextInputSpinner forces className=h-full, which stretched its wrapper and
pinned the fixed-size spinner to the top of the trigger. Use a plain
size=small Spinner so the trigger's centered slot aligns it vertically.

Signed-off-by: Nathan Walston <nwalston@nvidia.com>

* fix(studio): drop off-center loading spinner from compare trigger [ASE-186]

The loading affordance is the disabled control + 'Loading other runs'
placeholder; the extra slotEnd spinner sat off-center next to the chevron
and added nothing over the disabled state.

Signed-off-by: Nathan Walston <nwalston@nvidia.com>

* fix(studio): compare dropdown hierarchy — bold options, subdued labels, real indent [ASE-186]

- Clickable rows (collapsed lines + nested trials) are now bold; labels
  (panel title + evaluation group headings) are secondary/subdued, so weight
  reads as 'bold = actionable'
- Panel title gets extra bottom spacing to separate it from the list
- Fix trial indentation: SelectItem's own padding overrode a className on the
  item, so indent the content (inner Text) instead

Signed-off-by: Nathan Walston <nwalston@nvidia.com>

* fix(studio): use valid text-color-* utilities in compare dropdown [ASE-186]

text-content-*/text-status-* aren't produced by the Foundations tailwind
plugin (it namespaces semantic text colors as text-color-*), so those class
names were silent no-ops and never subdued anything.

- Group headings -> text-color-subtle (most muted, per feedback)
- Panel title + Clear link + not-found body -> text-color-secondary
- Not-found heading -> text-color-primary; warning icon -> text-color-feedback-warning

Signed-off-by: Nathan Walston <nwalston@nvidia.com>

* style(studio): compare group headings use text-color-secondary [ASE-186]

Signed-off-by: Nathan Walston <nwalston@nvidia.com>

* fix(studio): use real short-form text color utilities in compare view [ASE-186]

text-color-* is the CSS variable name (--text-color-*), not the generated
utility; Tailwind emits the short form (text-secondary, text-primary,
text-feedback-warning). Swap all compare-view text colors to those so they
actually apply — group headings + title + Clear link now text-secondary,
not-found heading text-primary, warning icon text-feedback-warning.

Signed-off-by: Nathan Walston <nwalston@nvidia.com>

* style(studio): add child marker to nested trial rows [ASE-186]

Prefix nested trial options with a muted, decorative (aria-hidden) '↳' so
their child relationship to the evaluation heading reads at a glance. The
option's aria-label still carries the full '<evaluation> · Trial XXXXX'.

Signed-off-by: Nathan Walston <nwalston@nvidia.com>

* test(studio): stabilize not-available compare test for slow CI [ASE-186]

The 'test case not available' branch is the terminal state, shown only
after the full group->evals->trace->run-fanout chain settles — the slowest
path. Anchor on the mounted compare view, then wait for the terminal text
with CI headroom, instead of relying on findByText's 1s default.

Signed-off-by: Nathan Walston <nwalston@nvidia.com>

---------

Signed-off-by: Nathan Walston <nwalston@nvidia.com>
Signed-off-by: Sam Oluwalana <soluwalana@nvidia.com>
shanaiabuggy added a commit that referenced this pull request Jul 22, 2026
Resolve conflicts from #641 (trace comparison view) landing on main:
- Keep the session-detail direction for the shared IntakeDetail components
  (TraceDetailView, TraceSpanAccordions).
- Drop the now-orphaned trace-based comparison (EvaluationTraceDetailRoute,
  IntakeTraceDetailRoute): the router points at session routes and the
  comparison is superseded by session detail views. It is re-homed onto the
  session pattern in a follow-up commit.

Signed-off-by: shanaiabuggy <59746633+shanaiabuggy@users.noreply.github.com>
shanaiabuggy added a commit that referenced this pull request Jul 23, 2026
…r button [ASE-186]

The session-based test-case comparison refactor lost several affordances from
the original trace comparison (#641) after main merged into this branch and the
shared trace components resolved to the session-view versions:

* The "Compare against evaluation run" selector only rendered once ?compareWith
  was already set, so it was unreachable. Restore it as an entry point in the
  single session view's header (new useSessionCompareRuns hook shared by both
  the single and compare views); picking a run sets ?compareWith.
* Compare columns fell back to the flat span tree. Rebuild SessionCompareColumn
  on the read-only SpanListView so each span renders as an expandable accordion
  row with Attributes / Evaluation Context, per-row feedback, and expand/collapse
  controls — local open-state keeps the two columns from fighting over ?spanId.
* Re-add the Clear button beside the selector in compare mode.

Add default MSW handlers + fixtures for experiment-groups / evaluations /
evaluation-sessions (the single session view now fetches sibling runs) and a
regression test for the compare entry point.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: shanaiabuggy <59746633+shanaiabuggy@users.noreply.github.com>
shanaiabuggy added a commit that referenced this pull request Jul 23, 2026
…ws [ASE-186]

Reworks the trace comparison from #641 to follow the session detail model: the
test-case comparison now renders two side-by-side session (test case) views
instead of two trace detail views, driven by ?compareWith on the evaluation
session route.

Studio:
* Compare inside EvaluationSessionDetailRoute via ?compareWith, rendering two
  SessionCompareColumns; re-key the run selector and test-case run fetching from
  trace_id to session_id. New useSessionCompareRuns hook is shared by the single
  session view and the compare view (React Query dedupes the overlapping fetches).
* Restore the "Compare against evaluation run" selector as an entry point in the
  single session view's header — picking a run sets ?compareWith — plus the
  Clear button beside it in compare mode.
* Render each compare column on the read-only SpanListView so spans show as
  expandable accordion rows (Attributes / Evaluation Context, per-row feedback,
  expand/collapse) with local open-state, rather than the flat span tree.
* Add default MSW handlers + fixtures for experiment-groups / evaluations /
  evaluation-sessions and a regression test for the compare entry point.

Seed:
* seed_experiments_demo.py gains a cost_usd_cycle knob and a
  secondary-sort-fixtures group with tied per-session and aggregate costs, so the
  tables' secondary (tie-break) sort can be exercised locally.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: shanaiabuggy <59746633+shanaiabuggy@users.noreply.github.com>
AnuradhaKaruppiah pushed a commit to AnuradhaKaruppiah/nemo-platform that referenced this pull request Jul 24, 2026
* feat(studio): add session telemetry detail views

Signed-off-by: Brian Newsom <brnewsom@nvidia.com>

* style(studio): format session detail views

Signed-off-by: Brian Newsom <brnewsom@nvidia.com>

* test(studio): stabilize linked span hydration

Signed-off-by: Brian Newsom <brnewsom@nvidia.com>

* fix(studio): encode session route identifiers

Signed-off-by: Brian Newsom <brnewsom@nvidia.com>

* feat(studio): render test-case comparison as side-by-side session views [ASE-186]

Reworks the trace comparison from NVIDIA-NeMo#641 to follow the session detail model: the
test-case comparison now renders two side-by-side session (test case) views
instead of two trace detail views, driven by ?compareWith on the evaluation
session route.

Studio:
* Compare inside EvaluationSessionDetailRoute via ?compareWith, rendering two
  SessionCompareColumns; re-key the run selector and test-case run fetching from
  trace_id to session_id. New useSessionCompareRuns hook is shared by the single
  session view and the compare view (React Query dedupes the overlapping fetches).
* Restore the "Compare against evaluation run" selector as an entry point in the
  single session view's header — picking a run sets ?compareWith — plus the
  Clear button beside it in compare mode.
* Render each compare column on the read-only SpanListView so spans show as
  expandable accordion rows (Attributes / Evaluation Context, per-row feedback,
  expand/collapse) with local open-state, rather than the flat span tree.
* Add default MSW handlers + fixtures for experiment-groups / evaluations /
  evaluation-sessions and a regression test for the compare entry point.

Seed:
* seed_experiments_demo.py gains a cost_usd_cycle knob and a
  secondary-sort-fixtures group with tied per-session and aggregate costs, so the
  tables' secondary (tie-break) sort can be exercised locally.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: shanaiabuggy <59746633+shanaiabuggy@users.noreply.github.com>

* fix flaky test

Signed-off-by: shanaiabuggy <59746633+shanaiabuggy@users.noreply.github.com>

---------

Signed-off-by: Brian Newsom <brnewsom@nvidia.com>
Signed-off-by: shanaiabuggy <59746633+shanaiabuggy@users.noreply.github.com>
Co-authored-by: shanaiabuggy <59746633+shanaiabuggy@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
AnuradhaKaruppiah pushed a commit to AnuradhaKaruppiah/nemo-platform that referenced this pull request Jul 24, 2026
* feat(studio): add session telemetry detail views

Signed-off-by: Brian Newsom <brnewsom@nvidia.com>

* style(studio): format session detail views

Signed-off-by: Brian Newsom <brnewsom@nvidia.com>

* test(studio): stabilize linked span hydration

Signed-off-by: Brian Newsom <brnewsom@nvidia.com>

* fix(studio): encode session route identifiers

Signed-off-by: Brian Newsom <brnewsom@nvidia.com>

* feat(studio): render test-case comparison as side-by-side session views [ASE-186]

Reworks the trace comparison from NVIDIA-NeMo#641 to follow the session detail model: the
test-case comparison now renders two side-by-side session (test case) views
instead of two trace detail views, driven by ?compareWith on the evaluation
session route.

Studio:
* Compare inside EvaluationSessionDetailRoute via ?compareWith, rendering two
  SessionCompareColumns; re-key the run selector and test-case run fetching from
  trace_id to session_id. New useSessionCompareRuns hook is shared by the single
  session view and the compare view (React Query dedupes the overlapping fetches).
* Restore the "Compare against evaluation run" selector as an entry point in the
  single session view's header — picking a run sets ?compareWith — plus the
  Clear button beside it in compare mode.
* Render each compare column on the read-only SpanListView so spans show as
  expandable accordion rows (Attributes / Evaluation Context, per-row feedback,
  expand/collapse) with local open-state, rather than the flat span tree.
* Add default MSW handlers + fixtures for experiment-groups / evaluations /
  evaluation-sessions and a regression test for the compare entry point.

Seed:
* seed_experiments_demo.py gains a cost_usd_cycle knob and a
  secondary-sort-fixtures group with tied per-session and aggregate costs, so the
  tables' secondary (tie-break) sort can be exercised locally.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: shanaiabuggy <59746633+shanaiabuggy@users.noreply.github.com>

* fix flaky test

Signed-off-by: shanaiabuggy <59746633+shanaiabuggy@users.noreply.github.com>

---------

Signed-off-by: Brian Newsom <brnewsom@nvidia.com>
Signed-off-by: shanaiabuggy <59746633+shanaiabuggy@users.noreply.github.com>
Co-authored-by: shanaiabuggy <59746633+shanaiabuggy@users.noreply.github.com>
Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants