Phase 4 — Typed Data Artifact Views
Goal
Let an answer or Investigation dataset appear as a trustworthy table, metric set or chart without allowing the model to generate arbitrary executable UI or redefine the underlying data.Architectural decision
Driftless owns a stable, versionedDataArtifactSpec. assistant-ui may render it through an adapter,
but its experimental Generative UI schema is not persisted as the domain contract.
The authoritative chain is:
persisted dataset -> validated Driftless view spec -> React renderer -> user interaction
Never:
model-authored HTML/JS -> iframe -> authoritative result
First vocabulary
Keep the first vocabulary deliberately small:DataTableViewMetricGridViewBarChartViewLineChartViewonly when the x field is temporalEvidenceListViewComparisonView
Stable spec
Define a discriminated union resembling:- artifact/dataset belongs to the workspace;
- referenced fields exist and have compatible types;
- aggregation is allowlisted (
count,sum,avg,min,max); - grouping cardinality and row limits are bounded;
- URLs and evidence references come from persisted provenance;
- actions are allowlisted and permission-checked.
assistant-ui compatibility spike
Before adding production behavior, run a small isolated spike:- Keep
@assistant-ui/react@0.15.8pinned. - Evaluate the oldest compatible
@assistant-ui/react-generative-uirelease that satisfies the repository’s seven-dayminimumReleaseAge; do not add an exclusion. - Render a static
MetricGrid + BarChart + Tablefrom fixtures inside the existingExternalStoreRuntimepath. - Prove build, SSR assumptions, React 19, Zod version, CSS isolation, accessibility and lazy chunk impact.
- Prove no request reaches Assistant Cloud.
- If it integrates cleanly and adds less maintenance than it removes, create a thin adapter from
DataArtifactSpecto its component registry. - If its
0.0.xAPI, dependencies or transport assumptions fight the External Store, implement a small localDataArtifactRendererover Driftless components. Preserve the spec so the renderer remains replaceable.
@assistant-ui/react merely to unlock this phase unless a separate dependency review
proves the migration and package-age guard.
Chat integration
The current assistant message reserves a slot between prose and sources. A Chat response may link a persisted artifact id in message metadata; the UI fetches and renders it there. It must not infer an artifact by parsing prose. For large Investigation artifacts, the message shows a compact preview and an explicitOpen Investigation action. The full table/chart surface remains the Investigation route.
Actions
UI actions dispatch typed intents such as:- switch view;
- filter/group locally through the server-supported query contract;
- inspect evidence;
- export CSV/JSON;
- select rows for Collection promotion.
$action or component callback is only the frontend dispatch mechanism. The server
still authenticates, authorizes and validates every mutation.
Accessibility and truthful visualization
- Every chart has a textual/table alternative and an accessible name.
- Tooltips are not the only place values exist.
- Truncated categories say how many are shown of the total.
- Missing values remain missing; they are never coerced to zero.
- Mixed currencies/scopes never share an aggregate series.
- A chart title states the metric, scope and period.
- Color never carries status alone.
Acceptance
- The same persisted dataset can render as table and chart without regenerating data.
- Invalid fields/aggregations fail closed with a typed error.
- A saved artifact renders identically after refresh.
- Every visible value can be traced to a persisted row or deterministic aggregate.
- Assistant UI/renderer failure degrades to the canonical table, not to an empty answer.
- Ordinary text-only messages remain unchanged and do not pay the artifact chunk.
Rollback
Disable rich rendering and show the canonicalDataTableView. Persisted artifact specs and datasets
remain valid because they are Driftless-owned.