Skip to content

feat(studio): Implement designs for intake trace and span views#460

Open
rrhyne wants to merge 7 commits into
mainfrom
rrhyne/intake-trace-span-views
Open

feat(studio): Implement designs for intake trace and span views#460
rrhyne wants to merge 7 commits into
mainfrom
rrhyne/intake-trace-span-views

Conversation

@rrhyne

@rrhyne rrhyne commented Jun 25, 2026

Copy link
Copy Markdown

Summary

Adds accordion + trajectory-tree trace/span detail views to Studio, with self-describing per-kind span templates.

  • Trace view: hierarchical trajectory tree beside collapsible span accordions; summary header (status + start/end timing, Total Tokens / Total Cost KPIs with per-direction breakdown popovers); trace error banner; trace metadata + raw-JSON debug.
  • Per-kind span templates (LLM, Tool, Retriever, Embedding, Agent, Reranker, Evaluator, Guardrail, Chain): each a self-describing descriptor (*SpanTemplate.ts) + body (*SpanContent.tsx) owning its elevated fields, section selection, and row-header title/badge. Registry is pure wiring with a generic default for UNKNOWN, so it is total.
  • Span body: error banner, kind body, shared section catalog (Usage / Input / Output / Metadata / Annotations), raw-JSON debug toggle. Metadata drops fields surfaced elsewhere.
  • Row headers: kind badge with accent-tinted icon, kind-elevated title, compact tooltip-labeled metrics.
  • Reusable atoms under IntakeComponents; lists under IntakeLists.

Annotations form (Figma alignment)

  • AnnotationsPanel: "Note" → "Notes" label; feedback column given a fixed width (was w-fit, which collapsed under FormField's intrinsic width:100% and wrapped/clipped the thumb buttons); row now wraps gracefully on narrow containers.

Testing

  • pnpm --filter nemo-studio-ui test — AnnotationsPanel suite passes.
  • Typecheck: no new errors introduced (pre-existing unrelated errors remain in evaluator/experiment routes).

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added refreshed Trace and Span detail experiences with accordion-based metadata, tree/list span navigation, and improved headers.
    • Introduced span-kind templates (LLM, Tool, Retriever, Reranker, Evaluator, Guardrail, Chain, Agent, Embedding) plus a kind badge and richer key/value rendering.
    • Added annotation management (feedback + notes), “Add note” focusing, and expandable raw JSON debugging.
  • Bug Fixes
    • Improved multi-open accordion behavior and strengthened loading/empty/error handling across annotations and detail panels.
  • Documentation
    • Updated Intake Detail documentation for the new layout and span template structure.

@rrhyne rrhyne requested review from a team as code owners June 25, 2026 17:00
@rrhyne rrhyne force-pushed the rrhyne/intake-trace-span-views branch 2 times, most recently from 7302f47 to 2b444ad Compare June 25, 2026 17:15
@github-actions

github-actions Bot commented Jun 25, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 21322/27924 76.4% 61.4%
Integration Tests 12350/26693 46.3% 19.7%

@coderabbitai

coderabbitai Bot commented Jun 25, 2026

Copy link
Copy Markdown

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

Adds intake UI primitives, span template infrastructure, span and trace detail views, route wiring, and a deterministic showcase seeding script.

Changes

Studio intake detail rebuild

Layer / File(s) Summary
Shared accordion and key/value primitives
web/packages/common/src/components/IntakeAccordion/*, web/packages/common/src/components/KeyValueGrid/index.tsx, web/packages/studio/src/components/IntakeDetail/IntakeComponents/{KeyValueRows.tsx,keyValueFormatting.ts,keyValueTypes.ts,RawJsonDebug.tsx,SpanPayloadBlock.tsx,IntakeErrorBanner.tsx}
Adds shared accordion, key/value, JSON, payload, and banner primitives used by intake detail components.
Span kind badges
web/packages/studio/src/components/SpanKindBadge/*, web/packages/studio/src/components/IntakeDetail/IntakeComponents/IntakeTelemetryStatusBadge.test.tsx
Adds span-kind badge config, rendering, and related test wiring.
Template contracts and raw-attribute helpers
web/packages/studio/src/components/IntakeDetail/SpanTemplates/{types.ts,rawAttributes.ts,rawAttributes.test.ts,templateFields.tsx,registry.ts}
Adds span template types, raw-attribute parsing, field renderers, registry lookup, and raw-attribute tests.
Span and trace key-value builders
web/packages/studio/src/components/IntakeDetail/IntakeComponents/{spanKeyValues.tsx,spanKeyValues.test.tsx,traceKeyValues.tsx,traceKeyValues.test.tsx}
Builds span summary and LLM entries plus trace summary, highlight metrics, and experiment-context entries.
Basic span templates
web/packages/studio/src/components/IntakeDetail/SpanTemplates/{DefaultSpan*,AgentSpan*,ChainSpan*,EmbeddingSpan*,ToolSpan*}
Adds fallback and simple kind templates for default, agent, chain, embedding, and tool spans.
Rich span templates
web/packages/studio/src/components/IntakeDetail/SpanTemplates/{LlmSpan*,EvaluatorSpan*,GuardrailSpan*,RetrieverSpan*,RerankerSpan*}
Adds LLM, evaluator, guardrail, retriever, and reranker template renderers and descriptors.
Span annotations and feedback
web/packages/studio/src/components/IntakeDetail/IntakeComponents/{useSpanAnnotationActions.ts,SpanFeedbackControls.tsx,AnnotationsPanel.tsx,AnnotationsPanel.test.tsx}
Adds span annotation mutations, header controls, the annotations panel, and panel tests.
Trace hierarchy utilities and navigation tree
web/packages/studio/src/util/intakeTelemetry.*, web/packages/studio/src/components/IntakeDetail/TraceDetailSpanTree.tsx
Adds span-tree construction, duration calculation, and trace tree rendering.
Span metadata accordions and span detail view
web/packages/studio/src/components/IntakeDetail/{TraceDetailSummaryHeader.tsx,SpanMetadataAccordions.tsx,TraceSpanAccordionContent.tsx,SpanDetailView.tsx,SpanTriggerLabel.tsx,SpanTriggerMeta.tsx}
Adds trace summary header, span detail sections, and the standalone span page.
Trace explorer and page
web/packages/studio/src/components/IntakeDetail/{traceSpanShared.ts,TraceSpanListView.tsx,TraceSpanTreeView.tsx,TraceSpanAccordions.tsx,TraceDetailView.tsx,intakeDetail-readme.md}
Adds the trace explorer shell, list/tree views, and the trace detail page.
Route and table wiring
web/packages/studio/src/routes/IntakeSpanDetailRoute/index.tsx, web/packages/studio/src/routes/IntakeTraceDetailRoute/index.tsx, web/packages/studio/src/routes/groups/{intakeRoutes.tsx,experimentRoutes.tsx}, web/packages/studio/src/components/IntakeLists/{IntakeSpansTable.tsx,IntakeSpansTable.test.tsx,IntakeTracesTable.tsx,IntakeTracesTable.test.tsx}, web/packages/studio/src/components/dataViews/ExperimentGroupDataView/useExperimentGroupExperiments.ts
Repoints span/trace routes and intake table imports to the new view components.

Intake showcase seed script

Layer / File(s) Summary
Seeder setup
services/intake/scripts/spans/seed_span_type_showcase.py
Adds deterministic ID generation, shared emission state, and message serialization.
Seeded scenarios
services/intake/scripts/spans/seed_span_type_showcase.py
Adds the showcase trace scenarios and expected session list.
Seeder entrypoint
services/intake/scripts/spans/seed_span_type_showcase.py
Adds CLI orchestration, REST posting, preflight checks, and ingest verification.

Sequence Diagram(s)

Trace detail flow

sequenceDiagram
  participant IntakeTraceDetailView
  participant TraceSpanAccordions
  participant TraceSpanTreeView
  participant TraceSpanListView
  participant TraceSpanAccordionContent
  IntakeTraceDetailView->>TraceSpanAccordions: trace and workspace
  TraceSpanAccordions->>TraceSpanTreeView: tree mode state
  TraceSpanAccordions->>TraceSpanListView: list mode state
  TraceSpanTreeView->>TraceSpanAccordionContent: selected span details
  TraceSpanListView->>TraceSpanAccordionContent: open span details
Loading

Showcase seed flow

sequenceDiagram
  participant main
  participant DeterministicIdGenerator
  participant Seeder
  participant OTLPHTTPExporter
  participant IntakeRESTAPI
  participant _verify
  main->>DeterministicIdGenerator: workspace seed
  main->>Seeder: emit scenarios
  main->>OTLPHTTPExporter: export spans
  main->>IntakeRESTAPI: POST evaluator-results and annotations
  main->>_verify: verify expected sessions
Loading

Possibly related PRs

Suggested labels

feat

Suggested reviewers

  • BrianNewsom
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 37.50% 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.
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.
Title check ✅ Passed The title accurately summarizes the main change: implementing intake trace and span views in Studio.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch rrhyne/intake-trace-span-views

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

@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: 10

🧹 Nitpick comments (3)
web/packages/studio/src/util/intakeTelemetry.ts (1)

162-184: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicated span-partitioning logic.

Lines 163-184 replicate the spansById/childrenByParent/roots/orphans build and sort from buildSpanHierarchyRows (102-123) verbatim. Extract a shared helper so the two views can't diverge.

♻️ Extract partition helper
interface SpanPartition {
  childrenByParent: Map<string, Span[]>;
  roots: Span[];
  orphans: Span[];
}

const partitionSpans = (spans: Span[]): SpanPartition => {
  const spansById = new Map(spans.map((span) => [span.span_id, span]));
  const childrenByParent = new Map<string, Span[]>();
  const roots: Span[] = [];
  const orphans: Span[] = [];
  for (const span of spans) {
    if (span.parent_span_id && spansById.has(span.parent_span_id)) {
      const children = childrenByParent.get(span.parent_span_id) ?? [];
      children.push(span);
      childrenByParent.set(span.parent_span_id, children);
    } else if (span.parent_span_id) {
      orphans.push(span);
    } else {
      roots.push(span);
    }
  }
  for (const children of childrenByParent.values()) children.sort(compareSpansByStartedAt);
  roots.sort(compareSpansByStartedAt);
  orphans.sort(compareSpansByStartedAt);
  return { childrenByParent, roots, orphans };
};
🤖 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/util/intakeTelemetry.ts` around lines 162 - 184, The
span partitioning logic in buildSpanTree is duplicated from
buildSpanHierarchyRows, so extract the shared span-partition helper and have
both callers use it. Create a reusable helper near these functions that returns
childrenByParent, roots, and orphans, with the same sorting behavior, then
update buildSpanTree and buildSpanHierarchyRows to consume that helper instead
of rebuilding the maps inline. Use the existing symbols buildSpanTree,
buildSpanHierarchyRows, and compareSpansByStartedAt to keep the implementation
aligned.
web/packages/studio/src/components/IntakeDetail/TraceDetailSummaryHeader.tsx (1)

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

Use a density token instead of raw gap-4.

Rest of this file uses gap="density-*" / gap-density-*; gap-4 breaks token consistency.

Proposed tweak
-      <div className="ml-auto flex max-w-full flex-nowrap items-start gap-4 overflow-x-auto">
+      <div className="ml-auto flex max-w-full flex-nowrap items-start gap-density-xl overflow-x-auto">

As per coding guidelines: "Follow NVIDIA Foundations React's design tokens and theming system for consistent visual design".

🤖 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/components/IntakeDetail/TraceDetailSummaryHeader.tsx`
at line 96, The flex container in TraceDetailSummaryHeader is using a raw gap-4
value instead of the established density token pattern used elsewhere in the
file. Update that class on the main wrapper div to use the matching
density-based gap token so it stays consistent with the surrounding layout and
NVIDIA Foundations React design tokens.

Source: Coding guidelines

web/packages/studio/src/components/SpanKindBadge/index.tsx (1)

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

Use a type-only import for SpanKind.

SpanKind is only referenced in SpanKindBadgeProps, so this should be import type to match the repo rule and avoid a needless runtime import when type-preserving emit is enabled. As per coding guidelines, "web/**/*.{ts,tsx}: Use import type for type-only imports in TypeScript".

Proposed fix
-import { SpanKind } from '`@nemo/sdk/generated/platform/schema`';
+import type { SpanKind } from '`@nemo/sdk/generated/platform/schema`';
🤖 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/components/SpanKindBadge/index.tsx` at line 4,
`SpanKind` is only used in the `SpanKindBadgeProps` type, so update the import
in `SpanKindBadge` to a type-only import. Keep the existing usage in the props
type, but change the `@nemo/sdk/generated/platform/schema` import to `import
type` to satisfy the repo’s `web/**/*.{ts,tsx}` rule and avoid generating a
runtime import.

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.

Inline comments:
In `@web/packages/common/src/components/IntakeAccordion/index.tsx`:
- Around line 79-80: The IntakeAccordion trigger in the `IntakeAccordion`
component is wrapping arbitrary `ReactNode` values from `item.slotLabel` and
`item.slotEnd` in inline `span` elements, which can create invalid DOM for block
children. Update the rendering in `IntakeAccordion` to use wrappers that safely
support both inline and block content, or tighten the `slotLabel`/`slotEnd` API
so callers can only pass inline phrasing content. Keep the fix localized to the
`IntakeAccordion` component where these slots are rendered.

In
`@web/packages/studio/src/components/IntakeDetail/IntakeComponents/keyValueFormatting.ts`:
- Around line 8-19: The isMeaningfulValue type guard currently narrows to string
| number | boolean even though it returns true for non-empty arrays and objects,
which can mislead callers. Update the signature on isMeaningfulValue in
keyValueFormatting so it either returns plain boolean or widens the predicate to
include the object/array cases it accepts, while keeping the existing truthiness
checks unchanged.

In
`@web/packages/studio/src/components/IntakeDetail/IntakeComponents/KeyValueGrid.tsx`:
- Around line 14-15: The presence check in isPresentValue still treats boolean
ReactNode values as present, which can produce empty-looking rows in
KeyValueGrid; update the isPresentValue helper to also reject true and false (or
normalize booleans before they reach this component) so only renderable values
are considered present.

In
`@web/packages/studio/src/components/IntakeDetail/IntakeComponents/KeyValueRows.tsx`:
- Around line 15-23: The row renderer in KeyValueRows currently ignores
KeyValueEntry.wrapValue and always applies break-all to the value cell, which
makes it inconsistent with the shared KeyValueEntry contract and KeyValueGrid.
Update the value rendering inside the entries.map block to respect
entry.wrapValue, using the wrapped styling only when that flag is set and
preserving the non-wrapping/default behavior otherwise.

In
`@web/packages/studio/src/components/IntakeDetail/IntakeComponents/RawJsonDebug.tsx`:
- Around line 21-22: `RawJsonDebug` currently serializes `value` directly in the
`useMemo` callback, which can throw for circular references or `BigInt` and
break the detail view. Update the `json` computation in `RawJsonDebug.tsx` to
wrap `JSON.stringify(value, null, 2)` in a `try/catch`, and return a safe
fallback like `[unserializable value]` when serialization fails so the component
still renders.

In
`@web/packages/studio/src/components/IntakeDetail/IntakeComponents/SpanFeedbackControls.tsx`:
- Line 37: The header feedback action in SpanFeedbackControls is swallowing
failures because useSpanAnnotationActions is destructured without the exposed
error state. Update the SpanFeedbackControls component to also read error from
useSpanAnnotationActions and surface it through the existing UI pattern used in
this area, such as a toast or tooltip, so a failed submitFeedback click is
visible instead of silently ignored.

In
`@web/packages/studio/src/components/IntakeDetail/IntakeComponents/SpanPayloadBlock.tsx`:
- Around line 17-22: The SpanPayloadBlock rendering logic is altering the
payload by calling trim() before passing it to CodeSnippet, which changes the
displayed request/response body. Update the value handling in SpanPayloadBlock
so the original value is rendered unchanged, and use trimming only to determine
whether the payload is empty (keep the existing content check but pass the
unmodified value through).

In
`@web/packages/studio/src/components/IntakeDetail/IntakeComponents/useSpanAnnotationActions.ts`:
- Around line 56-77: The submitFeedback callback in useSpanAnnotationActions
currently only creates a new feedback annotation, so repeated submissions can
duplicate rows and counts. Update this flow to replace any existing feedback for
the same span before calling createAnnotation.mutateAsync, or switch to an
explicit upsert/replace API path keyed by span_id and feedback kind. Keep the
change localized to submitFeedback and any related annotation mutation helpers
used there.

In
`@web/packages/studio/src/components/IntakeDetail/SpanTemplates/DefaultSpanTemplate.ts`:
- Around line 12-15: The fallback span template is not matching the shared
SpanTemplate contract because defaultSpanTemplate includes both Content and the
'kind' section even though the generic fallback is documented to omit them.
Update DefaultSpanTemplate so the fallback layout aligns with types.ts by
removing the extra Content and 'kind' entry, and keep the template shape
consistent with the intended fallback behavior.

In
`@web/packages/studio/src/components/IntakeDetail/SpanTemplates/ToolSpanContent.tsx`:
- Around line 22-28: The Tool span template is rendering duration twice because
TemplateKeyValues already adds the shared timing fields. Update
ToolSpanContent’s fields array to remove the explicit Duration entry and keep
only the tool-specific values (e.g. Tool and Description), so the rendered
output does not duplicate duration.

---

Nitpick comments:
In
`@web/packages/studio/src/components/IntakeDetail/TraceDetailSummaryHeader.tsx`:
- Line 96: The flex container in TraceDetailSummaryHeader is using a raw gap-4
value instead of the established density token pattern used elsewhere in the
file. Update that class on the main wrapper div to use the matching
density-based gap token so it stays consistent with the surrounding layout and
NVIDIA Foundations React design tokens.

In `@web/packages/studio/src/components/SpanKindBadge/index.tsx`:
- Line 4: `SpanKind` is only used in the `SpanKindBadgeProps` type, so update
the import in `SpanKindBadge` to a type-only import. Keep the existing usage in
the props type, but change the `@nemo/sdk/generated/platform/schema` import to
`import type` to satisfy the repo’s `web/**/*.{ts,tsx}` rule and avoid
generating a runtime import.

In `@web/packages/studio/src/util/intakeTelemetry.ts`:
- Around line 162-184: The span partitioning logic in buildSpanTree is
duplicated from buildSpanHierarchyRows, so extract the shared span-partition
helper and have both callers use it. Create a reusable helper near these
functions that returns childrenByParent, roots, and orphans, with the same
sorting behavior, then update buildSpanTree and buildSpanHierarchyRows to
consume that helper instead of rebuilding the maps inline. Use the existing
symbols buildSpanTree, buildSpanHierarchyRows, and compareSpansByStartedAt to
keep the implementation aligned.
🪄 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: 3de569f7-e4f6-4ee9-9ee6-7d92ba82f920

📥 Commits

Reviewing files that changed from the base of the PR and between d124a7a and 2b444ad.

📒 Files selected for processing (68)
  • web/packages/common/src/components/IntakeAccordion/IntakeAccordion.css
  • web/packages/common/src/components/IntakeAccordion/index.test.tsx
  • web/packages/common/src/components/IntakeAccordion/index.tsx
  • web/packages/studio/src/components/IntakeAnnotationsPanel/index.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/AnnotationsPanel.test.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/AnnotationsPanel.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/IntakeErrorBanner.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/IntakeTelemetryStatusBadge.test.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/IntakeTelemetryStatusBadge.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/KeyValueGrid.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/KeyValueRows.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/RawJsonDebug.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/SpanFeedbackControls.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/SpanPayloadBlock.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/keyValueFormatting.ts
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/keyValueTypes.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/spanKeyValues.test.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/spanKeyValues.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/traceKeyValues.test.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/traceKeyValues.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/useSpanAnnotationActions.ts
  • web/packages/studio/src/components/IntakeDetail/SpanDetailView.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanMetadataAccordions.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/AgentSpanContent.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/AgentSpanTemplate.ts
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/ChainSpanContent.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/ChainSpanTemplate.ts
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/DefaultSpanContent.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/DefaultSpanTemplate.ts
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/EmbeddingSpanContent.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/EmbeddingSpanTemplate.ts
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/EvaluatorSpanContent.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/EvaluatorSpanTemplate.ts
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/GuardrailSpanContent.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/GuardrailSpanTemplate.ts
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/LlmSpanContent.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/LlmSpanTemplate.ts
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/RerankerSpanContent.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/RerankerSpanTemplate.ts
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/RetrieverSpanContent.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/RetrieverSpanTemplate.ts
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/ToolSpanContent.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/ToolSpanTemplate.ts
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/rawAttributes.test.ts
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/rawAttributes.ts
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/registry.ts
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/templateFields.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/types.ts
  • web/packages/studio/src/components/IntakeDetail/TraceDetailSpanTree.css
  • web/packages/studio/src/components/IntakeDetail/TraceDetailSpanTree.tsx
  • web/packages/studio/src/components/IntakeDetail/TraceDetailSummaryHeader.tsx
  • web/packages/studio/src/components/IntakeDetail/TraceDetailView.tsx
  • web/packages/studio/src/components/IntakeDetail/TraceSpanAccordionContent.tsx
  • web/packages/studio/src/components/IntakeDetail/TraceSpanAccordions.tsx
  • web/packages/studio/src/components/IntakeDetail/intakeDetail-readme.md
  • web/packages/studio/src/components/IntakeLists/IntakeSpansTable.test.tsx
  • web/packages/studio/src/components/IntakeLists/IntakeSpansTable.tsx
  • web/packages/studio/src/components/IntakeLists/IntakeTelemetryDataView.tsx
  • web/packages/studio/src/components/IntakeLists/IntakeTracesTable.test.tsx
  • web/packages/studio/src/components/IntakeLists/IntakeTracesTable.tsx
  • web/packages/studio/src/components/SpanKindBadge/index.test.tsx
  • web/packages/studio/src/components/SpanKindBadge/index.tsx
  • web/packages/studio/src/components/SpanKindBadge/spanKindConfig.ts
  • web/packages/studio/src/routes/IntakeSpanDetailRoute/index.tsx
  • web/packages/studio/src/routes/IntakeTraceDetailRoute/index.tsx
  • web/packages/studio/src/routes/groups/intakeRoutes.tsx
  • web/packages/studio/src/util/intakeTelemetry.test.ts
  • web/packages/studio/src/util/intakeTelemetry.ts
💤 Files with no reviewable changes (1)
  • web/packages/studio/src/components/IntakeAnnotationsPanel/index.tsx

Comment thread web/packages/common/src/components/IntakeAccordion/index.tsx Outdated
Comment thread web/packages/studio/src/components/IntakeDetail/IntakeComponents/KeyValueGrid.tsx Outdated
Comment thread web/packages/studio/src/components/IntakeDetail/IntakeComponents/KeyValueRows.tsx Outdated
Comment thread web/packages/studio/src/components/IntakeDetail/IntakeComponents/RawJsonDebug.tsx Outdated
Comment thread web/packages/common/src/components/IntakeAccordion/index.tsx Outdated
Comment thread web/packages/studio/src/components/IntakeDetail/IntakeComponents/KeyValueGrid.tsx Outdated
Comment thread web/packages/studio/src/components/IntakeDetail/IntakeComponents/KeyValueGrid.tsx Outdated
Comment thread web/packages/common/src/components/KeyValueGrid/index.tsx
Comment thread web/packages/studio/src/components/IntakeDetail/IntakeComponents/RawJsonDebug.tsx Outdated

@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: 2

🧹 Nitpick comments (1)
services/intake/scripts/spans/seed_span_type_showcase.py (1)

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

Use concrete annotations here.

from __future__ import annotations stringifies all annotations; this file has no forward refs requiring it. Remove it. As per coding guidelines, **/*.py: "Always prefer concrete type hints over string-based ones in Python code; do not import types under TYPE_CHECKING, instead import types as regular imports when possible."

🤖 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 `@services/intake/scripts/spans/seed_span_type_showcase.py` at line 48, Remove
the unnecessary from __future__ import annotations from
seed_span_type_showcase.py and keep the file using concrete type hints directly,
since there are no forward references. Review the annotations in the
module-level code and any functions/classes there to ensure they remain valid
without stringification, and leave regular imports in place rather than relying
on postponed evaluation.

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.

Inline comments:
In `@services/intake/scripts/spans/seed_span_type_showcase.py`:
- Around line 765-772: The _post_annotations helper currently POSTs every
showcase annotation on each run, which creates duplicate ann-{uuid} records.
Update _post_annotations in seed_span_type_showcase.py to make writes idempotent
by checking for existing showcase annotations before posting, or by
deleting/cleaning existing ones first; use the existing client, base_url,
workspace, and annotations flow to locate the logic and ensure reruns do not
create duplicate feedback, labels, or notes.
- Around line 796-805: The _verify helper currently only prints the visible
showcase sessions, so it can report success even when no seeded traces were
ingested. Update _verify in seed_span_type_showcase.py to validate the expected
showcase- session IDs after the httpx.get call, and raise an error if the
filtered showcase list is empty or otherwise missing required sessions. Keep the
existing response.raise_for_status and session collection logic, but make the
verification fail fast instead of printing a success message when ingestion did
not produce the expected traces.

---

Nitpick comments:
In `@services/intake/scripts/spans/seed_span_type_showcase.py`:
- Line 48: Remove the unnecessary from __future__ import annotations from
seed_span_type_showcase.py and keep the file using concrete type hints directly,
since there are no forward references. Review the annotations in the
module-level code and any functions/classes there to ensure they remain valid
without stringification, and leave regular imports in place rather than relying
on postponed evaluation.
🪄 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: 6050bbfd-75e6-475e-9e91-ee789ff547e6

📥 Commits

Reviewing files that changed from the base of the PR and between b67d34e and 5ce5ee3.

📒 Files selected for processing (1)
  • services/intake/scripts/spans/seed_span_type_showcase.py

Comment thread services/intake/scripts/spans/seed_span_type_showcase.py Outdated
Comment thread services/intake/scripts/spans/seed_span_type_showcase.py
Comment thread web/packages/studio/src/components/IntakeDetail/SpanTemplates/LlmSpanContent.tsx Outdated
Comment thread web/packages/studio/src/components/IntakeDetail/SpanTemplates/LlmSpanContent.tsx Outdated
Comment thread web/packages/studio/src/components/IntakeDetail/intakeDetail-readme.md Outdated
Comment thread web/packages/studio/src/components/IntakeDetail/TraceSpanAccordions.tsx Outdated
Comment thread web/packages/studio/src/components/IntakeDetail/TraceSpanAccordions.tsx Outdated
Comment thread web/packages/studio/src/components/IntakeDetail/TraceSpanAccordions.tsx Outdated

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

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (2)
web/packages/studio/src/components/IntakeDetail/IntakeComponents/useSpanAnnotationActions.ts (1)

58-77: 🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

Feedback replacement is still race-prone.

This is still list -> delete -> create across separate requests, and isMutating stays false during the initial listAnnotations call. Two rapid clicks can start overlapping runs before the buttons disable, and concurrent clients can still leave duplicate feedback rows. Use a single replace/upsert contract server-side, or at minimum track a local pending state for the whole callback.

Also applies to: 139-141

🤖 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/components/IntakeDetail/IntakeComponents/useSpanAnnotationActions.ts`
around lines 58 - 77, The feedback replace flow in
useSpanAnnotationActions.submitFeedback is still race-prone because it does
listAnnotations, deleteMutation.mutateAsync, then create in separate requests
while isMutating is false during the initial fetch. Update the feedback path to
use a single server-side replace/upsert contract if available, or add a local
pending state around the entire submitFeedback callback so the UI blocks
re-entry until the full operation completes. Also make the same fix for the
other feedback submission path referenced in the component so duplicate feedback
rows cannot be created by rapid clicks or concurrent clients.
web/packages/studio/src/components/IntakeDetail/SpanTemplates/templateFields.tsx (1)

75-86: 🎯 Functional Correctness | 🟡 Minor

Use a stable key instead of field.label. TemplateKeyValues passes display labels through as React keys, so any repeated label or param-label collision will trigger duplicate keys and can drop rows. Add a separate field id 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
`@web/packages/studio/src/components/IntakeDetail/SpanTemplates/templateFields.tsx`
around lines 75 - 86, TemplateKeyValues is using field.label as the React key in
KeyValueGrid, which can collide when labels repeat or when param labels match.
Update the TemplateKeyValues mapping to carry a stable unique identifier on each
item, and use that identifier for key instead of the display label. Adjust the
related field construction in statusField, timingFields, and the TemplateField
shape as needed so each rendered row has a unique id while keeping label and
value unchanged.
🤖 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.

Outside diff comments:
In
`@web/packages/studio/src/components/IntakeDetail/IntakeComponents/useSpanAnnotationActions.ts`:
- Around line 58-77: The feedback replace flow in
useSpanAnnotationActions.submitFeedback is still race-prone because it does
listAnnotations, deleteMutation.mutateAsync, then create in separate requests
while isMutating is false during the initial fetch. Update the feedback path to
use a single server-side replace/upsert contract if available, or add a local
pending state around the entire submitFeedback callback so the UI blocks
re-entry until the full operation completes. Also make the same fix for the
other feedback submission path referenced in the component so duplicate feedback
rows cannot be created by rapid clicks or concurrent clients.

In
`@web/packages/studio/src/components/IntakeDetail/SpanTemplates/templateFields.tsx`:
- Around line 75-86: TemplateKeyValues is using field.label as the React key in
KeyValueGrid, which can collide when labels repeat or when param labels match.
Update the TemplateKeyValues mapping to carry a stable unique identifier on each
item, and use that identifier for key instead of the display label. Adjust the
related field construction in statusField, timingFields, and the TemplateField
shape as needed so each rendered row has a unique id while keeping label and
value unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 956514fc-2cc7-47c2-9c57-47e62c710f6a

📥 Commits

Reviewing files that changed from the base of the PR and between 5ce5ee3 and 6348007.

📒 Files selected for processing (32)
  • services/intake/scripts/spans/seed_span_type_showcase.py
  • web/packages/common/src/components/IntakeAccordion/index.tsx
  • web/packages/common/src/components/KeyValueGrid/index.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/AnnotationsPanel.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/KeyValueRows.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/RawJsonDebug.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/SpanFeedbackControls.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/SpanPayloadBlock.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/SpanTriggerLabel.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/SpanTriggerMeta.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/keyValueFormatting.ts
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/keyValueTypes.ts
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/spanKeyValues.test.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/spanKeyValues.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/traceKeyValues.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/useSpanAnnotationActions.ts
  • web/packages/studio/src/components/IntakeDetail/SpanMetadataAccordions.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/EvaluatorSpanContent.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/GuardrailSpanContent.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/LlmSpanContent.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/RerankerSpanContent.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/RerankerSpanTemplate.ts
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/RetrieverSpanContent.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/RetrieverSpanTemplate.ts
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/templateFields.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/types.ts
  • web/packages/studio/src/components/IntakeDetail/TraceSpanAccordions.tsx
  • web/packages/studio/src/components/IntakeDetail/TraceSpanListView.tsx
  • web/packages/studio/src/components/IntakeDetail/TraceSpanTreeView.tsx
  • web/packages/studio/src/components/IntakeDetail/traceSpanShared.ts
  • web/packages/studio/src/components/dataViews/ExperimentGroupDataView/useExperimentGroupExperiments.ts
  • web/packages/studio/src/routes/groups/experimentRoutes.tsx
💤 Files with no reviewable changes (1)
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/keyValueTypes.ts
✅ Files skipped from review due to trivial changes (1)
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/types.ts
🚧 Files skipped from review as they are similar to previous changes (16)
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/RerankerSpanTemplate.ts
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/GuardrailSpanContent.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/KeyValueRows.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/RawJsonDebug.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/RetrieverSpanTemplate.ts
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/LlmSpanContent.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/spanKeyValues.test.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/SpanPayloadBlock.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/SpanFeedbackControls.tsx
  • web/packages/common/src/components/IntakeAccordion/index.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/spanKeyValues.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanTemplates/EvaluatorSpanContent.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/AnnotationsPanel.tsx
  • web/packages/studio/src/components/IntakeDetail/SpanMetadataAccordions.tsx
  • web/packages/studio/src/components/IntakeDetail/IntakeComponents/traceKeyValues.tsx
  • services/intake/scripts/spans/seed_span_type_showcase.py

@rrhyne rrhyne requested a review from nakolean June 25, 2026 21:35
@rrhyne rrhyne force-pushed the rrhyne/intake-trace-span-views branch from a273b0d to 18304ec Compare June 26, 2026 13:16
rrhyne and others added 5 commits June 26, 2026 09:27
Accordion + trajectory-tree trace/span detail views with self-describing
per-kind templates.

- Trace view: a hierarchical trajectory tree beside collapsible span
  accordions; a summary header (status + start/end timing on the left; Total
  Tokens and Total Cost KPIs with hover popovers for the per-direction
  breakdown); a trace error banner beside the tree when the trace failed; and
  trace metadata + raw-JSON debug below.
- Per-kind span templates (LLM, Tool, Retriever, Embedding, Agent, Reranker,
  Evaluator, Guardrail, Chain): each is a self-describing descriptor
  (`*SpanTemplate.ts`) + body (`*SpanContent.tsx`) that owns its elevated
  fields, section selection, and row-header title/badge. The registry is pure
  wiring with a generic default template for UNKNOWN, so it is total.
- Span body: error banner, kind body, a shared section catalog (Usage / Input /
  Output / Metadata / Annotations), and a raw-JSON debug toggle. Metadata drops
  fields already surfaced elsewhere (status/error, template-claimed attributes).
- Row headers: kind badge with accent-tinted icon, kind-elevated title (e.g.
  evaluator name), and compact tooltip-labeled metrics (e.g. "9tk", "3.50s").
- Reusable atoms under IntakeComponents (key/value grid + rows, payload block,
  error banner, raw-JSON debug, status badge); lists under IntakeLists.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Rob Rhyne <rrhyne@nvidia.com>
Move the trace-tree and IntakeAccordion styling off `.css` files and onto the
components. KUI's styles are variable-driven and live in Tailwind's `base`
layer, so component-level Tailwind utilities (and `--nv-*` variable overrides)
win the cascade without `\!important`.

- Delete TraceDetailSpanTree.css: row width/rounding/padding, label layout, and
  kind/error icon colors are now Tailwind utilities on the rendered elements.
- IntakeAccordion: set surface, trigger/content padding, and the last-row border
  via KUI's `--nv-accordion-*` variables on the component; lay out the label/end
  groups with Tailwind. IntakeAccordion.css is reduced to the single
  `.nv-accordion-label-text` flex rule — KUI's internal trigger-children wrapper,
  which exposes neither a className nor a variable.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Rob Rhyne <rrhyne@nvidia.com>
Signed-off-by: Rob Rhyne <rrhyne@nvidia.com>
Signed-off-by: Rob Rhyne <rrhyne@nvidia.com>
Signed-off-by: Rob Rhyne <rrhyne@nvidia.com>
@rrhyne rrhyne force-pushed the rrhyne/intake-trace-span-views branch from 18304ec to 46629d6 Compare June 26, 2026 13:29
@rrhyne rrhyne changed the title Implement designs for intake trace and span views feat(studio): Implement designs for intake trace and span views Jun 26, 2026
@github-actions github-actions Bot added the feat label Jun 26, 2026
Apply prettier formatting (studio), fix ruff check/format in the intake span showcase seed script, and rename intakeDetail-readme.md -> README.md.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Signed-off-by: Rob Rhyne <rrhyne@nvidia.com>
@rrhyne rrhyne force-pushed the rrhyne/intake-trace-span-views branch from 40cd1c4 to 3d64ffa Compare June 26, 2026 14:03
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