{"version":3,"file":"project-setup-CMwDyf5G.mjs","names":["waitOnDeps","resolveTarget","parseYaml"],"sources":["../src/workers/specfile.ts","../src/workers/agents.ts","../src/workers/chatui.ts","../src/workers/render.ts","../src/workers/viewer.ts","../src/workers/help.ts","../src/workers/wait-probes.ts","../src/workers/providers.ts","../src/workers/target.ts","../src/cli/commands/worker.ts","../src/workers/fallback.ts","../src/config/main-config-ops.ts","../src/session/issue-claims.ts","../src/workers/queue.ts","../src/workers/queue-runner.ts","../src/workers/queue-deps.ts","../src/session/project-setup.ts"],"sourcesContent":["/**\n * specfile.ts — `--spec <path>` reads a worker's prompt from a file (or stdin\n * via `--spec -`) instead of an inline `-p '<prompt>'`, which has repeatedly\n * died on shell quoting for anything long or multi-line.\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { resolve } from \"node:path\";\n\n/** The path a --spec value resolves to for display/recording; \"-\" (stdin) passes through unchanged. */\nexport function resolveSpecPath(spec: string, cwd: string): string {\n  return spec === \"-\" ? \"-\" : resolve(cwd, spec);\n}\n\n/** The prompt text a --spec value reads: the file's exact bytes, or stdin's. */\nexport function readSpecPrompt(spec: string, cwd: string): string {\n  if (spec === \"-\") {\n    let content: string;\n    try {\n      content = readFileSync(0, \"utf8\");\n    } catch (e) {\n      throw new Error(`--spec -: could not read stdin: ${(e as Error).message}`);\n    }\n    if (!content) throw new Error(\"--spec -: stdin was empty\");\n    return content;\n  }\n  const path = resolveSpecPath(spec, cwd);\n  if (!existsSync(path)) throw new Error(`--spec: file not found: ${path}`);\n  const content = readFileSync(path, \"utf8\");\n  if (!content) throw new Error(`--spec: file is empty: ${path}`);\n  return content;\n}\n","/**\n * agents.ts — run agent definitions (~/.claude/agents/<name>.md) as workers.\n *\n * The file format is the Claude Code agent one: YAML front matter (`model`,\n * `tools`, `description`) followed by a Markdown body that is the agent's\n * system prompt. `pai worker run --agent <name>` loads it and maps it onto\n * the worker runner:\n *\n *   - body    → --append-system-prompt (prepended, so an explicit caller\n *               flag still wins);\n *   - tools   → --allowedTools;\n *   - model   → a task class via its tier (haiku→simple, sonnet→implement,\n *               opus→complex). Non-Anthropic ids map through the provider\n *               registry (models.fast → haiku tier, models.default → sonnet\n *               tier, a provider's modelTiers override if set), unless\n *               --class is given.\n */\n\nimport { readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport type { ModelTier, WorkerProvider } from \"./config.js\";\n\nexport type { ModelTier } from \"./config.js\";\n\nimport { UNLABELED } from \"./status.js\";\n\nexport interface AgentDef {\n  name: string;\n  /** Front-matter `model`, when present (any string; mapped via modelToClass). */\n  model?: string;\n  /** Front-matter `tools`, comma-separated. */\n  tools?: string[];\n  /** Front-matter `description`. */\n  description?: string;\n  /** Everything after the front matter — the agent's system prompt. */\n  body: string;\n  /** The file the definition was read from. */\n  path: string;\n}\n\n/** Directory the agent library lives in. */\nexport function agentsDir(): string {\n  return join(homedir(), \".claude\", \"agents\");\n}\n\nexport function agentPath(name: string): string {\n  return join(agentsDir(), `${name}.md`);\n}\n\n/** `key: value` (bare) or `key: [a, b]` / `key:\\n  - a\\n  - b` (list). */\nfunction parseFrontMatter(text: string): Record<string, string | string[]> {\n  const out: Record<string, string | string[]> = {};\n  let key = \"\";\n  for (const raw of text.split(\"\\n\")) {\n    const listItem = /^\\s+-\\s+(.*)$/.exec(raw);\n    if (listItem && key) {\n      const cur = out[key];\n      const item = listItem[1].trim().replace(/^[\"']|[\"']$/g, \"\");\n      out[key] = Array.isArray(cur) ? [...cur, item] : [item];\n      continue;\n    }\n    const kv = /^([A-Za-z0-9_-]+):\\s*(.*)$/.exec(raw);\n    if (!kv) continue;\n    key = kv[1];\n    const val = kv[2].trim();\n    if (!val) {\n      out[key] = [];\n    } else if (val.startsWith(\"[\") && val.endsWith(\"]\")) {\n      out[key] = val\n        .slice(1, -1)\n        .split(\",\")\n        .map((s) => s.trim().replace(/^[\"']|[\"']$/g, \"\"))\n        .filter(Boolean);\n    } else {\n      out[key] = val.replace(/^[\"']|[\"']$/g, \"\");\n    }\n  }\n  return out;\n}\n\n/** Parse an agent file's text (front matter + body). Throws on empty body. */\nexport function parseAgentFile(name: string, text: string, path: string): AgentDef {\n  const m = /^---\\n([\\s\\S]*?)\\n---\\n?([\\s\\S]*)$/.exec(text);\n  if (!m) {\n    throw new Error(\n      `${path}: expected YAML front matter (--- … ---) before the agent body`\n    );\n  }\n  const fm = parseFrontMatter(m[1]);\n  const body = m[2].trim();\n  if (!body) throw new Error(`${path}: the agent body (after the front matter) is empty`);\n  const def: AgentDef = { name, body, path };\n  if (typeof fm.model === \"string\" && fm.model) def.model = fm.model;\n  if (Array.isArray(fm.tools) && fm.tools.length) def.tools = fm.tools;\n  if (typeof fm.description === \"string\" && fm.description) def.description = fm.description;\n  return def;\n}\n\n/** Load ~/.claude/agents/<name>.md; the error names the library when missing. */\nexport function loadAgent(name: string): AgentDef {\n  const path = agentPath(name);\n  let text: string;\n  try {\n    text = readFileSync(path, \"utf8\");\n  } catch {\n    throw new Error(\n      `no agent named \"${name}\" at ${path}. ` +\n        `The agent library lives in ~/.claude/agents/<name>.md and runs on workers.`\n    );\n  }\n  return parseAgentFile(name, text, path);\n}\n\n/** Tier → task class: the cheap tier runs as simple, the middle as\n *  implement, the top as complex. */\nconst TIER_CLASS: Record<ModelTier, string> = {\n  haiku: \"simple\",\n  sonnet: \"implement\",\n  opus: \"complex\",\n};\n\n/** Which tier a model id belongs to: one of the CLI's tier aliases, or an\n *  exact match against a configured provider's models (a modelTiers override\n *  first, then fast → haiku tier, default → sonnet tier). null = no match. */\nexport function modelTier(\n  model: string,\n  providers?: Record<string, WorkerProvider>\n): ModelTier | null {\n  const m = model.toLowerCase();\n  if (m.includes(\"haiku\")) return \"haiku\";\n  if (m.includes(\"sonnet\")) return \"sonnet\";\n  if (m.includes(\"opus\")) return \"opus\";\n  if (providers) {\n    for (const p of Object.values(providers)) {\n      const override = p.modelTiers?.[model];\n      if (override) return override;\n      if (p.models.fast === model) return \"haiku\";\n      if (p.models.default === model) return \"sonnet\";\n    }\n  }\n  return null;\n}\n\n/** Model ids already warned about — one line per id, not one per run. */\nconst unmatchedTierLogged = new Set<string>();\n\n/** Map an agent's front-matter model to a worker class. An id that matches\n *  no tier is logged once and falls back to the middle tier's class rather\n *  than dropping the hint silently. */\nexport function modelToClass(\n  model: string | undefined,\n  providers?: Record<string, WorkerProvider>\n): string | undefined {\n  if (!model) return undefined;\n  const tier = modelTier(model, providers);\n  if (tier) return TIER_CLASS[tier];\n  if (!unmatchedTierLogged.has(model)) {\n    unmatchedTierLogged.add(model);\n    console.error(\n      `[agents] model \"${model}\" matches no known tier — ` +\n        `falling back to the ${TIER_CLASS.sonnet} class.`\n    );\n  }\n  return TIER_CLASS.sonnet;\n}\n\n/** Extra claude args the definition contributes (before the caller's own). */\nexport function agentClaudeArgs(def: AgentDef): string[] {\n  const args: string[] = [];\n  if (def.tools?.length) args.push(\"--allowedTools\", def.tools.join(\",\"));\n  args.push(\"--append-system-prompt\", def.body);\n  return args;\n}\n\n/** `<agent>: <first 50 chars of prompt>` — the default label for a run. */\nexport function agentLabel(name: string, prompt: string | null | undefined): string {\n  return `${name}: ${prompt ?? UNLABELED}`.slice(0, name.length + 2 + 50);\n}\n\n/**\n * Default `--label` for a bare `pai worker run` (no --chain/--agent, which\n * derive their own): the prompt's first non-blank line, whitespace-collapsed,\n * stripped of a leading markdown marker (#, *, -, >), truncated to 48 chars\n * with \"…\" appended if it was cut. An empty/whitespace-only prompt falls back\n * to \"worker <class>\" so the row is never blank.\n */\nexport function deriveLabel(prompt: string | null | undefined, klass: string): string {\n  const firstLine = (prompt ?? \"\")\n    .split(\"\\n\")\n    .map((l) => l.trim())\n    .find((l) => l.length > 0);\n  if (!firstLine) return `worker ${klass}`;\n  const stripped = firstLine.replace(/^[#*\\->]+\\s*/, \"\").replace(/\\s+/g, \" \").trim();\n  if (!stripped) return `worker ${klass}`;\n  return stripped.length > 48 ? `${stripped.slice(0, 48)}…` : stripped;\n}\n","/**\n * chatui.ts — the chat line of a `follow` pane.\n *\n * A follow pane with a target behaves like a small chat, Claude Code style:\n * the transcript lives in a terminal scroll region that ends three rows above\n * the pane's bottom; below it a separator rule row, then the two fixed rows —\n * the prompt row (`› `, readline line editing) and the ticker row. A transcript\n * line is inserted above the fixed rows with a save-cursor / scroll-region /\n * restore-cursor write that never touches them; the scroll region makes the\n * transcript roll inside itself. Everything here builds strings (or parses one\n * line), so the tests assert exact byte sequences — no terminal needed.\n */\n\n/** The prompt marker of the chat row. */\nexport const CHAT_PROMPT = \"› \";\n\n/** Dim hint shown once behind the cursor until the first line is typed. */\nexport const CHAT_HINT = \"type here and press Enter · /help for commands\";\n\n/** What `/help` prints (one command per line, dim). */\nexport const CHAT_HELP = [\n  \"/quit            close this pane\",\n  \"/resume <text>   continue the finished worker with <text>\",\n  \"/status          one-line worker status\",\n  \"your controls    exclusive clickr control to this worker (my controls takes it back)\",\n  \"anything else is sent to the worker — said while it runs, resumed after\",\n];\n\n// ---------------------------------------------------------------------------\n// visible width & wrapping (the gutter must stay the leftmost column)\n// ---------------------------------------------------------------------------\n\n/** Index just past the escape starting at `i` (CSI, OSC or a two-char one). */\nfunction endOfEscape(s: string, i: number): number {\n  const n = s[i + 1];\n  if (n === \"[\") {\n    let j = i + 2;\n    while (j < s.length && !(s[j]! >= \"@\" && s[j]! <= \"~\")) j++;\n    return Math.min(s.length, j + 1);\n  }\n  if (n === \"]\") {\n    let j = i + 2;\n    while (j < s.length && s[j] !== \"\\x07\") j++;\n    return Math.min(s.length, j + 1);\n  }\n  return i + 2;\n}\n\n/** Printable columns of `s` — ANSI escape sequences measure zero. */\nexport function visibleWidth(s: string): number {\n  let w = 0;\n  let i = 0;\n  while (i < s.length) {\n    if (s[i] === \"\\x1b\") {\n      i = endOfEscape(s, i);\n      continue;\n    }\n    w += 1;\n    i += 1;\n  }\n  return w;\n}\n\n/**\n * The SGR sequences in effect at `upto`: everything opened since the last\n * reset, in order. Anything that is not an SGR escape is ignored (it does\n * not change colour state).\n */\nfunction sgrStateAt(text: string, upto: number): string[] {\n  const open: string[] = [];\n  let i = 0;\n  while (i < Math.min(upto, text.length)) {\n    if (text[i] === \"\\x1b\") {\n      const end = endOfEscape(text, i);\n      const esc = text.slice(i, end);\n      if (/^\\x1b\\[[0-9;]*m$/.test(esc)) {\n        const params = esc.slice(2, -1);\n        const resets = params === \"\" || params.split(\";\").includes(\"0\");\n        if (resets) open.length = 0;\n        if (!(params === \"\" || params === \"0\")) open.push(esc);\n      }\n      i = end;\n      continue;\n    }\n    i += 1;\n  }\n  return open;\n}\n\n/**\n * Wrap one rendered row to `width` printable columns. Breaks on whitespace\n * where possible, hard-wraps words longer than the width, never splits an\n * ANSI escape, and re-opens the colours it wraps inside of, so a diff row\n * keeps its `-`/`+` colour on every continuation row.\n */\nexport function wrapText(text: string, width: number): string[] {\n  if (width < 1 || visibleWidth(text) <= width) return [text];\n\n  // visible characters by their index in `text`\n  const chars: number[] = [];\n  for (let i = 0; i < text.length; i++) {\n    if (text[i] === \"\\x1b\") {\n      i = endOfEscape(text, i) - 1;\n      continue;\n    }\n    chars.push(i);\n  }\n\n  // words as [first, last] indexes into `chars` (escapes ride along later)\n  const words: Array<{ s: number; e: number; w: number }> = [];\n  {\n    let s = -1;\n    let w = 0;\n    for (let k = 0; k <= chars.length; k++) {\n      const ch = k === chars.length ? \" \" : text[chars[k]!]!;\n      if (ch === \" \") {\n        if (s >= 0) {\n          words.push({ s, e: k - 1, w });\n          s = -1;\n          w = 0;\n        }\n      } else {\n        if (s < 0) s = k;\n        w++;\n      }\n    }\n  }\n  // a leading indent (diff rows) belongs to the first word, width counted\n  if (words.length && words[0]!.s > 0) {\n    words[0] = { s: 0, e: words[0]!.e, w: words[0]!.w + words[0]!.s };\n  }\n\n  // chunk spans [start, end] over `chars`, greedy on visible width — the\n  // width of a chunk is simply its span in `chars`, inner spaces included\n  const spans: Array<[number, number]> = [];\n  let cs = -1;\n  let ce = -1;\n  for (const word of words) {\n    if (word.w > width) {\n      // oversized word: fill the rest of the line, then full-width rows.\n      // `take` is the word's chars that still fit — the gap before the word\n      // eats into the room, and when it eats all of it the word starts fresh\n      const room = cs < 0 ? 0 : width - (ce - cs + 1);\n      const take = room > 0 ? ce + room - word.s + 1 : 0;\n      if (take > 0) spans.push([cs, ce + room]);\n      else if (cs >= 0) spans.push([cs, ce]);\n      let pos = word.s + Math.max(0, take);\n      let remaining = word.w - Math.max(0, take);\n      while (remaining > width) {\n        spans.push([pos, pos + width - 1]);\n        pos += width;\n        remaining -= width;\n      }\n      cs = pos;\n      ce = pos + remaining - 1;\n      continue;\n    }\n    if (cs < 0) {\n      cs = word.s;\n      ce = word.e;\n      continue;\n    }\n    if (word.e - cs + 1 <= width) {\n      ce = word.e;\n      continue;\n    }\n    spans.push([cs, ce]);\n    cs = word.s;\n    ce = word.e;\n  }\n  if (cs >= 0) spans.push([cs, ce]);\n\n  const out: string[] = [];\n  for (const [a, b] of spans) {\n    const from = chars[a]!;\n    // take trailing escapes up to the next visible char with the chunk\n    let end = chars[b]! + 1;\n    while (end < text.length && text[end] === \"\\x1b\") end = endOfEscape(text, end);\n    let piece = text.slice(from, end);\n    const reopen = sgrStateAt(text, from);\n    if (reopen.length) piece = reopen.join(\"\") + piece;\n    if (sgrStateAt(text, end).length) piece += \"\\x1b[0m\";\n    out.push(piece);\n  }\n  return out.length ? out : [\"\"];\n}\n\n// ---------------------------------------------------------------------------\n// the layout: scroll region + two fixed rows\n// ---------------------------------------------------------------------------\n\n/** Restrict scrolling to the transcript region (rows 1 … rows-3). */\nexport function chatScrollRegion(rows: number): string {\n  return `\\x1b[1;${Math.max(1, rows - 3)}r`;\n}\n\n/**\n * The separator row between the transcript and the prompt: cleared, then —\n * when the pane's width is known — a dim rule of `cols` box-drawing `─`\n * filling the row. `cols` 0 (unknown) keeps the row blank; `dim` is the\n * pane's colour helper, identity when colours are off.\n */\nexport function chatBlankRow(\n  rows: number,\n  cols = 0,\n  dim: (s: string) => string = (s) => s\n): string {\n  const rule = cols > 0 ? dim(\"─\".repeat(cols)) : \"\";\n  return `\\x1b[${Math.max(1, rows - 2)};1H\\x1b[K` + rule;\n}\n\n/**\n * Enter the chat layout: clear the pane, set the scroll region, draw the\n * separator row and park the cursor at column 3 of the prompt row (rows-1,\n * right after `› `). The ticker owns row `rows`.\n */\nexport function chatEnter(\n  rows: number,\n  cols = 0,\n  dim: (s: string) => string = (s) => s\n): string {\n  return (\n    \"\\x1b[2J\" + chatScrollRegion(rows) + chatBlankRow(rows, cols, dim) +\n    `\\x1b[${Math.max(1, rows - 1)};3H`\n  );\n}\n\n/** Leave it: reset the scroll region, show the cursor, drop to the last row. */\nexport function chatLeave(rows: number): string {\n  return \"\\x1b[r\\x1b[?25h\" + `\\x1b[${Math.max(1, rows)};1H`;\n}\n\n/**\n * Redraw the ticker on its own row and park the cursor back on the prompt\n * row at `parkCol` (default right after `› `): a ticker refresh never leaves\n * the cursor on the bottom row.\n */\nexport function chatTickerRow(text: string, rows: number, parkCol = 3): string {\n  return (\n    \"\\x1b7\" +\n    `\\x1b[${Math.max(1, rows)};1H\\x1b[K` + text +\n    `\\x1b[${Math.max(1, rows - 1)};${Math.max(1, parkCol)}H`\n  );\n}\n\n/**\n * The prompt row: the fixed `› ` prefix, then the input buffer — or, while\n * the buffer is empty, the dim placeholder behind the same prefix. The\n * cursor parks right after the buffer (`cursorAt` chars in, for a cursor\n * mid-draft), so typed text always starts at the column the placeholder\n * occupied, never glued to a hint.\n */\nexport function chatPromptRow(\n  rows: number,\n  buffer = \"\",\n  dim: (s: string) => string = (s) => s,\n  cursorAt?: number\n): string {\n  const rowN = Math.max(1, rows - 1);\n  const body = buffer !== \"\" ? buffer : dim(CHAT_HINT);\n  const col = 3 + Math.max(0, Math.min(cursorAt ?? buffer.length, buffer.length));\n  return `\\x1b[${rowN};1H\\x1b[K` + CHAT_PROMPT + body + `\\x1b[${rowN};${col}H`;\n}\n\nexport interface ChatInsert {\n  seq: string;\n  /** rows filled after this one (caps at regionRows, then it always scrolls). */\n  fill: number;\n}\n\n/**\n * Insert one transcript row above the fixed prompt/ticker rows. While the\n * region is still filling (`fill < regionRows`) the row is placed top-down;\n * once full, the cursor moves to the region's bottom row and a newline\n * scrolls the region up by one — the two fixed rows are never touched. The\n * user's cursor is saved before and restored after, so readline keeps its\n * position on the prompt row.\n */\nexport function chatInsertLine(line: string, fill: number, regionRows: number): ChatInsert {\n  const growing = fill < regionRows;\n  const seq =\n    \"\\x1b7\" +\n    (growing\n      ? `\\x1b[${fill + 1};1H${line}\\x1b[K`\n      : `\\x1b[${regionRows};1H\\n${line}\\x1b[K`) +\n    \"\\x1b8\";\n  return { seq, fill: Math.min(fill + 1, regionRows) };\n}\n\n// ---------------------------------------------------------------------------\n// prompt command parsing\n// ---------------------------------------------------------------------------\n\nexport type ChatAction =\n  | { kind: \"message\"; text: string }\n  | { kind: \"help\" }\n  | { kind: \"quit\" }\n  | { kind: \"status\" }\n  | { kind: \"resume\"; text: string }\n  | { kind: \"controls\"; who: \"you\" | \"me\" };\n\nconst CONTROLS_LINE = /^(your|my) controls\\.?$/i;\n\n/**\n * One submitted prompt line → what to do with it. `/help`, `/quit`,\n * `/status` and `/resume <text>` are commands (a bare `/resume` comes back\n * with empty text so the caller can print its usage); \"your controls\" /\n * \"my controls\" is the same `pai worker controls <id> you|me` action, never\n * forwarded to the worker as a normal chat line; anything else, including\n * any other `/word`, is a message for the worker.\n */\nexport function parseChatLine(raw: string): ChatAction {\n  const text = raw.trim();\n  if (text === \"/help\") return { kind: \"help\" };\n  if (text === \"/quit\") return { kind: \"quit\" };\n  if (text === \"/status\") return { kind: \"status\" };\n  if (text.startsWith(\"/resume\")) return { kind: \"resume\", text: text.slice(\"/resume\".length).trim() };\n  const controls = text.match(CONTROLS_LINE);\n  if (controls) return { kind: \"controls\", who: controls[1]!.toLowerCase() === \"your\" ? \"you\" : \"me\" };\n  return { kind: \"message\", text };\n}\n\n/**\n * The auto-exit countdown must not fire while the prompt holds unsent text:\n * true while it does. null/undefined (no prompt wired) never holds.\n */\nexport function holdAutoExit(promptText: string | null | undefined): boolean {\n  return typeof promptText === \"string\" && promptText.trim() !== \"\";\n}\n","/**\n * render.ts — turn worker events into the lines a human reads.\n *\n * Ports the glm-ps transcript rendering: the gutter rules (dim `>` for reads\n * and searches, `$` for shell, magenta `~` + red/green diff for edits, green\n * `+` for writes), Read-result trimming (first 3 lines then a count), and the\n * result footer. Colors are applied only when the output is a TTY, so MCP\n * tool output stays plain text.\n */\n\nimport { deadlineLabel } from \"./deadline.js\";\nimport { relative, basename } from \"node:path\";\nimport { ANTHROPIC_NATIVE, NATIVE_ANTHROPIC_MODELS, getProviderOrNative, readWorkersSection, type WorkersConfig } from \"./config.js\";\nimport { shortText } from \"./args.js\";\nimport { denialMark, parseDenialText } from \"./denials.js\";\nimport { bashExitCode, WAIT_EXIT_STILL_RUNNING } from \"./wait.js\";\nimport { fmtElapsed,waitingLine, waitOnCallLine, waitOnResultLine, detachedLine, realWaitDeps } from \"./waiting.js\";\nimport { ageOf, elapsedOf, contextLabel, contextFooter,contextPercent, isChatPane, type WorkerStatus, isLive, UNLABELED } from \"./status.js\";\nimport { ownedTree } from \"./worktree.js\";\nimport { workerDepth } from \"./tree.js\";\nimport { sessionTag } from \"./scope.js\";\nimport { endLabel } from \"./endreason.js\";\nimport { parseWorkerReport, renderReport } from \"./report.js\";\n\nexport type ColorEnabled = boolean;\n\nconst CODES = {\n  dim: \"2\",\n  bold: \"1\",\n  red: \"31\",\n  green: \"32\",\n  yellow: \"33\",\n  blue: \"34\",\n  mag: \"35\",\n  cyan: \"36\",\n} as const;\n\nexport type ColorName = keyof typeof CODES;\n\nexport function makeColor(enabled: ColorEnabled) {\n  return (name: ColorName, s: string): string =>\n    enabled ? `\\x1b[${CODES[name]}m${s}\\x1b[0m` : s;\n}\n\nexport type Paint = ReturnType<typeof makeColor>;\n\n/** Path relative to cwd when it lies inside it, otherwise unchanged. */\nexport function relPath(path: string, cwd: string): string {\n  if (!path || !cwd) return path;\n  let r: string;\n  try {\n    r = relative(cwd, path);\n  } catch {\n    return path;\n  }\n  return r.startsWith(\"..\") ? path : r;\n}\n\n/** Minimal line diff for Edit previews: common prefix/suffix, one hunk. */\nexport function unifiedDiffLines(oldStr: string, newStr: string): string[] {\n  const oldL = oldStr.split(\"\\n\");\n  const newL = newStr.split(\"\\n\");\n  let start = 0;\n  while (start < oldL.length && start < newL.length && oldL[start] === newL[start]) start++;\n  let endOld = oldL.length;\n  let endNew = newL.length;\n  while (endOld > start && endNew > start && oldL[endOld - 1] === newL[endNew - 1]) {\n    endOld--;\n    endNew--;\n  }\n  const out: string[] = [];\n  for (let i = start; i < endOld; i++) out.push(\"-\" + oldL[i]);\n  for (let i = start; i < endNew; i++) out.push(\"+\" + newL[i]);\n  return out;\n}\n\nexport interface ToolUseBlock {\n  type?: string;\n  text?: string;\n  name?: string;\n  id?: string;\n  input?: unknown;\n  /** tool_result blocks only: the call this answers. */\n  tool_use_id?: string;\n  is_error?: boolean;\n  content?: unknown;\n}\n\nexport interface StreamEventLike {\n  type?: string;\n  subtype?: string;\n  model?: string;\n  cwd?: string;\n  message?: { content?: ToolUseBlock[] };\n  result?: string;\n  is_error?: boolean;\n  num_turns?: number;\n  duration_ms?: number;\n  /** ISO stamp the runner attaches to every mirrored event (2g). */\n  _ts?: string;\n  /** Operator text (type: \"operator\"). */\n  text?: string;\n  /** Operator mirror of a handoff delivery — shown only as the ◆ inbox line. */\n  handoff?: boolean;\n  /** Handoff fields (type: \"handoff\", from the inbox tail). */\n  from?: string;\n  kind?: string;\n}\n\n/**\n * `HH:MM:SS` at an offset east of UTC in minutes (Date.getTimezoneOffset()\n * negated), from any ISO stamp the runner wrote — `Z` or a local `+HH:MM`.\n * null when the stamp cannot be parsed. Offsets make this testable without\n * depending on the machine's zone; the default is this machine's.\n */\nexport function clockOf(ts: string, offMin = -new Date().getTimezoneOffset()): string | null {\n  const t = Date.parse(ts);\n  if (Number.isNaN(t)) return null;\n  return new Date(t + offMin * 60_000).toISOString().slice(11, 19);\n}\n\n/** `YYYY-MM-DD` at the same offset — the local day a date separator shows. */\nexport function dayOf(ts: string, offMin = -new Date().getTimezoneOffset()): string | null {\n  const t = Date.parse(ts);\n  if (Number.isNaN(t)) return null;\n  return new Date(t + offMin * 60_000).toISOString().slice(0, 10);\n}\n\n/** The gutter of one rendered event: its three shapes and its width. */\nexport interface Gutter {\n  /** first row: `HH:MM:SS │ ` (dim). */\n  first: string;\n  /** later rows of one event, no wrapping: blanks of the same width. */\n  cont: string;\n  /** wrapped continuation rows: blank time, the `│` bar kept (dim). */\n  barCont: string;\n  /** printable columns first/cont/barCont occupy. */\n  width: number;\n}\n\n/**\n * The transcript gutter (2g): `HH:MM:SS │ ` from the event's `_ts`, dim, with\n * the worker tag in front when several run at once. Continuation lines get\n * blanks of the same width so wrapped text stays aligned; when the viewer\n * wraps lines itself, continuation rows carry the `│` bar instead (barCont)\n * so the bar runs unbroken down the pane. null when the event carries no\n * stamp (logs from before 2g render with the plain prefix). The time is the\n * stamp's wall clock at `offMin` — the default renders local time, whatever\n * zone stamped the log (old logs were stamped in UTC).\n */\nexport function gutterFor(\n  c: Paint,\n  e: { _ts?: string },\n  tag?: string,\n  offMin?: number\n): Gutter | null {\n  if (!e._ts) return null;\n  const time = clockOf(e._ts, offMin) ?? (e._ts.length >= 19 ? e._ts.slice(11, 19) : e._ts);\n  const head = tag ? `${tag} ${time}` : time;\n  const width = head.length + 3; // + \" │ \"\n  return {\n    first: c(\"dim\", `${head} │ `),\n    cont: \" \".repeat(width),\n    barCont: c(\"dim\", `${\" \".repeat(head.length)} │ `),\n    width,\n  };\n}\n\n/**\n * The ticker's tool part: `$ <command>` for Bash (first 60 chars), the file\n * basename for the file tools, the bare name for everything else.\n */\nexport function tickerTool(name: string, inp: unknown): string {\n  const i = (typeof inp === \"object\" && inp !== null ? inp : {}) as Record<string, unknown>;\n  const get = (k: string) => (typeof i[k] === \"string\" ? (i[k] as string) : \"\");\n  if (name === \"Bash\") return `$ ${shortText(get(\"command\").replace(/\\s+/g, \" \").trim(), 60)}`;\n  if (name === \"Read\" || name === \"Edit\" || name === \"Write\" || name === \"MultiEdit\") {\n    const base = get(\"file_path\").split(\"/\").pop() ?? \"\";\n    return base || name;\n  }\n  return name;\n}\n\n/**\n * The liveness line: `⋯ 12s · run tests before the fix · $ bun run test` —\n * seconds since the last *rendered* event, the worker's last stated intent\n * (its last assistant text, ≤60 chars) and the tool it is currently running.\n * Parts that are empty drop out.\n */\nexport function tickerText(secs: number, intent: string, tool: string, meter?: string | null): string {\n  const head = `⋯ ${secs}s`;\n  const parts = [intent, tool].map((p) => p.trim()).filter(Boolean);\n  const tail = parts.join(\" · \");\n  const line = tail ? `${head} · ${tail}` : head;\n  return meter ? `${line} · ${meter}` : line;\n}\n\n/** What the chat pane's status row shows (chatStatusRow formats it). */\nexport interface StatusRow {\n  provider: string;\n  model: string;\n  contextTokens?: number | null;\n  contextWindow?: number | null;\n  turns: number;\n  tools: number;\n  /** runtime so far in seconds; the finished row freezes its final value. */\n  elapsed: number;\n  /** seconds since the last rendered event (running only). */\n  idle?: number;\n  intent?: string;\n  tool?: string;\n  /** a finished state freezes the row with ✓/✗ instead of the ticker part. */\n  state?: string | null;\n  /** set while the run waits in the stagger gate for a cache warm-up. */\n  warmup?: { elapsedSec: number; limitSec: number } | null;\n  /** set while the run waits behind the provider cap (capacity gate). */\n  capacity?: { provider: string; cap: number; total: number; position: number; elapsedSec: number } | null;\n}\n\nexport { fmtElapsed };\n\n/**\n * The chat pane's status row (always visible while following):\n * `[glm/glm-5.3] ctx 84k/200k (42%) · turns 12 · tools 7 · 4m12s · ⋯ 7s · <intent> · <tool>`\n * — context yellow past 70 %, red past 85 %, dropped when unknown; once the\n * worker finished, the ticker part is replaced by `✓ done` / `✗ failed`.\n */\nexport function chatStatusRow(c: Paint, s: StatusRow): string {\n  const parts: string[] = [];\n  const pct = contextPercent(s);\n  if (pct !== null) {\n    const label = contextLabel(s);\n    parts.push(pct > 85 ? c(\"red\", label) : pct > 70 ? c(\"yellow\", label) : label);\n  }\n  parts.push(`turns ${s.turns}`, `tools ${s.tools}`, fmtElapsed(s.elapsed));\n  if (s.state && s.state !== \"running\" && s.state !== \"queued\") {\n    parts.push(s.state === \"done\" ? c(\"green\", \"✓ done\") : c(\"red\", \"✗ failed\"));\n  } else if (s.capacity) {\n    parts.push(c(\"yellow\", `queued: ${s.capacity.total} on ${s.capacity.provider}, cap ${s.capacity.cap} (position ${s.capacity.position})`));\n  } else if (s.warmup) {\n    parts.push(warmupText(s.warmup) as string);\n  } else {\n    parts.push(`⋯ ${Math.max(0, Math.floor(s.idle ?? 0))}s`);\n    for (const p of [s.intent, s.tool]) if (p && p.trim()) parts.push(p.trim());\n  }\n  const model = shortModel(s.model);\n  return `[${s.provider}${model ? \"/\" + model : \"\"}] ${parts.join(\" · \")}`;\n}\n\n/**\n * One blank line between turns, none inside one: a blank goes before an\n * assistant message that follows a tool result or an operator message (the\n * worker starting to speak again after its tools were answered / it was told\n * something), not between the text, tool calls and results of one turn.\n */\nexport function blankBetween(prev: { type?: string } | null, e: { type?: string }): boolean {\n  if (!prev) return false;\n  if (e.type !== \"assistant\") return false;\n  return prev.type === \"user\" || prev.type === \"operator\" || prev.type === \"handoff\";\n}\n\n/** The worker's last stated intent: the first line of its last text, ≤60. */\nexport function intentOf(text: string): string {\n  const first = text.trim().split(\"\\n\").find((l) => l.trim()) ?? \"\";\n  return shortText(first.trim().replace(/\\s+/g, \" \"), 60);\n}\n\n/**\n * The context meter `ctx 84k/200k (42%)` (contextLabel, shared with the\n * chat status row), yellow from 70 %, red from 85 %. null when the numbers\n * are missing or below `minPct` (the table only shows it past 60; the pane\n * liveness line always shows it).\n */\nexport function contextMeter(\n  c: Paint,\n  s: Pick<WorkerStatus, \"contextTokens\" | \"contextWindow\">,\n  minPct = 0\n): string | null {\n  const pct = contextPercent(s);\n  if (pct === null || pct <= minPct) return null;\n  const label = contextLabel(s);\n  if (pct > 85) return c(\"red\", label);\n  if (pct > 70) return c(\"yellow\", label);\n  return label;\n}\n\nfunction renderToolUse(\n  c: Paint,\n  prefix: string,\n  name: string,\n  inp: unknown,\n  cwd: string\n): string[] {\n  const i = (typeof inp === \"object\" && inp !== null ? inp : {}) as Record<string, unknown>;\n  const get = (k: string) => (typeof i[k] === \"string\" ? (i[k] as string) : \"\");\n  if (name === \"Read\") {\n    return [`${prefix}${c(\"dim\", \">\")} Reading ${relPath(get(\"file_path\"), cwd)}`];\n  }\n  if (name === \"Grep\" || name === \"Glob\") {\n    return [\n      `${prefix}${c(\"dim\", \">\")} Searching ${c(\"cyan\", get(\"pattern\"))} in ${relPath(get(\"path\") || \".\", cwd)}`,\n    ];\n  }\n  if (name === \"Bash\") {\n    // the job, not the mechanism: wait-on and detached starts read in plain words (raw command: `pai worker replay`)\n    const plain = waitOnCallLine(get(\"command\")) ?? detachedLine(get(\"command\"));\n    if (plain) return [`${prefix}${c(\"yellow\", plain)}`];\n    return [`${prefix}${c(\"dim\", \"$\")} ${shortText(get(\"command\"), 160)}`];\n  }\n  if (name === \"Edit\") {\n    const out = [`${prefix}${c(\"mag\", \"~\")} Editing ${relPath(get(\"file_path\"), cwd)}`];\n    for (const line of unifiedDiffLines(get(\"old_string\"), get(\"new_string\"))) {\n      if (line.startsWith(\"-\")) out.push(`${prefix}    ${c(\"red\", line)}`);\n      else if (line.startsWith(\"+\")) out.push(`${prefix}    ${c(\"green\", line)}`);\n      else out.push(`${prefix}    ${c(\"dim\", line)}`);\n    }\n    return out;\n  }\n  if (name === \"Write\") {\n    const n = get(\"content\").split(\"\\n\").length;\n    return [`${prefix}${c(\"green\", \"+\")} Writing ${relPath(get(\"file_path\"), cwd)} (${n} lines)`];\n  }\n  if (name === \"WebSearch\" || name === \"WebFetch\") {\n    return [`${prefix}${c(\"dim\", \">\")} ${name} ${shortText(get(\"query\") || get(\"url\"), 100)}`];\n  }\n  return [`${prefix}${c(\"dim\", \">\")} ${name} ${shortText(JSON.stringify(i), 120)}`];\n}\n\n/** Render one stream-json event; `tools` maps tool_use_id → tool name. */\nexport function renderEvent(\n  c: Paint,\n  prefix: string,\n  e: StreamEventLike,\n  cwd: string,\n  tools: Record<string, string>,\n  gutter?: { first: string; cont: string } | null\n): string[] {\n  const out: string[] = [];\n  if (e.type === \"system\" && e.subtype === \"init\") {\n    out.push(\n      `${prefix}${c(\"dim\", `worker started · model ${e.model ?? \"?\"} · cwd ${basename(e.cwd || cwd || \"\")}`)}`\n    );\n  } else if (e.type === \"operator\") {\n    // a handoff delivery is said to the worker AND tailed from the inbox —\n    // the transcript shows only the ◆ line, its mirror renders nothing\n    if (e.handoff) return out;\n    // split per line so the gutter continuation pads wrapped text\n    for (const ln of String(e.text ?? \"\").split(\"\\n\")) {\n      out.push(`${prefix}${c(\"cyan\", \"» \" + ln)}`);\n    }\n  } else if (e.type === \"handoff\") {\n    // a child's message from the inbox: ◆ from <id> · <kind>: <text>\n    for (const ln of String(e.text ?? \"\").split(\"\\n\")) {\n      out.push(`${prefix}${c(\"mag\", `◆ from ${e.from ?? \"?\"} · ${e.kind ?? \"?\"}: ${ln}`)}`);\n    }\n  } else if (e.type === \"assistant\") {\n    for (const b of e.message?.content ?? []) {\n      if (b.type === \"text\" && (b.text ?? \"\").trim()) {\n        for (const ln of (b.text ?? \"\").trim().split(\"\\n\")) out.push(`${prefix}${ln}`);\n      } else if (b.type === \"tool_use\") {\n        out.push(...renderToolUse(c, prefix, b.name ?? \"?\", b.input, cwd));\n      }\n    }\n  } else if (e.type === \"user\") {\n    for (const b of e.message?.content ?? []) {\n      if (b.type !== \"tool_result\") continue;\n      let content: unknown = (b as { content?: unknown }).content ?? \"\";\n      if (Array.isArray(content)) {\n        content = content\n          .map((x) => (typeof x === \"object\" && x !== null && \"text\" in x ? String((x as { text?: string }).text ?? \"\") : \"\"))\n          .join(\"\\n\");\n      }\n      const text = String(content);\n      const isError = (b as { is_error?: boolean }).is_error === true;\n      const waited = !isError && tools[(b as { tool_use_id?: string }).tool_use_id ?? \"\"] === \"Bash:wait-on\" ? waitOnResultLine(text) : null;\n      if (waited) {\n        out.push(`${prefix}${c(\"yellow\", waited)}`);\n      } else if (!isError && tools[(b as { tool_use_id?: string }).tool_use_id ?? \"\"] === \"Read\") {\n        // keep Read results as the tool returned them (`<lineno>\\t<code>`),\n        // only their count is summarised\n        const lines = text.split(\"\\n\");\n        for (const ln of lines.slice(0, 3)) out.push(`${prefix}${c(\"dim\", ln)}`);\n        if (lines.length > 3) {\n          out.push(`${prefix}${c(\"dim\", `    … ${lines.length} lines`)}`);\n        }\n      } else if (isError && tools[(b as { tool_use_id?: string }).tool_use_id ?? \"\"] === \"Bash:wait\" && bashExitCode(text) === WAIT_EXIT_STILL_RUNNING) {\n        out.push(`${prefix}${c(\"yellow\", \"… still running, waiting again\")}`);\n      } else if (isError) {\n        // guard/hook denials are expected friction (amber); other errors are real (red)\n        const denied = parseDenialText(text) !== null || / blocked:/.test(text);\n        out.push(`${prefix}    ${c(denied ? \"yellow\" : \"red\", \"! \" + shortText(text, 200))}`);\n      } else if (text.trim()) {\n        out.push(`${prefix}    ${c(\"dim\", shortText(text, 120))}`);\n      }\n    }\n  } else if (e.type === \"result\") {\n    const ok = !e.is_error;\n    const mark = ok ? c(\"green\", \"✓ done\") : c(\"red\", \"✗ failed\");\n    out.push(`${prefix}${mark} · ${e.num_turns ?? \"?\"} turns · ${Math.floor((e.duration_ms ?? 0) / 1000)}s`);\n    // a contract-compliant final message renders as the compact report block\n    const report = parseWorkerReport(String(e.result ?? \"\"));\n    if (report) {\n      out.push(...renderReport(c, prefix, report, cwd));\n    } else {\n      for (const ln of String(e.result ?? \"\").trim().split(\"\\n\")) {\n        out.push(`${prefix}  ${ln}`);\n      }\n    }\n  }\n  if (!gutter) return out;\n  return out.map((ln, i) => (i === 0 ? gutter.first : gutter.cont) + ln);\n}\n\n/** Transcript header: id, provider, label, session name, project dir. */\nexport function headerLine(\n  c: Paint,\n  s: {\n    id: string;\n    label: string;\n    cwd: string;\n    provider?: string;\n    session?: { name?: string } | null;\n    spec?: string | null;\n    reportFormat?: \"json\" | \"ag2\";\n    reportValid?: boolean;\n    reportErrors?: string[];\n    endReason?: string;\n    endBy?: string;\n  }\n): string {\n  const bits = [s.provider ? `[${s.provider}]` : \"\", sessionTag(s)].filter(Boolean).join(\" \");\n  const sep = bits ? `  ${bits}` : \"\";\n  const specBit = s.spec ? `  spec: ${s.spec}` : \"\";\n  // R! an AG2 report that failed `aibroker agentish check`; R? either the\n  // validator couldn't confirm it or a claimed changed path failed\n  // verification against the filesystem (see reportVerify in run.ts)\n  const reportBit =\n    s.reportValid === false\n      ? \"  \" + c(\"red\", s.reportFormat === \"ag2\" && (s.reportErrors ?? []).length ? \"R!\" : \"R?\")\n      : \"\";\n  const why = endLabel(s);\n  const endBit = why ? `  ended: ${why}` : \"\";\n  return c(\"bold\", `━━ ${s.id}${sep}  ${s.label}  (${basename(s.cwd)})${specBit}${reportBit}${endBit}`);\n}\n\n/** The chain label behind a stage label: strip the trailing \" · <stage>\". */\nfunction chainLabelOf(stages: WorkerStatus[]): string {\n  const first = stages[0];\n  if (!first) return \"\";\n  const suffix = first.stage ? ` · ${first.stage}` : \"\";\n  return first.label.endsWith(suffix) && suffix\n    ? first.label.slice(0, first.label.length - suffix.length)\n    : first.label;\n}\n\n/**\n * The ps table (RUNNING + FINISHED last 8) as a forest: a worker whose parent\n * is another worker renders indented under it (`├`/`└` connectors); a parent\n * that is not a worker is a chain id and gets its old `chain <id>` header.\n * `⎇` marks an unmerged worktree branch, `◆N` an inbox with N handoffs.\n */\n/** Delivery state of the latest note: pending until the worker's next tool call, then the delivery time. */\nfunction noteMark(s: WorkerStatus): string {\n  if (s.notePending?.length) return \" [note pending]\";\n  if (s.noteDeliveredAt) return ` [note delivered ${s.noteDeliveredAt.slice(11, 16)}]`;\n  return \"\";\n}\n\nexport function renderTable(\n  c: Paint,\n  statuses: WorkerStatus[],\n  scopeLabel: string,\n  now: Date = new Date(),\n  inbox: Record<string, number> = {},\n  workers: Pick<WorkersConfig, \"providers\" | \"nativeModels\"> = safeWorkers()\n): string {\n  const provTag = (s: WorkerStatus) => providerTag(s, workers);\n  const queued: WorkerStatus[] = [];\n  const running: WorkerStatus[] = [];\n  const done: WorkerStatus[] = [];\n  for (const s of statuses) {\n    if (s.state === \"queued\" && isLive(s)) queued.push(s);\n    else if (isLive(s)) running.push(s);\n    else {\n      if (s.state === \"running\") s.state = \"lost\";\n      done.push(s);\n    }\n  }\n  // QUEUED rows in grant order: each provider's waiters in the order the\n  // capacity gate grants them (the `capacity` field carries that position),\n  // providers grouped, then any queued status without a capacity field\n  const qKey = (s: WorkerStatus): [string, number] => [s.capacity?.provider ?? s.provider, s.capacity?.position ?? 1e9];\n  queued.sort((a, b) => {\n    const [pa, na] = qKey(a);\n    const [pb, nb] = qKey(b);\n    if (pa !== pb) return pa < pb ? -1 : 1;\n    if (na !== nb) return na - nb;\n    return a.id < b.id ? -1 : 1;\n  });\n  const isWorker = (id: string): boolean => statuses.some((s) => s.id === id);\n  // a chain id (no status file) groups its stages under a header instead\n  const chainOf = (s: WorkerStatus): string | null => (s.parent && !isWorker(s.parent) ? s.parent : null);\n  const treeLine = (line: string, chain: string | null, last: boolean): string => {\n    if (chain === null) return line;\n    const mark = last ? \"└\" : \"├\";\n    const bar = last ? \" \" : \"│\";\n    return line.startsWith(\"      \")\n      ? `  ${bar}   ${line.slice(6)}`\n      : `  ${mark} ${line.slice(2)}`;\n  };\n  // sub-workers: one connector level per depth under their worker parent\n  const rowPrefix = (depth: number, last: boolean): string =>\n    depth <= 0 ? \"  \" : \"  \" + \"│ \".repeat(depth - 1) + (last ? \"└ \" : \"├ \");\n  const rowCont = (depth: number, last: boolean): string =>\n    depth <= 0 ? \"      \" : \"  \" + \"│ \".repeat(depth - 1) + (last ? \"  \" : \"│ \");\n  const branchMark = (s: WorkerStatus): string =>\n    s.branch && !s.merged ? \"  \" + c(\"yellow\", \"⎇\" + (s.commits ? String(s.commits) : \"\")) : \"\";\n  // tree path relative to the worktrees dir, and the resume chain links\n  const treeMark = (s: WorkerStatus): string => {\n    const t = ownedTree(s);\n    const parts = [\n      ...(t ? [`tree ${basename(t.dir)}`] : []),\n      ...(s.pool?.slot ? [`slot ${basename(s.pool.slot)} #${s.pool.task}${s.pool.warm ? ` ${s.pool.warm}` : \"\"}`] : []),\n      ...(s.resumedFrom ? [`resumed from ${s.resumedFrom}`] : []),\n      ...(s.resumedBy ? [`resumed by ${s.resumedBy}`] : []),\n      ...(s.route ? [`route ${s.route.reason}`] : []),\n      ...(s.switchReason ? [s.switchReason] : []),\n      ...(s.fallThroughOf ? [`fall-through of ${s.fallThroughOf}`] : []),\n      ...(s.fallThroughTo ? [`fell through to ${s.fallThroughTo}`] : []),\n    ];\n    return parts.length ? \"  \" + c(\"dim\", parts.join(\"  \")) : \"\";\n  };\n  const inboxMark = (s: WorkerStatus): string =>\n    inbox[s.id] ? \" \" + c(\"mag\", `◆${inbox[s.id]}`) : \"\";\n  // \"R!\" an AG2 report that failed `aibroker agentish check`, \"R?\" either\n  // the validator couldn't confirm it (missing/unreadable CLI) or a claimed\n  // changed path failed verification against the filesystem — shown for\n  // json reports too in the verify-failure case\n  const reportMark = (s: WorkerStatus): string =>\n    s.reportValid === false\n      ? \"  \" + c(\"red\", s.reportFormat === \"ag2\" && (s.reportErrors ?? []).length ? \"R!\" : \"R?\")\n      : \"\";\n\n  const deniedMark = (s: WorkerStatus): string => {\n    const m = denialMark(s);\n    return m ? \"  \" + c(\"red\", m) : \"\";\n  };\n  const timeMark = (s: WorkerStatus): string => {\n    const l = deadlineLabel(s, now.getTime());\n    return l ? \"  \" + c(l === \"timed out\" || l.startsWith(\"OVERDUE\") ? \"red\" : \"dim\", l) : \"\";\n  };\n\n  const clock = `${String(now.getHours()).padStart(2, \"0\")}:${String(now.getMinutes()).padStart(2, \"0\")}:${String(now.getSeconds()).padStart(2, \"0\")}`;\n  const lines: string[] = [c(\"bold\", `Workers  ${clock}`), \"\"];\n  // the QUEUED section only exists while something waits: a table that never\n  // had a queue stays exactly the RUNNING/FINISHED table it always was\n  if (queued.length) {\n    lines.push(c(\"bold\", `QUEUED (${queued.length})`));\n    for (const s of queued) {\n      const cap = s.capacity;\n      const pos = cap\n        ? `position ${cap.position} of ${cap.total}, cap ${cap.cap}`\n        : `waiting for a ${s.provider} slot`;\n      lines.push(\n        `  ${c(\"cyan\", s.id)} ${provTag(s)} ${c(\"yellow\", pos)}  waited ${elapsedOf(s.started, now)}`\n      );\n      lines.push(`      task: ${s.label}  ${basename(s.cwd)}`);\n    }\n    lines.push(\"\");\n  }\n  lines.push(c(\"bold\", `RUNNING (${running.length})`));\n  if (!running.length) lines.push(\"  none\");\n  for (let i = 0; i < running.length; i++) {\n    const s = running[i];\n    const chain = chainOf(s);\n    if (chain) {\n      const prev = running[i - 1];\n      if (!prev || chainOf(prev) !== chain) {\n        const stages = running.filter((x) => chainOf(x) === chain);\n        lines.push(`  ${c(\"bold\", `chain ${chain}`)}  ${chainLabelOf(stages)}`);\n      }\n    }\n    const last =\n      !!chain && (i + 1 >= running.length || chainOf(running[i + 1]) !== chain);\n    const depth = workerDepth(statuses, s.id);\n    const subLast =\n      !chain && (i + 1 >= running.length || running[i + 1].parent !== s.parent);\n    const meter = contextMeter(c, s, 60);\n    const p = chain ? \"  \" : rowPrefix(depth, subLast);\n    const q = chain ? \"      \" : rowCont(depth, subLast);\n    // owner session tag on running rows too: in the MACHINE section every row\n    // must say whose worker it is (finished rows already carry it)\n    const tag = sessionTag(s);\n    lines.push(\n      treeLine(\n        `${p}${c(\"cyan\", s.id)}${inboxMark(s)} ${provTag(s)}${tag ? \" \" + tag : \"\"}  ${ageOf(s.started, now).padStart(4)} old  turns ${String(s.turns).padStart(2)}  tools ${String(s.tools).padStart(2)}  ${basename(s.cwd)}${branchMark(s)}${treeMark(s)}${timeMark(s)}${deniedMark(s)}${meter ? \"  \" + meter : \"\"}`,\n        chain,\n        last\n      )\n    );\n    lines.push(treeLine(`${q}task: ${s.label}`, chain, last));\n    if (s.note) lines.push(treeLine(`${q}${c(\"dim\", `note: ${s.note.replace(/\\s+/g, \" \").slice(0, 100)}${noteMark(s)}`)}`, chain, last));\n    lines.push(\n      treeLine(\n        s.waitingOn\n          ? `${q}${c(\"yellow\", waitingLine(s.waitingOn, now.getTime()))}`\n          : `${q}now:  ${c(\"yellow\", s.last)}  (${ageOf(s.updated, now)} ago)`,\n        chain,\n        last\n      )\n    );\n  }\n  lines.push(\"\");\n  lines.push(c(\"bold\", \"FINISHED (last 8)\"));\n  const doneSlice = done.slice(-8);\n  for (let i = 0; i < doneSlice.length; i++) {\n    const s = doneSlice[i];\n    const chain = chainOf(s);\n    if (chain) {\n      const prev = doneSlice[i - 1];\n      if (!prev || chainOf(prev) !== chain) {\n        const stages = doneSlice.filter((x) => chainOf(x) === chain);\n        lines.push(`  ${c(\"bold\", `chain ${chain}`)}  ${chainLabelOf(stages)}`);\n      }\n    }\n    const last =\n      !!chain && (i + 1 >= doneSlice.length || chainOf(doneSlice[i + 1]) !== chain);\n    const depth = workerDepth(statuses, s.id);\n    const subLast =\n      !chain && (i + 1 >= doneSlice.length || doneSlice[i + 1].parent !== s.parent);\n    const col = s.state === \"done\" ? \"green\" : s.state === \"lost\" ? \"yellow\" : \"red\";\n    const tag = sessionTag(s);\n    lines.push(\n      treeLine(\n        `${chain ? \"  \" : rowPrefix(depth, subLast)}${s.id}${inboxMark(s)} ${provTag(s)}${tag ? \" \" + tag : \"\"}  ${c(col, (s.state === \"lost\" ? \"? lost\" : s.state).padEnd(6))} rc=${s.rc}  ${String(s.secs ?? \"?\").padStart(4)}s  turns ${String(s.turns).padStart(2)}  tools ${String(s.tools).padStart(2)}  ${basename(s.cwd)}${branchMark(s)}${treeMark(s)}${timeMark(s)}${deniedMark(s)}${reportMark(s)}${endLabel(s) ? \"  \" + c(\"dim\", `[${endLabel(s)}]`) : \"\"}  ${s.label}`,\n        chain,\n        last\n      )\n    );\n  }\n  lines.push(\"\");\n  lines.push(c(\"dim\", \"worker follow        live transcript of running workers\"));\n  lines.push(c(\"dim\", \"worker <id>          replay one worker\"));\n  lines.push(c(\"dim\", scopeLabel));\n  return lines.join(\"\\n\");\n}\n\n/**\n * The one place a model id is compacted for display, so every renderer\n * shortens identically: the vendor prefix goes (the provider column already\n * says who serves it), a release-date suffix goes, version segments read as\n * dots, and a `[1m]` window marker is kept because it changes what the run\n * costs. `claude-opus-5[1m]` → `opus-5[1m]`, `claude-haiku-4-5-20251001` →\n * `haiku-4.5`, `glm-5.3[1m]` and `k3[1m]` unchanged. Empty in, empty out.\n */\nfunction safeWorkers(): Pick<WorkersConfig, \"providers\" | \"nativeModels\"> {\n  try {\n    return readWorkersSection().workers;\n  } catch {\n    return { providers: {}, nativeModels: NATIVE_ANTHROPIC_MODELS };\n  }\n}\n\n/** `[provider]`, or `[provider/model]` when the served model is not the\n *  provider's default (e.g. the router picked another). */\nexport function providerTag(\n  s: WorkerStatus,\n  workers: Pick<WorkersConfig, \"providers\" | \"nativeModels\">\n): string {\n  const model = shortModel(s.model);\n  const dflt = getProviderOrNative(workers, s.provider)?.models.default;\n  if (!model || (dflt && shortModel(dflt) === model)) return `[${s.provider}]`;\n  return `[${s.provider}/${model}]`;\n}\n\nexport function shortModel(model: string | null | undefined): string {\n  const raw = String(model ?? \"\").trim();\n  if (!raw) return \"\";\n  const wide = /\\[1m\\]$/i.test(raw);\n  let id = wide ? raw.slice(0, -4) : raw;\n  id = id.replace(/^(?:us\\.|eu\\.|apac\\.)?(?:anthropic|claude|openai|google|models)[./-]/i, \"\");\n  id = id.replace(/-\\d{8}$/, \"\");\n  // trailing numeric segments are one version: haiku-4-5 → haiku-4.5\n  const parts = id.split(\"-\");\n  const nums: string[] = [];\n  while (parts.length > 1 && /^\\d+(?:\\.\\d+)*$/.test(parts[parts.length - 1])) {\n    nums.unshift(parts.pop() as string);\n  }\n  if (nums.length) id = `${parts.join(\"-\")}-${nums.join(\".\")}`;\n  return wide ? `${id}[1m]` : id;\n}\n\n/** `waiting (warm-up) 7s/12s` for a run held in the stagger gate, else null. */\nexport function warmupText(w: { elapsedSec: number; limitSec: number } | null | undefined): string | null {\n  return w ? `waiting (warm-up) ${Math.max(0, Math.floor(w.elapsedSec))}s/${Math.floor(w.limitSec)}s` : null;\n}\n\n/**\n * The goal of a statusline row: what the worker is FOR, never what it is doing\n * this second. The operator's `--label` is the goal and is preferred over\n * anything the model wrote; an unlabelled run's label already holds its prompt\n * (see run.ts), so the same path shortens that to its first sentence, cut on a\n * word boundary. A run with neither label nor prompt reads \"unlabeled\". Width\n * fitting goes through shortText, the repo's one truncation helper.\n */\nexport function goalOf(s: Pick<WorkerStatus, \"label\">, max = 40): string {\n  const raw = String(s.label ?? \"\").trim();\n  if (!raw || raw === \"(no prompt)\") return UNLABELED;\n  const first = raw.split(/(?<=[.!?])\\s+/)[0] ?? raw;\n  if (first.length <= max) return shortText(first, max);\n  const cut = first.slice(0, max - 1).replace(/\\s+\\S*$/, \"\");\n  return shortText(`${cut || first.slice(0, max - 1)}…`, max);\n}\n\n/**\n * A worker pane's bottom line: `<goal> · <model> · started HH:MM · <age>` —\n * what the pane is FOR and how long it has run, never the tool call it\n * happens to be executing this second (that is `pai worker ps` / `follow`\n * territory). `columns`, when known, shrinks the goal so the fixed\n * `model · started · age` tail always survives — trimming that tail instead\n * would defeat the one thing an operator scanning several panes needs at a\n * glance. A legacy status with no recorded model omits that field rather\n * than rendering a bare gap.\n */\nexport function paneStatusRow(\n  s: Pick<WorkerStatus, \"label\" | \"model\" | \"started\" | \"contextUsed\" | \"contextWindow\" | \"waitingOn\" | \"denials\" | \"denialCount\" | \"warmup\" | \"capacity\">,\n  now: Date = new Date(),\n  columns: number | null = null\n): string {\n  const model = [shortModel(s.model), contextFooter(s)].filter(Boolean).join(\" · \");\n  const started = String(s.started ?? \"\").slice(11, 16);\n  const elapsed = elapsedOf(s.started, now);\n  const tail = [model, started ? `started ${started}` : \"\", elapsed, denialMark(s)].filter(Boolean).join(\" · \");\n  const budget = columns !== null ? Math.max(1, columns - tail.length - 3) : 40;\n  // a blocked worker's footer says what it waits on instead of its goal:\n  // the capacity queue first, then the stagger warm-up, then a wait-on job\n  const cap = s.capacity;\n  const head =\n    (cap ? `queued: ${cap.total} on ${cap.provider}, cap ${cap.cap} (position ${cap.position})` : null) ??\n    warmupText(s.warmup) ??\n    (s.waitingOn ? waitingLine(s.waitingOn, now.getTime(), realWaitDeps, Math.max(10, budget - 30)) : goalOf(s, budget));\n  return `${head} · ${tail}`;\n}\n\n/**\n * The statusline bar: `▶N (M nested) · <providers> · oldest <age>` and today's\n * ✓/✗ tail. `pai worker ps` has the full table and each pane its own bottom\n * line, so the bar only answers how many workers are running, on which\n * providers, and how long the oldest has been going. `▶N` counts every live\n * worker (the whole tree); `(M nested)` says how many of them were spawned by\n * another worker rather than by a session. `<providers>` lists the provider\n * names `pai worker providers` shows, most-populous first (ties by name), each\n * suffixed `×N` past one; native Anthropic runs show their short model name\n * (`sonnet-5.5`) since \"anthropic\" alone says nothing. No active-provider\n * head: it read as \"workers run on glm\" when none did, and the bar already\n * shows the session's provider elsewhere. `columns`, when known, shrinks only\n * the providers segment.\n */\nexport function renderStatusLine(\n  mine: WorkerStatus[],\n  now: Date = new Date(),\n  columns: number | null = null\n): string {\n  // isChatPane carries the migration shim for pre-`origin` entries (see\n  // status.ts): the chat pane is not a worker row and not counted in ▶N.\n  const running = mine.filter((s) => !isChatPane(s) && isLive(s));\n  const today = `${now.getFullYear()}-${String(now.getMonth() + 1).padStart(2, \"0\")}-${String(now.getDate()).padStart(2, \"0\")}`;\n  const doneToday = mine.filter((s) => s.state !== \"running\" && s.state !== \"queued\" && s.started.startsWith(today));\n  const ok = doneToday.filter((s) => s.state === \"done\").length;\n  const bad = doneToday.length - ok;\n  const tail = doneToday.length ? `   ✓${ok} ✗${bad} today` : \"\";\n  if (!running.length) return tail.trim();\n\n  // nested: spawned by another worker (its parent has a status file; a chain\n  // id or a session is a root, as in tree.ts workerDepth)\n  const ids = new Set(mine.map((s) => s.id));\n  const nested = running.filter((s) => s.parent && ids.has(s.parent)).length;\n  const head = `▶${running.length}${nested ? ` (${nested} nested)` : \"\"}`;\n\n  const counts = new Map<string, number>();\n  for (const s of running) {\n    const name = s.provider === ANTHROPIC_NATIVE ? shortModel(s.model) || s.provider : s.provider || \"?\";\n    counts.set(name, (counts.get(name) ?? 0) + 1);\n  }\n  const providersFull = [...counts.entries()]\n    .sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0]))\n    .map(([m, n]) => (n > 1 ? `${m} ×${n}` : m))\n    .join(\" · \");\n  const oldest = running.reduce((a, b) => (a.started < b.started ? a : b));\n  const oldestPart = `oldest ${ageOf(oldest.started, now)}`;\n\n  let providers = providersFull;\n  const fixedLen = head.length + 3 + oldestPart.length + tail.length; // + \" · \"\n  if (columns !== null && fixedLen + 3 + providersFull.length > columns) {\n    const budget = columns - fixedLen - 3;\n    providers = budget > 0 ? shortText(providersFull, budget) : \"\";\n  }\n  const mid = [providers, oldestPart].filter(Boolean).join(\" · \");\n  return `${head} · ${mid}${tail}`;\n}\n","/**\n * viewer.ts — ps / follow / replay / status line over the worker logDir.\n *\n * Scoping: workers launched from this terminal's AIBroker session (or, as the\n * fallback, its iTerm tab) unless --all or an explicit worker id is given.\n * Outside iTerm, everything degrades to \"all workers\" — the Python behaviour.\n *\n * Transcripts render with a `HH:MM:SS │ ` gutter (2g): dim, taken from the\n * `_ts` stamp on every mirrored event (local wall clock — stamps carry a local\n * offset and old UTC stamps are converted), the worker tag in front when\n * several run at once, a date separator when the day changes, and — on a TTY —\n * a liveness line (`⋯ 12s · run tests before the fix · $ bun run test`) that\n * is rewritten in place between events. Attaching to a worker that is already\n * running first replays its last events (backfill), then continues live.\n *\n * Following one worker turns the pane into a small chat (see chatui.ts): the\n * transcript scrolls in a region that ends two rows above the bottom, the\n * prompt row (`› `, readline editing) and the ticker row stay fixed, and every\n * submitted line is said to the worker while it runs and resumes it (same\n * Claude session) once it has finished. Lines the pane wraps itself keep the\n * `│` bar on continuation rows, so no content ever lands left of the bar.\n * Non-TTY output keeps the plain scrolling behaviour.\n */\n\nimport { existsSync, openSync, readSync, closeSync, readFileSync } from \"node:fs\";\nimport { createInterface } from \"node:readline\";\nimport { execFileSync, spawn, type SpawnOptions } from \"node:child_process\";\nimport { eventsPath, ledgerPath } from \"./paths.js\";\nimport { isChatPane, isLive, isTerminal, loadStatus, loadStatuses, ownsPid, reconcileStatuses, type WorkerStatus } from \"./status.js\";\nimport { currentTabKey, ownerSessionName, resolveSession, workerInScope } from \"./scope.js\";\nimport { readInbox } from \"./handoff.js\";\nimport { sayToWorker } from \"./operator.js\";\nimport { clickrControlsArgv, markControlsHeld } from \"./controls.js\";\nimport { appendLedger } from \"./ledger.js\";\nimport { closeOwnPane } from \"./pane.js\";\nimport {\n  CHAT_HELP,\n  chatBlankRow,\n  chatEnter,\n  chatInsertLine,\n  chatLeave,\n  chatPromptRow,\n  chatScrollRegion,\n  chatTickerRow,\n  holdAutoExit,\n  parseChatLine,\n  wrapText,\n} from \"./chatui.js\";\nimport {\n  blankBetween,\n  contextMeter,\n  dayOf,\n  gutterFor,\n  headerLine,\n  intentOf,\n  makeColor,\n  paneStatusRow,\n  renderEvent,\n  renderStatusLine,\n  renderTable,\n  tickerText,\n  tickerTool,\n  type Gutter,\n  type Paint,\n  type StatusRow,\n  type StreamEventLike,\n} from \"./render.js\";\nimport { parseWaitOn, waitingLine } from \"./waiting.js\";\nimport { denialLines } from \"./denials.js\";\nimport { lastCommand } from \"./tool-errors.js\";\nimport { isWaitPollCommand } from \"./wait.js\";\n\n/** Whether a Bash command ends in a `pai worker wait*` poll. */\nconst isWaitPoll = (cmd: string): boolean => {\n  const last = lastCommand(cmd);\n  return last !== null && isWaitPollCommand(last.segment);\n};\n\n/** How many existing events a fresh follow pane replays before going live. */\nexport const BACKFILL_EVENTS = 200;\n\n// ---------------------------------------------------------------------------\n// ps\n// ---------------------------------------------------------------------------\n\n/**\n * Live `pai worker run` processes on this machine that no live status file\n * owns: the cross-check that makes hiding a worker impossible even by\n * stripping its status file. Every legitimate spawn has a status (its own pid\n * plus its recorded parentPid — the zsh wrapper shell around the pai process,\n * which ps also shows naming the worker). Pane follows are views, not runs.\n */\nexport function strayWorkerProcesses(\n  statuses: Pick<WorkerStatus, \"pid\" | \"started\" | \"state\" | \"parentPid\">[],\n  psOut: string = execFileSync(\"ps\", [\"-axo\", \"pid=,command=\"], { encoding: \"utf8\" })\n): Array<{ pid: number; command: string }> {\n  const owned = new Set<number>();\n  for (const s of statuses) {\n    if ((s.state !== \"running\" && s.state !== \"queued\") || !ownsPid(s as WorkerStatus)) continue;\n    owned.add(s.pid);\n    if (s.parentPid && s.parentPid > 0) owned.add(s.parentPid);\n  }\n  const out: Array<{ pid: number; command: string }> = [];\n  for (const line of psOut.split(\"\\n\")) {\n    const t = line.trim();\n    if (!t) continue;\n    const at = t.indexOf(\" \");\n    if (at <= 0) continue;\n    const pid = Number(t.slice(0, at));\n    const command = t.slice(at + 1);\n    if (!Number.isInteger(pid) || pid <= 0 || owned.has(pid)) continue;\n    // anchored on the invocation lead: `pai worker run` or `node <…> worker\n    // run` (the pai bin is the runner's argv[1]). A substring search would\n    // flag every claude child whose PROMPT merely mentions `pai worker run`\n    // (observed live), and shell wrappers around a real run are owned through\n    // the run's recorded parentPid instead.\n    if (!/^(?:node \\S+ |pai )?worker run\\b/.test(command)) continue;\n    out.push({ pid, command: command.slice(0, 120) });\n  }\n  return out;\n}\n\n/**\n * The one `ps` face: this session's workers first (the tree it owns), then —\n * whenever live workers from other sessions exist — a MACHINE section listing\n * EVERY live worker on the host with its owner session, so no session can\n * look at its own truth while another session's worker runs unlisted. A\n * `--all` call already shows everything and gets no second section. Stray\n * `pai worker run` processes without a status file are appended as the\n * pgrep-level cross-check.\n */\nexport function psOutput(\n  logDir: string,\n  showAll: boolean,\n  env: NodeJS.ProcessEnv = process.env,\n  color = process.stdout.isTTY === true\n): string {\n  const c = makeColor(color);\n  const term = env.ITERM_SESSION_ID ?? \"\";\n  reconcileStatuses(logDir, new Date(), 0);\n  const statuses = loadStatuses(logDir);\n  const scoped = showAll || !term ? statuses : statuses.filter((s) => workerInScope(s, term));\n  const scopeLabel =\n    showAll || !term\n      ? \"scope: all workers\"\n      : resolveSession(term)\n        ? `scope: session ${resolveSession(term)!.name}`\n        : `scope: tab ${currentTabKey(env)} (this iTerm tab)`;\n  const inbox = inboxCounts(logDir, scoped);\n  const parts = [renderTable(c, scoped, scopeLabel, new Date(), inbox)];\n  // machine view: every live spawned worker on the host, whoever owns it —\n  // chat panes are terminals, not spawned workers, and never counted\n  const scopedIds = new Set(scoped.map((s) => s.id));\n  const machine = statuses\n    .filter((s) => !isChatPane(s) && isLive(s))\n    .map((s) => {\n      // owner session name on every row: registry lookup when the status\n      // itself does not carry one (\"?\" rows are the only ones left bare)\n      const name = ownerSessionName(s);\n      return name === \"?\" || s.session?.name === name\n        ? s\n        : { ...s, session: { id: s.session?.id ?? \"\", name } };\n    });\n  const foreign = machine.filter((s) => !scopedIds.has(s.id));\n  if (!showAll && term && foreign.length) {\n    const here = machine.length - foreign.length;\n    parts.push(\n      renderTable(\n        c,\n        machine,\n        `scope: MACHINE — every live worker on this host (${machine.length} running` +\n          `${here ? `, ${here} in this session` : \"\"}); the tag names each row's owner session`,\n        new Date(),\n        {}\n      )\n    );\n  }\n  const stray = strayWorkerProcesses(statuses);\n  if (stray.length) {\n    parts.push(\n      c(\"yellow\", `MACHINE cross-check: ${stray.length} pai worker run process(es) with no status file:`) +\n        \"\\n\" +\n        stray.map((s) => `  pid ${s.pid}  ${s.command}`).join(\"\\n\")\n    );\n  }\n  return parts.join(\"\\n\");\n}\n\n/** Handoffs waiting in each listed worker's inbox: id → count. */\nexport function inboxCounts(logDir: string, statuses: WorkerStatus[]): Record<string, number> {\n  const out: Record<string, number> = {};\n  for (const s of statuses) {\n    const n = readInbox(logDir, s.id).length;\n    if (n) out[s.id] = n;\n  }\n  return out;\n}\n\n// ---------------------------------------------------------------------------\n// one event → rendered lines (shared by replay, backfill and the live tail)\n// ---------------------------------------------------------------------------\n\n/** What applyEvent() carries between the events of one transcript. */\nexport interface FollowState {\n  /** day separator already printed (\"\" before the first stamped event). */\n  lastDay: string;\n  /** tool_use id → tool name (Edit previews and Read trimming need it). */\n  tools: Record<string, string>;\n  /** the worker's last stated intent — its last assistant text, ≤60 chars. */\n  intent: string;\n  /** the ticker's tool part of the last tool_use (\"$ bun run test\"). */\n  tool: string;\n  /** the last event seen, for the blank line between turns. */\n  prev: StreamEventLike | null;\n}\n\nexport function initialFollowState(intent = \"waiting for first event\"): FollowState {\n  return { lastDay: \"\", tools: {}, intent, tool: \"\", prev: null };\n}\n\n/** One applied event: what to print, and how the ticker changes. */\nexport interface FollowStep {\n  /** rendered lines (\"\" among them marks the blank line between turns). */\n  lines: string[];\n  /** day separator to print first, when the stamp's local day changed. */\n  day: string | null;\n  /** the event produced visible output — the ticker clock restarts. */\n  activity: boolean;\n  state: FollowState;\n}\n\n/**\n * Gutter the rendered body of one event, wrapping when the pane width is\n * known. Unwrapped (null `wrapWidth`, e.g. piped output): the first row gets\n * the stamped gutter, later rows of the event blanks — exactly the pre-chat\n * rendering. Wrapped: every row is folded at `wrapWidth` columns and each\n * continuation row carries the blank gutter with the `│` bar, so the bar runs\n * unbroken down the pane and no content ever lands left of it.\n */\nexport function gutterBody(\n  body: string[],\n  gutter: Gutter | null,\n  wrapWidth: number | null\n): string[] {\n  if (!gutter) return body;\n  if (wrapWidth === null || wrapWidth <= gutter.width) {\n    return body.map((ln, i) => (i === 0 ? gutter.first : gutter.cont) + ln);\n  }\n  const out: string[] = [];\n  for (const ln of body) {\n    for (const piece of wrapText(ln, wrapWidth - gutter.width)) {\n      out.push((out.length === 0 ? gutter.first : gutter.barCont) + piece);\n    }\n  }\n  return out;\n}\n\n/**\n * Render one event and advance the follow state. Everything the viewer shows\n * between events of one worker comes from here: replay, the backfill on\n * attach and the live tail all use it, so they space identically — events\n * back to back, one blank line between turns. `activity` is false for events\n * that render nothing (stream noise, empty tool results): they leave the\n * ticker's \"since last event\" clock running. `wrapWidth` (the pane's column\n * count, re-read on resize) makes the viewer wrap rows itself; null keeps\n * the terminal's own wrapping.\n */\nexport function applyEvent(\n  c: Paint,\n  s: FollowState,\n  e: StreamEventLike,\n  cwd: string,\n  tag?: string,\n  offMin?: number,\n  wrapWidth?: number | null\n): FollowStep {\n  const tools = { ...s.tools };\n  if (e.type === \"assistant\") {\n    for (const b of e.message?.content ?? []) {\n      if (b.type === \"tool_use\" && b.id) {\n        const cmd = (b.input as { command?: unknown } | undefined)?.command;\n        const bashCmd = b.name === \"Bash\" && typeof cmd === \"string\" ? cmd : null;\n        tools[b.id] = bashCmd && parseWaitOn(bashCmd) ? \"Bash:wait-on\" : bashCmd && isWaitPoll(bashCmd) ? \"Bash:wait\" : (b.name ?? \"?\");\n      }\n    }\n  }\n  const day = typeof e._ts === \"string\" ? (dayOf(e._ts, offMin) ?? rawDay(e._ts)) : \"\";\n  const state: FollowState = {\n    lastDay: day && day !== s.lastDay ? day : s.lastDay,\n    tools,\n    intent: s.intent,\n    tool: s.tool,\n    prev: e,\n  };\n  if (e.type === \"assistant\") {\n    for (const b of e.message?.content ?? []) {\n      if (b.type === \"text\" && (b.text ?? \"\").trim()) state.intent = intentOf(b.text ?? \"\");\n      else if (b.type === \"tool_use\") state.tool = tickerTool(b.name ?? \"?\", b.input);\n    }\n  }\n  const gutter = gutterFor(c, e, tag, offMin);\n  const prefix = \"\";\n  const body = gutterBody(renderEvent(c, prefix, e, cwd, tools), gutter, wrapWidth ?? null);\n  // the turn separator carries the gutter's bar (barCont) so the │ runs\n  // unbroken down the pane; \"\" only when the event has no stamp/gutter\n  const lines = blankBetween(s.prev, e) ? [gutter ? gutter.barCont : \"\", ...body] : body;\n  return {\n    lines,\n    day: day && day !== s.lastDay ? day : null,\n    activity: lines.some((ln) => ln !== \"\"),\n    state,\n  };\n}\n\n/** `YYYY-MM-DD` straight out of an unparsable stamp, \"\" when it has none. */\nfunction rawDay(ts: string): string {\n  return /^\\d{4}-\\d{2}-\\d{2}/.test(ts) ? ts.slice(0, 10) : \"\";\n}\n\n/**\n * The events a fresh follow replays before going live: the last `cap`\n * non-empty log lines, oldest first.\n */\nexport function backfillLines(raw: string, cap = BACKFILL_EVENTS): string[] {\n  return raw.split(\"\\n\").filter((l) => l.trim()).slice(-cap);\n}\n\n// ---------------------------------------------------------------------------\n// replay\n// ---------------------------------------------------------------------------\n\n/** The rendered transcript of one worker, from the start, as one string. */\nexport function replayOutput(\n  logDir: string,\n  wid: string,\n  color = process.stdout.isTTY === true,\n  tailLines?: number\n): string {\n  const path = eventsPath(logDir, wid);\n  if (!existsSync(path)) {\n    throw new Error(`no event log for ${wid}`);\n  }\n  const c = makeColor(color);\n  const st =\n    loadStatuses(logDir).find((s) => s.id === wid) ??\n    ({ id: wid, label: \"\", cwd: \"\", provider: \"\" } as WorkerStatus);\n  const wrapWidth = typeof process.stdout.columns === \"number\" ? process.stdout.columns : null;\n  const out: string[] = [headerLine(c, st), ...denialLines(st)];\n  const raw = readFileSync(path, \"utf8\");\n  const lines = tailLines !== undefined ? raw.trimEnd().split(\"\\n\").slice(-tailLines) : raw.split(\"\\n\");\n  // the worker's inbox handoffs join the transcript where they happened (_ts)\n  const handoffs: StreamEventLike[] = readInbox(logDir, wid).map((h) => ({\n    type: \"handoff\",\n    from: h.from,\n    kind: h.kind,\n    text: h.text,\n    _ts: h._ts,\n  }));\n  let state = initialFollowState(\"\");\n  const events: StreamEventLike[] = [];\n  for (const line of lines) {\n    if (!line.trim()) continue;\n    let e: StreamEventLike;\n    try {\n      e = JSON.parse(line) as StreamEventLike;\n    } catch {\n      continue;\n    }\n    events.push(e);\n  }\n  const stamp = (e: StreamEventLike): number => {\n    const t = e._ts ? Date.parse(e._ts) : NaN;\n    return Number.isNaN(t) ? 0 : t;\n  };\n  const merged = [...events, ...handoffs].sort((a, b) => stamp(a) - stamp(b));\n  for (const e of merged) {\n    const step = applyEvent(c, state, e, st.cwd ?? \"\", undefined, undefined, wrapWidth);\n    if (step.day) out.push(c(\"dim\", `── ${step.day} ──`));\n    out.push(...step.lines);\n    state = step.state;\n  }\n  return out.join(\"\\n\");\n}\n\n/** Entries `follow <id>` prints when there is no terminal to stream to. */\nexport const FOLLOW_TAIL_ENTRIES = 20;\n\n/**\n * `follow <id>` without a terminal (stdout not a TTY, or PAI_WORKER=1) would\n * never exit; unless --auto-exit or --live asks for streaming it prints the\n * transcript tail instead. Returns that text, or null when follow should run.\n */\nexport function followTailOutput(\n  logDir: string,\n  target: string | null,\n  opts: { live: boolean; autoExit: boolean; tail?: number },\n  env: NodeJS.ProcessEnv = process.env,\n  isTTY = process.stdout.isTTY === true,\n  err: (s: string) => void = (s) => process.stderr.write(s)\n): string | null {\n  if (!target || opts.live || opts.autoExit) return null;\n  if (isTTY && env.PAI_WORKER !== \"1\") return null;\n  const n = opts.tail !== undefined && opts.tail > 0 ? opts.tail : FOLLOW_TAIL_ENTRIES;\n  const text = replayOutput(logDir, target, false, n);\n  err(`follow: no terminal, printed the last ${n} entries (use --live to stream)\\n`);\n  return text;\n}\n\n// ---------------------------------------------------------------------------\n// follow\n// ---------------------------------------------------------------------------\n\ninterface FollowHandle {\n  fd: number;\n  buf: string;\n}\n\n/**\n * The follow exit decision for one worker: it is over once its result event\n * was rendered, or once its status reached a terminal state — pooled\n * runs keep their pid alive after the status says done, so the pid is no\n * evidence; a worker killed without writing a result still ends. A status never read\n * (undefined) means \"not over\": follow keeps waiting for the first event.\n */\nexport function workerEnded(\n  resultRendered: boolean,\n  state: WorkerStatus[\"state\"] | undefined\n): boolean {\n  return resultRendered || isTerminal(state);\n}\n\n// ---------------------------------------------------------------------------\n// operator input (2i): this pane's stdin drives say / resume\n// ---------------------------------------------------------------------------\n\n/** What makeOperatorInput() needs from the follow around it. */\nexport interface OperatorInputDeps {\n  /** the worker typed lines go to right now (null: none, lines are ignored). */\n  target: () => string | null;\n  /** forwards one message to a running worker. */\n  say: (id: string, text: string) => Promise<string>;\n  /** whether a status file exists for the id (say failed → resume, or note). */\n  workerKnown: (id: string) => boolean;\n  /** continues a finished worker (same Claude session). */\n  resume: (text: string, id: string) => void;\n  /** one line of feedback in the pane. */\n  note: (s: string) => void;\n  paint: Paint;\n  /** chat mode only: the echoed line replaces the \"» sent\" note. */\n  sent?: (id: string) => void;\n}\n\n/**\n * One typed stdin line → say (worker running) or resume (worker finished):\n * the operator channel of a `follow <id>` pane. Trimmed; empty lines and a\n * missing target are ignored.\n */\nexport function makeOperatorInput(d: OperatorInputDeps): (raw: string) => void {\n  return (raw: string) => {\n    const text = raw.trim();\n    if (!text) return;\n    const id = d.target();\n    if (id === null) return;\n    d.say(id, text).then(\n      () => (d.sent ? d.sent(id) : d.note(d.paint(\"dim\", `» sent to ${id}`))),\n      (e: Error) => {\n        if (d.workerKnown(id)) d.resume(text, id);\n        else d.note(d.paint(\"red\", `» ${e.message}`));\n      }\n    );\n  };\n}\n\n/** What followWorkers writes to (process.stdout, or a fake in tests). */\nexport interface FollowStream {\n  write(s: string): boolean;\n  isTTY?: boolean;\n  columns?: number;\n  rows?: number;\n  on?(event: \"resize\", fn: () => void): unknown;\n  removeListener?(event: \"resize\", fn: () => void): unknown;\n}\n\n/** The child of a `pai worker resume` spawn (tests inject a fake). */\nexport interface ResumeChild {\n  stdout?: { on(event: \"data\", cb: (chunk: Buffer) => void): unknown };\n  on(event: \"close\", cb: (code: number | null) => void): unknown;\n}\n\n/** The child of a clickr controls spawn (tests inject a fake). */\nexport interface ControlsChild {\n  stdout?: { on(event: \"data\", cb: (chunk: Buffer) => void): unknown };\n  stderr?: { on(event: \"data\", cb: (chunk: Buffer) => void): unknown };\n  on(event: \"close\", cb: (code: number | null) => void): unknown;\n}\n\n/** Test seams for followWorkers: the streams, the resume spawn, the prompt. */\nexport interface FollowIO {\n  stdin?: NodeJS.ReadableStream;\n  stdout?: FollowStream;\n  /** replaces the `pai worker resume` spawn (tests record instead of run). */\n  spawnResume?: (id: string, text: string) => ResumeChild;\n  /** replaces the clickr controls spawn (tests record instead of run). */\n  spawnControls?: (id: string, who: \"you\" | \"me\", pid: number | undefined) => ControlsChild;\n  /** current unsent prompt text (tests force a draft to hold the countdown). */\n  promptLine?: () => string;\n}\n\n/**\n * Tail one worker (target) or the running workers of this scope, live.\n * Workers whose event log already exists are first replayed (last\n * BACKFILL_EVENTS events), then tailed. Auto-exit: with a target, wait\n * `autoExit` seconds after its end; without one, exit once no worker in\n * scope has run for that many seconds in a row, never within the first 30 s.\n *\n * With a target on a TTY the pane becomes a chat (chatui.ts): transcript in\n * a scroll region, fixed prompt and ticker rows, submitted lines said to the\n * worker (or resuming it after it finished) and echoed as `»` rows. A draft\n * in the prompt holds the auto-exit countdown. Non-TTY output keeps the\n * plain scrolling behaviour; FORCE_TTY=1 emits the chat layout over a pipe.\n */\nexport async function followWorkers(\n  logDir: string,\n  target: string | null,\n  showAll: boolean,\n  autoExit: number,\n  env: NodeJS.ProcessEnv = process.env,\n  color = process.stdout.isTTY === true,\n  io?: FollowIO\n): Promise<void> {\n  const c = makeColor(color);\n  const out_ = io?.stdout ?? process.stdout;\n  const in_ = io?.stdin ?? process.stdin;\n  // A write to a pane that just closed (EPIPE/ENXIO) or is mid-resize throws\n  // synchronously; unguarded, that crashes the whole follow process, which\n  // the pai-worker profile's Close Sessions On End then closes with nothing\n  // left on screen to explain why. Every direct write to `out_` goes through\n  // here instead, so the pane can only ever go quiet, never vanish for it.\n  const safeWrite = (s: string): void => {\n    try {\n      out_.write(s);\n    } catch {\n      /* unwritable pane — the tick loop's PANE-CLOSED ledger line is the record */\n    }\n  };\n  // FORCE_TTY=1: the TTY layout over a pipe (tests, recorded panes)\n  const tty = out_.isTTY === true || env.FORCE_TTY === \"1\";\n  const term = env.ITERM_SESSION_ID ?? \"\";\n  // iTerm user variable: lets AIBroker leave worker panes out of its Claude\n  // session list. Real TTY only (not FORCE_TTY); no tmux passthrough helper exists.\n  if (out_.isTTY === true && target) {\n    safeWrite(`\\x1b]1337;SetUserVar=paiWorkerPane=${Buffer.from(target).toString(\"base64\")}\\x07`);\n  }\n  const scopeTab = target || showAll ? \"\" : currentTabKey(env);\n  const handles = new Map<string, FollowHandle>();\n  const seenHeader = new Set<string>();\n  const finished = new Set<string>();\n  // handoffs already rendered per worker (id → inbox lines shown so far)\n  const inboxSeen = new Map<string, number>();\n  const states = new Map<string, FollowState>();\n  const started = Date.now();\n  let idleSince: number | null = null;\n  let aborted = false;\n  // why this pane's follow last exited — recorded in the ledger's PANE-CLOSED\n  // line on every exit (a crash closes the pane instantly under the\n  // Close-Sessions-On-End profile, so the ledger is often the only surviving\n  // record of why)\n  let exitReason = \"aborted\";\n  let consecutiveErrors = 0;\n  const MAX_CONSECUTIVE_ERRORS = 10;\n  // liveness state: rewritten in place between events, TTY only\n  let lastEventAt = Date.now();\n  let meterStatus: WorkerStatus | null = null;\n  // the pane's bottom line (chat mode): the target's current status, kept\n  // fresh every loop tick (not only on a new event) so a `pai worker goal`\n  // relabel shows up on the pane's next refresh, not its next tool call\n  let paneStatus: WorkerStatus | undefined;\n  const onInt = () => {\n    aborted = true;\n  };\n  process.once(\"SIGINT\", onInt);\n\n  // --- the chat layout (target + TTY): transcript region, a blank separator\n  // row, then the two fixed rows (prompt, ticker)\n  const chat = tty && target !== null;\n  let rows = out_.rows ?? 24;\n  const columns = (): number | null => (typeof out_.columns === \"number\" ? out_.columns : null);\n  let fill = 0; // transcript rows filled since the region was (re)set\n  const regionRows = () => Math.max(1, rows - 3);\n  // the rendered transcript, kept so a resize can replay it onto the cleared\n  // pane (chat mode only; capped so a long run cannot grow without bound)\n  const retained: string[] = [];\n  const RETAIN_CAP = 500;\n  /** Every line the pane shows goes through here: plain newline, or a row\n   *  inserted above the fixed prompt/ticker rows (chatui.chatInsertLine). */\n  const out = (line: string, keep = true) => {\n    if (!chat) {\n      safeWrite(line + \"\\n\");\n      return;\n    }\n    if (keep) {\n      retained.push(line);\n      if (retained.length > RETAIN_CAP) retained.splice(0, retained.length - RETAIN_CAP);\n    }\n    const r = chatInsertLine(line, fill, regionRows());\n    safeWrite(r.seq);\n    fill = r.fill;\n  };\n\n  // The ticker redraws its line in place: in the chat layout that is its own\n  // bottom row (save-cursor, draw, restore-cursor); the plain mode writes\n  // CR + erase-to-end-of-line, never a newline. The control bytes live in\n  // their own string literals — bundling them onto a template literal makes\n  // the bundler fold them in as raw chars, and a raw CR inside a template\n  // literal is normalised to LF by the language, which is how the ticker\n  // once scrolled a blank line per tick.\n  const eraseLiveness = () => {\n    lastLiveness = \"\";\n    if (chat) return;\n    if (tty) safeWrite(\"\\r\\x1b[K\");\n  };\n  let ticker = initialFollowState();\n  // the chat ticker row doubles as the worker's status line: provider/model,\n  // context meter, turns, tools, runtime — frozen with ✓/✗ once it finished\n  const statusRowOf = (st: WorkerStatus, secs: number): StatusRow => {\n    const fin = finished.has(st.id);\n    const startedAt = Date.parse((st.started ?? \"\").replace(\" \", \"T\"));\n    const elapsed =\n      fin && st.secs !== null\n        ? st.secs\n        : Number.isNaN(startedAt)\n          ? 0\n          : Math.floor((Date.now() - startedAt) / 1000);\n    return {\n      provider: st.provider,\n      model: st.model,\n      contextTokens: st.contextTokens,\n      contextWindow: st.contextWindow,\n      turns: st.turns,\n      tools: st.tools,\n      elapsed,\n      idle: secs,\n      intent: ticker.intent,\n      tool: waitingNow() ?? ticker.tool,\n      state: fin ? (st.state === \"running\" ? \"done\" : st.state) : null,\n      warmup: st.warmup ?? null,\n      capacity: st.capacity ?? null,\n    };\n  };\n  // what a blocked worker waits on, from the freshest status the pane has\n  const waitingNow = (): string | null => {\n    const w = (paneStatus ?? meterStatus)?.waitingOn;\n    return w ? waitingLine(w) : null;\n  };\n  let lastLiveness = \"\";\n  /** write the ticker only when its text changed — an idle pane stays silent */\n  const safeWriteLiveness = (s: string) => {\n    if (s === lastLiveness) return;\n    lastLiveness = s;\n    safeWrite(s);\n  };\n  const writeLiveness = () => {\n    if (!tty) return;\n    // clock shown in 5 s steps: a ticking second would repaint the pane forever\n    const now5 = Math.floor(Date.now() / 5000) * 5000;\n    const secs = Math.max(0, Math.floor((now5 - lastEventAt) / 5000) * 5);\n    if (chat) {\n      // the pane's bottom line: goal · model · started · age, never the tool\n      // call this second (see paneStatusRow) — before the first status file\n      // exists there is nothing to show it from yet, so the plain ticker\n      // covers that brief startup window only\n      const text = paneStatus\n        ? paneStatusRow(paneStatus, new Date(now5), columns())\n        : tickerText(secs, ticker.intent, ticker.tool);\n      safeWriteLiveness(chatTickerRow(text, rows, promptCursorCol()));\n    } else {\n      const meter = meterStatus ? contextMeter(c, meterStatus) : null;\n      safeWriteLiveness(\n        \"\\r\\x1b[K\" + tickerText(secs, ticker.intent, waitingNow() ?? ticker.tool, meter)\n      );\n    }\n  };\n\n  const runningIds = (): string[] =>\n    loadStatuses(logDir)\n      .filter(\n        (s) =>\n          isLive(s) &&\n          (target !== null || showAll || (scopeTab ? workerInScope(s, term) : true))\n      )\n      .map((s) => s.id);\n\n  // --- one rendered event, shared by the backfill and the live tail\n  const emitEvent = (e: StreamEventLike, wid: string, st: WorkerStatus, multi: boolean) => {\n    if (e.type === \"operator\" && chat && suppressMirror(String(e.text ?? \"\"))) return;\n    if (!seenHeader.has(wid)) {\n      eraseLiveness();\n      out(headerLine(c, st));\n      seenHeader.add(wid);\n    }\n    const state = states.get(wid) ?? initialFollowState();\n    const step = applyEvent(\n      c,\n      state,\n      e,\n      st.cwd ?? \"\",\n      multi ? c(\"cyan\", wid.slice(-4)) : undefined,\n      undefined,\n      columns()\n    );\n    if (step.day) {\n      out(c(\"dim\", `── ${step.day} ──`));\n    }\n    states.set(wid, step.state);\n    if (wid === target) ticker = step.state;\n    eraseLiveness();\n    for (const ln of step.lines) {\n      out(ln);\n    }\n    if (step.activity) lastEventAt = Date.now();\n    if (e.type === \"result\") {\n      meterStatus = st;\n      finished.add(wid);\n    } else if (wid === target || target === null) {\n      meterStatus = st;\n    }\n  };\n\n  // --- attach: replay what is already in the log, then tail from its end\n  const attachHandle = (wid: string, path: string, st: WorkerStatus, multi: boolean): FollowHandle => {\n    const handle = { fd: openSync(path, \"r\"), buf: \"\" };\n    try {\n      const existing = readFileSync(path, \"utf8\");\n      if (existing.trim()) {\n        for (const line of backfillLines(existing)) {\n          let e: StreamEventLike;\n          try {\n            e = JSON.parse(line) as StreamEventLike;\n          } catch {\n            continue;\n          }\n          emitEvent(e, wid, st, multi);\n        }\n      } else {\n        // no event yet: show the header now, not at the first event\n        if (!seenHeader.has(wid)) {\n          out(headerLine(c, st));\n          seenHeader.add(wid);\n        }\n      }\n      // the backfill already rendered the file; the live tail starts at EOF\n      const sink = Buffer.alloc(65536);\n      for (;;) {\n        let n: number;\n        try {\n          n = readSync(handle.fd, sink, 0, sink.length, null);\n        } catch {\n          break;\n        }\n        if (n <= 0) break;\n      }\n    } catch {\n      // unreadable log: tail from wherever the fd happens to be\n    }\n    return handle;\n  };\n\n  // --- say / resume from this pane's stdin\n  const noteLine = (s: string) => {\n    eraseLiveness();\n    out(s);\n  };\n  // SpawnOptions (not the stdio-tuple overload): we only read stdout and\n  // want the plain ChildProcess shape; tests inject a fake that records\n  const spawnResume =\n    io?.spawnResume ??\n    ((id: string, text: string): ResumeChild =>\n      spawn(\"pai\", [\"worker\", \"resume\", id, text, \"--print-id\", \"--no-pane\"], {\n        stdio: [\"ignore\", \"pipe\", \"inherit\"],\n        // this pane already shows the resumed worker: PAI_WORKER=1 lets the child run without a pane of its own\n        env: { ...process.env, PAI_WORKER: \"1\" },\n      } as SpawnOptions) as unknown as ResumeChild);\n  const resumeTarget = (text: string, id: string) => {\n    noteLine(c(\"dim\", `» resuming ${id} …`));\n    const child = spawnResume(id, text);\n    let idOut = \"\";\n    child.stdout?.on(\"data\", (chunk: Buffer) => {\n      idOut += chunk.toString(\"utf8\");\n    });\n    child.on(\"close\", (rc: number | null) => {\n      const newId = idOut.trim().split(\"\\n\").pop() ?? \"\";\n      if (rc === 0 && /^\\d{8}-\\d{6}-\\d+$/.test(newId)) {\n        noteLine(c(\"dim\", `» resumed as ${newId}`));\n        target = newId;\n        finished.delete(newId);\n        seenHeader.delete(newId);\n        states.delete(newId);\n        ticker = initialFollowState(\"resumed\");\n        lastEventAt = Date.now();\n      } else {\n        noteLine(c(\"red\", `» resume failed (rc=${rc})`));\n      }\n    });\n  };\n  // same argv `pai worker controls` builds — the pane just spawns clickr\n  // itself instead of shelling out to the CLI, so it can capture the result\n  // for the pane's own echo rather than inheriting stdio into the transcript\n  const spawnControls =\n    io?.spawnControls ??\n    ((id: string, who: \"you\" | \"me\", pid: number | undefined): ControlsChild =>\n      spawn(\"clickr\", clickrControlsArgv(id, who, pid), {\n        stdio: [\"ignore\", \"pipe\", \"pipe\"],\n      } as SpawnOptions) as unknown as ControlsChild);\n  const controlsTarget = (id: string, who: \"you\" | \"me\") => {\n    const pid = loadStatuses(logDir).find((s) => s.id === id)?.pid;\n    const child = spawnControls(id, who, pid);\n    let errText = \"\";\n    child.stderr?.on(\"data\", (chunk: Buffer) => {\n      errText += chunk.toString(\"utf8\");\n    });\n    child.on(\"close\", (rc: number | null) => {\n      if (rc === 0) {\n        if (who === \"you\") markControlsHeld(logDir, id);\n        noteLine(\n          c(\"dim\", `» controls → ${who === \"you\" ? `${id} (exclusive; needs clickr with --agent support)` : \"operator\"}`)\n        );\n      } else {\n        noteLine(c(\"red\", `» controls failed (rc=${rc})${errText.trim() ? `: ${errText.trim()}` : \"\"}`));\n      }\n    });\n  };\n  const handleOperatorLine = makeOperatorInput({\n    target: () => target,\n    say: (id, text) => sayToWorker(logDir, id, text),\n    workerKnown: (id) => loadStatuses(logDir).some((s) => s.id === id),\n    resume: resumeTarget,\n    note: noteLine,\n    paint: c,\n    ...(chat ? { sent: () => undefined } : {}), // the echo replaces the note\n  });\n\n  // --- the chat line: readline editing on the prompt row\n  // the readline interface keeps stdin flowing — without a close, the process\n  // outlives follow itself (a pane then never closes, however long ago the\n  // worker ended), so it is closed in the finally block below\n  const terminalIn = (in_ as { isTTY?: boolean }).isTTY === true;\n  let rlIn: ReturnType<typeof createInterface> | null = null;\n  let onResize: (() => void) | null = null;\n  // an echoed line comes back as a mirrored operator event within moments —\n  // remember what was echoed and swallow the twin, so the pane shows what\n  // was typed exactly once\n  const echoed = new Map<string, { n: number; until: number }>();\n  const suppressMirror = (text: string): boolean => {\n    const g = echoed.get(text);\n    if (!g || Date.now() > g.until) return false;\n    g.n -= 1;\n    if (g.n <= 0) echoed.delete(text);\n    return true;\n  };\n  /** Column the prompt row's cursor parks at: right after the draft's cursor. */\n  const promptCursorCol = (): number => {\n    const line = rlIn?.line ?? \"\";\n    const cur = (rlIn as unknown as { cursor?: number } | null)?.cursor;\n    return 3 + Math.max(0, Math.min(typeof cur === \"number\" ? cur : line.length, line.length));\n  };\n  /**\n   * The pane owns the prompt row's rendering: `› `, the buffer — or the dim\n   * placeholder while the buffer is empty — and the cursor parked after it.\n   */\n  const drawPrompt = () => {\n    if (!chat) return;\n    const line = rlIn?.line ?? \"\";\n    const cur = (rlIn as unknown as { cursor?: number } | null)?.cursor;\n    safeWrite(chatPromptRow(rows, line, (s) => c(\"dim\", s), cur));\n  };\n  if (chat) {\n    const echoOperator = (text: string) => {\n      const id = target;\n      if (id === null) return;\n      echoed.set(text, { n: 1, until: Date.now() + 10_000 });\n      const st = states.get(id) ?? initialFollowState();\n      const step = applyEvent(\n        c,\n        st,\n        { type: \"operator\", _ts: new Date().toISOString(), text },\n        \"\",\n        undefined,\n        undefined,\n        columns()\n      );\n      if (step.day) out(c(\"dim\", `── ${step.day} ──`));\n      for (const ln of step.lines) out(ln);\n      states.set(id, step.state);\n    };\n    const handleChatLine = (raw: string) => {\n      const act = parseChatLine(raw);\n      let redrew = false;\n      switch (act.kind) {\n        case \"message\":\n          if (!act.text) break;\n          handleOperatorLine(act.text); // send the line …\n          drawPrompt(); // … placeholder back before the » echo is written\n          redrew = true;\n          echoOperator(act.text);\n          break;\n        case \"resume\":\n          if (!act.text) {\n            out(c(\"dim\", \"usage: /resume <text>\"));\n            break;\n          }\n          if (target !== null) resumeTarget(act.text, target);\n          drawPrompt();\n          redrew = true;\n          echoOperator(act.text);\n          break;\n        case \"controls\":\n          if (target !== null) controlsTarget(target, act.who);\n          else out(c(\"dim\", \"no target worker for controls\"));\n          break;\n        case \"help\":\n          for (const ln of CHAT_HELP) out(c(\"dim\", ln));\n          break;\n        case \"status\": {\n          const s =\n            target !== null ? loadStatuses(logDir).find((x) => x.id === target) : undefined;\n          out(c(\"dim\", s ? `${s.id} · ${s.state} · ${s.last}` : `${target ?? \"?\"} · no status`));\n          break;\n        }\n        case \"quit\":\n          aborted = true;\n          break;\n      }\n      if (!redrew) drawPrompt(); // on a pipe readline does not repaint the row\n    };\n    // readline edits silently (its output is a mute stream); the pane draws\n    // the prompt row itself from the live buffer, so the placeholder yields\n    // to the first keystroke and returns when the buffer empties again.\n    // The emitter no-ops matter: with terminal:true readline attaches a\n    // resize listener on its output, and a bare { write } object crashes\n    // follow in a real terminal (\"output.on is not a function\").\n    const silent = {\n      write: () => true,\n      on: () => silent,\n      once: () => silent,\n      off: () => silent,\n      removeListener: () => silent,\n      emit: () => false,\n    } as unknown as NodeJS.WriteStream;\n    rlIn = createInterface({ input: in_, output: silent, terminal: terminalIn });\n    rlIn.on(\"line\", handleChatLine);\n    // Ctrl-C: an empty prompt leaves, a draft clears; Ctrl-D (close) leaves\n    rlIn.on(\"SIGINT\", () => {\n      if ((rlIn?.line ?? \"\").trim() === \"\") aborted = true;\n      else {\n        rlIn?.write(null, { ctrl: true, name: \"u\" });\n        drawPrompt();\n      }\n    });\n    rlIn.on(\"close\", () => {\n      aborted = true;\n    });\n    // the separator rule above the prompt row needs the pane's width and the\n    // pane's dim colour — chatEnter without cols leaves the row blank\n    safeWrite(chatEnter(rows, columns() ?? 0, (s) => c(\"dim\", s)));\n    drawPrompt();\n    if (terminalIn) {\n      // every keystroke re-renders the row (and re-parks the cursor) from\n      // the buffer readline now holds\n      (in_ as NodeJS.ReadableStream).on(\"keypress\", () => drawPrompt());\n    }\n    // resize: re-read the geometry, rebuild the region, fill it afresh\n    onResize = () => {\n      if (typeof out_.rows === \"number\") rows = out_.rows;\n      fill = 0;\n      // clear first: the refill lands rows top-down and must not overwrite\n      // the stale transcript left under the old geometry\n      safeWrite(\n        \"\\x1b[2J\" + chatScrollRegion(rows) + chatBlankRow(rows, columns() ?? 0, (s) => c(\"dim\", s))\n      );\n      // the retained transcript replays in order, newest regionRows() lines\n      // only - a shrunken pane shows its newest rows, not a scroll replay\n      for (const ln of retained.slice(-regionRows())) out(ln, false);\n      drawPrompt();\n    };\n    out_.on?.(\"resize\", onResize);\n  } else if (target !== null && (in_ as { isTTY?: boolean }).isTTY) {\n    // plain operator channel: TTY stdin, non-TTY stdout\n    rlIn = createInterface({ input: in_ });\n    rlIn.on(\"line\", handleOperatorLine);\n  }\n\n  /** The prompt's unsent text — a draft holds the auto-exit countdown. */\n  const promptText = () => (io?.promptLine ? io.promptLine() : (rlIn?.line ?? \"\"));\n\n  try {\n    for (;;) {\n      if (aborted) return;\n      let outcome: TickOutcome;\n      try {\n        outcome = await runOneTick();\n        consecutiveErrors = 0;\n      } catch (e) {\n        consecutiveErrors++;\n        const msg = e instanceof Error ? e.message : String(e);\n        // best-effort: the pane itself may be exactly what is unwritable\n        try {\n          noteLine(c(\"red\", `» follow error: ${msg}`));\n        } catch {\n          /* pane unwritable — the ledger line in finally is the record */\n        }\n        process.stderr.write(`pai worker follow: ${msg}\\n`);\n        if (consecutiveErrors < MAX_CONSECUTIVE_ERRORS) {\n          await sleep(200);\n          continue;\n        }\n        exitReason = `error: ${msg}`.slice(0, 200);\n        // a crash would otherwise close this pane the instant the process\n        // exits (Close Sessions On End) — hold it open so the error above is\n        // readable, not just a pane that vanished for no visible reason\n        if (chat && rlIn) {\n          try {\n            noteLine(c(\"dim\", \"» follow crashed — press enter to close this pane\"));\n          } catch {\n            /* already unwritable */\n          }\n          await Promise.race([\n            new Promise<void>((resolve) => rlIn!.once(\"line\", () => resolve())),\n            sleep(60_000),\n          ]);\n        }\n        return;\n      }\n      if (outcome.done) {\n        exitReason = outcome.reason;\n        return;\n      }\n    }\n  } finally {\n    // close before anything else: an open readline keeps the process (and the\n    // iTerm pane running it) alive long after follow has decided to end\n    rlIn?.close();\n    process.removeListener(\"SIGINT\", onInt);\n    if (onResize) out_.removeListener?.(\"resize\", onResize);\n    if (chat) safeWrite(chatLeave(rows));\n    for (const h of handles.values()) {\n      try {\n        closeSync(h.fd);\n      } catch {\n        /* already closed */\n      }\n    }\n    if (target !== null) {\n      appendLedger(ledgerPath(logDir), \"PANE-CLOSED\", {\n        id: target,\n        reason: exitReason,\n        secs: Math.floor((Date.now() - started) / 1000),\n      });\n      // pane mode (--auto-exit): the pane ends with its follow, whatever the profile does\n      if (autoExit) await closeOwnPane(env);\n    }\n  }\n\n  /** Ended per the status file. */\n  function statusEnded(rendered: boolean, st: WorkerStatus): boolean {\n    return workerEnded(rendered, st.state);\n  }\n\n  /** Freeze the worker's clock and print the one final \"ended\" line. */\n  function markFinished(wid: string, st: WorkerStatus, multi: boolean): void {\n    finished.add(wid);\n    eraseLiveness();\n    const pre = multi ? c(\"cyan\", wid.slice(-4)) + c(\"dim\", \" ┃ \") : \"  \";\n    out(`${pre}${c(\"red\", \"✗ \" + (st.state || \"ended\"))} · ${st.last ?? \"\"}`);\n    const why = [st.endReason, st.endBy].filter(Boolean).join(\" \");\n    const secs = st.secs ?? Math.max(0, Math.floor((Date.now() - Date.parse((st.started ?? \"\").replace(\" \", \"T\"))) / 1000));\n    out(\n      c(\n        \"dim\",\n        `ended ${st.state ?? \"?\"} rc=${st.rc ?? \"?\"}${why ? \" \" + why : \"\"} after ${Number.isNaN(secs) ? \"?\" : secs + \"s\"}`\n      )\n    );\n  }\n\n  /** What one poll decided: keep following, or the reason it is over. */\n  type TickOutcome = { done: true; reason: string } | { done: false };\n\n  /**\n   * One poll of the loop: attach new handles, drain them, check exit\n   * conditions. Returning (rather than throwing) `done: true` is how a\n   * normal end is told apart from the error path above — everything in here\n   * that can throw (rendering, terminal writes) is still covered by that\n   * path, so one bad event or write never takes the whole pane down with it.\n   */\n  let scanCache: Map<string, WorkerStatus> | null = null;\n  let scanAt = 0;\n  async function runOneTick(): Promise<TickOutcome> {\n    // ponytail: a pinned pane reads its one status file; an all-workers pane\n    // rescans the (thousands of) status files at most every 2 s\n    let statuses: Map<string, WorkerStatus>;\n    if (target) {\n      const one = loadStatus(logDir, target);\n      statuses = new Map(one ? [[one.id, one]] : []);\n    } else {\n      if (Date.now() - scanAt >= 2000 || !scanCache) {\n        scanCache = new Map(loadStatuses(logDir).map((s) => [s.id, s]));\n        scanAt = Date.now();\n      }\n      statuses = scanCache;\n    }\n    if (target) paneStatus = statuses.get(target) ?? paneStatus;\n    const wanted = target ? [target] : runningIds();\n    for (const wid of wanted) {\n      if (handles.has(wid) || finished.has(wid)) continue;\n      const path = eventsPath(logDir, wid);\n      const st = statuses.get(wid) ?? ({ id: wid, label: \"\", cwd: \"\", provider: \"\" } as WorkerStatus);\n      if (existsSync(path)) {\n        const multi = target === null || handles.size > 0;\n        handles.set(wid, attachHandle(wid, path, st, multi));\n        states.set(wid, states.get(wid) ?? initialFollowState());\n      } else if (!seenHeader.has(wid)) {\n        // worker just started, no event yet: name it instead of a blank pane\n        out(headerLine(c, st));\n        seenHeader.add(wid);\n      }\n    }\n    const multi = handles.size > 1 || target === null;\n    let progressed = false;\n\n    for (const [wid, h] of [...handles.entries()]) {\n      const st = statuses.get(wid) ?? ({ id: wid, label: \"\", cwd: \"\", provider: \"\" } as WorkerStatus);\n      // read everything appended since the last poll (fd position advances)\n      const buffer = Buffer.alloc(65536);\n      for (;;) {\n        let n: number;\n        try {\n          n = readSync(h.fd, buffer, 0, buffer.length, null);\n        } catch {\n          n = 0;\n        }\n        if (n <= 0) break;\n        h.buf += buffer.toString(\"utf8\", 0, n);\n      }\n      const lines = h.buf.split(\"\\n\");\n      h.buf = lines.pop() ?? \"\";\n      for (const line of lines) {\n        if (!line.trim()) continue;\n        progressed = true;\n        let e: StreamEventLike;\n        try {\n          e = JSON.parse(line) as StreamEventLike;\n        } catch {\n          continue;\n        }\n        emitEvent(e, wid, st, multi);\n      }\n      if (statusEnded(finished.has(wid), st)) {\n        markFinished(wid, st, multi);\n        closeSync(h.fd);\n        handles.delete(wid);\n      }\n    }\n    // a worker that never wrote an event log has no handle above — its end\n    // still has to stop the pane's clock and start the exit countdown\n    if (target !== null && !handles.has(target) && !finished.has(target)) {\n      const st = statuses.get(target);\n      if (st && statusEnded(false, st)) markFinished(target, st, false);\n    }\n\n    // inbox tail: new handoffs render as ◆ lines in the recipient's pane\n    // (they may also arrive via the say mirror — the durable copy is here)\n    for (const wid of [...handles.keys()]) {\n      const st = statuses.get(wid) ?? ({ id: wid, label: \"\", cwd: \"\", provider: \"\" } as WorkerStatus);\n      const msgs = readInbox(logDir, wid);\n      const seenN = inboxSeen.get(wid) ?? 0;\n      if (msgs.length > seenN) {\n        for (const m of msgs.slice(seenN)) {\n          emitEvent(\n            { type: \"handoff\", from: m.from, kind: m.kind, text: m.text, _ts: m._ts },\n            wid,\n            st,\n            multi\n          );\n        }\n        inboxSeen.set(wid, msgs.length);\n        progressed = true;\n      }\n    }\n\n    const lingerOn = target; // resume swaps `target` under us (see above)\n    if (lingerOn !== null && finished.has(lingerOn)) {\n      if (autoExit) {\n        // a draft in the prompt holds the countdown: the operator may be\n        // about to say or resume something\n        if (holdAutoExit(promptText())) {\n          writeLiveness();\n          await sleep(250);\n          return { done: false };\n        }\n        const until = Date.now() + autoExit * 1000;\n        while (\n          Date.now() < until &&\n          !aborted &&\n          target === lingerOn &&\n          !holdAutoExit(promptText())\n        ) {\n          writeLiveness();\n          await sleep(250);\n        }\n        // interrupted, resumed inside the window, or a draft appeared: follow on\n        if (aborted || target !== lingerOn || holdAutoExit(promptText())) return { done: false };\n        eraseLiveness();\n        out(c(\"dim\", \"closing\"));\n        return { done: true, reason: \"worker-ended\" };\n      }\n      // no auto-exit: only a terminal follow with no wired stdin is done —\n      // an interactive one stays up for say / resume input\n      if (rlIn === null) return { done: true, reason: \"worker-ended\" };\n    }\n    if (autoExit && !target) {\n      if ([...(scanCache?.values() ?? [])].some((s) => isLive(s))) {\n        idleSince = null;\n      } else if (idleSince === null) {\n        idleSince = Date.now();\n      } else if (Date.now() - started >= 30_000 && Date.now() - idleSince >= autoExit * 1000) {\n        eraseLiveness();\n        out(c(\"dim\", \"closing\"));\n        return { done: true, reason: \"idle\" };\n      }\n    }\n    if (!progressed) {\n      writeLiveness();\n      await sleep(500);\n    }\n    return { done: false };\n  }\n}\n\nfunction sleep(ms: number): Promise<void> {\n  return new Promise((r) => setTimeout(r, ms));\n}\n\n// ---------------------------------------------------------------------------\n// status line\n// ---------------------------------------------------------------------------\n\n/**\n * The status bar's worker line for THIS session's pool: workers its claude\n * session (or, failing that, its terminal) spawned, plus their descendants\n * (ownership as supervision's ownershipKey / scope's workerInScope define it).\n * Other sessions' live workers show as a dim `(+M elsewhere)` suffix. With no\n * session identity at all (no `term`, no `claudeSession`) the bar keeps the\n * machine-wide count.\n */\nexport function statusLineOutput(\n  logDir: string,\n  term: string,\n  _cwd: string,\n  claudeSession: string = \"\",\n  now: Date = new Date()\n): string {\n  reconcileStatuses(logDir, now, 0);\n  const statuses = loadStatuses(logDir).filter((s) => !isChatPane(s));\n  if (!term && !claudeSession) return renderStatusLine(statuses, now);\n\n  const byId = new Map(statuses.map((s) => [s.id, s]));\n  const ownsRoot = (s: WorkerStatus): boolean =>\n    (!!claudeSession && s.spawnerSession === claudeSession) || (!!term && workerInScope(s, term));\n  const isMine = (s: WorkerStatus): boolean => {\n    const seen = new Set<string>();\n    for (let w: WorkerStatus | undefined = s; w && !seen.has(w.id); w = w.parent ? byId.get(w.parent) : undefined) {\n      if (ownsRoot(w)) return true;\n      seen.add(w.id);\n    }\n    return false;\n  };\n  const mine = statuses.filter(isMine);\n  const elsewhere = statuses.filter((s) => !isMine(s) && isLive(s)).length;\n  const line = renderStatusLine(mine, now);\n  if (!elsewhere) return line;\n  const suffix = makeColor(true)(\"dim\", `(+${elsewhere} elsewhere)`);\n  return line ? `${line} ${suffix}` : suffix;\n}\n","/**\n * help.ts — `pai worker help`: a worker with a budget asks a stronger model\n * to do one sub-task, then continues with the answer.\n *\n * The risk is a local worker deferring everything upward, so every call is\n * counted per orchestrated unit (scope) and refused past the budget, and\n * every call lands in `<logDir>/help-ledger.jsonl` so the help rate is\n * measurable (`pai worker help --report`).\n *\n * Scope: PAI_HELP_SCOPE when the orchestrator set it, else the top-most\n * ancestor in the caller's parent chain, else the caller itself.\n */\n\nimport { execFileSync, spawn } from \"node:child_process\";\nimport { appendFileSync, existsSync, mkdirSync, readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { loadStatuses, type WorkerStatus } from \"./status.js\";\nimport { parentFromEnv } from \"./tree.js\";\n\nexport const DEFAULT_HELP_BUDGET = 2;\nexport const HELP_MAX_MINUTES = 20;\n/** Exit code of a refused call. */\nexport const HELP_REFUSED_EXIT = 4;\n\nexport interface HelpEntry {\n  ts: string;\n  caller: string | null;\n  scope: string;\n  task: string;\n  provider: string;\n  model: string;\n  durationMs: number;\n  tokens: number | null;\n  outcome: \"ok\" | \"failed\";\n}\n\nexport function helpLedgerPath(logDir: string): string {\n  return join(logDir, \"help-ledger.jsonl\");\n}\n\nexport function readHelpLedger(logDir: string, scope?: string): HelpEntry[] {\n  const path = helpLedgerPath(logDir);\n  if (!existsSync(path)) return [];\n  const out: HelpEntry[] = [];\n  for (const line of readFileSync(path, \"utf8\").split(\"\\n\")) {\n    if (!line.trim()) continue;\n    try {\n      const e = JSON.parse(line) as HelpEntry;\n      if (!scope || e.scope === scope) out.push(e);\n    } catch {\n      // half-written line: skip\n    }\n  }\n  return out;\n}\n\nexport function appendHelpEntry(logDir: string, e: HelpEntry): void {\n  const path = helpLedgerPath(logDir);\n  if (!existsSync(dirname(path))) mkdirSync(dirname(path), { recursive: true });\n  appendFileSync(path, JSON.stringify(e) + \"\\n\", \"utf8\");\n}\n\n/** The unit a help call is counted against. */\nexport function resolveHelpScope(\n  statuses: Pick<WorkerStatus, \"id\" | \"parent\">[],\n  env: NodeJS.ProcessEnv = process.env\n): string {\n  const set = env.PAI_HELP_SCOPE?.trim();\n  if (set) return set;\n  const me = parentFromEnv(env);\n  if (!me) return \"session\";\n  const byId = new Map(statuses.map((s) => [s.id, s]));\n  let cur = me;\n  const seen = new Set([cur]);\n  for (;;) {\n    const p = byId.get(cur)?.parent;\n    if (!p || seen.has(p) || !byId.has(p)) return cur;\n    seen.add(p);\n    cur = p;\n  }\n}\n\nexport function helpBudget(env: NodeJS.ProcessEnv = process.env): number {\n  const n = Number(env.PAI_HELP_BUDGET);\n  return Number.isInteger(n) && n >= 0 && env.PAI_HELP_BUDGET?.trim() ? n : DEFAULT_HELP_BUDGET;\n}\n\nexport interface HelpRunResult {\n  /** The sub-worker's final report text. */\n  report: string;\n  tokens: number | null;\n  ok: boolean;\n}\n\nexport interface HelpDeps {\n  /** Run the sub-worker to completion. */\n  spawnWorker: (argv: string[], cwd: string) => Promise<HelpRunResult>;\n  /** Files changed in cwd (git porcelain paths). */\n  changedFiles: (cwd: string) => string[];\n  now: () => number;\n}\n\nexport interface HelpRequest {\n  task: string;\n  provider: string;\n  model: string;\n  files: string[];\n  cwd: string;\n}\n\nexport type HelpOutcome =\n  | { refused: true; message: string }\n  | { refused: false; text: string; ok: boolean };\n\nexport function helpArgv(req: HelpRequest): string[] {\n  const files = req.files.length ? `\\n\\nRelevant files: ${req.files.join(\", \")}` : \"\";\n  return [\n    \"worker\", \"run\",\n    \"--provider\", req.provider,\n    \"--model\", req.model,\n    \"--class\", \"implement\",\n    \"--no-worktree\",\n    \"--max-minutes\", String(HELP_MAX_MINUTES),\n    \"--label\", `help: ${req.task.slice(0, 60)}`,\n    \"--output-format\", \"json\",\n    \"-p\", `${req.task}${files}`,\n  ];\n}\n\nexport async function requestHelp(\n  logDir: string,\n  req: HelpRequest,\n  deps: HelpDeps,\n  env: NodeJS.ProcessEnv = process.env\n): Promise<HelpOutcome> {\n  const scope = resolveHelpScope(loadStatuses(logDir), env);\n  const budget = helpBudget(env);\n  const used = readHelpLedger(logDir, scope).length;\n  if (used >= budget) {\n    return { refused: true, message: `help budget used (${used}/${budget}): report the blocker in your R x= line instead` };\n  }\n  const before = new Set(deps.changedFiles(req.cwd));\n  const t0 = deps.now();\n  let res: HelpRunResult;\n  try {\n    res = await deps.spawnWorker(helpArgv(req), req.cwd);\n  } catch (e) {\n    res = { report: e instanceof Error ? e.message : String(e), tokens: null, ok: false };\n  }\n  appendHelpEntry(logDir, {\n    ts: new Date(t0).toISOString(),\n    caller: parentFromEnv(env),\n    scope,\n    task: req.task,\n    provider: req.provider,\n    model: req.model,\n    durationMs: deps.now() - t0,\n    tokens: res.tokens,\n    outcome: res.ok ? \"ok\" : \"failed\",\n  });\n  const changed = deps.changedFiles(req.cwd).filter((f) => !before.has(f));\n  const text = `${res.report.trim()}\\n\\nchanged files: ${changed.length ? changed.join(\", \") : \"none\"}`;\n  return { refused: false, text, ok: res.ok };\n}\n\nexport function renderHelpReport(entries: HelpEntry[]): string {\n  if (!entries.length) return \"no help calls recorded\";\n  const lines = entries.map(\n    (e) =>\n      `${e.ts}  scope=${e.scope}  caller=${e.caller ?? \"-\"}  ${e.provider}/${e.model}  ` +\n      `${Math.round(e.durationMs / 1000)}s  tokens=${e.tokens ?? \"?\"}  ${e.outcome}  ${e.task.replace(/\\s+/g, \" \").slice(0, 80)}`\n  );\n  const perScope = new Map<string, number>();\n  for (const e of entries) perScope.set(e.scope, (perScope.get(e.scope) ?? 0) + 1);\n  lines.push(\"\", [...perScope].map(([s, n]) => `${s}: ${n} call${n === 1 ? \"\" : \"s\"}`).join(\"; \"));\n  return lines.join(\"\\n\");\n}\n\n/** Real changed-file lister: git porcelain paths, empty outside git. */\nexport function gitChangedFiles(cwd: string): string[] {\n  try {\n    return execFileSync(\"git\", [\"status\", \"--porcelain\"], { cwd, encoding: \"utf8\", stdio: [\"ignore\", \"pipe\", \"ignore\"] })\n      .split(\"\\n\")\n      .filter(Boolean)\n      .map((l) => l.slice(3));\n  } catch {\n    return [];\n  }\n}\n\n/** Real spawn: the same pai binary, `worker run --output-format json`; parses claude's result JSON. */\nexport function spawnPaiWorker(argv: string[], cwd: string): Promise<HelpRunResult> {\n  return new Promise((resolve) => {\n    const bin = process.env.PAI_BIN || \"pai\";\n    const child = spawn(bin, argv, { cwd, stdio: [\"ignore\", \"pipe\", \"pipe\"], env: process.env });\n    let out = \"\";\n    let errText = \"\";\n    child.stdout.on(\"data\", (d) => (out += d));\n    child.stderr.on(\"data\", (d) => (errText += d));\n    child.on(\"error\", (e) => resolve({ report: e.message, tokens: null, ok: false }));\n    child.on(\"close\", (code) => {\n      try {\n        const j = JSON.parse(out) as { result?: string; usage?: Record<string, number>; is_error?: boolean };\n        const u = j.usage ?? {};\n        const tokens = (u.input_tokens ?? 0) + (u.output_tokens ?? 0) + (u.cache_read_input_tokens ?? 0) + (u.cache_creation_input_tokens ?? 0);\n        resolve({ report: j.result ?? out, tokens: tokens || null, ok: code === 0 && j.is_error !== true });\n      } catch {\n        resolve({ report: (out || errText).trim(), tokens: null, ok: code === 0 });\n      }\n    });\n  });\n}\n","/**\n * wait-probes.ts — bounded waits for a server to answer and for files to appear:\n * `pai worker wait-url <url>` and `pai worker wait-file <path...>`. Siblings of\n * wait-on (a pid) and wait (child workers); each returns within --max seconds\n * (default 100, limit 590) so the caller loops a few times instead of sleeping.\n *\n * Exit codes: 0 ready, 3 not yet at --max, 2 unusable arguments.\n */\n\nimport { existsSync } from \"node:fs\";\n\nexport const PROBE_DEFAULT_SECS = 100;\nexport const PROBE_CAP_SECS = 590;\n\nexport interface ProbeDeps {\n  now: () => number;\n  sleep: (ms: number) => Promise<void>;\n  out: (line: string) => void;\n  /** HTTP status of a GET, or an error word (\"connection refused\", \"timeout\") when nothing answered. */\n  get: (url: string, timeoutMs: number) => Promise<number | string>;\n  exists: (path: string) => boolean;\n}\n\nexport const realProbeDeps: ProbeDeps = {\n  now: () => Date.now(),\n  sleep: (ms) => new Promise((r) => setTimeout(r, ms)),\n  out: (l) => console.log(l),\n  async get(url, timeoutMs) {\n    try {\n      const res = await fetch(url, { signal: AbortSignal.timeout(timeoutMs) });\n      void res.body?.cancel();\n      return res.status;\n    } catch (e) {\n      const err = e as { name?: string; cause?: { code?: string } };\n      if (err.name === \"TimeoutError\" || err.name === \"AbortError\") return \"timeout\";\n      return err.cause?.code === \"ECONNREFUSED\" ? \"connection refused\" : (err.cause?.code ?? \"no answer\");\n    }\n  },\n  exists: existsSync,\n};\n\nconst maxMsOf = (secs: number | undefined): number => Math.min(secs ?? PROBE_DEFAULT_SECS, PROBE_CAP_SECS) * 1000;\nconst secsSince = (d: ProbeDeps, t0: number): number => Math.round((d.now() - t0) / 1000);\n\n/** Up once the server answers with any 2xx-4xx status (a 404 or 401 still proves the port serves HTTP). */\nexport async function waitUrl(o: { url: string; maxSecs?: number }, d: ProbeDeps = realProbeDeps): Promise<number> {\n  try {\n    new URL(o.url);\n  } catch {\n    d.out(`wait-url: invalid url ${o.url}`);\n    return 2;\n  }\n  const maxMs = maxMsOf(o.maxSecs);\n  const t0 = d.now();\n  let delay = 500;\n  let last: number | string = \"no answer\";\n  for (;;) {\n    last = await d.get(o.url, 3000);\n    if (typeof last === \"number\" && last >= 200 && last < 500) {\n      d.out(`up: ${o.url} answered HTTP ${last} after ${secsSince(d, t0)}s`);\n      return 0;\n    }\n    const left = maxMs - (d.now() - t0);\n    if (left <= 0) break;\n    await d.sleep(Math.min(delay, left));\n    delay = Math.min(delay * 2, 5000);\n  }\n  d.out(`not yet: ${o.url} (last: ${typeof last === \"number\" ? `HTTP ${last}` : last}) after ${secsSince(d, t0)}s; call wait-url again`);\n  return 3;\n}\n\n/** Ready once every path exists; one status line per path. */\nexport async function waitFile(o: { paths: string[]; maxSecs?: number }, d: ProbeDeps = realProbeDeps): Promise<number> {\n  if (o.paths.length === 0) {\n    d.out(\"wait-file: no path given\");\n    return 2;\n  }\n  const maxMs = maxMsOf(o.maxSecs);\n  const t0 = d.now();\n  const missing = () => o.paths.filter((p) => !d.exists(p));\n  while (missing().length > 0 && d.now() - t0 < maxMs) {\n    await d.sleep(Math.min(1000, Math.max(1, maxMs - (d.now() - t0))));\n  }\n  const gone = new Set(missing());\n  for (const p of o.paths) d.out(gone.has(p) ? `missing: ${p}` : `exists: ${p}`);\n  if (gone.size > 0) {\n    d.out(`not yet: ${gone.size} of ${o.paths.length} missing after ${secsSince(d, t0)}s; call wait-file again`);\n    return 3;\n  }\n  return 0;\n}\n","/**\n * providers.ts — provider, class and switch management over the workers config.\n *\n * One layer under both `pai worker providers …` and the MCP worker_providers\n * tool. Every mutation re-reads the config file, changes only the workers\n * section, and writes it back atomically — the file is shared with everything\n * else PAI runs, so a torn write is not an option.\n *\n * The CLI's `--key` writes the token inline as `key:` in workers.yaml\n * (quoted, and the file is kept 0600 — see workers-config.ts); `--key-file`\n * still writes only a path. The MCP `add` tool instead accepts a raw `key`\n * and parks it in ~/.claude/pai/keys/<name>, mode 0600, storing only the\n * path in the config — a chat is not a place to leave a credential lying\n * around.\n */\n\nimport { existsSync, writeFileSync, chmodSync, mkdirSync } from \"node:fs\";\nimport {\n  ANTHROPIC_NATIVE,\n  DEFAULT_LOG_DIR,\n  MODEL_CAPABILITIES,\n  PROVIDER_TAGS,\n  WorkersConfigError,\n  expandHome,\n  getProviderOrNative,\n  isModelCapability,\n  keysDir,\n  maskKey,\n  nativeAnthropicProvider,\n  providerCostTier,\n  readWorkersSection,\n  resolveCapability,\n  writeWorkersSection,\n  type ClassTarget,\n  type ModelCapability,\n  type WorkerProvider,\n  type WorkersConfig,\n} from \"./config.js\";\nimport { clearCooldown, probeQuota, quotaSkipThreshold } from \"./routing.js\";\nimport { workersLogDir } from \"./paths.js\";\nimport { workersYamlLegacyNotice, workersYamlPath } from \"./workers-config.js\";\nimport { isLoopbackProvider } from \"./run-env.js\";\nimport { probeLoopback, type PortCheck } from \"./local-provider.js\";\nimport { CONFIG_FILE } from \"../daemon/config.js\";\n\nexport interface AddProviderInput {\n  name: string;\n  baseUrl: string;\n  keyFile?: string | null;\n  /** Raw token (MCP `add` only): parked in ~/.claude/pai/keys/<name>, only the path stored. */\n  key?: string;\n  /** Raw token (CLI `--key` only): written verbatim as `key:` in workers.yaml. */\n  inlineKey?: string;\n  model: string;\n  fastModel?: string;\n  env?: Record<string, string>;\n  note?: string;\n  protocol?: \"anthropic\" | \"openai\";\n  upstreamUrl?: string;\n  engine?: \"claude\" | \"codex\" | \"image\";\n  quotaProbe?: string;\n  contextWindow?: number;\n  costTier?: number;\n  tags?: string[];\n  /** Config file override (tests, dry runs); default ~/.claude/pai/config.yaml. */\n  configPath?: string;\n}\n\nexport function addProvider(input: AddProviderInput): WorkersConfig {\n  if (!/^[a-zA-Z0-9][a-zA-Z0-9_-]*$/.test(input.name)) {\n    throw new WorkersConfigError(\n      `provider name \"${input.name}\" may only contain letters, digits, - and _`\n    );\n  }\n  if (input.protocol === \"openai\" && !input.upstreamUrl) {\n    throw new WorkersConfigError(\n      `protocol \"openai\" needs the upstreamUrl (the Chat Completions base, ` +\n        `e.g. \"https://api.openai.com/v1\") — the PAI proxy translates to it.`\n    );\n  }\n  if (!input.baseUrl && input.protocol !== \"openai\") {\n    throw new WorkersConfigError(\"baseUrl is required\");\n  }\n\n  let keyFile = input.keyFile ?? null;\n  if (input.key !== undefined) {\n    const dir = keysDir();\n    if (!existsSync(dir)) mkdirSync(dir, { recursive: true });\n    const path = `${dir}/${input.name}`;\n    writeFileSync(path, input.key.trim() + \"\\n\", { encoding: \"utf8\", mode: 0o600 });\n    try {\n      chmodSync(path, 0o600);\n    } catch {\n      /* mode above already applied on create where supported */\n    }\n    keyFile = path;\n  }\n\n  const { raw, workers } = readWorkersSection(input.configPath);\n  const provider: WorkerProvider = {\n    enabled: true,\n    protocol: input.protocol ?? \"anthropic\",\n    baseUrl: input.baseUrl,\n    keyFile,\n    ...(input.inlineKey ? { key: input.inlineKey } : {}),\n    models: input.fastModel\n      ? { default: input.model, fast: input.fastModel }\n      : { default: input.model },\n    env: input.env ?? {},\n    ...(input.note ? { note: input.note } : {}),\n    ...(input.upstreamUrl ? { upstreamUrl: input.upstreamUrl } : {}),\n    ...(input.engine && input.engine !== \"claude\" ? { engine: input.engine } : {}),\n    ...(input.quotaProbe ? { quotaProbe: input.quotaProbe } : {}),\n    ...(input.contextWindow ? { contextWindow: input.contextWindow } : {}),\n    ...(input.costTier ? { costTier: input.costTier } : {}),\n    ...(input.tags?.length ? { tags: input.tags as WorkerProvider[\"tags\"] } : {}),\n  };\n  workers.providers[input.name] = provider;\n\n  // First provider takes over the whole section: active, default classes, pane.\n  const first = Object.keys(workers.providers).length === 1;\n  if (first) {\n    workers.enabled = true;\n    workers.active = input.name;\n    workers.logDir = workers.logDir || DEFAULT_LOG_DIR;\n    const fast = input.fastModel ? `${input.name}/fast` : input.name;\n    workers.classes = {\n      draft: fast,\n      plan: input.name,\n      implement: input.name,\n      review: input.name,\n      research: input.name,\n      spotcheck: fast,\n      simple: fast,\n      complex: input.name,\n      image: input.name,\n    };\n  }\n\n  writeWorkersSection(raw, workers, input.configPath);\n  return workers;\n}\n\n/** Change costTier / tags on an existing provider (MCP action \"update\"). */\nexport function updateProvider(\n  name: string,\n  changes: { costTier?: number; tags?: string[] },\n  configPath?: string\n): WorkersConfig {\n  const { raw, workers } = readWorkersSection(configPath);\n  const p = workers.providers[name];\n  if (!p) {\n    throw new WorkersConfigError(\n      `no provider named \"${name}\". Configured: ${Object.keys(workers.providers).join(\", \") || \"(none)\"}`\n    );\n  }\n  if (changes.costTier !== undefined) {\n    if (!Number.isInteger(changes.costTier) || changes.costTier < 1 || changes.costTier > 5) {\n      throw new WorkersConfigError(\"costTier must be an integer 1 (cheapest) … 5 (most expensive)\");\n    }\n    p.costTier = changes.costTier;\n  }\n  if (changes.tags !== undefined) {\n    for (const t of changes.tags) {\n      if (!(PROVIDER_TAGS as readonly string[]).includes(t)) {\n        throw new WorkersConfigError(`\"${t}\" is not a tag (from: ${PROVIDER_TAGS.join(\", \")})`);\n      }\n    }\n    p.tags = changes.tags as WorkerProvider[\"tags\"];\n  }\n  writeWorkersSection(raw, workers, configPath);\n  return workers;\n}\n\nexport function removeProvider(name: string, configPath?: string): WorkersConfig {\n  const { raw, workers } = readWorkersSection(configPath);\n  if (!workers.providers[name]) {\n    throw new WorkersConfigError(`no provider named \"${name}\"`);\n  }\n  delete workers.providers[name];\n  for (const [cls, target] of Object.entries(workers.classes)) {\n    const targetProvider = typeof target === \"string\" ? target.split(\"/\")[0] : target.provider;\n    if (targetProvider === name) delete workers.classes[cls];\n  }\n  if (workers.active === name) workers.active = null;\n  writeWorkersSection(raw, workers, configPath);\n  return workers;\n}\n\n/**\n * Point a class target at `name`, keeping every other field. Only touches\n * targets that already pin a provider — a constraint-only object (no\n * `provider`) only narrows auto-routing and is left alone. A string target's\n * `/alias` is dropped (falling back to `name`'s default model) when `name`\n * has no such model configured — the class must move to `name` either way,\n * since leaving it on the old provider is exactly the bug this fixes.\n */\nfunction repointClassTarget(\n  target: ClassTarget,\n  name: string,\n  providers: WorkersConfig[\"providers\"]\n): ClassTarget | null {\n  if (typeof target === \"string\") {\n    const [provider, alias] = target.split(\"/\");\n    if (provider === name) return null;\n    if (alias && name !== ANTHROPIC_NATIVE && alias !== \"default\" && !providers[name]?.models[alias]) {\n      return name;\n    }\n    return alias ? `${name}/${alias}` : name;\n  }\n  if (!target.provider || target.provider === name) return null;\n  return { ...target, provider: name };\n}\n\n/**\n * Make `name` the active provider. Unless `name` is \"auto\", also re-points\n * every class whose target pins a provider (string or `{provider: …}`) at\n * it — a class pinned to a provider otherwise wins over `active` at run time\n * (routing.ts resolveTarget), so leaving classes untouched would make `use`\n * silently do nothing for any class already pinned elsewhere.\n */\nexport function useProvider(\n  name: string,\n  configPath?: string\n): { workers: WorkersConfig; repointed: number } {\n  const { raw, workers } = readWorkersSection(configPath);\n  if (name !== ANTHROPIC_NATIVE && name !== \"auto\" && !workers.providers[name]) {\n    throw new WorkersConfigError(\n      `no provider named \"${name}\". Configured: ${Object.keys(workers.providers).join(\", \") || \"(none)\"}`\n    );\n  }\n  workers.active = name;\n  let repointed = 0;\n  if (name !== \"auto\") {\n    for (const [cls, target] of Object.entries(workers.classes)) {\n      const next = repointClassTarget(target, name, workers.providers);\n      if (next !== null) {\n        workers.classes[cls] = next;\n        repointed++;\n      }\n    }\n  }\n  writeWorkersSection(raw, workers, configPath);\n  return { workers, repointed };\n}\n\n/**\n * The provider a model command targets: the named one, else the active one.\n * \"auto\" and an unset active both ask for an explicit name.\n */\nexport function resolveProviderName(workers: WorkersConfig, name?: string): string {\n  const target = name ?? workers.active ?? \"\";\n  if (target === ANTHROPIC_NATIVE || workers.providers[target]) return target;\n  if (!target) throw new WorkersConfigError(\"no active provider — name one explicitly\");\n  if (target === \"auto\") {\n    throw new WorkersConfigError('active is \"auto\" — name a provider explicitly');\n  }\n  throw new WorkersConfigError(\n    `no provider named \"${target}\". Configured: ${[ANTHROPIC_NATIVE, ...Object.keys(workers.providers)].join(\", \")}`\n  );\n}\n\n/**\n * Set a provider's model id for a capability — default, fast, image, …\n * (`pai worker model`, MCP worker_model).\n */\nexport function setProviderModel(\n  name: string,\n  capability: ModelCapability,\n  model: string,\n  configPath?: string\n): WorkersConfig {\n  if (!isModelCapability(capability)) {\n    throw new WorkersConfigError(\n      `\"${capability}\" is not a valid capability name (must match ^[a-z][a-z0-9-]*$; well-known: ${MODEL_CAPABILITIES.join(\", \")})`\n    );\n  }\n  const id = model.trim();\n  if (!id) throw new WorkersConfigError(`a ${capability} model id must not be empty`);\n  const { raw, workers } = readWorkersSection(configPath);\n  const p = getProviderOrNative(workers, name);\n  if (!p) {\n    throw new WorkersConfigError(\n      `no provider named \"${name}\". Configured: ${[ANTHROPIC_NATIVE, ...Object.keys(workers.providers)].join(\", \")}`\n    );\n  }\n  // the built-in provider is synthesized on read; its table is workers.nativeModels\n  (name === ANTHROPIC_NATIVE ? workers.nativeModels : p.models)[capability] = id;\n  writeWorkersSection(raw, workers, configPath);\n  return workers;\n}\n\nexport function setProviderEnabled(name: string, enabled: boolean, configPath?: string): WorkersConfig {\n  const { raw, workers } = readWorkersSection(configPath);\n  const p = workers.providers[name];\n  if (!p) throw new WorkersConfigError(`no provider named \"${name}\"`);\n  p.enabled = enabled;\n  writeWorkersSection(raw, workers, configPath);\n  // `enable` is also the manual cooldown-clear (spec: routing)\n  if (enabled) clearCooldown(workersLogDir(workers), name);\n  return workers;\n}\n\n/**\n * Point a class at a target (\"provider\", \"provider/fast\", or an object with\n * provider + optional mcp/maxCostTier/requireTags/order). An object without\n * a provider only constrains auto-routing for that class.\n */\nexport function setClass(name: string, target: ClassTarget, configPath?: string): WorkersConfig {\n  const { raw, workers } = readWorkersSection(configPath);\n  if (typeof target === \"string\") {\n    const [provider, alias] = target.split(\"/\");\n    const native = provider === ANTHROPIC_NATIVE;\n    const p = native ? undefined : workers.providers[provider];\n    if (!native && !p) {\n      throw new WorkersConfigError(\n        `no provider named \"${provider}\" in \"${target}\". Configured: ${Object.keys(workers.providers).join(\", \") || \"(none)\"}`\n      );\n    }\n    if (alias) {\n      if (!isModelCapability(alias)) {\n        throw new WorkersConfigError(\n          `unknown model alias \"${alias}\" — providers expose: ${MODEL_CAPABILITIES.join(\", \")}`\n        );\n      }\n      // the native provider has no configurable model slots — any alias\n      // resolves through resolveModelCapability's own default fallback\n      if (!native && alias !== \"default\" && !p!.models[alias]) {\n        throw new WorkersConfigError(`provider \"${provider}\" has no ${alias} model configured`);\n      }\n    }\n  } else if (target.provider) {\n    if (target.provider !== ANTHROPIC_NATIVE && !workers.providers[target.provider]) {\n      throw new WorkersConfigError(\n        `no provider named \"${target.provider}\". Configured: ${Object.keys(workers.providers).join(\", \") || \"(none)\"}`\n      );\n    }\n  }\n  workers.classes[name] = target;\n  writeWorkersSection(raw, workers, configPath);\n  return workers;\n}\n\nexport function unsetClass(name: string, configPath?: string): WorkersConfig {\n  const { raw, workers } = readWorkersSection(configPath);\n  if (!(name in workers.classes)) {\n    throw new WorkersConfigError(`no class named \"${name}\"`);\n  }\n  delete workers.classes[name];\n  writeWorkersSection(raw, workers, configPath);\n  return workers;\n}\n\nexport function setWorkersEnabled(enabled: boolean, configPath?: string): WorkersConfig {\n  const { raw, workers } = readWorkersSection(configPath);\n  workers.enabled = enabled;\n  writeWorkersSection(raw, workers, configPath);\n  return workers;\n}\n\n/** `glm/fast` | `{provider, mcp, …}` → one printable target line. */\nexport function classTargetText(target: ClassTarget): string {\n  if (typeof target === \"string\") return target;\n  const bits = [\n    target.provider ?? \"(routing)\",\n    ...(target.mcp?.length ? [`mcp(${target.mcp.join(\",\")})`] : []),\n    ...(target.maxCostTier !== undefined ? [`max tier ${target.maxCostTier}`] : []),\n    ...(target.requireTags?.length ? [`needs ${target.requireTags.join(\",\")}`] : []),\n    ...(target.order?.length ? [`order [${target.order.join(\",\")}]`] : []),\n  ];\n  return bits.join(\" \");\n}\n\n/**\n * `default X  fast Y  image Z  …` — every well-known capability on one line\n * (unset ones shown as \"(none)\"), plus any open-set capability this provider\n * actually declares (e.g. `vision`), which is only listed when set.\n */\nexport function modelPrefsText(p: WorkerProvider): string {\n  const known = new Set<string>(MODEL_CAPABILITIES);\n  const extra = Object.keys(p.models).filter((c) => !known.has(c)).sort();\n  return [...MODEL_CAPABILITIES, ...extra].map((c) => `${c} ${p.models[c] ?? \"(none)\"}`).join(\"  \");\n}\n\n/**\n * Compact model listing for `pai worker model` / worker_model get: the active\n * provider, then one line per provider with all its capability preferences.\n */\nexport function describeModels(workers: WorkersConfig): string[] {\n  const lines = [`active provider: ${workers.active ?? \"(none)\"}`];\n  for (const name of [...Object.keys(workers.providers), ANTHROPIC_NATIVE]) {\n    const p = getProviderOrNative(workers, name)!;\n    const active = workers.active === name ? \"  [active]\" : \"\";\n    lines.push(`${name}${active}  ${modelPrefsText(p)}`);\n  }\n  return lines;\n}\n\n/** Classes (in declaration order) whose target resolves to this provider. */\nfunction classesForProvider(workers: WorkersConfig, name: string): string[] {\n  return Object.entries(workers.classes)\n    .filter(([, target]) => (typeof target === \"string\" ? target.split(\"/\")[0] : target.provider) === name)\n    .map(([cls]) => cls);\n}\n\n/**\n * Human-readable provider listing (quota probe included when configured).\n * `running` marks each loopback provider \"running\" or \"not running\" — the\n * port probe of local-provider.ts, done by the callers in parallel with a\n * short timeout, so a model reading the list cannot mistake an\n * enabled-but-down server for a usable one.\n */\nexport function describeProviders(\n  workers: WorkersConfig,\n  configPath: string = CONFIG_FILE,\n  running?: Record<string, boolean>\n): string[] {\n  const lines: string[] = [];\n  const nativeActive = workers.active === ANTHROPIC_NATIVE;\n  const nativeDefault = !workers.active;\n  lines.push(\n    `${ANTHROPIC_NATIVE}  [built-in${nativeActive ? \", active\" : \"\"}]${nativeDefault ? \" (active: default)\" : \"\"}  Claude Code's own OAuth/Max-plan login — no base URL, no API key`\n  );\n  lines.push(`    ${modelPrefsText(nativeAnthropicProvider(workers.nativeModels))}`);\n  const nativeClasses = classesForProvider(workers, ANTHROPIC_NATIVE);\n  lines.push(`    classes: ${nativeClasses.length ? nativeClasses.join(\", \") : \"(none)\"}`);\n  const names = Object.keys(workers.providers);\n  if (!names.length) {\n    lines.push(`no other providers configured. Add one with:`);\n    lines.push(\n      `  pai worker providers add <name> --base-url <url> --key-file <path> --model <model>`\n    );\n    lines.push(`config: ${existsSync(workersYamlPath()) ? workersYamlPath() : configPath}`);\n    return lines;\n  }\n  for (const name of names) {\n    const p = workers.providers[name];\n    const flags = [\n      p.enabled ? \"enabled\" : \"disabled\",\n      workers.active === name ? \"active\" : null,\n    ].filter(Boolean);\n    const quota = p.quotaProbe ? probeQuota(p) : null;\n    const quotaNote = quota === null ? \"\" : `  quota ${quota}% (skip at ${quotaSkipThreshold(p)})`;\n    const tierTags = [`tier ${providerCostTier(p)}`, ...(p.tags ?? [])].join(\", \");\n    if (running && isLoopbackProvider(p)) flags.push(running[name] ? \"running\" : \"not running\");\n    lines.push(`${name}  [${flags.join(\", \")}]  ${p.baseUrl}`);\n    lines.push(`    ${modelPrefsText(p)}${quotaNote}`);\n    lines.push(`    ${tierTags}`);\n    if (p.key) lines.push(`    key ${maskKey(p.key)}`);\n    if (p.keyFile) lines.push(`    key file ${expandHome(p.keyFile)}`);\n    if (!p.key && !p.keyFile) lines.push(`    no key file (token \"local\")`);\n    if (p.note) lines.push(`    ${p.note}`);\n    if (p.protocol === \"openai\") {\n      lines.push(`    via PAI proxy ← ${p.upstreamUrl ?? \"(upstreamUrl missing)\"}`);\n    }\n    if (p.engine === \"codex\") {\n      lines.push(`    engine codex (runs through the Codex CLI)`);\n    }\n    if (p.engine === \"image\") {\n      lines.push(`    engine image (no process spawn — POSTs {url}/images/generations directly)`);\n    }\n    const cls = classesForProvider(workers, name);\n    lines.push(`    classes: ${cls.length ? cls.join(\", \") : \"(none)\"}`);\n  }\n  const setNames = Object.keys(workers.mcpSets);\n  if (setNames.length) {\n    lines.push(`mcp sets: ${setNames.map((s) => `${s}=[${workers.mcpSets[s].join(\",\")}]`).join(\"  \")}`);\n  }\n  if (workers.active === \"auto\") {\n    lines.push(`routing: auto — order [${workers.routing.order.join(\", \")}], cooldown ${workers.routing.cooldownMinutes}m`);\n  }\n  lines.push(`config: ${existsSync(workersYamlPath()) ? workersYamlPath() : configPath}`);\n  return lines;\n}\n\n/**\n * Set which provider(s), in order, serve a capability across the whole\n * config (`pai worker capability <name> <provider>[,<provider>…]`, MCP\n * worker_capability). resolveCapability walks this list at run time.\n */\nexport function setCapabilityPreference(\n  capability: string,\n  providers: string[],\n  configPath?: string\n): WorkersConfig {\n  if (!isModelCapability(capability)) {\n    throw new WorkersConfigError(`\"${capability}\" is not a valid capability name (must match ^[a-z][a-z0-9-]*$)`);\n  }\n  if (!providers.length) {\n    throw new WorkersConfigError(\"at least one provider name is required\");\n  }\n  const { raw, workers } = readWorkersSection(configPath);\n  for (const name of providers) {\n    if (name !== ANTHROPIC_NATIVE && !workers.providers[name]) {\n      throw new WorkersConfigError(\n        `no provider named \"${name}\". Configured: ${Object.keys(workers.providers).join(\", \") || \"(none)\"}`\n      );\n    }\n  }\n  workers.capabilities[capability] = providers;\n  writeWorkersSection(raw, workers, configPath);\n  return workers;\n}\n\nexport function unsetCapabilityPreference(capability: string, configPath?: string): WorkersConfig {\n  const { raw, workers } = readWorkersSection(configPath);\n  if (!(capability in workers.capabilities)) {\n    throw new WorkersConfigError(`no capability preference set for \"${capability}\"`);\n  }\n  delete workers.capabilities[capability];\n  writeWorkersSection(raw, workers, configPath);\n  return workers;\n}\n\n/**\n * `pai worker capability` with no args: every configured `capabilities:`\n * preference and what it resolves to right now — provider/model/engine, or\n * `fallback: <provider>/<model>` when nothing on the list actually declares\n * the capability (see resolveCapability's fellBack flag).\n */\nexport function describeCapabilities(workers: WorkersConfig): string[] {\n  const names = Object.keys(workers.capabilities);\n  if (!names.length) {\n    return [\"no capability preferences set — set one with `pai worker capability <name> <provider>[,<provider>…]`\"];\n  }\n  return names.map((cap) => {\n    const pref = workers.capabilities[cap];\n    try {\n      const r = resolveCapability(workers, cap);\n      const resolved = r.fellBack ? `fallback: ${r.provider}/${r.model}` : `${r.provider}/${r.model}  engine ${r.engine}`;\n      return `${cap}: [${pref.join(\", \")}] -> ${resolved}`;\n    } catch (e) {\n      return `${cap}: [${pref.join(\", \")}] -> unresolved: ${e instanceof Error ? e.message : String(e)}`;\n    }\n  });\n}\n","/**\n * target.ts — where delegated work runs, said in plain words. Every delegation\n * entry point (MCP worker_handoff, queue_add/queue_run, plan_save/plan_run,\n * `pai worker run`) takes the same three optional arguments and resolves them\n * here, once:\n *\n *   where  \"local\" | \"cloud\" | <provider name>   (omitted: today's routing)\n *   model  \"default\" | \"fast\" | <model id>\n *   now    true: front of the provider's waiting order\n *\n * \"local\" is resolveLocalProvider(); \"cloud\" is the session's cloud provider\n * (the provider normal routing follows: detectSessionProvider, else workers.yaml\n * `active`, each only when not loopback, else anthropic). The description is the line a tool result starts\n * with, so the session can tell the operator where the work runs.\n */\n\nimport { CliError } from \"../cli/define.js\";\nimport { ANTHROPIC_NATIVE, getProviderOrNative, readWorkersSection, type WorkersConfig } from \"./config.js\";\nimport { probeLoopback, resolveLocalProvider, type ResolveLocalOpts } from \"./local-provider.js\";\nimport { isLoopbackProvider } from \"./run-env.js\";\nimport { detectSessionProvider } from \"./session-provider.js\";\nimport { workersLogDir } from \"./paths.js\";\nimport { detectSessionName } from \"./session-name.js\";\nimport { liveResolveCtx, resolveWorkers, type ResolveCtx } from \"./session-profile.js\";\n\nexport interface TargetArgs {\n  where?: string;\n  model?: string;\n  now?: boolean;\n  /** The spawn is part of a fan-out (queue run, plan run with parallel > 1): session-profile fallback honours parallel_min. */\n  batch?: boolean;\n}\n\nexport interface Target {\n  /** Provider to run on; undefined when `where` was omitted (today's routing decides). */\n  provider?: string;\n  /** Concrete model id, or the alias \"fast\" when no provider is fixed; undefined = the provider's/class default. */\n  model?: string;\n  /** `fast` asked with no provider fixed: the routed provider's fast model (RunOptions.modelFast). */\n  modelFast?: boolean;\n  /** `default` asked with no provider fixed: the routed provider's default model, whatever its worker_model (RunOptions.modelDefault). */\n  modelDefault?: boolean;\n  /** \"front\": goes ahead of the provider's waiting runs. */\n  priority?: \"front\";\n  /** One plain line: \"local: flashnext-iq3\", \"cloud: anthropic sonnet\", \"kimi k3\". */\n  description: string;\n}\n\nexport interface TargetDeps extends ResolveLocalOpts {\n  workers: Pick<WorkersConfig, \"providers\" | \"nativeModels\"> & { active?: string | null };\n  logDir: string;\n  env?: NodeJS.ProcessEnv;\n  /** Session-profile resolution context (session-profile.ts); default: the live one. */\n  profileCtx?: () => Promise<ResolveCtx>;\n}\n\n/** The deps for the live config. */\nexport function liveTargetDeps(): TargetDeps {\n  const { workers } = readWorkersSection();\n  return { workers, logDir: workersLogDir(workers) };\n}\n\ntype ProviderTable = TargetDeps[\"workers\"];\n\nfunction modelFor(cfg: ProviderTable, provider: string, model: string | undefined): string {\n  const p = getProviderOrNative(cfg, provider);\n  const m = model?.trim();\n  if (m && m !== \"default\" && m !== \"fast\") return m;\n  if (m === \"fast\" || (m !== \"default\" && p?.workerModel === \"fast\")) return p?.models.fast ?? p?.models.default ?? \"\";\n  return p?.models.default ?? \"\";\n}\n\n/** The provider \"the cloud\" means for this session. */\nfunction cloudProvider(cfg: ProviderTable, env: NodeJS.ProcessEnv, logDir: string): string {\n  const usable = (n: string | null | undefined): n is string => {\n    if (!n || n === \"auto\") return false;\n    const p = getProviderOrNative(cfg, n);\n    return !!p && p.enabled && !isLoopbackProvider(p);\n  };\n  const session = detectSessionProvider(cfg, { env, logDir })?.name;\n  if (usable(session)) return session;\n  if (usable(cfg.active)) return cfg.active;\n  return ANTHROPIC_NATIVE;\n}\n\nasync function unknownProvider(cfg: ProviderTable, name: string, why: string, opts: ResolveLocalOpts): Promise<CliError> {\n  const running = await probeLoopback(cfg, opts.check);\n  const names = [ANTHROPIC_NATIVE, ...Object.entries(cfg.providers).filter(([, p]) => p.enabled).map(([n]) => n)];\n  const list = names.map((n) => (n in running ? `${n} (${running[n] ? \"running\" : \"not running\"})` : n)).join(\", \");\n  return new CliError(`no usable provider \"${name}\": ${why}`, `valid: ${list}; or where local / cloud`);\n}\n\n/** Resolve where/model/now into a provider, model and priority. */\nexport async function resolveTarget(args: TargetArgs, deps: TargetDeps = liveTargetDeps()): Promise<Target> {\n  const where = args.where?.trim() || undefined;\n  const modelArg = args.model?.trim() || undefined;\n  const priority = args.now === true ? (\"front\" as const) : undefined;\n  const cfg = deps.workers;\n\n  if (!where) {\n    // the session's own profile (or its fallback) decides before today's routing does\n    const env = deps.env ?? process.env;\n    const r = deps.profileCtx || (await detectSessionName(env))\n      ? resolveWorkers({ explicit: { model: modelArg }, batch: args.batch }, await (deps.profileCtx ?? (() => liveResolveCtx(env)))())\n      : undefined;\n    if (r?.source === \"none\") throw new CliError(r.description, \"pai session profile: session_profile_set fallback / parallel_min\");\n    if (r?.provider && (r.source === \"profile\" || r.source === \"fallback\")) {\n      const model = modelFor(cfg, r.provider, r.model);\n      return { provider: r.provider, model: model || undefined, priority, description: `${r.description}${priority ? \", first in line\" : \"\"}` };\n    }\n    const fast = modelArg === \"fast\";\n    const dflt = modelArg === \"default\";\n    const id = modelArg && modelArg !== \"default\" && !fast ? modelArg : undefined;\n    return { model: id, modelFast: fast || undefined, modelDefault: dflt || undefined, priority, description: `default routing${id ? ` ${id}` : fast ? \" fast model\" : \"\"}${priority ? \", first in line\" : \"\"}` };\n  }\n\n  let provider: string;\n  let label: string;\n  if (where === \"local\") {\n    provider = (await resolveLocalProvider(cfg, deps.logDir, deps)).name;\n    label = \"local: \";\n  } else if (where === \"cloud\") {\n    provider = cloudProvider(cfg, deps.env ?? process.env, deps.logDir);\n    label = \"cloud: \";\n  } else {\n    const p = getProviderOrNative(cfg, where);\n    if (!p) throw await unknownProvider(cfg, where, \"not configured\", deps);\n    if (!p.enabled) throw await unknownProvider(cfg, where, \"disabled\", deps);\n    provider = where;\n    label = \"\";\n  }\n  const model = modelFor(cfg, provider, modelArg);\n  const named = label === \"local: \" ? provider : `${provider}${model ? ` ${model}` : \"\"}`;\n  return { provider, model: model || undefined, priority, description: `${label}${named}${priority ? \", first in line\" : \"\"}` };\n}\n\n/** Resolver seam the entry points take, so tests inject. */\nexport type TargetResolver = (args: TargetArgs) => Promise<Target>;\n\n/** Lead line of a tool result: where it runs, when the caller said anything. */\nexport function withTarget(t: Target | undefined, body: string): string {\n  return t ? `Runs on ${t.description}.\\n${body}` : body;\n}\n","/**\n * Workers: `pai worker <verb>` — run a task on another provider, watch it,\n * talk to it, merge what it did. Thin: every verb calls src/workers/*, the\n * same code the MCP tools and the Agent hook use. Names, flags, stdout and\n * exit codes are the ones hooks, prompts, skills and shims already call.\n */\n\nimport { currentWorkerId } from \"../../workers/worker-id.js\";\nimport { spawn } from \"node:child_process\";\nimport { existsSync, readdirSync, readFileSync, statSync } from \"node:fs\";\nimport { getProviderOrNative, isModelCapability, readWorkersSection, WorkersConfigError, type ModelCapability, type WorkerProvider, type WorkersConfig } from \"../../workers/config.js\";\nimport { eventsPath, ledgerPath, workersLogDir } from \"../../workers/paths.js\";\nimport { longInlinePromptHint, parseRunnerArgs } from \"../../workers/args.js\";\nimport { runWorker, type RunOptions } from \"../../workers/run.js\";\nimport { runChain } from \"../../workers/chain.js\";\nimport { realDeps as waitOnDeps, statusMarker, statusQueue, waitOn } from \"../../workers/wait-on.js\";\nimport { readSpecPrompt, resolveSpecPath } from \"../../workers/specfile.js\";\nimport { agentClaudeArgs, agentLabel, deriveLabel, loadAgent, modelToClass } from \"../../workers/agents.js\";\nimport { followTailOutput, followWorkers,psOutput, replayOutput, statusLineOutput } from \"../../workers/viewer.js\";\nimport { assertPaneNotDisabled, checkPaneForWorker, closeEndedPanes, openFollowPane, openPaneForWorker, resolveHostSession } from \"../../workers/pane.js\";\nimport { renderUsage, usageJson, parseWhen, workerUsage } from \"../../workers/usage.js\";\nimport { ageOf, loadStatus, setWorkerNote } from \"../../workers/status.js\";\nimport { providerCap, queueRows, reorderQueue } from \"../../workers/capacity.js\";\nimport { killTree } from \"../../workers/kill-tree.js\";\nimport { sayToWorker } from \"../../workers/operator.js\";\nimport { handoffFromInside } from \"../../workers/handoff.js\";\nimport { gitChangedFiles, HELP_REFUSED_EXIT, readHelpLedger, renderHelpReport, requestHelp, spawnPaiWorker } from \"../../workers/help.js\";\nimport { readMergeVerify } from \"../../workers/workers-config.js\";\nimport { discardWorker, formatKnowledge, gcWorktrees, leftoverWorktrees, mergeWorker, verifyWorker } from \"../../workers/worktree.js\";\nimport { formatPending, pendingGate, pendingResults } from \"../../workers/pending.js\";\nimport { runWait } from \"../../workers/wait.js\";\nimport { realProbeDeps, waitFile, waitUrl } from \"../../workers/wait-probes.js\";\nimport { describeModels, describeCapabilities, modelPrefsText, resolveProviderName, setCapabilityPreference, setProviderModel, unsetCapabilityPreference } from \"../../workers/providers.js\";\nimport { BATCH_ENV } from \"../../workers/session-profile.js\";\nimport { resolveTarget, type TargetResolver } from \"../../workers/target.js\";\nimport { CliError, OPT, type CommandDef, type RunContext } from \"../define.js\";\nimport { dim, err, ok } from \"../lib/utils.js\";\n\n// ---------------------------------------------------------------------------\n// Shared helpers\n// ---------------------------------------------------------------------------\n\nfunction logDir(): string {\n  try {\n    return workersLogDir(readWorkersSection().workers);\n  } catch (e) {\n    throw new CliError(`cannot read the worker configuration: ${msgOf(e)}`, \"pai config path   (shows which file is read)\");\n  }\n}\n\nconst msgOf = (e: unknown) => (e instanceof Error ? e.message : String(e));\n\n/** Run a verb; any thrown error becomes one plain sentence (exit 1) with the next command. */\nasync function guard(next: string, fn: () => Promise<number | void> | number | void): Promise<number | void> {\n  try {\n    return await fn();\n  } catch (e) {\n    if (e instanceof CliError) throw e;\n    throw new CliError(msgOf(e), next);\n  }\n}\n\nconst str = (v: unknown): string | undefined => (typeof v === \"string\" ? v : undefined);\nconst flag = (ctx: RunContext, name: string): boolean => ctx.opts[name] === true;\nconst num = (v: unknown): number | undefined => (typeof v === \"number\" ? v : undefined);\nconst out = (s: string) => process.stdout.write(s + \"\\n\");\n\n// ---------------------------------------------------------------------------\n// run / resume\n// ---------------------------------------------------------------------------\n\n/**\n * Everything `worker run` hands to the engine, built from the parsed flags.\n * Pure apart from reading the spec/agent files, so the argv it produces can be\n * compared with the old command's.\n */\nexport type RunPlan =\n  | { kind: \"chain\"; chain: Parameters<typeof runChain>[0] }\n  | { kind: \"run\"; run: RunOptions };\n\nexport function buildRunPlan(ctx: RunContext): RunPlan {\n  const o = ctx.opts;\n  const className = str(o.class) ?? str(o.role);\n  const report = str(o.report);\n  if (report !== undefined && report !== \"json\" && report !== \"ag2\") {\n    throw new Error(`--report: expected \"json\" or \"ag2\", got \"${report}\"`);\n  }\n  const cwd = str(o.cwd);\n  if (cwd !== undefined) {\n    if (!existsSync(cwd)) throw new Error(`--cwd: directory does not exist: ${cwd}`);\n    if (!statSync(cwd).isDirectory()) throw new Error(`--cwd: not a directory: ${cwd}`);\n  }\n  const noPane = o[\"no-pane\"] === true;\n  let claudeArgs = ctx.rest;\n  let specPath: string | undefined;\n  const spec = str(o.spec);\n  if (spec !== undefined) {\n    if (parseRunnerArgs(ctx.rest).headless) {\n      throw new Error(\"--spec and -p/--print are mutually exclusive — pass the prompt one way, not both\");\n    }\n    const cwdForSpec = cwd ?? process.cwd();\n    specPath = resolveSpecPath(spec, cwdForSpec);\n    claudeArgs = [\"-p\", readSpecPrompt(spec, cwdForSpec), ...ctx.rest];\n  } else {\n    const hint = longInlinePromptHint(parseRunnerArgs(ctx.rest).prompt);\n    if (hint) process.stderr.write(hint + \"\\n\");\n  }\n\n  assertPaneNotDisabled(noPane);\n  let label = str(o.label);\n  let agentClass: string | undefined;\n  const agent = str(o.agent);\n  if (agent) {\n    const def = loadAgent(agent);\n    claudeArgs = [...agentClaudeArgs(def), ...claudeArgs];\n    let agentProviders: Record<string, WorkerProvider> | undefined;\n    try {\n      agentProviders = readWorkersSection().workers.providers;\n    } catch {\n      agentProviders = undefined;\n    }\n    agentClass = modelToClass(def.model, agentProviders);\n    if (!label) label = agentLabel(agent, parseRunnerArgs(claudeArgs).prompt);\n  }\n  const chain = str(o.chain);\n  if (chain) {\n    const brief = parseRunnerArgs(claudeArgs).prompt;\n    if (!brief) throw new Error(\"--chain needs the task as -p '<brief>'\");\n    return {\n      kind: \"chain\",\n      chain: {\n        stages: chain.split(\",\"),\n        className: className ?? agentClass,\n        providerFlag: str(o.provider),\n        modelFlag: str(o.model),\n        label,\n        noPane,\n        mcpFlag: str(o.mcp),\n        specPath,\n        cwd,\n        brief,\n        claudeArgs,\n      },\n    };\n  }\n  if (!label) label = deriveLabel(parseRunnerArgs(claudeArgs).prompt, className ?? agentClass ?? \"default\");\n  return {\n    kind: \"run\",\n    run: {\n      providerFlag: str(o.provider),\n      localFlag: o.local === true ? true : undefined,\n      urgent: o.urgent === true ? true : undefined,\n      localOk: o[\"local-ok\"] === true ? true : undefined,\n      cloud: o.cloud === true ? true : undefined,\n      className: className ?? agentClass,\n      modelFlag: str(o.model),\n      label,\n      mcpFlag: str(o.mcp),\n      specPath,\n      cwd,\n      noPane,\n      noStagger: o[\"no-stagger\"] === true ? true : undefined,\n      noQueue: o[\"no-queue\"] === true ? true : undefined,\n      worktreeFlag: o[\"no-worktree\"] === true ? false : o.worktree === true ? true : undefined,\n      maxMinutes: num(o[\"max-minutes\"]),\n      deadline: str(o.deadline),\n      browser: o[\"no-browser\"] === true ? false : o.browser === true ? true : undefined,\n      printCmd: o[\"print-cmd\"] === true || ctx.dryRun ? true : undefined,\n      reportFormatFlag: report as \"json\" | \"ag2\" | undefined,\n      noReportRetry: o[\"no-report-retry\"] === true,\n      orchestrate: o.orchestrate === true ? true : undefined,\n      capabilityFlag: str(o.capability) ?? str(o.for),\n      imageOut: str(o.out),\n      imageSize: str(o.size),\n      imageTimeoutMs: num(o[\"timeout-ms\"]),\n      claudeArgs,\n    },\n  };\n}\n\n/** --where / --model / --now through resolveTarget (target.ts), the one resolver every delegation entry point uses. */\nexport async function applyTarget(ctx: RunContext, plan: RunPlan, resolveIt: TargetResolver = resolveTarget): Promise<void> {\n  const where = str(ctx.opts.where);\n  const model = str(ctx.opts.model);\n  const now = flag(ctx, \"now\");\n  if (!where && !now && model !== \"fast\" && model !== \"default\") return;\n  if (where && flag(ctx, \"local\")) throw new Error(\"--where and --local both name where to run; use one\");\n  const t = await resolveIt({ where, model, now });\n  process.stderr.write(`pai worker: ${t.description}\\n`);\n  const target = plan.kind === \"chain\" ? plan.chain : plan.run;\n  if (t.provider) target.providerFlag = t.provider;\n  // \"default\" / \"fast\" are aliases, never a raw model id\n  target.modelFlag = model === \"default\" || model === \"fast\" ? t.model : (t.model ?? target.modelFlag);\n  if (plan.kind === \"run\") {\n    if (t.modelFast) plan.run.modelFast = true;\n    if (t.modelDefault) plan.run.modelDefault = true;\n    if (t.priority) plan.run.priority = t.priority;\n  }\n}\n\nconst runCommand: CommandDef = {\n  name: \"run\",\n  summary: \"Run one task on a worker (another provider or model)\",\n  description:\n    \"Starts a Claude Code worker through the chosen provider and waits for it. The task goes in as -p '<task>' or, safer for long text, --spec FILE.\\n\" +\n    \"Options this command does not know (for example -p, --allowedTools) are handed to claude unchanged.\\n\" +\n    \"--label is the row shown in `ps`, `follow` and the status line; without it the first line of the task is used.\\n\" +\n    \"Give a worker an MCP tool by naming mcp__server__tool in --allowedTools; the server loads by itself.\",\n  allowUnknown: true,\n  options: [\n    { ...OPT.provider, summary: \"Provider to run on (default: the active one, else the routing order)\" },\n    { name: \"class\", type: \"string\", value: \"NAME\", summary: \"Use the provider set for this kind of work (draft, implement, review, research, spotcheck, simple, complex, image)\" },\n    { name: \"role\", type: \"string\", value: \"NAME\", summary: \"Old name of --class\" },\n    { name: \"capability\", type: \"string\", value: \"NAME\", summary: \"Run on whichever provider serves this capability (see `pai worker capability`), e.g. image\" },\n    { name: \"for\", type: \"string\", value: \"NAME\", summary: \"Short for --capability\" },\n    { name: \"out\", type: \"string\", value: \"FILE\", summary: \"Where an image run writes its PNG (default: next to the worker log)\" },\n    { name: \"size\", type: \"string\", value: \"WxH\", summary: \"Image size for an image run, e.g. 1024x1024 (default 1024x1024)\" },\n    { name: \"timeout-ms\", type: \"number\", value: \"N\", summary: \"How long an image run waits for its answer (default 120000)\" },\n    { name: \"chain\", type: \"string\", value: \"STAGES\", summary: \"Comma-separated stages run one after the other, e.g. draft,implement,review\" },\n    { name: \"agent\", type: \"string\", value: \"NAME\", summary: \"Run the agent definition ~/.claude/agents/NAME.md on a worker\" },\n    { ...OPT.model, summary: \"Model for this run: default, fast or a model id (default: the model set for the class)\" },\n    { name: \"urgent\", type: \"boolean\", summary: \"Needs a fast answer: go to the cloud even when the policy prefers local (see `pai worker policy`)\" },\n    { name: \"where\", type: \"string\", value: \"WHERE\", summary: \"Where to run: local, cloud or a provider name (local and cloud are resolved by PAI; same as the MCP delegation tools' where)\" },\n    { name: \"batch\", type: \"boolean\", summary: \"This run is part of a fan-out: session-profile fallback skips targets below the profile's parallel_min\" },\n    { name: \"now\", type: \"boolean\", summary: \"Go ahead of the runs waiting for a slot on the provider\" },\n    { name: \"local\", type: \"boolean\", summary: \"Run on the local model server PAI resolves (the one that answers); never pick a local provider by name\" },\n    { name: \"local-ok\", type: \"boolean\", summary: \"This run may go to a local provider under the prefer-cloud policy\" },\n    { name: \"cloud\", type: \"boolean\", summary: \"This run goes to the cloud under the prefer-local or auto policy\" },\n    { name: \"label\", type: \"string\", value: \"TEXT\", summary: \"Short task label shown in ps, follow and the status line\" },\n    { name: \"spec\", type: \"string\", value: \"FILE\", summary: \"Read the task from this file (or - for stdin) instead of -p\" },\n    { name: \"cwd\", type: \"string\", value: \"DIR\", summary: \"Directory the worker runs in (default: here)\" },\n    { name: \"mcp\", type: \"string\", value: \"NAMES\", summary: \"MCP servers or sets this worker may use, comma-separated (see `pai worker mcp`)\" },\n    { name: \"no-pane\", type: \"boolean\", summary: \"Run without a visible pane (refused unless a worker or the operator override allows it)\" },\n    { name: \"no-queue\", type: \"boolean\", summary: \"Do not queue behind the provider's concurrent-run cap (workers.yaml maxConcurrent)\" },\n    { name: \"no-stagger\", type: \"boolean\", summary: \"Do not wait for an earlier run on the same provider to warm its prompt cache\" },\n    { name: \"worktree\", type: \"boolean\", summary: \"Work in a git worktree on branch worker/ID (default for implement and complex work in a git repo)\" },\n    { name: \"no-worktree\", type: \"boolean\", summary: \"Work in place, no worktree\" },\n    { name: \"max-minutes\", type: \"number\", value: \"N\", summary: \"Stop after N minutes and keep the work (0 = no limit; default from the config, 60)\" },\n    { name: \"deadline\", type: \"string\", value: \"HH:MM\", summary: \"Stop at this local time (tomorrow if already past); not with --max-minutes\" },\n    { name: \"browser\", type: \"boolean\", summary: \"Allow browser tools\" },\n    { name: \"no-browser\", type: \"boolean\", summary: \"Remove every browser tool from this worker\" },\n    { name: \"print-cmd\", type: \"boolean\", summary: \"Print the claude command as JSON and exit without starting anything\" },\n    { name: \"report\", type: \"string\", value: \"FORMAT\", summary: \"Final report format: json or ag2 (default ag2)\" },\n    { name: \"no-report-retry\", type: \"boolean\", summary: \"Do not ask once more when the final report is malformed\" },\n    { name: \"orchestrate\", type: \"boolean\", summary: \"This worker plans and reviews; code edits are denied and go to local units\" },\n  ],\n  examples: [\n    \"pai worker run --class implement --label 'fix the retry loop' -p 'Fix the retry loop in src/net.ts'\",\n    \"pai worker run --provider glm --spec /tmp/task.txt\",\n    \"pai worker run --local -p 'Summarize the changelog'\",\n    \"pai worker run --where cloud --model fast --now -p 'Say hi'\",\n    \"pai worker run --chain draft,implement,review -p 'Add a --json flag to the export command'\",\n    \"pai worker run --print-cmd --class spotcheck -p 'Say hi'\",\n  ],\n  seeAlso: [\"pai worker ps\", \"pai worker follow\", \"pai worker merge\", \"pai worker resume\"],\n  run: (ctx) =>\n    guard(\"pai worker run --print-cmd -p 'test'   (shows the command without starting it)\", async () => {\n      const plan = buildRunPlan(ctx);\n      if (flag(ctx, \"batch\")) process.env[BATCH_ENV] = \"1\";\n      await applyTarget(ctx, plan);\n      return plan.kind === \"chain\" ? await runChain(plan.chain) : await runWorker(plan.run);\n    }),\n};\n\nconst resumeCommand: CommandDef = {\n  name: \"resume\",\n  summary: \"Continue a finished worker with a new instruction\",\n  description: \"Starts a new worker on the same provider and model that picks up the conversation of a finished one (claude --resume).\",\n  args: [\n    { name: \"ID\", required: true, summary: \"Id of the finished worker (see `pai worker ps`)\" },\n    { name: \"TEXT\", required: true, summary: \"What the worker should do next\" },\n  ],\n  options: [\n    { name: \"print-id\", type: \"boolean\", summary: \"Print the new worker id on its own line\" },\n    { name: \"no-pane\", type: \"boolean\", summary: \"Run without a visible pane (refused unless allowed)\" },\n    { name: \"output-format\", type: \"string\", value: \"FORMAT\", summary: \"text (default), json or stream-json, as for `run`\" },\n    { name: \"label\", type: \"string\", value: \"TEXT\", summary: \"Short task label (default: the old label with a return arrow)\" },\n  ],\n  examples: [\"pai worker resume w-20260101-abc 'Also add a test'\", \"pai worker resume w-20260101-abc 'Continue' --print-id\"],\n  seeAlso: [\"pai worker ps\", \"pai worker run\"],\n  run: (ctx) =>\n    guard(\"pai worker ps   (lists worker ids)\", async () => {\n      const id = ctx.args.ID as string;\n      const text = ctx.args.TEXT as string;\n      const noPane = flag(ctx, \"no-pane\");\n      assertPaneNotDisabled(noPane);\n      const dir = logDir();\n      const old = loadStatus(dir, id);\n      if (!old) throw new Error(`no worker named \"${id}\"`);\n      if (!old.claudeSession) {\n        throw new Error(\n          `worker ${id} recorded no Claude session id — it predates resume support or ran through an engine that does not expose one`\n        );\n      }\n      const claudeArgs = [\"--resume\", old.claudeSession, \"-p\", text];\n      const fmt = str(ctx.opts[\"output-format\"]);\n      if (fmt !== undefined) claudeArgs.push(\"--output-format\", fmt);\n      let newId = \"\";\n      const rc = await runWorker({\n        providerFlag: old.provider,\n        modelFlag: old.model,\n        label: str(ctx.opts.label) || `↩ ${old.label}`,\n        noPane,\n        claudeArgs,\n        resumeOf: id,\n        onWorkerStart: (wid) => {\n          newId = wid;\n        },\n      });\n      if (flag(ctx, \"print-id\") && newId) out(newId);\n      return rc;\n    }),\n};\n\n// ---------------------------------------------------------------------------\n// Looking at workers\n// ---------------------------------------------------------------------------\n\nconst psCommand: CommandDef = {\n  name: \"ps\",\n  summary: \"List this session's workers, running and finished\",\n  description:\n    \"Shows the workers started from this terminal. When other sessions have live workers too, a MACHINE section lists every live worker on this computer with the session that owns it.\",\n  options: [{ name: \"all\", type: \"boolean\", summary: \"Workers of all sessions, not just this terminal's\" }],\n  examples: [\"pai worker ps\", \"pai worker ps --all\"],\n  seeAlso: [\"pai worker follow\", \"pai worker pending\", \"pai worker kill\"],\n  run: (ctx) =>\n    guard(\"pai worker ps --all\", () => {\n      const dir = logDir();\n      const pending = pendingResults(dir, process.cwd()).length;\n      if (pending) out(`${pending} unmerged result(s) — pai worker pending`);\n      const left = leftoverWorktrees(dir);\n      if (left) out(`worktrees: ${left} finished, not merged; pai worker gc --dry-run`);\n      out(psOutput(dir, flag(ctx, \"all\")));\n    }),\n};\n\nconst usageCommand: CommandDef = {\n  name: \"usage\",\n  summary: \"Token totals per provider and model for a set of workers\",\n  description:\n    \"Sums the exact tokens of the selected workers per provider and model: input, cache read, cache write 5m and 1h, output, plus the reported cost. A run's result event is authoritative when it carries totals; otherwise the assistant messages are summed (killed runs). Local providers are marked and carry no cost. \" +\n    \"This is the worker side of the A/B comparison; the top session's side is `pai audit tokens usage`.\",\n  options: [\n    { name: \"label\", type: \"string\", value: \"PREFIX\", summary: \"Only workers whose label starts with PREFIX\" },\n    { name: \"since\", type: \"string\", value: \"WHEN\", summary: \"Only workers started at or after WHEN (ISO time, or 1h / 30m)\" },\n    { name: \"until\", type: \"string\", value: \"WHEN\", summary: \"Only workers started at or before WHEN (ISO time, or 1h / 30m)\" },\n    OPT.json,\n  ],\n  examples: [\"pai worker usage --since 2h\", \"pai worker usage --label armA --since 2026-10-18T06:00:00 --json\"],\n  seeAlso: [\"pai audit tokens usage\", \"pai worker ps\"],\n  run: (ctx) =>\n    guard(\"pai worker ps\", () => {\n      const { workers } = readWorkersSection();\n      const baseUrls = Object.fromEntries(Object.entries(workers.providers).map(([k, v]) => [k, v.baseUrl]));\n      const rep = workerUsage(\n        logDir(),\n        {\n          labelPrefix: str(ctx.opts.label),\n          since: str(ctx.opts.since) ? parseWhen(str(ctx.opts.since)!) : undefined,\n          until: str(ctx.opts.until) ? parseWhen(str(ctx.opts.until)!) : undefined,\n        },\n        baseUrls\n      );\n      const help = readHelpLedger(logDir());\n      out(\n        flag(ctx, \"json\")\n          ? JSON.stringify({ ...(usageJson(rep) as object), help }, null, 2)\n          : renderUsage(rep, { workers: true }) + (help.length ? `\\n\\nhelp calls:\\n${renderHelpReport(help)}` : \"\")\n      );\n    }),\n};\n\nconst followCommand: CommandDef = {\n  name: \"follow\",\n  summary: \"Watch a worker live, or all running workers\",\n  description: \"Live view of one worker's transcript, or of every running worker in this session. Ctrl-C leaves it.\",\n  args: [{ name: \"ID\", summary: \"Worker id (default: all running workers of this session)\" }],\n  options: [\n    { name: \"all\", type: \"boolean\", summary: \"Follow the workers of all sessions\" },\n    { name: \"auto-exit\", type: \"number\", value: \"SECS\", optionalValue: true, summary: \"Leave SECS seconds after the workers end (default from the config)\" },\n    { name: \"live\", type: \"boolean\", summary: \"Stream even without a terminal (default there: print the tail and exit)\" },\n    { name: \"tail\", type: \"number\", value: \"N\", summary: \"Entries printed when there is no terminal (default 20)\" },\n  ],\n  examples: [\"pai worker follow\", \"pai worker follow w-20260101-abc\", \"pai worker follow --all --auto-exit 10\"],\n  seeAlso: [\"pai worker ps\", \"pai worker replay\", \"pai worker pane\"],\n  run: (ctx) =>\n    guard(\"pai worker ps\", async () => {\n      const { workers } = readWorkersSection();\n      const ae = ctx.opts[\"auto-exit\"];\n      const autoExit = ae === undefined || ae === false ? 0 : ae === true ? workers.pane.autoExitSecs : Number(ae);\n      const target = (ctx.args.ID as string | undefined) ?? null;\n      const tailText = followTailOutput(logDir(), target, {\n        live: flag(ctx, \"live\"),\n        autoExit: ae !== undefined && ae !== false,\n        tail: num(ctx.opts.tail),\n      });\n      if (tailText !== null) {\n        out(tailText);\n        return;\n      }\n      await followWorkers(logDir(), target, flag(ctx, \"all\"), autoExit);\n    }),\n};\n\nconst replayCommand: CommandDef = {\n  name: \"replay\",\n  summary: \"Print the transcript of one worker\",\n  description: \"Shows what a finished or running worker did, from its recorded events.\",\n  args: [{ name: \"ID\", required: true, summary: \"Worker id (see `pai worker ps`)\" }],\n  options: [{ name: \"tail\", type: \"number\", value: \"N\", summary: \"Only the last N lines\" }],\n  examples: [\"pai worker replay w-20260101-abc\", \"pai worker replay w-20260101-abc --tail 40\"],\n  seeAlso: [\"pai worker follow\", \"pai worker log\"],\n  run: (ctx) =>\n    guard(\"pai worker ps\", () => {\n      out(replayOutput(logDir(), ctx.args.ID as string, process.stdout.isTTY === true, num(ctx.opts.tail)));\n    }),\n};\n\nconst watchCommand: CommandDef = {\n  name: \"watch\",\n  summary: \"Worker list that refreshes every 2 seconds\",\n  description: \"Runs `pai worker ps --all` again every 2 seconds with the system `watch` program. Ctrl-C leaves it.\",\n  examples: [\"pai worker watch\", \"pai worker ps --all\"],\n  seeAlso: [\"pai worker ps\", \"pai worker follow\"],\n  run: () =>\n    new Promise<number>((resolve, reject) => {\n      const proc = spawn(\"watch\", [\"-n\", \"2\", \"pai worker ps --all\"], { stdio: \"inherit\" });\n      proc.on(\"error\", (e) => reject(new CliError(`cannot run watch: ${e.message}`, \"pai worker ps --all\")));\n      proc.on(\"close\", (code) => resolve(code ?? 1));\n    }),\n};\n\nconst paneCommand: CommandDef = {\n  name: \"pane\",\n  summary: \"Open a window pane that follows a worker\",\n  description:\n    \"Opens the follow pane for a worker: a tmux split when you are in tmux, else an iTerm2 pane on macOS, else it prints the follow command to run yourself.\",\n  args: [{ name: \"ID\", summary: \"Worker id (default: all running workers)\" }],\n  options: [\n    { name: \"check\", type: \"boolean\", summary: \"Only report whether the pane is open, with its profile file, font and window bounds\" },\n    { name: \"close-ended\", type: \"boolean\", summary: \"Close every open pane whose worker has ended\" },\n    { ...OPT.dryRun, summary: \"With --close-ended: only list what would be closed\" },\n  ],\n  examples: [\"pai worker pane\", \"pai worker pane w-20260101-abc --check\", \"pai worker pane --close-ended --dry-run\"],\n  seeAlso: [\"pai worker follow\", \"pai worker ps\"],\n  run: (ctx) =>\n    guard(\"pai worker follow\", async () => {\n      const { workers } = readWorkersSection();\n      const dir = logDir();\n      if (flag(ctx, \"close-ended\")) {\n        const r = await closeEndedPanes(\n          dir,\n          (wid) => {\n            const st = loadStatus(dir, wid);\n            return st !== null && st.state !== \"running\" && st.state !== \"queued\";\n          },\n          ctx.dryRun\n        );\n        for (const l of r.closed) out(`${ctx.dryRun ? \"would close\" : \"closed\"} ${l}`);\n        for (const l of r.kept) out(`kept ${l}`);\n        if (!r.closed.length) out(\"no ended worker panes open\");\n        return;\n      }\n      const host = await resolveHostSession();\n      const term = host.term;\n      process.stderr.write((host.via === \"none\" ? `host session: none (${host.reason})` : `host session: ${host.uid} via ${host.via}`) + \"\\n\");\n      const id = ctx.args.ID as string | undefined;\n      if (id) {\n        out(flag(ctx, \"check\") ? await checkPaneForWorker(id, workers.pane.fontSize, term) : (await openPaneForWorker(dir, workers, id, term)).message);\n      } else {\n        out(await openFollowPane(dir, workers, term, flag(ctx, \"check\")));\n      }\n    }),\n};\n\nconst logCommand: CommandDef = {\n  name: \"log\",\n  summary: \"Worker ledger or the raw events of one worker\",\n  description: \"No argument lists the worker logs. `all` prints the whole ledger, `tail` its last 20 lines, a worker id its last 30 raw events.\",\n  args: [{ name: \"WHAT\", summary: \"all, tail, or a worker id (default: list the logs)\" }],\n  examples: [\"pai worker log\", \"pai worker log tail\", \"pai worker log w-20260101-abc\"],\n  seeAlso: [\"pai worker replay\", \"pai worker errors\"],\n  run: (ctx) =>\n    guard(\"pai worker log   (lists the logs)\", () => {\n      const dir = logDir();\n      const what = ctx.args.WHAT as string | undefined;\n      const ledger = ledgerPath(dir);\n      if (what === \"all\") return void out(existsSync(ledger) ? readFileSync(ledger, \"utf8\") : dim(\"(no ledger yet)\"));\n      if (what === \"tail\") {\n        if (!existsSync(ledger)) return void out(dim(\"(no ledger yet)\"));\n        return void out(readFileSync(ledger, \"utf8\").trim().split(\"\\n\").slice(-20).join(\"\\n\"));\n      }\n      if (what) {\n        const path = eventsPath(dir, what);\n        if (!existsSync(path)) throw new Error(`no event log for ${what}`);\n        return void out(readFileSync(path, \"utf8\").trim().split(\"\\n\").slice(-30).join(\"\\n\"));\n      }\n      if (!existsSync(dir)) return void out(dim(\"(no workers yet)\"));\n      for (const f of readdirSync(dir).filter((x) => x.endsWith(\".jsonl\")).sort()) {\n        const st = statSync(`${dir}/${f}`);\n        out(`  ${f.replace(\".jsonl\", \"\")}  ${(st.size / 1024 / 1024).toFixed(1)} MB  ${st.mtime.toISOString().slice(0, 19).replace(\"T\", \" \")}`);\n      }\n    }),\n};\n\nconst errorsCommand: CommandDef = {\n  name: \"errors\",\n  summary: \"Tool errors workers hit, grouped by kind\",\n  description: \"Counts the errors workers ran into, with numbers and paths removed so equal errors group together.\",\n  options: [{ name: \"since\", type: \"string\", value: \"AGE\", default: \"24h\", summary: \"Only errors newer than this, e.g. 30m, 2h, 1d\" }],\n  examples: [\"pai worker errors\", \"pai worker errors --since 2h\"],\n  seeAlso: [\"pai worker log\"],\n  run: (ctx) =>\n    guard(\"pai worker errors --since 24h\", async () => {\n      const { errorsTable, groupToolErrors, parseSince, readToolErrors } = await import(\"../../workers/tool-errors.js\");\n      const since = str(ctx.opts.since) ?? \"24h\";\n      const ms = parseSince(since);\n      if (ms === null) throw new Error(`bad --since \"${since}\" (use 30m, 2h, 1d)`);\n      out(errorsTable(groupToolErrors(readToolErrors(logDir(), Date.now() - ms))));\n    }),\n};\n\nconst statusLineCommand: CommandDef = {\n  name: \"status-line\",\n  summary: \"One-line worker summary for a status bar\",\n  description:\n    \"Prints nothing when no worker is in scope. Called by the status line script with the terminal session id, the pane's directory and the Claude session id (which claims the workers that session's shell started).\",\n  args: [\n    { name: \"TERM\", summary: \"Terminal session id (default: $ITERM_SESSION_ID)\" },\n    { name: \"CWD\", summary: \"Directory of the pane (default: here)\" },\n    { name: \"SESSION\", summary: \"Claude session id\" },\n  ],\n  examples: [\"pai worker status-line\", \"pai worker status-line \\\"$ITERM_SESSION_ID\\\" \\\"$PWD\\\" ''\"],\n  seeAlso: [\"pai worker ps\"],\n  run: (ctx) =>\n    guard(\"pai worker ps\", () => {\n      const line = statusLineOutput(\n        logDir(),\n        (ctx.args.TERM as string | undefined) ?? process.env.ITERM_SESSION_ID ?? \"\",\n        (ctx.args.CWD as string | undefined) ?? process.cwd(),\n        (ctx.args.SESSION as string | undefined) ?? \"\",\n        new Date()\n      );\n      if (line) out(line);\n    }),\n};\n\n// ---------------------------------------------------------------------------\n// Talking to workers\n// ---------------------------------------------------------------------------\n\nconst sayCommand: CommandDef = {\n  name: \"say\",\n  summary: \"Send a message to a running worker\",\n  description: \"The message goes to the worker's open input, as if you had typed it in its pane. Prints ok.\",\n  args: [\n    { name: \"ID\", required: true, summary: \"Worker id (see `pai worker ps`)\" },\n    { name: \"TEXT\", required: true, summary: \"The message\" },\n  ],\n  options: [{ name: \"goal\", type: \"string\", value: \"TEXT\", summary: \"Record a goal note shown in ps (the label stays) before sending\" }],\n  examples: [\"pai worker say w-20260101-abc 'Also cover the empty case'\", \"pai worker say w-20260101-abc 'Go on' --goal 'finish the export'\"],\n  seeAlso: [\"pai worker goal\", \"pai worker resume\"],\n  run: (ctx) =>\n    guard(\"pai worker ps\", async () => {\n      const dir = logDir();\n      const goal = str(ctx.opts.goal);\n      if (goal !== undefined) setWorkerNote(dir, ctx.args.ID as string, goal);\n      await sayToWorker(dir, ctx.args.ID as string, ctx.args.TEXT as string);\n      out(\"ok\");\n    }),\n};\n\nconst goalCommand: CommandDef = {\n  name: \"goal\",\n  summary: \"Leave a goal note on a running worker\",\n  description: \"Records a note shown under the worker's task in ps; the label is not changed and no message is sent. Prints ok.\",\n  args: [\n    { name: \"ID\", required: true, summary: \"Worker id (see `pai worker ps`)\" },\n    { name: \"TEXT\", required: true, summary: \"The note\" },\n  ],\n  examples: [\"pai worker goal w-20260101-abc 'fix the retry loop'\", \"pai worker goal w-20260101-abc 'review the export tests'\"],\n  seeAlso: [\"pai worker say\", \"pai worker ps\"],\n  run: (ctx) =>\n    guard(\"pai worker ps\", () => {\n      setWorkerNote(logDir(), ctx.args.ID as string, ctx.args.TEXT as string);\n      out(\"ok\");\n    }),\n};\n\nconst handoffCommand: CommandDef = {\n  name: \"handoff\",\n  summary: \"From inside a worker: pass a question or result to its parent\",\n  description:\n    'Adds a message to the parent\\'s inbox and, when the parent is running, says it to the parent. The payload is JSON: {\"kind\":\"proposal|question|blocker\",\"text\":\"...\",\"data\":{...}}. Sender and receiver come from the environment.',\n  args: [{ name: \"JSON\", required: true, summary: \"The payload as JSON\" }],\n  examples: [\n    `pai worker handoff '{\"kind\":\"question\",\"text\":\"Which branch should I target?\"}'`,\n    `pai worker handoff '{\"kind\":\"blocker\",\"text\":\"Tests need a database\",\"data\":{\"table\":\"users\"}}'`,\n  ],\n  seeAlso: [\"pai worker say\"],\n  run: (ctx) =>\n    guard(\"pai worker handoff '{\\\"kind\\\":\\\"question\\\",\\\"text\\\":\\\"...\\\"}'\", async () => {\n      const json = ctx.args.JSON as string;\n      let payload: unknown;\n      try {\n        payload = JSON.parse(json);\n      } catch {\n        throw new Error(`payload is not JSON: ${json}`);\n      }\n      const h = await handoffFromInside(logDir(), process.env, payload);\n      out(`ok → ${h.to} (${h.kind}); inbox ${h.to}.inbox.jsonl`);\n    }),\n};\n\nconst helpCommand: CommandDef = {\n  name: \"help\",\n  summary: \"From inside a worker: ask a stronger model to do one sub-task (budgeted)\",\n  description:\n    \"Runs a bounded sub-worker (class implement, in place, 20 minutes at most) on a stronger provider and prints its report and the files it changed. \" +\n    \"Each orchestrated unit gets a small budget of help calls (default 2, PAI_HELP_BUDGET); past it the verb exits 4 and you report the blocker instead. \" +\n    \"Every call is recorded in help-ledger.jsonl; --report lists them.\",\n  options: [\n    { name: \"task\", type: \"string\", value: \"TEXT\", summary: \"The one-paragraph sub-task\" },\n    { name: \"provider\", type: \"string\", value: \"NAME\", summary: \"Provider to ask (default anthropic)\" },\n    { name: \"model\", type: \"string\", value: \"NAME\", summary: \"Model to ask (default sonnet)\" },\n    { name: \"files\", type: \"string\", value: \"A,B\", summary: \"Files the sub-task concerns, comma-separated\" },\n    { name: \"report\", type: \"boolean\", summary: \"List the recorded help calls instead of asking\" },\n    { name: \"scope\", type: \"string\", value: \"ID\", summary: \"With --report: only this unit\" },\n  ],\n  examples: [\n    \"pai worker help --task 'Rewrite the retry loop in src/net.ts to back off exponentially' --files src/net.ts\",\n    \"pai worker help --report --scope 20261018-0301-1\",\n  ],\n  seeAlso: [\"pai worker handoff\", \"pai worker usage\"],\n  run: (ctx) =>\n    guard(\"pai worker help --task '<sub-task>'\", async () => {\n      if (flag(ctx, \"report\")) {\n        out(renderHelpReport(readHelpLedger(logDir(), str(ctx.opts.scope))));\n        return;\n      }\n      const task = str(ctx.opts.task)?.trim();\n      if (!task) throw new Error(\"--task is required\");\n      const res = await requestHelp(\n        logDir(),\n        {\n          task,\n          provider: str(ctx.opts.provider) ?? \"anthropic\",\n          model: str(ctx.opts.model) ?? \"sonnet\",\n          files: (str(ctx.opts.files) ?? \"\").split(\",\").map((f) => f.trim()).filter(Boolean),\n          cwd: process.cwd(),\n        },\n        { spawnWorker: spawnPaiWorker, changedFiles: gitChangedFiles, now: Date.now }\n      );\n      if (res.refused) throw new CliError(res.message, undefined, HELP_REFUSED_EXIT);\n      out(res.text);\n      return res.ok ? 0 : 1;\n    }),\n};\n\n// ---------------------------------------------------------------------------\n// Taking the work back\n// ---------------------------------------------------------------------------\n\nconst mergeCommand: CommandDef = {\n  name: \"merge\",\n  summary: \"Merge a worker's branch into your checkout\",\n  description:\n    \"Merges branch worker/ID into the original checkout, then removes the worktree and deletes the branch. With --verify (or the workers.yaml `merge.verify` default, which --verify overrides and --no-verify skips) the command runs on the merged tree first; if it exits non-zero the merge is reverted (git revert, never reset), the branch and worktree are kept, and the exit code is 1. A built-in stub scan always runs after the merge: added lines under src/ matching `TODO: implement`, `Promise.resolve(0) // TODO` or `throw new Error(\\\"not implemented` revert the merge the same way.\",\n  args: [{ name: \"ID\", required: true, summary: \"Worker id (see `pai worker pending`)\" }],\n  options: [\n    { name: \"no-commit\", type: \"boolean\", summary: \"Apply the changes uncommitted; keep branch and worktree\" },\n    { name: \"patch\", type: \"boolean\", summary: \"Same as --no-commit\" },\n    { name: \"verify\", type: \"string\", value: \"CMD\", summary: \"Run CMD after the merge; revert the merge when it fails (default: workers.yaml merge.verify)\" },\n    { name: \"no-verify\", type: \"boolean\", summary: \"Skip the configured merge.verify default (prints a warning)\" },\n  ],\n  examples: [\n    \"pai worker merge w-20260101-abc\",\n    \"pai worker merge w-20260101-abc --no-commit\",\n    'pai worker merge 20261018-0301-1 --verify \"npx tsc --noEmit\"',\n  ],\n  seeAlso: [\"pai worker verify\", \"pai worker pending\", \"pai worker discard\"],\n  run: (ctx) =>\n    guard(\"pai worker pending\", () => {\n      let verify = str(ctx.opts.verify);\n      if (verify === undefined) {\n        const configured = readMergeVerify();\n        if (flag(ctx, \"no-verify\")) {\n          if (configured) out(`warning: --no-verify skips the configured merge.verify gate (${configured})`);\n        } else verify = configured;\n      }\n      out(mergeWorker(logDir(), ctx.args.ID as string, { noCommit: flag(ctx, \"no-commit\") || flag(ctx, \"patch\"), verify }));\n    }),\n};\n\nconst verifyCommand: CommandDef = {\n  name: \"verify\",\n  summary: \"Check that a worker's changes are already in your checkout\",\n  description:\n    \"Compares what the worker committed with the working tree (or --against a ref). Exit 0 when every file is identical, so discarding is safe; exit 1 otherwise. Also reads archived workers.\",\n  args: [{ name: \"ID\", required: true, summary: \"Worker id\" }],\n  options: [\n    { name: \"against\", type: \"string\", value: \"REF\", summary: \"Compare against this git ref instead of the working tree\" },\n    { ...OPT.json, summary: \"Print the result as JSON\" },\n  ],\n  examples: [\"pai worker verify w-20260101-abc\", \"pai worker verify w-20260101-abc --against main --json\"],\n  seeAlso: [\"pai worker merge\", \"pai worker discard\"],\n  run: (ctx) =>\n    guard(\"pai worker pending\", () => {\n      const r = verifyWorker(logDir(), ctx.args.ID as string, { against: str(ctx.opts.against) });\n      if (flag(ctx, \"json\")) out(JSON.stringify(r, null, 2));\n      else {\n        for (const f of r.files) out(`${f.state.padEnd(9)} ${f.path}`);\n        out(`${r.ok ? \"all identical\" : \"not applied\"} (${r.files.length} file(s), ${r.ref} vs ${r.against})`);\n      }\n      return r.ok ? 0 : 1;\n    }),\n};\n\nconst pendingCommand: CommandDef = {\n  name: \"pending\",\n  summary: \"Finished workers whose work is not merged yet\",\n  description:\n    \"Lists workers whose branch or worktree holds work that is not in this repository. With --gate it works as a release check: exit 1 with the list unless PAI_ALLOW_PENDING=1.\",\n  options: [\n    { name: \"all\", type: \"boolean\", summary: \"Every repository, not just this one\" },\n    { ...OPT.json, summary: \"Machine-readable output\" },\n    { name: \"gate\", type: \"boolean\", summary: \"Release check: exit 1 with the list unless PAI_ALLOW_PENDING=1\" },\n  ],\n  examples: [\"pai worker pending\", \"pai worker pending --all --json\", \"pai worker pending --gate\"],\n  seeAlso: [\"pai worker merge\", \"pai worker discard\"],\n  run: (ctx) =>\n    guard(\"pai worker ps\", () => {\n      const res = pendingResults(logDir(), flag(ctx, \"all\") ? undefined : process.cwd());\n      if (flag(ctx, \"gate\")) {\n        const g = pendingGate(res);\n        if (g.message) process.stderr.write(g.message + \"\\n\");\n        return g.code;\n      }\n      if (flag(ctx, \"json\")) out(JSON.stringify(res, null, 2));\n      else out(res.length ? formatPending(res, flag(ctx, \"all\")) : \"no pending worker results\");\n    }),\n};\n\nconst discardCommand: CommandDef = {\n  name: \"discard\",\n  summary: \"Throw away a worker's branch and worktree\",\n  description: \"Removes the worktree and branch of a worker and keeps nothing. Use `verify` first if you are unsure.\",\n  args: [{ name: \"ID\", required: true, summary: \"Worker id\" }],\n  examples: [\"pai worker discard w-20260101-abc\", \"pai worker verify w-20260101-abc && pai worker discard w-20260101-abc\"],\n  seeAlso: [\"pai worker verify\", \"pai worker merge\", \"pai worker gc\"],\n  run: (ctx) =>\n    guard(\"pai worker pending\", () => {\n      out(discardWorker(logDir(), ctx.args.ID as string));\n    }),\n};\n\nconst gcCommand: CommandDef = {\n  name: \"gc\",\n  summary: \"Archive leftover worker worktrees\",\n  description: \"Moves old finished workers' worktrees into refs/pai-archive/ID. Before a worktree is removed, gitignored knowledge files (Notes/ and the like; not node_modules, dist, coverage, logs) are copied into the main checkout; a worktree that cannot be salvaged is kept. --dry-run prints what each worktree carries.\",\n  options: [\n    { name: \"older-than\", type: \"string\", value: \"HOURS\", default: \"24\", summary: \"Minimum age of a finished worker, in hours\" },\n    { name: \"all-finished\", type: \"boolean\", summary: \"Any finished worker, regardless of age\" },\n    { ...OPT.dryRun, summary: \"Print what would be archived and what each worktree carries, change nothing\" },\n  ],\n  examples: [\"pai worker gc --dry-run\", \"pai worker gc --older-than 72\", \"pai worker gc --all-finished\"],\n  seeAlso: [\"pai worker discard\", \"pai worker pending\"],\n  run: (ctx) =>\n    guard(\"pai worker gc --dry-run\", () => {\n      const raw = str(ctx.opts[\"older-than\"]) ?? \"24\";\n      const hours = Number(raw);\n      if (!Number.isFinite(hours) || hours < 0) throw new Error(`bad --older-than \"${raw}\"`);\n      const res = gcWorktrees(logDir(), flag(ctx, \"all-finished\") ? 0 : hours, ctx.dryRun, Date.now(), true);\n      const verb = ctx.dryRun ? \"would archive\" : \"archived\";\n      for (const r of res) {\n        out(r.skipped ? `skipped ${r.id}: ${r.skipped}` : `${verb} ${r.id} -> ${r.archive}`);\n        if (r.adopted) out(`  adopted detached HEAD ${r.adopted.slice(0, 7)}`);\n        if (ctx.dryRun && r.knowledge) {\n          const k = formatKnowledge(r.knowledge);\n          for (const l of k.length ? k : [\"carries nothing\"]) out(`  ${l}`);\n        }\n      }\n      const done = res.filter((r) => r.archive);\n      const kept = res.filter((r) => r.skipped);\n      const files = done.reduce((n, r) => n + (r.salvaged?.filter((l) => l.startsWith(\"salvaged \")).length ?? 0), 0);\n      out(\n        `${done.length} ${ctx.dryRun ? \"would be archived\" : \"archived\"}, salvaged ${files} file(s), kept ${kept.length}` +\n          (kept.length ? ` (${kept.map((r) => `${r.id}: ${r.skipped}`).join(\"; \")})` : \"\")\n      );\n    }),\n};\n\nconst killCommand: CommandDef = {\n  name: \"kill\",\n  summary: \"Stop a running worker\",\n  description: \"Stops the worker and every live descendant (the tree `pai worker ps` draws), leaves first: SIGTERM, then SIGKILL if a process outlives it. Each saves its final state. A worker whose process id has been reused by something else is marked lost and nothing is signalled. --only stops just this worker.\",\n  args: [{ name: \"ID\", required: true, summary: \"Worker id (see `pai worker ps`)\" }],\n  options: [{ name: \"only\", type: \"boolean\", summary: \"Kill only this worker, leave its children running\" }],\n  examples: [\"pai worker kill w-20260101-abc\", \"pai worker ps   (find the id first)\"],\n  seeAlso: [\"pai worker ps\"],\n  run: (ctx) =>\n    guard(\"pai worker ps\", async () => {\n      const id = ctx.args.ID as string;\n      const dir = logDir();\n      const status = loadStatus(dir, id);\n      if (!status) throw new Error(`no worker named \"${id}\"`);\n      if (status.state !== \"running\" && status.state !== \"queued\")\n        throw new Error(`worker ${id} is not running (state: ${status.state})`);\n      if (!status.pid || status.pid <= 0) throw new Error(`worker ${id} has no pid recorded`);\n      for (const line of await killTree(dir, id, { only: ctx.opts.only === true })) out(line);\n    }),\n};\n\n// ---------------------------------------------------------------------------\n// Waiting\n// ---------------------------------------------------------------------------\n\nconst waitOnCommand: CommandDef = {\n  name: \"wait-on\",\n  summary: \"Wait for a background job to finish\",\n  description:\n    \"Waits at most --max seconds (default 110, limit 590; over ~110 s needs the Bash tool timeout raised, which the PAI hook does automatically) for a process id. Exit 0: it is gone. Exit 3: still running, call again. Exit 2: it never existed. Exit 4: killed by the ceiling or stall rule (its whole process tree gets SIGTERM, SIGKILL after 5 s; likely a hang or infinite loop). A `pai worker run` target still queued behind its provider cap is not stall-killed (the queue prints a heartbeat at least every 60 s), and the ceiling counts from when it left the queue.\\n\" +\n    \"Recipe: nohup sh -c 'CMD; echo $? > /tmp/job.rc' > /tmp/job.log 2>&1 & echo $! > /tmp/job.pid, then repeat `pai worker wait-on $(cat /tmp/job.pid) --log /tmp/job.log` until it exits 0.\",\n  args: [{ name: \"PID\", required: true, summary: \"Process id of the job\" }],\n  options: [\n    { name: \"log\", type: \"string\", value: \"FILE\", summary: \"Log file whose last lines are printed on return; FILE.rc holds the exit code\" },\n    { name: \"max\", type: \"number\", value: \"SECS\", summary: \"Longest wait in seconds (default 110, limit 590; over ~110 s needs the Bash tool timeout raised, which the PAI hook does automatically)\" },\n    { name: \"tail\", type: \"number\", value: \"N\", summary: \"Log lines printed on return (default 20)\" },\n    { name: \"max-minutes\", type: \"number\", value: \"N\", summary: \"Hard ceiling on the process's age (default 30; a queued worker run counts from leaving the queue): still alive then = kill its process tree, exit 4\" },\n    { name: \"stall-minutes\", type: \"number\", value: \"N\", summary: \"With --log: log silent this long while alive (default 5) = kill its process tree, exit 4\" },\n  ],\n  examples: [\"pai worker wait-on 12345\", \"pai worker wait-on $(cat /tmp/job.pid) --log /tmp/job.log --max 60\"],\n  seeAlso: [\"pai worker wait\", \"pai worker wait-url\", \"pai worker wait-file\"],\n  run: (ctx) =>\n    guard(\"pai worker wait-on <pid>\", async () => {\n      const wid = currentWorkerId(process.env, logDir());\n      const mark = wid ? statusMarker(logDir(), wid) : undefined;\n      // a killed wait-on must not leave a stale waitingOn behind\n      for (const sig of [\"SIGINT\", \"SIGTERM\"] as const) {\n        process.once(sig, () => {\n          mark?.(null);\n          process.exit(128 + (sig === \"SIGINT\" ? 2 : 15));\n        });\n      }\n      return await waitOn(\n        { pid: Number(ctx.args.PID), log: str(ctx.opts.log), maxSecs: num(ctx.opts.max), tail: num(ctx.opts.tail), maxMinutes: num(ctx.opts[\"max-minutes\"]), stallMinutes: num(ctx.opts[\"stall-minutes\"]) },\n        { ...waitOnDeps, mark, queue: statusQueue(logDir()) }\n      );\n    }),\n};\n\nconst waitCommand: CommandDef = {\n  name: \"wait\",\n  summary: \"Wait for child workers; returns when any finishes or --max elapses\",\n  description:\n    \"Prints one JSON status line per worker id and returns within --max seconds (default 100, limit 590; over ~110 s needs the Bash tool timeout raised, which the PAI hook does automatically) as soon as ANY of them finishes. Exit 0: all done. Exit 1: a finished worker failed. Exit 3: some still running, call again with the unfinished ids.\\n\" +\n    \"Use this instead of sleeping and re-checking `pai worker ps`. --timeout keeps the old behaviour: wait for ALL, exit 1 on timeout (the same code as a failed worker; a timed-out worker's JSON has \\\"state\\\":\\\"running\\\", \\\"timedOut\\\":true and no \\\"ok\\\", and stderr says the worker is not affected).\",\n  args: [{ name: \"IDS\", required: true, variadic: true, summary: \"One or more worker ids\" }],\n  options: [\n    { name: \"max\", type: \"number\", value: \"SECS\", summary: \"Longest wait in seconds (default 100, limit 590; over ~110 s needs the Bash tool timeout raised, which the PAI hook does automatically)\" },\n    { name: \"timeout\", type: \"number\", value: \"SECS\", summary: \"Wait for ALL workers, give up after this many seconds (exit 1)\" },\n  ],\n  examples: [\"pai worker wait w-20260101-abc\", \"pai worker wait w-20260101-abc w-20260101-def --max 60\"],\n  seeAlso: [\"pai worker ps\", \"pai worker wait-on\", \"pai worker wait-url\", \"pai worker wait-file\"],\n  run: (ctx) =>\n    guard(\"pai worker ps\", () =>\n      runWait(logDir(), ctx.args.IDS as string[], { max: num(ctx.opts.max), timeout: num(ctx.opts.timeout) }, out, (l) =>\n        process.stderr.write(err(l) + \"\\n\")\n      )\n    ),\n};\n\nconst waitUrlCommand: CommandDef = {\n  name: \"wait-url\",\n  summary: \"Wait for a server to answer HTTP\",\n  description:\n    \"Polls the URL with backoff for at most --max seconds (default 100, limit 590; over ~110 s needs the Bash tool timeout raised, which the PAI hook does automatically). Exit 0: it answered 2xx-4xx. Exit 3: not yet, call again.\",\n  args: [{ name: \"URL\", required: true, summary: \"e.g. http://127.0.0.1:8016/v1/models\" }],\n  options: [{ name: \"max\", type: \"number\", value: \"SECS\", summary: \"Longest wait in seconds (default 100, limit 590; over ~110 s needs the Bash tool timeout raised, which the PAI hook does automatically)\" }],\n  examples: [\"pai worker wait-url http://127.0.0.1:8016/v1/models\", \"pai worker wait-url http://127.0.0.1:8016/v1/models --max 60\"],\n  seeAlso: [\"pai worker wait\", \"pai worker wait-on\", \"pai worker wait-file\"],\n  run: (ctx) => guard(\"pai worker wait-url <url>\", () => waitUrl({ url: String(ctx.args.URL), maxSecs: num(ctx.opts.max) }, { ...realProbeDeps, out })),\n};\n\nconst waitFileCommand: CommandDef = {\n  name: \"wait-file\",\n  summary: \"Wait for files to appear\",\n  description:\n    \"Waits at most --max seconds (default 100, limit 590; over ~110 s needs the Bash tool timeout raised, which the PAI hook does automatically) until every path exists; prints one line per path. Exit 0: all exist. Exit 3: some missing, call again.\",\n  args: [{ name: \"PATHS\", required: true, variadic: true, summary: \"One or more file paths\" }],\n  options: [{ name: \"max\", type: \"number\", value: \"SECS\", summary: \"Longest wait in seconds (default 100, limit 590; over ~110 s needs the Bash tool timeout raised, which the PAI hook does automatically)\" }],\n  examples: [\"pai worker wait-file /tmp/job.rc\", \"pai worker wait-file /tmp/a.rc /tmp/b.rc --max 60\"],\n  seeAlso: [\"pai worker wait\", \"pai worker wait-on\", \"pai worker wait-url\"],\n  run: (ctx) =>\n    guard(\"pai worker wait-file <path...>\", () => waitFile({ paths: ctx.args.PATHS as string[], maxSecs: num(ctx.opts.max) }, { ...realProbeDeps, out })),\n};\n\n// ---------------------------------------------------------------------------\n// Which model, which provider\n// ---------------------------------------------------------------------------\n\nconst modelCommand: CommandDef = {\n  name: \"model\",\n  summary: \"Show or set the model a provider uses\",\n  description:\n    \"No arguments lists the models of every provider.\\n\" +\n    \"`model MODEL-ID` sets the default model of the active provider.\\n\" +\n    \"`model CAPABILITY` shows one capability (default, fast, image, ...); `model CAPABILITY MODEL-ID` sets it.\\n\" +\n    \"`pai worker capability` chooses which provider serves a capability.\",\n  args: [\n    { name: \"WHAT\", summary: \"A capability name, or a model id to set as default\" },\n    { name: \"MODEL\", summary: \"Model id to set for that capability\" },\n  ],\n  options: [\n    { ...OPT.provider, summary: \"Provider to read or change (default: the active one)\" },\n    { name: \"capability\", type: \"string\", value: \"NAME\", summary: \"Capability to show or set, with the model id as the only argument\" },\n  ],\n  examples: [\"pai worker model\", \"pai worker model fast\", \"pai worker model fast glm-fast --provider glm\"],\n  seeAlso: [\"pai worker capability\", \"pai providers\"],\n  run: (ctx) =>\n    guard(\"pai worker model\", () => {\n      const { workers } = readWorkersSection();\n      let what = ctx.args.WHAT as string | undefined;\n      let model = ctx.args.MODEL as string | undefined;\n      const cap = str(ctx.opts.capability);\n      const provider = str(ctx.opts.provider);\n      if (cap !== undefined) {\n        if (!isModelCapability(cap)) throw new WorkersConfigError(`\"${cap}\" is not a valid capability name`);\n        if (model !== undefined) throw new WorkersConfigError(\"with --capability pass only a model id\");\n        model = what;\n        what = cap;\n      }\n      if (what === undefined) {\n        for (const line of describeModels(workers)) out(`  ${line}`);\n        return;\n      }\n      let capability: ModelCapability = \"default\";\n      let id = what;\n      if (isModelCapability(what)) {\n        capability = what;\n        if (model === undefined) {\n          const name = resolveProviderName(workers, provider);\n          const p = getProviderOrNative(workers, name);\n          if (p) out(`  ${name} ${capability} ${p.models[capability] ?? \"(none)\"}`);\n          return;\n        }\n        id = model;\n      } else if (model !== undefined) {\n        throw new WorkersConfigError(`unexpected second argument \"${model}\" — usage: model [<capability>] <model-id>`);\n      }\n      const name = resolveProviderName(workers, provider);\n      const fresh = setProviderModel(name, capability, id);\n      const p = getProviderOrNative(fresh, name);\n      if (p) {\n        out(ok(`${name} ${capability} model: ${p.models[capability]}`));\n        out(dim(`  ${modelPrefsText(p)}`));\n      }\n    }),\n};\n\nconst capabilityCommand: CommandDef = {\n  name: \"capability\",\n  summary: \"Choose which provider serves a capability (e.g. image)\",\n  description:\n    \"No arguments lists every preference and what it resolves to now. `capability NAME PROVIDER[,PROVIDER...]` sets the list (the first usable one wins); `capability NAME --unset` removes it.\\n\" +\n    \"A provider of kind image preferred for \\\"image\\\" is what `pai worker run --capability image` calls.\",\n  args: [\n    { name: \"NAME\", summary: \"Capability name, e.g. image\" },\n    { name: \"PROVIDERS\", summary: \"Provider names, comma-separated, best first\" },\n  ],\n  options: [\n    { name: \"unset\", type: \"boolean\", summary: \"Remove the preference for NAME\" },\n    { ...OPT.json, summary: \"Machine-readable output\" },\n  ],\n  examples: [\"pai worker capability\", \"pai worker capability image imagegen,backup\", \"pai worker capability image --unset\"],\n  seeAlso: [\"pai worker model\", \"pai worker run\"],\n  run: (ctx) =>\n    guard(\"pai worker capability\", () => {\n      const name = ctx.args.NAME as string | undefined;\n      const providers = ctx.args.PROVIDERS as string | undefined;\n      if (name === undefined) {\n        const { workers } = readWorkersSection();\n        const lines = describeCapabilities(workers);\n        if (flag(ctx, \"json\")) out(JSON.stringify(lines));\n        else for (const line of lines) out(`  ${line}`);\n        return;\n      }\n      if (flag(ctx, \"unset\")) {\n        unsetCapabilityPreference(name);\n        out(ok(`removed the capability preference for \"${name}\"`));\n        return;\n      }\n      if (providers === undefined) {\n        throw new Error(`usage: pai worker capability ${name} <provider>[,<provider>…]  (or --unset to remove it)`);\n      }\n      const workers = setCapabilityPreference(name, providers.split(\",\").map((p) => p.trim()));\n      const line = describeCapabilities(workers).find((l) => l.startsWith(`${name}:`));\n      out(ok(`${name}: [${workers.capabilities[name]?.join(\", \")}]`));\n      if (line) out(`  -> ${line.split(\" -> \")[1]}`);\n    }),\n};\n\n// ---------------------------------------------------------------------------\n// The provider capacity queue\n// ---------------------------------------------------------------------------\n\n/** Resolved cap per provider name, for the queue readers. */\nexport function providerCaps(workers: WorkersConfig): Record<string, number | undefined> {\n  const out: Record<string, number | undefined> = {};\n  for (const name of Object.keys(workers.providers)) out[name] = providerCap(workers, name);\n  return out;\n}\n\nconst queueCommand: CommandDef = {\n  name: \"queue\",\n  summary: \"Show or reorder the workers waiting for a provider slot\",\n  description:\n    \"No arguments lists every worker parked behind a provider's concurrency cap, per provider in grant order (the order the capacity gate hands out slots in). \" +\n    \"`queue front ID` moves a waiting worker to position 1, `queue up ID` one place up — pull-forward. Only the order of the waiting ones changes; a running worker is never interrupted. \" +\n    \"The waiting worker itself re-reads the order on its next poll, so a move takes effect within seconds.\",\n  args: [\n    { name: \"VERB\", summary: \"front or up (default: list the queue)\" },\n    { name: \"ID\", summary: \"Worker id to pull forward (with front/up)\" },\n  ],\n  examples: [\"pai worker queue\", \"pai worker queue front 20261019-142851-84910\", \"pai worker queue up 20261019-142851-84910\"],\n  seeAlso: [\"pai worker ps\", \"pai worker kill\"],\n  run: (ctx) =>\n    guard(\"pai worker queue\", async () => {\n      const verb = (ctx.args.VERB as string | undefined) ?? \"list\";\n      const id = ctx.args.ID as string | undefined;\n      const dir = logDir();\n      const { workers } = readWorkersSection();\n      if (verb === \"list\") {\n        const rows = queueRows(dir, providerCaps(workers));\n        if (!rows.length) {\n          out(\"nothing waiting\");\n          return;\n        }\n        let prov = \"\";\n        for (const r of rows) {\n          if (r.provider !== prov) {\n            prov = r.provider;\n            out(`${prov}${r.cap !== undefined ? ` (cap ${r.cap})` : \"\"}:`);\n          }\n          const s = r.status;\n          out(\n            `  ${r.position}. ${r.id}` +\n              (s ? `  ${s.label}  ${s.cwd.split(\"/\").pop() ?? s.cwd}  waited ${ageOf(s.updated)}` : \"\") +\n              `  position ${r.position} of ${r.queued}`\n          );\n        }\n        return;\n      }\n      if (!id) throw new Error(`usage: pai worker queue ${verb} <id>`);\n      const status = loadStatus(dir, id);\n      if (!status) throw new Error(`no worker named \"${id}\"`);\n      if (verb !== \"front\" && verb !== \"up\") throw new Error(`unknown queue verb \"${verb}\" (expected front or up)`);\n      const order = reorderQueue(dir, status.provider, id, verb);\n      out(`${id} is now position ${order.indexOf(id) + 1} of ${order.length} on ${status.provider}`);\n    }),\n};\n\n// ---------------------------------------------------------------------------\n// The group\n// ---------------------------------------------------------------------------\n\nexport const workerCommand: CommandDef = {\n  name: \"worker\",\n  summary: \"Run tasks on other providers: run, ps, follow, merge, ...\",\n  description:\n    \"Workers are Claude Code runs on a provider you chose (cheaper, faster or local) that do one task while you keep working.\\n\" +\n    \"Start one with `run`, watch it with `ps` or `follow`, then bring its work back with `merge`.\",\n  examples: [\"pai worker run --class implement -p 'Fix the retry loop'\", \"pai worker ps\", \"pai worker merge w-20260101-abc\"],\n  seeAlso: [\"pai providers\", \"pai help worker run\"],\n  subcommands: [\n    runCommand,\n    resumeCommand,\n    psCommand,\n    usageCommand,\n    followCommand,\n    replayCommand,\n    watchCommand,\n    paneCommand,\n    logCommand,\n    errorsCommand,\n    statusLineCommand,\n    sayCommand,\n    goalCommand,\n    handoffCommand,\n    helpCommand,\n    mergeCommand,\n    verifyCommand,\n    pendingCommand,\n    discardCommand,\n    gcCommand,\n    killCommand,\n    queueCommand,\n    waitOnCommand,\n    waitUrlCommand,\n    waitFileCommand,\n    waitCommand,\n    modelCommand,\n    capabilityCommand,\n  ],\n};\n","/**\n * fallback.ts — machine-wide Claude Code fallback to a worker provider.\n *\n * When the Anthropic plan runs out, `pai worker fallback on <provider>`\n * points EVERY new Claude Code process on this machine at that provider:\n * interactive sessions, task-bus sessions, the daemon's headless summarizer.\n * It writes the provider's base URL, token (read from its key file at switch\n * time — so the token then sits in settings.json until `off`), the three\n * DEFAULT_*_MODEL pins, its extra env (API_TIMEOUT_MS …) plus tool search on\n * and nonessential traffic off into the `env` block of ~/.claude/settings.json,\n * and pins the top-level `model` to the provider's default model.\n *\n * What settings.json carried before the switch is saved under\n * `workers.fallback.saved` in the PAI config file (CONFIG_FILE); `fallback off`\n * restores it exactly and removes the added keys. Both files are written\n * atomically; nothing else in them is touched. While fallback is on the\n * Agent hook keeps routing subagents to workers, unchanged — those runs set\n * their own env per provider and are unaffected.\n *\n * Running Claude Code processes keep the provider they started with until\n * restarted; `fallback status` lists them and points at the note `on` leaves\n * in the workers log dir (FALLBACK-ACTIVE.md).\n *\n * CLAUDE_SETTINGS_PATH overrides the settings.json location (dry runs against\n * a copy); the config path is injectable for tests the same way.\n */\n\nimport { execFileSync } from \"node:child_process\";\nimport { existsSync, readFileSync, writeFileSync, unlinkSync, mkdirSync } from \"node:fs\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { readJsonStrict, writeJsonAtomic } from \"../config/json-store.js\";\nimport {\n  WorkersConfigError,\n  readWorkersSection,\n  resolveModelCapability,\n  resolveProviderKey,\n  writeWorkersSection,\n  type WorkerProvider,\n  type WorkersFallback,\n} from \"./config.js\";\nimport { resolveTarget } from \"./routing.js\";\nimport { workersLogDir } from \"./paths.js\";\n\n/** settings.json location; CLAUDE_SETTINGS_PATH points it at a copy for dry runs. */\nexport function fallbackSettingsPath(): string {\n  return process.env.CLAUDE_SETTINGS_PATH ?? join(homedir(), \".claude\", \"settings.json\");\n}\n\n/** The note `on` writes so a human landing in the log dir sees the switch. */\nexport function fallbackNotePath(logDir: string): string {\n  return join(logDir, \"FALLBACK-ACTIVE.md\");\n}\n\nexport interface FallbackPaths {\n  /** settings.json to switch (default: fallbackSettingsPath()). */\n  settingsPath?: string;\n  /** pai config.yaml (or config.json) holding the workers section (default: the real one). */\n  configPath?: string;\n}\n\nexport interface FallbackOnResult {\n  provider: string;\n  /** True when fallback was already on for this provider (env re-applied, saved state kept). */\n  alreadyOn: boolean;\n  /** Env keys written into settings.json. */\n  envKeys: string[];\n  /** Model the top-level pin was set to. */\n  model: string;\n}\n\nexport interface FallbackOffResult {\n  provider: string;\n  /** Env keys removed or restored in settings.json. */\n  envKeys: string[];\n}\n\n/**\n * The env block fallback writes: the provider's endpoint and token, model\n * pins (fast model as haiku, default as sonnet and opus — the same mapping\n * buildRunEnv uses), the provider's own env, and the two fallback constants.\n */\nexport function fallbackEnv(provider: WorkerProvider): Record<string, string> {\n  const token = resolveProviderKey(provider) ?? \"local\";\n  return {\n    ANTHROPIC_BASE_URL: provider.baseUrl,\n    ANTHROPIC_AUTH_TOKEN: token,\n    ANTHROPIC_DEFAULT_OPUS_MODEL: provider.models.default,\n    ANTHROPIC_DEFAULT_SONNET_MODEL: provider.models.default,\n    ANTHROPIC_DEFAULT_HAIKU_MODEL: resolveModelCapability(provider, \"fast\"),\n    ...provider.env,\n    ENABLE_TOOL_SEARCH: \"true\",\n    CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC: \"1\",\n  };\n}\n\nfunction assertFallbackCapable(name: string, p: WorkerProvider): void {\n  if (p.protocol === \"openai\") {\n    throw new WorkersConfigError(\n      `provider \"${name}\" speaks the openai protocol and only works through the live PAI proxy — ` +\n        `fallback needs an anthropic-protocol provider every process can reach directly.`\n    );\n  }\n  if (p.engine === \"codex\") {\n    throw new WorkersConfigError(\n      `provider \"${name}\" runs through the Codex CLI — fallback switches Claude Code itself and needs a claude-engine provider.`\n    );\n  }\n  if (!p.baseUrl) {\n    throw new WorkersConfigError(`provider \"${name}\" has no baseUrl — fallback cannot point at it.`);\n  }\n}\n\n/** The env block of a parsed settings.json record, or null when absent. */\nfunction envBlockOf(settings: Record<string, unknown>): Record<string, unknown> | null {\n  return typeof settings.env === \"object\" && settings.env !== null\n    ? (settings.env as Record<string, unknown>)\n    : null;\n}\n\n/** Apply a saved state to a parsed settings.json record (inverse of the switch). */\nfunction restoreSettings(\n  settings: Record<string, unknown>,\n  saved: WorkersFallback[\"saved\"]\n): string[] {\n  const keys = Object.keys(saved.env);\n  if (saved.envExisted) {\n    const env = { ...(typeof settings.env === \"object\" && settings.env !== null ? (settings.env as Record<string, unknown>) : {}) };\n    for (const k of keys) {\n      const v = saved.env[k];\n      if (v === null) delete env[k];\n      else env[k] = v;\n    }\n    settings.env = env;\n  } else {\n    delete settings.env;\n  }\n  if (saved.model === null) delete settings.model;\n  else settings.model = saved.model;\n  return keys;\n}\n\nfunction writeFallbackNote(logDir: string, r: FallbackOnResult): string {\n  const path = fallbackNotePath(logDir);\n  if (!existsSync(logDir)) mkdirSync(logDir, { recursive: true });\n  writeFileSync(\n    path,\n    [\n      `# Fallback active`,\n      ``,\n      `- switched: ${new Date().toISOString().slice(0, 19).replace(\"T\", \" \")} UTC`,\n      `- provider: ${r.provider} — every NEW Claude Code process on this machine runs on it`,\n      `- settings.json: env got ${r.envKeys.join(\", \")}; top-level model pinned to ${r.model}`,\n      `- turn off: pai worker fallback off (restores settings.json exactly)`,\n      ``,\n      `## Running sessions`,\n      ``,\n      `restart this session in its project directory; the new process uses ${r.provider}; keep the same AIBroker name`,\n      ``,\n    ].join(\"\\n\"),\n    \"utf8\"\n  );\n  return path;\n}\n\n/**\n * Switch every new Claude Code process to a worker provider.\n *\n * Write order: the saved state lands in the pai config BEFORE settings.json\n * is touched, so a crash between the two writes leaves `off` able to restore\n * (and `on` re-applies idempotently, healing the gap).\n */\nexport function fallbackOn(providerFlag: string | undefined, paths: FallbackPaths = {}): FallbackOnResult {\n  const settingsPath = paths.settingsPath ?? fallbackSettingsPath();\n  const { raw, workers } = readWorkersSection(paths.configPath);\n  const logDir = workersLogDir(workers);\n  const target = resolveTarget(workers, logDir, { flagProvider: providerFlag });\n  const { providerName, provider } = target;\n  assertFallbackCapable(providerName, provider);\n\n  const env = fallbackEnv(provider);\n  const envKeys = Object.keys(env);\n  const settings = readJsonStrict(settingsPath, settingsPath);\n\n  const prev = workers.fallback;\n  if (prev && prev.provider === providerName) {\n    // Already on for this provider: re-apply (heals a crash between the two\n    // writes) but keep the ORIGINAL saved state and stamp — that is what `off`\n    // must restore to.\n    const eb = envBlockOf(settings);\n    settings.env = { ...(eb ?? {}), ...env };\n    settings.model = provider.models.default;\n    writeJsonAtomic(settingsPath, settings, { label: settingsPath });\n    return { provider: providerName, alreadyOn: true, envKeys, model: provider.models.default };\n  }\n  if (prev) {\n    // Switching providers while on: restore what the first switch saved, then\n    // save fresh from the restored state.\n    restoreSettings(settings, prev.saved);\n  }\n  const envBlock = envBlockOf(settings);\n\n  const saved: WorkersFallback[\"saved\"] = {\n    env: {},\n    model: typeof settings.model === \"string\" ? settings.model : null,\n    envExisted: envBlock !== null,\n  };\n  for (const k of envKeys) {\n    saved.env[k] = envBlock && typeof envBlock[k] === \"string\" ? (envBlock[k] as string) : null;\n  }\n\n  workers.fallback = { provider: providerName, saved, on: new Date().toISOString() };\n  writeWorkersSection(raw, workers, paths.configPath);\n\n  settings.env = { ...(envBlock ?? {}), ...env };\n  settings.model = provider.models.default;\n  writeJsonAtomic(settingsPath, settings, { label: settingsPath });\n\n  const r: FallbackOnResult = { provider: providerName, alreadyOn: false, envKeys, model: provider.models.default };\n  writeFallbackNote(logDir, r);\n  return r;\n}\n\n/** Restore settings.json exactly and clear the switch. Errors when not on. */\nexport function fallbackOff(paths: FallbackPaths = {}): FallbackOffResult {\n  const settingsPath = paths.settingsPath ?? fallbackSettingsPath();\n  const { raw, workers } = readWorkersSection(paths.configPath);\n  const fb = workers.fallback;\n  if (!fb) throw new WorkersConfigError(\"fallback is not on — nothing to restore\");\n\n  const settings = readJsonStrict(settingsPath, settingsPath);\n  const envKeys = restoreSettings(settings, fb.saved);\n  writeJsonAtomic(settingsPath, settings, { label: settingsPath });\n\n  workers.fallback = null;\n  writeWorkersSection(raw, workers, paths.configPath);\n\n  try {\n    const note = fallbackNotePath(workersLogDir(workers));\n    if (existsSync(note)) unlinkSync(note);\n  } catch {\n    /* the note is advisory; its removal must never fail the restore */\n  }\n  return { provider: fb.provider, envKeys };\n}\n\nexport interface FallbackStatus {\n  on: boolean;\n  provider: string | null;\n  /** ISO stamp of the switch, when on. */\n  onAt: string | null;\n  /** FALLBACK-ACTIVE.md path, when on. */\n  notePath: string | null;\n  /** Where the running-session list came from. */\n  sessionsSource: \"aibroker\" | \"ps\";\n  /** One line per running Claude Code process/session. */\n  sessions: string[];\n}\n\n/** Running Claude Code processes: the AIBroker managers registry when it has\n * entries, else `ps`. Informational — sessions keep their provider until\n * restarted whatever this shows. */\nexport function listClaudeSessions(): { source: \"aibroker\" | \"ps\"; lines: string[] } {\n  // AIBroker registry (~/.aibroker/managers.json): manager name → session\n  // record. Best-effort — any parse problem falls through to ps.\n  try {\n    const regPath = join(homedir(), \".aibroker\", \"managers.json\");\n    if (existsSync(regPath)) {\n      const reg = JSON.parse(readFileSync(regPath, \"utf8\")) as Record<string, unknown>;\n      const names = Object.keys(reg);\n      if (names.length) {\n        const lines = names.map((name) => {\n          const rec = typeof reg[name] === \"object\" && reg[name] !== null ? (reg[name] as Record<string, unknown>) : {};\n          const bits = [name];\n          for (const field of [\"session\", \"cwd\", \"pid\"] as const) {\n            const v = rec[field];\n            if (typeof v === \"string\" || typeof v === \"number\") bits.push(`${field} ${v}`);\n          }\n          return bits.join(\"  \");\n        });\n        return { source: \"aibroker\", lines };\n      }\n    }\n  } catch {\n    /* fall through to ps */\n  }\n  try {\n    const out = execFileSync(\"/bin/ps\", [\"-eo\", \"pid=,etime=,command=\"], {\n      encoding: \"utf8\",\n      timeout: 10_000,\n    });\n    // pid, etime, then the command; keep only lines whose command is a\n    // `claude` executable (the `cli.js` shape also matches other daemons)\n    const lines = out\n      .split(\"\\n\")\n      .map((l) => l.trim())\n      .filter(Boolean)\n      .map((l) => {\n        const m = l.match(/^\\d+\\s+\\S+\\s+(.*)$/);\n        return m ? m[1] : \"\";\n      })\n      .filter((cmd) => {\n        const first = cmd.split(/\\s+/)[0] ?? \"\";\n        return first === \"claude\" || first.endsWith(\"/claude\");\n      })\n      .map((cmd) => (cmd.length > 100 ? cmd.slice(0, 97) + \"…\" : cmd))\n      .slice(0, 20);\n    return { source: \"ps\", lines };\n  } catch {\n    return { source: \"ps\", lines: [] };\n  }\n}\n\nexport function fallbackStatus(paths: FallbackPaths = {}): FallbackStatus {\n  const { workers } = readWorkersSection(paths.configPath);\n  const fb = workers.fallback;\n  const sessions = listClaudeSessions();\n  if (!fb) {\n    return {\n      on: false,\n      provider: null,\n      onAt: null,\n      notePath: null,\n      sessionsSource: sessions.source,\n      sessions: sessions.lines,\n    };\n  }\n  const notePath = fallbackNotePath(workersLogDir(workers));\n  return {\n    on: true,\n    provider: fb.provider,\n    onAt: fb.on,\n    notePath,\n    sessionsSource: sessions.source,\n    sessions: sessions.lines,\n  };\n}\n\n/** Human-readable status block for the CLI and the MCP tool. */\nexport function fallbackStatusText(s: FallbackStatus): string[] {\n  const lines: string[] = [];\n  if (!s.on) {\n    lines.push(\"fallback: off — new Claude Code processes run on the Anthropic login\");\n    lines.push(\"turn on with: pai worker fallback on [provider]\");\n  } else {\n    lines.push(`fallback: on — provider ${s.provider} (since ${s.onAt})`);\n    lines.push(\"every NEW Claude Code process runs on it; turn off with: pai worker fallback off\");\n    if (s.notePath) {\n      lines.push(`note: ${s.notePath}${existsSync(s.notePath) ? \"\" : \" (missing)\"}`);\n    }\n  }\n  lines.push(\"\");\n  lines.push(\n    s.sessions.length\n      ? `running Claude Code sessions (${s.sessionsSource}; they keep their current provider until restarted):`\n      : `no running Claude Code sessions detected (${s.sessionsSource})`\n  );\n  lines.push(...(s.sessions.length ? s.sessions.map((l) => `  ${l}`) : []));\n  return lines;\n}\n","/**\n * main-config-ops.ts — the `pai config list/get/set/unset` operations shared\n * by the CLI (src/cli/commands/config.ts) and the MCP tools\n * (src/daemon-mcp/tools/config.ts). One implementation, two thin callers, so\n * a change to masking or validation cannot drift between them.\n */\n\nimport { existsSync } from \"node:fs\";\nimport { Document } from \"yaml\";\nimport {\n  DEFAULTS,\n  loadConfig,\n  paiConfigFilePath,\n  paiConfigYamlFilePath,\n  readMainConfigRaw,\n  writeMainConfigRaw,\n} from \"../daemon/config.js\";\nimport {\n  readWorkersSection,\n  DEFAULT_PANE,\n  DEFAULT_LOG_DIR,\n  DEFAULT_ROUTING,\n  DEFAULT_TREE,\n  DEFAULT_CACHE_KEEPALIVE_SECS,\n  DEFAULT_MAX_MINUTES,\n  maskKey,\n} from \"../workers/config.js\";\nimport { migrateMainConfigToYaml } from \"./main-config.js\";\nimport { writeYamlFileAtomic } from \"./yaml-store.js\";\n\nexport class MainConfigOpsError extends Error {}\n\n// ---------------------------------------------------------------------------\n// Dotted-path helpers\n// ---------------------------------------------------------------------------\n\nexport function splitConfigPath(dotted: string): string[] {\n  const segments = dotted.split(\".\").filter((s) => s.length > 0);\n  if (!segments.length) throw new MainConfigOpsError(\"path is required\");\n  return segments;\n}\n\nfunction getAtPath(root: unknown, segments: string[]): { value: unknown; found: boolean } {\n  let cur: unknown = root;\n  for (const seg of segments) {\n    if (cur !== null && typeof cur === \"object\" && !Array.isArray(cur) && seg in (cur as Record<string, unknown>)) {\n      cur = (cur as Record<string, unknown>)[seg];\n    } else {\n      return { value: undefined, found: false };\n    }\n  }\n  return { value: cur, found: true };\n}\n\nfunction setAtPath(root: Record<string, unknown>, segments: string[], value: unknown): Record<string, unknown> {\n  const clone = structuredClone(root);\n  let cur: Record<string, unknown> = clone;\n  for (let i = 0; i < segments.length - 1; i++) {\n    const seg = segments[i];\n    const next = cur[seg];\n    if (next === null || typeof next !== \"object\" || Array.isArray(next)) cur[seg] = {};\n    cur = cur[seg] as Record<string, unknown>;\n  }\n  cur[segments[segments.length - 1]] = value;\n  return clone;\n}\n\nfunction deleteAtPath(root: Record<string, unknown>, segments: string[]): Record<string, unknown> {\n  const clone = structuredClone(root);\n  let cur: Record<string, unknown> = clone;\n  for (let i = 0; i < segments.length - 1; i++) {\n    const seg = segments[i];\n    const next = cur[seg];\n    if (next === null || typeof next !== \"object\" || Array.isArray(next)) return clone;\n    cur = next as Record<string, unknown>;\n  }\n  delete cur[segments[segments.length - 1]];\n  return clone;\n}\n\n// ---------------------------------------------------------------------------\n// Value parsing (`pai config set <path> <value>`)\n// ---------------------------------------------------------------------------\n\n/** true/false, null, numbers, `[...]`/`{...}` as JSON, else the raw string. */\nexport function parseConfigValueString(raw: string): unknown {\n  if (raw === \"true\") return true;\n  if (raw === \"false\") return false;\n  if (raw === \"null\") return null;\n  if (/^-?\\d+(\\.\\d+)?$/.test(raw)) return Number(raw);\n  const trimmed = raw.trim();\n  if (trimmed.startsWith(\"[\") || trimmed.startsWith(\"{\")) {\n    try {\n      return JSON.parse(trimmed);\n    } catch (e) {\n      throw new MainConfigOpsError(`invalid JSON value: ${e instanceof Error ? e.message : String(e)}`);\n    }\n  }\n  return raw;\n}\n\n// ---------------------------------------------------------------------------\n// Secret masking\n// ---------------------------------------------------------------------------\n\nconst SECRET_SEGMENT_RE = /key|token|secret|password/i;\n\n/** Paths not caught by SECRET_SEGMENT_RE but whose value routinely embeds a\n *  credential (a Postgres URL's userinfo component). */\nconst SPECIAL_SECRET_PATHS = new Set([\"postgres.connectionString\"]);\n\nfunction isSecretPath(segments: (string | number)[]): boolean {\n  if (SPECIAL_SECRET_PATHS.has(segments.filter((s) => typeof s === \"string\").join(\".\"))) return true;\n  return segments.some((s) => typeof s === \"string\" && SECRET_SEGMENT_RE.test(s));\n}\n\n/** Deep-clone `value`, replacing every string leaf on a secret path with\n *  `maskKey`'s `****<last4>` form. Used by every reader (list/get, MCP). */\nexport function maskSecretsDeep(value: unknown, path: (string | number)[] = []): unknown {\n  if (Array.isArray(value)) return value.map((v, i) => maskSecretsDeep(v, [...path, i]));\n  if (value !== null && typeof value === \"object\") {\n    const out: Record<string, unknown> = {};\n    for (const [k, v] of Object.entries(value as Record<string, unknown>)) {\n      out[k] = maskSecretsDeep(v, [...path, k]);\n    }\n    return out;\n  }\n  if (typeof value === \"string\" && value && isSecretPath(path)) return maskKey(value);\n  return value;\n}\n\n// ---------------------------------------------------------------------------\n// Schema (DEFAULTS + the non-provider `workers` shape) for type validation\n// and the effective (defaults-merged) view\n// ---------------------------------------------------------------------------\n\n/** The non-provider `workers` sub-object every writer persists to the main\n *  config (providers/classes/mcp_sets/active live in workers.yaml instead —\n *  see readWorkersSection). Shared by schemaRoot and effectiveConfigRoot. */\nfunction workersMainConfigShape(): Record<string, unknown> {\n  const { workers } = readWorkersSection();\n  return {\n    enabled: workers.enabled,\n    pane: workers.pane,\n    logDir: workers.logDir,\n    routing: workers.routing,\n    tree: workers.tree,\n    cacheKeepaliveSecs: workers.cacheKeepaliveSecs,\n    defaultMaxMinutes: workers.defaultMaxMinutes,\n    noBrowserByDefault: workers.noBrowserByDefault,\n    reaper: workers.reaper,\n    ...(workers.fallback ? { fallback: workers.fallback } : {}),\n  };\n}\n\nfunction schemaRoot(): Record<string, unknown> {\n  return {\n    ...(DEFAULTS as unknown as Record<string, unknown>),\n    workers: {\n      enabled: false,\n      pane: DEFAULT_PANE,\n      logDir: DEFAULT_LOG_DIR,\n      routing: DEFAULT_ROUTING,\n      tree: DEFAULT_TREE,\n      cacheKeepaliveSecs: DEFAULT_CACHE_KEEPALIVE_SECS,\n      defaultMaxMinutes: DEFAULT_MAX_MINUTES,\n      noBrowserByDefault: false,\n      reaper: true,\n    },\n  };\n}\n\n/** loadConfig() (typed, defaults-merged) plus the workers subset — the\n *  \"effective\" view `pai config list --all` / `get` resolve against. */\nfunction effectiveConfigRoot(): Record<string, unknown> {\n  return {\n    ...(loadConfig() as unknown as Record<string, unknown>),\n    workers: workersMainConfigShape(),\n  };\n}\n\n/**\n * Refuse an unset top-level key (typo protection) unless --force, and — when\n * DEFAULTS names a scalar at this exact path — refuse a value of a different\n * JS type unless --force. Nested unknown keys (e.g. under `tasks.providers`)\n * are always allowed: DEFAULTS does not enumerate every provider shape.\n */\nfunction validateAgainstSchema(segments: string[], value: unknown, opts: { force?: boolean }): void {\n  const schema = schemaRoot();\n  const topKey = segments[0];\n  if (!(topKey in schema) && !opts.force) {\n    throw new MainConfigOpsError(\n      `unknown top-level config key \"${topKey}\" (known: ${Object.keys(schema).sort().join(\", \")}) — pass --force to set it anyway`\n    );\n  }\n  const { value: expected, found } = getAtPath(schema, segments);\n  if (found && expected !== null && expected !== undefined) {\n    const expectedType = Array.isArray(expected) ? \"array\" : typeof expected;\n    const actualType = Array.isArray(value) ? \"array\" : typeof value;\n    if (expectedType !== actualType && !opts.force) {\n      throw new MainConfigOpsError(\n        `${segments.join(\".\")}: expected ${expectedType}, got ${actualType} (pass --force to override)`\n      );\n    }\n  }\n}\n\n// ---------------------------------------------------------------------------\n// Public ops\n// ---------------------------------------------------------------------------\n\nexport interface ListConfigResult {\n  /** The section this reflects: file-set values only, or defaults-merged. */\n  scope: \"file\" | \"effective\";\n  yaml: string;\n  data: Record<string, unknown>;\n}\n\n/** `pai config list` / `config_list`. `all=true` shows the defaults-merged\n *  effective config; otherwise only what the file explicitly sets. Secrets\n *  are always masked. */\nexport function listConfigOp(opts: { all?: boolean } = {}): ListConfigResult {\n  const root = opts.all ? effectiveConfigRoot() : readMainConfigRaw();\n  const masked = maskSecretsDeep(root) as Record<string, unknown>;\n  return { scope: opts.all ? \"effective\" : \"file\", yaml: String(new Document(masked)), data: masked };\n}\n\nexport interface GetConfigResult {\n  found: boolean;\n  value: unknown;\n}\n\n/** `pai config get <path>` / `config_get`: resolves against the\n *  defaults-merged effective config (a value not set in the file still\n *  answers with its default), masked if the path looks like a secret. */\nexport function getConfigValueOp(dottedPath: string): GetConfigResult {\n  const segments = splitConfigPath(dottedPath);\n  const { value, found } = getAtPath(effectiveConfigRoot(), segments);\n  return { found, value: found ? maskSecretsDeep(value, segments) : undefined };\n}\n\n/** `pai config get`'s CLI text: a scalar prints as-is, an object/array\n *  subtree prints as YAML (matching `config list`) unless `json` is passed —\n *  the MCP `config_get` tool returns the structured value directly and never\n *  goes through this. */\nexport function formatConfigGetOutput(value: unknown, opts: { json?: boolean } = {}): string {\n  if (opts.json) return JSON.stringify(value, null, 2);\n  if (value !== null && typeof value === \"object\") return String(new Document(value)).trimEnd();\n  return String(value);\n}\n\nexport interface SetConfigResult {\n  yamlCreated: boolean;\n  yamlPath: string;\n  value: unknown;\n}\n\n/**\n * `pai config set <path> <value>` / `config_set`: parses `value`, validates\n * its type against DEFAULTS (refusable with `force`), converts config.json\n * to config.yaml first if neither exists yet, then writes through\n * writeMainConfigRaw (comment-preserving when config.yaml exists).\n */\nexport function setConfigValueOp(dottedPath: string, rawValue: string, opts: { force?: boolean } = {}): SetConfigResult {\n  const segments = splitConfigPath(dottedPath);\n  const value = parseConfigValueString(rawValue);\n  validateAgainstSchema(segments, value, opts);\n\n  const jsonPath = paiConfigFilePath();\n  const yamlPath = paiConfigYamlFilePath();\n  let yamlCreated = false;\n  if (!existsSync(yamlPath)) {\n    if (existsSync(jsonPath)) {\n      migrateMainConfigToYaml(jsonPath, {});\n    } else {\n      writeYamlFileAtomic(yamlPath, \"{}\\n\", { label: yamlPath });\n    }\n    yamlCreated = true;\n  }\n\n  const raw = readMainConfigRaw();\n  writeMainConfigRaw(setAtPath(raw, segments, value));\n  return { yamlCreated, yamlPath, value };\n}\n\nexport interface UnsetConfigResult {\n  existed: boolean;\n}\n\n/** `pai config unset <path>` / `config_unset`: no-ops (existed=false) when\n *  the path was never set explicitly — defaults are never \"unset\". */\nexport function unsetConfigValueOp(dottedPath: string): UnsetConfigResult {\n  const segments = splitConfigPath(dottedPath);\n  const raw = readMainConfigRaw();\n  const { found } = getAtPath(raw, segments);\n  if (!found) return { existed: false };\n  writeMainConfigRaw(deleteAtPath(raw, segments));\n  return { existed: true };\n}\n","/**\n * `pai issue claim|release|claims`: the shared core of the CLI and the MCP\n * tools. Inside a worker (PAI_WORKER_ID) a claim is also recorded in that\n * worker's status, so saveStatus can release it when the worker ends.\n */\nimport { currentWorkerId } from \"../workers/worker-id.js\";\nimport { loadStatus, saveStatus } from \"../workers/status.js\";\nimport { readWorkersSection } from \"../workers/config.js\";\nimport { workersLogDir } from \"../workers/paths.js\";\nimport { listClaims, listStale, loadStatusConfig, setClaim, type ForgeDeps, type StaleDeps } from \"./forge-sink.js\";\n\nexport interface IssueOpts extends ForgeDeps { logDir?: string; workerId?: string }\n\nexport function issueClaim(cwd: string, n: number, add: boolean, o: IssueOpts = {}): { message: string; planned: string[] } {\n  const r = setClaim(cwd, loadStatusConfig(cwd), n, add, o);\n  const wid = o.workerId ?? currentWorkerId(process.env, o.logDir);\n  if (wid && !o.dryRun) {\n    const logDir = o.logDir ?? workersLogDir(readWorkersSection().workers);\n    const st = loadStatus(logDir, wid);\n    if (st) {\n      const rest = (st.claims ?? []).filter((c) => !(c.issue === n && c.repo === r.repo));\n      st.claims = add ? [...rest, { issue: n, repo: r.repo, at: new Date().toISOString() }] : rest;\n      saveStatus(logDir, st);\n    }\n  }\n  return r;\n}\n\nexport function issueClaims(cwd: string, o: IssueOpts = {}) {\n  return listClaims(cwd, loadStatusConfig(cwd), o);\n}\n\nexport function issueStale(cwd: string, days = 7, o: StaleDeps = {}) {\n  return listStale(cwd, loadStatusConfig(cwd), days, o);\n}\n","/**\n * queue.ts — `pai queue`: items, per-project settings, the state file, spec\n * composition, size classification and review rendering. Pure and file-only;\n * workers, git and the clock live in queue-runner.ts / queue-deps.ts.\n */\n\nimport { createHash } from \"node:crypto\";\nimport { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from \"node:fs\";\nimport { basename, dirname, join, resolve } from \"node:path\";\nimport { parse as parseYaml } from \"yaml\";\nimport { paiHomePath } from \"../config/pai-home.js\";\n\nexport type ItemState = \"pending\" | \"running\" | \"ready\" | \"too-big\" | \"needs-decision\" | \"cloud\" | \"accepted\" | \"rejected\";\n\nexport interface DiffInfo {\n  files: number;\n  lines: number;\n  /** `git diff --stat` text of the worker branch. */\n  stat: string;\n}\n\nexport interface QueueItem {\n  id: string;\n  text: string;\n  repo: string;\n  files: string[];\n  image?: string;\n  created: string;\n  state: ItemState;\n  /** `again` rounds so far. */\n  rounds: number;\n  /** Operator notes from `again`, oldest first. */\n  notes: string[];\n  /** Diff of the attempt the latest note is about. */\n  prevDiff?: string;\n  worker?: string;\n  diff?: DiffInfo;\n  gate?: { ok: boolean; output: string };\n  proof?: string;\n  report?: string;\n  why?: string;\n}\n\nexport interface QueueSettings {\n  provider?: string;\n  gate?: string;\n  proof?: string;\n  install?: string;\n  maxFiles: number;\n  maxLines: number;\n  maxParallel?: number;\n  rules?: string;\n}\n\nexport const DEFAULT_MAX_FILES = 6;\nexport const DEFAULT_MAX_LINES = 200;\n\nexport const QUEUE_YAML_SCHEMA = `# <project>/.pai/queue.yaml — all keys optional\nprovider: local        # default: the active local provider\ngate: xcodebuild ...   # run in the worker's worktree before \"ready\", and on accept (default: none)\nproof: ./shot.sh       # prints a path (e.g. a PNG) on its last stdout line, run in the worktree\ninstall: ./install.sh  # run in the checkout after a successful accept\nmax_files: 6           # larger diffs become \"too-big\"\nmax_lines: 200         # added + removed lines\nmax_parallel: 2        # default: the provider's maxConcurrent\nrules: Use tabs.       # extra text appended to every worker spec`;\n\nexport function parseSettings(text: string): QueueSettings {\n  const raw = (text.trim() ? parseYaml(text) : {}) as Record<string, unknown> | null;\n  const o = raw && typeof raw === \"object\" ? raw : {};\n  const str = (k: string): string | undefined => (typeof o[k] === \"string\" && (o[k] as string).trim() ? (o[k] as string).trim() : undefined);\n  const num = (k: string): number | undefined => (typeof o[k] === \"number\" && Number.isFinite(o[k]) && (o[k] as number) > 0 ? Math.floor(o[k] as number) : undefined);\n  return {\n    provider: str(\"provider\"),\n    gate: str(\"gate\"),\n    proof: str(\"proof\"),\n    install: str(\"install\"),\n    maxFiles: num(\"max_files\") ?? DEFAULT_MAX_FILES,\n    maxLines: num(\"max_lines\") ?? DEFAULT_MAX_LINES,\n    maxParallel: num(\"max_parallel\"),\n    rules: str(\"rules\"),\n  };\n}\n\nexport function loadSettings(repo: string): QueueSettings {\n  const p = join(repo, \".pai\", \"queue.yaml\");\n  return parseSettings(existsSync(p) ? readFileSync(p, \"utf8\") : \"\");\n}\n\n/** Per-project state file under the PAI home, never in the repo. */\nexport function queueStatePath(repo: string): string {\n  const abs = resolve(repo);\n  const key = `${basename(abs).replace(/[^A-Za-z0-9._-]/g, \"_\")}-${createHash(\"sha1\").update(abs).digest(\"hex\").slice(0, 8)}`;\n  return paiHomePath(\"queue\", `${key}.json`);\n}\n\ninterface StateFile {\n  next: number;\n  items: QueueItem[];\n}\n\nexport class QueueStore {\n  constructor(\n    readonly path: string,\n    private now: () => number = Date.now,\n  ) {}\n\n  private read(): StateFile {\n    if (!existsSync(this.path)) return { next: 1, items: [] };\n    try {\n      const s = JSON.parse(readFileSync(this.path, \"utf8\")) as StateFile;\n      return { next: s.next ?? s.items.length + 1, items: s.items ?? [] };\n    } catch {\n      return { next: 1, items: [] };\n    }\n  }\n\n  private write(s: StateFile): void {\n    mkdirSync(dirname(this.path), { recursive: true });\n    const tmp = `${this.path}.tmp`;\n    writeFileSync(tmp, JSON.stringify(s, null, 2) + \"\\n\", \"utf8\");\n    renameSync(tmp, this.path);\n  }\n\n  list(): QueueItem[] {\n    return this.read().items;\n  }\n\n  get(id: string): QueueItem | undefined {\n    return this.list().find((i) => i.id === id);\n  }\n\n  add(text: string, repo: string, opts: { files?: string[]; image?: string } = {}): QueueItem {\n    const s = this.read();\n    const item: QueueItem = {\n      id: `q${s.next}`,\n      text: text.trim(),\n      repo,\n      files: opts.files ?? [],\n      ...(opts.image ? { image: opts.image } : {}),\n      created: new Date(this.now()).toISOString(),\n      state: \"pending\",\n      rounds: 0,\n      notes: [],\n    };\n    s.next++;\n    s.items.push(item);\n    this.write(s);\n    return item;\n  }\n\n  /** Apply `patch` to one item; throws on an unknown id. */\n  update(id: string, patch: Partial<QueueItem>): QueueItem {\n    const s = this.read();\n    const i = s.items.findIndex((x) => x.id === id);\n    if (i < 0) throw new Error(`no queue item ${id}`);\n    s.items[i] = { ...s.items[i], ...patch };\n    this.write(s);\n    return s.items[i];\n  }\n}\n\n// ---------------------------------------------------------------------------\n// transitions\n\nconst ALLOWED: Record<ItemState, ItemState[]> = {\n  pending: [\"running\", \"rejected\"],\n  running: [\"ready\", \"too-big\", \"needs-decision\", \"pending\"],\n  ready: [\"accepted\", \"rejected\", \"pending\", \"cloud\"],\n  \"too-big\": [\"rejected\", \"pending\", \"cloud\"],\n  \"needs-decision\": [\"rejected\", \"pending\", \"cloud\"],\n  cloud: [\"running\", \"rejected\"],\n  accepted: [],\n  rejected: [],\n};\n\nexport function canMove(from: ItemState, to: ItemState): boolean {\n  return ALLOWED[from].includes(to);\n}\n\nexport function move(store: QueueStore, id: string, to: ItemState, patch: Partial<QueueItem> = {}): QueueItem {\n  const it = store.get(id);\n  if (!it) throw new Error(`no queue item ${id}`);\n  if (!canMove(it.state, to)) throw new Error(`${id} is ${it.state}; it cannot become ${to}`);\n  return store.update(id, { ...patch, state: to });\n}\n\nexport const MAX_AGAIN_ROUNDS = 2;\n\n/** Re-queue an item with the operator's note; the second round goes to the cloud instead. */\nexport function again(store: QueueStore, id: string, note: string, prevDiff?: string): QueueItem {\n  const it = store.get(id);\n  if (!it) throw new Error(`no queue item ${id}`);\n  const rounds = it.rounds + 1;\n  const to: ItemState = rounds >= MAX_AGAIN_ROUNDS ? \"cloud\" : \"pending\";\n  return move(store, id, to, { rounds, notes: [...it.notes, note.trim()], prevDiff: prevDiff ?? it.prevDiff, why: undefined });\n}\n\n// ---------------------------------------------------------------------------\n// size\n\n/** null when the diff fits the limits, else why it is too big. */\nexport function classifySize(d: Pick<DiffInfo, \"files\" | \"lines\">, s: Pick<QueueSettings, \"maxFiles\" | \"maxLines\">): string | null {\n  const over: string[] = [];\n  if (d.files > s.maxFiles) over.push(`${d.files} files (limit ${s.maxFiles})`);\n  if (d.lines > s.maxLines) over.push(`${d.lines} lines (limit ${s.maxLines})`);\n  return over.length ? `too big: ${over.join(\", \")}` : null;\n}\n\n/** Sum a `git diff --numstat` output; binary files count as one file, no lines. */\nexport function parseNumstat(text: string): Pick<DiffInfo, \"files\" | \"lines\"> {\n  let files = 0;\n  let lines = 0;\n  for (const l of text.split(\"\\n\")) {\n    const m = /^(\\d+|-)\\t(\\d+|-)\\t/.exec(l);\n    if (!m) continue;\n    files++;\n    lines += (m[1] === \"-\" ? 0 : Number(m[1])) + (m[2] === \"-\" ? 0 : Number(m[2]));\n  }\n  return { files, lines };\n}\n\n// ---------------------------------------------------------------------------\n// spec\n\nexport function queueFooter(it: QueueItem, s: QueueSettings): string {\n  return [\n    \"---\",\n    \"Rules for this task:\",\n    \"- Work only with RELATIVE paths inside the current working directory. It is your own git worktree; never use an absolute path to the repository, or you edit the main checkout instead.\",\n    `- Keep the change small: at most ${s.maxFiles} files and ${s.maxLines} changed lines. If the task needs more, stop, change nothing and report why.`,\n    `- ${s.gate ? `Do not run the full test suite; the gate (${s.gate}) is run for you.` : \"Do not run a full test suite.\"}`,\n    `- Git add the files you changed, then commit on the current branch before you report, with the message \"queue ${it.id}: ${it.text.slice(0, 60)}\". An empty commit is not a commit; uncommitted work is lost.`,\n    \"- Report with an R message.\",\n    ...(s.rules ? [\"\", \"Project rules:\", s.rules] : []),\n  ].join(\"\\n\");\n}\n\n/** The worker task: the operator's sentence, files, image, earlier attempt and notes, then the fixed footer. */\nexport function composeQueueSpec(it: QueueItem, s: QueueSettings, failure?: string): string {\n  const lines = [it.text];\n  if (it.files.length) lines.push(\"\", `Files this probably touches: ${it.files.join(\", \")}`);\n  if (it.image) lines.push(\"\", `Reference image (look at it): ${it.image}`);\n  if (s.proof) lines.push(\"\", `Proof: after the change \\`${s.proof}\\` is run and its output shown to the operator.`);\n  if (it.notes.length) {\n    if (it.prevDiff) lines.push(\"\", \"A previous attempt made this change, and the operator says it is still wrong:\", \"```diff\", it.prevDiff.trim(), \"```\");\n    lines.push(\"\", \"Operator notes, oldest first:\", ...it.notes.map((n, i) => `${i + 1}. ${n}`), \"Address the latest note.\");\n  }\n  if (failure) lines.push(\"\", \"The previous attempt failed. Its failure output (tail):\", \"```\", failure.trim(), \"```\", \"Fix the cause and try again.\");\n  lines.push(\"\", queueFooter(it, s));\n  return lines.join(\"\\n\");\n}\n\n// ---------------------------------------------------------------------------\n// rendering\n\nconst oneLine = (t: string, n = 60) => (t.replace(/\\s+/g, \" \").length > n ? t.replace(/\\s+/g, \" \").slice(0, n - 1) + \"…\" : t.replace(/\\s+/g, \" \"));\nconst statShort = (d?: DiffInfo) => (d ? `${d.files}f/${d.lines}l` : \"-\");\n\nexport function renderReview(items: QueueItem[]): string {\n  const ready = items.filter((i) => i.state === \"ready\");\n  if (!ready.length) return \"nothing ready\";\n  return ready\n    .map((i) => `${i.id}  ${oneLine(i.text)}  ${statShort(i.diff)}  gate ${i.gate ? (i.gate.ok ? \"ok\" : \"FAILED\") : \"-\"}  proof ${i.proof ?? \"-\"}`)\n    .join(\"\\n\");\n}\n\nexport function renderList(items: QueueItem[]): string {\n  if (!items.length) return \"queue is empty\";\n  return items.map((i) => `${i.id}  ${i.state.padEnd(14)} ${oneLine(i.text)}${i.why ? `  (${oneLine(i.why, 50)})` : \"\"}`).join(\"\\n\");\n}\n","/**\n * queue-runner.ts — drains the pending items of a queue. One worker branch per\n * item, never merged here: an item ends \"ready\" (diff, gate, proof, report),\n * \"too-big\", or \"needs-decision\" after one local retry. Accept merges.\n * Everything touching workers, git, shells or the clock goes through QueueDeps.\n */\n\nimport { withRunLock, queueLockPath, type LockDeps } from \"./run-lock.js\";\nimport { filesOverlap } from \"./plan.js\";\nimport { tail, type MergeOutcome, type StartRequest, type WorkerOutcome } from \"./plan-runner.js\";\nimport { classifySize, composeQueueSpec, move, type DiffInfo, type QueueItem, type QueueSettings, type QueueStore } from \"./queue.js\";\n\nexport interface QueueDeps {\n  startWorker(req: Pick<StartRequest, \"label\" | \"provider\" | \"tier\" | \"spec\" | \"model\" | \"priority\"> & { attempt: number; itemId: string }): Promise<WorkerOutcome>;\n  /** Size and stat of worker/<id> against the checkout; commits = non-empty commits on it. */\n  inspect(repo: string, workerId: string): Promise<DiffInfo & { commits: number }>;\n  /** Run a shell command (gate, proof, install) in `cwd`. */\n  sh(cmd: string, cwd: string): Promise<{ ok: boolean; output: string }>;\n  merge(repo: string, workerId: string, gate: string): Promise<MergeOutcome>;\n  /** The provider a queue value names: `local` becomes the running local server, any other name is returned unchanged. */\n  resolveLocal(provider: string): Promise<string>;\n  /** Stop the workers this runner has started (SIGTERM/SIGINT path). */\n  stopActive?(): Promise<void>;\n}\n\nexport interface QueueRunOptions {\n  provider: string;\n  parallel: number;\n  /** Take \"cloud\" items and run them on Sonnet instead of the pending ones. */\n  escalate?: boolean;\n  /** Model every local-tier worker of the run gets (default: the provider's). */\n  model?: string;\n  /** \"front\": every worker of the run goes ahead of the provider's waiting runs. */\n  priority?: \"front\";\n  /** Called after an item reached ready or needs-decision (the stored item). */\n  onEvent?: (kind: \"ready\" | \"needs-decision\", item: QueueItem) => void;\n  /** Lock/signal hooks, replaced by tests. */\n  lockDeps?: LockDeps;\n}\n\nexport interface QueueRunSummary {\n  ready: string[];\n  tooBig: string[];\n  needsDecision: string[];\n  spawnRefusal?: string;\n}\n\nconst LOCAL_ATTEMPTS = 2;\n\n/** Last non-empty stdout line of the proof command: the path (or value) it produced. */\nexport const proofValue = (out: string): string => out.trim().split(\"\\n\").pop()?.trim() ?? \"\";\n\nexport function runQueue(store: QueueStore, settings: QueueSettings, opts: QueueRunOptions, deps: QueueDeps): Promise<QueueRunSummary> {\n  const running = new Set<string>();\n  let aborted = false;\n  const guarded: QueueDeps = {\n    ...deps,\n    startWorker: (req) => (aborted ? new Promise<WorkerOutcome>(() => undefined) : deps.startWorker(req).then((o) => (aborted ? new Promise<WorkerOutcome>(() => undefined) : o))),\n  };\n  // interrupted items go back to pending so the next run restarts them\n  const onSignal = async (): Promise<void> => {\n    aborted = true;\n    await deps.stopActive?.();\n    for (const id of running) if (store.get(id)?.state === \"running\") move(store, id, \"pending\");\n  };\n  return withRunLock(queueLockPath(store.path), \"the queue\", () => runQueueLocked(store, settings, opts, guarded, running), { ...opts.lockDeps, onSignal });\n}\n\nasync function runQueueLocked(store: QueueStore, settings: QueueSettings, opts: QueueRunOptions, deps: QueueDeps, active: Set<string>): Promise<QueueRunSummary> {\n  const summary: QueueRunSummary = { ready: [], tooBig: [], needsDecision: [] };\n  const take = opts.escalate ? \"cloud\" : \"pending\";\n  const queue = store.list().filter((i) => i.state === take);\n  const running = new Map<string, { item: QueueItem; done: Promise<void> }>();\n  const refusals = new Map<string, number>();\n  let halted = false;\n\n  const attemptItem = async (item: QueueItem): Promise<void> => {\n    move(store, item.id, \"running\");\n    active.add(item.id);\n    // `local` as the queue's provider means resolveLocalProvider() at run\n    // start — the loopback server that answers, never a provider picked by name.\n    const localName = await deps.resolveLocal(opts.provider);\n    const ladder: Array<{ tier: \"local\" | \"sonnet\"; provider: string }> = opts.escalate\n      ? [{ tier: \"sonnet\", provider: \"anthropic\" }]\n      : Array.from({ length: LOCAL_ATTEMPTS }, () => ({ tier: \"local\" as const, provider: localName }));\n    let failure: string | undefined;\n    for (let i = 0; i < ladder.length; i++) {\n      const { tier, provider } = ladder[i];\n      const out = await deps.startWorker({ itemId: item.id, label: `queue: ${item.id}`, spec: composeQueueSpec(item, settings, failure), provider, tier, attempt: i + 1, ...(tier === \"local\" && opts.model ? { model: opts.model } : {}), ...(opts.priority ? { priority: opts.priority } : {}) });\n      if (!out.ok && out.spawnRefused) {\n        failure = out.failure || \"worker spawn refused\";\n        const n = (refusals.get(failure) ?? 0) + 1;\n        refusals.set(failure, n);\n        if (n >= 2) halted = true;\n        break;\n      }\n      if (!out.ok && out.fatal) {\n        failure = out.failure || \"the worker could not be isolated\";\n        break;\n      }\n      if (!out.ok) {\n        failure = out.failure || \"the worker ended without a valid passing report\";\n        continue;\n      }\n      const d = await deps.inspect(item.repo, out.id);\n      if (!d.commits) {\n        failure = `no-commit: the worker branch has no commit. Git add the files you changed, then commit on the current branch and edit files only by relative path inside your worktree.`;\n        continue;\n      }\n      const diff: DiffInfo = { files: d.files, lines: d.lines, stat: d.stat };\n      const big = classifySize(diff, settings);\n      if (big) {\n        move(store, item.id, \"too-big\", { worker: out.id, diff, why: big, report: out.report });\n        summary.tooBig.push(item.id);\n        return;\n      }\n      let gate: { ok: boolean; output: string } | undefined;\n      if (settings.gate && out.worktreeDir) {\n        gate = await deps.sh(settings.gate, out.worktreeDir);\n        gate = { ok: gate.ok, output: tail(gate.output, 20) };\n        if (!gate.ok) {\n          failure = `gate failed (${settings.gate}):\\n${gate.output}`;\n          continue;\n        }\n      }\n      let proof: string | undefined;\n      if (settings.proof && out.worktreeDir) {\n        const p = await deps.sh(settings.proof, out.worktreeDir);\n        proof = p.ok ? proofValue(p.output) : `proof failed: ${tail(p.output, 3)}`;\n      }\n      move(store, item.id, \"ready\", { worker: out.id, diff, gate, proof, report: out.report, why: undefined });\n      summary.ready.push(item.id);\n      opts.onEvent?.(\"ready\", store.get(item.id) ?? item);\n      return;\n    }\n    move(store, item.id, \"needs-decision\", { why: tail(failure ?? \"\", 10) });\n    summary.needsDecision.push(item.id);\n    opts.onEvent?.(\"needs-decision\", store.get(item.id) ?? item);\n  };\n\n  for (;;) {\n    const busy = [...running.values()].map((r) => r.item);\n    for (const it of halted ? [] : queue) {\n      if (running.size >= opts.parallel) break;\n      if (running.has(it.id) || store.get(it.id)?.state !== take) continue;\n      if (busy.some((b) => it.files.length && b.files.length && filesOverlap(b.files, it.files))) continue;\n      busy.push(it);\n      const done = attemptItem(it).finally(() => {\n        running.delete(it.id);\n        active.delete(it.id);\n      });\n      running.set(it.id, { item: it, done });\n    }\n    if (running.size === 0) break;\n    await Promise.race([...running.values()].map((r) => r.done));\n  }\n  if (halted) summary.spawnRefusal = [...refusals.keys()].pop();\n  return summary;\n}\n\n/** Merge ready items with the gate, then run the install command. A failed merge leaves the item ready. */\nexport async function acceptItems(\n  store: QueueStore,\n  settings: QueueSettings,\n  ids: string[],\n  deps: Pick<QueueDeps, \"merge\" | \"sh\">,\n): Promise<Array<{ id: string; ok: boolean; note: string }>> {\n  const results: Array<{ id: string; ok: boolean; note: string }> = [];\n  for (const id of ids) {\n    const it = store.get(id);\n    if (!it || it.state !== \"ready\" || !it.worker) {\n      results.push({ id, ok: false, note: it ? `${id} is ${it.state}, not ready` : `no queue item ${id}` });\n      continue;\n    }\n    const m = await deps.merge(it.repo, it.worker, settings.gate ?? \"\");\n    if (!m.ok) {\n      const note = tail(m.output, 10);\n      store.update(id, { why: note });\n      results.push({ id, ok: false, note });\n      continue;\n    }\n    move(store, id, \"accepted\", { why: undefined });\n    let note = \"merged\";\n    if (settings.install) {\n      const r = await deps.sh(settings.install, it.repo);\n      note = r.ok ? \"merged, installed\" : `merged, install failed: ${tail(r.output, 5)}`;\n    }\n    results.push({ id, ok: true, note });\n  }\n  return results;\n}\n","/**\n * queue-deps.ts — the real QueueDeps of `pai queue`: workers and merges are the\n * plan runner's launchWorker / mergeBranch; git and shell calls run as children.\n */\n\nimport { mkdtempSync, writeFileSync } from \"node:fs\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { capture, launchWorker, mergeBranch, realCommitsAhead, stopLaunchedWorkers } from \"./plan-deps.js\";\nimport { parseNumstat } from \"./queue.js\";\nimport type { QueueDeps } from \"./queue-runner.js\";\nimport { resolveRunnerProvider } from \"./local-provider.js\";\n\nexport function realQueueDeps(logDir: string, repo: string): QueueDeps {\n  const dir = mkdtempSync(join(tmpdir(), \"pai-queue-\"));\n  const git = async (repo: string, ...a: string[]) => (await capture(\"git\", a, repo)).out;\n  return {\n    async startWorker(req) {\n      const specFile = join(dir, `${req.itemId}-${req.attempt}.txt`);\n      writeFileSync(specFile, req.spec, \"utf8\");\n      return launchWorker(req, specFile, repo, logDir);\n    },\n    async inspect(repo, id) {\n      const base = (await git(repo, \"merge-base\", \"HEAD\", `worker/${id}`)).trim();\n      const range = `${base}..worker/${id}`;\n      const size = parseNumstat(await git(repo, \"diff\", \"--numstat\", range));\n      return { ...size, stat: (await git(repo, \"diff\", \"--stat\", range)).trim(), commits: await realCommitsAhead(repo, base, id) };\n    },\n    async sh(cmd, cwd) {\n      const r = await capture(cmd, [], cwd, true);\n      return { ok: r.code === 0, output: r.out + r.err };\n    },\n    merge: mergeBranch,\n    resolveLocal: resolveRunnerProvider,\n    stopActive: async () => void (await stopLaunchedWorkers(logDir)),\n  };\n}\n\n/** Diff of worker/<id> against the checkout, for an `again` round (capped). */\nexport async function branchDiff(repo: string, id: string, maxLines = 300): Promise<string> {\n  const base = (await capture(\"git\", [\"merge-base\", \"HEAD\", `worker/${id}`], repo)).out.trim();\n  const out = (await capture(\"git\", [\"diff\", `${base}..worker/${id}`], repo)).out;\n  return out.split(\"\\n\").slice(0, maxLines).join(\"\\n\");\n}\n","/**\n * `pai project init` and the project checks of `pai project health`: the\n * shared core of the CLI and the MCP tools project_setup / project_health.\n *\n * init detects what it can (git toplevel, origin kind, existing .pai files) and\n * writes `.pai/project.yaml` and a starter `.pai/worker.md`; it never overwrites\n * (`--force` does, keeping a .bak) and never searches issues for an anchor.\n * Every check prints `ok - <what>` or `missing - <what> - fix: <one command>`.\n */\nimport { execFileSync } from \"node:child_process\";\nimport { copyFileSync, existsSync, mkdirSync, readFileSync, statSync, writeFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { parse } from \"yaml\";\nimport { resolveFromModule } from \"../module-paths.js\";\nimport { PREAMBLE_MAX_BYTES, PREAMBLE_REL, projectRoot } from \"../workers/preamble.js\";\nimport { paneBackend, resolveHostSession, type HostSession } from \"../workers/pane.js\";\nimport {\n  ForgeError, PROJECT_CONFIG_REL, parseStatusConfig, writeContinueToForge,\n  type ForgeDeps, type StatusConfig,\n} from \"./forge-sink.js\";\n\nexport type OriginKind = \"forge\" | \"github\" | \"none\";\n\nexport function originUrl(cwd: string): string | undefined {\n  try {\n    return execFileSync(\"git\", [\"remote\", \"get-url\", \"origin\"], { cwd, encoding: \"utf8\", stdio: [\"ignore\", \"pipe\", \"ignore\"] }).trim() || undefined;\n  } catch { return undefined; }\n}\n\n/** The checks only make sense inside a git checkout. */\nexport function isGitProject(cwd: string): boolean {\n  return existsSync(join(projectRoot(cwd), \".git\"));\n}\n\nexport function originKind(url: string | undefined): OriginKind {\n  if (!url) return \"none\";\n  return /(^|[@/])github\\.com[:/]/i.test(url) ? \"github\" : \"forge\";\n}\n\n/** Generic and cache-stable on purpose: no dates, ids or paths. */\nexport const STARTER_WORKER_MD = `Project rules for every worker started in this repository.\n\n- Read the code a change touches before editing it; reuse existing helpers.\n- Run only the tests of the files you touched; report the counts.\n- Commit on your worker branch with a conventional message; never push or tag.\n- Keep secrets, tokens and personal data out of code, tests and docs.\n`;\n\nexport interface InitOpts { anchor?: number; marker?: string; force?: boolean; dryRun?: boolean }\nexport interface InitResult { root: string; origin: OriginKind; sink: \"forge\" | \"todo\"; written: string[]; kept: string[]; message: string[] }\n\nfunction projectYaml(sink: \"forge\" | \"todo\", anchor?: number, marker?: string): string {\n  const forge = sink === \"forge\" && (anchor || marker)\n    ? `  forge:\\n${anchor ? `    anchor: ${anchor}\\n` : \"\"}${marker ? `    marker: ${JSON.stringify(marker)}\\n` : \"\"}`\n    : \"\";\n  return `status:\\n  sink: ${sink}\\n${forge}`;\n}\n\nexport function initProject(cwd: string, o: InitOpts = {}): InitResult {\n  const root = projectRoot(cwd);\n  const kind = originKind(originUrl(root));\n  const sink = kind === \"forge\" ? \"forge\" : \"todo\";\n  const res: InitResult = { root, origin: kind, sink, written: [], kept: [], message: [] };\n  const yamlPath = join(root, PROJECT_CONFIG_REL);\n  let anchor = o.anchor;\n  let marker = o.marker;\n  if (existsSync(yamlPath) && !o.force) {\n    res.kept.push(PROJECT_CONFIG_REL);\n  } else {\n    if (existsSync(yamlPath)) {\n      // --force keeps what is already there unless given anew\n      try { const old = parseStatusConfig(readFileSync(yamlPath, \"utf8\")); anchor ??= old.anchor; marker ??= old.marker; } catch { /* unreadable: replaced */ }\n    }\n    put(res, root, PROJECT_CONFIG_REL, projectYaml(sink, anchor, marker), o);\n  }\n  if (existsSync(join(root, PREAMBLE_REL)) && !o.force) res.kept.push(PREAMBLE_REL);\n  else put(res, root, PREAMBLE_REL, STARTER_WORKER_MD, o);\n  return res;\n}\n\nfunction put(res: InitResult, root: string, rel: string, text: string, o: InitOpts): void {\n  const path = join(root, rel);\n  const had = existsSync(path);\n  res.message.push(`${o.dryRun ? \"would write\" : \"wrote\"} ${rel}${had ? \" (old copy kept as .bak)\" : \"\"}`);\n  res.written.push(rel);\n  if (o.dryRun) return;\n  mkdirSync(dirname(path), { recursive: true });\n  if (had) copyFileSync(path, `${path}.bak`);\n  writeFileSync(path, text);\n}\n\n// ---------------------------------------------------------------------------\n// Checks\n// ---------------------------------------------------------------------------\n\nexport interface CheckLine { ok: boolean; what: string; fix?: string }\nexport const formatCheck = (c: CheckLine): string => (c.ok ? `ok - ${c.what}` : `missing - ${c.what} - fix: ${c.fix}`);\n\nexport interface CheckDeps extends ForgeDeps {\n  host?: () => Promise<HostSession>;\n  /** Daemon start (ms epoch), null when it does not answer. */\n  daemonStart?: () => Promise<number | null>;\n  /** mtime (ms epoch) of the installed daemon build, null when unknown. */\n  buildTime?: () => number | null;\n  env?: NodeJS.ProcessEnv;\n  platform?: string;\n}\n\nexport async function projectChecks(cwd: string, d: CheckDeps = {}): Promise<CheckLine[]> {\n  const root = projectRoot(cwd);\n  const out: CheckLine[] = [];\n  const yamlPath = join(root, PROJECT_CONFIG_REL);\n  let cfg: StatusConfig | null = null;\n  if (!existsSync(yamlPath)) {\n    out.push({ ok: false, what: `${PROJECT_CONFIG_REL} present`, fix: \"pai project init\" });\n  } else {\n    try {\n      parse(readFileSync(yamlPath, \"utf8\"));\n      cfg = parseStatusConfig(readFileSync(yamlPath, \"utf8\"));\n      out.push({ ok: true, what: `${PROJECT_CONFIG_REL} valid (sink: ${cfg.sink})` });\n    } catch {\n      out.push({ ok: false, what: `${PROJECT_CONFIG_REL} is not valid YAML`, fix: \"pai project init --force\" });\n    }\n  }\n  if (cfg?.sink === \"forge\") {\n    const anchorFix = \"pai project init --force --anchor <issue> --marker <text>\";\n    if (!cfg.anchor || !cfg.marker) {\n      out.push({ ok: false, what: \"forge anchor and marker set\", fix: anchorFix });\n    } else {\n      try {\n        // dry run: GETs only; resolves the token, the anchor, its marker and the handover issue\n        writeContinueToForge(root, cfg, \"\", { ...d, dryRun: true });\n        out.push({ ok: true, what: `forge token present; anchor #${cfg.anchor} reachable, marker matches` });\n      } catch (e) {\n        const m = e instanceof ForgeError ? e.message : String(e);\n        out.push(m === \"no forge token\"\n          ? { ok: false, what: \"forge token present\", fix: \"pai config set forge.token <token>\" }\n          : { ok: false, what: `forge anchor #${cfg.anchor}: ${m}`, fix: anchorFix });\n      }\n    }\n  }\n  const wPath = join(root, PREAMBLE_REL);\n  if (!existsSync(wPath)) out.push({ ok: false, what: `${PREAMBLE_REL} present`, fix: \"pai project init\" });\n  else {\n    const size = statSync(wPath).size;\n    out.push(size > PREAMBLE_MAX_BYTES\n      ? { ok: false, what: `${PREAMBLE_REL} is ${size} bytes, over the ${PREAMBLE_MAX_BYTES} limit`, fix: `$EDITOR ${PREAMBLE_REL}` }\n      : { ok: true, what: `${PREAMBLE_REL} size ok (${size} bytes)` });\n  }\n  const env = d.env ?? process.env;\n  const backend = paneBackend(env, d.platform ?? process.platform, env.ITERM_SESSION_ID);\n  if (backend === \"tmux\") out.push({ ok: true, what: \"worker panes open in tmux\" });\n  else {\n    const h = await (d.host ?? (() => resolveHostSession()))();\n    out.push(h.via === \"none\"\n      ? { ok: false, what: `iTerm host session for worker panes (${h.reason})`, fix: \"pai worker pane --check\" }\n      : { ok: true, what: `iTerm host session ${h.uid} via ${h.via}` });\n  }\n  const started = await (d.daemonStart ?? realDaemonStart)();\n  const built = (d.buildTime ?? realBuildTime)();\n  if (started === null) out.push({ ok: false, what: \"daemon running\", fix: \"pai daemon restart\" });\n  else if (built !== null && started < built) out.push({ ok: false, what: \"daemon started before the installed build\", fix: \"pai daemon restart\" });\n  else out.push({ ok: true, what: \"daemon running on the installed build\" });\n  return out;\n}\n\nasync function realDaemonStart(): Promise<number | null> {\n  try {\n    const [{ PaiClient }, { loadConfig }] = await Promise.all([import(\"../daemon/ipc-client.js\"), import(\"../daemon/config.js\")]);\n    const s = await new PaiClient(loadConfig().socketPath).status();\n    return Date.now() - Number(s.uptime) * 1000;\n  } catch { return null; }\n}\n\nfunction realBuildTime(): number | null {\n  try {\n    // dist/daemon/index.mjs is what `pai daemon restart` launches\n    return statSync(resolveFromModule(import.meta.url, \"dist/daemon/index.mjs\")).mtimeMs;\n  } catch { return null; }\n}\n"],"mappings":"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"}