// SPEC: PJ2026-010401 Web工作台 draft-2026-06-18-r1; PJ2026-0104010803 唯一投影 draft-2026-06-19-p2-terminal-sealed-final-response; PJ2026-010403 API契约 draft-2026-06-18-r1. // Responsibility: Same-origin fake Workbench API and static server for Playwright browser regression tests. import { createReadStream, existsSync, readFileSync, statSync } from "node:fs"; import { readFile } from "node:fs/promises"; import { createServer, type IncomingMessage, type ServerResponse } from "node:http"; import { extname, join, resolve, sep } from "node:path"; import { DEFAULT_WORKBENCH_EMPTY_SESSION_TTL_MS, classifyWorkbenchEmptySessionGcCandidate } from "../../../internal/cloud/workbench-empty-session-gc.ts"; type JsonRecord = Record; interface SessionRecord extends JsonRecord { sessionId: string; threadId?: string | null; status?: string | null; lastTraceId?: string | null; messages?: JsonRecord[]; hidden?: boolean; } interface ScenarioState { scenarioId: string; providerProfile: string; selectedSessionId: string; sessions: SessionRecord[]; traces: Record; requestLedger: JsonRecord[]; legacyRequestLedger: JsonRecord[]; chatRequests: JsonRecord[]; projectLinks: JsonRecord[]; listOmitSelected: boolean; sessionDelayMs: number; sessionDetailDelayMs: number; chatDelayMs: number; terminalScript: boolean; terminalFailureScript: boolean; staleTraceId: string | null; liveBackfillTraceId: string | null; liveBackfillReadyAtMs: number | null; } interface FakePerformanceWindow { id: string; label: string; seconds: number | null; windowFrom: string | null; windowTo: string; generatedAt: string; } const cwd = process.cwd(); const args = new Map(); for (let index = 2; index < process.argv.length; index += 1) { const key = process.argv[index]; const value = process.argv[index + 1]; if (key?.startsWith("--")) { args.set(key.slice(2), value && !value.startsWith("--") ? value : "true"); if (value && !value.startsWith("--")) index += 1; } } const port = Number(args.get("port") ?? process.env.HWLAB_WORKBENCH_E2E_PORT ?? 4173); const distDir = resolve(cwd, args.get("dist") ?? "dist"); const capturePath = resolve(cwd, "tests/workbench-e2e/fixtures/real-captures/d601-v03-redacted.json"); const capture = JSON.parse(await readFile(capturePath, "utf8")) as { scenario: { selectedSessionId: string; providerProfile: string; sessions: SessionRecord[]; traces: Record } }; const progressOnlyText = "PROGRESS_ONLY_SHOULD_NOT_RENDER_AS_FINAL"; const finalOnlyText = "FINAL_ONLY_SHOULD_RENDER"; const markdownFinalText = [ "已新增并实际运行:", "", "- Go:`go test ./...` 保留两个空格", "- Rust:`cargo test --release`", "", "```sh", "go test ./...", "cargo test --release", "```", "", "| benchmark | Go | Rust |", "|---|---:|---:|", "| fib | 1.2ms | 1.0ms |", "", "| runtime | status |", "|---|---|", "| local | pass |" ].join("\n"); const terminalAssistantFinalText = [ "全部六份数据到手!下面是完整的六语言终极性能对比:", "", "| language | runtime | status |", "|---|---|---|", "| Lua | LuaJIT | pass |", "| Python | CPython | pass |", "| Rust | native | pass |" ].join("\n"); const canonicalTraceFinalText = "messageProjection 的 sealed final response 才是主消息正文。"; const traceDetailConflictText = "TRACE_DETAIL_CONFLICT_SHOULD_NOT_REPLACE_MESSAGE"; const runtimeConfigScript = ``; let state = createScenarioState("baseline"); const sseClients = new Set(); const server = createServer((request, response) => { void handleRequest(request, response).catch((error) => { json(response, 500, { ok: false, status: 500, error: { code: "e2e_server_error", message: error instanceof Error ? error.message : String(error) } }); }); }); server.listen(port, "127.0.0.1", () => { console.log(`workbench-e2e-server listening on http://127.0.0.1:${port}`); }); async function handleRequest(request: IncomingMessage, response: ServerResponse): Promise { const method = request.method ?? "GET"; const url = new URL(request.url ?? "/", `http://${request.headers.host ?? `127.0.0.1:${port}`}`); const path = url.pathname; recordLedger(method, url); refreshBackgroundProjection(); if (path === "/__e2e/health") return json(response, 200, { ok: true, scenarioId: state.scenarioId }); if (path === "/__e2e/state") return json(response, 200, stateSummary()); if (path === "/__e2e/reset" && method === "POST") { const body = await readJson(request); state = createScenarioState(String(body.scenarioId ?? "baseline")); return json(response, 200, stateSummary()); } if (path === "/__e2e/scroll-follow/append" && method === "POST") { const body = await readJson(request); return json(response, 200, appendScrollFollowEvents(positiveInteger(body.count, 1))); } if (path === "/__e2e/gc-empty-sessions" && method === "POST") { const body = await readJson(request); return json(response, 200, gcEmptySessions(body)); } if (path === "/auth/session" || path === "/auth/bootstrap") { const payload = authPayload(); return json(response, payload.authenticated === true ? 200 : 401, payload); } if (path === "/auth/login" && method === "POST") return authLoginResponse(response); if (path === "/v1/workbench/events" && method === "GET") return sse(request, response, url); if (path === "/v1/workbench/launches" && method === "POST") return json(response, 201, await createWorkbenchLaunch(request)); if (path === "/v1/workbench/sessions" && method === "GET") { await delay(state.sessionDelayMs); return json(response, 200, workbenchSessionListPayload(url)); } const turnMatch = path.match(/^\/v1\/workbench\/turns\/([^/]+)$/u); if (turnMatch && method === "GET") { const traceId = decodeURIComponent(turnMatch[1] ?? ""); if (state.scenarioId === "completed-replay-detail-404" && traceId === "trc_completed") return json(response, 404, { ok: false, status: 404, error: { code: "turn_replay_unavailable" } }); if (traceId === state.staleTraceId) return json(response, 502, { ok: false, status: 502, error: { code: "upstream_unavailable", message: "stale trace is unavailable" } }); return json(response, 200, workbenchTurnPayload(traceId)); } const traceMatch = path.match(/^\/v1\/workbench\/traces\/([^/]+)\/events$/u); if (traceMatch && method === "GET") { const traceId = decodeURIComponent(traceMatch[1] ?? ""); if (state.scenarioId === "completed-replay-detail-404" && traceId === "trc_completed") return json(response, 404, { ok: false, status: 404, error: { code: "trace_replay_unavailable" } }); if (state.scenarioId === "trace-hydration-timeout-diagnostic" && traceId === "trc_trace_hydration_timeout") return errorDiagnosticResponse(response, 504, `/v1/workbench/traces/${traceId}/events`, "trace_hydration_timeout", "Trace 更新超时,运行记录暂不可见。", { traceId: "33333333333333333333333333333333", requestId: "req_e2e_trace_hydration_timeout", layer: "workbench-read-model", category: "trace-hydration" }); if (state.scenarioId === "sealed-final-response-diagnostics" && traceId === "trc_sealed_final_diag") return errorDiagnosticResponse(response, 504, `/v1/workbench/traces/${traceId}/events`, "trace_hydration_timeout", "Trace 更新超时,运行记录暂不可见。", { traceId: "55555555555555555555555555555555", requestId: "req_e2e_sealed_final_trace_timeout", layer: "workbench-read-model", category: "trace-hydration" }); if (traceId === state.staleTraceId) return json(response, 502, { ok: false, status: 502, error: { code: "upstream_unavailable", message: "stale trace is unavailable" } }); return json(response, 200, workbenchTracePayload(traceId, url)); } const sessionMessagesMatch = path.match(/^\/v1\/workbench\/sessions\/([^/]+)\/messages$/u); if (sessionMessagesMatch && method === "GET") { const sessionId = canonicalSessionId(decodeURIComponent(sessionMessagesMatch[1] ?? "")); await delay(sessionDetailDelayMs(sessionId)); if (state.scenarioId === "created-session-read-failure" && sessionId === "ses_created_read_failure") return json(response, 503, { ok: false, status: 503, error: { code: "session_messages_unavailable" } }); const session = visibleSessionById(sessionId); return session ? json(response, 200, workbenchSessionMessagesPayload(session, url)) : json(response, 404, { ok: false, status: 404, error: { code: "session_not_found" } }); } const workbenchSessionMatch = path.match(/^\/v1\/workbench\/sessions\/([^/]+)$/u); if (workbenchSessionMatch && method === "GET") { const sessionId = canonicalSessionId(decodeURIComponent(workbenchSessionMatch[1] ?? "")); await delay(sessionDetailDelayMs(sessionId)); if (state.scenarioId === "created-session-read-failure" && sessionId === "ses_created_read_failure") return json(response, 503, { ok: false, status: 503, error: { code: "session_detail_unavailable" } }); if (state.scenarioId === "session-switch-detail-404-isolated" && sessionId === "ses_stale_404") return json(response, 404, { ok: false, status: 404, error: { code: "session_not_found" } }); if (state.scenarioId === "completed-replay-detail-404" && sessionId === "ses_completed") return json(response, 404, { ok: false, status: 404, error: { code: "session_replay_unavailable" } }); const session = visibleSessionById(sessionId, { includeArchived: true }); return session ? json(response, 200, { ok: true, status: "found", session }) : json(response, 404, { ok: false, status: 404, error: { code: "session_not_found" } }); } if (path === "/v1/agent/chat" && method === "POST") { const body = await readJson(request); state.chatRequests.push(redactRequestBody(body)); await delay(state.chatDelayMs); if (state.scenarioId === "admission-unavailable") { return json(response, 503, { ok: false, accepted: false, status: "failed", traceId: body.traceId, error: { code: "admission_unavailable", layer: "admission", retryable: true, message: "admission_unavailable: durable turn was not persisted" }, blocker: { code: "admission_unavailable", layer: "admission", retryable: true, summary: "durable turn was not persisted" }, valuesRedacted: true }); } return json(response, 200, acceptChatTurn(body)); } if (path === "/v1/agent/sessions" && method === "POST") { const body = await readJson(request); const session = createManualSession(body); state.selectedSessionId = session.sessionId; state.sessions.unshift(session); return json(response, state.scenarioId === "create-while-route-loading" ? 201 : 200, { ok: true, status: "ok", session }); } const agentSessionMatch = path.match(/^\/v1\/agent\/sessions\/([^/]+)$/u); if (agentSessionMatch && method === "DELETE") { const session = sessionById(decodeURIComponent(agentSessionMatch[1] ?? "")); if (!session) return json(response, 404, { ok: false, status: 404, error: { code: "session_not_found" } }); session.status = "archived"; session.updatedAt = new Date().toISOString(); return json(response, 200, { ok: true, status: "archived", session, archivedCount: 1 }); } if (agentSessionMatch && method === "GET") return json(response, 200, { session: sessionPayload(decodeURIComponent(agentSessionMatch[1] ?? "")) }); if (path === "/v1/provider-profiles") return json(response, 200, { profiles: [{ profile: "codex-api", name: "Codex API", configured: true }, { profile: "deepseek", name: "DeepSeek", configured: true }] }); if (path === "/health/live" || path === "/health" || path === "/v1") return json(response, 200, { status: "ok", serviceId: "workbench-e2e", codeAgent: { ready: true, status: "ready" } }); if (path === "/v1/live-builds") return json(response, 200, { status: "ok", builds: [] }); if (path === "/v1/hwpod/specs") return json(response, 200, hwpodSpecsPayload()); if (path === "/v1/hwpod-node-ops") return json(response, 200, hwpodNodeOpsPayload()); if (path.startsWith("/v1/project-management")) return projectManagementPayload(request, response, url, method); if (path === "/v1/web-performance/summary") { if (state.scenarioId === "performance-summary-error") return errorDiagnosticResponse(response, 502, "/v1/web-performance/summary", "upstream_unavailable", "暂时无法连接上游。"); const matrixStatus = performanceSummaryErrorStatus(state.scenarioId); if (matrixStatus !== null) return errorDiagnosticResponse(response, matrixStatus, "/v1/web-performance/summary", `e2e_http_${matrixStatus}`, `模拟 ${matrixStatus} 错误。`, { traceId: statusMatrixTraceId(matrixStatus), requestId: `req_e2e_api_status_${matrixStatus}`, category: matrixStatus >= 500 ? "server" : "client" }); if (state.scenarioId === "performance-network-error") { response.destroy(new Error("e2e performance network reset")); return; } if (state.scenarioId === "performance-empty") return json(response, 200, webPerformanceEmptyPayload(url)); if (state.scenarioId === "performance-stale-window") return json(response, 200, webPerformanceStaleWindowPayload(url)); return json(response, 200, webPerformanceSummaryPayload(url)); } if (path.startsWith("/v1/") || path.startsWith("/auth/") || path.startsWith("/health")) return json(response, 500, { ok: false, status: 500, error: { code: "unmocked_request", path } }); return staticFile(response, path); } function hwpodSpecsPayload(): JsonRecord { return { ok: true, status: "completed", count: 1, availableCount: 0, nodeOpsContractVersion: "hwpod-node-ops-v1", specs: [ { name: "d601-f103-v2", hwpodId: "d601-f103-v2", nodeId: "node-d601-f103-v2", workspacePath: "F:\\Work\\D601-HWLAB", source: { caseId: "d601-f103-v2-compile" }, availability: { ok: false, status: "blocked", checkedAt: "2026-06-18T04:30:00.000Z", results: [ { opId: "op_01_workspace_ls", op: "workspace.ls", ok: false, status: "blocked", blocker: { code: "hwpod_node_unavailable", layer: "hwpod-node", retryable: true, summary: "no outbound WebSocket hwpod-node is connected" } } ] } } ] }; } function hwpodNodeOpsPayload(): JsonRecord { return { ok: true, status: "ready", contractVersion: "hwpod-node-ops-v1", route: "/v1/hwpod-node-ops", supportedOps: ["node.health", "workspace.ls", "debug.build", "debug.flash"], websocket: { connectedCount: 0, pendingCount: 1, nodes: [] }, events: [ { ts: "2026-06-18T04:30:00.000Z", status: "blocked", blocker: { code: "hwpod_node_unavailable", summary: "no outbound WebSocket hwpod-node is connected" } } ] }; } async function projectManagementPayload(request: IncomingMessage, response: ServerResponse, url: URL, method: string): Promise { const path = url.pathname; const source = projectManagementSource(); const files = projectManagementFiles(); const links = state.projectLinks; const tasks = projectManagementTasks(links); if (path === "/v1/project-management/workbench-links" && method === "POST") { const body = await readJson(request); const link = projectManagementLinkFromBody(body); state.projectLinks.unshift(link); return json(response, 201, projectManagementEnvelope({ link })); } if (method !== "GET" && method !== "HEAD") return json(response, 405, { ok: false, contractVersion: "project-management-v1", serviceId: "hwlab-project-management", error: { code: "method_not_allowed" }, valuesRedacted: true }); if (path === "/v1/project-management" || path === "/v1/project-management/navigation") { return json(response, 200, projectManagementEnvelope({ navigation: { id: "project-management", label: "Project Management", actor: { id: "usr_e2e_admin", role: "admin", authMethod: "web-session" }, items: [ { id: "projects", label: "Projects", apiRoute: "/v1/project-management/projects" }, { id: "mdtodo", label: "MDTODO", apiRoute: "/v1/project-management/mdtodo/tasks" } ], capabilities: { mdtodoProjection: true, workbenchLaunch: true, workbenchLinks: true, sourceOfTruth: "markdown-files" } }, projection: { sourceId: source.sourceId, documentCount: files.length, taskCount: tasks.length, projectedAt: "2026-06-25T09:00:00.000Z" } })); } if (path === "/v1/project-management/projects") return json(response, 200, projectManagementEnvelope({ projects: [{ projectId: "project_hwlab_v03", name: "HWLAB MDTODO", sourceIds: [source.sourceId], sourceOfTruth: "markdown-files", status: "active" }] })); if (path === "/v1/project-management/mdtodo/sources") return json(response, 200, projectManagementEnvelope({ sources: [source] })); if (path === "/v1/project-management/mdtodo/files") return json(response, 200, projectManagementEnvelope({ files: files.filter((file) => !url.searchParams.get("sourceId") || file.sourceId === url.searchParams.get("sourceId")) })); if (path === "/v1/project-management/mdtodo/tasks") return json(response, 200, projectManagementEnvelope({ tasks: tasks.filter((task) => (!url.searchParams.get("sourceId") || task.sourceId === url.searchParams.get("sourceId")) && (!url.searchParams.get("fileRef") || task.fileRef === url.searchParams.get("fileRef"))) })); if (path === "/v1/project-management/workbench-links") return json(response, 200, projectManagementEnvelope({ links: links.filter((link) => !url.searchParams.get("taskRef") || link.taskRef === url.searchParams.get("taskRef")) })); return json(response, 404, { ok: false, contractVersion: "project-management-v1", serviceId: "hwlab-project-management", error: { code: "not_found" }, valuesRedacted: true }); } function projectManagementEnvelope(payload: JsonRecord): JsonRecord { return { ok: true, contractVersion: "project-management-v1", serviceId: "hwlab-project-management", ...payload, valuesRedacted: true }; } function projectManagementSource(): JsonRecord { return { sourceId: "hwlab-v03-mdtodo", kind: "mdtodo-file-tree", displayName: "HWLAB MDTODO", projectId: "project_hwlab_v03", status: "active", rootRef: "[redacted]", valuesRedacted: true }; } function projectManagementFiles(): JsonRecord[] { return [ { sourceId: "hwlab-v03-mdtodo", fileRef: "file_plan", projectId: "project_hwlab_v03", relativePath: "project-management/PJ2026-01/MDTODO.md", title: "项目管理任务", taskCount: 2, parseError: null, revision: 1, updatedAt: "2026-06-25T09:00:00.000Z" }, { sourceId: "hwlab-v03-mdtodo", fileRef: "file_rollout", projectId: "project_hwlab_v03", relativePath: "ops/D601-v03-rollout.md", title: "D601 发布任务", taskCount: 1, parseError: null, revision: 1, updatedAt: "2026-06-25T09:00:00.000Z" } ]; } function projectManagementTasks(links: JsonRecord[] = []): JsonRecord[] { const linkCount = (taskRef: string) => links.filter((link) => link.taskRef === taskRef).length; return [ { taskRef: "mdtodo:hwlab-v03-mdtodo:file_plan:t1", projectId: "project_hwlab_v03", sourceId: "hwlab-v03-mdtodo", fileRef: "file_plan", taskId: "t1", title: "实现项目根导航", status: "done", parentTaskRef: null, depth: 0, lineNumber: 4, ordinal: 1, linkCount: linkCount("mdtodo:hwlab-v03-mdtodo:file_plan:t1"), updatedAt: "2026-06-25T09:00:00.000Z" }, { taskRef: "mdtodo:hwlab-v03-mdtodo:file_plan:t2", projectId: "project_hwlab_v03", sourceId: "hwlab-v03-mdtodo", fileRef: "file_plan", taskId: "t2", title: "展示 MDTODO 任务详情", status: "open", parentTaskRef: "mdtodo:hwlab-v03-mdtodo:file_plan:t1", depth: 1, lineNumber: 5, ordinal: 2, linkCount: linkCount("mdtodo:hwlab-v03-mdtodo:file_plan:t2"), updatedAt: "2026-06-25T09:00:00.000Z" }, { taskRef: "mdtodo:hwlab-v03-mdtodo:file_rollout:t1", projectId: "project_hwlab_v03", sourceId: "hwlab-v03-mdtodo", fileRef: "file_rollout", taskId: "t1", title: "D601 v03 页面验收", status: "blocked", parentTaskRef: null, depth: 0, lineNumber: 3, ordinal: 3, linkCount: linkCount("mdtodo:hwlab-v03-mdtodo:file_rollout:t1"), updatedAt: "2026-06-25T09:00:00.000Z" } ]; } function projectManagementSeedLinks(): JsonRecord[] { return [{ linkId: "lnk_project_task_root", projectId: "project_hwlab_v03", taskRef: "mdtodo:hwlab-v03-mdtodo:file_plan:t1", sessionId: "ses_project_seed", traceId: "trc_project_seed", role: "reference", updatedAt: "2026-06-25T09:00:00.000Z" }]; } function projectManagementLinkFromBody(body: JsonRecord): JsonRecord { const now = new Date().toISOString(); return { linkId: String(body.linkId ?? `lnk_project_launch_${Date.now().toString(36)}`), projectId: String(body.projectId ?? "project_hwlab_v03"), taskRef: typeof body.taskRef === "string" ? body.taskRef : null, sessionId: typeof body.sessionId === "string" ? body.sessionId : null, traceId: typeof body.traceId === "string" ? body.traceId : null, role: String(body.role ?? "launch"), updatedAt: now, link: body.link && typeof body.link === "object" ? body.link : { valuesRedacted: true } }; } async function createWorkbenchLaunch(request: IncomingMessage): Promise { const body = await readJson(request); const now = new Date().toISOString(); const sessionId = typeof body.sessionId === "string" && body.sessionId.trim() ? body.sessionId : `ses_project_launch_${Date.now().toString(36)}`; const conversationId = typeof body.conversationId === "string" && body.conversationId.trim() ? body.conversationId : `cnv_project_launch_${Date.now().toString(36)}`; const launchContext = body.launchContext && typeof body.launchContext === "object" ? body.launchContext as JsonRecord : {}; const session: SessionRecord = { sessionId, conversationId, status: "idle", projectId: String(body.projectId ?? launchContext.projectId ?? "project_hwlab_v03"), launchContext, metadata: { launchContext }, startedAt: now, updatedAt: now, messageCount: 0, firstUserMessagePreview: null, messages: [] }; state.sessions.unshift(session); const link = projectManagementLinkFromBody({ linkId: `lnk_project_launch_${sessionId.replace(/^ses_/u, "")}`, projectId: session.projectId, taskRef: body.taskRef, sessionId, traceId: null, role: "launch", link: { launchContext, workbenchUrl: `/workbench/sessions/${sessionId}`, valuesRedacted: true } }); state.projectLinks.unshift(link); return { ok: true, status: "created", contractVersion: "workbench-launch-v1", sessionId, conversationId, projectId: session.projectId, taskRef: body.taskRef, workbenchUrl: `/workbench/sessions/${sessionId}`, linkId: link.linkId, link, launchContext, valuesRedacted: true }; } function webPerformanceSummaryPayload(url: URL): JsonRecord { const sampleWindow = fakePerformanceWindow(url.searchParams.get("window")); const rows = [ performanceRow({ kind: "workbench-journey", metric: "session-switch-full-load", route: "/workbench/sessions/:sessionId", count: 21, p50: 0.18, p75: 0.31, p95: 1.12, tone: "warn", backend: "agentrun", transport: "sse", targetState: "completed", sourceFamily: "workbench" }, sampleWindow), performanceRow({ kind: "workbench-event-phase", metric: "trace-event-projected", route: "/workbench", count: 28, p50: 0.08, p75: 0.14, p95: 0.42, tone: "ok", eventType: "tool_result", phase: "render", source: "rum", sourceFamily: "workbench" }, sampleWindow), performanceRow({ kind: "workbench-backend-event", metric: "backend-event-visible", route: "/v1/workbench/events", count: 15, p50: 0.2, p75: 0.34, p95: 1.38, tone: "warn", eventType: "agentrun.stdout", backend: "agentrun", cache: "miss", sourceFamily: "backend" }, sampleWindow), performanceRow({ kind: "web-vital", metric: "LCP", route: "/performance", count: 9, p50: 1.2, p75: 1.8, p95: 2.9, tone: "ok", sourceFamily: "web" }, sampleWindow), performanceRow({ kind: "api", metric: "api_request", route: "/v1/web-performance/summary", method: "GET", statusClass: "2xx", outcome: "ok", count: 17, p50: 0.09, p75: 0.15, p95: 0.33, tone: "ok", sourceFamily: "web", backendEvidence: fakeBackendEvidence({ route: "/v1/web-performance/summary", count: 16, p95: 0.18, diagnostic: "backend_matched", diagnosticLabel: "后端样本已匹配" }) }, sampleWindow), performanceRow({ kind: "api", metric: "api_request", route: "/v1/workbench/sessions", method: "GET", statusClass: "2xx", outcome: "ok", count: 3, p50: 2.5, p75: 5, p95: 10, tone: "warn", problem: "slow-api_request", sampleState: "low-sample", freshness: "low-sample", aggregationKind: "histogram", approximation: "bucketed", sourceFamily: "web", backendEvidence: fakeBackendEvidence({ route: "/v1/workbench/sessions", count: 4, p95: 0.24, diagnostic: "rum_slower_than_backend", diagnosticLabel: "RUM 慢于后端" }) }, sampleWindow), performanceRow({ kind: "long-task", metric: "longtask", route: "/workbench", count: 3, p50: 0.08, p75: 0.11, p95: 0.2, tone: "warn", problem: "main-thread busy", sourceFamily: "web" }, sampleWindow) ]; const sampleCount = performanceSampleCount(rows); const collectionHealth = performanceCollectionHealthPayload(rows, sampleWindow); return { ok: true, status: "ready", source: "fake-server", observedAt: sampleWindow.generatedAt, namespace: "hwlab-v03", gitopsTarget: "D601/v03", sampleWindow: performanceSampleWindowPayload(sampleWindow), summary: performanceSummaryContract(sampleWindow, rows, { status: "ready", sampleCount, sampleSeries: 12, problemCount: rows.filter((row) => row.tone === "warn").length }), backendEvidence: fakeBackendEvidenceSummary(rows, sampleWindow), collectionHealth, dashboard: webPerformanceDashboardPayload(rows, sampleWindow, collectionHealth), rows, problems: rows.filter((row) => row.tone === "warn"), webVitals: rows.filter((row) => row.kind === "web-vital"), apiRoutes: rows.filter((row) => row.kind === "api"), longTasks: rows.filter((row) => row.kind === "long-task"), workbenchJourneys: rows.filter((row) => row.kind === "workbench-journey"), workbenchEventPhases: rows.filter((row) => row.kind === "workbench-event-phase"), workbenchBackendEvents: rows.filter((row) => row.kind === "workbench-backend-event") }; } function fakeBackendEvidence(input: { route: string; count: number; p95: number; diagnostic: string; diagnosticLabel: string }): JsonRecord { return { status: "matched", statusLabel: "已匹配后端", diagnostic: input.diagnostic, diagnosticLabel: input.diagnosticLabel, detail: `fake-server backend evidence for ${input.route}`, route: input.route, method: "GET", count: input.count, p50: Math.max(0.02, input.p95 / 3), p75: Math.max(0.04, input.p95 / 2), p95: input.p95, responseBytesP95: 4096, lastObservedAt: "2026-06-18T04:29:59.000Z", phases: [{ phase: "workbench_session_page_query", outcome: "ok", count: input.count, p95: Math.min(input.p95, 0.2) }] }; } function fakeBackendEvidenceSummary(rows: JsonRecord[], sampleWindow: FakePerformanceWindow): JsonRecord { const evidenceRows = rows .map((row) => row.backendEvidence) .filter((evidence): evidence is JsonRecord => Boolean(evidence && typeof evidence === "object" && !Array.isArray(evidence))) .map((evidence) => ({ route: evidence.route, method: evidence.method, statusClass: "2xx", outcome: "ok", count: evidence.count, average: evidence.p50, p50: evidence.p50, p75: evidence.p75, p95: evidence.p95, firstObservedAt: sampleWindow.windowFrom, lastObservedAt: evidence.lastObservedAt, responseBytes: { count: evidence.count, average: 2048, p50: 2048, p75: 3072, p95: evidence.responseBytesP95 }, phases: evidence.phases, valuesRedacted: true })); return { schemaVersion: "hwlab-backend-performance-evidence-v1", source: "fake-server-backend-performance-store", observedAt: sampleWindow.generatedAt, sampleCount: evidenceRows.reduce((sum, row) => sum + Number(row.count ?? 0), 0), retainedSampleCount: evidenceRows.length, routeCount: evidenceRows.length, rows: evidenceRows, available: true, valuesRedacted: true }; } function webPerformanceEmptyPayload(url: URL): JsonRecord { const sampleWindow = fakePerformanceWindow(url.searchParams.get("window")); const rows: JsonRecord[] = []; const collectionHealth = performanceCollectionHealthPayload(rows, sampleWindow); return { ok: true, status: "waiting", source: "fake-server", observedAt: sampleWindow.generatedAt, namespace: "hwlab-v03", gitopsTarget: "D601/v03", sampleWindow: performanceSampleWindowPayload(sampleWindow), summary: performanceSummaryContract(sampleWindow, rows, { status: "waiting", sampleCount: 0, sampleSeries: 0, problemCount: 0 }), collectionHealth, dashboard: webPerformanceDashboardPayload(rows, sampleWindow, collectionHealth), rows, problems: [], webVitals: [], apiRoutes: [], longTasks: [], workbenchJourneys: [], workbenchEventPhases: [], workbenchBackendEvents: [] }; } function webPerformanceStaleWindowPayload(url: URL): JsonRecord { const sampleWindow = fakePerformanceWindow(url.searchParams.get("window")); const rows: JsonRecord[] = []; const collectionHealth = { schemaVersion: "hwlab-web-performance-collection-health-v1", status: "waiting", statusLabel: "等待数据", reason: "no_samples_in_window", reasonLabel: "当前窗口暂无样本", sampleCount: 0, retainedSampleCount: 37, sampleSeries: 0, lowSampleThreshold: 5, firstSampleAt: null, lastSampleAt: null, lastRetainedSampleAt: "2026-06-18T03:20:00.000Z", secondsSinceLastSample: 4200, windowCoverageSeconds: null, sourceFamilyCounts: [{ sourceFamily: "web", rowCount: 0, sampleCount: 37 }], unknownAttribution: { workbenchRows: 0, rowsWithUnknown: 0, samplesWithUnknown: 0, backendUnknownRows: 0, transportUnknownRows: 0 }, diagnostics: [{ code: "no_samples_in_window", label: "当前窗口无样本", tone: "warn", detail: "保留样本存在,但当前窗口没有性能样本。" }] }; return { ok: true, status: "waiting", source: "fake-server", observedAt: sampleWindow.generatedAt, namespace: "hwlab-v03", gitopsTarget: "D601/v03", sampleWindow: performanceSampleWindowPayload(sampleWindow), summary: performanceSummaryContract(sampleWindow, rows, { status: "waiting", sampleCount: 0, retainedSampleCount: 37, sampleSeries: 0, problemCount: 0 }), backendEvidence: { schemaVersion: "hwlab-backend-performance-evidence-v1", source: "fake-server-backend-performance-store", observedAt: sampleWindow.generatedAt, sampleCount: 0, retainedSampleCount: 37, routeCount: 0, rows: [], available: true, valuesRedacted: true }, collectionHealth, dashboard: webPerformanceDashboardPayload(rows, sampleWindow, collectionHealth), rows, problems: [], webVitals: [], apiRoutes: [], longTasks: [], workbenchJourneys: [], workbenchEventPhases: [], workbenchBackendEvents: [] }; } function performanceRow(row: JsonRecord, sampleWindow: FakePerformanceWindow): JsonRecord { const count = Number(row.count ?? 0); const sampleState = count === 0 ? "empty" : count < 5 ? "low-sample" : "ok"; return { method: "GET", statusClass: "2xx", outcome: "ok", unit: "seconds", sampleState, sampleCount: count, sourceFamily: "mixed", freshness: sampleState === "ok" ? "fresh" : sampleState, aggregationKind: "exact", approximation: "exact", windowFrom: sampleWindow.windowFrom, windowTo: sampleWindow.windowTo, generatedAt: sampleWindow.generatedAt, ...row }; } function webPerformanceDashboardPayload(rows: JsonRecord[], sampleWindow: FakePerformanceWindow, collectionHealth: JsonRecord = performanceCollectionHealthPayload(rows, sampleWindow)): JsonRecord { const workbench = rows.filter((row) => String(row.kind).startsWith("workbench")); const api = rows.filter((row) => row.kind === "api"); const vital = rows.filter((row) => row.kind === "web-vital"); const longTask = rows.filter((row) => row.kind === "long-task"); const sampleCount = performanceSampleCount(rows); const problemCount = rows.filter((row) => row.tone === "warn").length; return { schemaVersion: "hwlab-web-performance-dashboard-v1", generatedAt: sampleWindow.generatedAt, sampleWindow: { ...performanceSampleWindowPayload(sampleWindow), buckets: [{ id: sampleWindow.id, label: sampleWindow.label, observedAt: sampleWindow.generatedAt, sampleCount }] }, freshness: { observedAt: sampleWindow.generatedAt, generatedAt: sampleWindow.generatedAt, windowFrom: sampleWindow.windowFrom, windowTo: sampleWindow.windowTo, sampleCount, source: "fake-server", sourceFamily: "mixed", namespace: "hwlab-v03", gitopsTarget: "D601/v03", status: collectionHealth.status, statusLabel: collectionHealth.statusLabel, reason: collectionHealth.reason, reasonLabel: collectionHealth.reasonLabel, lowSampleThreshold: 5, lastSampleAt: collectionHealth.lastSampleAt, lastRetainedSampleAt: collectionHealth.lastRetainedSampleAt, secondsSinceLastSample: collectionHealth.secondsSinceLastSample }, collectionHealth, cards: [ { id: "health", label: "采集状态", value: collectionHealth.statusLabel, unit: "状态", tone: sampleCount === 0 ? "source" : collectionHealth.status === "fresh" ? "ok" : "warn", detail: collectionHealth.reasonLabel }, { id: "samples", label: "样本数", value: sampleCount, unit: "样本", tone: sampleCount === 0 ? "source" : "ok", detail: `${sampleWindow.label} · ${rows.length} 个序列` }, { id: "workbench", label: "工作台序列", value: workbench.length, unit: "序列", tone: workbench.length > 0 ? "ok" : "source", detail: "hwlab-v03 / D601/v03" }, { id: "problems", label: "问题行", value: problemCount, unit: "条", tone: problemCount > 0 ? "warn" : "ok", detail: "低样本阈值 5 个样本" } ], trends: [ { id: "workbench-experience", title: "工作台体感趋势", subtitle: "首屏、会话切换和提交首个可见结果的 P95", unit: "seconds", points: workbench.map(dashboardPoint) }, { id: "api-timing", title: "同源 API 耗时", subtitle: "Cloud Web 同源 API 请求 P95", unit: "seconds", points: api.map(dashboardPoint) }, { id: "web-vitals", title: "浏览器核心指标", subtitle: "浏览器体感当前窗口", unit: "mixed", points: vital.map(dashboardPoint) } ], distributions: [ { id: "status", title: "状态分布", subtitle: "按健康状态聚合当前窗口行数", unit: "count", buckets: [{ label: "正常", count: 4, tone: "ok" }, { label: "预警", count: 2, tone: "warn" }] }, { id: "samples", title: "样本状态", subtitle: "正常、低样本和暂无数据分布", unit: "count", buckets: [{ label: "正常样本", count: 6, tone: "ok" }] } ], topN: [ { id: "top-api", title: "慢 API TopN", subtitle: "同源 API P95 最慢路由", unit: "seconds", rows: api.map(dashboardTopRow) }, { id: "top-workbench", title: "工作台慢路径 TopN", subtitle: "工作台 journey 和事件可见延迟", unit: "seconds", rows: workbench.map(dashboardTopRow) }, { id: "top-long-task", title: "长任务 TopN", subtitle: "主线程长任务当前窗口", unit: "seconds", rows: longTask.map(dashboardTopRow) } ] }; } function performanceCollectionHealthPayload(rows: JsonRecord[], sampleWindow: FakePerformanceWindow): JsonRecord { const sampleCount = performanceSampleCount(rows); const sourceFamilyCounts = performanceSourceFamilyCounts(rows); const unknownAttribution = performanceUnknownAttribution(rows); const diagnostics: JsonRecord[] = []; let status = "fresh"; let reason = "window_has_samples"; let reasonLabel = "当前窗口采集正常"; if (sampleCount <= 0) { status = "waiting"; reason = "no_samples_retained"; reasonLabel = "采集器尚未上报样本"; diagnostics.push({ code: reason, label: "暂无采集样本", tone: "source", detail: "fake-server 当前场景没有性能样本。" }); } else if (sampleCount < 5) { status = "low-sample"; reason = "low_sample_window"; reasonLabel = "当前窗口低样本"; diagnostics.push({ code: reason, label: "低样本窗口", tone: "warn", detail: `当前窗口只有 ${sampleCount} 个样本,低于 5 个样本阈值。` }); } const rowsWithUnknown = Number(unknownAttribution.rowsWithUnknown ?? 0); if (rowsWithUnknown > 0) { if (status === "fresh") { status = "degraded"; reason = "unknown_attribution"; reasonLabel = "归因字段不完整"; } diagnostics.push({ code: "unknown_attribution", label: "工作台归因不完整", tone: "warn", detail: `${rowsWithUnknown} 条工作台序列存在 backend 或 transport unknown。` }); } if (sourceFamilyCounts.length > 1) diagnostics.push({ code: "mixed_source_family", label: "多来源样本", tone: "ok", detail: `当前窗口包含 ${sourceFamilyCounts.length} 类低基数来源。` }); if (!diagnostics.length) diagnostics.push({ code: "ok", label: "采集健康", tone: "ok", detail: "当前窗口有足够样本,且没有发现低样本、缺样或 unknown 归因问题。" }); return { schemaVersion: "hwlab-web-performance-collection-health-v1", status, statusLabel: status === "fresh" ? "采集正常" : status === "low-sample" ? "低样本" : status === "degraded" ? "归因不完整" : "等待数据", reason, reasonLabel, sampleCount, retainedSampleCount: sampleCount, sampleSeries: rows.length, lowSampleThreshold: 5, firstSampleAt: sampleCount > 0 ? sampleWindow.windowFrom : null, lastSampleAt: sampleCount > 0 ? sampleWindow.generatedAt : null, lastRetainedSampleAt: sampleCount > 0 ? sampleWindow.generatedAt : null, secondsSinceLastSample: sampleCount > 0 ? 0 : null, windowCoverageSeconds: sampleCount > 0 ? sampleWindow.seconds : null, sourceFamilyCounts, unknownAttribution, diagnostics }; } function performanceSourceFamilyCounts(rows: JsonRecord[]): JsonRecord[] { const counts = new Map(); for (const row of rows) { const sourceFamily = String(row.sourceFamily ?? "mixed"); const entry = counts.get(sourceFamily) ?? { sourceFamily, rowCount: 0, sampleCount: 0 }; entry.rowCount += 1; entry.sampleCount += Math.max(0, Number(row.count) || 0); counts.set(sourceFamily, entry); } return [...counts.values()].sort((left, right) => right.sampleCount - left.sampleCount || left.sourceFamily.localeCompare(right.sourceFamily)); } function performanceUnknownAttribution(rows: JsonRecord[]): JsonRecord { const workbenchRows = rows.filter((row) => String(row.kind ?? "").startsWith("workbench")); const isUnknown = (value: unknown) => !String(value ?? "").trim() || String(value ?? "").trim().toLowerCase() === "unknown" || String(value ?? "").trim() === "-"; const rowsWithUnknown = workbenchRows.filter((row) => isUnknown(row.backend) || isUnknown(row.transport)).length; return { workbenchRows: workbenchRows.length, rowsWithUnknown, samplesWithUnknown: workbenchRows.reduce((sum, row) => sum + ((isUnknown(row.backend) || isUnknown(row.transport)) ? Math.max(0, Number(row.count) || 0) : 0), 0), backendUnknownRows: workbenchRows.filter((row) => isUnknown(row.backend)).length, transportUnknownRows: workbenchRows.filter((row) => isUnknown(row.transport)).length }; } function fakePerformanceWindow(value: string | null): FakePerformanceWindow { const id = ["5m", "15m", "1h", "6h", "24h", "all"].includes(String(value)) ? String(value) : "15m"; const generatedAt = "2026-06-18T04:30:00.000Z"; const specs: Record> = { "5m": { label: "最近 5 分钟", seconds: 300, windowFrom: "2026-06-18T04:25:00.000Z" }, "15m": { label: "最近 15 分钟", seconds: 900, windowFrom: "2026-06-18T04:15:00.000Z" }, "1h": { label: "最近 1 小时", seconds: 3600, windowFrom: "2026-06-18T03:30:00.000Z" }, "6h": { label: "最近 6 小时", seconds: 21600, windowFrom: "2026-06-17T22:30:00.000Z" }, "24h": { label: "最近 24 小时", seconds: 86400, windowFrom: "2026-06-17T04:30:00.000Z" }, all: { label: "全部累计", seconds: null, windowFrom: null } }; const spec = specs[id] ?? { label: "最近 15 分钟", seconds: 900, windowFrom: "2026-06-18T04:15:00.000Z" }; return { id, generatedAt, windowTo: generatedAt, ...spec }; } function performanceSampleWindowPayload(sampleWindow: FakePerformanceWindow): JsonRecord { return { id: sampleWindow.id, label: sampleWindow.label, seconds: sampleWindow.seconds, windowFrom: sampleWindow.windowFrom, windowTo: sampleWindow.windowTo, generatedAt: sampleWindow.generatedAt, aggregationKind: "exact", approximation: "exact" }; } function performanceSummaryContract(sampleWindow: FakePerformanceWindow, rows: JsonRecord[], summary: JsonRecord): JsonRecord { return { routeCount: rows.length, durationSeries: rows.filter((row) => row.unit === "seconds").length, lowSampleThreshold: 5, workbenchJourneySeries: rows.filter((row) => row.kind === "workbench-journey").length, workbenchEventPhaseSeries: rows.filter((row) => row.kind === "workbench-event-phase").length, workbenchBackendEventVisibleSeries: rows.filter((row) => row.kind === "workbench-backend-event").length, window: sampleWindow.id, windowLabel: sampleWindow.label, windowSeconds: sampleWindow.seconds, windowFrom: sampleWindow.windowFrom, windowTo: sampleWindow.windowTo, generatedAt: sampleWindow.generatedAt, aggregationKind: "exact", approximation: "exact", ...summary }; } function performanceSampleCount(rows: JsonRecord[]): number { return rows.reduce((total, row) => total + (Number(row.count) || 0), 0); } function dashboardPoint(row: JsonRecord): JsonRecord { return { label: dashboardMetricLabel(row), detail: dashboardRouteLabel(row.route), value: row.p95, p50: row.p50, p75: row.p75, p95: row.p95, count: row.count, tone: row.tone, sampleState: row.sampleState }; } function dashboardTopRow(row: JsonRecord): JsonRecord { return { label: dashboardMetricLabel(row), detail: dashboardRouteLabel(row.route), value: row.p95, unit: row.unit ?? "seconds", count: row.count, tone: row.tone }; } function dashboardRouteLabel(route: unknown): string { const value = String(route ?? "").trim(); if (!value || value === "-") return "当前窗口"; return value .replace(/:sessionId/gu, ":会话") .replace(/:traceId/gu, ":轨迹") .replace(/:runId/gu, ":运行") .replace(/:threadId/gu, ":线程") .replace(/:turnId/gu, ":轮次"); } function dashboardMetricLabel(row: JsonRecord): string { const metric = String(row.metric ?? "unknown"); const labels: Record = { "session-switch-full-load": "切换会话完整加载", "trace-event-projected": "轨迹事件投影", "backend-event-visible": "后端事件到可见", LCP: "最大内容绘制", fetchJson: "同源 API 请求", longtask: "主线程长任务" }; return labels[metric] ?? metric; } function createScenarioState(scenarioId: string): ScenarioState { const base = structuredClone(capture.scenario); const id = scenarioId || "baseline"; const sessions = base.sessions; const traces = base.traces; if (id === "cross-project-detail-boundary") sessions.push(hiddenBoundarySession()); if (id === "legacy-cnv-deeplink-canonical") { sessions.unshift(legacyCanonicalSession()); traces.trc_40badc15523146c9 = legacyCanonicalTrace(); } if (id === "submit-authority-race") { sessions.unshift(submitSplitSession()); traces.trc_submit_split = submitSplitTrace(); } if (id === "session-switch-delayed-detail-frame") { markSessionText(sessions, "ses_running", "SESSION_A_ONLY", "SESSION_A_ONLY running source session"); markSessionText(sessions, "ses_completed", "SESSION_B_ONLY", "SESSION_B_ONLY completed target session"); } if (id === "session-rail-many") { for (let index = 0; index < 51; index += 1) sessions.push(manyRailSession(index)); } if (id === "session-switch-detail-404-isolated") { sessions.unshift(staleDetailSession()); sessions.push(emptySession()); } if (id === "terminal-empty-trace") { sessions.push(terminalEmptyTraceSession()); traces.trc_terminal_empty = terminalEmptyTrace(); } if (id === "markdown-final-response") { sessions.unshift(markdownFinalSession()); traces.trc_markdown_final = markdownFinalTrace(); } if (id === "terminal-assistant-event-final-response") { sessions.unshift(terminalAssistantFinalSession()); traces.trc_terminal_assistant_final = terminalAssistantFinalTrace(); } if (id === "progress-only-final-response") markRunningProgressOnly(sessions, traces); if (id === "terminal-completed-no-final-response") markRunningNoFinalResponse(sessions, traces); if (id === "tool-completed-projection-running") markToolCompletedProjectionRunning(sessions, traces); if (id === "terminal-canceled-late-timing") markTerminalCanceledLateTiming(sessions, traces); if (id === "projection-degraded-diagnostics") { sessions.unshift(projectionDegradedSession()); traces.trc_projection_degraded = projectionDegradedTrace(); } if (id === "projection-sse-error") { sessions.unshift(projectionSseErrorSession()); traces.trc_projection_sse_error = projectionSseErrorTrace(); } if (id === "trace-hydration-timeout-diagnostic") { sessions.unshift(traceHydrationTimeoutSession()); traces.trc_trace_hydration_timeout = traceHydrationTimeoutTrace(); } if (id === "sealed-final-response-diagnostics") { sessions.unshift(sealedFinalResponseDiagnosticSession()); traces.trc_sealed_final_diag = sealedFinalResponseDiagnosticTrace(); } if (id === "trace-final-response-not-message-authority") { sessions.unshift(traceFinalResponseConflictSession()); traces.trc_trace_final_conflict = traceFinalResponseConflictTrace(); } if (id === "scroll-follow-long-trace") { const session = scrollFollowSession(); sessions.unshift(session); traces.trc_scroll_follow = scrollFollowTrace(90); } if (id === "projector-resume-from-checkpoint") { const session = projectorResumeSession(); sessions.unshift(session); traces.trc_f2456023233a485b = projectorResumeEarlyTrace(); } if (id === "cross-session-late-events") { sessions.unshift(crossSessionLateB(), crossSessionLateA()); traces.trc_late_A = crossSessionLateTraceA(); } if (id === "deleted-session-deeplink") sessions.unshift(archivedDeletedSession()); if (id === "session-switch-empty-reload") sessions.push(emptySession()); if (id === "empty-session-gc") sessions.unshift(staleEmptyTtlSession(), freshEmptyTtlSession(), staleMessagedTtlSession()); const selectedSessionId = id === "scroll-follow-long-trace" ? "ses_scroll_follow" : id === "deep-link" || id === "stale-nested-trace" ? "ses_failed" : id === "legacy-cnv-deeplink-canonical" ? "ses_running" : id === "session-switch-detail-404-isolated" || id === "completed-replay-detail-404" || id === "deleted-session-deeplink" || id === "terminal-turn-stale-session-active" ? "ses_completed" : id === "terminal-empty-trace" ? "ses_terminal_empty" : id === "markdown-final-response" ? "ses_markdown_final" : id === "terminal-assistant-event-final-response" ? "ses_terminal_assistant_final" : id === "progress-only-final-response" || id === "terminal-completed-no-final-response" || id === "tool-completed-projection-running" || id === "terminal-canceled-late-timing" ? "ses_running" : id === "projector-resume-from-checkpoint" ? "ses_317f78e1-ed91-4b09-a72a-3668d5469f59" : id === "projection-degraded-diagnostics" ? "ses_projection_degraded" : id === "projection-sse-error" ? "ses_projection_sse_error" : id === "trace-hydration-timeout-diagnostic" ? "ses_trace_hydration_timeout" : id === "sealed-final-response-diagnostics" ? "ses_sealed_final_diag" : id === "trace-final-response-not-message-authority" ? "ses_trace_final_conflict" : id === "create-while-route-loading" ? "ses_running" : base.selectedSessionId; const staleTraceId = id === "stale-nested-trace" || id === "stale-submit-restore" ? "trc_stale_502" : null; return { scenarioId: id, providerProfile: base.providerProfile, selectedSessionId, sessions, traces, requestLedger: [], legacyRequestLedger: [], chatRequests: [], projectLinks: projectManagementSeedLinks(), listOmitSelected: id === "selected-missing-from-list", sessionDelayMs: id === "loading" ? 2_500 : 0, sessionDetailDelayMs: id === "legacy-cnv-deeplink-canonical" ? 1_500 : id === "session-switch-delayed-detail-frame" ? 900 : id === "submit-authority-race" ? 1_000 : 0, chatDelayMs: id === "submit-authority-race" ? 1_000 : 0, terminalScript: id === "event-replay" || id === "running-to-terminal" || id === "stale-submit-restore" || id === "progress-only-final-response" || id === "terminal-completed-no-final-response" || id === "terminal-canceled-late-timing", terminalFailureScript: id === "stale-submit-restore", staleTraceId, liveBackfillTraceId: id === "projector-resume-from-checkpoint" ? "trc_f2456023233a485b" : null, liveBackfillReadyAtMs: id === "projector-resume-from-checkpoint" ? Date.now() + 5_000 : null }; } function refreshBackgroundProjection(): void { if (state.scenarioId !== "projector-resume-from-checkpoint") return; if (!state.liveBackfillReadyAtMs || Date.now() < state.liveBackfillReadyAtMs) return; const session = sessionById("ses_317f78e1-ed91-4b09-a72a-3668d5469f59"); if (session?.status === "completed") return; commitProjectorResumeProjection(); } function projectorResumeSession(): SessionRecord { const now = new Date().toISOString(); const trace = projectorResumeEarlyTrace(); return { sessionId: "ses_317f78e1-ed91-4b09-a72a-3668d5469f59", threadId: "thr_projector_resume_1596", status: "running", lastTraceId: "trc_f2456023233a485b", startedAt: now, updatedAt: now, messageCount: 2, firstUserMessagePreview: "issue 1596 durable projector resume sample", turnSummary: { traceId: "trc_f2456023233a485b", status: "running", running: true, terminal: false, ...projectorResumeProjection("projecting", 4) }, messages: [ { id: "msg_projector_resume_user", messageId: "msg_projector_resume_user", role: "user", title: "用户", text: "issue 1596 durable projector resume sample", status: "sent", createdAt: now, sessionId: "ses_317f78e1-ed91-4b09-a72a-3668d5469f59", threadId: "thr_projector_resume_1596", traceId: "trc_f2456023233a485b", turnId: "turn_projector_resume_1596" }, { id: "msg_projector_resume_agent", messageId: "msg_projector_resume_agent", role: "agent", title: "Code Agent", text: "", status: "running", createdAt: now, sessionId: "ses_317f78e1-ed91-4b09-a72a-3668d5469f59", threadId: "thr_projector_resume_1596", traceId: "trc_f2456023233a485b", turnId: "turn_projector_resume_1596", runnerTrace: trace, ...projectorResumeProjection("projecting", 4) } ] }; } function projectorResumeEarlyTrace(): JsonRecord { const createdAt = new Date().toISOString(); const projection = projectorResumeProjection("projecting", 4); const events = [ { seq: 1, sourceSeq: 1, createdAt, label: "agentrun:request:accepted", type: "backend_status", status: "running", payload: { commandId: "cmd_d4d20aa2bb2c4d19a91143ce87d73704" } }, { seq: 2, sourceSeq: 2, createdAt, label: "agentrun:run:created", type: "backend_status", status: "running", payload: { runId: "run_58ef1811071548539f881515912560d8", runStatus: "claimed" } }, { seq: 3, sourceSeq: 3, createdAt, label: "agentrun:command:created", type: "backend_status", status: "running", payload: { commandId: "cmd_d4d20aa2bb2c4d19a91143ce87d73704", commandState: "running" } }, { seq: 4, sourceSeq: 4, createdAt, label: "agentrun:runner-job:created", type: "backend_status", status: "running", payload: { commandId: "cmd_d4d20aa2bb2c4d19a91143ce87d73704", namespace: "agentrun-v01" } } ]; return { traceId: "trc_f2456023233a485b", status: "running", running: true, terminal: false, sessionId: "ses_317f78e1-ed91-4b09-a72a-3668d5469f59", threadId: "thr_projector_resume_1596", turnId: "turn_projector_resume_1596", events, eventCount: events.length, fullTraceLoaded: true, hasMore: false, ...projection }; } function projectorResumeCompletedTrace(): JsonRecord { const createdAt = new Date().toISOString(); const finalText = "fake projector resume completed from durable checkpoint."; const projection = projectorResumeProjection("caught-up", 7); const events = [ ...(projectorResumeEarlyTrace().events as JsonRecord[]), { seq: 5, sourceSeq: 2748, createdAt, label: "agentrun:assistant:message", type: "assistant_message", status: "completed", message: finalText, payload: { commandId: "cmd_d4d20aa2bb2c4d19a91143ce87d73704" } }, { seq: 6, sourceSeq: 2749, createdAt, label: "item/commandExecution:completed", type: "commandExecution", status: "completed", stdout: "OK\n", payload: { commandId: "cmd_d4d20aa2bb2c4d19a91143ce87d73704", exitCode: 0 } }, { seq: 7, sourceSeq: 2750, createdAt, label: "agentrun:backend:turn/completed", type: "backend_status", status: "completed", terminal: true, payload: { commandId: "cmd_d4d20aa2bb2c4d19a91143ce87d73704", terminalStatus: "completed" } } ]; return { traceId: "trc_f2456023233a485b", status: "completed", running: false, terminal: true, sessionId: "ses_317f78e1-ed91-4b09-a72a-3668d5469f59", threadId: "thr_projector_resume_1596", turnId: "turn_projector_resume_1596", events, eventCount: events.length, fullTraceLoaded: true, hasMore: false, finalResponse: { text: finalText, status: "completed" }, traceSummary: { source: "durable-projector-resume", terminalStatus: "completed", valuesPrinted: false }, ...projection }; } function projectorResumeProjection(status: "projecting" | "caught-up", lastProjectedSeq: number): JsonRecord { const caughtUp = status === "caught-up"; const projection = { projectionStatus: status, projectionHealth: status, lastProjectedSeq, sourceLatestSeq: 2750, sourceRunId: "run_58ef1811071548539f881515912560d8", sourceCommandId: "cmd_d4d20aa2bb2c4d19a91143ce87d73704", staleMs: caughtUp ? 0 : 90_000, blocker: caughtUp ? null : { code: "projector_resume_pending", layer: "workbench-projector", retryable: true, message: "后台投影恢复中,已从 checkpoint 记录 lastProjectedSeq=4。", valuesPrinted: false }, valuesRedacted: true }; return { projection, ...projection }; } function commitProjectorResumeProjection(): void { const completed = projectorResumeCompletedTrace(); state.traces.trc_f2456023233a485b = completed; const session = sessionById("ses_317f78e1-ed91-4b09-a72a-3668d5469f59"); if (!session) return; session.status = "completed"; session.updatedAt = new Date().toISOString(); session.turnSummary = { traceId: "trc_f2456023233a485b", status: "completed", running: false, terminal: true, ...projectorResumeProjection("caught-up", 7) }; session.messages = (session.messages ?? []).map((message) => { if (message.role !== "agent" || message.traceId !== "trc_f2456023233a485b") return message; return { ...message, text: "fake projector resume completed from durable checkpoint.", status: "completed", runnerTrace: completed, ...projectorResumeProjection("caught-up", 7) }; }); const terminalEvent = (completed.events as JsonRecord[]).at(-1) ?? null; if (terminalEvent) broadcastSse("workbench.trace.event", { type: "trace.event", sessionId: session.sessionId, threadId: session.threadId ?? null, traceId: "trc_f2456023233a485b", event: terminalEvent, snapshot: completed }); broadcastSse("workbench.turn.snapshot", { type: "turn.snapshot", sessionId: session.sessionId, threadId: session.threadId ?? null, traceId: "trc_f2456023233a485b", turn: turnPayload("trc_f2456023233a485b") }); } function markSessionText(sessions: SessionRecord[], sessionId: string, userText: string, agentText: string): void { const session = sessions.find((item) => item.sessionId === sessionId); if (!session) return; session.firstUserMessagePreview = userText; session.messages = (session.messages ?? []).map((message) => { if (message.role === "user") return { ...message, text: userText }; if (message.role === "agent") return { ...message, text: agentText }; return message; }); } function markRunningProgressOnly(sessions: SessionRecord[], traces: Record): void { const createdAt = new Date().toISOString(); const progressEvent = { seq: 1, createdAt, label: "agentrun:assistant:message", type: "assistant_message", status: "running", replyAuthority: false, final: false, message: progressOnlyText }; const trace = { traceId: "trc_running", status: "running", sessionId: "ses_running", threadId: "thr_running", turnId: "turn_running", events: [progressEvent], eventCount: 1, fullTraceLoaded: false, hasMore: false }; traces.trc_running = trace; const session = sessions.find((item) => item.sessionId === "ses_running"); if (!session) return; session.status = "running"; session.lastTraceId = "trc_running"; session.firstUserMessagePreview = "progress-only running turn"; session.messages = (session.messages ?? []).map((message) => { if (message.role === "user") return { ...message, text: "progress-only running turn" }; if (message.role !== "agent" || message.traceId !== "trc_running") return message; return { ...message, text: "", status: "running", runnerTrace: trace }; }); } function markRunningNoFinalResponse(sessions: SessionRecord[], traces: Record): void { const trace = noFinalRunningTrace(); traces.trc_running = trace; const session = sessions.find((item) => item.sessionId === "ses_running"); if (!session) return; session.status = "running"; session.lastTraceId = "trc_running"; session.firstUserMessagePreview = "completed turn without final response"; session.messages = (session.messages ?? []).map((message) => { if (message.role === "user") return { ...message, text: "completed turn without final response" }; if (message.role !== "agent" || message.traceId !== "trc_running") return message; return { ...message, text: "", status: "running", runnerTrace: trace }; }); } function markTerminalCanceledLateTiming(sessions: SessionRecord[], traces: Record): void { const trace = terminalCanceledLateTimingRunningTrace(); traces.trc_running = trace; const session = sessions.find((item) => item.sessionId === "ses_running"); if (!session) return; session.status = "running"; session.lastTraceId = "trc_running"; session.firstUserMessagePreview = "terminal canceled timing should stay sealed"; session.messages = (session.messages ?? []).map((message) => { if (message.role === "user") return { ...message, text: "terminal canceled timing should stay sealed" }; if (message.role !== "agent" || message.traceId !== "trc_running") return message; return { ...message, text: "", status: "running", timing: trace.timing, startedAt: trace.startedAt, lastEventAt: trace.lastEventAt, finishedAt: null, durationMs: null, runnerTrace: trace }; }); } function terminalCanceledLateTimingRunningTrace(): JsonRecord { const startedAt = "2026-06-17T09:39:00.000Z"; const lastEventAt = "2026-06-17T09:39:04.000Z"; const timing = { startedAt, lastEventAt, finishedAt: null, durationMs: null, valuesRedacted: true }; return { traceId: "trc_running", status: "running", sessionId: "ses_running", threadId: "thr_running", turnId: "turn_running", timing, startedAt, lastEventAt, finishedAt: null, durationMs: null, events: [{ seq: 1, createdAt: lastEventAt, label: "agentrun:backend:turn/running", type: "backend_status", status: "running" }], eventCount: 1, fullTraceLoaded: false, hasMore: false }; } function applyTerminalCanceledLateTiming(durationMs: number, finishedAt: string): JsonRecord | null { const startedAt = "2026-06-17T09:39:00.000Z"; const timing = { startedAt, lastEventAt: finishedAt, finishedAt, durationMs, valuesRedacted: true }; const event = { seq: 2, createdAt: finishedAt, label: "agentrun:terminal:canceled", type: "backend_status", status: "canceled", terminal: true }; const trace = { traceId: "trc_running", status: "canceled", sessionId: "ses_running", threadId: "thr_running", turnId: "turn_running", timing, startedAt, lastEventAt: finishedAt, finishedAt, durationMs, events: [event], eventCount: 2, fullTraceLoaded: true, hasMore: false, finalResponse: { text: "hwlab-user-cancel", status: "canceled" } }; state.traces.trc_running = trace; const session = sessionById("ses_running"); if (!session) return null; session.status = "canceled"; session.updatedAt = finishedAt; session.messages = (session.messages ?? []).map((message) => message.role === "agent" && message.traceId === "trc_running" ? { ...message, text: "hwlab-user-cancel", status: "canceled", timing, startedAt, lastEventAt: finishedAt, finishedAt, durationMs, runnerTrace: trace } : message); return trace; } function markToolCompletedProjectionRunning(sessions: SessionRecord[], traces: Record): void { const trace = toolCompletedProjectionRunningTrace(); traces.trc_running = trace; const session = sessions.find((item) => item.sessionId === "ses_running"); if (!session) return; session.status = "running"; session.lastTraceId = "trc_running"; session.firstUserMessagePreview = "tool completed but turn still running"; session.messages = (session.messages ?? []).map((message) => { if (message.role === "user") return { ...message, text: "tool completed but turn still running" }; if (message.role !== "agent" || message.traceId !== "trc_running") return message; return { ...message, text: "", status: "running", runnerTrace: trace }; }); } function toolCompletedProjectionRunningTrace(): JsonRecord { const createdAt = new Date().toISOString(); const events = [ { seq: 1, createdAt, label: "agentrun:assistant:message", type: "assistant_message", status: "running", terminal: false, message: "正在安装 Python。" }, { seq: 2, createdAt, label: "item/commandExecution:completed", type: "commandExecution", status: "completed", terminal: false, command: "ls -ld .", stdout: "OK\n" } ]; return { traceId: "trc_running", status: "completed", turnStatus: "running", projectionStatus: "projecting", sessionId: "ses_running", threadId: "thr_running", turnId: "turn_running", events, eventCount: events.length, fullTraceLoaded: true, hasMore: false, finalResponse: null, assistantText: null }; } function projectionDiagnostic(input: { code: string; message: string; health?: string; category?: string; layer?: string; traceId: string; runId?: string; commandId?: string; staleMs?: number }): JsonRecord { const diagnostic = { contractVersion: "hwlab-error-diagnostic-v1", traceId: input.traceId, requestId: `req_e2e_${input.code}`, route: "/v1/workbench/events", layer: input.layer ?? "agentrun", category: input.category ?? "upstream-timeout", code: input.code, httpStatus: 0, source: "server", observedAt: new Date().toISOString(), retryable: true, valuesPrinted: false }; return { projectionStatus: "projecting", projectionHealth: input.health ?? "degraded", lastProjectedSeq: 137, sourceRunId: input.runId ?? "run_projection_diag", sourceCommandId: input.commandId ?? "cmd_projection_diag", staleMs: input.staleMs ?? 12_345, blocker: { code: input.code, layer: input.layer ?? "agentrun", category: input.category ?? "upstream-timeout", message: input.message, retryable: true, timeoutMs: 2500, runId: input.runId ?? "run_projection_diag", commandId: input.commandId ?? "cmd_projection_diag", traceId: diagnostic.traceId, requestId: diagnostic.requestId, route: diagnostic.route, source: diagnostic.source, httpStatus: diagnostic.httpStatus, diagnostic, valuesPrinted: false }, diagnostic, valuesRedacted: true }; } function projectionDegradedTrace(): JsonRecord { const projection = projectionDiagnostic({ traceId: "trc_projection_degraded", code: "agentrun_result_timeout", message: "状态更新超时,最近投影 seq=137,AgentRun 结果暂不可见。" }); return { traceId: "trc_projection_degraded", status: "running", sessionId: "ses_projection_degraded", threadId: "thr_projection_degraded", turnId: "turn_projection_degraded", events: [], eventCount: 0, fullTraceLoaded: true, hasMore: false, projection, ...projection }; } function projectionDegradedSession(): SessionRecord { const now = new Date().toISOString(); const projection = projectionDiagnostic({ traceId: "trc_projection_degraded", code: "agentrun_result_timeout", message: "状态更新超时,最近投影 seq=137,AgentRun 结果暂不可见。" }); return { sessionId: "ses_projection_degraded", threadId: "thr_projection_degraded", status: "running", lastTraceId: "trc_projection_degraded", updatedAt: now, messageCount: 2, firstUserMessagePreview: "projection degraded visibility", turnSummary: { traceId: "trc_projection_degraded", status: "running", running: true, terminal: false, ...projection }, messages: [ { id: "msg_projection_degraded_user", messageId: "msg_projection_degraded_user", role: "user", title: "用户", text: "projection degraded visibility", status: "sent", createdAt: now, sessionId: "ses_projection_degraded", threadId: "thr_projection_degraded", turnId: "turn_projection_degraded" }, { id: "msg_projection_degraded_agent", messageId: "msg_projection_degraded_agent", role: "agent", title: "Code Agent", text: "", status: "running", createdAt: now, sessionId: "ses_projection_degraded", threadId: "thr_projection_degraded", traceId: "trc_projection_degraded", turnId: "turn_projection_degraded", projection, runnerTrace: projectionDegradedTrace() } ] }; } function projectionSseErrorTrace(): JsonRecord { return { traceId: "trc_projection_sse_error", status: "running", sessionId: "ses_projection_sse_error", threadId: "thr_projection_sse_error", turnId: "turn_projection_sse_error", events: [], eventCount: 0, fullTraceLoaded: false, hasMore: false }; } function projectionSseErrorSession(): SessionRecord { const now = new Date().toISOString(); return { sessionId: "ses_projection_sse_error", threadId: "thr_projection_sse_error", status: "running", lastTraceId: "trc_projection_sse_error", updatedAt: now, messageCount: 2, firstUserMessagePreview: "projection SSE error visibility", messages: [ { id: "msg_projection_sse_error_user", messageId: "msg_projection_sse_error_user", role: "user", title: "用户", text: "projection SSE error visibility", status: "sent", createdAt: now, sessionId: "ses_projection_sse_error", threadId: "thr_projection_sse_error", turnId: "turn_projection_sse_error" }, { id: "msg_projection_sse_error_agent", messageId: "msg_projection_sse_error_agent", role: "agent", title: "Code Agent", text: "", status: "running", createdAt: now, sessionId: "ses_projection_sse_error", threadId: "thr_projection_sse_error", traceId: "trc_projection_sse_error", turnId: "turn_projection_sse_error", runnerTrace: projectionSseErrorTrace() } ] }; } function traceHydrationTimeoutTrace(): JsonRecord { return { traceId: "trc_trace_hydration_timeout", status: "running", sessionId: "ses_trace_hydration_timeout", threadId: "thr_trace_hydration_timeout", turnId: "turn_trace_hydration_timeout", events: [], eventCount: 0, fullTraceLoaded: false, hasMore: true }; } function traceHydrationTimeoutSession(): SessionRecord { const now = new Date().toISOString(); return { sessionId: "ses_trace_hydration_timeout", threadId: "thr_trace_hydration_timeout", status: "running", lastTraceId: "trc_trace_hydration_timeout", updatedAt: now, messageCount: 2, firstUserMessagePreview: "trace hydration timeout visibility", messages: [ { id: "msg_trace_hydration_timeout_user", messageId: "msg_trace_hydration_timeout_user", role: "user", title: "用户", text: "trace hydration timeout visibility", status: "sent", createdAt: now, sessionId: "ses_trace_hydration_timeout", threadId: "thr_trace_hydration_timeout", turnId: "turn_trace_hydration_timeout" }, { id: "msg_trace_hydration_timeout_agent", messageId: "msg_trace_hydration_timeout_agent", role: "agent", title: "Code Agent", text: "", status: "running", createdAt: now, sessionId: "ses_trace_hydration_timeout", threadId: "thr_trace_hydration_timeout", traceId: "trc_trace_hydration_timeout", turnId: "turn_trace_hydration_timeout", runnerTrace: traceHydrationTimeoutTrace() } ] }; } function sealedFinalResponseDiagnosticTrace(): JsonRecord { const now = new Date().toISOString(); const finalText = "已完成的 sealed final response 不应被诊断覆盖。"; return { traceId: "trc_sealed_final_diag", status: "completed", sessionId: "ses_sealed_final_diag", threadId: "thr_sealed_final_diag", turnId: "turn_sealed_final_diag", events: [], eventCount: 1, fullTraceLoaded: false, hasMore: true, finalResponse: { text: finalText, status: "completed" }, terminalEvidence: { terminal: true, status: "completed" }, sealedAt: now }; } function sealedFinalResponseDiagnosticSession(): SessionRecord { const now = new Date().toISOString(); const finalText = "已完成的 sealed final response 不应被诊断覆盖。"; const trace = sealedFinalResponseDiagnosticTrace(); return { sessionId: "ses_sealed_final_diag", threadId: "thr_sealed_final_diag", status: "completed", lastTraceId: "trc_sealed_final_diag", updatedAt: now, messageCount: 2, firstUserMessagePreview: "sealed final response diagnostic separation", turnSummary: { traceId: "trc_sealed_final_diag", status: "completed", running: false, terminal: true, sealedAt: now }, messages: [ { id: "msg_sealed_final_user", messageId: "msg_sealed_final_user", role: "user", title: "用户", text: "sealed final response diagnostic separation", status: "sent", createdAt: now, sessionId: "ses_sealed_final_diag", threadId: "thr_sealed_final_diag", turnId: "turn_sealed_final_diag" }, { id: "msg_sealed_final_agent", messageId: "msg_sealed_final_agent", role: "agent", title: "Code Agent", text: finalText, status: "completed", createdAt: now, updatedAt: now, sessionId: "ses_sealed_final_diag", threadId: "thr_sealed_final_diag", traceId: "trc_sealed_final_diag", turnId: "turn_sealed_final_diag", sealedAt: now, runnerTrace: trace, finalResponse: { text: finalText, status: "completed" } } ] }; } function traceFinalResponseConflictTrace(): JsonRecord { const now = new Date().toISOString(); const event = { seq: 1, sourceSeq: 91, createdAt: now, label: "agentrun:assistant:message", type: "assistant_message", status: "completed", terminal: true, final: true, replyAuthority: true, message: traceDetailConflictText }; return { traceId: "trc_trace_final_conflict", status: "completed", sessionId: "ses_trace_final_conflict", threadId: "thr_trace_final_conflict", turnId: "turn_trace_final_conflict", events: [event], eventCount: 1, fullTraceLoaded: true, hasMore: false, finalResponse: { text: traceDetailConflictText, status: "completed" }, terminalEvidence: { terminal: true, status: "completed" }, sealedAt: now }; } function traceFinalResponseConflictSession(): SessionRecord { const now = new Date().toISOString(); return { sessionId: "ses_trace_final_conflict", threadId: "thr_trace_final_conflict", status: "completed", lastTraceId: "trc_trace_final_conflict", updatedAt: now, messageCount: 2, firstUserMessagePreview: "trace final response authority separation", turnSummary: { traceId: "trc_trace_final_conflict", status: "completed", running: false, terminal: true, sealedAt: now }, messages: [ { id: "msg_trace_final_conflict_user", messageId: "msg_trace_final_conflict_user", role: "user", title: "用户", text: "trace final response authority separation", status: "sent", createdAt: now, sessionId: "ses_trace_final_conflict", threadId: "thr_trace_final_conflict", turnId: "turn_trace_final_conflict" }, { id: "msg_trace_final_conflict_agent", messageId: "msg_trace_final_conflict_agent", role: "agent", title: "Code Agent", text: canonicalTraceFinalText, status: "completed", createdAt: now, updatedAt: now, sessionId: "ses_trace_final_conflict", threadId: "thr_trace_final_conflict", traceId: "trc_trace_final_conflict", turnId: "turn_trace_final_conflict", sealedAt: now, finalResponse: { text: canonicalTraceFinalText, status: "completed" }, runnerTrace: { traceId: "trc_trace_final_conflict", status: "completed", sessionId: "ses_trace_final_conflict", threadId: "thr_trace_final_conflict", events: [], eventCount: 1, fullTraceLoaded: false, hasMore: true } } ] }; } function noFinalRunningTrace(): JsonRecord { const createdAt = new Date().toISOString(); return { traceId: "trc_running", status: "running", sessionId: "ses_running", threadId: "thr_running", turnId: "turn_running", events: [{ seq: 1, createdAt, label: "agentrun:backend:turn/running", type: "backend_status", status: "running" }], eventCount: 1, fullTraceLoaded: false, hasMore: false }; } function completedNoFinalTrace(): JsonRecord { const createdAt = new Date().toISOString(); const events = [ { seq: 1, createdAt, label: "agentrun:backend:turn/running", type: "backend_status", status: "running" }, { seq: 2, createdAt, label: "agentrun:backend:turn/completed", type: "backend_status", status: "completed", terminal: true } ]; return { traceId: "trc_running", status: "completed", sessionId: "ses_running", threadId: "thr_running", turnId: "turn_running", events, eventCount: events.length, fullTraceLoaded: true, hasMore: false }; } function scrollFollowSession(): SessionRecord { const now = new Date().toISOString(); const trace = scrollFollowTrace(90); const history = Array.from({ length: 18 }, (_, index) => { const seq = index + 1; return seq % 2 === 0 ? { id: `msg_scroll_history_agent_${seq}`, messageId: `msg_scroll_history_agent_${seq}`, role: "agent", title: "Code Agent", text: `历史回复 ${seq}\n\n用于撑开主工作区滚动高度。`, status: "completed", createdAt: now, sessionId: "ses_scroll_follow", threadId: "thr_scroll_follow", turnId: `turn_scroll_history_${seq}` } : { id: `msg_scroll_history_user_${seq}`, messageId: `msg_scroll_history_user_${seq}`, role: "user", title: "用户", text: `历史问题 ${seq}:保持主工作区可滚动。`, status: "sent", createdAt: now, sessionId: "ses_scroll_follow", threadId: "thr_scroll_follow", turnId: `turn_scroll_history_${seq}` }; }); const messages = [ ...history, { id: "msg_scroll_follow_user", messageId: "msg_scroll_follow_user", role: "user", title: "用户", text: "scroll follow long trace probe", status: "sent", createdAt: now, sessionId: "ses_scroll_follow", threadId: "thr_scroll_follow", traceId: "trc_scroll_follow", turnId: "turn_scroll_follow" }, { id: "msg_scroll_follow_agent", messageId: "msg_scroll_follow_agent", role: "agent", title: "Code Agent", text: "", status: "running", createdAt: now, sessionId: "ses_scroll_follow", threadId: "thr_scroll_follow", traceId: "trc_scroll_follow", turnId: "turn_scroll_follow", runnerTrace: trace } ]; return { sessionId: "ses_scroll_follow", threadId: "thr_scroll_follow", status: "running", lastTraceId: "trc_scroll_follow", startedAt: now, updatedAt: now, messageCount: messages.length, firstUserMessagePreview: "scroll follow long trace probe", messages }; } function scrollFollowTrace(count: number): JsonRecord { const events = Array.from({ length: count }, (_, index) => scrollFollowEvent(index + 1)); return { traceId: "trc_scroll_follow", status: "running", sessionId: "ses_scroll_follow", threadId: "thr_scroll_follow", turnId: "turn_scroll_follow", events, eventCount: events.length, fullTraceLoaded: true, hasMore: false }; } function scrollFollowEvent(seq: number): JsonRecord { const createdAt = new Date(Date.parse("2026-06-18T18:00:00.000Z") + seq * 1000).toISOString(); if (seq % 5 === 0) { return { seq, sourceSeq: seq, createdAt, label: "agentrun:assistant:message", type: "assistant_message", status: "running", message: `滚动跟随采样 assistant row ${seq}\n\n- markdown 行 ${seq}\n- append 后不能闪到顶部` }; } return { seq, sourceSeq: seq, createdAt, label: "item/commandExecution:running", type: "commandExecution", status: "running", itemId: `scroll-follow-${seq}`, command: `printf 'scroll follow row ${seq}\\n'`, stdout: `scroll-follow stdout ${seq}\nline ${seq} keeps the row tall enough for scroll sampling\n` }; } function appendScrollFollowEvents(count: number): JsonRecord { if (state.scenarioId !== "scroll-follow-long-trace") return { ok: false, status: 409, error: { code: "scenario_mismatch", scenarioId: state.scenarioId } }; const trace = state.traces.trc_scroll_follow ?? scrollFollowTrace(0); const events = Array.isArray(trace.events) ? [...trace.events as JsonRecord[]] : []; const appended: JsonRecord[] = []; for (let index = 0; index < count; index += 1) { const seq = Number(events.at(-1)?.seq ?? events.length) + 1; const event = scrollFollowEvent(seq); events.push(event); appended.push(event); } const nextTrace = { ...trace, status: "running", events, eventCount: events.length, fullTraceLoaded: true, hasMore: false }; state.traces.trc_scroll_follow = nextTrace; const session = sessionById("ses_scroll_follow"); if (session) { session.status = "running"; session.updatedAt = new Date().toISOString(); session.messages = (session.messages ?? []).map((message) => message.role === "agent" && message.traceId === "trc_scroll_follow" ? { ...message, status: "running", runnerTrace: nextTrace } : message); } for (const event of appended) { broadcastSse("workbench.trace.event", { type: "trace.event", sessionId: "ses_scroll_follow", threadId: "thr_scroll_follow", traceId: "trc_scroll_follow", event, snapshot: nextTrace }); } broadcastSse("workbench.turn.snapshot", { type: "turn.snapshot", sessionId: "ses_scroll_follow", threadId: "thr_scroll_follow", traceId: "trc_scroll_follow", turn: turnPayload("trc_scroll_follow") }); return { ok: true, status: "appended", appended: appended.length, eventCount: events.length }; } function createManualSession(body: JsonRecord): SessionRecord { const now = new Date().toISOString(); const token = state.scenarioId === "server-authoritative-create" ? "server_created" : state.scenarioId === "create-while-route-loading" ? "created_while_running" : state.scenarioId === "created-session-read-failure" ? "created_read_failure" : Date.now().toString(36); const sessionId = typeof body.sessionId === "string" && body.sessionId.trim() ? body.sessionId : `ses_${token}`; const threadId = typeof body.threadId === "string" && body.threadId.trim() ? body.threadId : null; return { sessionId, threadId, status: "active", startedAt: now, updatedAt: now, messageCount: 0, firstUserMessagePreview: null, messages: [] }; } function hiddenBoundarySession(): SessionRecord { const now = new Date().toISOString(); return { sessionId: "ses_cross_project", threadId: "thr_cross_project", hidden: true, status: "completed", lastTraceId: "trc_cross_project", startedAt: now, updatedAt: now, messageCount: 2, firstUserMessagePreview: "边界外 session 不应泄露", messages: [] }; } function terminalEmptyTraceSession(): SessionRecord { const now = new Date().toISOString(); return { sessionId: "ses_terminal_empty", threadId: "thr_terminal_empty", status: "completed", lastTraceId: "trc_terminal_empty", startedAt: now, updatedAt: now, messageCount: 2, firstUserMessagePreview: "完成态空 Trace 文案验证", messages: [ { id: "msg_terminal_empty_user", role: "user", title: "用户", text: "完成态空 Trace 文案验证", status: "sent", createdAt: now, sessionId: "ses_terminal_empty", threadId: "thr_terminal_empty", turnId: "turn_terminal_empty" }, { id: "msg_terminal_empty_agent", role: "agent", title: "Code Agent", text: "终态空 Trace 已完成。", status: "completed", createdAt: now, sessionId: "ses_terminal_empty", threadId: "thr_terminal_empty", traceId: "trc_terminal_empty", turnId: "turn_terminal_empty", runnerTrace: terminalEmptyTrace() } ] }; } function terminalEmptyTrace(): JsonRecord { return { traceId: "trc_terminal_empty", status: "completed", sessionId: "ses_terminal_empty", threadId: "thr_terminal_empty", events: [], eventCount: 0, fullTraceLoaded: true, hasMore: false, finalResponse: { text: "终态空 Trace 已完成。" } }; } function legacyCanonicalSession(): SessionRecord { const now = new Date().toISOString(); return { sessionId: "ses_c5e1330558c94d8e", conversationId: "cnv_c5e1330558c94d8e", threadId: "thr_c5e1330558c94d8e", status: "completed", lastTraceId: "trc_40badc15523146c9", startedAt: now, updatedAt: now, messageCount: 2, firstUserMessagePreview: "legacy cnv deep link canonical smoke", messages: [ { id: "msg_c5_user", role: "user", title: "用户", text: "legacy cnv deep link canonical smoke", status: "sent", createdAt: now, sessionId: "ses_c5e1330558c94d8e", threadId: "thr_c5e1330558c94d8e", traceId: "trc_40badc15523146c9" }, { id: "msg_c5_agent", role: "agent", title: "Code Agent", text: "已完成:新增 Python benchmark 脚本。", status: "completed", createdAt: now, sessionId: "ses_c5e1330558c94d8e", threadId: "thr_c5e1330558c94d8e", traceId: "trc_40badc15523146c9", runnerTrace: legacyCanonicalTrace() } ] }; } function legacyCanonicalTrace(): JsonRecord { return { traceId: "trc_40badc15523146c9", status: "completed", sessionId: "ses_c5e1330558c94d8e", threadId: "thr_c5e1330558c94d8e", events: [{ seq: 1, label: "agentrun:assistant:message", type: "assistant_message", status: "completed", terminal: true, final: true, message: "已完成:新增 Python benchmark 脚本。" }], eventCount: 1, fullTraceLoaded: true, hasMore: false, finalResponse: { text: "已完成:新增 Python benchmark 脚本。", status: "completed" } }; } function markdownFinalSession(): SessionRecord { const now = new Date().toISOString(); return { sessionId: "ses_markdown_final", conversationId: "cnv_markdown_final", threadId: "thr_markdown_final", status: "completed", lastTraceId: "trc_markdown_final", startedAt: now, updatedAt: now, messageCount: 2, firstUserMessagePreview: "render markdown final response", messages: [ { id: "msg_markdown_user", messageId: "msg_markdown_user", role: "user", title: "用户", text: "render markdown final response", status: "sent", createdAt: now, sessionId: "ses_markdown_final", threadId: "thr_markdown_final", traceId: "trc_markdown_final", turnId: "trc_markdown_final" }, { id: "msg_markdown_agent", messageId: "msg_markdown_agent", role: "agent", title: "Code Agent", text: markdownFinalText, parts: [{ type: "text", text: markdownFinalText }], status: "completed", createdAt: now, updatedAt: now, sessionId: "ses_markdown_final", threadId: "thr_markdown_final", traceId: "trc_markdown_final", turnId: "trc_markdown_final", runnerTrace: markdownFinalTrace() } ] }; } function markdownFinalTrace(): JsonRecord { const createdAt = new Date().toISOString(); const event = { seq: 1, sourceSeq: 88, createdAt, label: "agentrun:assistant:message", type: "assistant_message", status: "completed", terminal: true, final: true, replyAuthority: true, message: markdownFinalText }; return { traceId: "trc_markdown_final", status: "completed", sessionId: "ses_markdown_final", threadId: "thr_markdown_final", events: [event], eventCount: 1, fullTraceLoaded: true, hasMore: false, finalResponse: { text: markdownFinalText, status: "completed" } }; } function terminalAssistantFinalSession(): SessionRecord { const now = new Date().toISOString(); const trace = terminalAssistantFinalTrace(); return { sessionId: "ses_terminal_assistant_final", conversationId: "cnv_terminal_assistant_final", threadId: "thr_terminal_assistant_final", status: "completed", lastTraceId: "trc_terminal_assistant_final", startedAt: now, updatedAt: now, messageCount: 2, firstUserMessagePreview: "再把lua加入对比测试", messages: [ { id: "msg_terminal_assistant_user", messageId: "msg_terminal_assistant_user", role: "user", title: "用户", text: "再把lua加入对比测试", status: "sent", createdAt: now, sessionId: "ses_terminal_assistant_final", threadId: "thr_terminal_assistant_final", traceId: "trc_terminal_assistant_final", turnId: "trc_terminal_assistant_final" }, { id: "msg_terminal_assistant_agent", messageId: "msg_terminal_assistant_agent", role: "agent", title: "Code Agent", text: terminalAssistantFinalText, parts: [{ type: "text", text: terminalAssistantFinalText, status: "completed" }], status: "completed", createdAt: now, updatedAt: now, sessionId: "ses_terminal_assistant_final", threadId: "thr_terminal_assistant_final", traceId: "trc_terminal_assistant_final", turnId: "trc_terminal_assistant_final", runnerTrace: trace, finalResponse: { text: terminalAssistantFinalText, status: "completed" } } ] }; } function terminalAssistantFinalTrace(): JsonRecord { const createdAt = new Date().toISOString(); const events = [ { seq: 1, sourceSeq: 21, createdAt, label: "agentrun:assistant:message", type: "assistant_message", status: "running", replyAuthority: false, final: false, terminal: false, message: "现在写 Lua 基准测试脚本。" }, { seq: 2, sourceSeq: 28, createdAt, label: "agentrun:assistant:message", type: "assistant_message", status: "completed", replyAuthority: true, final: true, terminal: true, message: terminalAssistantFinalText }, { seq: 3, sourceSeq: 29, createdAt, label: "agentrun:terminal:completed", type: "result", status: "completed", terminal: true, message: "AgentRun command completed." } ]; return { traceId: "trc_terminal_assistant_final", status: "completed", sessionId: "ses_terminal_assistant_final", threadId: "thr_terminal_assistant_final", events, eventCount: events.length, fullTraceLoaded: true, hasMore: false, assistantText: terminalAssistantFinalText, finalResponse: { text: terminalAssistantFinalText, status: "completed" } }; } function manyRailSession(index: number): SessionRecord { const id = String(index).padStart(2, "0"); const now = new Date(Date.now() - (index + 1) * 1000).toISOString(); return { sessionId: `ses_many_${id}`, threadId: `thr_many_${id}`, status: "completed", lastTraceId: `trc_many_${id}`, startedAt: now, updatedAt: now, messageCount: 0, firstUserMessagePreview: `历史 session ${id}`, messages: [] }; } function staleDetailSession(): SessionRecord { const now = new Date().toISOString(); return { sessionId: "ses_stale_404", threadId: "thr_stale_404", status: "active", startedAt: now, updatedAt: now, messageCount: 0, firstUserMessagePreview: "已失效的列表项", messages: [] }; } function emptySession(): SessionRecord { const now = new Date().toISOString(); return { sessionId: "ses_empty", threadId: "thr_empty", status: "active", startedAt: now, updatedAt: now, messageCount: 0, firstUserMessagePreview: "空白会话", messages: [] }; } function staleEmptyTtlSession(): SessionRecord { const at = "2026-06-18T16:00:00.000Z"; return { sessionId: "ses_empty_ttl", threadId: "thr_empty_ttl", status: "idle", startedAt: at, updatedAt: at, messageCount: 0, firstUserMessagePreview: null, messages: [] }; } function freshEmptyTtlSession(): SessionRecord { const at = "2026-06-18T16:15:30.000Z"; return { sessionId: "ses_empty_fresh", threadId: "thr_empty_fresh", status: "idle", startedAt: at, updatedAt: at, messageCount: 0, firstUserMessagePreview: null, messages: [] }; } function staleMessagedTtlSession(): SessionRecord { const at = "2026-06-18T15:50:00.000Z"; return { sessionId: "ses_empty_ttl_has_message", threadId: "thr_empty_ttl_has_message", status: "completed", startedAt: at, updatedAt: at, messageCount: 2, firstUserMessagePreview: "超过 TTL 但已有消息,不能被 GC", messages: [ { id: "msg_empty_ttl_user", role: "user", title: "用户", text: "超过 TTL 但已有消息,不能被 GC", status: "sent", createdAt: at, sessionId: "ses_empty_ttl_has_message", threadId: "thr_empty_ttl_has_message" }, { id: "msg_empty_ttl_agent", role: "agent", title: "Code Agent", text: "保留已有消息 session。", status: "completed", createdAt: at, sessionId: "ses_empty_ttl_has_message", threadId: "thr_empty_ttl_has_message" } ] }; } function archivedDeletedSession(): SessionRecord { const now = new Date().toISOString(); return { sessionId: "ses_deleted", threadId: "thr_deleted", status: "archived", startedAt: now, updatedAt: now, messageCount: 0, firstUserMessagePreview: "已删除 session", messages: [] }; } function submitSplitSession(): SessionRecord { const now = new Date().toISOString(); return { sessionId: "ses_submit_split", threadId: "thr_submit_split", status: "idle", lastTraceId: "trc_submit_split", startedAt: now, updatedAt: now, messageCount: 2, firstUserMessagePreview: "workbench submit race probe redacted: 请只回复 OK。", messages: [ { id: "msg_submit_split_user", messageId: "msg_submit_split_user", role: "user", title: "用户", text: "", status: "sent", createdAt: now, sessionId: "ses_submit_split", threadId: "thr_submit_split", traceId: "trc_submit_split", turnId: "turn_submit_split" }, { id: "msg_submit_split_agent", messageId: "msg_submit_split_agent", role: "agent", title: "Code Agent", text: "", status: "running", createdAt: now, sessionId: "ses_submit_split", threadId: "thr_submit_split", traceId: "trc_submit_split", turnId: "turn_submit_split", runnerTrace: { traceId: "trc_submit_split", status: "running", sessionId: "ses_submit_split", threadId: "thr_submit_split", events: [], eventCount: 0, fullTraceLoaded: false, hasMore: false } } ] }; } function submitSplitTrace(): JsonRecord { return { traceId: "trc_submit_split", status: "running", sessionId: "ses_submit_split", threadId: "thr_submit_split", turnId: "turn_submit_split", events: [], eventCount: 0, fullTraceLoaded: false, hasMore: false }; } function crossSessionLateA(): SessionRecord { const now = new Date().toISOString(); return { sessionId: "ses_late_A", threadId: "thr_late_A", status: "completed", lastTraceId: "trc_late_A", startedAt: now, updatedAt: now, messageCount: 2, firstUserMessagePreview: "写一个python脚本测试性能", messages: [ { id: "msg_late_A_user", messageId: "msg_late_A_user", role: "user", title: "用户", text: "写一个python脚本测试性能", status: "sent", createdAt: now, sessionId: "ses_late_A", threadId: "thr_late_A", traceId: "trc_late_A", turnId: "turn_late_A" }, { id: "msg_late_A_agent", messageId: "msg_late_A_agent", role: "agent", title: "Code Agent", text: "已写好 perf_test.py,脚本可用。", status: "completed", createdAt: now, sessionId: "ses_late_A", threadId: "thr_late_A", traceId: "trc_late_A", turnId: "turn_late_A", runnerTrace: crossSessionLateTraceA() } ] }; } function crossSessionLateB(): SessionRecord { const now = new Date().toISOString(); return { sessionId: "ses_late_B", threadId: "thr_late_B", status: "active", lastTraceId: "trc_late_A", startedAt: now, updatedAt: now, messageCount: 2, firstUserMessagePreview: "B session waiting", messages: [ { id: "msg_late_B_user", messageId: "msg_late_B_user", role: "user", title: "用户", text: "B session waiting", status: "sent", createdAt: now, sessionId: "ses_late_B", threadId: "thr_late_B", traceId: "trc_late_A", turnId: "turn_late_B" }, { id: "msg_late_B_agent", messageId: "msg_late_B_agent", role: "agent", title: "Code Agent", text: "", status: "running", createdAt: now, sessionId: "ses_late_B", threadId: "thr_late_B", traceId: "trc_late_A", turnId: "turn_late_B", runnerTrace: { traceId: "trc_late_A", status: "running", sessionId: "ses_late_B", threadId: "thr_late_B", events: [], eventCount: 0, fullTraceLoaded: false, hasMore: false } } ] }; } function crossSessionLateTraceA(): JsonRecord { const now = new Date().toISOString(); const finalText = "已写好 perf_test.py,脚本可用。"; const event = { seq: 1, createdAt: now, label: "agentrun:assistant:message", type: "assistant_message", status: "completed", replyAuthority: true, final: true, message: finalText, terminal: true }; return { traceId: "trc_late_A", status: "completed", sessionId: "ses_late_A", threadId: "thr_late_A", turnId: "turn_late_A", events: [event], eventCount: 1, fullTraceLoaded: true, hasMore: false, finalResponse: { text: finalText, status: "completed" }, assistantText: finalText }; } function sessionDetailDelayMs(sessionId: string): number { if (state.scenarioId === "cross-session-late-events" && sessionId === "ses_late_A") return 900; if (state.scenarioId === "create-while-route-loading" && (sessionId === "ses_running" || sessionId === "ses_created_while_running")) return 4_000; return state.sessionDetailDelayMs; } function acceptChatTurn(body: JsonRecord): JsonRecord { const sessionId = typeof body.sessionId === "string" && body.sessionId.trim() ? body.sessionId : state.selectedSessionId; const session = sessionById(sessionId) ?? createManualSession({ sessionId }); if (!state.sessions.includes(session)) state.sessions.unshift(session); const threadId = typeof body.threadId === "string" && body.threadId.trim() ? body.threadId : null; const traceId = state.scenarioId === "live-rest-backfill-without-terminal-sse" ? "trc_live_backfill" : typeof body.traceId === "string" && body.traceId.trim() ? body.traceId : `trc_${Date.now().toString(16)}`; const message = typeof body.message === "string" ? body.message : ""; const now = new Date().toISOString(); session.status = "running"; session.lastTraceId = traceId; session.updatedAt = now; session.firstUserMessagePreview = session.firstUserMessagePreview ?? message; session.messageCount = (session.messages?.length ?? 0) + 2; session.messages = [ ...(session.messages ?? []), { id: `msg_${traceId}_user`, role: "user", title: "用户", text: message, status: "sent", createdAt: now, sessionId, threadId, traceId }, { id: `msg_${traceId}_agent`, role: "agent", title: "Code Agent", text: "", status: "running", createdAt: now, sessionId, threadId, traceId, runnerTrace: { traceId, status: "running", sessionId, threadId, events: [], eventCount: 0, fullTraceLoaded: false, hasMore: false } } ]; if (state.scenarioId === "live-rest-backfill-without-terminal-sse") { state.liveBackfillTraceId = traceId; state.liveBackfillReadyAtMs = Date.now() + 2_000; state.traces[traceId] = liveBackfillEarlyTrace(sessionId, threadId, traceId); scheduleLiveBackfillProjection(sessionId, threadId, traceId, state.liveBackfillReadyAtMs); } else { state.traces[traceId] = { traceId, status: "running", sessionId, threadId, events: [], eventCount: 0, fullTraceLoaded: false, hasMore: false }; } return { status: "running", accepted: true, running: true, terminal: false, traceId, sessionId, threadId, turnId: traceId }; } function liveBackfillEarlyTrace(sessionId: string, threadId: string | null, traceId: string): JsonRecord { const createdAt = new Date().toISOString(); const agentRun = liveBackfillAgentRun("pending", null, 4); return { traceId, status: "running", running: true, terminal: false, sessionId, threadId, agentRun, events: [ { seq: 1, sourceSeq: 1, createdAt, label: "agentrun:request:accepted", type: "backend_status", status: "running", payload: { commandId: agentRun.commandId } }, { seq: 2, sourceSeq: 2, createdAt, label: "agentrun:run:created", type: "backend_status", status: "running", payload: { runId: agentRun.runId, runStatus: agentRun.runStatus } }, { seq: 3, sourceSeq: 3, createdAt, label: "agentrun:command:created", type: "backend_status", status: "running", payload: { commandId: agentRun.commandId, commandState: agentRun.commandState } }, { seq: 4, sourceSeq: 4, createdAt, label: "agentrun:runner-job:created", type: "backend_status", status: "running", payload: { commandId: agentRun.commandId, jobName: agentRun.jobName, namespace: agentRun.namespace } } ], eventCount: 4, fullTraceLoaded: true, hasMore: false, traceSummary: { source: "agentrun-events", agentRun, valuesPrinted: false } }; } function liveBackfillCompletedTrace(sessionId: string, threadId: string | null, traceId: string): JsonRecord { const createdAt = new Date().toISOString(); const finalText = "fake AgentRun completed after REST backfill without terminal SSE."; const agentRun = liveBackfillAgentRun("completed", "completed", 23); const events = [ ...(liveBackfillEarlyTrace(sessionId, threadId, traceId).events as JsonRecord[]), { seq: 5, sourceSeq: 21, createdAt, label: "agentrun:assistant:message", type: "assistant_message", status: "completed", message: finalText, payload: { commandId: agentRun.commandId } }, { seq: 6, sourceSeq: 22, createdAt, label: "item/commandExecution:completed", type: "commandExecution", status: "completed", stdout: "OK\n", payload: { commandId: agentRun.commandId, exitCode: 0 } }, { seq: 7, sourceSeq: 23, createdAt, label: "agentrun:backend:turn/completed", type: "backend_status", status: "completed", terminal: true, payload: { commandId: agentRun.commandId, phase: "command-terminal", terminalStatus: "completed" } } ]; return { traceId, status: "completed", running: false, terminal: true, sessionId, threadId, agentRun, events, eventCount: events.length, fullTraceLoaded: true, hasMore: false, finalResponse: { text: finalText, status: "completed" }, traceSummary: { source: "agentrun-command-result", terminalStatus: "completed", agentRun, valuesPrinted: false } }; } function liveBackfillAgentRun(commandState: string, terminalStatus: string | null, lastSeq: number): JsonRecord { return { adapter: "agentrun-v01", runId: "run_live_backfill_issue1555", commandId: "cmd_live_backfill_issue1555", status: commandState, runStatus: "claimed", commandState, terminalStatus, runnerStatus: "running", namespace: "agentrun-v02", jobName: "agentrun-v01-runner-live-backfill-issue1555", lastSeq, valuesPrinted: false }; } function scheduleLiveBackfillProjection(sessionId: string, threadId: string | null, traceId: string, readyAtMs: number): void { const scenarioId = state.scenarioId; setTimeout(() => { if (state.scenarioId !== scenarioId || state.liveBackfillTraceId !== traceId) return; commitLiveBackfillProjection(sessionId, threadId, traceId); }, Math.max(0, readyAtMs - Date.now())); } function commitLiveBackfillProjection(sessionId: string, threadId: string | null, traceId: string): void { const completed = liveBackfillCompletedTrace(sessionId, threadId, traceId); const finalText = typeof (completed.finalResponse as JsonRecord | undefined)?.text === "string" ? String((completed.finalResponse as JsonRecord).text) : ""; state.traces[traceId] = completed; const session = sessionById(sessionId); if (!session) return; session.status = "completed"; session.updatedAt = new Date().toISOString(); session.messages = (session.messages ?? []).map((message) => { if (message.role !== "agent" || message.traceId !== traceId) return message; return { ...message, text: finalText, status: "completed", runnerTrace: completed }; }); } function sessionSummary(session: SessionRecord): SessionRecord { const { messages: _messages, hidden: _hidden, ...rest } = session; const status = typeof rest.status === "string" ? rest.status : "unknown"; return { ...rest, status, running: isRunningStatus(status), terminal: isTerminalStatus(status) } as SessionRecord; } function isRunningStatus(status: string): boolean { return ["active", "accepted", "pending", "running"].includes(status); } function isTerminalStatus(status: string): boolean { return ["blocked", "canceled", "cancelled", "completed", "failed", "timeout"].includes(status); } function workbenchSessionListPayload(url: URL): JsonRecord { if (url.searchParams.has("projectId") || url.searchParams.has("workspaceId")) return { ok: false, status: 400, error: { code: "workbench_authority_removed" } }; const includeRouteId = url.searchParams.get("includeSessionId") || ""; const includeSessionId = includeRouteId ? canonicalSessionId(includeRouteId) : ""; const limit = boundedPageLimit(url.searchParams.get("limit")); const offset = cursorOffset(url.searchParams.get("cursor") || url.searchParams.get("after")); const visible = state.sessions.filter((item) => !item.hidden && (item.status !== "archived" || item.sessionId === includeSessionId)); const authorityVisible = state.scenarioId === "create-while-route-loading" && includeSessionId === "ses_running" ? visible.filter((item) => item.sessionId !== "ses_created_while_running") : visible; const listed = state.listOmitSelected && includeSessionId ? authorityVisible.filter((item) => item.sessionId !== includeSessionId) : authorityVisible; const page = listed.slice(offset, offset + limit); const included = includeSessionId && !page.some((session) => session.sessionId === includeSessionId) ? listed.find((session) => session.sessionId === includeSessionId) ?? null : null; const summaries = [...(included ? [included] : []), ...page].map((session) => sessionSummary(session)); const hasMore = offset + limit < listed.length; return { ok: true, status: "succeeded", contractVersion: "workbench-sessions-v1", sessions: summaries, count: summaries.length, total: listed.length, cursor: offset > 0 ? cursorFromOffset(offset) : null, hasMore, nextCursor: hasMore ? cursorFromOffset(offset + limit) : null }; } function boundedPageLimit(value: string | null): number { const parsed = Number.parseInt(value ?? "", 10); return Math.min(100, Math.max(1, Number.isInteger(parsed) && parsed > 0 ? parsed : 50)); } function cursorOffset(value: string | null): number { const text = typeof value === "string" ? value.trim() : ""; if (!text) return 0; if (text.startsWith("idx:")) return Math.max(0, Number.parseInt(text.slice(4), 10) || 0); return Math.max(0, Number.parseInt(text, 10) || 0); } function cursorFromOffset(offset: number): string { return `idx:${Math.max(0, Math.trunc(offset))}`; } function workbenchSessionMessagesPayload(session: SessionRecord, url: URL): JsonRecord { const messages = Array.isArray(session.messages) ? session.messages : []; const requestedLimit = Number(url.searchParams.get("limit") ?? messages.length); const limit = Math.max(1, Number.isFinite(requestedLimit) ? Math.trunc(requestedLimit) : messages.length || 100); const page = messages.slice(0, limit); return { ok: true, status: "succeeded", sessionId: session.sessionId, messages: page, count: page.length, total: messages.length, hasMore: messages.length > page.length }; } function sessionById(id: string): SessionRecord | null { return state.sessions.find((session) => session.sessionId === id) ?? null; } function canonicalSessionId(id: string): string { const text = id.trim(); if (!text.startsWith("cnv_")) return text; const conversation = state.sessions.find((session) => session.conversationId === text); return conversation?.sessionId ?? `ses_${text.slice("cnv_".length)}`; } function visibleSessionById(id: string, options: { includeArchived?: boolean } = {}): SessionRecord | null { const session = sessionById(id); if (!session || session.hidden) return null; if (session.status === "archived" && !options.includeArchived) return null; return session; } function sessionPayload(sessionId: string): JsonRecord { const session = sessionById(sessionId); if (state.scenarioId === "terminal-turn-stale-session-active" && sessionId === "ses_completed") return { sessionId, status: "active", lastTraceId: "trc_completed", updatedAt: new Date().toISOString() }; return { sessionId, status: session?.status ?? "unknown", lastTraceId: session?.lastTraceId ?? null, updatedAt: new Date().toISOString() }; } function turnPayload(traceId: string): JsonRecord { if (state.scenarioId === "live-rest-backfill-without-terminal-sse" && traceId === state.liveBackfillTraceId) { const session = state.sessions.find((item) => item.lastTraceId === traceId) ?? state.sessions[0]; const sessionId = session?.sessionId ?? state.selectedSessionId; const threadId = typeof session?.threadId === "string" ? session.threadId : null; return state.traces[traceId] ?? liveBackfillEarlyTrace(sessionId, threadId, traceId); } const trace = state.traces[traceId] ?? { traceId, status: "unknown", events: [] }; if (state.scenarioId === "tool-completed-projection-running" && traceId === "trc_running") return { ...trace, traceId, status: "running", running: true, terminal: false, projectionStatus: "projecting", trace: { status: trace.status, eventCount: trace.eventCount ?? 0 } }; if (state.scenarioId === "terminal-turn-stale-session-active" && traceId === "trc_completed") return { ...trace, traceId, status: "active", running: true, terminal: false, trace: { status: "completed", eventCount: trace.eventCount ?? 0 } }; const status = String(trace.status ?? "unknown"); return { ...trace, traceId, status, running: ["running", "pending", "accepted"].includes(status), terminal: ["completed", "failed", "blocked", "timeout", "canceled"].includes(status) }; } function workbenchTurnPayload(traceId: string): JsonRecord { const turn = turnPayload(traceId); return { ok: true, status: "ok", contractVersion: "workbench-read-model-v1", turn, ...projectionEnvelope(turn) }; } function tracePayload(traceId: string, url: URL): JsonRecord { const turn = turnPayload(traceId); const events = Array.isArray(turn.events) ? turn.events as JsonRecord[] : []; const afterProjectedSeq = traceAfterProjectedSeq(url); const requestedLimit = Number(url.searchParams.get("limit") ?? events.length); const limit = Math.max(1, Number.isFinite(requestedLimit) ? Math.trunc(requestedLimit) : events.length || 100); const indexedEvents = events.map((event, index) => { const projectedSeq = nonNegativeInteger(event.projectedSeq ?? event.seq, index + 1); return { event: { ...event, seq: projectedSeq, projectedSeq }, projectedSeq }; }); const filtered = afterProjectedSeq > 0 ? indexedEvents.filter((item) => item.projectedSeq > afterProjectedSeq) : indexedEvents; const pageRecords = filtered.slice(0, limit); const page = pageRecords.map((item) => item.event); const firstProjectedSeq = pageRecords.length > 0 ? pageRecords[0]?.projectedSeq ?? null : null; const lastProjectedSeq = pageRecords.length > 0 ? pageRecords.at(-1)?.projectedSeq ?? null : null; const hasMore = filtered.length > page.length; return { ...turn, events: page, eventCount: events.length, hasMore, fullTraceLoaded: !hasMore, nextProjectedSeq: page.length > 0 ? lastProjectedSeq : afterProjectedSeq, nextCursor: hasMore && lastProjectedSeq ? `projected:${lastProjectedSeq}` : null, range: { afterProjectedSeq, fromProjectedSeq: firstProjectedSeq, toProjectedSeq: lastProjectedSeq, limit, returned: page.length, total: events.length } }; } function traceAfterProjectedSeq(url: URL): number { const cursor = url.searchParams.get("cursor") ?? ""; if (cursor.startsWith("projected:")) return nonNegativeInteger(cursor.slice("projected:".length), 0); return nonNegativeInteger(url.searchParams.get("afterProjectedSeq"), 0); } function workbenchTracePayload(traceId: string, url: URL): JsonRecord { const payload = tracePayload(traceId, url); if (state.scenarioId === "tool-completed-projection-running" && traceId === "trc_running") { return { ok: true, status: "ok", contractVersion: "workbench-read-model-v1", traceId, sessionId: payload.sessionId ?? null, threadId: payload.threadId ?? null, traceStatus: "completed", timing: payload.timing, startedAt: payload.startedAt, lastEventAt: payload.lastEventAt, finishedAt: payload.finishedAt, durationMs: payload.durationMs, events: payload.events, eventCount: payload.eventCount, hasMore: payload.hasMore, nextProjectedSeq: payload.nextProjectedSeq, nextCursor: payload.nextCursor, range: payload.range, fullTraceLoaded: payload.fullTraceLoaded, projectionStatus: "projecting", terminalEvidence: null, finalResponse: null, traceSummary: payload.traceSummary, retention: payload.retention }; } return { ok: true, status: "ok", contractVersion: "workbench-read-model-v1", traceId, sessionId: payload.sessionId ?? null, threadId: payload.threadId ?? null, traceStatus: payload.status, timing: payload.timing, startedAt: payload.startedAt, lastEventAt: payload.lastEventAt, finishedAt: payload.finishedAt, durationMs: payload.durationMs, events: payload.events, eventCount: payload.eventCount, hasMore: payload.hasMore, nextProjectedSeq: payload.nextProjectedSeq, nextCursor: payload.nextCursor, range: payload.range, fullTraceLoaded: payload.fullTraceLoaded, terminalEvidence: payload.terminalEvidence, finalResponse: payload.finalResponse, traceSummary: payload.traceSummary, retention: payload.retention, ...projectionEnvelope(payload) }; } function projectionEnvelope(payload: JsonRecord): JsonRecord { const projection = payload.projection && typeof payload.projection === "object" ? payload.projection as JsonRecord : null; if (!projection) return {}; return { projection, projectionStatus: projection.projectionStatus, projectionHealth: projection.projectionHealth, lastProjectedSeq: projection.lastProjectedSeq, sourceRunId: projection.sourceRunId, sourceCommandId: projection.sourceCommandId, staleMs: projection.staleMs, blocker: projection.blocker }; } function sse(request: IncomingMessage, response: ServerResponse, url: URL): void { response.writeHead(200, { "content-type": "text/event-stream; charset=utf-8", "cache-control": "no-cache", connection: "keep-alive" }); sseClients.add(response); request.on("close", () => sseClients.delete(response)); writeSse(response, "workbench.connected", { type: "connected", sessionId: url.searchParams.get("sessionId") }); if (state.scenarioId === "projection-sse-error") { const scenarioId = state.scenarioId; setTimeout(() => { if (state.scenarioId !== scenarioId) return; const projection = projectionDiagnostic({ traceId: "trc_projection_sse_error", code: "workbench_sse_projection_error", message: "SSE 投影事件异常,实时状态暂不可见。", category: "realtime-error", layer: "workbench-sse", runId: "run_projection_sse_error", commandId: "cmd_projection_sse_error" }); writeSse(response, "workbench.error", { type: "error", sessionId: "ses_projection_sse_error", threadId: "thr_projection_sse_error", traceId: "trc_projection_sse_error", projection, ...projectionEnvelope({ projection }), error: projection.blocker }); }, 350); } if (state.scenarioId === "cross-session-late-events") { const scenarioId = state.scenarioId; setTimeout(() => { if (state.scenarioId !== scenarioId) return; const trace = crossSessionLateTraceA(); const event = (trace.events as JsonRecord[])[0]; writeSse(response, "workbench.trace.event", { type: "trace.event", sessionId: "ses_late_A", threadId: "thr_late_A", traceId: "trc_late_A", event, snapshot: trace }); writeSse(response, "workbench.turn.snapshot", { type: "turn.snapshot", sessionId: "ses_late_A", threadId: "thr_late_A", traceId: "trc_late_A", turn: trace }); }, 650); return; } if (!state.terminalScript) return; const scenarioId = state.scenarioId; setTimeout(() => { if (state.scenarioId !== scenarioId) return; if (state.scenarioId === "terminal-canceled-late-timing") { const trace = applyTerminalCanceledLateTiming(12_000, "2026-06-17T09:39:12.000Z"); const event = Array.isArray(trace?.events) ? trace.events.at(-1) as JsonRecord : null; if (event) writeSse(response, "workbench.trace.event", { type: "trace.event", sessionId: "ses_running", threadId: "thr_running", traceId: "trc_running", event, snapshot: trace }); const message = runningAgentMessageSnapshot(); if (message) writeSse(response, "workbench.message.snapshot", { type: "message.snapshot", sessionId: "ses_running", threadId: "thr_running", traceId: "trc_running", message }); writeSse(response, "workbench.turn.snapshot", { type: "turn.snapshot", sessionId: "ses_running", threadId: "thr_running", traceId: "trc_running", turn: turnPayload("trc_running") }); setTimeout(() => { if (state.scenarioId !== scenarioId) return; applyTerminalCanceledLateTiming(14_000, "2026-06-17T09:39:14.000Z"); const late = runningAgentMessageSnapshot(); if (late) writeSse(response, "workbench.message.snapshot", { type: "message.snapshot", sessionId: "ses_running", threadId: "thr_running", traceId: "trc_running", message: late }); writeSse(response, "workbench.turn.snapshot", { type: "turn.snapshot", sessionId: "ses_running", threadId: "thr_running", traceId: "trc_running", turn: turnPayload("trc_running") }); }, 650); return; } if (state.scenarioId === "terminal-completed-no-final-response") { const trace = completedNoFinalTrace(); const event = (trace.events as JsonRecord[]).at(-1) ?? { status: "completed", terminal: true }; writeSse(response, "workbench.trace.event", { type: "trace.event", sessionId: "ses_running", threadId: "thr_running", traceId: "trc_running", event, snapshot: trace }); finishRunningNoFinalResponse(trace); const message = runningAgentMessageSnapshot(); if (message) writeSse(response, "workbench.message.snapshot", { type: "message.snapshot", sessionId: "ses_running", threadId: "thr_running", traceId: "trc_running", message }); writeSse(response, "workbench.turn.snapshot", { type: "turn.snapshot", sessionId: "ses_running", threadId: "thr_running", traceId: "trc_running", turn: turnPayload("trc_running") }); return; } const terminalStatus = state.terminalFailureScript ? "failed" : "completed"; const terminalText = state.terminalFailureScript ? "恢复后失败:缺少受控依赖。" : state.scenarioId === "progress-only-final-response" ? finalOnlyText : "事件重放后完成。"; const event = { seq: 3, createdAt: new Date().toISOString(), label: "agentrun:assistant:message", type: "assistant_message", status: terminalStatus, replyAuthority: true, final: true, message: terminalText, terminal: true }; writeSse(response, "workbench.trace.event", { type: "trace.event", sessionId: "ses_running", threadId: "thr_running", traceId: "trc_running", event, snapshot: { traceId: "trc_running", sessionId: "ses_running", threadId: "thr_running", status: terminalStatus, events: [event], eventCount: 3, fullTraceLoaded: true, finalResponse: { text: terminalText, status: terminalStatus } } }); finishRunningSession(terminalStatus, terminalText); const message = runningAgentMessageSnapshot(); if (message) writeSse(response, "workbench.message.snapshot", { type: "message.snapshot", sessionId: "ses_running", threadId: "thr_running", traceId: "trc_running", message }); writeSse(response, "workbench.turn.snapshot", { type: "turn.snapshot", sessionId: "ses_running", threadId: "thr_running", traceId: "trc_running", turn: turnPayload("trc_running") }); }, state.scenarioId === "progress-only-final-response" ? 5_000 : state.scenarioId === "event-replay" ? 1_500 : 350); } function broadcastSse(eventName: string, payload: JsonRecord): void { for (const client of Array.from(sseClients)) writeSse(client, eventName, payload); } function writeSse(response: ServerResponse, eventName: string, payload: JsonRecord): void { response.write(`event: ${eventName}\n`); response.write(`data: ${JSON.stringify(payload)}\n\n`); } function finishRunningSession(status: "completed" | "failed", text: string): void { const session = sessionById("ses_running"); if (!session) return; session.status = status; session.updatedAt = new Date().toISOString(); const trace = state.traces.trc_running ?? { traceId: "trc_running", status: "running", events: [] }; const finalEvent = { seq: 4, createdAt: new Date().toISOString(), label: `agentrun:terminal:${status}`, status, terminal: true }; const events = [...(Array.isArray(trace.events) ? trace.events as JsonRecord[] : []), finalEvent]; state.traces.trc_running = { ...trace, status, events, eventCount: events.length, fullTraceLoaded: true, hasMore: false, assistantText: text, finalResponse: { text, status } }; session.messages = (session.messages ?? []).map((message) => message.role === "agent" ? { ...message, text, status, runnerTrace: state.traces.trc_running } : message); } function finishRunningNoFinalResponse(trace: JsonRecord = completedNoFinalTrace()): void { state.traces.trc_running = trace; const session = sessionById("ses_running"); if (!session) return; session.status = "completed"; session.updatedAt = new Date().toISOString(); session.messages = (session.messages ?? []).map((message) => message.role === "agent" ? { ...message, text: "", status: "completed", runnerTrace: trace } : message); } function runningAgentMessageSnapshot(): JsonRecord | null { const session = sessionById("ses_running"); const message = session?.messages?.find((item) => item.role === "agent" && item.traceId === "trc_running"); return message ?? null; } function stateSummary(): JsonRecord { return { scenarioId: state.scenarioId, selectedSessionId: state.selectedSessionId, requestLedger: state.requestLedger, legacyRequestLedger: state.legacyRequestLedger, chatRequests: state.chatRequests, staleTraceId: state.staleTraceId, sessions: state.sessions.map((item) => ({ sessionId: item.sessionId, threadId: item.threadId, status: item.status, lastTraceId: item.lastTraceId, hidden: item.hidden === true })) }; } function gcEmptySessions(body: JsonRecord): JsonRecord { const ttlMs = positiveInteger(body.ttlMs, DEFAULT_WORKBENCH_EMPTY_SESSION_TTL_MS); const nowMs = Date.parse(typeof body.now === "string" ? body.now : "2026-06-18T16:20:30.000Z"); const archivedSessionIds: string[] = []; const keptByReason: Record = {}; for (const session of state.sessions) { if (session.status === "archived") continue; const decision = classifyWorkbenchEmptySessionGcCandidate(toBackendSessionRecord(session), { nowMs, ttlMs }); if (!decision.eligible) { keptByReason[decision.reason] = (keptByReason[decision.reason] ?? 0) + 1; continue; } session.status = "archived"; session.updatedAt = new Date(nowMs).toISOString(); archivedSessionIds.push(session.sessionId); } return { ok: true, status: "completed", ttlMs, archived: archivedSessionIds.length, archivedSessionIds, keptByReason, valuesRedacted: true }; } function toBackendSessionRecord(session: SessionRecord): JsonRecord { return { id: session.sessionId, status: session.status, startedAt: session.startedAt, updatedAt: session.updatedAt, lastTraceId: session.lastTraceId, session: { createdAt: session.startedAt, updatedAt: session.updatedAt, messageCount: session.messageCount, messages: session.messages ?? [], lastTraceId: session.lastTraceId, valuesRedacted: true, secretMaterialStored: false } }; } function recordLedger(method: string, url: URL): void { if (!url.pathname.startsWith("/v1/")) return; const entry = { method, path: url.pathname, query: Object.fromEntries(url.searchParams.entries()) }; state.requestLedger.push(entry); if (isLegacyWorkbenchPath(url.pathname)) state.legacyRequestLedger.push(entry); } function isLegacyWorkbenchPath(path: string): boolean { if (/^\/v1\/workbench\/(sessions(?:\/[^/]+(?:\/messages)?)?|events|turns\/[^/]+|traces\/[^/]+\/events)$/u.test(path)) return false; if (path === "/v1/agent/chat" || /^\/v1\/agent\/sessions(?:\/[^/]+(?:\/select)?)?$/u.test(path)) return false; return path.startsWith("/v1/workbench/") || path.startsWith("/v1/agent/"); } function authPayload(): JsonRecord { const deniedCapabilities = { web: "forbidden", workbench: "forbidden", codeAgent: "forbidden", billing: "forbidden", apiKeys: "forbidden", admin: "forbidden" }; if (state.scenarioId === "auth-upstream-unavailable" || state.scenarioId === "auth-invalid-credentials") { return { authenticated: false, mode: "server", authMethod: null, identityAuthority: null, sessionKind: null, actor: null, user: null, capabilities: deniedCapabilities, expiresAt: null, valuesRedacted: true, error: { code: "auth_required", message: "Authentication is required", status: 401 } }; } const actor = { id: "usr_e2e_admin", username: "e2e-admin", role: "admin", status: "active" }; return { authenticated: true, mode: "server", authMethod: "web-session", identityAuthority: "hwlab-local", sessionKind: "browser", actor, user: actor, capabilities: { web: "available", workbench: "available", codeAgent: "available", billing: "unlinked", apiKeys: "available", admin: "available" }, expiresAt: null, valuesRedacted: true }; } function authLoginResponse(response: ServerResponse): void { if (state.scenarioId === "auth-upstream-unavailable") return json(response, 502, { ok: false, status: "failed", error: { code: "upstream_unavailable", message: "auth upstream unavailable", retryable: true, layer: "proxy" } }); return json(response, 401, { ok: false, status: "failed", error: { code: "invalid_credentials", message: "invalid credentials" } }); } function performanceSummaryErrorStatus(scenarioId: string): number | null { const match = /^performance-summary-error-(400|401|403|404|409|500)$/u.exec(scenarioId); return match ? Number(match[1]) : null; } function statusMatrixTraceId(status: number): string { return String(status).repeat(11).slice(0, 32); } function redactRequestBody(value: JsonRecord): JsonRecord { const output: JsonRecord = {}; for (const [key, item] of Object.entries(value)) output[key] = /secret|token|key|password|authorization/iu.test(key) ? "" : item; return output; } async function readJson(request: IncomingMessage): Promise { const chunks: Buffer[] = []; for await (const chunk of request) chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)); if (chunks.length === 0) return {}; try { const parsed = JSON.parse(Buffer.concat(chunks).toString("utf8")); return parsed && typeof parsed === "object" ? parsed as JsonRecord : {}; } catch { return {}; } } function errorDiagnosticResponse(response: ServerResponse, status: number, route: string, code: string, message: string, overrides: Partial = {}): void { const diagnostic = { contractVersion: "hwlab-error-diagnostic-v1", traceId: String(overrides.traceId ?? "11111111111111111111111111111111"), requestId: String(overrides.requestId ?? "req_e2e_api_error_diagnostic"), route, layer: String(overrides.layer ?? "api"), category: String(overrides.category ?? "server"), code, httpStatus: status, source: String(overrides.source ?? "server"), observedAt: new Date().toISOString(), valuesPrinted: false }; json(response, status, { ok: false, status, error: { code, message, diagnostic } }, { traceparent: `00-${diagnostic.traceId}-2222222222222222-01`, "x-hwlab-otel-trace-id": diagnostic.traceId, "x-request-id": diagnostic.requestId }); } function json(response: ServerResponse, status: number, body: unknown, headers: Record = {}): void { response.writeHead(status, { "content-type": "application/json; charset=utf-8", ...headers }); response.end(JSON.stringify(body)); } function staticFile(response: ServerResponse, path: string): void { const filePath = safeStaticPath(path); const target = filePath && existsSync(filePath) && statSync(filePath).isFile() ? filePath : join(distDir, "index.html"); response.writeHead(200, { "content-type": contentType(target) }); if (extname(target) === ".html") { response.end(injectRuntimeConfig(readFileSync(target, "utf8"))); return; } createReadStream(target).pipe(response); } function injectRuntimeConfig(html: string): string { if (html.includes("HWLAB_CLOUD_WEB_CONFIG")) return html; return html.replace("", ` ${runtimeConfigScript}\n `); } function safeStaticPath(path: string): string | null { const normalized = resolve(distDir, `.${decodeURIComponent(path === "/" ? "/index.html" : path)}`); return normalized === distDir || normalized.startsWith(`${distDir}${sep}`) ? normalized : null; } function contentType(filePath: string): string { switch (extname(filePath)) { case ".html": return "text/html; charset=utf-8"; case ".js": return "text/javascript; charset=utf-8"; case ".css": return "text/css; charset=utf-8"; case ".svg": return "image/svg+xml"; case ".ico": return "image/x-icon"; default: return "application/octet-stream"; } } function delay(ms: number): Promise { return ms > 0 ? new Promise((resolveDelay) => setTimeout(resolveDelay, ms)) : Promise.resolve(); } function positiveInteger(value: unknown, fallback: number): number { const parsed = Number.parseInt(String(value ?? ""), 10); return Number.isInteger(parsed) && parsed > 0 ? parsed : fallback; } function nonNegativeInteger(value: unknown, fallback: number): number { const parsed = Number.parseInt(String(value ?? ""), 10); return Number.isInteger(parsed) && parsed >= 0 ? parsed : Math.max(0, Math.trunc(fallback)); }