Skip to content

feat(studio): DataDesigner details profiler results#428

Open
steramae-nvidia wants to merge 1 commit into
mainfrom
steramae/dd-details-redesign
Open

feat(studio): DataDesigner details profiler results#428
steramae-nvidia wants to merge 1 commit into
mainfrom
steramae/dd-details-redesign

Conversation

@steramae-nvidia

@steramae-nvidia steramae-nvidia commented Jun 24, 2026

Copy link
Copy Markdown
Contributor
Screenshot 2026-06-23 at 4 44 03 PM

Summary by CodeRabbit

Release Notes

  • New Features
    • Added Dataset Profiler section displaying per-column statistics including record counts, null/unique percentages, and categorical/numerical distributions
    • Added Job Configuration panel for viewing detailed job configuration information
    • Reorganized job details page with tabbed interface separating Profile analysis and Output files

Signed-off-by: Sean Teramae <steramae@nvidia.com>
@steramae-nvidia steramae-nvidia requested review from a team as code owners June 24, 2026 00:12
@github-actions github-actions Bot added the feat label Jun 24, 2026
@coderabbitai

coderabbitai Bot commented Jun 24, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a dataset profiler results section, a builder config side panel, and a categorical histogram chart to the Data Designer job details page. Introduces three shared hooks for job routing, artifacts fileset resolution, and analysis loading. Refactors the route and fileset section to consume the new hooks. Also updates DEFAULT_BUILD_MODEL_NAME.

Changes

Data Designer Job Details: Profiler, Config Panel, and Shared Hooks

Layer / File(s) Summary
Dataset profiler types, helpers, and tests
...DataDesignerJobDetailsRoute/datasetProfilerTypes.ts, ...datasetProfilerTypes.test.ts
Defines sentinel values, discriminated ColumnStatistics union, DatasetProfilerResults shape, type guards, percentage/formatting helpers, and distribution extractors. Tests cover all exports.
Builder config parser, formatter, and tests
...DataDesignerJobDetailsRoute/builderConfig.ts, ...builderConfig.test.ts
Adds BUILDER_CONFIG_FILENAME, BuilderConfigSummary interfaces, defensive summarizeBuilderConfig, and formatColumnTypeBreakdown. Tests cover null returns, full extraction, breakdown ordering, minimal and malformed configs.
Shared route hooks
...DataDesignerJobDetailsRoute/useDataDesignerJobFromRoute.ts, ...useDataDesignerArtifactsFileset.ts, ...useDataDesignerJobAnalysis.ts
Adds useDataDesignerJobFromRoute (terminal-status polling), useDataDesignerArtifactsFileset (artifacts fileset + file listing), and useDataDesignerJobAnalysis (analysis result detection + download + parse).
CategoricalHistogramChart component
...DataDesignerJobDetailsRoute/CategoricalHistogramChart.tsx
Recharts vertical bar chart; sorts categories by descending count, shows top N, aggregates remainder, and handles empty state.
ColumnProfileCard component
...DataDesignerJobDetailsRoute/ColumnProfileCard.tsx
Per-column stats card with conditional detail block (histogram, numerical stats, LLM tokens, or validation count) dispatched on column stats variant.
DatasetProfilerSection component
...DataDesignerJobDetailsRoute/DatasetProfilerSection.tsx
Renders pending/error/loading/empty states and, when analysis is available, record count progress and a ColumnProfileCard grid.
DataDesignerConfigPanel component
...DataDesignerJobDetailsRoute/DataDesignerConfigPanel.tsx
Right-side SidePanel that fetches and parses builder_config.json from the artifacts fileset, rendering loading, missing, error, or summary states.
Route restructure and JobOutputFilesetSection refactor
...DataDesignerJobDetailsRoute/index.tsx, ...JobOutputFilesetSection.tsx
Route switches to useDataDesignerJobFromRoute, adds tabs (Profile / Output Files) and DataDesignerConfigPanel. JobOutputFilesetSection drops props and consumes useDataDesignerArtifactsFileset.
DEFAULT_BUILD_MODEL_NAME update
web/packages/studio/src/constants/constants.ts
Removes duplicated nvidia- prefix and trailing -5 from the model name constant.

Suggested labels

feat

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main feature added: comprehensive profiler results visualization for DataDesigner with profile cards, histograms, and metrics.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 steramae/dd-details-redesign

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

🧹 Nitpick comments (4)
web/packages/studio/src/routes/DataDesignerJobDetailsRoute/builderConfig.ts (1)

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

Mark summary interface fields as readonly.

These interfaces represent parsed summary snapshots and should be immutable at the type level.

Proposed diff
 export interface BuilderConfigColumnSummary {
-  name: string;
-  type: string;
-  modelAlias?: string;
+  readonly name: string;
+  readonly type: string;
+  readonly modelAlias?: string;
 }
 
 export interface BuilderConfigModelSummary {
-  alias: string;
-  model: string;
-  provider?: string;
+  readonly alias: string;
+  readonly model: string;
+  readonly provider?: string;
 }
 
 export interface BuilderConfigSeedSummary {
-  type: string;
-  samplingStrategy?: string;
+  readonly type: string;
+  readonly samplingStrategy?: string;
 }
 
 export interface BuilderConfigSummary {
-  columnCount: number;
-  columns: BuilderConfigColumnSummary[];
-  columnTypeBreakdown: Array<{ type: string; count: number }>;
-  models: BuilderConfigModelSummary[];
-  seed?: BuilderConfigSeedSummary;
-  constraintCount: number;
-  profilerCount: number;
-  processorNames: string[];
-  libraryVersion?: string;
+  readonly columnCount: number;
+  readonly columns: BuilderConfigColumnSummary[];
+  readonly columnTypeBreakdown: Array<{ type: string; count: number }>;
+  readonly models: BuilderConfigModelSummary[];
+  readonly seed?: BuilderConfigSeedSummary;
+  readonly constraintCount: number;
+  readonly profilerCount: number;
+  readonly processorNames: string[];
+  readonly libraryVersion?: string;
 }

As per coding guidelines: web/**/*.{ts,tsx}: Use \readonly` for immutable properties in TypeScript interfaces and types`.

🤖 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/DataDesignerJobDetailsRoute/builderConfig.ts`
around lines 17 - 44, Add the readonly keyword to all property declarations in
the four summary interfaces (BuilderConfigColumnSummary,
BuilderConfigModelSummary, BuilderConfigSeedSummary, and BuilderConfigSummary)
to mark them as immutable at the type level. For each property in these
interfaces, prefix the property name with the readonly keyword to ensure the
data structures represent immutable snapshots that cannot be modified after
creation.

Source: Coding guidelines

web/packages/studio/src/routes/DataDesignerJobDetailsRoute/DataDesignerConfigPanel.tsx (1)

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

Import FC as type-only.

FC is only used in type positions here.

Proposed diff
-import { FC, useMemo } from 'react';
+import { useMemo, type FC } from 'react';

As per coding guidelines: web/**/*.{ts,tsx}: Use \import type` for type-only 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/DataDesignerJobDetailsRoute/DataDesignerConfigPanel.tsx`
at line 14, The import statement at the top of DataDesignerConfigPanel.tsx
imports both FC and useMemo from 'react' using a single import statement. Since
FC is only used in type positions (as a functional component type), it should be
imported using import type syntax instead of regular import. Split the import
statement so that FC is imported with import type while useMemo remains in a
regular import statement.

Source: Coding guidelines

web/packages/studio/src/routes/DataDesignerJobDetailsRoute/JobOutputFilesetSection.tsx (1)

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

Convert type-only React imports to import type.

ComponentProps and FC are type-only and should use import type in this TSX file.

Proposed fix
-import { ComponentProps, FC, useCallback, useEffect, useMemo, useState } from 'react';
+import { useCallback, useEffect, useMemo, useState } from 'react';
+import type { ComponentProps, FC } from 'react';

As per coding guidelines, web/**/*.{ts,tsx}: Use import type for type-only 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/DataDesignerJobDetailsRoute/JobOutputFilesetSection.tsx`
at line 20, In the import statement at the top of JobOutputFilesetSection.tsx,
separate the type-only imports from the runtime imports. Move ComponentProps and
FC to a new line using import type syntax, keeping useCallback, useEffect,
useMemo, and useState in the regular import statement from React. This ensures
type-only imports are clearly distinguished from runtime dependencies according
to the project's TypeScript guidelines.

Source: Coding guidelines

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

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

Use import type for FC in this TSX module.

FC is type-only and should be imported with import type to match the TypeScript guideline.

Proposed fix
-import { FC, useState } from 'react';
+import { useState } from 'react';
+import type { FC } from 'react';

As per coding guidelines, web/**/*.{ts,tsx}: Use import type for type-only 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/DataDesignerJobDetailsRoute/index.tsx` at line
25, The import statement at the top of the DataDesignerJobDetailsRoute file
imports FC as a type-only import along with useState in a single import
statement. Separate this into two imports: create a type-only import for FC
using import type, and keep a regular import for useState from react. This
ensures that type-only imports are explicitly marked as such, following
TypeScript guidelines that help with tree-shaking and code clarity.

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/studio/src/routes/DataDesignerJobDetailsRoute/DataDesignerConfigPanel.tsx`:
- Around line 59-63: The key prop for the mapped KVPair components uses only
model.alias and column.name respectively, which can collide when duplicate
aliases or names exist (such as multiple "(unnamed)" entries), causing React to
mis-reconcile elements. Replace the key prop in both the model mapping (around
line 59-63 in the summary.models.map) and the column mapping (around line 75-79)
with a stable unique identifier that includes both the alias/name and the array
index, or another property that ensures uniqueness across duplicates, to prevent
reconciliation issues.

In
`@web/packages/studio/src/routes/DataDesignerJobDetailsRoute/DatasetProfilerSection.tsx`:
- Around line 57-67: The loading state condition in the first if statement is
checking hasAnalysis instead of the actual analysis data, which causes the
empty-state message to appear when hasAnalysis is true but the data is still
loading. Change the condition from checking !hasAnalysis to checking !analysis
(or checking if analysis is falsy/undefined) to properly gate the skeleton
loading state. This ensures the skeleton loader displays whenever data is
actually still loading, regardless of the hasAnalysis flag status. The fix
applies to the loading branch condition at the beginning of this component
logic.

In
`@web/packages/studio/src/routes/DataDesignerJobDetailsRoute/datasetProfilerTypes.ts`:
- Around line 148-153: The getPercentComplete function can return values above
100 or below 0 due to backend count drift, which breaks progress rendering in
consumers expecting valid percentage values. Clamp the calculated percentage
result to the range [0, 100] by wrapping the return statement with Math.max(0,
Math.min(100, ...)) to ensure the function always returns a value between 0 and
100 inclusive.
- Around line 136-137: The type predicate isLLMColumnStatistics narrows to only
LLMTextColumnStatistics, but the runtime check using LLM_COLUMN_TYPES actually
validates against four different LLM column types (llm-text, llm-code,
llm-structured, and llm-judge). Create a union type that includes all four LLM
column statistic variants, then update the return type of the
isLLMColumnStatistics predicate to use this union type instead of
LLMTextColumnStatistics to align the type guard with the actual runtime
behavior.

In
`@web/packages/studio/src/routes/DataDesignerJobDetailsRoute/useDataDesignerArtifactsFileset.ts`:
- Around line 26-29: The useDataDesignerListCreateJobResults hook call is not
capturing error information from its response. Currently when the hook fails,
it's being treated identically to the case where there are simply no results,
causing incorrect error messages to display downstream. Extract the error state
that the hook returns (in addition to the data and isLoading states already
being destructured) and ensure this error state is used by downstream code to
properly render an error state instead of conflating it with empty results.
Apply this same fix to all usages of useDataDesignerListCreateJobResults
including the location at lines 74-89.

In
`@web/packages/studio/src/routes/DataDesignerJobDetailsRoute/useDataDesignerJobAnalysis.ts`:
- Around line 33-36: The useDataDesignerJobAnalysis hook is not capturing errors
from the useDataDesignerListCreateJobResults query call. When the results
listing fails, the hook currently reports hasAnalysis as false and isError as
false, misclassifying backend failures as missing analysis. Extract the error
state from the useDataDesignerListCreateJobResults destructuring (similar to how
data and isLoading are extracted) and incorporate it into the hook's return
value so that actual backend errors are properly surfaced to consumers rather
than being silently dropped.

---

Nitpick comments:
In `@web/packages/studio/src/routes/DataDesignerJobDetailsRoute/builderConfig.ts`:
- Around line 17-44: Add the readonly keyword to all property declarations in
the four summary interfaces (BuilderConfigColumnSummary,
BuilderConfigModelSummary, BuilderConfigSeedSummary, and BuilderConfigSummary)
to mark them as immutable at the type level. For each property in these
interfaces, prefix the property name with the readonly keyword to ensure the
data structures represent immutable snapshots that cannot be modified after
creation.

In
`@web/packages/studio/src/routes/DataDesignerJobDetailsRoute/DataDesignerConfigPanel.tsx`:
- Line 14: The import statement at the top of DataDesignerConfigPanel.tsx
imports both FC and useMemo from 'react' using a single import statement. Since
FC is only used in type positions (as a functional component type), it should be
imported using import type syntax instead of regular import. Split the import
statement so that FC is imported with import type while useMemo remains in a
regular import statement.

In `@web/packages/studio/src/routes/DataDesignerJobDetailsRoute/index.tsx`:
- Line 25: The import statement at the top of the DataDesignerJobDetailsRoute
file imports FC as a type-only import along with useState in a single import
statement. Separate this into two imports: create a type-only import for FC
using import type, and keep a regular import for useState from react. This
ensures that type-only imports are explicitly marked as such, following
TypeScript guidelines that help with tree-shaking and code clarity.

In
`@web/packages/studio/src/routes/DataDesignerJobDetailsRoute/JobOutputFilesetSection.tsx`:
- Line 20: In the import statement at the top of JobOutputFilesetSection.tsx,
separate the type-only imports from the runtime imports. Move ComponentProps and
FC to a new line using import type syntax, keeping useCallback, useEffect,
useMemo, and useState in the regular import statement from React. This ensures
type-only imports are clearly distinguished from runtime dependencies according
to the project's TypeScript guidelines.
🪄 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: 63a66446-24f0-4fc3-a33c-ef9c32f8b383

📥 Commits

Reviewing files that changed from the base of the PR and between d8ea9e2 and 1d2deab.

📒 Files selected for processing (14)
  • web/packages/studio/src/constants/constants.ts
  • web/packages/studio/src/routes/DataDesignerJobDetailsRoute/CategoricalHistogramChart.tsx
  • web/packages/studio/src/routes/DataDesignerJobDetailsRoute/ColumnProfileCard.tsx
  • web/packages/studio/src/routes/DataDesignerJobDetailsRoute/DataDesignerConfigPanel.tsx
  • web/packages/studio/src/routes/DataDesignerJobDetailsRoute/DatasetProfilerSection.tsx
  • web/packages/studio/src/routes/DataDesignerJobDetailsRoute/JobOutputFilesetSection.tsx
  • web/packages/studio/src/routes/DataDesignerJobDetailsRoute/builderConfig.test.ts
  • web/packages/studio/src/routes/DataDesignerJobDetailsRoute/builderConfig.ts
  • web/packages/studio/src/routes/DataDesignerJobDetailsRoute/datasetProfilerTypes.test.ts
  • web/packages/studio/src/routes/DataDesignerJobDetailsRoute/datasetProfilerTypes.ts
  • web/packages/studio/src/routes/DataDesignerJobDetailsRoute/index.tsx
  • web/packages/studio/src/routes/DataDesignerJobDetailsRoute/useDataDesignerArtifactsFileset.ts
  • web/packages/studio/src/routes/DataDesignerJobDetailsRoute/useDataDesignerJobAnalysis.ts
  • web/packages/studio/src/routes/DataDesignerJobDetailsRoute/useDataDesignerJobFromRoute.ts

Comment on lines +59 to +63
{summary.models.map((model) => (
<KVPair
key={model.alias}
label={model.alias}
value={model.provider ? `${model.model} (${model.provider})` : model.model}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Use stable unique keys for mapped KV pairs.

key={model.alias} / key={column.name} collides on duplicate aliases/names (e.g., (unnamed) fallbacks), which can mis-reconcile rows.

Proposed diff
-          {summary.models.map((model) => (
+          {summary.models.map((model, index) => (
             <KVPair
-              key={model.alias}
+              key={`${model.alias}-${index}`}
               label={model.alias}
               value={model.provider ? `${model.model} (${model.provider})` : model.model}
             />
           ))}
@@
-          {summary.columns.map((column) => (
+          {summary.columns.map((column, index) => (
             <KVPair
-              key={column.name}
+              key={`${column.name}-${index}`}
               label={column.name}
               value={column.modelAlias ? `${column.type} · ${column.modelAlias}` : column.type}
             />
           ))}

Also applies to: 75-79

🤖 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/DataDesignerJobDetailsRoute/DataDesignerConfigPanel.tsx`
around lines 59 - 63, The key prop for the mapped KVPair components uses only
model.alias and column.name respectively, which can collide when duplicate
aliases or names exist (such as multiple "(unnamed)" entries), causing React to
mis-reconcile elements. Replace the key prop in both the model mapping (around
line 59-63 in the summary.models.map) and the column mapping (around line 75-79)
with a stable unique identifier that includes both the alias/name and the array
index, or another property that ensures uniqueness across duplicates, to prevent
reconciliation issues.

Comment on lines +57 to +67
if (isLoading && !hasAnalysis) {
return (
<ColumnGrid>
{Array.from({ length: 6 }, (_, i) => (
<Skeleton key={i} className="h-40 w-full rounded-lg" />
))}
</ColumnGrid>
);
}

if (!hasAnalysis) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Fix loading gate to avoid false “no column statistics” state.

With hasAnalysis === true and download still in flight, this path skips skeleton and renders the empty-state message. Gate on analysis instead of hasAnalysis for the loading branch.

Proposed fix
-  if (isLoading && !hasAnalysis) {
+  if (isLoading && !analysis) {
     return (
       <ColumnGrid>
         {Array.from({ length: 6 }, (_, i) => (
           <Skeleton key={i} className="h-40 w-full rounded-lg" />
         ))}
       </ColumnGrid>
     );
   }

Also applies to: 75-108

🤖 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/DataDesignerJobDetailsRoute/DatasetProfilerSection.tsx`
around lines 57 - 67, The loading state condition in the first if statement is
checking hasAnalysis instead of the actual analysis data, which causes the
empty-state message to appear when hasAnalysis is true but the data is still
loading. Change the condition from checking !hasAnalysis to checking !analysis
(or checking if analysis is falsy/undefined) to properly gate the skeleton
loading state. This ensures the skeleton loader displays whenever data is
actually still loading, regardless of the hasAnalysis flag status. The fix
applies to the loading branch condition at the beginning of this component
logic.

Comment on lines +136 to +137
export const isLLMColumnStatistics = (stats: ColumnStatistics): stats is LLMTextColumnStatistics =>
LLM_COLUMN_TYPES.has(stats.column_type);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

# First, check if the file exists and explore its structure
fd -t f "datasetProfilerTypes.ts" web/packages/studio/src/

Repository: NVIDIA-NeMo/nemo-platform

Length of output: 246


🏁 Script executed:

# Read the entire file to understand context
cat -n web/packages/studio/src/routes/DataDesignerJobDetailsRoute/datasetProfilerTypes.ts

Repository: NVIDIA-NeMo/nemo-platform

Length of output: 11846


🏁 Script executed:

# Search for LLM_COLUMN_TYPES definition
rg "LLM_COLUMN_TYPES" web/packages/studio/src/routes/DataDesignerJobDetailsRoute/

Repository: NVIDIA-NeMo/nemo-platform

Length of output: 463


Type predicate must narrow to union of all LLM variants.

Line 136 declares narrowing to LLMTextColumnStatistics, but line 137's runtime check (LLM_COLUMN_TYPES) accepts 'llm-text', 'llm-code', 'llm-structured', and 'llm-judge'. This breaks the type guard contract—TypeScript narrows to the wrong type.

Create a union type for all four LLM variants and update the predicate return type:

Fix
+export type LLMColumnStatistics =
+  | LLMTextColumnStatistics
+  | LLMCodeColumnStatistics
+  | LLMStructuredColumnStatistics
+  | LLMJudgedColumnStatistics;
+
-export const isLLMColumnStatistics = (stats: ColumnStatistics): stats is LLMTextColumnStatistics =>
+export const isLLMColumnStatistics = (stats: ColumnStatistics): stats is LLMColumnStatistics =>
   LLM_COLUMN_TYPES.has(stats.column_type);
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export const isLLMColumnStatistics = (stats: ColumnStatistics): stats is LLMTextColumnStatistics =>
LLM_COLUMN_TYPES.has(stats.column_type);
export type LLMColumnStatistics =
| LLMTextColumnStatistics
| LLMCodeColumnStatistics
| LLMStructuredColumnStatistics
| LLMJudgedColumnStatistics;
export const isLLMColumnStatistics = (stats: ColumnStatistics): stats is LLMColumnStatistics =>
LLM_COLUMN_TYPES.has(stats.column_type);
🤖 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/DataDesignerJobDetailsRoute/datasetProfilerTypes.ts`
around lines 136 - 137, The type predicate isLLMColumnStatistics narrows to only
LLMTextColumnStatistics, but the runtime check using LLM_COLUMN_TYPES actually
validates against four different LLM column types (llm-text, llm-code,
llm-structured, and llm-judge). Create a union type that includes all four LLM
column statistic variants, then update the return type of the
isLLMColumnStatistics predicate to use this union type instead of
LLMTextColumnStatistics to align the type guard with the actual runtime
behavior.

Comment on lines +148 to +153
export const getPercentComplete = (results: DatasetProfilerResults): number => {
if (results.target_num_records <= 0) {
return 0;
}
return (100 * results.num_records) / results.target_num_records;
};

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Clamp completion percentage to [0, 100].

Line 152 can return values above 100 (or below 0) when backend counts drift, which can break determinate progress rendering in consumers.

Proposed fix
 export const getPercentComplete = (results: DatasetProfilerResults): number => {
   if (results.target_num_records <= 0) {
     return 0;
   }
-  return (100 * results.num_records) / results.target_num_records;
+  const percent = (100 * results.num_records) / results.target_num_records;
+  return Math.max(0, Math.min(100, percent));
 };
🤖 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/DataDesignerJobDetailsRoute/datasetProfilerTypes.ts`
around lines 148 - 153, The getPercentComplete function can return values above
100 or below 0 due to backend count drift, which breaks progress rendering in
consumers expecting valid percentage values. Clamp the calculated percentage
result to the range [0, 100] by wrapping the return statement with Math.max(0,
Math.min(100, ...)) to ensure the function always returns a value between 0 and
100 inclusive.

Comment on lines +26 to +29
const { data: resultsResponse, isLoading: isResultsLoading } =
useDataDesignerListCreateJobResults(workspace, jobName, {
query: { refetchInterval: isTerminal ? false : 3000 },
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Surface results-list errors from the hook.

A failed useDataDesignerListCreateJobResults call is currently collapsed into the same state as “no artifacts result”, so downstream renders the wrong message instead of an error state.

Proposed fix
-  const { data: resultsResponse, isLoading: isResultsLoading } =
+  const {
+    data: resultsResponse,
+    isLoading: isResultsLoading,
+    isError: isResultsError,
+    error: resultsError,
+  } =
     useDataDesignerListCreateJobResults(workspace, jobName, {
       query: { refetchInterval: isTerminal ? false : 3000 },
     });
...
   return {
     workspace,
     jobName,
     job,
     isTerminal,
     artifactsResult,
     filesetLoc,
     filesetWorkspace,
     filesetName,
     listFilesParams,
     files,
     isResultsLoading,
+    isResultsError,
+    resultsError,
     isFilesLoading,
     isFilesError,
     filesError,
   };

Also applies to: 74-89

🤖 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/DataDesignerJobDetailsRoute/useDataDesignerArtifactsFileset.ts`
around lines 26 - 29, The useDataDesignerListCreateJobResults hook call is not
capturing error information from its response. Currently when the hook fails,
it's being treated identically to the case where there are simply no results,
causing incorrect error messages to display downstream. Extract the error state
that the hook returns (in addition to the data and isLoading states already
being destructured) and ensure this error state is used by downstream code to
properly render an error state instead of conflating it with empty results.
Apply this same fix to all usages of useDataDesignerListCreateJobResults
including the location at lines 74-89.

Comment on lines +33 to +36
const { data: resultsResponse, isLoading: isResultsLoading } =
useDataDesignerListCreateJobResults(workspace, jobName, {
query: { enabled: enabled && Boolean(workspace && jobName) },
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Do not drop results-list errors in this hook.

When listing results fails, this hook currently reports hasAnalysis: false and isError: false, which misclassifies backend failures as “no analysis generated”.

Proposed fix
-  const { data: resultsResponse, isLoading: isResultsLoading } =
+  const {
+    data: resultsResponse,
+    isLoading: isResultsLoading,
+    isError: isResultsError,
+    error: resultsError,
+  } =
     useDataDesignerListCreateJobResults(workspace, jobName, {
       query: { enabled: enabled && Boolean(workspace && jobName) },
     });
...
   return {
     analysis: analysisQuery.data,
     hasAnalysis,
     isLoading: isResultsLoading || (hasAnalysis && analysisQuery.isLoading),
-    isError: analysisQuery.isError,
-    error: analysisQuery.error,
+    isError: isResultsError || analysisQuery.isError,
+    error: resultsError ?? analysisQuery.error,
   };

Also applies to: 61-67

🤖 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/DataDesignerJobDetailsRoute/useDataDesignerJobAnalysis.ts`
around lines 33 - 36, The useDataDesignerJobAnalysis hook is not capturing
errors from the useDataDesignerListCreateJobResults query call. When the results
listing fails, the hook currently reports hasAnalysis as false and isError as
false, misclassifying backend failures as missing analysis. Extract the error
state from the useDataDesignerListCreateJobResults destructuring (similar to how
data and isLoading are extracted) and incorporate it into the hook's return
value so that actual backend errors are properly surfaced to consumers rather
than being silently dropped.

@github-actions

Copy link
Copy Markdown
Contributor
Suite Lines Covered Line Rate Branch Rate
Unit Tests 20908/27478 76.1% 61.2%
Integration Tests 12109/26247 46.1% 19.5%

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.

1 participant