fix(review-gates): green success badges, null-safe preview rows, optional section items

- Extract shared statusBadgeClass() helper (src/viewers/statusBadge.ts) so
  SqlViewer, CteResultViewer and PhaseSummaryViewer can't drift: ok/success/
  passed/promoted render green (--success), warn renders amber (--warning),
  error/failed stay destructive red, everything else stays neutral outline.
  Previously CteResultViewer/PhaseSummaryViewer mapped "ok"/"promoted" to the
  default badge variant, which is bg-primary (GSD red) — success states
  rendered red.
- enrich.js: buildCteResultV2 now falls back preview.rows to [] instead of
  null when last_test.preview_rows is missing (pre-upgrade ok records), and
  CteResultViewer reads result.preview?.rows?.length with a null-safe
  fallback so it degrades to the "No preview rows" empty state instead of
  crashing.
- PhaseSummaryViewer: section.items is optional (model-authored sections can
  be prose-only); render (section.items ?? []) instead of crashing.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-07 01:37:35 +02:00
co-authored by Claude Fable 5
parent b089482b8d
commit b59b57c4e6
9 changed files with 65 additions and 26 deletions
+2 -7
View File
@@ -1,5 +1,6 @@
import React, { useEffect, useState } from "react";
import { highlightSql } from "./highlight";
import { statusBadgeClass } from "./statusBadge";
export interface SqlBlock {
name: string;
@@ -17,12 +18,6 @@ const STATUS_LABELS: Record<string, string> = {
untested: "untested",
};
const STATUS_CLASSES: Record<string, string> = {
passed: "bg-[oklch(var(--success)/0.15)] text-[oklch(0.45_0.12_165)] ring-1 ring-[oklch(var(--success)/0.3)]",
failed: "bg-destructive/10 text-destructive ring-1 ring-destructive/25",
untested: "bg-muted text-muted-foreground ring-1 ring-border",
};
function Block({ block }: { block: SqlBlock }) {
const [open, setOpen] = useState(true);
const [html, setHtml] = useState<string>("");
@@ -39,7 +34,7 @@ function Block({ block }: { block: SqlBlock }) {
const badge = block.testStatus ? STATUS_LABELS[block.testStatus] : null;
const badgeClass = block.testStatus
? STATUS_CLASSES[block.testStatus]
? statusBadgeClass(block.testStatus)
: "";
return (