${escapeHtml(step.details)}`
: `No extra details.
` }export type Conversation = { id: string; kind: "direct" | "channel"; title?: string; }; export type Thread = { id: string; conversationId: string; title: string; }; export type Message = { id: string; direction: "inbound" | "outbound"; conversation: Conversation; senderId: string; senderName?: string; text: string; timestamp: number; threadId?: string; threadTitle?: string; deleted?: boolean; editedAt?: number; reactions: Array<{ emoji: string; senderId: string }>; }; export type BusEvent = | { cursor: number; kind: "thread-created"; thread: Thread } | { cursor: number; kind: string; message?: Message; emoji?: string }; export type Snapshot = { conversations: Conversation[]; threads: Thread[]; messages: Message[]; events: BusEvent[]; }; export type ReportEnvelope = { report: null | { outputPath: string; markdown: string; generatedAt: string; }; }; export type SeedScenario = { id: string; title: string; surface: string; objective: string; successCriteria: string[]; docsRefs?: string[]; codeRefs?: string[]; }; export type Bootstrap = { baseUrl: string; latestReport: ReportEnvelope["report"]; controlUiUrl: string | null; controlUiEmbeddedUrl: string | null; kickoffTask: string; scenarios: SeedScenario[]; defaults: { conversationKind: "direct" | "channel"; conversationId: string; senderId: string; senderName: string; }; }; export type ScenarioStep = { name: string; status: "pass" | "fail" | "skip"; details?: string; }; export type ScenarioOutcome = { id: string; name: string; status: "pending" | "running" | "pass" | "fail" | "skip"; details?: string; steps?: ScenarioStep[]; startedAt?: string; finishedAt?: string; }; export type ScenarioRun = { kind: "suite" | "self-check"; status: "idle" | "running" | "completed"; startedAt?: string; finishedAt?: string; scenarios: ScenarioOutcome[]; counts: { total: number; pending: number; running: number; passed: number; failed: number; skipped: number; }; }; export type OutcomesEnvelope = { run: ScenarioRun | null; }; export type TabId = "debug" | "scenarios" | "report" | "events"; export type UiState = { bootstrap: Bootstrap | null; snapshot: Snapshot | null; latestReport: ReportEnvelope["report"]; scenarioRun: ScenarioRun | null; selectedConversationId: string | null; selectedThreadId: string | null; selectedScenarioId: string | null; activeTab: TabId; composer: { conversationKind: "direct" | "channel"; conversationId: string; senderId: string; senderName: string; text: string; }; busy: boolean; error: string | null; }; export function formatTime(timestamp: number) { return new Date(timestamp).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit", second: "2-digit", }); } function formatIso(iso?: string) { if (!iso) { return "n/a"; } return new Date(iso).toLocaleString([], { month: "short", day: "numeric", hour: "2-digit", minute: "2-digit", second: "2-digit", }); } function escapeHtml(text: string) { return text .replaceAll("&", "&") .replaceAll("<", "<") .replaceAll(">", ">") .replaceAll('"', """); } export function deriveSelectedConversation(state: UiState): string | null { if (state.selectedConversationId) { return state.selectedConversationId; } return state.snapshot?.conversations[0]?.id ?? null; } export function deriveSelectedThread(state: UiState): string | null { return state.selectedThreadId ?? null; } export function filteredMessages(state: UiState) { const messages = state.snapshot?.messages ?? []; return messages.filter((message) => { if (state.selectedConversationId && message.conversation.id !== state.selectedConversationId) { return false; } if (state.selectedThreadId && message.threadId !== state.selectedThreadId) { return false; } return true; }); } function findScenarioOutcome(state: UiState, scenario: SeedScenario) { return ( state.scenarioRun?.scenarios.find((outcome) => outcome.id === scenario.id) ?? state.scenarioRun?.scenarios.find((outcome) => outcome.name === scenario.title) ?? null ); } function renderStatusChip(status: ScenarioOutcome["status"]) { const label = status === "pending" ? "seeded" : status === "pass" ? "pass" : status === "fail" ? "fail" : status; return `${escapeHtml(label)}`; } function renderRefs(refs: string[] | undefined, kind: "docs" | "code") { if (!refs?.length) { return `
No ${kind} refs attached.
`; } return refs.map((ref) => `${escapeHtml(ref)}`).join("");
}
function renderScenarioBoard(state: UiState, scenarios: SeedScenario[]) {
if (scenarios.length === 0) {
return 'No repo-backed scenarios yet.
'; } return scenarios .map((scenario) => { const outcome = findScenarioOutcome(state, scenario); return ` `; }) .join(""); } function renderScenarioInspector(state: UiState, scenarios: SeedScenario[]) { const scenario = scenarios.find((candidate) => candidate.id === state.selectedScenarioId) ?? scenarios[0] ?? null; if (!scenario) { return 'No scenario selected.
Scenario inspector
${escapeHtml(scenario.objective)}
${escapeHtml(outcome.details ?? "No summary details captured.")}
${escapeHtml(step.details)}`
: `No extra details.
` }No step-level data captured yet.
' }Not executed in the current run yet. Seed plan only.
' }No structured scenario run yet. Seed plan loaded; outcomes arrive once a suite or self-check starts.
Live run
Started ${escapeHtml(formatIso(run.startedAt))} · Finished ${escapeHtml(formatIso(run.finishedAt))}
Seed plan
${escapeHtml(kickoffTask || "No kickoff task loaded.")}
Protocol
${escapeHtml(state.latestReport?.markdown ?? "Run the suite or self-check to capture a Markdown protocol report.")}
Wire view
No events yet.
' : events .map((event) => { const tail = "thread" in event ? `${event.thread.conversationId}/${event.thread.id}` : event.message ? `${event.message.senderId}: ${event.message.text}` : ""; return `${escapeHtml(tail)}
Live lane
Manual probe
Agent control
Private QA workspace
Editorial control-room view for seeded scenarios, live traffic, and protocol evidence.