// 重构前 index.ts 只读参考：commit 6a04144d3f5103014f75b637d7e6bc2f45bf007f，blob 56e590c1a6b5ca7ad128bf2c992f60e46c355a58；可用 `git show 6a04144d3f5103014f75b637d7e6bc2f45bf007f:src/components/microservices/code-queue/src/index.ts` 查看。

import { existsSync, readdirSync, readFileSync, statSync, type Dirent } from "node:fs";
import { resolve } from "node:path";
import type {
  AttemptSummary,
  FeedbackPromptRecord,
  JudgeDecision,
  JudgeResult,
  JsonValue,
  LiveOutput,
  PromptHistoryItem,
  QueueTask,
  QueuedStatusReason,
  RuntimeConfig,
  SessionCommandOutput,
  SessionFileChange,
  TranscriptKind,
  TranscriptLine,
} from "./types";
import { codeAgentPortForModel, codeAgentPortInfo, codeExecutionModeInfo, extractRecord } from "./code-agent/common";
import { currentTaskPromptMarker, resolvedReferenceContextTitle, stripCodeQueueEnvironmentHint, userPromptForDisplay } from "./prompts";
import { sanitizeTaskOutputText } from "./output-redaction";
import { outputArchiveSignature, taskFullOutput } from "./task-output";
import { retryPrompt } from "./judge";
import { readOaTraceStepsForTask, type OaTraceStepSummary } from "./oa-events";

export interface TaskViewContext {
  config: Pick<RuntimeConfig, "codexHome">;
  errorToJson: (error: unknown) => JsonValue;
  jsonResponse: (body: unknown, status?: number) => Response;
  logger: (level: "debug" | "info" | "warn" | "error", message: string, data?: JsonValue) => void;
  mergePromptHistory: (items: PromptHistoryItem[]) => PromptHistoryItem[];
  nowIso: () => string;
  outputPromptHistory: (task: QueueTask) => PromptHistoryItem[];
  pageBySeq: <T extends { seq: number }>(items: T[], url: URL, limit: number) => {
    mode: "tail" | "after" | "before";
    afterSeq: number;
    beforeSeq: number | null;
    nextAfterSeq: number;
    previousBeforeSeq: number | null;
    hasMore: boolean;
    hasBefore: boolean;
    chunk: T[];
  };
  parseLimit: (url: URL) => number;
  parseSeqParam: (url: URL, name: string, defaultValue: number | null) => number | null;
  queueIdOf: (task: QueueTask) => string;
  queuedStatusReason: (task: QueueTask) => QueuedStatusReason | null;
  queuedTaskPromptEditable: (task: QueueTask) => boolean;
  taskQueueEnteredAt: (task: QueueTask) => string;
}

function isCodexToolLifecycleOutput(output: Pick<LiveOutput, "channel" | "method" | "itemId" | "text">): boolean {
  if (output.channel !== "tool" || typeof output.itemId !== "string" || output.itemId.length === 0) return false;
  const method = String(output.method || "");
  if (method !== "item/started" && method !== "item/completed") return false;
  return /\b(?:webSearch|mcpToolCall|dynamicToolCall)\b/u.test(String(output.text || ""));
}

function codexToolLifecycleStartedBeforeIn(outputs: Pick<LiveOutput, "channel" | "method" | "itemId" | "text">[], output: Pick<LiveOutput, "channel" | "method" | "itemId" | "text">): boolean {
  if (!isCodexToolLifecycleOutput(output)) return false;
  return outputs.some((item) => item !== output && isCodexToolLifecycleOutput(item) && item.itemId === output.itemId && item.method === "item/started");
}

const judgeFailRetryLimit = 3;
const transcriptCache = new Map<string, { signature: string; previewTranscript?: TranscriptLine[]; fullTranscript?: TranscriptLine[] }>();
const codexSessionPathCache = new Map<string, string>();
const codexSessionFileChangeCache = new Map<string, { signature: string; changes: Map<string, SessionFileChange> }>();
const codexSessionCommandOutputCache = new Map<string, { signature: string; outputs: Map<string, SessionCommandOutput> }>();
let context: TaskViewContext | null = null;

export function configureTaskView(runtimeContext: TaskViewContext): void {
  context = runtimeContext;
}

function ctx(): TaskViewContext {
  if (context === null) throw new Error("task-view module is not configured");
  return context;
}

function taskTimestamp(value: string | null): string | null {
  if (value === null || value.length === 0) return null;
  const time = Date.parse(value);
  return Number.isFinite(time) ? new Date(time).toISOString() : null;
}

function terminalTask(task: QueueTask): boolean {
  return task.status === "succeeded" || task.status === "failed" || task.status === "canceled";
}

function terminalTaskUnread(task: QueueTask): boolean {
  return terminalTask(task) && task.readAt === null;
}

function queuedStatusPayload(task: QueueTask): { queuedReason: QueuedStatusReason | null; queuedReasonLabel: string | null } {
  const reason = ctx().queuedStatusReason(task);
  return {
    queuedReason: reason,
    queuedReasonLabel: reason?.label ?? null,
  };
}

function durationMsBetween(startAt: string | null | undefined, endAt: string | null | undefined): number | null {
  const start = typeof startAt === "string" ? Date.parse(startAt) : NaN;
  const end = typeof endAt === "string" ? Date.parse(endAt) : NaN;
  if (!Number.isFinite(start) || !Number.isFinite(end)) return null;
  return Math.max(0, end - start);
}

function safePreview(value: string, max = 900): string {
  const compact = value.replace(/\s+/gu, " ").trim();
  return compact.length > max ? `${compact.slice(0, max)}...` : compact;
}

function prefixPreview(value: string, max = 900): string {
  const trimmed = value.trim();
  return trimmed.length > max ? `${trimmed.slice(0, max)}...` : trimmed;
}

function linePreview(text: string, maxLines: number, maxChars: number): { text: string; omittedLines: number } {
  const clean = sanitizeTaskOutputText(text).replace(/\u001b\[[0-9;]*m/gu, "").trimEnd();
  if (clean.length === 0) return { text: "", omittedLines: 0 };
  const lines = clean.split(/\r?\n/u);
  const kept: string[] = [];
  let chars = 0;
  for (const line of lines) {
    if (kept.length >= maxLines || chars + line.length > maxChars) break;
    kept.push(line);
    chars += line.length + 1;
  }
  return { text: kept.join("\n"), omittedLines: Math.max(0, lines.length - kept.length) };
}

function completeTraceText(text: string): { text: string; omittedLines: number } {
  return { text: sanitizeTaskOutputText(text).replace(/\u001b\[[0-9;]*m/gu, "").trimEnd(), omittedLines: 0 };
}

function editedOutputPreview(text: string): { text: string; omittedLines: number } {
  return linePreview(compactTranscriptBody(text), 120, 24_000);
}

function codexSessionDateDir(value: string | null | undefined): string | null {
  if (typeof value !== "string" || value.length === 0) return null;
  const date = new Date(value);
  if (Number.isNaN(date.getTime())) return null;
  return resolve(
    ctx().config.codexHome,
    "sessions",
    String(date.getUTCFullYear()),
    String(date.getUTCMonth() + 1).padStart(2, "0"),
    String(date.getUTCDate()).padStart(2, "0"),
  );
}

function codexSessionSignature(path: string): string | null {
  try {
    const stat = statSync(path);
    return `${stat.size}:${Math.floor(stat.mtimeMs)}`;
  } catch {
    return null;
  }
}

function findCodexSessionFile(task: QueueTask): string | null {
  const threadId = task.codexThreadId;
  if (threadId === null || threadId.length === 0) return null;
  const cached = codexSessionPathCache.get(threadId);
  if (cached !== undefined && existsSync(cached)) return cached;

  const roots = Array.from(new Set([
    codexSessionDateDir(task.startedAt),
    codexSessionDateDir(task.createdAt),
    codexSessionDateDir(task.updatedAt),
    resolve(ctx().config.codexHome, "sessions"),
  ].filter((value): value is string => value !== null && existsSync(value))));
  const matches: string[] = [];
  let scanned = 0;
  const scan = (dir: string, depth: number): void => {
    if (depth < 0 || scanned > 4000) return;
    scanned += 1;
    let entries: Dirent[];
    try {
      entries = readdirSync(dir, { withFileTypes: true });
    } catch {
      return;
    }
    for (const entry of entries) {
      const path = resolve(dir, entry.name);
      if (entry.isDirectory()) {
        scan(path, depth - 1);
      } else if (entry.isFile() && entry.name.endsWith(".jsonl") && entry.name.includes(threadId)) {
        matches.push(path);
      }
    }
  };
  for (const root of roots) scan(root, root.endsWith("/sessions") ? 4 : 1);
  matches.sort((left, right) => (statMtimeMs(right) - statMtimeMs(left)) || right.localeCompare(left));
  const match = matches[0] ?? null;
  if (match !== null) codexSessionPathCache.set(threadId, match);
  return match;
}

function statMtimeMs(path: string): number {
  try {
    return statSync(path).mtimeMs;
  } catch {
    return 0;
  }
}

function parseCodexToolOutputText(raw: string): string {
  const text = String(raw || "");
  try {
    const parsed = JSON.parse(text) as Record<string, unknown>;
    if (typeof parsed.output === "string") return parsed.output;
  } catch {
    // Keep the raw tool output if it is not the JSON wrapper used by Codex.
  }
  return text;
}

function recordStringField(record: Record<string, unknown> | null, keys: string[]): string {
  if (record === null) return "";
  for (const key of keys) {
    const value = record[key];
    if (typeof value === "string") return value;
  }
  return "";
}

function recordNumberField(record: Record<string, unknown> | null, keys: string[]): number | null {
  if (record === null) return null;
  for (const key of keys) {
    const value = Number(record[key]);
    if (Number.isFinite(value)) return value;
  }
  return null;
}

function parseToolOutputStreams(raw: string): { stdout: string; stderr: string; output: string; exitCode: number | null } {
  const text = String(raw || "");
  try {
    const parsed = JSON.parse(text) as unknown;
    const record = extractRecord(parsed);
    const stdout = recordStringField(record, ["stdout", "stdoutText"]);
    const stderr = recordStringField(record, ["stderr", "stderrText"]);
    const output = recordStringField(record, ["output", "text"]);
    const exitCode = recordNumberField(record, ["exitCode", "code", "status"]);
    if (stdout.length > 0 || stderr.length > 0 || output.length > 0) {
      return { stdout: stdout || output, stderr, output: output || [stdout, stderr].filter(Boolean).join("\n"), exitCode };
    }
  } catch {
    // Not a JSON wrapper; parse the Codex CLI tool-result envelope below.
  }

  const outputMatch = /(?:^|\n)Output:\n([\s\S]*)$/u.exec(text);
  const exitMatch = /Process exited with code\s+(-?\d+)/u.exec(text);
  if (outputMatch !== null) {
    const output = (outputMatch[1] ?? "").trimEnd();
    return {
      stdout: output,
      stderr: "",
      output,
      exitCode: exitMatch === null ? null : Number(exitMatch[1]),
    };
  }
  return { stdout: text, stderr: "", output: text, exitCode: exitMatch === null ? null : Number(exitMatch[1]) };
}

function formatCommandOutput(output: SessionCommandOutput | null | undefined): string {
  if (output === null || output === undefined) return "";
  const parts: string[] = [];
  const stdout = output.stdout.trimEnd();
  const stderr = output.stderr.trimEnd();
  if (stdout.length > 0) parts.push(stderr.length > 0 ? `[stdout]\n${stdout}` : stdout);
  if (stderr.length > 0) parts.push(`[stderr]\n${stderr}`);
  if (parts.length > 0) return parts.join("\n");
  return output.output.trimEnd();
}

function addCommandOutputStreams(line: TranscriptLine, output: SessionCommandOutput | null | undefined, fullText: boolean): TranscriptLine {
  if (output === null || output === undefined) return line;
  const stdout = output.stdout.trimEnd();
  const stderr = output.stderr.trimEnd();
  if (stdout.length > 0) {
    const preview = fullText ? completeTraceText(stdout) : outputPreview(stdout);
    if (preview.text.length > 0) {
      line.stdoutPreview = preview.text;
      line.stdoutOmittedLines = preview.omittedLines || undefined;
    }
  }
  if (stderr.length > 0) {
    const preview = fullText ? completeTraceText(stderr) : outputPreview(stderr);
    if (preview.text.length > 0) {
      line.stderrPreview = preview.text;
      line.stderrOmittedLines = preview.omittedLines || undefined;
    }
  }
  return line;
}

function parseCodexSessionCommandOutputs(path: string): Map<string, SessionCommandOutput> {
  const signature = codexSessionSignature(path);
  const cached = codexSessionCommandOutputCache.get(path);
  if (signature !== null && cached?.signature === signature) return cached.outputs;

  const outputs = new Map<string, SessionCommandOutput>();
  try {
    const text = readFileSync(path, "utf8");
    for (const line of text.split(/\r?\n/u)) {
      if (line.trim().length === 0) continue;
      let record: Record<string, unknown>;
      try {
        record = JSON.parse(line) as Record<string, unknown>;
      } catch {
        continue;
      }
      const payload = extractRecord(record.payload);
      if (payload === null) continue;
      const type = String(payload.type || "");
      if (type !== "function_call_output" && type !== "custom_tool_call_output") continue;
      const callId = typeof payload.call_id === "string" ? payload.call_id : "";
      if (callId.length === 0) continue;
      const parsed = parseToolOutputStreams(String(payload.output || ""));
      if (parsed.output.trim().length === 0 && parsed.stdout.trim().length === 0 && parsed.stderr.trim().length === 0) continue;
      outputs.set(callId, {
        callId,
        at: typeof record.timestamp === "string" ? record.timestamp : "",
        stdout: parsed.stdout,
        stderr: parsed.stderr,
        output: parsed.output,
        exitCode: parsed.exitCode,
      });
    }
  } catch (error) {
    ctx().logger("warn", "codex_session_command_output_parse_failed", { path, error: ctx().errorToJson(error) });
  }
  if (signature !== null) codexSessionCommandOutputCache.set(path, { signature, outputs });
  if (codexSessionCommandOutputCache.size > 40) {
    const firstKey = codexSessionCommandOutputCache.keys().next().value;
    if (typeof firstKey === "string") codexSessionCommandOutputCache.delete(firstKey);
  }
  return outputs;
}

function codexSessionCommandOutputsByCallId(task: QueueTask): Map<string, SessionCommandOutput> {
  const path = findCodexSessionFile(task);
  return path === null ? new Map() : parseCodexSessionCommandOutputs(path);
}

function isInlineFileChangeInput(name: string, input: string): boolean {
  return name === "apply_patch" && /^\*\*\* Begin Patch/mu.test(input);
}

function trimmedPatchForTrace(input: string): string {
  const normalized = input.replace(/\r\n/gu, "\n").replace(/\r/gu, "\n").trimEnd();
  const maxChars = 120_000;
  if (normalized.length <= maxChars) return normalized;
  return `${normalized.slice(0, maxChars)}\n...[patch content truncated: ${normalized.length - maxChars} chars omitted]`;
}

function parseCodexSessionFileChanges(path: string): Map<string, SessionFileChange> {
  const signature = codexSessionSignature(path);
  const cached = codexSessionFileChangeCache.get(path);
  if (signature !== null && cached?.signature === signature) return cached.changes;

  const changes = new Map<string, SessionFileChange>();
  try {
    const text = readFileSync(path, "utf8");
    for (const line of text.split(/\r?\n/u)) {
      if (line.trim().length === 0) continue;
      let record: Record<string, unknown>;
      try {
        record = JSON.parse(line) as Record<string, unknown>;
      } catch {
        continue;
      }
      const payload = extractRecord(record.payload);
      if (payload === null) continue;
      const type = String(payload.type || "");
      const callId = typeof payload.call_id === "string" ? payload.call_id : "";
      if (callId.length === 0) continue;
      if (type === "custom_tool_call") {
        const name = String(payload.name || "");
        const input = typeof payload.input === "string" ? payload.input : "";
        if (!isInlineFileChangeInput(name, input)) continue;
        changes.set(callId, {
          callId,
          at: typeof record.timestamp === "string" ? record.timestamp : "",
          name,
          input: trimmedPatchForTrace(input),
          output: "",
        });
        continue;
      }
      if (type === "custom_tool_call_output") {
        const existing = changes.get(callId);
        if (existing === undefined) continue;
        existing.output = parseCodexToolOutputText(String(payload.output || ""));
      }
    }
  } catch (error) {
    ctx().logger("warn", "codex_session_file_change_parse_failed", { path, error: ctx().errorToJson(error) });
  }
  if (signature !== null) codexSessionFileChangeCache.set(path, { signature, changes });
  if (codexSessionFileChangeCache.size > 40) {
    const firstKey = codexSessionFileChangeCache.keys().next().value;
    if (typeof firstKey === "string") codexSessionFileChangeCache.delete(firstKey);
  }
  return changes;
}

function codexSessionFileChangesByCallId(task: QueueTask): Map<string, SessionFileChange> {
  const path = findCodexSessionFile(task);
  return path === null ? new Map() : parseCodexSessionFileChanges(path);
}

function fileChangeTextWithInlinePatch(item: LiveOutput, changes: Map<string, SessionFileChange>): string {
  if (item.method !== "item/fileChange/outputDelta" || typeof item.itemId !== "string") return item.text;
  const change = changes.get(item.itemId);
  if (change === undefined || change.input.length === 0 || item.text.includes(change.input)) return item.text;
  return `${item.text.trimEnd()}\n\n${change.input}\n`;
}

function compactNoisyLine(line: string): string {
  const compact = line.replace(/\s+/gu, " ").trimEnd();
  const hasEncodedBlob = /[A-Za-z0-9+/=]{220,}/u.test(compact);
  const hasSshWrapper = compact.includes("UNIDESK_SSH_TOOL_DIR") || compact.includes("apply_patch") || compact.includes("base64 -d");
  if (compact.length > 420 && (hasEncodedBlob || hasSshWrapper)) {
    return `${compact.slice(0, 220)} ... [omitted noisy wrapper, ${compact.length - 220} chars]`;
  }
  return compact.length > 1200 ? `${compact.slice(0, 900)} ... [omitted ${compact.length - 900} chars]` : line;
}

function compactTranscriptBody(text: string): string {
  return text.split(/\r?\n/u).map(compactNoisyLine).join("\n");
}

function parseCommandLine(text: string): { command: string; status?: string } | null {
  const match = text.match(/^item\/(?:started|completed):\s+([\s\S]*?)\s+status=([A-Za-z0-9_-]+)/u);
  if (match === null) return null;
  return { command: match[1]?.trim() ?? "", status: match[2] };
}

function extractOuterQuotedShellArg(text: string): { body: string; trailing: string } | null {
  const quote = text[0];
  if (quote !== "\"" && quote !== "'") return null;
  let escaped = false;
  for (let index = 1; index < text.length; index += 1) {
    const char = text[index] ?? "";
    if (quote === "\"" && escaped) {
      escaped = false;
      continue;
    }
    if (quote === "\"" && char === "\\") {
      escaped = true;
      continue;
    }
    if (char === quote) return { body: text.slice(1, index), trailing: text.slice(index + 1).trim() };
  }
  return null;
}

function decodeShellDoubleQuoted(text: string): string {
  return text
    .replace(/\\(["\\$`])/gu, "$1")
    .replace(/\\\r?\n/gu, "");
}

function displayCommand(command: string): string {
  const normalized = command.trim().replace(/\\n/gu, "\n");
  const match = normalized.match(/^(?:\/usr\/bin\/env\s+)?(?:\/(?:usr\/)?bin\/)?(?:bash|sh)\s+-lc\s+([\s\S]+)$/u);
  if (match === null) return normalized;
  const shellText = (match[1] ?? "").trim();
  const shellArg = extractOuterQuotedShellArg(shellText);
  if (shellArg === null) return (match[1] ?? normalized).trim();
  const quote = shellText[0];
  const body = quote === "\"" ? decodeShellDoubleQuoted(shellArg.body) : shellArg.body;
  return shellArg.trailing.length > 0 ? `${body} ${shellArg.trailing}` : body;
}

function shortCommandTitle(command: string): string {
  const firstLine = displayCommand(command).split(/\r?\n/u).find((line) => line.trim().length > 0)?.trim() ?? command.trim();
  return safePreview(firstLine, 180);
}

function commandPreview(command: string): { text: string; omittedLines: number } {
  return linePreview(compactTranscriptBody(displayCommand(command)), 10, 8000);
}

function outputPreview(text: string): { text: string; omittedLines: number } {
  return linePreview(compactTranscriptBody(text), 4, 1600);
}

function fullMessageBody(text: string): { text: string; omittedLines: number } {
  return linePreview(text.replace(/\u001b\[[0-9;]*m/gu, "").trimEnd(), 12, 4000);
}

function timestampMs(value: string | null | undefined): number | null {
  if (typeof value !== "string" || value.length === 0) return null;
  const time = Date.parse(value);
  return Number.isFinite(time) ? time : null;
}

function nonNegativeElapsed(startMs: number | null, endMs: number | null): number | null {
  if (startMs === null || endMs === null) return null;
  return Math.max(0, endMs - startMs);
}

function taskTiming(task: QueueTask): JsonValue {
  const nowMs = Date.now();
  const createdMs = timestampMs(task.createdAt);
  const startedMs = timestampMs(task.startedAt);
  const finishedMs = timestampMs(task.finishedAt);
  const updatedMs = timestampMs(task.updatedAt);
  const terminal = task.status === "succeeded" || task.status === "failed" || task.status === "canceled";
  const effectiveEndMs = finishedMs ?? (terminal ? updatedMs : nowMs);
  return {
    queueWaitMs: nonNegativeElapsed(createdMs, startedMs ?? (terminal ? effectiveEndMs : nowMs)),
    durationMs: nonNegativeElapsed(startedMs, effectiveEndMs),
    totalElapsedMs: nonNegativeElapsed(createdMs, effectiveEndMs),
    effectiveEndAt: finishedMs !== null ? task.finishedAt : terminal ? task.updatedAt : null,
    running: !terminal && startedMs !== null,
  };
}

const codexStatsTimeZone = "Asia/Shanghai";
const codexStatsDateFormatter = new Intl.DateTimeFormat("en-CA", {
  timeZone: codexStatsTimeZone,
  year: "numeric",
  month: "2-digit",
  day: "2-digit",
});

interface DailyTaskStatsBucket {
  date: string;
  executedTasks: number;
  completedTasks: number;
  retryAttempts: number;
  succeededTasks: number;
  failedTasks: number;
  canceledTasks: number;
  totalDurationMs: number;
  durationSamples: number;
}

function codexStatsDateKey(value: string | Date | null | undefined): string | null {
  const date = value instanceof Date ? value : typeof value === "string" && value.length > 0 ? new Date(value) : null;
  if (date === null || Number.isNaN(date.getTime())) return null;
  const parts = codexStatsDateFormatter.formatToParts(date).reduce<Record<string, string>>((memo, part) => {
    if (part.type !== "literal") memo[part.type] = part.value;
    return memo;
  }, {});
  const year = parts.year;
  const month = parts.month;
  const day = parts.day;
  return year !== undefined && month !== undefined && day !== undefined ? `${year}-${month}-${day}` : null;
}

function shiftDateKey(dateKey: string, offsetDays: number): string {
  const [year = "1970", month = "01", day = "01"] = dateKey.split("-");
  const shifted = new Date(Date.UTC(Number(year), Number(month) - 1, Number(day) + offsetDays));
  return shifted.toISOString().slice(0, 10);
}

function statsDaysFromUrl(url: URL): number {
  const value = Number(url.searchParams.get("days") ?? 14);
  return Number.isInteger(value) && value > 0 ? Math.min(90, value) : 14;
}

function emptyDailyTaskStatsBucket(date: string): DailyTaskStatsBucket {
  return {
    date,
    executedTasks: 0,
    completedTasks: 0,
    retryAttempts: 0,
    succeededTasks: 0,
    failedTasks: 0,
    canceledTasks: 0,
    totalDurationMs: 0,
    durationSamples: 0,
  };
}

function retryAttemptDates(task: QueueTask): Array<string | null> {
  const attempts = Array.isArray(task.attempts) ? task.attempts : [];
  const retryAttempts = attempts.filter((attempt, index) => attempt.mode === "retry" || Number(attempt.index || 0) > 1 || index > 0);
  const fallbackRetryCount = Math.max(0, Math.floor(Number(task.currentAttempt || 0)) - 1);
  const fallbackAt = taskTimestamp(task.updatedAt) ?? taskTimestamp(task.startedAt) ?? taskTimestamp(task.createdAt);
  return [
    ...retryAttempts.map((attempt) => taskTimestamp(attempt.startedAt) ?? taskTimestamp(attempt.finishedAt) ?? fallbackAt),
    ...Array.from({ length: Math.max(0, fallbackRetryCount - retryAttempts.length) }, () => fallbackAt),
  ];
}

function completedTaskDurationMs(task: QueueTask, finishedAt: string): number | null {
  const startedAt = taskTimestamp(task.startedAt) ?? taskTimestamp(task.attempts[0]?.startedAt ?? null) ?? taskTimestamp(task.createdAt);
  return durationMsBetween(startedAt, finishedAt);
}

function taskStatisticsSummary(tasks: QueueTask[], days = 14): JsonValue {
  const generatedAt = ctx().nowIso();
  const endDate = codexStatsDateKey(new Date()) ?? generatedAt.slice(0, 10);
  const safeDays = Math.max(1, Math.min(90, Math.floor(days)));
  const startDate = shiftDateKey(endDate, 1 - safeDays);
  const buckets = new Map<string, DailyTaskStatsBucket>();
  for (let offset = 0; offset < safeDays; offset += 1) {
    const date = shiftDateKey(startDate, offset);
    buckets.set(date, emptyDailyTaskStatsBucket(date));
  }

  const bucketFor = (value: string | null): DailyTaskStatsBucket | null => {
    const date = codexStatsDateKey(value);
    return date === null ? null : buckets.get(date) ?? null;
  };

  for (const task of tasks) {
    const executedBucket = bucketFor(taskTimestamp(task.startedAt) ?? taskTimestamp(task.attempts[0]?.startedAt ?? null));
    if (executedBucket !== null) executedBucket.executedTasks += 1;

    for (const retryAt of retryAttemptDates(task)) {
      const retryBucket = bucketFor(retryAt);
      if (retryBucket !== null) retryBucket.retryAttempts += 1;
    }

    if (!terminalTask(task)) continue;
    const finishedAt = taskTimestamp(task.finishedAt) ?? taskTimestamp(task.updatedAt);
    const completedBucket = bucketFor(finishedAt);
    if (finishedAt === null || completedBucket === null) continue;
    completedBucket.completedTasks += 1;
    if (task.status === "succeeded") completedBucket.succeededTasks += 1;
    if (task.status === "failed") completedBucket.failedTasks += 1;
    if (task.status === "canceled") completedBucket.canceledTasks += 1;
    const durationMs = completedTaskDurationMs(task, finishedAt);
    if (durationMs !== null) {
      completedBucket.totalDurationMs += durationMs;
      completedBucket.durationSamples += 1;
    }
  }

  const daily = Array.from(buckets.values()).map((bucket) => ({
    date: bucket.date,
    executedTasks: bucket.executedTasks,
    completedTasks: bucket.completedTasks,
    retryAttempts: bucket.retryAttempts,
    succeededTasks: bucket.succeededTasks,
    failedTasks: bucket.failedTasks,
    canceledTasks: bucket.canceledTasks,
    avgDurationMs: bucket.durationSamples > 0 ? Math.round(bucket.totalDurationMs / bucket.durationSamples) : null,
    totalDurationMs: bucket.totalDurationMs,
    durationSamples: bucket.durationSamples,
  }));
  const totals = daily.reduce((memo, day) => {
    memo.executedTasks += day.executedTasks;
    memo.completedTasks += day.completedTasks;
    memo.retryAttempts += day.retryAttempts;
    memo.succeededTasks += day.succeededTasks;
    memo.failedTasks += day.failedTasks;
    memo.canceledTasks += day.canceledTasks;
    memo.totalDurationMs += day.totalDurationMs;
    memo.durationSamples += day.durationSamples;
    return memo;
  }, {
    executedTasks: 0,
    completedTasks: 0,
    retryAttempts: 0,
    succeededTasks: 0,
    failedTasks: 0,
    canceledTasks: 0,
    totalDurationMs: 0,
    durationSamples: 0,
  });
  return {
    generatedAt,
    timezone: codexStatsTimeZone,
    days: safeDays,
    range: { startDate, endDate },
    totals: {
      ...totals,
      avgDurationMs: totals.durationSamples > 0 ? Math.round(totals.totalDurationMs / totals.durationSamples) : null,
    },
    daily,
  } as unknown as JsonValue;
}

function transcriptLine(kind: TranscriptKind, at: string, seq: number, title: string, rawSeqs: number[], body = "", command = "", status?: string, fullText = false): TranscriptLine {
  const bodyInfo = fullText ? completeTraceText(body) : kind === "message" ? fullMessageBody(body) : kind === "edited" ? editedOutputPreview(body) : outputPreview(body);
  const commandInfo = command.length > 0 ? fullText ? completeTraceText(displayCommand(command)) : commandPreview(command) : { text: "", omittedLines: 0 };
  return {
    seq,
    at,
    kind,
    title,
    status,
    commandPreview: commandInfo.text || undefined,
    commandOmittedLines: commandInfo.omittedLines || undefined,
    bodyPreview: bodyInfo.text || undefined,
    bodyOmittedLines: bodyInfo.omittedLines || undefined,
    rawSeqs,
  };
}

function pushUniqueRawSeq(rawSeqs: number[], seq: number): void {
  if (!rawSeqs.includes(seq)) rawSeqs.push(seq);
}

function messageFragmentMergeKey(line: TranscriptLine): string | null {
  if (line.kind !== "message") return null;
  const title = String(line.title || "").trim().toLowerCase();
  if (title !== "assistant message" && title !== "reasoning") return null;
  return title;
}

function appendMessageText(left: string, right: string): string {
  if (left.length === 0) return right;
  if (right.length === 0) return left;
  if (!/\s$/u.test(left) && !/^\s|^[,.;:!?)}\]]/u.test(right) && /[A-Za-z0-9]/u.test(left.at(-1) || "") && /[A-Za-z0-9]/u.test(right[0] || "")) return `${left} ${right}`;
  return `${left}${right}`;
}

function mergeTranscriptMessageGroup(group: TranscriptLine[]): TranscriptLine {
  const first = group[0];
  const last = group[group.length - 1] || first;
  const body = group.reduce((text, line) => appendMessageText(text, String(line.bodyPreview || "")), "");
  const rawSeqs: number[] = [];
  for (const line of group) {
    for (const seq of Array.isArray(line.rawSeqs) ? line.rawSeqs : []) pushUniqueRawSeq(rawSeqs, seq);
  }
  return {
    ...first,
    seq: Number.isFinite(Number(last.seq)) ? Number(last.seq) : Number(first.seq),
    at: last.at || first.at,
    status: last.status || first.status,
    bodyPreview: body.length > 0 ? body : undefined,
    bodyOmittedLines: group.reduce((sum, line) => sum + Number(line.bodyOmittedLines || 0), 0) || undefined,
    rawSeqs,
  };
}

function coalesceTranscriptMessageFragments(entries: TranscriptLine[]): TranscriptLine[] {
  const rows = sortTranscript([...entries]);
  const merged: TranscriptLine[] = [];
  let group: TranscriptLine[] = [];
  let groupKey: string | null = null;
  const flush = () => {
    if (group.length === 0) return;
    merged.push(group.length === 1 ? group[0] : mergeTranscriptMessageGroup(group));
    group = [];
    groupKey = null;
  };
  for (const line of rows) {
    const key = messageFragmentMergeKey(line);
    if (key !== null && key === groupKey) {
      group.push(line);
      continue;
    }
    flush();
    if (key !== null) {
      group = [line];
      groupKey = key;
    } else {
      merged.push(line);
    }
  }
  flush();
  return merged;
}

function traceMessageOverlayKey(line: TranscriptLine): string | null {
  return messageFragmentMergeKey(line);
}

function traceMessageOverlayCandidate(line: TranscriptLine): boolean {
  return traceMessageOverlayKey(line) !== null && String(line.bodyPreview || "").trim().length > 0;
}

function overlayTraceMessagesFromRawTranscript(oaLines: TranscriptLine[], rawLines: TranscriptLine[]): TranscriptLine[] {
  const rawMessages = rawLines.filter(traceMessageOverlayCandidate);
  if (rawMessages.length === 0) return oaLines;
  const messageSeqs = new Set<number>();
  for (const line of oaLines) {
    if (traceMessageOverlayKey(line) === null) continue;
    for (const seq of Array.isArray(line.rawSeqs) && line.rawSeqs.length > 0 ? line.rawSeqs : [line.seq]) {
      if (Number.isFinite(Number(seq))) messageSeqs.add(Number(seq));
    }
  }
  const result = oaLines.filter((line) => traceMessageOverlayKey(line) === null);
  for (const raw of rawMessages) {
    const seqs = Array.isArray(raw.rawSeqs) && raw.rawSeqs.length > 0 ? raw.rawSeqs : [raw.seq];
    if (!seqs.some((seq) => messageSeqs.has(Number(seq)))) continue;
    result.push(raw);
  }
  return coalesceTranscriptMessageFragments(result);
}


function commandKind(command: string): TranscriptKind {
  if (/\bwebSearch\b/u.test(command)) return "explored";
  if (/\b(apply_patch|git apply|cat >|tee .*<<|sed -i|python3? .*write_text)\b/u.test(command)) return "edited";
  if (/\b(rg|grep|find|ls|cat|sed -n|tail|head|git status|git diff|ps)\b/u.test(command)) return "explored";
  return "ran";
}

function commandKindLabel(kind: TranscriptKind): string {
  if (kind === "edited") return "Edited";
  if (kind === "explored") return "Explored";
  return "Ran";
}

function jsonPreview(value: unknown, max = 4000): string {
  try {
    return safePreview(JSON.stringify(value), max);
  } catch {
    return safePreview(String(value ?? ""), max);
  }
}

function recordDisplayField(record: Record<string, unknown> | null, keys: string[], max = 3000): string {
  if (record === null) return "";
  for (const key of keys) {
    const value = record[key];
    if (typeof value === "string") return value;
    if (value !== undefined && value !== null) return jsonPreview(value, max);
  }
  return "";
}

function decodeJsonStringFragment(value: string): string {
  try {
    return JSON.parse(`"${value}"`) as string;
  } catch {
    return value
      .replace(/\\"/gu, "\"")
      .replace(/\\\\/gu, "\\")
      .replace(/\\n/gu, "\n")
      .replace(/\\r/gu, "\r")
      .replace(/\\t/gu, "\t");
  }
}

function partialJsonStringField(text: string, key: string): string {
  const match = new RegExp(`"${key}"\\s*:\\s*"`, "u").exec(text);
  if (match === null) return "";
  const start = match.index + match[0].length;
  let escaped = false;
  for (let index = start; index < text.length; index += 1) {
    const char = text[index] ?? "";
    if (escaped) {
      escaped = false;
      continue;
    }
    if (char === "\\") {
      escaped = true;
      continue;
    }
    if (char === "\"") return decodeJsonStringFragment(text.slice(start, index));
  }
  return decodeJsonStringFragment(text.slice(start).replace(/\s*\.\.\.\s*$/u, ""));
}

function partialJsonNumberField(text: string, key: string): number | null {
  const match = new RegExp(`"${key}"\\s*:\\s*(-?\\d+(?:\\.\\d+)?)`, "u").exec(text);
  if (match === null) return null;
  const value = Number(match[1]);
  return Number.isFinite(value) ? value : null;
}

function openCodePartialRecordFromOutput(item: LiveOutput): Record<string, unknown> | null {
  if (!String(item.method || "").startsWith("opencode/")) return null;
  const text = item.text.trim();
  if (!text.includes("\"part\"") && !text.includes("\"tool\"")) return null;
  const tool = partialJsonStringField(text, "tool");
  const command = partialJsonStringField(text, "command") || partialJsonStringField(text, "cmd") || partialJsonStringField(text, "script");
  const output = partialJsonStringField(text, "output") || partialJsonStringField(text, "result");
  if (tool.length === 0 && command.length === 0 && output.length === 0) return null;
  const input: Record<string, unknown> = {};
  for (const key of ["command", "cmd", "script", "filePath", "filepath", "path", "pattern", "query", "title", "description"]) {
    const value = partialJsonStringField(text, key);
    if (value.length > 0) input[key] = value;
  }
  for (const key of ["offset", "limit"]) {
    const value = partialJsonNumberField(text, key);
    if (value !== null) input[key] = value;
  }
  return {
    type: partialJsonStringField(text, "type") || "tool_use",
    part: {
      type: "tool",
      tool: tool || "tool",
      state: {
        status: partialJsonStringField(text, "status"),
        input,
        output,
      },
    },
  };
}

function openCodeRecordFromOutput(item: LiveOutput): Record<string, unknown> | null {
  if (!String(item.method || "").startsWith("opencode/")) return null;
  try {
    return extractRecord(JSON.parse(item.text) as unknown);
  } catch {
    return openCodePartialRecordFromOutput(item);
  }
}

function openCodeToolInputCommand(tool: string, input: Record<string, unknown> | null): string {
  const command = recordStringField(input, ["command", "cmd", "script"]);
  if (command.length > 0) return command;
  const path = recordStringField(input, ["filePath", "filepath", "path"]);
  const pattern = recordStringField(input, ["pattern", "query"]);
  const offset = recordNumberField(input, ["offset"]);
  const limit = recordNumberField(input, ["limit"]);
  const args: string[] = [tool];
  if (pattern.length > 0) args.push(pattern);
  if (path.length > 0) args.push(path);
  if (offset !== null) args.push(`offset=${offset}`);
  if (limit !== null) args.push(`limit=${limit}`);
  if (args.length > 1) return args.join(" ");
  return input === null ? tool : `${tool} ${jsonPreview(input, 1200)}`;
}

function openCodeToolKind(tool: string, command: string): TranscriptKind {
  const normalized = `${tool} ${command}`.toLowerCase();
  if (/\b(read|grep|glob|list|ls|find|search|view|cat|sed|rg)\b/u.test(normalized)) return "explored";
  if (/\b(edit|write|patch|apply|update|create|delete|apply_patch|git apply|sed -i)\b/u.test(normalized)) return "edited";
  return commandKind(command);
}

function openCodeToolTitle(tool: string, command: string, input: Record<string, unknown> | null): string {
  const title = recordStringField(input, ["title", "description"]);
  if (title.length > 0) return safePreview(title, 180);
  const path = recordStringField(input, ["filePath", "filepath", "path"]);
  if (path.length > 0) return `${commandKindLabel(openCodeToolKind(tool, command))} ${path}`;
  return shortCommandTitle(command || tool);
}

function openCodeToolDurationMs(part: Record<string, unknown> | null, state: Record<string, unknown> | null): number | undefined {
  const explicit = recordNumberField(part, ["durationMs", "elapsedMs"]) ?? recordNumberField(state, ["durationMs", "elapsedMs"]);
  if (explicit !== null && explicit >= 0) return explicit;
  const time = extractRecord(state?.time) ?? extractRecord(part?.time);
  const start = recordNumberField(time, ["start", "startedAt"]);
  const end = recordNumberField(time, ["end", "finishedAt", "completedAt"]);
  return start !== null && end !== null && end >= start ? end - start : undefined;
}

function isOpenCodeStepBoundaryMethod(method: string | undefined): boolean {
  return method === "opencode/step-start" || method === "opencode/step-finish";
}

function openCodeVisibleAssistantText(text: string): string {
  return String(text || "").replace(/<(?:think|thinking)\b[^>]*>[\s\S]*?<\/(?:think|thinking)>/giu, "").trim();
}

function openCodeToolTranscriptLine(item: LiveOutput, fullText: boolean): TranscriptLine | null {
  const record = openCodeRecordFromOutput(item);
  const part = extractRecord(record?.part);
  if (record === null || part === null) return null;
  const recordType = recordStringField(record, ["type", "event", "name"]).toLowerCase();
  const partType = recordStringField(part, ["type"]).toLowerCase();
  if (recordType === "step_start" || recordType === "step-start" || partType === "step-start") return null;
  if (recordType === "step_finish" || recordType === "step-finish" || partType === "step-finish") return null;
  const state = extractRecord(part.state);
  const input = extractRecord(state?.input) ?? extractRecord(part.input);
  const tool = recordStringField(part, ["tool", "title"]) || recordStringField(record, ["type", "event", "name"]) || "tool";
  const command = openCodeToolInputCommand(tool, input);
  const metadata = extractRecord(state?.metadata);
  const filediff = extractRecord(metadata?.filediff);
  const rawOutput = recordDisplayField(state, ["output", "result"]) || recordDisplayField(part, ["output", "text", "content"]) || recordDisplayField(record, ["output", "text", "content"]);
  const diffOutput = recordDisplayField(metadata, ["diff"]) || recordDisplayField(filediff, ["patch"]);
  const status = recordStringField(state, ["status"]) || recordStringField(part, ["status"]) || recordStringField(record, ["status"]);
  const kind = openCodeToolKind(tool, command);
  const body = kind === "edited" && diffOutput.length > 0 ? diffOutput : rawOutput.length > 0 ? rawOutput : jsonPreview(record, 3000);
  const line = transcriptLine(kind, item.at, item.seq, openCodeToolTitle(tool, command, input), [item.seq], body, command, status || item.method, fullText);
  const durationMs = openCodeToolDurationMs(part, state);
  if (durationMs !== undefined) line.durationMs = durationMs;
  return line;
}

function promptLineCount(text: string): number {
  return text.length > 0 ? text.split(/\r\n|\r|\n/u).length : 0;
}

function promptSnapshot(text: string, maxPreviewChars = 1200): { text: string; preview: string; chars: number; lines: number; truncated: boolean } {
  const normalized = text.trimEnd();
  const preview = safePreview(normalized, maxPreviewChars);
  return {
    text: normalized,
    preview,
    chars: normalized.length,
    lines: promptLineCount(normalized),
    truncated: preview.length < normalized.length,
  };
}

function setAttemptInputPrompt(attempt: AttemptSummary, prompt: string): void {
  const snapshot = promptSnapshot(prompt, 1200);
  if (snapshot.chars === 0) return;
  attempt.inputPrompt = snapshot.text;
  attempt.inputPromptPreview = snapshot.preview;
  attempt.inputPromptChars = snapshot.chars;
  attempt.inputPromptLines = snapshot.lines;
}

function setAttemptFeedbackPrompt(attempt: AttemptSummary | undefined, prompt: string, source: string, forAttempt: number | null): void {
  if (attempt === undefined) return;
  const snapshot = promptSnapshot(prompt, 1600);
  if (snapshot.chars === 0) return;
  attempt.feedbackPrompt = snapshot.text;
  attempt.feedbackPromptPreview = snapshot.preview;
  attempt.feedbackPromptChars = snapshot.chars;
  attempt.feedbackPromptLines = snapshot.lines;
  attempt.feedbackPromptSource = source;
  attempt.feedbackPromptForAttempt = forAttempt;
}

function taskInitialPromptLine(task: QueueTask, fullText = false): TranscriptLine | null {
  const prompt = (task.basePrompt || userPromptForDisplay(task.prompt)).trimEnd();
  if (prompt.length === 0) return null;
  const line = transcriptLine("message", task.createdAt, 0.5, "Submitted prompt", [], prompt, "", "enqueue", fullText);
  const fullPrompt = task.prompt.trimEnd();
  if (fullText && fullPrompt.length > 0 && fullPrompt !== prompt) {
    line.fullPrompt = fullPrompt;
    line.fullPromptLines = promptLineCount(fullPrompt);
    line.fullPromptChars = fullPrompt.length;
    line.foldedReferencePrompt = true;
  }
  return line;
}

function promptHistoryTranscriptLines(task: QueueTask, fullText = false): TranscriptLine[] {
  return ctx().mergePromptHistory([...(Array.isArray(task.promptHistory) ? task.promptHistory : []), ...ctx().outputPromptHistory(task)])
    .map((item) => transcriptLine("message", item.at, item.seq, "Steer prompt", [item.seq], item.text, "", item.method, fullText));
}

function sortTranscript(entries: TranscriptLine[]): TranscriptLine[] {
  return entries.sort((left, right) => Number(left.seq) - Number(right.seq));
}

function boundedTranscript(entries: TranscriptLine[], limit: number): TranscriptLine[] {
  sortTranscript(entries);
  if (entries.length <= limit) return entries;
  const first = entries[0];
  if (first?.title === "Submitted prompt" && first.rawSeqs.length === 0 && limit > 1) {
    return [first, ...entries.slice(-(limit - 1))];
  }
  return entries.slice(-limit);
}

function buildTaskTranscript(task: QueueTask, limit = 180, rawOutputWindow = 0, fullText = false): TranscriptLine[] {
  const entries: TranscriptLine[] = [];
  const initialPrompt = taskInitialPromptLine(task, fullText);
  if (initialPrompt !== null) entries.push(initialPrompt);
  const promptHistoryLines = promptHistoryTranscriptLines(task, fullText);
  const promptHistorySeqs = new Set(promptHistoryLines.map((line) => line.seq));
  entries.push(...promptHistoryLines);
  type ActiveCommand = { seq: number; at: string; command: string; status?: string; body: string; rawSeqs: number[]; itemId?: string };
  let activeCommand: ActiveCommand | null = null;
  const activeCommandsByItemId = new Map<string, ActiveCommand>();

  const pushRawSeq = (command: ActiveCommand, seq: number): void => {
    if (!command.rawSeqs.includes(seq)) command.rawSeqs.push(seq);
  };

  const flushCommand = (command: ActiveCommand | null = activeCommand): void => {
    if (command === null) return;
    const kind = commandKind(command.command);
    const output = command.itemId === undefined ? null : commandOutputs.get(command.itemId) ?? null;
    const body = command.body.length > 0 ? command.body : formatCommandOutput(output);
    const title = command.command.trim().length > 0 ? shortCommandTitle(command.command) : "Command output";
    entries.push(addCommandOutputStreams(transcriptLine(
      kind,
      command.at,
      command.seq,
      title,
      command.rawSeqs,
      body,
      command.command,
      command.status,
      fullText,
    ), output, fullText));
    if (command === activeCommand) activeCommand = null;
    if (command.itemId !== undefined && activeCommandsByItemId.get(command.itemId) === command) {
      activeCommandsByItemId.delete(command.itemId);
    }
  };

  const itemIdCommand = (item: LiveOutput, parsed: { command: string; status?: string } | null = null): ActiveCommand | null => {
    if (typeof item.itemId !== "string" || item.itemId.length === 0) return null;
    let command = activeCommandsByItemId.get(item.itemId);
    if (command === undefined) {
      command = {
        seq: item.seq,
        at: item.at,
        command: parsed?.command ?? "",
        status: parsed?.status,
        body: "",
        rawSeqs: [],
        itemId: item.itemId,
      };
      activeCommandsByItemId.set(item.itemId, command);
    }
    return command;
  };

  const outputSource = rawOutputWindow > 0 ? task.output : taskFullOutput(task);
  const outputItems = rawOutputWindow > 0 && outputSource.length > rawOutputWindow
    ? outputSource.slice(-rawOutputWindow)
    : outputSource;
  const commandOutputs = outputItems.some((item) => item.channel === "command" && typeof item.itemId === "string")
    ? codexSessionCommandOutputsByCallId(task)
    : new Map<string, SessionCommandOutput>();
  const fileChangeInputs = outputItems.some((item) => item.channel === "diff" && item.method === "item/fileChange/outputDelta" && typeof item.itemId === "string")
    ? codexSessionFileChangesByCallId(task)
    : new Map<string, SessionFileChange>();
  type ActiveMessage = { seq: number; at: string; title: string; status?: string; body: string; rawSeqs: number[] };
  type ActiveCodexTool = { seq: number; at: string; text: string; status?: string; rawSeqs: number[]; itemId?: string };
  let activeMessage: ActiveMessage | null = null;
  const activeCodexToolsByItemId = new Map<string, ActiveCodexTool>();

  const flushMessage = (): void => {
    if (activeMessage === null) return;
    entries.push(transcriptLine("message", activeMessage.at, activeMessage.seq, activeMessage.title, activeMessage.rawSeqs, activeMessage.body, "", activeMessage.status, fullText));
    activeMessage = null;
  };

  const appendMessage = (item: LiveOutput, title: string, body: string, status?: string): void => {
    if (body.length === 0) return;
    if (activeMessage !== null && activeMessage.title === title && activeMessage.status === status) {
      activeMessage.body += body;
      activeMessage.at = item.at;
      activeMessage.seq = item.seq;
      pushUniqueRawSeq(activeMessage.rawSeqs, item.seq);
      return;
    }
    flushMessage();
    activeMessage = { seq: item.seq, at: item.at, title, status, body, rawSeqs: [item.seq] };
  };

  const parseCodexToolLifecycle = (item: LiveOutput): { status: string | undefined; text: string } => {
    const status = /\bstatus=([A-Za-z0-9_-]+)/u.exec(item.text)?.[1];
    return { status, text: String(item.text || "").trimEnd() };
  };

  const codexToolLifecycleLine = (tool: ActiveCodexTool): TranscriptLine => {
    const kind = commandKind(tool.text);
    return transcriptLine(kind, tool.at, tool.seq, shortCommandTitle(tool.text), tool.rawSeqs, "", tool.text, tool.status, fullText);
  };

  const flushCodexTool = (tool: ActiveCodexTool): void => {
    entries.push(codexToolLifecycleLine(tool));
    if (tool.itemId !== undefined && activeCodexToolsByItemId.get(tool.itemId) === tool) activeCodexToolsByItemId.delete(tool.itemId);
  };

  for (const item of outputItems) {
    if (initialPrompt !== null && item.channel === "user" && item.method === "enqueue") continue;
    if (item.channel === "user" && item.method === "turn/steer" && promptHistorySeqs.has(item.seq)) continue;
    if (item.channel === "user" && item.method === "turn/resume") continue;
    if (isOpenCodeStepBoundaryMethod(item.method)) continue;
    if (item.channel === "command" && item.method === "item/started") {
      flushMessage();
      const parsed = parseCommandLine(item.text);
      const groupedCommand = itemIdCommand(item, parsed);
      if (groupedCommand !== null) {
        flushCommand();
        groupedCommand.seq = item.seq;
        groupedCommand.at = item.at;
        groupedCommand.command = parsed?.command || item.text;
        groupedCommand.status = parsed?.status;
        pushRawSeq(groupedCommand, item.seq);
        continue;
      }
      flushCommand();
      activeCommand = {
        seq: item.seq,
        at: item.at,
        command: parsed?.command || item.text,
        status: parsed?.status,
        body: "",
        rawSeqs: [item.seq],
        ...(typeof item.itemId === "string" ? { itemId: item.itemId } : {}),
      };
      continue;
    }
    if (item.channel === "command" && item.method === "item/commandExecution/outputDelta") {
      flushMessage();
      const groupedCommand = itemIdCommand(item);
      if (groupedCommand !== null) {
        groupedCommand.body += item.text;
        pushRawSeq(groupedCommand, item.seq);
      } else if (activeCommand !== null) {
        activeCommand.body += item.text;
        pushRawSeq(activeCommand, item.seq);
      } else {
        const output = typeof item.itemId === "string" ? commandOutputs.get(item.itemId) ?? null : null;
        entries.push(addCommandOutputStreams(transcriptLine("ran", item.at, item.seq, "Command output", [item.seq], item.text || formatCommandOutput(output), "", undefined, fullText), output, fullText));
      }
      continue;
    }
    if (item.channel === "command" && item.method === "item/completed") {
      flushMessage();
      const parsed = parseCommandLine(item.text);
      const groupedCommand = itemIdCommand(item, parsed);
      if (groupedCommand !== null) {
        if (parsed?.command) groupedCommand.command = parsed.command;
        groupedCommand.status = parsed?.status ?? groupedCommand.status;
        pushRawSeq(groupedCommand, item.seq);
        flushCommand(groupedCommand);
      } else if (activeCommand !== null) {
        activeCommand.status = parsed?.status ?? activeCommand.status;
        pushRawSeq(activeCommand, item.seq);
        flushCommand();
      } else {
        const command = parsed?.command || item.text;
        const kind = commandKind(command);
        const output = typeof item.itemId === "string" ? commandOutputs.get(item.itemId) ?? null : null;
        entries.push(addCommandOutputStreams(transcriptLine(kind, item.at, item.seq, shortCommandTitle(command), [item.seq], formatCommandOutput(output), command, parsed?.status, fullText), output, fullText));
      }
      continue;
    }

    if (item.channel !== "assistant" && item.channel !== "reasoning") flushMessage();
    flushCommand();
    if (isCodexToolLifecycleOutput(item)) {
      const parsed = parseCodexToolLifecycle(item);
      const itemId = item.itemId || "";
      const existing = activeCodexToolsByItemId.get(itemId);
      if (item.method === "item/started") {
        if (existing !== undefined) flushCodexTool(existing);
        activeCodexToolsByItemId.set(itemId, {
          seq: item.seq,
          at: item.at,
          text: parsed.text,
          status: parsed.status ?? item.method,
          rawSeqs: [item.seq],
          itemId,
        });
      } else if (existing !== undefined) {
        existing.at = item.at;
        existing.status = parsed.status ?? existing.status;
        existing.text = parsed.text.length > 0 ? parsed.text : existing.text;
        pushUniqueRawSeq(existing.rawSeqs, item.seq);
        flushCodexTool(existing);
      } else {
        entries.push(codexToolLifecycleLine({
          seq: item.seq,
          at: item.at,
          text: parsed.text,
          status: parsed.status ?? item.method,
          rawSeqs: [item.seq],
          itemId,
        }));
      }
    } else if (item.channel === "diff") {
      const text = fileChangeTextWithInlinePatch(item, fileChangeInputs);
      entries.push(transcriptLine("edited", item.at, item.seq, "Edited files", [item.seq], text, "", item.method, fullText));
    } else if (item.channel === "error") {
      entries.push(transcriptLine("error", item.at, item.seq, "Error", [item.seq], item.text, "", item.method, fullText));
    } else if (item.channel === "assistant") {
      const body = String(item.method || "").startsWith("opencode/") ? openCodeVisibleAssistantText(item.text) : item.text;
      appendMessage(item, "Assistant message", body, item.method);
    } else if (item.channel === "reasoning") {
      appendMessage(item, "Reasoning", item.text, item.method);
    } else if (item.channel === "user") {
      entries.push(transcriptLine("message", item.at, item.seq, item.method === "enqueue" ? "Submitted prompt" : "User prompt", [item.seq], item.text, "", item.method, fullText));
    } else if (item.channel === "tool" && String(item.method || "").startsWith("opencode/")) {
      entries.push(openCodeToolTranscriptLine(item, fullText) ?? transcriptLine("system", item.at, item.seq, "OpenCode tool", [item.seq], item.text, "", item.method, fullText));
    } else {
      const title = item.method === "queue" && item.text.startsWith("attempt ")
        ? "Attempt started"
        : item.method === "startup" || item.method === "shutdown"
          ? "Recovered thread execution"
          : item.method === "judge"
            ? "Judge result"
            : "System";
      entries.push(transcriptLine("system", item.at, item.seq, title, [item.seq], item.text, "", item.method, fullText));
    }
  }
  flushMessage();
  flushCommand();
  for (const command of Array.from(activeCommandsByItemId.values()).sort((left, right) => left.seq - right.seq)) {
    flushCommand(command);
  }
  for (const tool of Array.from(activeCodexToolsByItemId.values()).sort((left, right) => left.seq - right.seq)) {
    flushCodexTool(tool);
  }
  return boundedTranscript(coalesceTranscriptMessageFragments(entries), limit);
}

function buildCompactTaskTranscript(task: QueueTask, limit = 12, rawOutputWindow = 24): TranscriptLine[] {
  return buildTaskTranscript(task, limit, rawOutputWindow, false);
}

function transcriptSignature(task: QueueTask): string {
  const last = task.output.at(-1);
  return `${task.updatedAt}:${task.output.length}:${last?.seq ?? 0}:${last?.text.length ?? 0}:${outputArchiveSignature(task)}:${task.status}:${task.createdAt}:${task.basePrompt.length}:${task.prompt.length}:${task.promptHistory.length}:${task.promptHistory.at(-1)?.seq ?? 0}`;
}

function cachedTranscript(task: QueueTask, fullText: boolean): TranscriptLine[] {
  const signature = transcriptSignature(task);
  const cached = transcriptCache.get(task.id);
  if (cached?.signature === signature) {
    const cachedTranscript = fullText ? cached.fullTranscript : cached.previewTranscript;
    if (cachedTranscript !== undefined) return cachedTranscript;
  }
  const transcript = buildTaskTranscript(task, Number.MAX_SAFE_INTEGER, 0, fullText);
  const next: { signature: string; previewTranscript?: TranscriptLine[]; fullTranscript?: TranscriptLine[] } = cached?.signature === signature ? cached : { signature };
  if (fullText) next.fullTranscript = transcript;
  else next.previewTranscript = transcript;
  transcriptCache.set(task.id, next);
  if (transcriptCache.size > 80) {
    const firstKey = transcriptCache.keys().next().value;
    if (typeof firstKey === "string") transcriptCache.delete(firstKey);
  }
  return transcript;
}

function cachedFullTranscript(task: QueueTask): TranscriptLine[] {
  return cachedTranscript(task, true);
}

function cachedPreviewTranscript(task: QueueTask): TranscriptLine[] {
  return cachedTranscript(task, false);
}

function outputForResponse(task: QueueTask, includeRaw: boolean): LiveOutput[] {
  const output = includeRaw ? taskFullOutput(task) : task.output.slice(-80);
  return output.map((item) => ({
    ...item,
    text: includeRaw ? sanitizeTaskOutputText(item.text) : safePreview(sanitizeTaskOutputText(item.text), 4000),
  }));
}

function attemptForResponse(attempt: AttemptSummary, full = false): JsonValue {
  const finalResponse = String(attempt.finalResponse ?? "");
  const inputPrompt = String(attempt.inputPrompt ?? "");
  const feedbackPrompt = String(attempt.feedbackPrompt ?? "");
  return {
    ...attempt,
    inputPrompt: full ? inputPrompt : undefined,
    inputPromptPreview: safePreview(String(attempt.inputPromptPreview || inputPrompt), full ? 3000 : 1200),
    inputPromptChars: Number(attempt.inputPromptChars ?? inputPrompt.length),
    inputPromptLines: Number(attempt.inputPromptLines ?? promptLineCount(inputPrompt)),
    finalResponse: full ? finalResponse : safePreview(finalResponse, 1200),
    finalResponsePreview: safePreview(String(attempt.finalResponsePreview || finalResponse), full ? 3000 : 1200),
    finalResponseChars: Number(attempt.finalResponseChars ?? finalResponse.length),
    feedbackPrompt: full ? feedbackPrompt : undefined,
    feedbackPromptPreview: safePreview(String(attempt.feedbackPromptPreview || feedbackPrompt), full ? 3000 : 1200),
    feedbackPromptChars: Number(attempt.feedbackPromptChars ?? feedbackPrompt.length),
    feedbackPromptLines: Number(attempt.feedbackPromptLines ?? promptLineCount(feedbackPrompt)),
    stderrTail: full ? attempt.stderrTail : safePreview(attempt.stderrTail, 1200),
  } as unknown as JsonValue;
}

function taskForResponse(task: QueueTask, full = false, includeRaw = full): JsonValue {
  const displayPrompt = task.basePrompt || userPromptForDisplay(task.prompt);
  return {
    ...task,
    agentPort: codeAgentPortForModel(task.model),
    agentPortInfo: codeAgentPortInfo(codeAgentPortForModel(task.model)),
    judgeFailRetryLimit,
    stepCount: null,
    llmStepCount: null,
    traceStats: null,
    statsSource: "unavailable",
    prompt: full ? task.prompt : safePreview(task.prompt, 2000),
    basePrompt: full ? task.basePrompt : safePreview(task.basePrompt, 2000),
    displayPrompt: full ? displayPrompt : safePreview(displayPrompt, 2000),
    promptEditable: ctx().queuedTaskPromptEditable(task),
    ...queuedStatusPayload(task),
    referenceTaskIds: task.referenceTaskIds,
    referenceInjection: task.referenceInjection,
    finalResponse: full ? task.finalResponse : safePreview(task.finalResponse, 5000),
    terminalUnread: terminalTaskUnread(task),
    attempts: task.attempts.map((attempt) => attemptForResponse(attempt, full)),
    output: outputForResponse(task, includeRaw),
    events: includeRaw ? task.events : task.events.slice(-120),
    transcript: full ? fullTranscript(task) : buildTaskTranscript(task, 120, 0),
  } as unknown as JsonValue;
}

function fullTranscript(task: QueueTask): TranscriptLine[] {
  return cachedFullTranscript(task);
}

function nonNegativeInteger(value: unknown): number | null {
  const parsed = Number(value);
  return Number.isFinite(parsed) && parsed >= 0 ? Math.floor(parsed) : null;
}

function retainedOutputStartsTraceStep(output: LiveOutput): boolean {
  if (output.channel === "diff" || output.channel === "tool") return true;
  if (output.channel !== "command") return false;
  const method = String(output.method || "");
  return method === "item/started" || (method !== "item/commandExecution/outputDelta" && method !== "item/completed");
}

function retainedTaskStepCount(task: QueueTask): number {
  return (Array.isArray(task.output) ? task.output : []).reduce((count, output) => count + (retainedOutputStartsTraceStep(output) ? 1 : 0), 0);
}

function taskStoredStepCount(task: QueueTask): number | null {
  return nonNegativeInteger(task.stepCount) ?? nonNegativeInteger(task.llmStepCount);
}

// Used only as a producer-side seed for OA stats snapshots; frontend/API
// display authority is the oa_trace_stats projection applied at route edges.
function taskListStepCount(task: QueueTask): number {
  return taskStoredStepCount(task) ?? retainedTaskStepCount(task);
}

function taskOutputMaxSeq(task: QueueTask): number {
  const output = Array.isArray(task.output) ? task.output : [];
  const promptHistory = Array.isArray(task.promptHistory) ? task.promptHistory : [];
  const attempts = Array.isArray(task.attempts) ? task.attempts : [];
  const values = [
    nonNegativeInteger(task.outputMaxSeq),
    nonNegativeInteger(output.at(-1)?.seq),
    nonNegativeInteger(promptHistory.at(-1)?.seq),
    ...attempts.map((attempt) => nonNegativeInteger(attempt.outputEndSeq)),
  ].filter((value): value is number => value !== null);
  return values.length > 0 ? Math.max(...values) : 0;
}

function taskForMetaResponse(task: QueueTask): JsonValue {
  const lastOutputSeq = taskOutputMaxSeq(task);
  const displayPrompt = task.basePrompt || userPromptForDisplay(task.prompt);
  return {
    id: task.id,
    queueId: ctx().queueIdOf(task),
    queueEnteredAt: ctx().taskQueueEnteredAt(task),
    prompt: task.prompt,
    basePrompt: task.basePrompt,
    displayPrompt,
    promptChars: task.prompt.length,
    basePromptChars: task.basePrompt.length,
    displayPromptChars: displayPrompt.length,
    promptEditable: ctx().queuedTaskPromptEditable(task),
    finalResponseChars: task.finalResponse.length,
    stepCount: null,
    llmStepCount: null,
    traceStats: null,
    statsSource: "unavailable",
    summaryOnly: false,
    referenceTaskIds: task.referenceTaskIds,
    referenceInjection: task.referenceInjection,
    providerId: task.providerId,
    executionMode: task.executionMode,
    requestedExecutionMode: task.requestedExecutionMode ?? null,
    executionModeInfo: codeExecutionModeInfo(task.executionMode),
    cwd: task.cwd,
    model: task.model,
    agentPort: codeAgentPortForModel(task.model),
    agentPortInfo: codeAgentPortInfo(codeAgentPortForModel(task.model)),
    reasoningEffort: task.reasoningEffort,
    maxAttempts: task.maxAttempts,
    status: task.status,
    ...queuedStatusPayload(task),
    createdAt: task.createdAt,
    updatedAt: task.updatedAt,
    startedAt: task.startedAt,
    finishedAt: task.finishedAt,
    readAt: task.readAt,
    currentAttempt: task.currentAttempt,
    currentMode: task.currentMode,
    judgeFailCount: task.judgeFailCount,
    judgeFailRetryLimit,
    codexThreadId: task.codexThreadId,
    activeTurnId: task.activeTurnId,
    schedulerHeartbeat: task.schedulerHeartbeat ?? null,
    finalResponse: task.finalResponse,
    lastError: task.lastError,
    lastJudge: task.lastJudge,
    promptHistory: task.promptHistory,
    attempts: task.attempts,
    cancelRequested: task.cancelRequested,
    terminalUnread: terminalTaskUnread(task),
    nextMode: task.nextMode,
    outputCount: task.output.length,
    retainedOutputCount: task.output.length,
    eventCount: task.events.length,
    transcriptCount: null,
    transcriptMaxSeq: lastOutputSeq,
    timing: taskTiming(task),
    transcript: [],
    output: [],
    events: [],
  } as unknown as JsonValue;
}

function taskForCompactMetaResponse(task: QueueTask): JsonValue {
  const displayPrompt = task.basePrompt || userPromptForDisplay(task.prompt);
  const lastOutputSeq = taskOutputMaxSeq(task);
  return {
    id: task.id,
    queueId: ctx().queueIdOf(task),
    queueEnteredAt: ctx().taskQueueEnteredAt(task),
    prompt: prefixPreview(task.prompt, 900),
    basePrompt: prefixPreview(task.basePrompt, 900),
    displayPrompt: prefixPreview(displayPrompt, 900),
    promptChars: task.prompt.length,
    basePromptChars: task.basePrompt.length,
    displayPromptChars: displayPrompt.length,
    promptEditable: ctx().queuedTaskPromptEditable(task),
    finalResponseChars: task.finalResponse.length,
    stepCount: null,
    llmStepCount: null,
    traceStats: null,
    statsSource: "unavailable",
    summaryOnly: true,
    referenceTaskIds: task.referenceTaskIds,
    referenceInjection: task.referenceInjection === null ? null : {
      injectedAt: task.referenceInjection.injectedAt,
      itemCount: task.referenceInjection.itemCount,
      directReferenceTaskIds: task.referenceInjection.directReferenceTaskIds,
      maxRounds: task.referenceInjection.maxRounds,
      truncated: task.referenceInjection.truncated,
    },
    providerId: task.providerId,
    executionMode: task.executionMode,
    requestedExecutionMode: task.requestedExecutionMode ?? null,
    executionModeInfo: codeExecutionModeInfo(task.executionMode),
    cwd: task.cwd,
    model: task.model,
    agentPort: codeAgentPortForModel(task.model),
    agentPortInfo: codeAgentPortInfo(codeAgentPortForModel(task.model)),
    reasoningEffort: task.reasoningEffort,
    maxAttempts: task.maxAttempts,
    status: task.status,
    ...queuedStatusPayload(task),
    createdAt: task.createdAt,
    updatedAt: task.updatedAt,
    startedAt: task.startedAt,
    finishedAt: task.finishedAt,
    readAt: task.readAt,
    currentAttempt: task.currentAttempt,
    currentMode: task.currentMode,
    judgeFailCount: task.judgeFailCount,
    judgeFailRetryLimit,
    codexThreadId: task.codexThreadId,
    activeTurnId: task.activeTurnId,
    schedulerHeartbeat: task.schedulerHeartbeat ?? null,
    finalResponse: prefixPreview(task.finalResponse, 1200),
    lastError: task.lastError,
    lastJudge: task.lastJudge,
    promptHistory: task.promptHistory.slice(-8),
    attempts: task.attempts.slice(-3).map((attempt) => attemptForResponse(attempt, false)),
    cancelRequested: task.cancelRequested,
    terminalUnread: terminalTaskUnread(task),
    nextMode: task.nextMode,
    outputCount: task.output.length,
    eventCount: task.events.length,
    transcriptCount: null,
    transcriptMaxSeq: lastOutputSeq,
    timing: taskTiming(task),
    transcript: [],
    output: [],
    events: [],
  } as unknown as JsonValue;
}

function lastAssistantMessage(task: QueueTask, transcript = fullTranscript(task)): JsonValue {
  const assistantLine = transcript.slice().reverse().find((line) => line.kind === "message" && line.title === "Assistant message");
  const text = task.finalResponse.trim().length > 0 ? task.finalResponse.trim() : String(assistantLine?.bodyPreview ?? "").trim();
  return {
    text,
    at: assistantLine?.at ?? task.finishedAt ?? task.updatedAt,
    seq: assistantLine?.seq ?? null,
    source: task.finalResponse.trim().length > 0 ? "finalResponse" : assistantLine !== undefined ? "transcript" : "none",
  };
}

function parseToolLimit(url: URL): number {
  const value = Number(url.searchParams.get("toolLimit") ?? 160);
  return Number.isInteger(value) && value > 0 ? Math.min(500, value) : 160;
}

function taskToolSummaryForLimit(task: QueueTask, limit: number, transcript = fullTranscript(task)): JsonValue {
  const allTools = transcript.filter((line) => line.kind === "ran" || line.kind === "explored" || line.kind === "edited");
  const boundedLimit = Math.max(1, Math.min(500, Math.floor(limit)));
  const start = Math.max(0, allTools.length - boundedLimit);
  return {
    count: allTools.length,
    returned: allTools.length - start,
    limit: boundedLimit,
    truncated: start > 0,
    items: allTools.slice(start).map((line) => ({
      seq: line.seq,
      at: line.at,
      kind: line.kind,
      title: line.title,
      status: line.status ?? null,
      commandPreview: line.commandPreview ?? "",
      commandOmittedLines: line.commandOmittedLines ?? 0,
      outputPreview: line.bodyPreview ?? "",
      outputOmittedLines: line.bodyOmittedLines ?? 0,
      rawSeqs: line.rawSeqs,
    })),
  } as unknown as JsonValue;
}

function taskToolSummary(task: QueueTask, url: URL, transcript = fullTranscript(task)): JsonValue {
  return taskToolSummaryForLimit(task, parseToolLimit(url), transcript);
}

function uniqueStrings(values: string[], limit = 20): string[] {
  const result: string[] = [];
  for (const value of values) {
    const normalized = value.trim();
    if (normalized.length === 0 || result.includes(normalized)) continue;
    result.push(normalized);
    if (result.length >= limit) break;
  }
  return result;
}

function cleanTracePath(value: string): string {
  return value
    .replace(/^['"`([{<]+/u, "")
    .replace(/['"`)\]}>.,;:]+$/u, "")
    .replace(/:\d+(?::\d+)?$/u, "")
    .replace(/^[ab]\//u, "")
    .trim();
}

function extractTracePaths(text: string): string[] {
  const source = String(text || "");
  const matches = source.match(/(?:~|\.{1,2}|\/)?(?:[A-Za-z0-9_.@+-]+\/)+[A-Za-z0-9_.@+-]+|[A-Za-z0-9_.@+-]+\.(?:c|cc|cpp|h|hpp|js|jsx|ts|tsx|json|md|py|sh|toml|ya?ml|txt|log|lock)/gu) || [];
  return uniqueStrings(matches.map(cleanTracePath).filter((path) => path.length >= 2 && !path.includes("...") && !/^(http|https|status|method)$/iu.test(path)), 40);
}

function parseEditedFilesFromText(text: string): string[] {
  const files: string[] = [];
  const addFile = (path: string): void => {
    const cleanPath = cleanTracePath(path);
    if (cleanPath.length === 0 || cleanPath === "/dev/null" || files.includes(cleanPath)) return;
    files.push(cleanPath);
  };
  for (const line of text.split(/\r?\n/u)) {
    const statusMatch = /^([AMDRCU?]{1,2})\s+(.+)$/u.exec(line);
    if (statusMatch) {
      addFile(statusMatch[2] || "");
      continue;
    }
    const patchMatch = /^\*\*\*\s+(?:Add|Update|Delete)\s+File:\s+(.+)$/u.exec(line);
    if (patchMatch) {
      addFile(patchMatch[1] || "");
      continue;
    }
    const moveMatch = /^\*\*\*\s+Move to:\s+(.+)$/u.exec(line);
    if (moveMatch) {
      addFile(moveMatch[1] || "");
      continue;
    }
    const diffMatch = /^diff --git a\/(.+?) b\/(.+)$/u.exec(line);
    if (diffMatch) {
      addFile(diffMatch[2] || diffMatch[1] || "");
      continue;
    }
    const plusMatch = /^\+\+\+ b\/(.+)$/u.exec(line);
    if (plusMatch) addFile(plusMatch[1] || "");
  }
  return files.length > 0 ? files : extractTracePaths(text);
}

function transcriptPreviewLines(text: string, maxLines: number, maxChars: number): string[] {
  const preview = linePreview(text, maxLines, maxChars).text;
  return preview.length === 0 ? [] : preview.split(/\r?\n/u).slice(0, maxLines);
}

function transcriptLineSummaryLines(line: TranscriptLine): string[] {
  const lines: string[] = [];
  const command = String(line.commandPreview || "").trim();
  if (command.length > 0) {
    for (const item of transcriptPreviewLines(command, 2, 420)) lines.push(`$ ${item}`);
  }
  const body = String(line.bodyPreview || "").trim();
  const remaining = Math.max(0, 4 - lines.length);
  if (body.length > 0 && remaining > 0) {
    for (const item of transcriptPreviewLines(body, remaining, 700)) lines.push(item);
  }
  if (lines.length === 0) lines.push(line.status ? `${line.title} (${line.status})` : line.title);
  return lines.slice(0, 4);
}

function isToolActionLine(line: TranscriptLine): boolean {
  return line.kind === "ran" || line.kind === "explored" || line.kind === "edited";
}

function toolStepCountsFromTranscript(lines: TranscriptLine[]): { toolCallCount: number; readCount: number; editCount: number; runCount: number } {
  const counts = lines.reduce((memo, line) => {
    if (line.kind === "explored") memo.readCount += 1;
    else if (line.kind === "edited") memo.editCount += 1;
    else if (line.kind === "ran") memo.runCount += 1;
    return memo;
  }, { readCount: 0, editCount: 0, runCount: 0 });
  return {
    ...counts,
    toolCallCount: counts.readCount + counts.editCount + counts.runCount,
  };
}

function realAttemptWindows(task: QueueTask, transcript: TranscriptLine[]): TraceAttemptWindow[] {
  return traceAttemptWindows(task, transcript).filter((window) => window.synthetic !== true && window.index > 0);
}

function taskExecutionTranscript(task: QueueTask, transcript: TranscriptLine[]): TranscriptLine[] {
  const windows = realAttemptWindows(task, transcript);
  if (windows.length === 0) return transcript;
  return sortTranscript(windows.flatMap((window) => executionLinesForAttempt(window.lines)));
}

function executionSummaryFromTranscript(
  task: QueueTask,
  transcript: TranscriptLine[],
  timing: Record<string, JsonValue>,
  outputCount = taskFullOutput(task).length,
  retainedOutputCount = task.output.length,
): JsonValue {
  const toolLines = transcript.filter(isToolActionLine);
  const editedFiles = uniqueStrings(toolLines.flatMap((line) => line.kind === "edited" ? parseEditedFilesFromText(`${line.title}\n${line.bodyPreview ?? ""}`) : []), 40);
  const commands = uniqueStrings(toolLines
    .map((line) => String(line.commandPreview || "").split(/\r?\n/u).find((row) => row.trim().length > 0)?.trim() ?? "")
    .filter(Boolean), 30);
  const counts = toolStepCountsFromTranscript(transcript);
  return {
    durationMs: timing.durationMs ?? timing.totalElapsedMs ?? null,
    totalElapsedMs: timing.totalElapsedMs ?? null,
    queueWaitMs: timing.queueWaitMs ?? null,
    toolCallCount: counts.toolCallCount,
    readCount: counts.readCount,
    editCount: counts.editCount,
    runCount: counts.runCount,
    editedFiles,
    commands,
    stepCount: counts.toolCallCount,
    llmStepCount: counts.toolCallCount,
    traceLineCount: transcript.filter((line) => line.title !== "Submitted prompt").length,
    transcriptMaxSeq: transcript.at(-1)?.seq ?? 0,
    outputCount,
    retainedOutputCount,
  } as unknown as JsonValue;
}

function taskExecutionSummary(task: QueueTask, transcript = cachedPreviewTranscript(task)): JsonValue {
  return executionSummaryFromTranscript(task, taskExecutionTranscript(task, transcript), taskTiming(task) as Record<string, JsonValue>);
}

function parseAttemptIndex(text: string): number | null {
  const match = /\battempt\s+(\d+)\s*\/\s*\d+/iu.exec(text);
  if (match === null) return null;
  const value = Number(match[1]);
  return Number.isInteger(value) && value > 0 ? value : null;
}

function traceAttemptIndexFromLine(line: TranscriptLine): number | null {
  return parseAttemptIndex(`${line.bodyPreview ?? ""}\n${line.commandPreview ?? ""}\n${line.title}`);
}

function parseJudgeLine(text: string): JudgeResult | null {
  const match = /\bjudge=(complete|retry|fail)\s+confidence=([0-9.]+)\s+source=([A-Za-z0-9_-]+):\s*([\s\S]*)$/u.exec(text.trim());
  if (match === null) return null;
  const confidence = Number(match[2]);
  const source = match[3] === "minimax" ? "minimax" : "fallback";
  const rawReason = (match[4] ?? "").trim();
  const detailsMatch = /\bMiniMax failure details:\s+([\s\S]*)$/u.exec(rawReason);
  const detailsText = detailsMatch?.[1] ?? "";
  const detailValue = (key: string): string | null => new RegExp(`\\b${key}=([^\\s]+)`, "u").exec(detailsText)?.[1] ?? null;
  const detailNumber = (key: string): number | undefined => {
    const value = Number(detailValue(key));
    return Number.isFinite(value) ? value : undefined;
  };
  const errorMessage = /\berror=([\s\S]*)$/u.exec(detailsText)?.[1]?.trim() ?? "";
  const failureDetails = detailsText.length === 0 ? null : {
    provider: "minimax" as const,
    stage: (detailValue("stage") || "unknown") as JudgeResult["failureDetails"] extends infer T ? T extends { stage: infer S } ? S : never : never,
    model: "",
    apiBase: "",
    occurredAt: "",
    durationMs: detailNumber("durationMs") ?? 0,
    timeoutMs: detailNumber("timeoutMs") ?? 0,
    timedOut: detailValue("timedOut") === "true",
    errorName: detailValue("errorName") || "",
    errorMessage,
    promptChars: detailNumber("promptChars"),
    promptLines: detailNumber("promptLines"),
    payloadBytes: detailNumber("payloadBytes"),
    responseStatus: detailNumber("responseStatus") ?? null,
  };
  return {
    decision: match[1] as JudgeDecision,
    confidence: Number.isFinite(confidence) ? confidence : 0,
    source,
    reason: detailsMatch === null ? rawReason : rawReason.slice(0, detailsMatch.index).trim(),
    failureDetails,
  };
}

function judgeFromAttemptLines(lines: TranscriptLine[]): { judge: JudgeResult; at: string | null; seq: number | null } | null {
  for (const line of lines.slice().reverse()) {
    if (line.title !== "Judge result" && line.status !== "judge") continue;
    const judge = parseJudgeLine(String(line.bodyPreview || ""));
    if (judge === null) continue;
    return { judge, at: line.at || null, seq: Number.isFinite(Number(line.seq)) ? Number(line.seq) : null };
  }
  return null;
}

function attemptFeedbackPromptRecord(task: QueueTask, attemptIndex: number, attempt: AttemptSummary | null, judge: JudgeResult | null = attempt?.judge ?? null): FeedbackPromptRecord | null {
  const directPrompt = String(attempt?.feedbackPrompt ?? "").trimEnd();
  if (directPrompt.length > 0) {
    const snapshot = promptSnapshot(directPrompt, 1600);
    return {
      text: snapshot.text,
      preview: String(attempt?.feedbackPromptPreview || snapshot.preview),
      chars: Number(attempt?.feedbackPromptChars ?? snapshot.chars),
      lines: Number(attempt?.feedbackPromptLines ?? snapshot.lines),
      source: String(attempt?.feedbackPromptSource || "judge-feedback"),
      forAttempt: Number.isFinite(Number(attempt?.feedbackPromptForAttempt)) ? Number(attempt?.feedbackPromptForAttempt) : attemptIndex + 1,
      truncated: snapshot.truncated,
    };
  }

  const hasPendingRetry = task.status === "retry_wait" || task.status === "queued";
  if (attemptIndex === task.attempts.length && hasPendingRetry && task.nextMode === "retry" && task.nextPrompt !== null && task.nextPrompt.trim().length > 0) {
    const snapshot = promptSnapshot(task.nextPrompt, 1600);
    return { ...snapshot, source: "pending-retry", forAttempt: attemptIndex + 1 };
  }

  const nextAttempt = task.attempts.find((item) => Number(item.index) === attemptIndex + 1) ?? task.attempts[attemptIndex] ?? null;
  const nextInput = String(nextAttempt?.inputPrompt ?? "").trimEnd();
  if (nextInput.length > 0) {
    const snapshot = promptSnapshot(nextInput, 1600);
    return { ...snapshot, source: "attempt-input", forAttempt: attemptIndex + 1 };
  }

  if (judge?.decision === "retry") {
    const generated = retryPrompt(task, judge);
    const snapshot = promptSnapshot(generated, 1600);
    return { ...snapshot, source: judge.continuePrompt?.trim() ? "judge-continue-prompt" : "judge-retry-generated", forAttempt: attemptIndex + 1 };
  }

  return null;
}

function attemptTimingSummary(attempt: AttemptSummary | null, lines: TranscriptLine[]): Record<string, JsonValue> {
  const startedAt = attempt?.startedAt || lines[0]?.at || null;
  const finishedAt = attempt?.finishedAt || lines.at(-1)?.at || null;
  const startedMs = timestampMs(startedAt);
  const finishedMs = timestampMs(finishedAt);
  const durationMs = nonNegativeElapsed(startedMs, finishedMs);
  return {
    durationMs,
    totalElapsedMs: durationMs,
    queueWaitMs: null,
    effectiveEndAt: finishedAt,
  };
}

interface TraceAttemptWindow {
  index: number;
  attempt: AttemptSummary | null;
  startSeq: number | null;
  endSeq: number | null;
  lines: TranscriptLine[];
  synthetic?: boolean;
  label?: string;
}

type TraceStatsLookup = Map<string, JsonValue> | Record<string, JsonValue> | null | undefined;

interface TraceSummaryOaSteps {
  allSteps?: OaTraceStepSummary[];
  attemptSteps?: Map<number, OaTraceStepSummary[]> | Record<string, OaTraceStepSummary[]>;
}

function transcriptLineSeq(line: TranscriptLine | undefined): number | null {
  const value = Number(line?.seq ?? NaN);
  return Number.isFinite(value) ? value : null;
}

function traceWindowFirstSeq(window: TraceAttemptWindow): number {
  return transcriptLineSeq(window.lines[0]) ?? window.startSeq ?? Number.POSITIVE_INFINITY;
}

function isRecoveredThreadLine(line: TranscriptLine): boolean {
  const status = String(line.status || "");
  const text = `${line.title}\n${line.bodyPreview ?? ""}\n${line.commandPreview ?? ""}`;
  return line.kind === "system" && (
    line.title === "Recovered thread execution"
    || line.title === "Queue recovered"
    || status === "startup"
    || status === "shutdown"
    || /\btask queued for retry\b|Service (?:re)?started while task was active|Service stopping while task was active/iu.test(text)
  );
}

function traceSystemLineIsError(line: TranscriptLine): boolean {
  const text = [
    line.title,
    line.status,
    line.bodyPreview,
    line.commandPreview,
    line.stderrPreview,
    line.stdoutPreview,
  ].map((value) => String(value || "")).join("\n");
  return /\b(error|failed|failure|interrupt|interrupted|cancell?ed|watchdog|timeout|closed|refused|aborted|exception)\b/iu.test(text);
}

function traceLineVisibleInTraceView(line: TranscriptLine): boolean {
  if (line.title === "Submitted prompt") return false;
  return line.kind !== "system" || traceSystemLineIsError(line);
}

function oaTraceStepKind(kind: string): TranscriptKind {
  const normalized = String(kind || "").trim().toLowerCase();
  if (normalized === "read" || normalized === "explored" || normalized === "explore") return "explored";
  if (normalized === "edit" || normalized === "edited") return "edited";
  if (normalized === "run" || normalized === "ran" || normalized === "command") return "ran";
  if (normalized === "error" || normalized === "failed") return "error";
  if (normalized === "message" || normalized === "assistant" || normalized === "user") return "message";
  return "system";
}

function oaTraceStepToTranscriptLine(step: OaTraceStepSummary): TranscriptLine {
  const kind = oaTraceStepKind(step.kind);
  const summaryText = step.summaryLines.join("\n").trimEnd();
  const commandText = summaryText.startsWith("item/") ? summaryText : "";
  return {
    seq: step.seq,
    at: step.at,
    kind,
    title: step.title || (kind === "explored" ? "Read" : kind === "edited" ? "Edit" : kind === "ran" ? "Run" : "Trace step"),
    status: step.status || undefined,
    commandPreview: commandText.length > 0 ? commandText : undefined,
    bodyPreview: commandText.length > 0 ? undefined : summaryText || undefined,
    rawSeqs: step.rawSeqs,
  };
}

function isCodexToolLifecycleTranscriptLine(line: TranscriptLine): boolean {
  const text = `${line.commandPreview ?? ""}\n${line.bodyPreview ?? ""}\n${line.title}`;
  const status = String(line.status || "");
  return (line.kind === "explored" || line.kind === "ran")
    && (status === "item/started" || status === "item/completed" || /^item\/(?:started|completed):/u.test(text))
    && /\b(?:webSearch|mcpToolCall|dynamicToolCall)\b/u.test(text);
}

function mergeCodexToolLifecycleGroup(group: TranscriptLine[]): TranscriptLine {
  if (group.length <= 1) return group[0];
  const first = group[0];
  const last = group.at(-1) || first;
  const rawSeqs: number[] = [];
  for (const line of group) {
    for (const seq of Array.isArray(line.rawSeqs) ? line.rawSeqs : [line.seq]) pushUniqueRawSeq(rawSeqs, Number(seq));
  }
  const command = String(last.commandPreview || first.commandPreview || last.bodyPreview || first.bodyPreview || last.title || first.title || "");
  return {
    ...first,
    seq: Number.isFinite(Number(last.seq)) ? Number(last.seq) : Number(first.seq),
    at: last.at || first.at,
    kind: commandKind(command),
    title: shortCommandTitle(command) || String(last.title || first.title || "WebSearch"),
    status: last.status || first.status,
    commandPreview: command || undefined,
    commandOmittedLines: Number(first.commandOmittedLines || 0) + Number(last.commandOmittedLines || 0) || undefined,
    bodyPreview: last.bodyPreview || first.bodyPreview,
    bodyOmittedLines: Number(first.bodyOmittedLines || 0) + Number(last.bodyOmittedLines || 0) || undefined,
    rawSeqs,
  };
}

function coalesceCodexToolLifecycleTranscriptLines(lines: TranscriptLine[]): TranscriptLine[] {
  const rows = sortTranscript([...lines]);
  const merged: TranscriptLine[] = [];
  let group: TranscriptLine[] = [];
  const flush = () => {
    if (group.length > 0) merged.push(mergeCodexToolLifecycleGroup(group));
    group = [];
  };
  for (const line of rows) {
    if (isCodexToolLifecycleTranscriptLine(line)) {
      const text = String(line.commandPreview || line.bodyPreview || "");
      if ((line.status === "item/started" || /^item\/started:/u.test(text)) && group.length > 0) flush();
      group.push(line);
      if (line.status === "item/completed" || /^item\/completed:/u.test(text)) flush();
      continue;
    }
    flush();
    merged.push(line);
  }
  flush();
  return merged;
}

async function oaTraceTranscriptForTask(task: QueueTask, attemptIndex: number | null): Promise<TranscriptLine[]> {
  const taskId = task.id;
  const steps = await readOaTraceStepsForTask(taskId, attemptIndex);
  const oaLines = coalesceCodexToolLifecycleTranscriptLines(coalesceTranscriptMessageFragments(steps.map(oaTraceStepToTranscriptLine).filter(traceLineVisibleInTraceView)));
  const rawLines = coalesceCodexToolLifecycleTranscriptLines(fullTranscript(task).filter(traceLineVisibleInTraceView));
  return coalesceCodexToolLifecycleTranscriptLines(overlayTraceMessagesFromRawTranscript(oaLines, rawLines));
}

function oaTraceTranscriptFromSteps(task: QueueTask, steps: OaTraceStepSummary[] = []): TranscriptLine[] {
  if (steps.length === 0) return [];
  const oaLines = coalesceCodexToolLifecycleTranscriptLines(coalesceTranscriptMessageFragments(steps.map(oaTraceStepToTranscriptLine).filter(traceLineVisibleInTraceView)));
  const rawLines = coalesceCodexToolLifecycleTranscriptLines(fullTranscript(task).filter(traceLineVisibleInTraceView));
  return coalesceCodexToolLifecycleTranscriptLines(overlayTraceMessagesFromRawTranscript(oaLines, rawLines));
}

function taskAttemptTraceSteps(oaSteps: TraceSummaryOaSteps | null | undefined, attemptIndex: number): OaTraceStepSummary[] {
  const source = oaSteps?.attemptSteps;
  if (source === undefined || source === null) return [];
  const key = String(attemptIndex);
  return source instanceof Map ? source.get(attemptIndex) ?? [] : source[key] ?? [];
}

function traceWindowsWithOaSteps(task: QueueTask, transcript: TranscriptLine[], oaSteps: TraceSummaryOaSteps | null | undefined): TraceAttemptWindow[] {
  const mergedTranscript = mergeTraceWindowLines(transcript, oaTraceTranscriptFromSteps(task, oaSteps?.allSteps ?? []));
  const windows = traceAttemptWindows(task, mergedTranscript);
  const byIndex = new Map<number, TraceAttemptWindow>();
  for (const window of windows) if (window.index > 0) byIndex.set(window.index, window);
  const maxIndex = Math.max(task.currentAttempt || 0, task.attempts.length, ...Array.from(byIndex.keys()), 0);
  for (let index = 1; index <= maxIndex; index += 1) {
    const lines = oaTraceTranscriptFromSteps(task, taskAttemptTraceSteps(oaSteps, index));
    if (lines.length === 0) continue;
    const existing = byIndex.get(index);
    if (existing !== undefined) {
      existing.lines = mergeTraceWindowLines(existing.lines, lines);
      existing.startSeq = minNullableSeq(existing.startSeq, transcriptLineSeq(lines[0]));
      const lastSeq = transcriptLineSeq(lines.at(-1));
      if (lastSeq !== null && (existing.endSeq === null || lastSeq > existing.endSeq)) existing.endSeq = lastSeq;
      continue;
    }
    const attempt = task.attempts.find((item) => Number(item.index) === index) ?? task.attempts[index - 1] ?? null;
    windows.push({
      index,
      attempt,
      startSeq: transcriptLineSeq(lines[0]),
      endSeq: transcriptLineSeq(lines.at(-1)),
      lines,
    });
  }
  return windows.sort((left, right) => Number(left.lines[0]?.seq ?? left.startSeq ?? 0) - Number(right.lines[0]?.seq ?? right.startSeq ?? 0));
}

function mergeTraceWindowLines(left: TranscriptLine[], right: TranscriptLine[]): TranscriptLine[] {
  const seen = new Set<string>();
  const merged: TranscriptLine[] = [];
  for (const line of [...left, ...right]) {
    const key = `${line.seq}:${line.title}:${line.status ?? ""}`;
    if (seen.has(key)) continue;
    seen.add(key);
    merged.push(line);
  }
  return sortTranscript(merged);
}

function minNullableSeq(left: number | null, right: number | null): number | null {
  if (left === null) return right;
  if (right === null) return left;
  return Math.min(left, right);
}

function isSystemOnlyOrphanGroup(lines: TranscriptLine[]): boolean {
  const executionLines = executionLinesForAttempt(lines);
  return executionLines.length > 0 && executionLines.every((line) => line.kind === "system");
}

function mergeSystemGroupIntoNextAttempt(windows: TraceAttemptWindow[], lines: TranscriptLine[]): boolean {
  if (!isSystemOnlyOrphanGroup(lines)) return false;
  const groupEndSeq = transcriptLineSeq(lines.at(-1));
  if (groupEndSeq === null) return false;
  const target = windows
    .filter((window) => window.synthetic !== true && traceWindowFirstSeq(window) > groupEndSeq)
    .sort((left, right) => traceWindowFirstSeq(left) - traceWindowFirstSeq(right))[0];
  if (target === undefined) return false;
  target.lines = mergeTraceWindowLines(lines, target.lines);
  target.startSeq = minNullableSeq(target.startSeq, transcriptLineSeq(lines[0]));
  return true;
}

function traceAttemptWindows(task: QueueTask, transcript: TranscriptLine[]): TraceAttemptWindow[] {
  const starts = transcript
    .map((line, position) => ({ line, position, index: line.title === "Attempt started" ? traceAttemptIndexFromLine(line) : null }))
    .filter((item): item is { line: TranscriptLine; position: number; index: number } => item.index !== null)
    .sort((left, right) => Number(left.line.seq) - Number(right.line.seq));
  const maxStartIndex = starts.reduce((max, item) => Math.max(max, item.index), 0);
  const maxIndex = Math.max(task.attempts.length, task.currentAttempt || 0, maxStartIndex);
  const windows: TraceAttemptWindow[] = [];
  for (let index = 1; index <= maxIndex; index += 1) {
    const attempt = task.attempts.find((item) => Number(item.index) === index) ?? task.attempts[index - 1] ?? null;
    const start = starts.find((item) => item.index === index) ?? starts[index - 1] ?? null;
    const nextStart = starts.find((item) => item.index > index) ?? null;
    const explicitStartSeq = Number((attempt as AttemptSummary | null)?.outputStartSeq ?? NaN);
    const explicitEndSeq = Number((attempt as AttemptSummary | null)?.outputEndSeq ?? NaN);
    const startSeq = Number.isFinite(explicitStartSeq) ? explicitStartSeq : start?.line.seq ?? null;
    const hasExplicitEndSeq = Number.isFinite(explicitEndSeq);
    const endSeq = hasExplicitEndSeq ? explicitEndSeq : nextStart !== null ? nextStart.line.seq : null;
    let lines = startSeq === null
      ? []
      : transcript.filter((line) => Number(line.seq) >= startSeq && (endSeq === null || (hasExplicitEndSeq ? Number(line.seq) <= endSeq : Number(line.seq) < endSeq)));
    if (lines.length === 0 && attempt !== null) {
      const startedMs = timestampMs(attempt.startedAt);
      const finishedMs = timestampMs(attempt.finishedAt);
      lines = transcript.filter((line) => {
        const lineMs = timestampMs(line.at);
        return lineMs !== null
          && (startedMs === null || lineMs >= startedMs)
          && (finishedMs === null || lineMs <= finishedMs);
      });
    }
    windows.push({ index, attempt, startSeq, endSeq, lines });
  }
  const coveredSeqs = new Set<number>();
  for (const window of windows) {
    for (const line of window.lines) coveredSeqs.add(Number(line.seq));
  }
  const orphanedGroups: TranscriptLine[][] = [];
  let group: TranscriptLine[] = [];
  const flushGroup = (): void => {
    if (group.length > 0 && executionLinesForAttempt(group).length > 0) orphanedGroups.push(group);
    group = [];
  };
  for (const line of transcript) {
    const seq = Number(line.seq);
    if (line.title === "Submitted prompt" || coveredSeqs.has(seq)) {
      flushGroup();
      continue;
    }
    group.push(line);
  }
  flushGroup();

  let syntheticIndex = -1;
  for (const lines of orphanedGroups) {
    if (mergeSystemGroupIntoNextAttempt(windows, lines)) continue;
    const hasSteer = lines.some((line) => line.title === "Steer prompt" || line.status === "turn/steer");
    const hasRecovery = lines.some(isRecoveredThreadLine);
    const startSeq = Number(lines[0]?.seq ?? NaN);
    const endSeq = Number(lines.at(-1)?.seq ?? NaN);
    windows.push({
      index: syntheticIndex,
      attempt: null,
      startSeq: Number.isFinite(startSeq) ? startSeq : null,
      endSeq: Number.isFinite(endSeq) ? endSeq : null,
      lines,
      synthetic: true,
      label: hasRecovery
        ? hasSteer ? "Recovered thread execution with steer prompt" : "Recovered thread execution"
        : hasSteer ? "Recovered thread execution with steer prompt" : "System events",
    });
    syntheticIndex -= 1;
  }

  return windows.sort((left, right) => Number(left.lines[0]?.seq ?? left.startSeq ?? 0) - Number(right.lines[0]?.seq ?? right.startSeq ?? 0));
}

function executionLinesForAttempt(lines: TranscriptLine[]): TranscriptLine[] {
  return lines.filter((line) => line.title !== "Submitted prompt" && line.title !== "Attempt started" && line.title !== "Judge result");
}

function taskTraceAttemptSummaries(task: QueueTask, transcript: TranscriptLine[], oaTraceStatsByScope: TraceStatsLookup = null, oaSteps: TraceSummaryOaSteps | null = null): JsonValue[] {
  const windows = traceWindowsWithOaSteps(task, transcript, oaSteps);
  return windows.map((window) => {
    const attempt = window.attempt;
    const parsedJudge = judgeFromAttemptLines(window.lines);
    const storedJudge = attempt?.judge ?? null;
    const synthetic = window.synthetic === true;
    const judge = synthetic ? null : storedJudge ?? parsedJudge?.judge ?? (window.index === task.attempts.length && task.lastJudge !== null ? task.lastJudge : null);
    const finalResponse = synthetic ? "" : String(attempt?.finalResponse ?? attempt?.finalResponsePreview ?? (window.index === task.attempts.length ? task.finalResponse : ""));
    const finalResponseChars = Number(attempt?.finalResponseChars ?? finalResponse.length);
    const executionLines = executionLinesForAttempt(window.lines);
    const attemptStats = synthetic || window.index <= 0 ? null : traceStatsForScope(oaTraceStatsByScope, taskAttemptScopeId(task.id, window.index));
    const fallbackStats = executionSummaryFromTranscript(
      task,
      executionLines,
      attemptTimingSummary(attempt, executionLines.length > 0 ? executionLines : window.lines),
      window.lines.length,
      window.lines.length,
    );
    const fallbackStatsRecord = traceStatsRecord(fallbackStats);
    const rawTracePresent = executionLines.length > 0 || window.lines.length > 0;
    const fallbackTraceStats = attemptStats === null && rawTracePresent
      ? traceStatsFallbackRecord(taskAttemptScopeId(task.id, window.index), fallbackStatsRecord, window.lines, window.endSeq)
      : null;
    const traceStats = attemptStats ?? fallbackTraceStats;
    const stepCount = traceStatsNumber(traceStats, "stepCount") ?? traceStatsNumber(fallbackStatsRecord, "stepCount");
    const readCount = traceStatsNumber(traceStats, "readCount") ?? traceStatsNumber(fallbackStatsRecord, "readCount");
    const editCount = traceStatsNumber(traceStats, "editCount") ?? traceStatsNumber(fallbackStatsRecord, "editCount");
    const runCount = traceStatsNumber(traceStats, "runCount") ?? traceStatsNumber(fallbackStatsRecord, "runCount");
    const errorCount = traceStatsNumber(traceStats, "errorCount") ?? traceStatsNumber(fallbackStatsRecord, "errorCount");
    const feedbackPrompt = synthetic ? null : attemptFeedbackPromptRecord(task, window.index, attempt, judge);
    const inputPrompt = promptSnapshot(String(attempt?.inputPrompt ?? ""), 1200);
    return {
      ...(attempt ?? {}),
      index: attempt?.index ?? window.index,
      synthetic,
      label: window.label ?? null,
      mode: attempt?.mode ?? (window.index <= 1 ? "initial" : "retry"),
      startedAt: attempt?.startedAt ?? window.lines[0]?.at ?? task.startedAt,
      finishedAt: attempt?.finishedAt ?? null,
      terminalStatus: attempt?.terminalStatus ?? null,
      transportClosedBeforeTerminal: attempt?.transportClosedBeforeTerminal ?? false,
      appServerExitCode: attempt?.appServerExitCode ?? null,
      appServerSignal: attempt?.appServerSignal ?? null,
      error: attempt?.error ?? null,
      stderrTail: attempt?.stderrTail ?? "",
      startSeq: window.startSeq,
      endSeq: window.endSeq,
      inputPrompt: undefined,
      inputPromptPreview: inputPrompt.preview,
      inputPromptChars: Number(attempt?.inputPromptChars ?? inputPrompt.chars),
      inputPromptLines: Number(attempt?.inputPromptLines ?? inputPrompt.lines),
      finalResponse,
      finalResponsePreview: attempt?.finalResponsePreview ?? safePreview(finalResponse, 3000),
      finalResponseChars,
      finalResponseTruncated: finalResponse.length < finalResponseChars,
      judge,
      judgeAt: attempt?.judgeAt ?? parsedJudge?.at ?? null,
      judgeSeq: attempt?.judgeSeq ?? parsedJudge?.seq ?? null,
      feedbackPrompt: undefined,
      feedbackPromptPreview: feedbackPrompt?.preview ?? "",
      feedbackPromptChars: feedbackPrompt?.chars ?? 0,
      feedbackPromptLines: feedbackPrompt?.lines ?? 0,
      feedbackPromptSource: feedbackPrompt?.source ?? null,
      feedbackPromptForAttempt: feedbackPrompt?.forAttempt ?? null,
      feedbackPromptTruncated: feedbackPrompt?.truncated ?? false,
      attemptScopeId: synthetic || window.index <= 0 ? null : taskAttemptScopeId(task.id, window.index),
      stepCount,
      readCount,
      editCount,
      runCount,
      errorCount,
      statsSource: attemptStats === null ? rawTracePresent ? "raw-trace-fallback" : "raw-trace-empty" : "oa-event-flow",
      traceStatsState: attemptStats === null ? rawTracePresent ? "degraded" : "empty" : "ready",
      traceStatsReason: attemptStats === null ? rawTracePresent ? "oa-event-flow-stats-unavailable-raw-trace-present" : "no-trace-steps-yet" : null,
      statsUnavailable: attemptStats === null,
      statsSyncing: attemptStats === null && rawTracePresent,
      rawTraceStepCount: attemptStats === null ? traceStatsNumber(fallbackStatsRecord, "stepCount") ?? window.lines.length : null,
      traceStats,
      execution: executionSummaryWithOaStats(fallbackStats, traceStats),
    };
  }) as unknown as JsonValue[];
}

function taskTraceSummaryFixtureResponse(task: QueueTask, options: { stats?: TraceStatsLookup; taskStats?: JsonValue | null; allSteps?: OaTraceStepSummary[]; attemptSteps?: Map<number, OaTraceStepSummary[]> | Record<string, OaTraceStepSummary[]> } = {}): JsonValue {
  return taskTraceSummaryResponse(task, options.taskStats ?? null, options.stats ?? null, { allSteps: options.allSteps ?? [], attemptSteps: options.attemptSteps ?? {} });
}

function resolvedReferencePromptParts(prompt: string): { reference: string; userPrompt: string } {
  const withoutEnvironment = stripCodeQueueEnvironmentHint(prompt);
  const trimmed = withoutEnvironment.trimStart();
  if (!trimmed.startsWith(resolvedReferenceContextTitle)) {
    return { reference: "", userPrompt: userPromptForDisplay(prompt) };
  }
  const offset = withoutEnvironment.length - trimmed.length;
  const index = withoutEnvironment.lastIndexOf(currentTaskPromptMarker);
  if (index < offset) return { reference: "", userPrompt: userPromptForDisplay(prompt) };
  return {
    reference: withoutEnvironment.slice(offset, index).trimEnd(),
    userPrompt: withoutEnvironment.slice(index + currentTaskPromptMarker.length).trimStart(),
  };
}

function taskTracePromptSummary(task: QueueTask): JsonValue {
  const displayPrompt = task.basePrompt || userPromptForDisplay(task.prompt);
  const parts = resolvedReferencePromptParts(task.prompt);
  return {
    basePrompt: displayPrompt,
    basePromptChars: displayPrompt.length,
    basePromptLines: promptLineCount(displayPrompt),
    promptChars: task.prompt.length,
    promptLines: promptLineCount(task.prompt),
    referencePromptChars: parts.reference.length,
    referencePromptLines: promptLineCount(parts.reference),
    hasReferenceInjection: parts.reference.length > 0 || task.referenceInjection !== null,
    referenceTaskIds: task.referenceTaskIds,
    referenceInjectionSummary: task.referenceInjection === null ? null : {
      injectedAt: task.referenceInjection.injectedAt,
      itemCount: task.referenceInjection.itemCount,
      directReferenceTaskIds: task.referenceInjection.directReferenceTaskIds,
      maxRounds: task.referenceInjection.maxRounds,
      truncated: task.referenceInjection.truncated,
    },
  } as unknown as JsonValue;
}

function traceStatsRecord(value: JsonValue | null | undefined): Record<string, JsonValue> | null {
  return typeof value === "object" && value !== null && !Array.isArray(value) ? value as Record<string, JsonValue> : null;
}

function traceStatsNumber(stats: Record<string, JsonValue> | null, key: string): number | null {
  const value = Number(stats?.[key]);
  return Number.isFinite(value) && value >= 0 ? Math.floor(value) : null;
}

function taskAttemptScopeId(taskId: string, attemptIndex: number): string {
  return `task:${taskId}:attempt:${Math.floor(attemptIndex)}`;
}

function traceStatsForScope(lookup: TraceStatsLookup, scopeId: string): Record<string, JsonValue> | null {
  if (lookup === null || lookup === undefined || scopeId.length === 0) return null;
  const value = lookup instanceof Map ? lookup.get(scopeId) : lookup[scopeId];
  return traceStatsRecord(value);
}

function taskScopeId(taskId: string): string {
  return `task:${taskId}`;
}

function traceStatsFallbackRecord(scopeId: string, fallback: Record<string, JsonValue> | null, lines: TranscriptLine[], endSeq: number | null): Record<string, JsonValue> {
  const stepCount = traceStatsNumber(fallback, "stepCount") ?? 0;
  return {
    scopeId,
    source: "oa-event-flow",
    stepCount,
    llmStepCount: traceStatsNumber(fallback, "llmStepCount") ?? stepCount,
    traceLineCount: traceStatsNumber(fallback, "traceLineCount") ?? lines.length,
    outputMaxSeq: traceStatsNumber(fallback, "transcriptMaxSeq") ?? Number(endSeq ?? lines.at(-1)?.seq ?? 0),
    readCount: traceStatsNumber(fallback, "readCount") ?? 0,
    editCount: traceStatsNumber(fallback, "editCount") ?? 0,
    runCount: traceStatsNumber(fallback, "runCount") ?? 0,
    errorCount: traceStatsNumber(fallback, "errorCount") ?? 0,
    sourceHint: "raw-trace-fallback",
  };
}

function executionSummaryWithOaStats(execution: JsonValue, stats: Record<string, JsonValue> | null): JsonValue {
  if (typeof execution !== "object" || execution === null || Array.isArray(execution)) return execution;
  const record = execution as Record<string, JsonValue>;
  if (stats === null) {
    const fallbackStepCount = traceStatsNumber(record, "stepCount") ?? traceStatsNumber(record, "llmStepCount");
    const rawTracePresent = (fallbackStepCount ?? 0) > 0 || (traceStatsNumber(record, "traceLineCount") ?? 0) > 0 || (traceStatsNumber(record, "transcriptMaxSeq") ?? 0) > 0;
    return {
      ...record,
      statsSource: rawTracePresent ? "raw-trace-fallback" : "raw-trace-empty",
      traceStats: null,
      statsUnavailable: true,
      statsSyncing: rawTracePresent,
      traceStatsState: rawTracePresent ? "degraded" : "empty",
      traceStatsReason: rawTracePresent ? "oa-event-flow-stats-unavailable-raw-trace-present" : "no-trace-steps-yet",
    } as unknown as JsonValue;
  }
  const sourceHint = String(stats.sourceHint ?? "");
  const stepCount = traceStatsNumber(stats, "stepCount");
  const llmStepCount = traceStatsNumber(stats, "llmStepCount") ?? stepCount;
  const readCount = traceStatsNumber(stats, "readCount");
  const editCount = traceStatsNumber(stats, "editCount");
  const runCount = traceStatsNumber(stats, "runCount");
  const errorCount = traceStatsNumber(stats, "errorCount");
  const traceLineCount = traceStatsNumber(stats, "traceLineCount");
  const outputMaxSeq = traceStatsNumber(stats, "outputMaxSeq");
  const toolCallCount = readCount === null && editCount === null && runCount === null ? null : (readCount ?? 0) + (editCount ?? 0) + (runCount ?? 0);
  return {
    ...record,
    ...(stepCount === null ? {} : { stepCount }),
    ...(llmStepCount === null ? {} : { llmStepCount }),
    ...(toolCallCount === null ? {} : { toolCallCount }),
    ...(readCount === null ? {} : { readCount }),
    ...(editCount === null ? {} : { editCount }),
    ...(runCount === null ? {} : { runCount }),
    ...(errorCount === null ? {} : { errorCount }),
    ...(traceLineCount === null ? {} : { traceLineCount }),
    ...(outputMaxSeq === null ? {} : { outputMaxSeq, transcriptMaxSeq: outputMaxSeq }),
    statsSource: "oa-event-flow",
    traceStats: stats,
    statsUnavailable: sourceHint === "raw-trace-fallback",
    statsSyncing: sourceHint === "raw-trace-fallback",
    traceStatsState: sourceHint === "raw-trace-fallback" ? "degraded" : "ready",
    traceStatsReason: sourceHint === "raw-trace-fallback" ? "oa-event-flow-stats-unavailable-raw-trace-present" : null,
  } as unknown as JsonValue;
}

function taskTraceSummaryResponse(task: QueueTask, oaTraceStats: JsonValue | null = null, oaTraceStatsByScope: TraceStatsLookup = null, oaSteps: TraceSummaryOaSteps | null = null): JsonValue {
  const transcript = cachedPreviewTranscript(task);
  const attempts = taskTraceAttemptSummaries(task, transcript, oaTraceStatsByScope, oaSteps);
  const stats = traceStatsRecord(oaTraceStats);
  const fallbackTranscript = mergeTraceWindowLines(transcript, oaTraceTranscriptFromSteps(task, oaSteps?.allSteps ?? []));
  const fallbackExecution = executionSummaryFromTranscript(task, fallbackTranscript, taskTiming(task) as Record<string, JsonValue>);
  const fallbackRecord = traceStatsRecord(fallbackExecution);
  const stepCount = traceStatsNumber(stats, "stepCount") ?? traceStatsNumber(fallbackRecord, "stepCount");
  const llmStepCount = traceStatsNumber(stats, "llmStepCount") ?? stepCount;
  const errorCount = traceStatsNumber(stats, "errorCount") ?? traceStatsNumber(fallbackRecord, "errorCount");
  const rawTracePresent = stats === null && ((stepCount ?? 0) > 0 || (traceStatsNumber(fallbackRecord, "traceLineCount") ?? 0) > 0 || (traceStatsNumber(fallbackRecord, "transcriptMaxSeq") ?? 0) > 0);
  const fallbackTraceStats = rawTracePresent ? traceStatsFallbackRecord(taskScopeId(task.id), fallbackRecord, fallbackTranscript, fallbackTranscript.at(-1)?.seq ?? null) : null;
  const effectiveStats = stats ?? fallbackTraceStats;
  const execution = executionSummaryWithOaStats(fallbackExecution, effectiveStats);
  return {
    id: task.id,
    queueId: ctx().queueIdOf(task),
    status: task.status,
    providerId: task.providerId,
    executionMode: task.executionMode,
    requestedExecutionMode: task.requestedExecutionMode ?? null,
    executionModeInfo: codeExecutionModeInfo(task.executionMode),
    model: task.model,
    agentPort: codeAgentPortForModel(task.model),
    agentPortInfo: codeAgentPortInfo(codeAgentPortForModel(task.model)),
    cwd: task.cwd,
    reasoningEffort: task.reasoningEffort,
    createdAt: task.createdAt,
    startedAt: task.startedAt,
    finishedAt: task.finishedAt,
    updatedAt: task.updatedAt,
    currentAttempt: task.currentAttempt,
    maxAttempts: task.maxAttempts,
    schedulerHeartbeat: task.schedulerHeartbeat ?? null,
    stepCount,
    llmStepCount,
    promptEditable: ctx().queuedTaskPromptEditable(task),
    prompt: taskTracePromptSummary(task),
    execution,
    traceStats: effectiveStats,
    statsSource: stats === null ? rawTracePresent ? "raw-trace-fallback" : "raw-trace-empty" : "oa-event-flow",
    traceStatsState: stats === null ? rawTracePresent ? "degraded" : "empty" : "ready",
    traceStatsReason: stats === null ? rawTracePresent ? "oa-event-flow-stats-unavailable-raw-trace-present" : "no-trace-steps-yet" : null,
    statsUnavailable: stats === null,
    statsSyncing: stats === null && rawTracePresent,
    rawTraceStepCount: stats === null ? stepCount ?? 0 : null,
    finalResponse: task.finalResponse,
    finalResponseChars: task.finalResponse.length,
    lastJudge: task.lastJudge,
    lastError: task.lastError,
    errorCount,
    attempts,
    timing: taskTiming(task),
  } as unknown as JsonValue;
}

function taskFeedbackPromptDetail(task: QueueTask, attemptIndex: number | null): FeedbackPromptRecord | null {
  const index = attemptIndex ?? (task.attempts.length > 0 ? task.attempts.length : task.currentAttempt || 1);
  if (!Number.isInteger(index) || index <= 0) return null;
  const attempt = task.attempts.find((item) => Number(item.index) === index) ?? task.attempts[index - 1] ?? null;
  let judge = attempt?.judge ?? null;
  if (judge === null) {
    const window = traceAttemptWindows(task, cachedPreviewTranscript(task)).find((item) => item.index === index) ?? null;
    judge = judgeFromAttemptLines(window?.lines ?? [])?.judge ?? null;
  }
  return attemptFeedbackPromptRecord(task, index, attempt, judge);
}

function taskPromptDetailResponse(task: QueueTask, url: URL): Response {
  const part = String(url.searchParams.get("part") || "full");
  const parts = resolvedReferencePromptParts(task.prompt);
  const basePrompt = task.basePrompt || userPromptForDisplay(task.prompt);
  if (part === "feedback" || part === "judge-feedback") {
    const attemptIndex = ctx().parseSeqParam(url, "attempt", null);
    const detail = taskFeedbackPromptDetail(task, attemptIndex);
    const text = detail?.text ?? "";
    return ctx().jsonResponse({
      ok: true,
      taskId: task.id,
      queueId: ctx().queueIdOf(task),
      status: task.status,
      updatedAt: task.updatedAt,
      part: "feedback",
      attempt: attemptIndex,
      forAttempt: detail?.forAttempt ?? null,
      source: detail?.source ?? null,
      text,
      preview: detail?.preview ?? "",
      chars: detail?.chars ?? text.length,
      lines: detail?.lines ?? promptLineCount(text),
      truncated: detail?.truncated ?? false,
    });
  }
  const text = part === "base"
    ? basePrompt
    : part === "reference"
      ? parts.reference
      : task.prompt;
  return ctx().jsonResponse({
    ok: true,
    taskId: task.id,
    queueId: ctx().queueIdOf(task),
    status: task.status,
    updatedAt: task.updatedAt,
    part,
    text,
    chars: text.length,
    lines: promptLineCount(text),
    promptChars: task.prompt.length,
    basePromptChars: basePrompt.length,
    referencePromptChars: parts.reference.length,
  });
}

async function taskTraceStepsResponse(task: QueueTask, url: URL): Promise<Response> {
  const limit = ctx().parseLimit(url);
  const attemptIndex = ctx().parseSeqParam(url, "attempt", null);
  const agentPort = codeAgentPortForModel(task.model);
  const transcript = await oaTraceTranscriptForTask(task, attemptIndex);
  const page = ctx().pageBySeq(transcript, url, limit);
  return ctx().jsonResponse({
    ok: true,
    taskId: task.id,
    queueId: ctx().queueIdOf(task),
    status: task.status,
    updatedAt: task.updatedAt,
    agentPort,
    agentPortInfo: codeAgentPortInfo(agentPort),
    attempt: attemptIndex,
    source: "oa-event-flow",
    steps: page.chunk.map((line) => ({
      seq: line.seq,
      at: line.at,
      kind: line.kind,
      title: line.title,
      status: line.status ?? null,
      durationMs: line.durationMs ?? null,
      rawSeqs: line.rawSeqs,
      summaryLines: transcriptLineSummaryLines(line),
      hasDetail: true,
    })),
    mode: page.mode,
    afterSeq: page.afterSeq,
    nextAfterSeq: page.nextAfterSeq,
    beforeSeq: page.beforeSeq,
    previousBeforeSeq: page.previousBeforeSeq,
    hasMore: page.hasMore,
    hasBefore: page.hasBefore,
    total: transcript.length,
    maxSeq: transcript.at(-1)?.seq ?? 0,
  });
}

async function taskTraceStepDetailResponse(task: QueueTask, url: URL): Promise<Response> {
  const seq = Number(url.searchParams.get("seq"));
  if (!Number.isFinite(seq)) return ctx().jsonResponse({ ok: false, error: "seq is required" }, 400);
  const agentPort = codeAgentPortForModel(task.model);
  const transcript = await oaTraceTranscriptForTask(task, null);
  const line = transcript.find((item) => Number(item.seq) === seq || item.rawSeqs.includes(seq));
  if (line === undefined) return ctx().jsonResponse({ ok: false, error: "trace step not found", seq }, 404);
  return ctx().jsonResponse({
    ok: true,
    taskId: task.id,
    queueId: ctx().queueIdOf(task),
    status: task.status,
    updatedAt: task.updatedAt,
    agentPort,
    agentPortInfo: codeAgentPortInfo(agentPort),
    seq,
    line,
  });
}

function taskSummaryResponse(task: QueueTask, url: URL): JsonValue {
  const transcript = fullTranscript(task);
  const fullOutput = taskFullOutput(task);
  return {
    id: task.id,
    queueId: ctx().queueIdOf(task),
    status: task.status,
    providerId: task.providerId,
    executionMode: task.executionMode,
    requestedExecutionMode: task.requestedExecutionMode ?? null,
    executionModeInfo: codeExecutionModeInfo(task.executionMode),
    model: task.model,
    agentPort: codeAgentPortForModel(task.model),
    agentPortInfo: codeAgentPortInfo(codeAgentPortForModel(task.model)),
    cwd: task.cwd,
    reasoningEffort: task.reasoningEffort,
    maxAttempts: task.maxAttempts,
    currentAttempt: task.currentAttempt,
    currentMode: task.currentMode,
    judgeFailCount: task.judgeFailCount,
    judgeFailRetryLimit,
    codexThreadId: task.codexThreadId,
    activeTurnId: task.activeTurnId,
    createdAt: task.createdAt,
    startedAt: task.startedAt,
    finishedAt: task.finishedAt,
    updatedAt: task.updatedAt,
    timing: taskTiming(task),
    initialPrompt: task.prompt,
    basePrompt: task.basePrompt,
    prompt: task.prompt,
    promptEditable: ctx().queuedTaskPromptEditable(task),
    referenceTaskIds: task.referenceTaskIds,
    referenceInjection: task.referenceInjection,
    lastAssistantMessage: lastAssistantMessage(task, transcript),
    toolSummary: taskToolSummary(task, url, transcript),
    attempts: task.attempts,
    lastJudge: task.lastJudge,
    lastError: task.lastError,
    cancelRequested: task.cancelRequested,
    transcriptCount: transcript.length,
    transcriptMaxSeq: transcript.at(-1)?.seq ?? 0,
    outputCount: fullOutput.length,
    retainedOutputCount: task.output.length,
    outputMaxSeq: fullOutput.at(-1)?.seq ?? 0,
    eventCount: task.events.length,
    cliHint: `bun scripts/cli.ts codex task ${task.id}`,
    traceHint: `bun scripts/cli.ts codex task ${task.id} --trace --tail --limit 80`,
    rawOutputHint: `bun scripts/cli.ts codex output ${task.id} --tail --limit 20`,
  } as unknown as JsonValue;
}


export {
  buildCompactTaskTranscript,
  buildTaskTranscript,
  cachedPreviewTranscript,
  codexToolLifecycleStartedBeforeIn,
  isCodexToolLifecycleOutput,
  formatCommandOutput,
  fullTranscript,
  lastAssistantMessage,
  promptLineCount,
  promptSnapshot,
  recordNumberField,
  recordStringField,
  safePreview,
  prefixPreview,
  setAttemptFeedbackPrompt,
  setAttemptInputPrompt,
  statsDaysFromUrl,
  taskExecutionSummary,
  taskListStepCount,
  taskOutputMaxSeq,
  taskForCompactMetaResponse,
  taskForMetaResponse,
  taskForResponse,
  taskStatisticsSummary,
  taskSummaryResponse,
  taskTiming,
  timestampMs,
  nonNegativeElapsed,
  taskToolSummary,
  taskTraceStepDetailResponse,
  taskTraceStepsResponse,
  taskTraceAttemptSummaries,
  taskTraceSummaryFixtureResponse,
  taskTraceSummaryResponse,
  taskPromptDetailResponse,
  transcriptLineSummaryLines,
};
