Epic 5 — Artifact Inspection

Covers browsing JSON artifacts with syntax highlighting, diffing between retry attempts, client-side JSON Schema validation, handling oversize and binary artifacts (download-only mode), sanitizer version mismatch staleness warnings, and a fully redacted view for Auditors with copy/cut/drag interception.

Personas: BU (primary) OP AU (redacted view)

Shared modules: RedactionFilter (Heuristic mode, surface: epic-5-*) CorrelationChip LastSyncedBadge

Story 5.1 — Browse JSON Artifacts

As a
BU
I want
to view a JSON artifact from a completed stage with syntax highlighting and tree navigation
So that
I can inspect the structured output produced by each agent without downloading it
Scenario: Artifact viewer renders for a passed stage
Giventhe user navigates to the artifact viewer for a stage with status = 'passed' WhenGET /runs/{run_id}/stages/{stage_id}/artifacts/{artifact_id} resolves Thenthe JSON content is rendered with syntax highlighting (keys, strings, numbers, booleans, nulls use distinct design-token colours); the tree is collapsible; a Copy JSON button is available
Scenario: Artifact list per stage
Giventhe user expands a stage card on the run timeline WhenGET /runs/{run_id}/stages/{stage_id}/artifacts resolves Thena list of artifact names, sizes, and MIME types is shown; each row links to the viewer; the attempt number is shown for multi-attempt stages
Endpoint / DBPurpose
GET /runs/{run_id}/stages/{stage_id}/artifactsArtifact list
GET /runs/{run_id}/stages/{stage_id}/artifacts/{artifact_id}Full artifact content
DB artifacts.content, artifacts.content_typeJSON payload and MIME type

Story 5.2 — Diff Between Retry Attempts

As a
BU
I want
to compare the artifact output between two retry attempts of the same stage
So that
I can see how the LLM's output changed between retries
Scenario: Diff view renders changed keys highlighted
Givena stage has attempt ≥ 2 and artifacts for each attempt exist Whenthe user selects two attempt numbers in the diff picker Thena side-by-side or unified JSON diff is rendered; added keys are highlighted green; removed keys red; changed values amber; unchanged keys are dimmed
Scenario: Single attempt — diff picker disabled
Giventhe stage has attempt = 1 Thenthe diff picker is rendered in a disabled state with tooltip Only one attempt — no diff available

Story 5.3 — JSON Schema Validation

As a
BU
I want
to see whether an artifact passes its expected JSON Schema
So that
I can identify structural regressions in the LLM output without manually inspecting the JSON
Scenario: Schema validation passes — green indicator
Giventhe artifact has an associated JSON Schema (resolved from artifacts.content.meta.schema_version) Whenthe viewer validates the content against the schema client-side Thena green Schema valid badge is shown above the JSON viewer
Scenario: Schema validation fails — error overlay with path
Whenvalidation fails Thena red Schema violation badge is shown; clicking it expands an error panel listing each violating JSON-path and the constraint that failed; the violating paths are also highlighted in the JSON tree

Story 5.4 — Oversize & Binary Artifact Handling

As a
BU
I want
to see a graceful fallback when an artifact is too large to display or is binary
So that
I can still download and inspect it locally without the viewer crashing
Scenario: Oversize JSON artifact — download-only mode
Giventhe artifact's content_length exceeds the viewer threshold (e.g. 1 MB) Thenthe viewer shows a File too large to display (<size>) notice and a Download artifact button; no JSON tree is rendered
Scenario: Binary artifact — download-only mode
Giventhe artifact's content_type is not application/json Thenthe viewer shows a Binary artifact — cannot display in browser notice with the MIME type and a Download artifact button

Story 5.5 — Sanitizer Staleness Warning

As a
BU
I want
to see a warning when an artifact was produced by an older sanitizer version than the current one
So that
I know the artifact may not conform to the latest schema and should be re-run
Scenario: Sanitizer version mismatch — amber warning
Givenartifacts.content.meta.sanitizer is "v1.2" and the current sanitizer is "v1.4" Whenthe artifact viewer renders Thenan amber Stale artifact banner is shown reading: This artifact was produced by sanitizer v1.2 (current: v1.4). Re-run the pipeline to get an up-to-date artifact.
Scenario: Sanitizer version matches — no warning
Givenartifacts.content.meta.sanitizer matches the current sanitizer version Thenno staleness banner is shown

Story 5.6 — Auditor Redacted View

As an
AU
I want
to view artifacts with sensitive values pre-redacted and my copy/cut actions intercepted
So that
I cannot exfiltrate raw secrets or PII from the artifact viewer
Scenario: JSON viewer renders with Heuristic Redaction Filter applied
Giventhe user has the Auditor role and the artifact contains a JWT at path $.auth.token Whenthe viewer renders Thenthe RedactionFilter (Heuristic, surface: epic-5-viewer) processes the JSON before DOM serialisation; the JWT value is replaced with [REDACTED]; a redaction.applied breadcrumb is emitted
Regression: Clipboard copy from Auditor view produces only [REDACTED]
Giventhe Auditor selects text that wraps a backend-supplied secret value Whenthe Auditor presses Ctrl/Cmd-C Thenthe copy event is intercepted with event.preventDefault(); redactSelection() processes the selection; only the redacted projection is written to event.clipboardData; regression test asserts clipboard contains [REDACTED], never the raw value