Skip to content

feat(studio): add Insights section with experiment↔insight linking#757

Merged
callingmedic911 merged 6 commits into
mainfrom
rrhyne/insights-experiments
Jul 24, 2026
Merged

feat(studio): add Insights section with experiment↔insight linking#757
callingmedic911 merged 6 commits into
mainfrom
rrhyne/insights-experiments

Conversation

@rrhyne

@rrhyne rrhyne commented Jul 17, 2026

Copy link
Copy Markdown
Contributor

Adds the Optimizer Insights section to Studio and links insights to the experiments (evaluations) run against them:

  • Insights list + detail routes (OptimizerRoute, OptimizerInsightRoute) with status workflow and an evidence-traces table.
  • Insight → experiment-group linking via ExperimentGroup.insight_id; the evaluation detail page surfaces its originating insight.
  • ChangesetBadge with an external-link icon; "Source" column/label across the experiment, insight, and evaluation surfaces.
  • Shared evaluator score formatting and trace-column helpers.
  • Intake seed scripts for optimizer insights and insight-linked experiment groups.

Uses the platform's current hierarchy conventions: experiment group ->
experiment (container) and experiment -> evaluation (leaf).

Summary by CodeRabbit

  • New Features
    • Added an Insights/Optimizer experience in Studio with insight lists, status actions, experiment groups, evidence traces, and “Run experiment” guidance.
    • Added originating insight descriptions/links and source badges across experiment and evaluation views.
    • Added a local demo seed/cleanup workflow.
  • Improvements
    • Insights lists now show experiment counts and latest activity.
    • Experiment groups support filtering by insight ID and soft-deletion state.
    • Trace filtering now supports multiple trace IDs.
    • Updated API docs for experiment-group filter capabilities.
  • Bug Fixes
    • Preserved insight, summary, and metadata fields when editing experiment groups.

@github-actions github-actions Bot added the feat label Jul 17, 2026
@github-actions

github-actions Bot commented Jul 17, 2026

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 27158/34869 77.9% 62.2%
Integration Tests 15968/33581 47.5% 20.0%

Comment thread web/packages/studio/src/routes/index.test.tsx Outdated
@callingmedic911
callingmedic911 force-pushed the rrhyne/insights-experiments branch from 693069f to 911f8a7 Compare July 23, 2026 20:43

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

Looks good enough to me.

@callingmedic911
callingmedic911 force-pushed the rrhyne/insights-experiments branch from aa4ef87 to 487c70a Compare July 24, 2026 15:45
@callingmedic911
callingmedic911 marked this pull request as ready for review July 24, 2026 20:31
@callingmedic911
callingmedic911 requested review from a team as code owners July 24, 2026 20:31
@coderabbitai

coderabbitai Bot commented Jul 24, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

The PR adds insight-linked experiment-group filtering, enriched Insights APIs, a deterministic demo utility, and a feature-gated Studio Optimizer experience with insight details, experiment groups, traces, source links, and evaluation integration.

Changes

Backend insight enrichment and filtering

Layer / File(s) Summary
Experiment-group filter contract
openapi/..., services/intake/src/nmp/intake/api/v2/experiments/..., services/intake/tests/integration/...
Documents and implements insight_id and soft-deletion filtering for experiment groups.
Bulk trace lookup pipeline
services/intake/src/nmp/intake/spans/..., services/intake/tests/...
Supports trace-ID lists, ClickHouse external data, and latest trace timestamps grouped by insight.
Enriched insight list response
plugins/nemo-insights/src/nemo_insights_plugin/..., plugins/nemo-insights/tests/...
Adds experiment-group counts and latest trace timestamps to paginated insight results.
Deterministic demo lifecycle
plugins/nemo-insights/scripts/insights_demo.py
Adds CLI commands to seed and clean a deterministic Insights workspace through HTTP APIs.

Studio optimizer experience

Layer / File(s) Summary
Optimizer flags and routes
services/studio/..., web/packages/studio/env/..., web/packages/studio/src/constants/..., web/packages/studio/src/routes/...
Adds the optimizer feature flag, routes, lazy loading, navigation, and route-gating tests.
Optimizer API client
web/packages/studio/src/api/optimizer.ts
Adds typed list, detail, and update operations with React Query hooks.
Insight list and detail pages
web/packages/studio/src/routes/optimizer/OptimizerRoute/..., web/packages/studio/src/routes/optimizer/OptimizerInsightRoute/..., web/packages/studio/src/routes/optimizer/insightStatus.*
Adds paginated insight listings, status actions, metadata, detail content, experiment groups, observed sessions, and mutation handling.
Optimizer experiment and trace views
web/packages/studio/src/routes/optimizer/OptimizerInsightRoute/InsightExperimentGroups.tsx, web/packages/studio/src/routes/optimizer/InsightTracesTable/..., web/packages/studio/src/routes/optimizer/InsightOpenModal/...
Adds filtered experiment-group and trace tables, pagination, error states, and CLI command generation.
Insight and source links
web/packages/studio/src/components/..., web/packages/studio/src/routes/EvaluationDetailRoute/..., web/packages/studio/src/routes/ExperimentGroupDetailRoute/...
Displays source and originating-insight links and preserves producer-owned experiment-group fields during updates.
Shared intake trace columns
web/packages/studio/src/components/IntakeLists/...
Extracts reusable trace-table column definitions and wires the existing intake table to the shared factory.

Sequence Diagram(s)

sequenceDiagram
  participant Studio
  participant InsightsAPI
  participant IntakeAPI
  participant ClickHouse
  Studio->>InsightsAPI: List insights
  InsightsAPI->>IntakeAPI: Request latest trace timestamps by group
  IntakeAPI->>ClickHouse: Query grouped trace references
  ClickHouse-->>IntakeAPI: Latest started_at values
  IntakeAPI-->>InsightsAPI: Trace timestamps
  InsightsAPI-->>Studio: Enriched insight list
Loading

Possibly related PRs

Suggested labels: feat

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 11.54% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main Studio Insights addition and experiment↔insight linking.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch rrhyne/insights-experiments

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

🧹 Nitpick comments (7)
plugins/nemo-insights/scripts/insights_demo.py (1)

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

Derive the trace count instead of hardcoding 11.

♻️ Compute from the fixture
+    trace_count = sum(len(evaluation.sessions) for evaluation in evaluations)
     print(
         f"Seeded workspace '{DEMO_WORKSPACE}' with {len(fixture.insights)} insights, "
-        f"{len(fixture.groups)} groups, {len(evaluations)} evaluations, and 11 traces."
+        f"{len(fixture.groups)} groups, {len(evaluations)} evaluations, and {trace_count} traces."
     )
🤖 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 `@plugins/nemo-insights/scripts/insights_demo.py` around lines 480 - 483,
Update the seeding summary print statement to derive the trace count from the
fixture data instead of hardcoding 11, using the fixture’s existing trace
collection and preserving the rest of the message.
web/packages/studio/src/routes/WorkspaceLayout/WorkspaceSideNav.tsx (1)

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

Group third-party imports before workspace aliases.

  • web/packages/studio/src/routes/WorkspaceLayout/WorkspaceSideNav.tsx#L22-L64: move lucide-react and react before @nemo/@studio imports.
  • web/packages/studio/src/routes/optimizer/InsightTracesTable/index.test.tsx#L4-L10: move testing-library and MSW imports before workspace aliases.
  • web/packages/studio/src/components/IntakeLists/IntakeTracesTable.tsx#L11-L25: keep all third-party imports together before aliases.
  • web/packages/studio/src/components/IntakeLists/intakeTraceColumns.tsx#L4-L16: move @nvidia/foundations-react-core and react before workspace aliases.

As per coding guidelines, “Group imports: external libraries, internal modules, relative imports in TypeScript.”

🤖 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/WorkspaceLayout/WorkspaceSideNav.tsx` around
lines 22 - 64, Reorder imports to group third-party dependencies before
workspace aliases: in
web/packages/studio/src/routes/WorkspaceLayout/WorkspaceSideNav.tsx (lines
22-64), place lucide-react and react before `@nemo/`@studio imports; in
web/packages/studio/src/routes/optimizer/InsightTracesTable/index.test.tsx
(lines 4-10), place testing-library and MSW imports before aliases; in
web/packages/studio/src/components/IntakeLists/IntakeTracesTable.tsx (lines
11-25), keep all third-party imports together before aliases; and in
web/packages/studio/src/components/IntakeLists/intakeTraceColumns.tsx (lines
4-16), place `@nvidia/foundations-react-core` and react before workspace aliases.

Source: Coding guidelines

web/packages/studio/src/routes/utils.ts (1)

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

Add explicit return types to public helpers.

gateOptimizerRoutes should return RouteObject[]; both route builders should return string.

As per coding guidelines, “Use explicit return types for public APIs and complex functions in TypeScript.”

Also applies to: 397-403

🤖 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/utils.ts` around lines 106 - 108, Update the
public helper return types: declare gateOptimizerRoutes as returning
RouteObject[], and add explicit string return types to both route-builder
functions referenced near the additional location. Preserve their existing
implementations and behavior.

Source: Coding guidelines

web/packages/studio/src/routes/optimizer/InsightTracesTable/index.tsx (1)

38-51: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Pagination flicker: missing keepPreviousData.

Other tables in this PR (OptimizerRoute, InsightExperimentGroups) use placeholderData: keepPreviousData to avoid a blank/loading flash while paging. This useListTraces call doesn't, so switching trace pages will briefly clear the table.

♻️ Suggested fix
   const { data, error, isFetching } = useListTraces(
     workspace,
     {
       filter: withOperators<TraceFilter>({ id: { $in: visibleTraceIds } }),
       mode: 'preview',
       page: 1,
       page_size: pageSize,
     },
     {
       query: {
         enabled: Boolean(workspace) && visibleTraceIds.length > 0,
+        placeholderData: keepPreviousData,
       },
     }
   );

Requires importing keepPreviousData from @tanstack/react-query.

🤖 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/optimizer/InsightTracesTable/index.tsx` around
lines 38 - 51, Update the useListTraces query options in InsightTracesTable to
import and set placeholderData to keepPreviousData, preserving the current trace
rows while switching pages and avoiding a loading flicker.
web/packages/studio/src/routes/optimizer/OptimizerInsightRoute/index.tsx (1)

136-149: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

No confirmation before "Delete"/"Resolve" status change.

Both actions call updateInsight immediately on click. Per Line 71's comment, only the external agent can move status back to open — there's no UI path to undo a stray "Delete" click. Consider a confirmation step before firing the mutation.

🤖 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/optimizer/OptimizerInsightRoute/index.tsx`
around lines 136 - 149, Add a confirmation step to the action handling in
OptimizerInsightRoute before invoking updateInsight for Delete or Resolve
actions. Ensure the mutation only runs after the user confirms, while preserving
immediate handling for other insightActions targets.
web/packages/studio/src/api/optimizer.ts (2)

27-65: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Catch-all index signatures defeat interface typing.

[key: string]: unknown on Insight (Line 44) and InsightPage (Line 64) lets any misspelled property (e.g. insight.staus) type-check silently, since the index signature swallows unknown keys. Consider dropping these and letting TS flag typos/missing fields.

🤖 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/api/optimizer.ts` around lines 27 - 65, Remove the
catch-all [key: string]: unknown index signatures from the Insight and
InsightPage interfaces. Keep all explicitly declared fields unchanged so
TypeScript reports misspelled or undeclared properties while preserving the
existing API shape.

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

Add explicit return types to exported fetcher functions.

optimizerListInsights, optimizerGetInsight, and optimizerUpdateInsight are public APIs without explicit return type annotations. As per coding guidelines, "Use explicit return types for public APIs and complex functions in TypeScript."

♻️ Example fix
-export const optimizerListInsights = (
+export const optimizerListInsights = (
   workspace: string,
   params?: OptimizerListInsightsParams,
   signal?: AbortSignal
-) =>
+): Promise<InsightPage> =>
   customFetch<InsightPage>({
🤖 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/api/optimizer.ts` around lines 86 - 153, Add explicit
return type annotations to the exported fetcher functions optimizerListInsights,
optimizerGetInsight, and optimizerUpdateInsight, matching the promise/result
types returned by their customFetch calls. Leave the query hooks and query-key
helpers unchanged.

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 `@plugins/nemo-insights/scripts/insights_demo.py`:
- Around line 278-285: Update the trace availability probe in the demo request
flow to target the configured demo workspace instead of hardcoded “default”.
Narrow the status handling so only genuine service-unavailable responses map to
the ClickHouse recovery hint, while a missing workspace is handled separately
without reporting ClickHouse as down.
- Line 41: Update _BASE_TIME to derive from the current UTC run time instead of
a fixed calendar date, while preserving deterministic relative offsets used by
the seeded traces and stable session IDs.

---

Nitpick comments:
In `@plugins/nemo-insights/scripts/insights_demo.py`:
- Around line 480-483: Update the seeding summary print statement to derive the
trace count from the fixture data instead of hardcoding 11, using the fixture’s
existing trace collection and preserving the rest of the message.

In `@web/packages/studio/src/api/optimizer.ts`:
- Around line 27-65: Remove the catch-all [key: string]: unknown index
signatures from the Insight and InsightPage interfaces. Keep all explicitly
declared fields unchanged so TypeScript reports misspelled or undeclared
properties while preserving the existing API shape.
- Around line 86-153: Add explicit return type annotations to the exported
fetcher functions optimizerListInsights, optimizerGetInsight, and
optimizerUpdateInsight, matching the promise/result types returned by their
customFetch calls. Leave the query hooks and query-key helpers unchanged.

In `@web/packages/studio/src/routes/optimizer/InsightTracesTable/index.tsx`:
- Around line 38-51: Update the useListTraces query options in
InsightTracesTable to import and set placeholderData to keepPreviousData,
preserving the current trace rows while switching pages and avoiding a loading
flicker.

In `@web/packages/studio/src/routes/optimizer/OptimizerInsightRoute/index.tsx`:
- Around line 136-149: Add a confirmation step to the action handling in
OptimizerInsightRoute before invoking updateInsight for Delete or Resolve
actions. Ensure the mutation only runs after the user confirms, while preserving
immediate handling for other insightActions targets.

In `@web/packages/studio/src/routes/utils.ts`:
- Around line 106-108: Update the public helper return types: declare
gateOptimizerRoutes as returning RouteObject[], and add explicit string return
types to both route-builder functions referenced near the additional location.
Preserve their existing implementations and behavior.

In `@web/packages/studio/src/routes/WorkspaceLayout/WorkspaceSideNav.tsx`:
- Around line 22-64: Reorder imports to group third-party dependencies before
workspace aliases: in
web/packages/studio/src/routes/WorkspaceLayout/WorkspaceSideNav.tsx (lines
22-64), place lucide-react and react before `@nemo/`@studio imports; in
web/packages/studio/src/routes/optimizer/InsightTracesTable/index.test.tsx
(lines 4-10), place testing-library and MSW imports before aliases; in
web/packages/studio/src/components/IntakeLists/IntakeTracesTable.tsx (lines
11-25), keep all third-party imports together before aliases; and in
web/packages/studio/src/components/IntakeLists/intakeTraceColumns.tsx (lines
4-16), place `@nvidia/foundations-react-core` and react before workspace aliases.
🪄 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: f3b497f8-8e61-45b1-be4a-c1c874eb9441

📥 Commits

Reviewing files that changed from the base of the PR and between 9fa8f2a and 732e3aa.

⛔ Files ignored due to path filters (6)
  • sdk/python/nemo-platform/.nmpcontext/openapi.yaml is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/resources/experiment_groups/experiment_groups.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/types/experiment_groups/experiment_group_filter_param.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/types/experiment_groups/experiment_group_list_params.py is excluded by !sdk/**
  • sdk/python/nemo-platform/tests/api_resources/test_experiment_groups.py is excluded by !sdk/**
  • web/packages/studio/src/assets/voyager.svg is excluded by !**/*.svg
📒 Files selected for processing (58)
  • openapi/ga/individual/platform.openapi.yaml
  • openapi/ga/openapi.yaml
  • openapi/openapi.yaml
  • plugins/nemo-insights/scripts/insights_demo.py
  • plugins/nemo-insights/src/nemo_insights_plugin/schema.py
  • plugins/nemo-insights/src/nemo_insights_plugin/service.py
  • plugins/nemo-insights/tests/test_insights_list_contract.py
  • services/intake/src/nmp/intake/api/v2/experiments/endpoints.py
  • services/intake/src/nmp/intake/api/v2/experiments/schemas.py
  • services/intake/src/nmp/intake/spans/api/query_filters.py
  • services/intake/src/nmp/intake/spans/api/traces.py
  • services/intake/src/nmp/intake/spans/clickhouse_client.py
  • services/intake/src/nmp/intake/spans/domain.py
  • services/intake/src/nmp/intake/spans/service.py
  • services/intake/src/nmp/intake/spans/trace_repository.py
  • services/intake/tests/integration/test_experiments_crud.py
  • services/intake/tests/test_traces_api.py
  • services/intake/tests/test_traces_clickhouse_repository.py
  • services/studio/src/nmp/studio/env_mappings.py
  • web/packages/studio/env/.env.dev.local.sample
  • web/packages/studio/env/.env.fastapi
  • web/packages/studio/src/api/optimizer.ts
  • web/packages/studio/src/components/ChangesetBadge/index.tsx
  • web/packages/studio/src/components/ExperimentGroupEditModal/index.test.tsx
  • web/packages/studio/src/components/ExperimentGroupEditModal/index.tsx
  • web/packages/studio/src/components/IntakeLists/IntakeTracesTable.tsx
  • web/packages/studio/src/components/IntakeLists/intakeTraceColumns.tsx
  • web/packages/studio/src/components/OriginatingInsightLink/index.tsx
  • web/packages/studio/src/components/dataViews/ExperimentGroupDataView/index.tsx
  • web/packages/studio/src/constants/environment.ts
  • web/packages/studio/src/constants/featureFlags/featureFlags.ts
  • web/packages/studio/src/constants/routes.ts
  • web/packages/studio/src/routes/EvaluationDetailRoute/EvaluationDetailMetrics.tsx
  • web/packages/studio/src/routes/EvaluationDetailRoute/index.test.tsx
  • web/packages/studio/src/routes/EvaluationDetailRoute/index.tsx
  • web/packages/studio/src/routes/EvaluationDetailRoute/optimizerDisabled.test.tsx
  • web/packages/studio/src/routes/ExperimentGroupDetailRoute/index.test.tsx
  • web/packages/studio/src/routes/ExperimentGroupDetailRoute/index.tsx
  • web/packages/studio/src/routes/WorkspaceLayout/WorkspaceSideNav.test.tsx
  • web/packages/studio/src/routes/WorkspaceLayout/WorkspaceSideNav.tsx
  • web/packages/studio/src/routes/groups/index.ts
  • web/packages/studio/src/routes/groups/optimizerRoutes.tsx
  • web/packages/studio/src/routes/index.test.tsx
  • web/packages/studio/src/routes/index.tsx
  • web/packages/studio/src/routes/optimizer/InsightOpenModal/command.ts
  • web/packages/studio/src/routes/optimizer/InsightOpenModal/index.test.ts
  • web/packages/studio/src/routes/optimizer/InsightOpenModal/index.tsx
  • web/packages/studio/src/routes/optimizer/InsightTracesTable/index.test.tsx
  • web/packages/studio/src/routes/optimizer/InsightTracesTable/index.tsx
  • web/packages/studio/src/routes/optimizer/OptimizerInsightRoute/InsightExperimentGroups.tsx
  • web/packages/studio/src/routes/optimizer/OptimizerInsightRoute/index.test.tsx
  • web/packages/studio/src/routes/optimizer/OptimizerInsightRoute/index.tsx
  • web/packages/studio/src/routes/optimizer/OptimizerRoute/index.test.tsx
  • web/packages/studio/src/routes/optimizer/OptimizerRoute/index.tsx
  • web/packages/studio/src/routes/optimizer/insightStatus.test.ts
  • web/packages/studio/src/routes/optimizer/insightStatus.ts
  • web/packages/studio/src/routes/utils.ts
  • web/packages/studio/src/tests/title-change.test.tsx

Comment thread plugins/nemo-insights/scripts/insights_demo.py
Comment thread plugins/nemo-insights/scripts/insights_demo.py
Signed-off-by: Aditya Pandey <aditypandey@nvidia.com>
Signed-off-by: Aditya Pandey <aditypandey@nvidia.com>
Signed-off-by: Aditya Pandey <aditypandey@nvidia.com>
Load each visible trace page in one Intake request to avoid per-row API fan-out while preserving evidence order and failure feedback.

Signed-off-by: Aditya Pandey <aditypandey@nvidia.com>
Apply repository Prettier formatting so the Studio format check passes.

Signed-off-by: Aditya Pandey <aditypandey@nvidia.com>
The insights work replaced the group detail header's description with a
static blurb, so the group's editable description was rendered nowhere,
and it gave group.summary a permanent panel that reads "—" for every
group no producer has summarized. Show the description as the page
subtitle again and render the summary panel only when it has content.

The group update endpoint is a full replace, so also resend the summary,
insight link, and metadata the edit form does not touch; saving a
description edit was clearing all three.

Move the originating insight link into the insight card's header as a
compact mark and label so the description text uses the full card width.

Signed-off-by: Aditya Pandey <aditypandey@nvidia.com>
@callingmedic911
callingmedic911 force-pushed the rrhyne/insights-experiments branch from 732e3aa to 5d7e38a Compare July 24, 2026 21:27

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

Caution

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

⚠️ Outside diff range comments (1)
services/intake/src/nmp/intake/api/v2/experiments/schemas.py (1)

51-57: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Normalize omitted pareto before creating the entity.

ExperimentGroupRequest.pareto becomes None when omitted, but create_experiment_group forwards it directly to ExperimentGroup. This bypasses the documented create default and can violate the non-nullable ExperimentGroupResponse.pareto contract. Normalize it in the create path while preserving the existing update behavior.

Suggested fix
-        pareto=body.pareto,
+        pareto=body.pareto if body.pareto is not None else ParetoConfig(),
🤖 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/src/nmp/intake/api/v2/experiments/schemas.py` around lines 51
- 57, Update create_experiment_group to replace an omitted
ExperimentGroupRequest.pareto value with the documented cost-versus-latency
ParetoConfig before constructing ExperimentGroup. Preserve None for update
requests so omitted pareto continues to retain the existing value, and keep the
ExperimentGroupResponse.pareto contract non-nullable.
🤖 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 `@services/intake/src/nmp/intake/api/v2/experiments/schemas.py`:
- Around line 51-57: Update create_experiment_group to replace an omitted
ExperimentGroupRequest.pareto value with the documented cost-versus-latency
ParetoConfig before constructing ExperimentGroup. Preserve None for update
requests so omitted pareto continues to retain the existing value, and keep the
ExperimentGroupResponse.pareto contract non-nullable.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Enterprise

Run ID: 86497ff9-29c5-4e06-b139-ad40cb79232b

📥 Commits

Reviewing files that changed from the base of the PR and between 732e3aa and 5d7e38a.

⛔ Files ignored due to path filters (6)
  • sdk/python/nemo-platform/.nmpcontext/openapi.yaml is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/resources/experiment_groups/experiment_groups.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/types/experiment_groups/experiment_group_filter_param.py is excluded by !sdk/**
  • sdk/python/nemo-platform/src/nemo_platform/types/experiment_groups/experiment_group_list_params.py is excluded by !sdk/**
  • sdk/python/nemo-platform/tests/api_resources/test_experiment_groups.py is excluded by !sdk/**
  • web/packages/studio/src/assets/voyager.svg is excluded by !**/*.svg
📒 Files selected for processing (58)
  • openapi/ga/individual/platform.openapi.yaml
  • openapi/ga/openapi.yaml
  • openapi/openapi.yaml
  • plugins/nemo-insights/scripts/insights_demo.py
  • plugins/nemo-insights/src/nemo_insights_plugin/schema.py
  • plugins/nemo-insights/src/nemo_insights_plugin/service.py
  • plugins/nemo-insights/tests/test_insights_list_contract.py
  • services/intake/src/nmp/intake/api/v2/experiments/endpoints.py
  • services/intake/src/nmp/intake/api/v2/experiments/schemas.py
  • services/intake/src/nmp/intake/spans/api/query_filters.py
  • services/intake/src/nmp/intake/spans/api/traces.py
  • services/intake/src/nmp/intake/spans/clickhouse_client.py
  • services/intake/src/nmp/intake/spans/domain.py
  • services/intake/src/nmp/intake/spans/service.py
  • services/intake/src/nmp/intake/spans/trace_repository.py
  • services/intake/tests/integration/test_experiments_crud.py
  • services/intake/tests/test_traces_api.py
  • services/intake/tests/test_traces_clickhouse_repository.py
  • services/studio/src/nmp/studio/env_mappings.py
  • web/packages/studio/env/.env.dev.local.sample
  • web/packages/studio/env/.env.fastapi
  • web/packages/studio/src/api/optimizer.ts
  • web/packages/studio/src/components/ChangesetBadge/index.tsx
  • web/packages/studio/src/components/ExperimentGroupEditModal/index.test.tsx
  • web/packages/studio/src/components/ExperimentGroupEditModal/index.tsx
  • web/packages/studio/src/components/IntakeLists/IntakeTracesTable.tsx
  • web/packages/studio/src/components/IntakeLists/intakeTraceColumns.tsx
  • web/packages/studio/src/components/OriginatingInsightLink/index.tsx
  • web/packages/studio/src/components/dataViews/ExperimentGroupDataView/index.tsx
  • web/packages/studio/src/constants/environment.ts
  • web/packages/studio/src/constants/featureFlags/featureFlags.ts
  • web/packages/studio/src/constants/routes.ts
  • web/packages/studio/src/routes/EvaluationDetailRoute/EvaluationDetailMetrics.tsx
  • web/packages/studio/src/routes/EvaluationDetailRoute/index.test.tsx
  • web/packages/studio/src/routes/EvaluationDetailRoute/index.tsx
  • web/packages/studio/src/routes/EvaluationDetailRoute/optimizerDisabled.test.tsx
  • web/packages/studio/src/routes/ExperimentGroupDetailRoute/index.test.tsx
  • web/packages/studio/src/routes/ExperimentGroupDetailRoute/index.tsx
  • web/packages/studio/src/routes/WorkspaceLayout/WorkspaceSideNav.test.tsx
  • web/packages/studio/src/routes/WorkspaceLayout/WorkspaceSideNav.tsx
  • web/packages/studio/src/routes/groups/index.ts
  • web/packages/studio/src/routes/groups/optimizerRoutes.tsx
  • web/packages/studio/src/routes/index.test.tsx
  • web/packages/studio/src/routes/index.tsx
  • web/packages/studio/src/routes/optimizer/InsightOpenModal/command.ts
  • web/packages/studio/src/routes/optimizer/InsightOpenModal/index.test.ts
  • web/packages/studio/src/routes/optimizer/InsightOpenModal/index.tsx
  • web/packages/studio/src/routes/optimizer/InsightTracesTable/index.test.tsx
  • web/packages/studio/src/routes/optimizer/InsightTracesTable/index.tsx
  • web/packages/studio/src/routes/optimizer/OptimizerInsightRoute/InsightExperimentGroups.tsx
  • web/packages/studio/src/routes/optimizer/OptimizerInsightRoute/index.test.tsx
  • web/packages/studio/src/routes/optimizer/OptimizerInsightRoute/index.tsx
  • web/packages/studio/src/routes/optimizer/OptimizerRoute/index.test.tsx
  • web/packages/studio/src/routes/optimizer/OptimizerRoute/index.tsx
  • web/packages/studio/src/routes/optimizer/insightStatus.test.ts
  • web/packages/studio/src/routes/optimizer/insightStatus.ts
  • web/packages/studio/src/routes/utils.ts
  • web/packages/studio/src/tests/title-change.test.tsx
🚧 Files skipped from review as they are similar to previous changes (51)
  • web/packages/studio/src/tests/title-change.test.tsx
  • web/packages/studio/src/routes/optimizer/insightStatus.test.ts
  • web/packages/studio/src/routes/WorkspaceLayout/WorkspaceSideNav.test.tsx
  • web/packages/studio/src/routes/EvaluationDetailRoute/EvaluationDetailMetrics.tsx
  • web/packages/studio/src/constants/featureFlags/featureFlags.ts
  • web/packages/studio/src/routes/groups/index.ts
  • services/intake/tests/integration/test_experiments_crud.py
  • web/packages/studio/src/components/ExperimentGroupEditModal/index.test.tsx
  • web/packages/studio/src/routes/utils.ts
  • web/packages/studio/src/constants/environment.ts
  • web/packages/studio/src/components/OriginatingInsightLink/index.tsx
  • web/packages/studio/src/components/ChangesetBadge/index.tsx
  • web/packages/studio/src/routes/EvaluationDetailRoute/index.test.tsx
  • web/packages/studio/src/routes/optimizer/OptimizerRoute/index.test.tsx
  • web/packages/studio/src/routes/groups/optimizerRoutes.tsx
  • web/packages/studio/src/routes/WorkspaceLayout/WorkspaceSideNav.tsx
  • web/packages/studio/src/routes/optimizer/InsightOpenModal/index.test.ts
  • services/intake/src/nmp/intake/spans/clickhouse_client.py
  • web/packages/studio/src/routes/optimizer/InsightOpenModal/index.tsx
  • web/packages/studio/src/routes/ExperimentGroupDetailRoute/index.test.tsx
  • web/packages/studio/src/routes/index.tsx
  • web/packages/studio/src/routes/EvaluationDetailRoute/optimizerDisabled.test.tsx
  • web/packages/studio/src/components/IntakeLists/intakeTraceColumns.tsx
  • web/packages/studio/src/components/dataViews/ExperimentGroupDataView/index.tsx
  • web/packages/studio/src/routes/optimizer/InsightOpenModal/command.ts
  • services/intake/src/nmp/intake/api/v2/experiments/endpoints.py
  • services/studio/src/nmp/studio/env_mappings.py
  • web/packages/studio/src/components/ExperimentGroupEditModal/index.tsx
  • web/packages/studio/src/routes/ExperimentGroupDetailRoute/index.tsx
  • web/packages/studio/src/routes/optimizer/OptimizerRoute/index.tsx
  • web/packages/studio/src/routes/index.test.tsx
  • web/packages/studio/src/routes/optimizer/insightStatus.ts
  • services/intake/src/nmp/intake/spans/domain.py
  • web/packages/studio/src/routes/optimizer/OptimizerInsightRoute/InsightExperimentGroups.tsx
  • services/intake/tests/test_traces_api.py
  • web/packages/studio/src/constants/routes.ts
  • web/packages/studio/src/routes/optimizer/InsightTracesTable/index.test.tsx
  • services/intake/src/nmp/intake/spans/api/traces.py
  • plugins/nemo-insights/tests/test_insights_list_contract.py
  • openapi/openapi.yaml
  • openapi/ga/individual/platform.openapi.yaml
  • openapi/ga/openapi.yaml
  • web/packages/studio/src/routes/optimizer/OptimizerInsightRoute/index.tsx
  • web/packages/studio/src/routes/optimizer/InsightTracesTable/index.tsx
  • plugins/nemo-insights/src/nemo_insights_plugin/service.py
  • web/packages/studio/src/routes/optimizer/OptimizerInsightRoute/index.test.tsx
  • web/packages/studio/src/components/IntakeLists/IntakeTracesTable.tsx
  • web/packages/studio/src/api/optimizer.ts
  • web/packages/studio/src/routes/EvaluationDetailRoute/index.tsx
  • services/intake/tests/test_traces_clickhouse_repository.py
  • plugins/nemo-insights/scripts/insights_demo.py

@callingmedic911
callingmedic911 added this pull request to the merge queue Jul 24, 2026
Merged via the queue into main with commit 574831b Jul 24, 2026
65 checks passed
@callingmedic911
callingmedic911 deleted the rrhyne/insights-experiments branch July 24, 2026 21:52
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.

3 participants