@rallycry/conveyor-agent 10.0.4 → 10.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/setup/bootstrap.ts","../src/connection/agent-connection.ts","../src/setup/bootstrap-poll.ts","../src/utils/logger.ts","../src/runner/git-utils.ts","../src/runner/plan-sync.ts","../src/harness/pty/settings.ts","../src/setup/git-ready.ts","../src/runner/work-preservation/index.ts","../src/runner/work-preservation/pg-dump.ts","../src/runner/work-preservation/restore-precedence.ts","../src/runner/work-preservation/snapshot-tar.ts","../src/runner/work-preservation/snapshot-artifact.ts","../src/runner/work-preservation/snapshot-transfer.ts","../../shared/dist/index.js","../src/runner/mode-controller.ts","../src/runner/lifecycle.ts","../src/harness/types.ts","../src/harness/claude-code/index.ts","../src/harness/pty/session.ts","../src/harness/pty/event-queue.ts","../src/harness/pty/hook-socket.ts","../src/harness/pty/jsonl-tailer.ts","../src/harness/pty/record-mapper.ts","../src/harness/pty/spawn-args.ts","../src/harness/pty/output-coalescer.ts","../src/harness/pty/tool-server.ts","../src/harness/pty/mcp-server.ts","../src/harness/pty/credentials.ts","../src/harness/pty/index.ts","../src/harness/index.ts","../src/execution/query-executor.ts","../src/execution/pack-runner-prompt.ts","../src/execution/prompt-formatters.ts","../src/execution/tag-context-resolver.ts","../src/execution/prompt-truncation.ts","../src/execution/pm-relaunch-instructions.ts","../src/execution/mode-prompt.ts","../src/execution/system-prompt.ts","../src/execution/prompt-builder.ts","../src/tools/task-context-tools.ts","../src/tools/helpers.ts","../src/tools/dependency-suggestion-tools.ts","../src/tools/mutation-tools.ts","../src/tools/attachment-tools.ts","../src/tools/checklist-tools.ts","../src/tools/common-tools.ts","../src/tools/pm-tools.ts","../src/tools/discovery-tools.ts","../src/tools/code-review-tools.ts","../src/tools/index.ts","../src/execution/event-handlers.ts","../src/execution/event-processor.ts","../src/execution/task-property-utils.ts","../src/execution/tool-access.ts","../src/execution/redactor.ts","../src/execution/exploration-tracker.ts","../src/runner/query-bridge.ts","../src/runner/session-runner-helpers.ts","../src/runner/port-discovery.ts","../src/runner/parent-pull-handler.ts","../src/runner/session-runner.ts","../src/setup/config.ts","../src/setup/commands.ts","../src/setup/codespace.ts"],"sourcesContent":["/**\n * Codespace bootstrap fetch — wraps the `/api/codespace/bootstrap/:name` call\n * with an AbortController timeout, exponential-backoff retries, and structured\n * stderr events the agent-runner-handler can ingest.\n *\n * Used at agent startup (`cli.ts`) and for runtime taskToken refresh when the\n * server signals an auth rejection (`agent-connection.ts`).\n */\n\nexport interface BootstrapConfig {\n mode?: \"task\" | \"project\";\n taskId?: string;\n sessionId?: string;\n taskToken?: string;\n runnerMode?: string;\n agentMode?: string;\n isAuto?: string;\n taskBranch?: string;\n projectId?: string;\n projectToken?: string;\n apiUrl?: string;\n workspaceBranch?: string;\n envVars?: Record<string, string>;\n}\n\nexport interface BootstrapAttemptResult {\n ok: boolean;\n status?: number;\n body?: BootstrapConfig;\n errorText?: string;\n reason?: string;\n}\n\nexport interface BootstrapFailureEvent {\n event: \"bootstrap_failed\";\n reason: string;\n apiUrl: string;\n instanceName: string;\n hasBootstrapToken: boolean;\n hasTaskToken: boolean;\n attempt: number;\n status?: number;\n detail?: string;\n}\n\nconst BOOTSTRAP_TIMEOUT_MS = 30_000;\nconst RETRY_DELAYS_MS = [5_000, 10_000, 20_000];\n\nfunction emitFailureEvent(payload: BootstrapFailureEvent): void {\n process.stderr.write(JSON.stringify(payload) + \"\\n\");\n}\n\nasync function singleBootstrapAttempt(\n apiUrl: string,\n instanceName: string,\n bootstrapToken: string | undefined,\n timeoutMs: number,\n): Promise<BootstrapAttemptResult> {\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n try {\n const headers: Record<string, string> = {};\n if (bootstrapToken) headers[\"x-codespace-token\"] = bootstrapToken;\n const response = await fetch(`${apiUrl}/api/codespace/bootstrap/${instanceName}`, {\n headers,\n signal: controller.signal,\n });\n if (!response.ok) {\n const errorText = await response.text().catch(() => \"\");\n return {\n ok: false,\n status: response.status,\n errorText: errorText.slice(0, 500),\n reason: response.status === 401 || response.status === 403 ? \"auth_rejected\" : \"http_error\",\n };\n }\n const body = (await response.json()) as BootstrapConfig;\n return { ok: true, body };\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n const reason = controller.signal.aborted ? \"timeout\" : \"network_error\";\n return { ok: false, errorText: message.slice(0, 500), reason };\n } finally {\n clearTimeout(timer);\n }\n}\n\nasync function sleep(ms: number): Promise<void> {\n await new Promise<void>((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nexport interface FetchBootstrapOptions {\n apiUrl: string;\n instanceName: string;\n bootstrapToken: string | undefined;\n timeoutMs?: number;\n retryDelaysMs?: number[];\n /** Whether to consider any HTTP error retryable. Network/timeout always retry. */\n retryOnHttpError?: boolean;\n}\n\nexport interface FetchBootstrapSuccess {\n ok: true;\n config: BootstrapConfig;\n attempts: number;\n}\n\nexport interface FetchBootstrapFailure {\n ok: false;\n reason: string;\n status?: number;\n detail?: string;\n attempts: number;\n}\n\nfunction buildFailure(\n reason: string,\n attempts: number,\n status: number | undefined,\n detail: string | undefined,\n): FetchBootstrapFailure {\n const out: FetchBootstrapFailure = { ok: false, reason, attempts };\n if (status === undefined) {\n // no status field\n } else {\n out.status = status;\n }\n if (detail) out.detail = detail;\n return out;\n}\n\nfunction isRetryable(reason: string, retryOnHttpError: boolean | undefined): boolean {\n if (reason === \"timeout\" || reason === \"network_error\") return true;\n return retryOnHttpError === true && reason === \"http_error\";\n}\n\n/**\n * Fetch the bootstrap payload with retries. Network errors and timeouts always\n * trigger a retry; HTTP errors are retried only when `retryOnHttpError` is set\n * (off by default — a 401/403/404 won't recover from retries).\n */\nexport async function fetchBootstrap(\n opts: FetchBootstrapOptions,\n): Promise<FetchBootstrapSuccess | FetchBootstrapFailure> {\n const timeoutMs = opts.timeoutMs ?? BOOTSTRAP_TIMEOUT_MS;\n const delays = opts.retryDelaysMs ?? RETRY_DELAYS_MS;\n const maxAttempts = delays.length + 1;\n const hasBootstrapToken = Boolean(opts.bootstrapToken);\n const hasTaskToken = Boolean(process.env.CONVEYOR_TASK_TOKEN);\n\n let lastReason = \"unknown\";\n let lastStatus: number | undefined;\n let lastDetail: string | undefined;\n\n for (let attempt = 1; attempt <= maxAttempts; attempt++) {\n const result = await singleBootstrapAttempt(\n opts.apiUrl,\n opts.instanceName,\n opts.bootstrapToken,\n timeoutMs,\n );\n if (result.ok && result.body) {\n return { ok: true, config: result.body, attempts: attempt };\n }\n lastReason = result.reason ?? \"unknown\";\n lastStatus = result.status;\n lastDetail = result.errorText;\n\n const failurePayload: BootstrapFailureEvent = {\n event: \"bootstrap_failed\",\n reason: lastReason,\n apiUrl: opts.apiUrl,\n instanceName: opts.instanceName,\n hasBootstrapToken,\n hasTaskToken,\n attempt,\n };\n if (lastStatus === undefined) {\n // no status field\n } else {\n failurePayload.status = lastStatus;\n }\n if (lastDetail) failurePayload.detail = lastDetail;\n emitFailureEvent(failurePayload);\n\n if (!isRetryable(lastReason, opts.retryOnHttpError) || attempt >= maxAttempts) {\n return buildFailure(lastReason, attempt, lastStatus, lastDetail);\n }\n await sleep(delays[attempt - 1]);\n }\n\n return buildFailure(lastReason, maxAttempts, lastStatus, lastDetail);\n}\n\n/** Apply a successful bootstrap config to process.env (mutates env vars). */\nexport function applyBootstrapToEnv(config: BootstrapConfig): void {\n for (const [key, value] of Object.entries(config.envVars ?? {})) {\n process.env[key] = value;\n }\n if (config.mode === \"project\") {\n if (config.projectToken) process.env.CONVEYOR_PROJECT_TOKEN = config.projectToken;\n if (config.projectId) process.env.CONVEYOR_PROJECT_ID = config.projectId;\n if (config.workspaceBranch) process.env.CONVEYOR_WORKSPACE_BRANCH = config.workspaceBranch;\n return;\n }\n if (config.taskId) process.env.CONVEYOR_TASK_ID = config.taskId;\n if (config.sessionId) process.env.CONVEYOR_SESSION_ID = config.sessionId;\n if (config.taskToken) process.env.CONVEYOR_TASK_TOKEN = config.taskToken;\n if (config.agentMode !== undefined) process.env.CONVEYOR_AGENT_MODE = config.agentMode;\n if (config.isAuto !== undefined) process.env.CONVEYOR_IS_AUTO = config.isAuto;\n if (config.runnerMode) process.env.CONVEYOR_MODE = config.runnerMode;\n if (config.taskBranch) process.env.CONVEYOR_TASK_BRANCH = config.taskBranch;\n}\n","/* oxlint-disable max-lines -- service method bindings are flat and cohesive; splitting would scatter closely-coupled call wrappers */\nimport { io, type Socket } from \"socket.io-client\";\nimport type {\n AgentSessionServiceMethods,\n AgentMode,\n AgentQuestion,\n SocketResponse,\n WorkspaceDiscoveredPort,\n} from \"@project/shared\";\nimport { fetchBootstrap, applyBootstrapToEnv } from \"../setup/bootstrap.js\";\nimport { pollUntilBound, PollUntilBoundHttpError } from \"../setup/bootstrap-poll.js\";\n\n// ── Configuration ──────────────────────────────────────────────────────────\n\nexport interface AgentConnectionConfig {\n apiUrl: string;\n taskToken: string;\n sessionId: string;\n runnerMode?: \"task\" | \"pm\" | \"code-review\";\n}\n\n// ── Incoming server-push event types ───────────────────────────────────────\n\nexport interface IncomingMessage {\n content: string;\n userId: string;\n source?: string;\n files?: Array<{ name: string; content: string; mimeType?: string }>;\n /**\n * Delivery hint for the PTY harness: \"prefill\" parks the message in the\n * Connected-TUI input for a human to review/edit/Enter instead of\n * auto-submitting (set by Refine → Discovery/Review). Absent → submit.\n */\n delivery?: \"prefill\";\n}\n\nexport interface SetModeData {\n agentMode: AgentMode;\n}\n\nexport interface ApiKeyUpdateData {\n apiKey: string;\n isSubscription?: boolean;\n}\n\n// ── Connection class ───────────────────────────────────────────────────────\n\nconst EVENT_BATCH_MS = 500;\nconst MAX_EVENT_BUFFER = 5000;\n\n// Task JWTs are minted with a 24h TTL (api: createTaskToken → createJWT(…, \"24h\")).\n// Proactively re-mint from the bootstrap endpoint well inside that window so a\n// long-running or restart-heavy task never reaches the API with an expired\n// token (which surfaces to the agent as \"Session not found\" on its next RPC).\n// 6h — comfortably inside the 24h TTL, with room for a few retries before expiry.\nconst TOKEN_REFRESH_INTERVAL_MS = 6 * 60 * 60 * 1000;\n\nexport class AgentConnection {\n private socket: Socket | null = null;\n private readonly config: AgentConnectionConfig;\n private eventBuffer: Array<{ event: { type: string; [key: string]: unknown } }> = [];\n private flushTimer: ReturnType<typeof setTimeout> | null = null;\n private tokenRefreshTimer: ReturnType<typeof setInterval> | null = null;\n private lastEmittedStatus: string | null = null;\n private lastReportedStatus: string | null = null;\n private droppedEventCount = 0;\n\n // Pending answer resolvers for askUserQuestion room-event fallback\n private pendingAnswerResolvers = new Map<string, (answers: Record<string, string>) => void>();\n\n // Dedup: suppress near-identical messages within a short window\n private recentMessages: Array<{ words: Set<string>; timestamp: number; preview: string }> = [];\n private static readonly DEDUP_WINDOW_MS = 30_000;\n private static readonly DEDUP_SIMILARITY_THRESHOLD = 0.7;\n private static readonly DEDUP_PREVIEW_LIMIT = 120;\n\n // Early-buffering: events that arrive before callbacks are registered\n private earlyMessages: IncomingMessage[] = [];\n private earlyStop = false;\n private earlySoftStop = false;\n private earlyModeChanges: SetModeData[] = [];\n\n // Registered callbacks\n private messageCallback: ((msg: IncomingMessage) => void) | null = null;\n private stopCallback: (() => void) | null = null;\n private softStopCallback: (() => void) | null = null;\n private modeChangeCallback: ((data: SetModeData) => void) | null = null;\n private apiKeyUpdateCallback: ((data: ApiKeyUpdateData) => void) | null = null;\n private pullBranchCallback: ((data: { branch: string }) => void) | null = null;\n private finalizeSnapshotCallback: (() => void) | null = null;\n private earlyPullBranches: Array<{ branch: string }> = [];\n\n // PTY relay (S5 terminal). Single-slot callbacks, set per PtySession run.\n private ptyInputCallback: ((data: string) => void) | null = null;\n private ptyResizeCallback: ((cols: number, rows: number) => void) | null = null;\n\n constructor(config: AgentConnectionConfig) {\n this.config = config;\n }\n\n get sessionId(): string {\n return this.config.sessionId;\n }\n\n get connected(): boolean {\n return this.socket?.connected ?? false;\n }\n\n // ── Typed service method call ──────────────────────────────────────────\n\n // Socket.IO keeps the SAME Socket instance across transport-level\n // reconnects (it only goes null on an explicit disconnect() teardown), so a\n // brief flap leaves `this.socket` non-null but `.connected === false`. Rather\n // than failing a tool call instantly (which the spawned `claude` surfaces as\n // \"Conveyor MCP disconnected\" and an excuse to go idle), we wait out a short\n // reconnect window, then emit with an ack timeout so a buffered packet whose\n // ack never returns can't hang the call forever. We do NOT auto-retry the\n // emit — re-sending a write could double-apply it; the agent prompt instructs\n // the model to retry the tool, which is the safe place to decide idempotency.\n private static readonly CALL_CONNECT_WAIT_MS = 20_000;\n private static readonly CALL_ACK_TIMEOUT_MS = 30_000;\n\n async call<M extends keyof AgentSessionServiceMethods>(\n method: M,\n payload: AgentSessionServiceMethods[M][\"payload\"],\n ): Promise<AgentSessionServiceMethods[M][\"response\"]> {\n const socket = this.socket;\n if (!socket) {\n throw new Error(\n `Not connected (method: ${String(method)}, session: ${this.config.sessionId})`,\n );\n }\n if (!socket.connected) {\n // Mid-reconnect — ride it out instead of failing fast.\n await this.waitForConnected(socket, AgentConnection.CALL_CONNECT_WAIT_MS, String(method));\n }\n return await this.emitWithAck(socket, method, payload);\n }\n\n /** Resolve once `socket` reports connected, or reject after `timeoutMs`. */\n private waitForConnected(socket: Socket, timeoutMs: number, method: string): Promise<void> {\n if (socket.connected) return Promise.resolve();\n return new Promise((resolve, reject) => {\n const cleanup = (): void => {\n clearTimeout(timer);\n socket.off(\"connect\", onConnect);\n };\n const onConnect = (): void => {\n cleanup();\n resolve();\n };\n const timer = setTimeout(() => {\n cleanup();\n reject(\n new Error(\n `Not connected — socket did not reconnect within ${timeoutMs / 1000}s ` +\n `(method: ${method}, session: ${this.config.sessionId}). Transient; retry.`,\n ),\n );\n }, timeoutMs);\n socket.once(\"connect\", onConnect);\n });\n }\n\n /** Emit an RPC and resolve on ack, rejecting if no ack arrives in time. */\n private emitWithAck<M extends keyof AgentSessionServiceMethods>(\n socket: Socket,\n method: M,\n payload: AgentSessionServiceMethods[M][\"payload\"],\n ): Promise<AgentSessionServiceMethods[M][\"response\"]> {\n return new Promise((resolve, reject) => {\n let settled = false;\n const timer = setTimeout(() => {\n if (settled) return;\n settled = true;\n reject(\n new Error(\n `Service call timed out after ${AgentConnection.CALL_ACK_TIMEOUT_MS / 1000}s ` +\n `(method: ${String(method)}, session: ${this.config.sessionId}). ` +\n `Usually a transient reconnect; retry.`,\n ),\n );\n }, AgentConnection.CALL_ACK_TIMEOUT_MS);\n socket.emit(\n `agentSessionService:${String(method)}`,\n payload,\n (response: SocketResponse<AgentSessionServiceMethods[M][\"response\"]>) => {\n if (settled) return;\n settled = true;\n clearTimeout(timer);\n if (response.success && response.data !== undefined) {\n resolve(response.data);\n } else {\n reject(new Error(response.error ?? `Service call failed: ${String(method)}`));\n }\n },\n );\n });\n }\n\n // ── Connection lifecycle ───────────────────────────────────────────────\n\n // oxlint-disable-next-line max-lines-per-function -- socket setup requires registering many co-located event handlers\n connect(): Promise<void> {\n if (!this.config.apiUrl) {\n return Promise.reject(new Error(\"Cannot connect: apiUrl is empty\"));\n }\n this.startProactiveTokenRefresh();\n // oxlint-disable-next-line max-lines-per-function -- socket event registration requires co-located handlers\n return new Promise((resolve, reject) => {\n let settled = false;\n let attempts = 0;\n const maxInitialAttempts = 30;\n\n process.stderr.write(\n `[conveyor-agent] Connecting to ${this.config.apiUrl} (mode: ${this.config.runnerMode ?? \"task\"}, session: ${this.config.sessionId})\\n`,\n );\n\n this.socket = io(this.config.apiUrl, {\n auth: {\n taskToken: this.config.taskToken,\n runnerMode: this.config.runnerMode ?? \"task\",\n },\n transports: [\"websocket\"],\n reconnection: true,\n reconnectionAttempts: Infinity,\n reconnectionDelay: 2000,\n reconnectionDelayMax: 30000,\n randomizationFactor: 0.3,\n extraHeaders: { \"ngrok-skip-browser-warning\": \"true\" },\n });\n\n // ── Server-push event handlers (v7 room-based events) ─────────\n // These events are emitted to the agentSessionService:<sessionId>\n // room. The agent joins this room via the connectAgent() call after\n // the socket connects.\n\n this.socket.on(\"session:message\", (msg: IncomingMessage) => {\n // Preserve source field from server for critical message filtering\n const incoming: IncomingMessage = {\n content: msg.content,\n userId: msg.userId,\n ...(msg.source && { source: msg.source }),\n ...(msg.files && { files: msg.files }),\n ...(msg.delivery === \"prefill\" && { delivery: msg.delivery }),\n };\n if (this.messageCallback) this.messageCallback(incoming);\n else this.earlyMessages.push(incoming);\n });\n\n this.socket.on(\"session:stop\", () => {\n if (this.stopCallback) this.stopCallback();\n else this.earlyStop = true;\n });\n\n this.socket.on(\"session:softStop\", () => {\n if (this.softStopCallback) this.softStopCallback();\n else this.earlySoftStop = true;\n });\n\n this.socket.on(\"session:modeChange\", (data: SetModeData) => {\n if (this.modeChangeCallback) this.modeChangeCallback(data);\n else this.earlyModeChanges.push(data);\n });\n\n this.socket.on(\n \"session:answerQuestion\",\n (data: { requestId: string; answers: Record<string, string> }) => {\n const resolver = this.pendingAnswerResolvers.get(data.requestId);\n if (resolver) resolver(data.answers);\n },\n );\n\n this.socket.on(\"agentRunner:updateApiKey\", (data: ApiKeyUpdateData) => {\n if (this.apiKeyUpdateCallback) this.apiKeyUpdateCallback(data);\n });\n\n this.socket.on(\"session:pullBranch\", (data: { branch: string }) => {\n if (this.pullBranchCallback) this.pullBranchCallback(data);\n else this.earlyPullBranches.push(data);\n });\n\n // The reconciler signals an imminent sleep so the agent captures its\n // finalize snapshot (pg_dump + working tree) NOW — the sleep confirms on\n // this eager capture instead of waiting for the ~2min periodic flush. No\n // early-buffer: if no capture callback is registered yet the pod isn't\n // ready to snapshot, and the shutdown/periodic path is the fallback.\n this.socket.on(\"session:finalizeSnapshot\", () => {\n this.finalizeSnapshotCallback?.();\n });\n\n // PTY relay (S2 → agent): keystrokes and reconciled resizes from the S5\n // terminal. Events are room-scoped so each targets this session; the\n // sessionId guard is defensive. No early-buffer — input/resize are\n // meaningless until a PtySession is live and has registered a callback.\n this.socket.on(\"pty:input\", (data: { sessionId?: string; data: string }) => {\n if (data.sessionId && data.sessionId !== this.config.sessionId) return;\n this.ptyInputCallback?.(data.data);\n });\n\n this.socket.on(\"pty:resize\", (data: { sessionId?: string; cols: number; rows: number }) => {\n if (data.sessionId && data.sessionId !== this.config.sessionId) return;\n this.ptyResizeCallback?.(data.cols, data.rows);\n });\n\n // ── Socket lifecycle events ────────────────────────────────────\n this.socket.on(\"connect\", () => {\n process.stderr.write(\"[conveyor-agent] Socket connected\\n\");\n if (!settled) {\n settled = true;\n resolve();\n }\n });\n\n this.socket.on(\"connect_error\", (err: Error) => {\n attempts++;\n process.stderr.write(\n `[conveyor-agent] Connection error (attempt ${attempts}/${maxInitialAttempts}): ${err.message}\\n`,\n );\n if (!settled && attempts >= maxInitialAttempts) {\n settled = true;\n reject(\n new Error(\n `Failed to connect to ${this.config.apiUrl} after ${maxInitialAttempts} attempts: ${err.message}`,\n ),\n );\n }\n });\n\n this.socket.on(\"disconnect\", (reason: string) => {\n process.stderr.write(`[conveyor-agent] Disconnected: ${reason}\\n`);\n // Server-initiated disconnect (auth rejected, session terminated)\n // arrives with reason \"server namespace disconnect\" or\n // \"io server disconnect\". The token may be stale — try refreshing\n // before Socket.IO's transport-level reconnect kicks in.\n if (reason === \"io server disconnect\" || reason === \"server namespace disconnect\") {\n void this.refreshTaskTokenFromBootstrap()\n .then((refreshed) => {\n if (refreshed && this.socket) {\n // socket.io's `io server disconnect` does NOT auto-reconnect\n // — we have to nudge it manually after refreshing the token.\n this.socket.connect();\n }\n })\n .catch(() => {});\n }\n });\n\n this.socket.on(\"auth:rejected\", () => {\n process.stderr.write(\"[conveyor-agent] Auth rejected by server, refreshing taskToken\\n\");\n void this.refreshTaskTokenFromBootstrap().catch(() => {});\n });\n\n this.socket.io.on(\"reconnect\", () => {\n process.stderr.write(\"[conveyor-agent] Reconnected\\n\");\n // Re-join the session room and process any pending messages from the disconnect window\n void this.reconnectToSession();\n });\n\n this.socket.io.on(\"reconnect_attempt\", () => {\n // Attempt counting is handled in connect_error handler above\n });\n });\n }\n\n disconnect(): void {\n this.stopProactiveTokenRefresh();\n // Best-effort flush on disconnect — don't await\n void this.flushEvents();\n if (this.socket) {\n this.socket.io.reconnection(false);\n this.socket.removeAllListeners();\n this.socket.disconnect();\n this.socket = null;\n }\n }\n\n // ── Reconnect with retry ────────────────────────────────────────────\n //\n // Socket.IO already retries the transport forever. This higher-level helper\n // re-issues the `connectAgent` RPC after a successful reconnect to re-join\n // the session room and drain pending messages. We retry indefinitely with a\n // capped exponential backoff — a stranded codespace with a missing agent is\n // worse than a long-running reconnect loop, and a transient API outage\n // shouldn't kill the agent process.\n\n private static readonly RECONNECT_BASE_DELAY_MS = 2_000;\n private static readonly RECONNECT_MAX_DELAY_MS = 60_000;\n private static readonly RECONNECT_STATUS_EVERY_N = 3;\n\n private isReconnecting = false;\n\n /**\n * Invoked after every successful session reconnect (the `connectAgent` RPC\n * re-established the session room). The runner uses this to force a TUI\n * repaint: the reconnect may have landed on a different/restarted API\n * process whose PTY scrollback ring is empty, and a quiet terminal would\n * otherwise never re-seed it.\n */\n onReconnected?: () => void;\n\n private async reconnectToSession(): Promise<void> {\n if (this.isReconnecting) return;\n this.isReconnecting = true;\n try {\n let attempt = 0;\n while (this.socket) {\n attempt++;\n try {\n const { pendingMessages } = await this.call(\"connectAgent\", {\n sessionId: this.config.sessionId,\n });\n this.drainPendingMessages(pendingMessages);\n process.stderr.write(\n `[conveyor-agent] Reconnected to session successfully (attempts: ${attempt})\\n`,\n );\n // Only re-report status if it actually changed since the last\n // successful report — avoids spamming duplicate status transitions\n // through the system on every reconnect.\n if (this.lastEmittedStatus && this.lastEmittedStatus !== this.lastReportedStatus) {\n const status = this.lastEmittedStatus;\n void this.call(\"reportAgentStatus\", {\n sessionId: this.config.sessionId,\n status,\n })\n .then(() => {\n this.lastReportedStatus = status;\n })\n .catch(() => {});\n }\n // Notify UI subscribers that reconnect succeeded.\n this.sendEvent({\n type: \"agent_runner_status\",\n reason: \"reconnected\",\n attempts: attempt,\n });\n try {\n this.onReconnected?.();\n } catch {\n /* repaint is best-effort — never fail the reconnect over it */\n }\n return;\n } catch (err) {\n const errMsg = err instanceof Error ? err.message : String(err);\n // Capped exponential backoff: 2s, 4s, 8s, 16s, 32s, then 60s steady.\n const delayMs = Math.min(\n AgentConnection.RECONNECT_BASE_DELAY_MS * 2 ** Math.min(attempt - 1, 5),\n AgentConnection.RECONNECT_MAX_DELAY_MS,\n );\n process.stderr.write(\n `[conveyor-agent] connectAgent failed (attempt ${attempt}): ${errMsg} — retrying in ${delayMs / 1000}s\\n`,\n );\n\n // Auth-rejected on the connectAgent RPC — the taskToken may be\n // stale (e.g. after a 24h JWT TTL or a server-side rotation). Try\n // refreshing from the bootstrap endpoint before the next attempt.\n if (this.looksLikeAuthError(errMsg)) {\n void this.refreshTaskTokenFromBootstrap().catch(() => {});\n }\n\n // Every Nth failure, emit a status event so the UI shows we're\n // still trying — piggybacks on the existing `task:agentStatus`\n // pathway via sendEvent (no new socket event needed).\n if (attempt % AgentConnection.RECONNECT_STATUS_EVERY_N === 0) {\n this.sendEvent({\n type: \"agent_runner_status\",\n reason: \"reconnecting\",\n attempt,\n });\n }\n\n await new Promise<void>((resolve) => {\n setTimeout(resolve, delayMs);\n });\n }\n }\n } finally {\n this.isReconnecting = false;\n }\n }\n\n private looksLikeAuthError(message: string): boolean {\n // \"session not found\" / \"session expired\" / \"invalid session\" are the\n // server's wording for an evicted-or-expired task session — the symptom of\n // a stale token. They contain none of unauthor/forbid/auth/token, so match\n // them explicitly, otherwise the refresh-on-reconnect path never fires.\n return /unauthor|forbid|auth|token|session (?:not found|expired|invalid)|invalid session/i.test(\n message,\n );\n }\n\n // ── Proactive task-token refresh ────────────────────────────────────────\n //\n // Socket.IO only re-presents the taskToken on a (re)connect handshake, and\n // the server only re-validates the JWT then. So a token that expires while\n // the socket stays connected goes unnoticed until the next RPC fails. Re-mint\n // periodically from the bootstrap endpoint — refreshFromBootstrap() updates\n // both this.config.taskToken and socket.auth.taskToken, so any later\n // reconnect carries a fresh token. No-ops for project mode / missing\n // codespace env, and is rate-limited to once/60s inside refreshFromBootstrap.\n\n private startProactiveTokenRefresh(): void {\n if (this.tokenRefreshTimer) return;\n this.tokenRefreshTimer = setInterval(() => {\n void this.refreshTaskTokenFromBootstrap().catch(() => {});\n }, TOKEN_REFRESH_INTERVAL_MS);\n // Don't let the refresh timer keep the process alive on its own.\n this.tokenRefreshTimer.unref?.();\n }\n\n private stopProactiveTokenRefresh(): void {\n if (this.tokenRefreshTimer) {\n clearInterval(this.tokenRefreshTimer);\n this.tokenRefreshTimer = null;\n }\n }\n\n private drainPendingMessages(messages: Array<{ content: string; userId: string }>): void {\n for (const msg of messages) {\n if (!msg.content) continue;\n if (this.messageCallback) {\n this.messageCallback({ content: msg.content, userId: msg.userId });\n } else {\n this.earlyMessages.push({ content: msg.content, userId: msg.userId });\n }\n }\n }\n\n // ── Callback registration with early-buffer draining ───────────────\n\n onMessage(callback: (msg: IncomingMessage) => void): void {\n this.messageCallback = callback;\n for (const msg of this.earlyMessages) callback(msg);\n this.earlyMessages = [];\n }\n\n onStop(callback: () => void): void {\n this.stopCallback = callback;\n if (this.earlyStop) {\n callback();\n this.earlyStop = false;\n }\n }\n\n onSoftStop(callback: () => void): void {\n this.softStopCallback = callback;\n if (this.earlySoftStop) {\n callback();\n this.earlySoftStop = false;\n }\n }\n\n onModeChange(callback: (data: SetModeData) => void): void {\n this.modeChangeCallback = callback;\n for (const data of this.earlyModeChanges) callback(data);\n this.earlyModeChanges = [];\n }\n\n onApiKeyUpdate(callback: (data: ApiKeyUpdateData) => void): void {\n this.apiKeyUpdateCallback = callback;\n }\n\n onPullBranch(callback: (data: { branch: string }) => void): void {\n this.pullBranchCallback = callback;\n for (const data of this.earlyPullBranches) callback(data);\n this.earlyPullBranches = [];\n }\n\n onFinalizeSnapshot(callback: () => void): void {\n this.finalizeSnapshotCallback = callback;\n }\n\n // ── PTY relay (S5 Connected-TUI terminal) ──────────────────────────\n\n /**\n * Forward a raw chunk of terminal output to the S2 relay (fire-and-forget).\n * The first chunk creates the server-side scrollback ring, which is what\n * surfaces the terminal in the UI. `dims` seed/refresh the ring geometry.\n */\n sendPtyOutput(data: string, dims?: { cols: number; rows: number }): void {\n if (!this.socket) return;\n void this.call(\"ptyOutput\", {\n sessionId: this.config.sessionId,\n data,\n ...(dims ? { cols: dims.cols, rows: dims.rows } : {}),\n }).catch(() => {});\n }\n\n /** Subscribe to relayed keystrokes. Returns an unsubscribe fn. */\n onPtyInput(handler: (data: string) => void): () => void {\n this.ptyInputCallback = handler;\n return () => {\n if (this.ptyInputCallback === handler) this.ptyInputCallback = null;\n };\n }\n\n /** Subscribe to relayed (reconciled) terminal resizes. Returns an unsubscribe fn. */\n onPtyResize(handler: (cols: number, rows: number) => void): () => void {\n this.ptyResizeCallback = handler;\n return () => {\n if (this.ptyResizeCallback === handler) this.ptyResizeCallback = null;\n };\n }\n\n // ── Convenience methods (thin wrappers around call / emit) ─────────\n\n async emitStatus(status: string, reason?: string): Promise<void> {\n this.lastEmittedStatus = status;\n // Await event flush (e.g. \"completed\") before reporting status change\n // so the API processes \"completed\" before \"idle\" — eliminates the\n // ordering race that caused duplicate completion message spam.\n await this.flushEvents();\n const payload = {\n sessionId: this.config.sessionId,\n status,\n ...(reason ? { reason } : {}),\n };\n const AWAIT_STATUSES = [\"idle\", \"waiting_for_input\", \"connected\"];\n if (AWAIT_STATUSES.includes(status)) {\n // Critical transition — server must process before agent blocks on waitForMessage()\n try {\n await this.call(\"reportAgentStatus\", payload);\n this.lastReportedStatus = status;\n } catch {\n // Best-effort — proceed even if status report fails.\n // Server-side forwardOrQueue has a DB cross-check fallback.\n }\n } else {\n void this.call(\"reportAgentStatus\", payload)\n .then(() => {\n this.lastReportedStatus = status;\n })\n .catch(() => {});\n }\n }\n\n postChatMessage(content: string): void {\n if (!this.socket) return;\n if (this.suppressIfDuplicate(content)) return;\n void this.call(\"postAgentMessage\", {\n sessionId: this.config.sessionId,\n content,\n }).catch(() => {});\n }\n\n // Awaitable variant of postChatMessage for callers that need to guarantee\n // the message is acknowledged by the server before proceeding (e.g. before\n // aborting the session). Dedup still applies; a suppressed message resolves\n // immediately without hitting the wire.\n async postChatMessageAwait(content: string): Promise<void> {\n if (!this.socket) return;\n if (this.suppressIfDuplicate(content)) return;\n try {\n await this.call(\"postAgentMessage\", {\n sessionId: this.config.sessionId,\n content,\n });\n } catch (err) {\n process.stderr.write(\n `[conveyor-agent] postChatMessageAwait failed: ${err instanceof Error ? err.message : String(err)}\\n`,\n );\n }\n }\n\n private suppressIfDuplicate(content: string): boolean {\n const d = this.checkAndTrackDuplicate(content);\n if (!d.duplicate) return false;\n process.stderr.write(\n `[dedup] Suppressed near-duplicate (matched: \"${d.matchedMessagePreview}\")\\n`,\n );\n return true;\n }\n\n // Exposed so `post_to_chat` can surface suppression back to the agent.\n checkAndTrackDuplicate(\n content: string,\n ): { duplicate: false } | { duplicate: true; matchedMessagePreview: string } {\n const now = Date.now();\n this.recentMessages = this.recentMessages.filter(\n (m) => now - m.timestamp < AgentConnection.DEDUP_WINDOW_MS,\n );\n const words = new Set(\n content\n .toLowerCase()\n .replace(/[^\\w\\s]/g, \"\")\n .split(/\\s+/)\n .filter((w) => w.length >= 3),\n );\n if (words.size === 0) return { duplicate: false };\n for (const recent of this.recentMessages) {\n let intersection = 0;\n for (const w of words) if (recent.words.has(w)) intersection++;\n const union = new Set([...words, ...recent.words]).size;\n if (union > 0 && intersection / union > AgentConnection.DEDUP_SIMILARITY_THRESHOLD) {\n return { duplicate: true, matchedMessagePreview: recent.preview };\n }\n }\n const max = AgentConnection.DEDUP_PREVIEW_LIMIT;\n const preview = content.length > max ? content.slice(0, max) + \"…\" : content;\n this.recentMessages.push({ words, timestamp: now, preview });\n if (this.recentMessages.length > 3) this.recentMessages.shift();\n return { duplicate: false };\n }\n\n sendHeartbeat(): void {\n if (!this.socket) return;\n const statusMap: Record<string, \"active\" | \"idle\" | \"building\"> = {\n running: \"active\",\n fetching_context: \"active\",\n connected: \"active\",\n connecting: \"active\",\n idle: \"idle\",\n };\n const heartbeatStatus = statusMap[this.lastEmittedStatus ?? \"idle\"] ?? \"active\";\n void this.call(\"heartbeat\", {\n sessionId: this.config.sessionId,\n timestamp: new Date().toISOString(),\n status: heartbeatStatus,\n }).catch(() => {});\n }\n\n emitModeChanged(agentMode?: AgentMode | null): void {\n this.sendEvent({ type: \"mode_changed\", agentMode });\n }\n\n async updateTaskFields(fields: {\n plan?: string;\n description?: string;\n }): Promise<{ ok: boolean; error?: string }> {\n if (!this.socket) return { ok: false, error: \"socket not connected\" };\n try {\n await this.call(\"updateTaskFields\", { sessionId: this.config.sessionId, ...fields });\n return { ok: true };\n } catch (err) {\n return { ok: false, error: err instanceof Error ? err.message : String(err) };\n }\n }\n\n storeSessionId(sdkSessionId: string): void {\n void this.call(\"storeSessionId\", { sessionId: this.config.sessionId, sdkSessionId }).catch(\n () => {},\n );\n }\n\n /** Report the full current set of runtime-discovered listening ports.\n * Throws on failure so the PortDiscovery poller can retry on its next\n * tick (a swallowed error here would silently drop the delta). */\n async reportDiscoveredPorts(ports: WorkspaceDiscoveredPort[]): Promise<void> {\n await this.call(\"reportDiscoveredPorts\", { sessionId: this.config.sessionId, ports });\n }\n\n // ── Typing indicators ───────────────────────────────────────────────\n\n sendTypingStart(): void {\n this.sendEvent({ type: \"agent_typing_start\" });\n }\n\n sendTypingStop(): void {\n this.sendEvent({ type: \"agent_typing_stop\" });\n }\n\n // ── RPC convenience wrappers (v6 compat, will migrate to call()) ───\n\n emitRateLimitPause(resetsAt: string): void {\n this.sendEvent({ type: \"rate_limit_update\", resetsAt });\n }\n\n updateStatus(status: string): void {\n this.emitStatus(status);\n }\n\n emitCodeReviewResult(content: string, approved: boolean): void {\n if (!this.socket) return;\n void this.call(\"submitCodeReviewResult\", {\n sessionId: this.config.sessionId,\n content,\n approved,\n }).catch(() => {});\n }\n\n // ── Question handling ──────────────────────────────────────────────\n\n async askUserQuestion(questions: AgentQuestion[]): Promise<Record<string, string>> {\n const questionText = questions\n .map(\n (q) =>\n `**${q.header}**\\n${q.question}${q.options.length ? \"\\n\" + q.options.map((o) => `- ${o.label}: ${o.description}`).join(\"\\n\") : \"\"}`,\n )\n .join(\"\\n\\n\");\n\n const requestId = crypto.randomUUID();\n\n // Race the RPC callback against the room-event fallback.\n // If the socket disconnects/reconnects while waiting, the RPC callback is\n // lost but the room event (emitted after reconnect to the session room)\n // will still deliver the answer.\n const roomEventPromise = new Promise<Record<string, string>>((resolve) => {\n this.pendingAnswerResolvers.set(requestId, resolve);\n });\n\n const rpcPromise = this.call(\"askUserQuestion\", {\n sessionId: this.config.sessionId,\n question: questionText,\n requestId,\n questions,\n }).then((res) => res.answers);\n\n try {\n return await Promise.race([rpcPromise, roomEventPromise]);\n } finally {\n this.pendingAnswerResolvers.delete(requestId);\n }\n }\n\n // ── Typed service method wrappers ───────────────────────────────────\n\n getTaskProperties(): Promise<{\n plan?: string;\n storyPointId?: string;\n title?: string;\n }> {\n return this.call(\"getTaskProperties\", { sessionId: this.config.sessionId });\n }\n\n triggerIdentification(): Promise<{ identified: boolean }> {\n return this.call(\"triggerIdentification\", { sessionId: this.config.sessionId });\n }\n\n async refreshAuthToken(): Promise<boolean> {\n const result = await this.refreshFromBootstrap();\n return result.refreshedClaude;\n }\n\n /**\n * Refresh the in-process `CONVEYOR_TASK_TOKEN` from the bootstrap endpoint.\n * Returns true if a new token was applied. Rate-limited locally to once per\n * 60s so a tight auth-rejected loop can't hammer the bootstrap endpoint —\n * the server enforces the same window via `lastBootstrapAt`.\n */\n private lastTaskTokenRefreshAt = 0;\n async refreshTaskTokenFromBootstrap(): Promise<boolean> {\n const result = await this.refreshFromBootstrap();\n return result.refreshedTaskToken;\n }\n\n private refreshFromBootstrap(): Promise<{\n refreshedClaude: boolean;\n refreshedTaskToken: boolean;\n }> {\n const none = Promise.resolve({ refreshedClaude: false, refreshedTaskToken: false });\n // Claudespace pods carry POD_BOOTSTRAP_TOKEN (retained by the entrypoint as\n // the credential-refresh key); the legacy GitHub Codespaces path keys on\n // instance name + CONVEYOR_BOOTSTRAP_TOKEN.\n const podBootstrapToken = process.env.POD_BOOTSTRAP_TOKEN;\n const codespaceName = process.env.CODESPACE_NAME || process.env.CLAUDESPACE_NAME;\n const apiUrl = this.config.apiUrl;\n if (!apiUrl || (!podBootstrapToken && !codespaceName)) {\n return none;\n }\n const now = Date.now();\n if (now - this.lastTaskTokenRefreshAt < 60_000) {\n return none;\n }\n this.lastTaskTokenRefreshAt = now;\n if (podBootstrapToken) {\n return this.refreshFromV3Bootstrap(apiUrl, podBootstrapToken);\n }\n if (!codespaceName) return none;\n return this.refreshFromCodespaceBootstrap(apiUrl, codespaceName);\n }\n\n /** Legacy GitHub Codespaces refresh path — keys on instance name. */\n private async refreshFromCodespaceBootstrap(\n apiUrl: string,\n codespaceName: string,\n ): Promise<{ refreshedClaude: boolean; refreshedTaskToken: boolean }> {\n const bootstrapToken = process.env.CONVEYOR_BOOTSTRAP_TOKEN;\n const result = await fetchBootstrap({\n apiUrl,\n instanceName: codespaceName,\n bootstrapToken,\n // Do not retry on http errors during a runtime refresh — a 401/403\n // means the token is consumed / session terminal and retrying won't\n // help. Network/timeout still retry inside fetchBootstrap.\n });\n if (!result.ok) return { refreshedClaude: false, refreshedTaskToken: false };\n const previousTaskToken = process.env.CONVEYOR_TASK_TOKEN;\n applyBootstrapToEnv(result.config);\n const refreshedTaskToken =\n result.config.mode !== \"project\" &&\n Boolean(result.config.taskToken) &&\n result.config.taskToken !== previousTaskToken;\n if (refreshedTaskToken && result.config.taskToken) {\n this.config.taskToken = result.config.taskToken;\n // Update socket auth so the next reconnect cycle uses the fresh token.\n if (this.socket) {\n const auth = this.socket.auth as Record<string, unknown> | undefined;\n if (auth && typeof auth === \"object\") {\n auth.taskToken = result.config.taskToken;\n }\n }\n }\n const refreshedClaude = Boolean(result.config.envVars?.CLAUDE_CODE_OAUTH_TOKEN);\n return { refreshedClaude, refreshedTaskToken };\n }\n\n /**\n * v3 refresh: re-fetch the full bootstrap bundle from the pod's bound v3\n * route and swap the credentials in place. The GitHub installation token\n * dies at ~1h and the sessionJwt at 24h; re-polling the bootstrap GET with\n * the same pod token is the designed refresh mechanism.\n */\n private async refreshFromV3Bootstrap(\n apiUrl: string,\n bootstrapToken: string,\n ): Promise<{ refreshedClaude: boolean; refreshedTaskToken: boolean }> {\n // maxWaitMs 0: a bound pod answers 200 on the first request; a 204\n // (unbound — should not happen at refresh time) or any HTTP/network error\n // must fail the refresh, not park the agent in a poll loop. The one\n // exception is a transient 429 (shared Cloud NAT IP vs podBootstrapLimiter),\n // which pollBundleWithRateLimitRetry retries before giving up.\n const bundle = await this.pollBundleWithRateLimitRetry(apiUrl, bootstrapToken);\n if (!bundle) {\n return { refreshedClaude: false, refreshedTaskToken: false };\n }\n\n const previousTaskToken = process.env.CONVEYOR_TASK_TOKEN;\n for (const [key, value] of Object.entries(bundle.envVars ?? {})) {\n process.env[key] = value;\n }\n if (bundle.githubToken) process.env.CONVEYOR_GITHUB_TOKEN = bundle.githubToken;\n if (bundle.anthropicKey) process.env.ANTHROPIC_API_KEY = bundle.anthropicKey;\n if (bundle.gcpToken) process.env.CLOUDSDK_AUTH_ACCESS_TOKEN = bundle.gcpToken;\n\n const refreshedTaskToken =\n Boolean(bundle.sessionJwt) && bundle.sessionJwt !== previousTaskToken;\n if (refreshedTaskToken) {\n process.env.CONVEYOR_TASK_TOKEN = bundle.sessionJwt;\n this.config.taskToken = bundle.sessionJwt;\n // Update socket auth so the next reconnect cycle uses the fresh token.\n if (this.socket) {\n const auth = this.socket.auth as Record<string, unknown> | undefined;\n if (auth && typeof auth === \"object\") {\n auth.taskToken = bundle.sessionJwt;\n }\n }\n }\n const refreshedClaude = Boolean(bundle.envVars?.CLAUDE_CODE_OAUTH_TOKEN);\n return { refreshedClaude, refreshedTaskToken };\n }\n\n /**\n * Poll the bootstrap bundle once (maxWaitMs 0), retrying only on a transient\n * 429 (standby-pool pods share one Cloud NAT IP against podBootstrapLimiter)\n * with a short backoff. Returns null when the refresh should be abandoned —\n * a non-429 error, or 429s past the retry budget — so the caller no-ops\n * instead of parking a RUNNING pod in a poll loop.\n */\n private async pollBundleWithRateLimitRetry(\n apiUrl: string,\n bootstrapToken: string,\n ): Promise<Awaited<ReturnType<typeof pollUntilBound>> | null> {\n const retryDelaysMs = [1_000, 3_000];\n for (let attempt = 0; ; attempt++) {\n try {\n return await pollUntilBound({ apiUrl, bootstrapToken, maxWaitMs: 0 });\n } catch (err) {\n const isRateLimited = err instanceof PollUntilBoundHttpError && err.status === 429;\n if (!isRateLimited || attempt >= retryDelaysMs.length) {\n return null;\n }\n await new Promise<void>((resolve) => {\n setTimeout(resolve, retryDelaysMs[attempt]);\n });\n }\n }\n }\n\n // ── Event buffering ────────────────────────────────────────────────\n\n sendEvent(event: { type: string; [key: string]: unknown }): void {\n if (!this.socket) return;\n // Cap the buffer so a long disconnect can't accumulate an unbounded\n // replay storm. Drop oldest on overflow (keeps the most recent state).\n if (this.eventBuffer.length >= MAX_EVENT_BUFFER) {\n this.eventBuffer.shift();\n this.droppedEventCount++;\n if (this.droppedEventCount === 1 || this.droppedEventCount % 500 === 0) {\n process.stderr.write(\n `[conveyor-agent] eventBuffer overflow — dropped ${this.droppedEventCount} event(s) (cap: ${MAX_EVENT_BUFFER})\\n`,\n );\n }\n }\n this.eventBuffer.push({ event });\n if (!this.flushTimer) {\n this.flushTimer = setTimeout(() => void this.flushEvents(), EVENT_BATCH_MS);\n }\n }\n\n async flushEvents(): Promise<void> {\n if (this.flushTimer) {\n clearTimeout(this.flushTimer);\n this.flushTimer = null;\n }\n if (!this.socket || this.eventBuffer.length === 0) return;\n const events = this.eventBuffer.map((entry) => entry.event);\n this.eventBuffer = [];\n // Await so callers (emitStatus) can guarantee ordering\n await this.call(\"emitAgentEvent\", { sessionId: this.config.sessionId, events }).catch(() => {});\n }\n}\n","import type { BootstrapBundle } from \"./bootstrap-bundle-types.js\";\n\nexport interface PollUntilBoundOptions {\n apiUrl: string;\n bootstrapToken: string;\n pollIntervalMs?: number;\n maxWaitMs?: number;\n}\n\n/** Thrown by `pollUntilBound` on a non-200/204 response; carries the HTTP\n * status so callers can distinguish transient conditions (e.g. 429) from\n * fatal ones (e.g. 401/403) without string-matching the message. */\nexport class PollUntilBoundHttpError extends Error {\n constructor(public readonly status: number) {\n super(`pollUntilBound got unexpected status ${status}`);\n this.name = \"PollUntilBoundHttpError\";\n }\n}\n\nasync function sleep(ms: number): Promise<void> {\n await new Promise<void>((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\nexport async function pollUntilBound(opts: PollUntilBoundOptions): Promise<BootstrapBundle> {\n const pollIntervalMs = opts.pollIntervalMs ?? 2_000;\n const maxWaitMs = opts.maxWaitMs ?? 30 * 60 * 1_000;\n const deadline = Date.now() + maxWaitMs;\n\n while (true) {\n const response = await fetch(`${opts.apiUrl}/api/v3/pods/bootstrap`, {\n headers: { Authorization: `Bearer ${opts.bootstrapToken}` },\n });\n\n if (response.status === 200) {\n return (await response.json()) as BootstrapBundle;\n }\n if (response.status === 204) {\n if (Date.now() >= deadline) {\n throw new Error(`pollUntilBound timed out after ${maxWaitMs}ms waiting for pod bind`);\n }\n await sleep(pollIntervalMs);\n continue;\n }\n throw new PollUntilBoundHttpError(response.status);\n }\n}\n","/** Minimal structured logger for conveyor-agent (writes to stderr). */\nexport function createServiceLogger(service: string) {\n const prefix = `[conveyor-agent:${service}]`;\n return {\n info(message: string, data?: Record<string, unknown>): void {\n const extra = data ? ` ${JSON.stringify(data)}` : \"\";\n process.stderr.write(`${prefix} ${message}${extra}\\n`);\n },\n warn(message: string, data?: Record<string, unknown>): void {\n const extra = data ? ` ${JSON.stringify(data)}` : \"\";\n process.stderr.write(`${prefix} WARN ${message}${extra}\\n`);\n },\n error(message: string, data?: Record<string, unknown>): void {\n const extra = data ? ` ${JSON.stringify(data)}` : \"\";\n process.stderr.write(`${prefix} ERROR ${message}${extra}\\n`);\n },\n };\n}\n","import { execSync } from \"node:child_process\";\nimport { realpathSync } from \"node:fs\";\n\n/** Fetch and merge the latest base branch to prevent stale-base merge conflicts.\n * Returns true on success or no-op (empty baseBranch), false on failure. */\nexport function syncWithBaseBranch(cwd: string, baseBranch: string): boolean {\n if (!baseBranch) return true;\n\n try {\n execSync(`git fetch origin ${baseBranch}`, { cwd, stdio: \"ignore\", timeout: 60_000 });\n } catch {\n process.stderr.write(\n `[conveyor-agent] Warning: git fetch origin ${baseBranch} failed, continuing with current base\\n`,\n );\n return false;\n }\n\n try {\n execSync(`git merge origin/${baseBranch} --no-edit`, { cwd, stdio: \"ignore\", timeout: 30_000 });\n } catch {\n process.stderr.write(\n `[conveyor-agent] Warning: merge origin/${baseBranch} failed, aborting merge and continuing\\n`,\n );\n try {\n execSync(\"git merge --abort\", { cwd, stdio: \"ignore\" });\n } catch {\n // merge --abort can fail if there's nothing to abort\n }\n return false;\n }\n\n process.stderr.write(`[conveyor-agent] Synced with latest origin/${baseBranch}\\n`);\n return true;\n}\n\n/** Ensure the repo is on the expected task branch. No-op if already correct.\n * Returns true on success, false on failure. */\nexport function ensureOnTaskBranch(cwd: string, taskBranch: string): boolean {\n if (!taskBranch) return true;\n\n const current = getCurrentBranch(cwd);\n if (current === taskBranch) return true;\n\n try {\n execSync(`git fetch origin ${taskBranch}`, { cwd, stdio: \"ignore\", timeout: 60_000 });\n } catch {\n process.stderr.write(`[conveyor-agent] Warning: git fetch origin ${taskBranch} failed\\n`);\n return false;\n }\n\n // Use `checkout -B` which creates or resets the local branch to track origin.\n // This handles the detached-HEAD case (entrypoint.sh leaves the repo detached\n // after `git reset --hard origin/<branch>`) and the case where a stale local\n // branch exists pointing at a different SHA.\n try {\n execSync(`git checkout -B ${taskBranch} origin/${taskBranch}`, {\n cwd,\n stdio: \"ignore\",\n timeout: 30_000,\n });\n } catch {\n process.stderr.write(`[conveyor-agent] Warning: git checkout ${taskBranch} failed\\n`);\n return false;\n }\n\n process.stderr.write(`[conveyor-agent] Checked out task branch ${taskBranch}\\n`);\n return true;\n}\n\n/** Returns true if the working tree has uncommitted changes (staged or unstaged). */\nexport function hasUncommittedChanges(cwd: string): boolean {\n const status = execSync(\"git status --porcelain\", {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n })\n .toString()\n .trim();\n return status.length > 0;\n}\n\n/** Returns the current branch name, or null if on detached HEAD. */\nexport function getCurrentBranch(cwd: string): string | null {\n try {\n const branch = execSync(\"git branch --show-current\", {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n })\n .toString()\n .trim();\n return branch || null;\n } catch {\n return null;\n }\n}\n\n/** Returns true if there are committed changes that haven't been pushed to origin. */\nexport function hasUnpushedCommits(cwd: string): boolean {\n try {\n const currentBranch = getCurrentBranch(cwd);\n if (!currentBranch) return false;\n\n try {\n execSync(`git rev-parse origin/${currentBranch}`, {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n } catch {\n try {\n execSync(\"git rev-parse HEAD\", { cwd, stdio: [\"ignore\", \"pipe\", \"ignore\"] });\n return true;\n } catch {\n return false;\n }\n }\n\n const ahead = execSync(`git rev-list --count HEAD --not origin/${currentBranch}`, {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n })\n .toString()\n .trim();\n return parseInt(ahead, 10) > 0;\n } catch {\n return false;\n }\n}\n\n/** Stage all changes and create a commit. Returns the commit hash if successful. */\nexport function stageAndCommit(cwd: string, message: string): string | null {\n try {\n execSync(\"git add -A\", { cwd, stdio: [\"ignore\", \"pipe\", \"ignore\"] });\n\n if (!hasUncommittedChanges(cwd)) return null;\n\n execSync(`git commit -m ${JSON.stringify(message)}`, {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n\n return execSync(\"git rev-parse HEAD\", { cwd, stdio: [\"ignore\", \"pipe\", \"ignore\"] })\n .toString()\n .trim();\n } catch {\n return null;\n }\n}\n\nfunction tryPush(cwd: string, branch: string, skipVerify = false): boolean {\n const noVerify = skipVerify ? \"--no-verify \" : \"\";\n try {\n execSync(`git push ${noVerify}origin ${branch}`, {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n timeout: 30_000,\n });\n return true;\n } catch {\n try {\n execSync(`git push ${noVerify}--force-with-lease origin ${branch}`, {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n timeout: 30_000,\n });\n return true;\n } catch {\n return false;\n }\n }\n}\n\nfunction isAuthError(cwd: string): boolean {\n try {\n execSync(\"git push --dry-run\", { cwd, stdio: [\"ignore\", \"pipe\", \"pipe\"], timeout: 30_000 });\n return false;\n } catch (err: unknown) {\n if ((err as { killed?: boolean }).killed) return true;\n const stderr = (err as { stderr?: Buffer }).stderr?.toString() ?? \"\";\n const stdout = (err as { stdout?: Buffer }).stdout?.toString() ?? \"\";\n const msg = stderr || stdout || (err instanceof Error ? err.message : \"\");\n return /authentication|authorization|403|401|token/i.test(msg);\n }\n}\n\n/** Update the git remote URL with a fresh token. */\nexport function updateRemoteToken(cwd: string, token: string): void {\n try {\n const url = execSync(\"git remote get-url origin\", { cwd, stdio: [\"ignore\", \"pipe\", \"ignore\"] })\n .toString()\n .trim();\n const match = url.match(/github\\.com[/:]([^/]+\\/[^/.]+)/);\n if (match) {\n const repo = match[1].replace(/\\.git$/, \"\");\n execSync(\n `git remote set-url origin \"https://x-access-token:${token}@github.com/${repo}.git\"`,\n { cwd, stdio: [\"ignore\", \"pipe\", \"ignore\"] },\n );\n }\n } catch {\n // silently fail — push retry will surface the real error\n }\n}\n\n// ── WIP snapshot ref ────────────────────────────────────────────────────\n//\n// Crash protection without polluting the task branch: uncommitted work is\n// captured as a stash-shaped commit (`git stash create` — does not touch\n// HEAD, the index, or the working tree) and force-pushed to a dedicated\n// `conveyor-wip/<branch>` ref. Real (intentional) commits are still pushed\n// to the task branch itself. On a fresh pod, `restoreWipSnapshot` re-applies\n// the snapshot when the branch head matches; once the tree is clean the\n// stale remote ref is deleted.\n\n/** The remote ref that holds the WIP snapshot for a task branch. */\nexport function wipRefForBranch(branch: string): string {\n return `conveyor-wip/${branch}`;\n}\n\n/** cwd values that have (or may have) a live remote WIP ref to clean up. */\nconst wipRefPushed = new Set<string>();\n\n/**\n * Capture the working tree + index (including untracked files) as a\n * stash-shaped commit WITHOUT moving HEAD or dirtying history. The index is\n * staged so untracked files are included, then restored so the agent's\n * `git status` view is unchanged.\n */\nfunction createWipSnapshot(cwd: string, message: string): string | null {\n try {\n execSync(\"git add -A\", { cwd, stdio: [\"ignore\", \"pipe\", \"ignore\"] });\n const sha = execSync(`git stash create ${JSON.stringify(message)}`, {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n })\n .toString()\n .trim();\n return sha || null;\n } catch {\n return null;\n } finally {\n try {\n execSync(\"git reset -q\", { cwd, stdio: [\"ignore\", \"pipe\", \"ignore\"] });\n } catch {\n /* nothing staged */\n }\n }\n}\n\nfunction tryPushRefspec(cwd: string, refspec: string, force = false): boolean {\n try {\n // --no-verify: a WIP snapshot to a throwaway conveyor-wip/* ref is a machine\n // crash-protection push, not a real branch update — it must never run the\n // pre-push quality gate (lint/typecheck/test).\n execSync(`git push --no-verify ${force ? \"--force \" : \"\"}origin ${JSON.stringify(refspec)}`, {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n timeout: 30_000,\n });\n return true;\n } catch {\n return false;\n }\n}\n\nasync function refreshRemoteToken(\n cwd: string,\n refreshToken?: () => Promise<string | undefined>,\n): Promise<void> {\n if (!refreshToken) return;\n try {\n const token = await refreshToken();\n if (token) {\n updateRemoteToken(cwd, token);\n process.env.GITHUB_TOKEN = token;\n process.env.GH_TOKEN = token;\n }\n } catch {\n // best effort — proceed with existing token\n }\n}\n\n/**\n * Re-apply a WIP snapshot pushed by a previous pod of this task. When the\n * snapshot was taken on the current HEAD, this is a plain re-apply. When the\n * branch advanced past the snapshot (review commits, a dev merge, another\n * pod), the snapshot is 3-way applied onto the new head so newer remote work\n * AND the WIP both land. Only a genuine line-level conflict refuses\n * (\"stale\") — the wip ref is kept on origin in that case so nothing is lost:\n * git fetch origin refs/heads/conveyor-wip/<branch> && git stash apply FETCH_HEAD\n */\nexport function restoreWipSnapshot(\n cwd: string,\n branch: string,\n): \"applied\" | \"stale\" | \"none\" | \"failed\" {\n if (!branch) return \"none\";\n const ref = wipRefForBranch(branch);\n try {\n execSync(`git fetch origin +refs/heads/${ref}:refs/remotes/origin/${ref}`, {\n cwd,\n stdio: \"ignore\",\n timeout: 60_000,\n });\n } catch {\n // Ref doesn't exist remotely (or fetch failed) — nothing to restore.\n return \"none\";\n }\n // A remote ref exists — remember to clean it up once the tree is clean.\n wipRefPushed.add(cwd);\n try {\n const sha = execSync(`git rev-parse refs/remotes/origin/${ref}`, {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n })\n .toString()\n .trim();\n // First parent of a stash-shaped commit is the HEAD it was created on.\n const parent = execSync(`git rev-parse \"${sha}^\"`, {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n })\n .toString()\n .trim();\n const head = execSync(\"git rev-parse HEAD\", { cwd, stdio: [\"ignore\", \"pipe\", \"ignore\"] })\n .toString()\n .trim();\n if (parent !== head) {\n // Branch moved since the snapshot. Try the 3-way apply (the stash\n // commit's first parent is the merge base, so git can transplant the\n // WIP onto the new head); back out cleanly on conflict and keep the\n // origin ref for manual recovery.\n try {\n execSync(`git stash apply ${sha}`, { cwd, stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n return \"applied\";\n } catch {\n try {\n execSync(\"git reset --merge\", { cwd, stdio: \"ignore\" });\n } catch {\n // best effort — leave whatever git managed to clean up\n }\n return \"stale\";\n }\n }\n execSync(`git stash apply ${sha}`, { cwd, stdio: [\"ignore\", \"pipe\", \"pipe\"] });\n return \"applied\";\n } catch {\n return \"failed\";\n }\n}\n\n/** Best-effort flush of pending work: pushes any real (intentional) commits to\n * the task branch, and captures uncommitted changes as a WIP snapshot on the\n * `conveyor-wip/<branch>` ref — never as commits on the branch itself. When\n * the tree is clean, a previously pushed WIP ref is deleted. Never throws. */\nexport async function flushPendingChanges(\n cwd: string,\n opts?: { wipMessage?: string; refreshToken?: () => Promise<string | undefined> },\n): Promise<{ committed: boolean; pushed: boolean; hadWork: boolean }> {\n let committed = false;\n let pushed = false;\n let hadWork = false;\n\n try {\n const branch = getCurrentBranch(cwd);\n if (!branch) return { committed, pushed, hadWork };\n\n const dirty = hasUncommittedChanges(cwd);\n const unpushed = hasUnpushedCommits(cwd);\n\n if (!dirty && !unpushed) {\n await dropStaleWipRef(cwd, branch, opts?.refreshToken);\n return { committed, pushed, hadWork };\n }\n\n hadWork = true;\n await refreshRemoteToken(cwd, opts?.refreshToken);\n\n // Real commits first so a WIP snapshot taken below sits on the pushed head.\n if (unpushed) {\n pushed = await pushToOrigin(cwd, opts?.refreshToken);\n }\n\n if (dirty) {\n const message = opts?.wipMessage ?? \"WIP: conveyor-agent snapshot\";\n const sha = createWipSnapshot(cwd, message);\n if (sha) {\n committed = tryPushRefspec(cwd, `${sha}:refs/heads/${wipRefForBranch(branch)}`, true);\n if (committed) wipRefPushed.add(cwd);\n }\n }\n } catch {\n // best effort\n }\n\n return { committed, pushed, hadWork };\n}\n\n/** Clean tree: the last WIP snapshot is stale — drop the remote ref so\n * recovery never resurrects superseded work. */\nasync function dropStaleWipRef(\n cwd: string,\n branch: string,\n refreshToken?: () => Promise<string | undefined>,\n): Promise<void> {\n if (!wipRefPushed.has(cwd)) return;\n await refreshRemoteToken(cwd, refreshToken);\n if (tryPushRefspec(cwd, `:refs/heads/${wipRefForBranch(branch)}`)) {\n wipRefPushed.delete(cwd);\n }\n}\n\n/** Push current branch to origin. Proactively refreshes the GitHub token before\n * attempting the push. On auth failure, refreshes again and retries. */\nexport async function pushToOrigin(\n cwd: string,\n refreshToken?: () => Promise<string | undefined>,\n skipVerify = false,\n): Promise<boolean> {\n try {\n const currentBranch = getCurrentBranch(cwd);\n if (!currentBranch) return false;\n\n // Proactively refresh token before pushing to avoid wasting time with a stale token\n if (refreshToken) {\n try {\n const token = await refreshToken();\n if (token) {\n updateRemoteToken(cwd, token);\n process.env.GITHUB_TOKEN = token;\n process.env.GH_TOKEN = token;\n }\n } catch {\n // best effort — proceed with existing token\n }\n }\n\n if (tryPush(cwd, currentBranch, skipVerify)) return true;\n\n if (refreshToken && isAuthError(cwd)) {\n const token = await refreshToken();\n if (token) {\n updateRemoteToken(cwd, token);\n process.env.GITHUB_TOKEN = token;\n process.env.GH_TOKEN = token;\n return tryPush(cwd, currentBranch, skipVerify);\n }\n }\n\n return false;\n } catch {\n return false;\n }\n}\n\n// ── Whole-repo crash protection ─────────────────────────────────────────\n//\n// `flushPendingChanges` only protects the primary workspace's current branch.\n// A pod that dies while a 5-subagent build has produced several unpushed\n// feature branches (and/or dirty per-subagent worktrees) loses all of it — the\n// pod is reprovisioned as a fresh clone of the branch tip on GitHub (see runbook\n// claudespace-pod-deaths-unpushed-work-loss). `flushAllPendingWork` widens the\n// net to EVERY local branch and worktree, backing them up under the throwaway\n// `conveyor-wip/*` namespace (never real branch names, so origin isn't polluted\n// with half-baked branches and CI/PRs aren't triggered).\n\n/** Backup ref that mirrors a local branch's tip (committed, unpushed work). */\nexport function branchBackupRef(branch: string): string {\n return `conveyor-wip/branches/${branch}`;\n}\n\n/** Enumerate the repo's worktrees as { path, branch }. branch is null for a\n * detached HEAD. Returns [] on any failure. */\nfunction listWorktrees(cwd: string): { path: string; branch: string | null }[] {\n try {\n const out = execSync(\"git worktree list --porcelain\", {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n }).toString();\n const result: { path: string; branch: string | null }[] = [];\n for (const entry of out.split(\"\\n\\n\")) {\n const lines = entry.trim().split(\"\\n\");\n const wl = lines.find((l) => l.startsWith(\"worktree \"));\n if (!wl) continue;\n const bl = lines.find((l) => l.startsWith(\"branch \"));\n result.push({\n path: wl.slice(\"worktree \".length),\n branch: bl ? bl.slice(\"branch refs/heads/\".length) : null,\n });\n }\n return result;\n } catch {\n return [];\n }\n}\n\n/** All local branch short-names (refs/heads/*). Returns [] on failure. */\nfunction listLocalBranches(cwd: string): string[] {\n try {\n // Single-quote the format: %(...) parens are shell metacharacters and would\n // otherwise trigger a subshell syntax error, making this return nothing.\n return execSync(\"git for-each-ref --format='%(refname:short)' refs/heads/\", {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n })\n .toString()\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter(Boolean);\n } catch {\n return [];\n }\n}\n\n/** Count of commits on `branch` not reachable from any origin/* ref — i.e.\n * genuinely unpushed local work. 0 covers both \"already pushed\" and \"an exact\n * copy of a remote branch (e.g. base)\". */\nfunction branchUnpushedCount(cwd: string, branch: string): number {\n try {\n const n = execSync(`git rev-list --count ${JSON.stringify(branch)} --not --remotes=origin`, {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n })\n .toString()\n .trim();\n return Number.parseInt(n, 10) || 0;\n } catch {\n return 0;\n }\n}\n\nfunction samePath(a: string, b: string): boolean {\n try {\n return realpathSync(a) === realpathSync(b);\n } catch {\n return a === b;\n }\n}\n\n/** Best-effort crash protection for the WHOLE repo, not just the primary\n * branch:\n * 1. the primary workspace via `flushPendingChanges` (real commits → task\n * branch, dirty tree → conveyor-wip/<branch>) — unchanged behavior;\n * 2. dirty working trees in every OTHER worktree → a stash-shaped snapshot on\n * conveyor-wip/<worktree-branch>;\n * 3. committed-but-unpushed work on every OTHER local branch → its tip mirrored\n * to conveyor-wip/branches/<branch>.\n * Each unit is failure-isolated so one bad branch/worktree can't abort the rest.\n * Never throws. */\nexport async function flushAllPendingWork(\n cwd: string,\n opts?: { wipMessage?: string; refreshToken?: () => Promise<string | undefined> },\n): Promise<{ hadWork: boolean; branchesBackedUp: number; worktreesSnapshotted: number }> {\n try {\n // 1. Primary workspace — existing behavior (real push + current-branch WIP).\n const primary = await flushPendingChanges(cwd, opts);\n await refreshRemoteToken(cwd, opts?.refreshToken);\n const currentBranch = getCurrentBranch(cwd);\n\n // 2 & 3. Widen to the other worktrees and branches.\n const worktreesSnapshotted = snapshotOtherWorktrees(cwd, opts?.wipMessage);\n const branchesBackedUp = backupOtherBranches(cwd, currentBranch);\n\n return {\n hadWork: primary.hadWork || worktreesSnapshotted > 0 || branchesBackedUp > 0,\n branchesBackedUp,\n worktreesSnapshotted,\n };\n } catch {\n return { hadWork: false, branchesBackedUp: 0, worktreesSnapshotted: 0 };\n }\n}\n\n/** Snapshot dirty working trees in every worktree except the primary `cwd` to\n * conveyor-wip/<worktree-branch>. Returns how many were snapshotted. */\nfunction snapshotOtherWorktrees(cwd: string, wipMessage?: string): number {\n let count = 0;\n for (const wt of listWorktrees(cwd)) {\n if (samePath(wt.path, cwd) || !wt.branch) continue;\n try {\n if (!hasUncommittedChanges(wt.path)) continue;\n const sha = createWipSnapshot(wt.path, wipMessage ?? \"WIP: conveyor-agent snapshot\");\n if (sha && tryPushRefspec(wt.path, `${sha}:refs/heads/${wipRefForBranch(wt.branch)}`, true)) {\n wipRefPushed.add(wt.path);\n count++;\n }\n } catch {\n // isolate per-worktree failure\n }\n }\n return count;\n}\n\n/** Mirror committed-but-unpushed work on every local branch (except the primary\n * workspace's current branch and our own conveyor-wip/* refs) to\n * conveyor-wip/branches/<branch>. Returns how many were backed up. */\nfunction backupOtherBranches(cwd: string, currentBranch: string | null): number {\n let count = 0;\n for (const branch of listLocalBranches(cwd)) {\n // The current branch is handled by step 1; never back up our own snapshots.\n if (branch === currentBranch || branch.startsWith(\"conveyor-wip/\")) continue;\n try {\n if (branchUnpushedCount(cwd, branch) === 0) continue;\n if (tryPushRefspec(cwd, `refs/heads/${branch}:refs/heads/${branchBackupRef(branch)}`, true)) {\n count++;\n }\n } catch {\n // isolate per-branch failure\n }\n }\n return count;\n}\n","import { readdirSync, statSync, readFileSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport type { AgentConnection } from \"../connection/agent-connection.js\";\nimport { configHomePlansDir } from \"../harness/pty/settings.js\";\n\nexport class PlanSync {\n private planFileSnapshot = new Map<string, number>();\n private lockedPlanFile: string | null = null;\n private workspaceDir: string;\n private connection: AgentConnection;\n\n constructor(workspaceDir: string, connection: AgentConnection) {\n this.workspaceDir = workspaceDir;\n this.connection = connection;\n }\n\n updateWorkspaceDir(workspaceDir: string): void {\n this.workspaceDir = workspaceDir;\n }\n\n private getPlanDirs(): string[] {\n // Claude Code 2.x writes plan-mode plan files to <config-home>/plans, not\n // the workspace .claude/plans — watch both. The snapshot taken at query\n // start keeps stale files from other sessions out of detection.\n return [join(this.workspaceDir, \".claude\", \"plans\"), configHomePlansDir()];\n }\n\n snapshotPlanFiles(): void {\n this.planFileSnapshot.clear();\n this.lockedPlanFile = null;\n for (const plansDir of this.getPlanDirs()) {\n try {\n for (const file of readdirSync(plansDir).filter((f) => f.endsWith(\".md\"))) {\n try {\n const fullPath = join(plansDir, file);\n const stat = statSync(fullPath);\n this.planFileSnapshot.set(fullPath, stat.mtimeMs);\n } catch {\n continue;\n }\n }\n } catch {\n /* plans dir doesn't exist yet */\n }\n }\n }\n\n private findNewestPlanFile(): { path: string; mtime: number } | null {\n let newest: { path: string; mtime: number } | null = null;\n for (const plansDir of this.getPlanDirs()) {\n let files: string[];\n try {\n files = readdirSync(plansDir).filter((f) => f.endsWith(\".md\"));\n } catch {\n continue;\n }\n\n for (const file of files) {\n const fullPath = join(plansDir, file);\n try {\n const stat = statSync(fullPath);\n const prevMtime = this.planFileSnapshot.get(fullPath);\n const isNew = prevMtime === undefined || stat.mtimeMs > prevMtime;\n if (isNew && (!newest || stat.mtimeMs > newest.mtime)) {\n newest = { path: fullPath, mtime: stat.mtimeMs };\n }\n } catch {\n continue;\n }\n }\n }\n return newest;\n }\n\n async syncPlanFile(): Promise<void> {\n const isInitialDetection = this.lockedPlanFile === null;\n const target = this.lockedPlanFile ?? this.findNewestPlanFile()?.path ?? null;\n if (!target) return;\n\n // Lock on initial detection before reading — matches prior behavior and\n // prevents a broken file from re-triggering detection on every tick.\n if (isInitialDetection) {\n this.lockedPlanFile = target;\n }\n\n const fileName = target.split(\"/\").pop() ?? \"plan\";\n\n let content: string;\n try {\n content = readFileSync(target, \"utf-8\").trim();\n } catch (err) {\n const reason = err instanceof Error ? err.message : String(err);\n this.connection.postChatMessage(\n `Plan sync warning: could not read local plan file (${fileName}): ${reason}. The task plan was not updated.`,\n );\n return;\n }\n\n if (!content) return;\n\n const result = await this.connection.updateTaskFields({ plan: content });\n if (!result.ok) {\n this.connection.postChatMessage(\n `Plan sync failed: the local plan file (${fileName}) was not persisted to the task (${result.error ?? \"unknown error\"}). Retry update_task_plan or re-run ExitPlanMode.`,\n );\n return;\n }\n\n const verb = isInitialDetection ? \"Detected local plan file\" : \"Synced local plan file\";\n const suffix = isInitialDetection ? \" and synced it to the task plan.\" : \" to the task plan.\";\n this.connection.postChatMessage(`${verb} (${fileName})${suffix}`);\n }\n}\n","/**\n * Claude Code config-dir paths and per-run settings/hook materialization.\n *\n * The PTY harness writes a throwaway `settings.json` (passed via\n * `claude --settings`) wiring two hooks that relay envelopes to a Unix socket:\n * - PostToolUse (all tools): fire-and-forget tool-progress envelopes.\n * - PreToolUse (ExitPlanMode): request/response — the runner's\n * `canUseTool` verdict (plan/property validation, identification trigger)\n * is returned as a permissionDecision so the plan-mode exit is gated by\n * Conveyor instead of the interactive dialog.\n * - PreToolUse (AskUserQuestion): observe-only — the session is told a\n * questionnaire is about to render (so it can report waiting_for_input)\n * and the hook always allows; the TUI collects the answer natively.\n * - PreToolUse (mcp__.*): local auto-allow — plan-permission spawns prompt\n * for MCP tools even when they're in permissions.allow, so the hook\n * answers allow without a socket round trip. The pod is the sandbox.\n * Writing a per-run file avoids clobbering the user's real `~/.claude/settings.json`.\n */\n\nimport { mkdir, writeFile, chmod } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\n\nexport function claudeConfigHome(): string {\n return process.env.CLAUDE_CONFIG_DIR ?? join(homedir(), \".claude\");\n}\n\nexport function projectSlug(cwd: string): string {\n return cwd.replace(/\\//g, \"-\");\n}\n\nexport function sessionTranscriptPath(cwd: string, sessionId: string): string {\n return join(claudeConfigHome(), \"projects\", projectSlug(cwd), `${sessionId}.jsonl`);\n}\n\n/** Where the CLI writes plan-mode plan files (CC 2.x): `<config-home>/plans`. */\nexport function configHomePlansDir(): string {\n return join(claudeConfigHome(), \"plans\");\n}\n\n/**\n * Per-tool allow rules approximating \"allow everything\". The CLI rejects a\n * bare `\"*\"` rule (and an unanchored `\"mcp__conveyor\"`) as invalid — that\n * parks the TUI on a blocking \"Settings Warning\" screen at boot — so the\n * built-in tools are named explicitly and the Conveyor MCP tools matched by\n * the only valid glob form (`mcp__<server>__*`). The built-in names matter\n * for the acceptEdits continuation after an auto-mode plan exit (Bash/MCP\n * would otherwise prompt with nobody at the terminal); plan-permission spawns\n * are read-only regardless, and build-capable spawns pass\n * `--dangerously-skip-permissions` and never consult this list.\n *\n * NOTE: `mcp__conveyor__*` does NOT suppress plan-mode prompts — the CLI\n * can't classify MCP tools as read-only, so `--permission-mode plan` prompts\n * for them regardless of this list. The `mcp__.*` PreToolUse hook below is\n * what actually admits MCP calls while planning; the rule stays as\n * defense-in-depth for the acceptEdits continuation.\n */\nexport const ALLOW_RULES = [\n \"Bash\",\n \"BashOutput\",\n \"Edit\",\n \"Write\",\n \"Read\",\n \"Glob\",\n \"Grep\",\n \"WebFetch\",\n \"WebSearch\",\n \"NotebookEdit\",\n \"Task\",\n \"TodoWrite\",\n \"ToolSearch\",\n \"KillShell\",\n \"SlashCommand\",\n \"Skill\",\n \"mcp__conveyor__*\",\n];\n\n/**\n * CJS hook helper. Reads the hook payload from stdin and branches on\n * `hook_event_name`:\n *\n * - PostToolUse: relays a fire-and-forget tool-progress envelope and prints\n * `{continue:true}` so the CLI proceeds. A short fallback timer guarantees\n * exit even if the socket is unavailable.\n * - PreToolUse: writes a `pre_tool_use` request and waits for the runner's\n * correlated verdict on the same connection, printing a\n * permissionDecision allow/deny. On socket failure or timeout it fails\n * CLOSED (deny) — the model retries after fixing the reported problem,\n * and the runner's denial-escalation backstop bounds pathological loops.\n * Exception: AskUserQuestion fails OPEN (allow, short timeout) — it is\n * observed for status reporting only, and a socket blip must never deny\n * the model's questionnaire.\n * Exception: MCP tools (`mcp__*`) are allowed locally without touching\n * the socket at all — the decision is unconditional, so there is no\n * fail-mode and no latency.\n */\nconst HOOK_HELPER_SOURCE = `\"use strict\";\nconst net = require(\"node:net\");\nconst crypto = require(\"node:crypto\");\n\nconst PRE_TOOL_USE_TIMEOUT_MS = 110000;\nconst ASK_USER_QUESTION_TIMEOUT_MS = 5000;\n\nlet raw = \"\";\nprocess.stdin.setEncoding(\"utf8\");\nprocess.stdin.on(\"data\", (chunk) => {\n raw += chunk;\n});\nprocess.stdin.on(\"end\", () => {\n let payload = {};\n try {\n const parsed = JSON.parse(raw);\n if (parsed && typeof parsed === \"object\") payload = parsed;\n } catch {\n payload = {};\n }\n if (payload.hook_event_name === \"PreToolUse\") {\n preToolUse(payload);\n } else {\n relayProgress(typeof payload.tool_name === \"string\" ? payload.tool_name : \"\");\n }\n});\n\nfunction relayProgress(toolName) {\n const socketPath = process.env.CONVEYOR_HOOK_SOCKET;\n let done = false;\n const finish = () => {\n if (done) return;\n done = true;\n process.stdout.write(JSON.stringify({ continue: true }));\n process.exit(0);\n };\n const fallback = setTimeout(finish, 250);\n if (!socketPath) {\n clearTimeout(fallback);\n finish();\n return;\n }\n const client = net.connect(socketPath, () => {\n // PostToolUse does not supply tool duration, so elapsed_time_seconds is\n // omitted rather than reported as a misleading 0 (the field is optional).\n const line = JSON.stringify({ tool_name: toolName }) + \"\\\\n\";\n client.write(line, () => {\n client.end();\n });\n });\n client.on(\"close\", () => {\n clearTimeout(fallback);\n finish();\n });\n client.on(\"error\", () => {\n clearTimeout(fallback);\n finish();\n });\n}\n\nfunction preToolUse(payload) {\n const socketPath = process.env.CONVEYOR_HOOK_SOCKET;\n let done = false;\n const respond = (decision, reason) => {\n if (done) return;\n done = true;\n process.stdout.write(\n JSON.stringify({\n hookSpecificOutput: {\n hookEventName: \"PreToolUse\",\n permissionDecision: decision,\n ...(reason ? { permissionDecisionReason: reason } : {}),\n },\n }),\n );\n process.exit(0);\n };\n // MCP tools are auto-allowed locally — no socket round trip, no fail-mode.\n // Plan mode prompts for them despite permissions.allow (the CLI can't\n // classify MCP tools as read-only), and the pod is the sandbox.\n if (typeof payload.tool_name === \"string\" && payload.tool_name.startsWith(\"mcp__\")) {\n respond(\"allow\");\n return;\n }\n // AskUserQuestion is observe-only (status reporting) — fail OPEN so a\n // missing/slow socket never denies the questionnaire. Everything else\n // (ExitPlanMode) is a Conveyor gate — fail CLOSED.\n const failOpen = payload.tool_name === \"AskUserQuestion\";\n const respondUnavailable = () =>\n failOpen\n ? respond(\"allow\")\n : respond(\n \"deny\",\n \"Conveyor validation is unavailable right now. Wait a moment and call the tool again.\",\n );\n if (!socketPath) {\n respondUnavailable();\n return;\n }\n const id = crypto.randomBytes(8).toString(\"hex\");\n const timer = setTimeout(\n respondUnavailable,\n failOpen ? ASK_USER_QUESTION_TIMEOUT_MS : PRE_TOOL_USE_TIMEOUT_MS,\n );\n const client = net.connect(socketPath, () => {\n client.write(\n JSON.stringify({\n kind: \"pre_tool_use\",\n id,\n tool_name: typeof payload.tool_name === \"string\" ? payload.tool_name : \"\",\n tool_input:\n payload.tool_input && typeof payload.tool_input === \"object\" ? payload.tool_input : {},\n }) + \"\\\\n\",\n );\n });\n let buffer = \"\";\n client.on(\"data\", (chunk) => {\n buffer += chunk.toString(\"utf8\");\n let index = buffer.indexOf(\"\\\\n\");\n while (index >= 0) {\n const line = buffer.slice(0, index);\n buffer = buffer.slice(index + 1);\n try {\n const verdict = JSON.parse(line);\n if (verdict && verdict.id === id) {\n clearTimeout(timer);\n client.end();\n respond(verdict.decision === \"allow\" ? \"allow\" : \"deny\", verdict.reason);\n return;\n }\n } catch {\n /* keep scanning */\n }\n index = buffer.indexOf(\"\\\\n\");\n }\n });\n client.on(\"error\", () => {\n clearTimeout(timer);\n respondUnavailable();\n });\n client.on(\"close\", () => {\n clearTimeout(timer);\n respondUnavailable();\n });\n}\n`;\n\nexport interface HookSettingsResult {\n settingsPath: string;\n helperPath: string;\n}\n\nexport async function writeHookSettings(dir: string): Promise<HookSettingsResult> {\n const helperPath = join(dir, \"hook-helper.cjs\");\n const settingsPath = join(dir, \"settings.json\");\n await mkdir(dir, { recursive: true });\n await writeFile(helperPath, HOOK_HELPER_SOURCE, \"utf8\");\n await chmod(helperPath, 0o755);\n const settings = {\n // Pre-accept Claude Code's \"Bypass Permissions mode\" disclaimer. Build-capable\n // spawns pass `--dangerously-skip-permissions`; on a real PTY the CLI otherwise\n // parks on the interactive \"Yes, I accept / No, exit\" dialog whose default focus\n // is \"No, exit\" — so it cannot be auto-dismissed by an Enter nudge and the run\n // stalls until the auto-nudge watchdog shuts it down. The CLI reads this key\n // from the `--settings` (flagSettings) layer via its bypass-mode gate, so\n // setting it here suppresses the dialog deterministically on every spawn —\n // independent of the `bypassPermissionsModeAccepted` seed in credentials.ts,\n // which the CLI's one-time migration consumes and which is subject to\n // persistence races on the codespace user-home.\n skipDangerousModePermissionPrompt: true,\n // Auto-approve tool calls so the interactive (PTY) agent never stops to\n // prompt the viewer. This only suppresses per-tool approval prompts — it\n // does NOT relax the planning gate: in discovery/plan mode the spawn passes\n // `--permission-mode plan`, which keeps the agent read-only (no edits/commits\n // until it exits plan mode) regardless of this allow-list. In build mode the\n // spawn already bypasses prompts via `--dangerously-skip-permissions`.\n // NOTE: a bare \"*\" rule is INVALID (the CLI rejects it and parks the TUI on\n // a Settings Warning dialog at boot) — hence the explicit ALLOW_RULES list.\n permissions: {\n allow: ALLOW_RULES,\n },\n hooks: {\n PreToolUse: [\n {\n matcher: \"ExitPlanMode\",\n hooks: [{ type: \"command\", command: `node ${JSON.stringify(helperPath)}`, timeout: 120 }],\n },\n {\n // Observe-only: lets the session report waiting_for_input the moment\n // the planning questionnaire renders. The helper fails open for this\n // tool, so the questionnaire is never blocked by Conveyor.\n matcher: \"AskUserQuestion\",\n hooks: [{ type: \"command\", command: `node ${JSON.stringify(helperPath)}`, timeout: 30 }],\n },\n {\n // Plan-permission spawns prompt for MCP tools even when they're in\n // permissions.allow — the CLI can't classify them as read-only. A\n // hook allow bypasses the permission engine in every mode. Loose by\n // design: the pod is the sandbox, and planning agents must call\n // update_task etc. The helper answers locally (no socket).\n matcher: \"mcp__.*\",\n hooks: [{ type: \"command\", command: `node ${JSON.stringify(helperPath)}`, timeout: 30 }],\n },\n ],\n PostToolUse: [\n {\n matcher: \"*\",\n hooks: [{ type: \"command\", command: `node ${JSON.stringify(helperPath)}` }],\n },\n ],\n },\n };\n await writeFile(settingsPath, JSON.stringify(settings, null, 2), \"utf8\");\n return { settingsPath, helperPath };\n}\n","import { access, stat } from \"node:fs/promises\";\n\n/**\n * Result of awaiting the entrypoint's background git preparation.\n *\n * - `\"ready\"` — the ready marker appeared; the task repo is up to date.\n * - `\"failed\"` — the failed marker appeared; git preparation errored (stale\n * image, fetch/checkout/clone failure). The caller must NOT\n * operate on the repo.\n * - `\"timeout\"` — neither marker appeared before the deadline.\n * - `\"not-gated\"` — no marker path is configured (GitHub Codespaces / local),\n * so this environment does not gate on the bash git block.\n */\nexport type GitReadyState = \"ready\" | \"failed\" | \"timeout\" | \"not-gated\";\n\nexport interface AwaitGitReadyOptions {\n /** Path to the ready marker. Defaults to `CONVEYOR_GIT_READY_MARKER` env. */\n markerPath?: string;\n /** Path to the failed marker. Defaults to `CONVEYOR_GIT_FAILED_MARKER` env\n * then `/workspaces/.conveyor-git-failed`. */\n failedPath?: string;\n /** Overall deadline. Defaults to ~10m to match the entrypoint's historical\n * fail-loud provision window. */\n timeoutMs?: number;\n /** Poll interval. Defaults to 200ms. */\n pollMs?: number;\n /** Optional log sink for progress messages. */\n onLog?: (msg: string) => void;\n}\n\nconst DEFAULT_FAILED_PATH = \"/workspaces/.conveyor-git-failed\";\nconst DEFAULT_TIMEOUT_MS = 600_000;\nconst DEFAULT_POLL_MS = 200;\n\nasync function fileExists(path: string): Promise<boolean> {\n try {\n await access(path);\n // A directory would never be our marker file; stat guards against a stale\n // dir of the same name from a prior pod on the baked image.\n const s = await stat(path);\n return s.isFile();\n } catch {\n return false;\n }\n}\n\n/**\n * Block until the pod entrypoint's backgrounded git preparation writes either\n * the ready or the failed marker.\n *\n * The v3 pod entrypoint launches `conveyor-agent` immediately (so the card\n * lights up) while `prepare_workspace_git` runs in the background. It exports\n * `CONVEYOR_GIT_READY_MARKER` and writes exactly one of the ready/failed\n * markers on completion. This helper is the agent-side gate: Claude must not\n * spawn on a stale branch, and setup/start scripts need the repo present.\n *\n * When no marker path is configured (GitHub Codespaces / local), returns\n * `\"not-gated\"` immediately so those environments keep their own git-sync\n * fallback (session-runner phase 3.5, guarded by `CONVEYOR_GIT_READY !== \"1\"`).\n *\n * Never throws — always resolves to a `GitReadyState`.\n */\nexport function awaitGitReady(opts: AwaitGitReadyOptions = {}): Promise<GitReadyState> {\n const markerPath = opts.markerPath ?? process.env.CONVEYOR_GIT_READY_MARKER;\n if (!markerPath) {\n return Promise.resolve(\"not-gated\");\n }\n const failedPath =\n opts.failedPath ?? process.env.CONVEYOR_GIT_FAILED_MARKER ?? DEFAULT_FAILED_PATH;\n const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const pollMs = opts.pollMs ?? DEFAULT_POLL_MS;\n\n opts.onLog?.(`waiting for workspace git (marker=${markerPath})`);\n return pollForMarkers(markerPath, failedPath, timeoutMs, pollMs, opts.onLog);\n}\n\nasync function pollForMarkers(\n markerPath: string,\n failedPath: string,\n timeoutMs: number,\n pollMs: number,\n onLog?: (msg: string) => void,\n): Promise<GitReadyState> {\n const deadline = Date.now() + timeoutMs;\n // Loop: check ready first, then failed, then deadline. Checking ready first\n // means that if the background writer somehow set both (it never should), the\n // benign \"ready\" wins over the destructive \"failed\".\n for (;;) {\n if (await fileExists(markerPath)) {\n onLog?.(\"workspace git ready\");\n return \"ready\";\n }\n if (await fileExists(failedPath)) {\n onLog?.(\"workspace git preparation failed (marker present)\");\n return \"failed\";\n }\n if (Date.now() >= deadline) {\n onLog?.(`workspace git not ready after ${timeoutMs}ms — giving up`);\n return \"timeout\";\n }\n await new Promise((resolve) => {\n setTimeout(resolve, pollMs);\n });\n }\n}\n","import { rm } from \"node:fs/promises\";\nimport type { BootstrapBundle } from \"../../setup/bootstrap-bundle-types.js\";\nimport { flushPendingChanges, restoreWipSnapshot } from \"../git-utils.js\";\nimport { dumpPostgresIfPresent } from \"./pg-dump.js\";\nimport { selectRestoreSource } from \"./restore-precedence.js\";\nimport { buildSnapshotTar, extractSnapshotTar, type SnapshotTarResult } from \"./snapshot-tar.js\";\nimport { downloadSnapshotToTemp, putSnapshotToGcs } from \"./snapshot-transfer.js\";\n\nexport { SNAPSHOT_CAPTURED_AT_HEADER } from \"./snapshot-transfer.js\";\n\nexport interface CaptureContext {\n cwd: string;\n branch: string;\n snapshotUploadUrl?: string;\n refreshToken?: () => Promise<string | undefined>;\n wipMessage?: string;\n /** Path to a pre-built postgres dump OUTSIDE cwd (see pg-dump.ts) that the\n * GCS tar should carry under its fixed in-archive name. */\n pgDumpPath?: string;\n /** Force the GCS PUT even when the tar is empty (sizeBytes === 0). Used by the\n * sleep FINALIZE path so `snapshotAt` is stamped and the reconciler's\n * teardown confirm lands immediately — an empty workspace is a valid (empty)\n * snapshot; on wake the restore's manifest check falls back to a clean\n * checkout. The periodic path leaves this false so a racing empty capture\n * never clobbers a good snapshot. */\n forceUpload?: boolean;\n}\n\nexport interface SnapshotArtifact {\n fileCount: number;\n deletionCount: number;\n sizeBytes: number;\n gcsUploaded: boolean;\n wipPushed: boolean;\n /** Whether this capture bundled a postgres dump into the GCS artifact. */\n pgDumped: boolean;\n}\n\nexport interface RestoreResult {\n source: \"gcs\" | \"wip\" | \"clean\";\n fileCount?: number;\n}\n\nlet periodicTimer: ReturnType<typeof setInterval> | null = null;\n\n/** The in-flight periodic capture, shared as a PROMISE so finalizeForSleep can\n * await it — a boolean guard only prevented overlap, it could not stop a slow\n * pre-finalize capture from PUTting a stale tar AFTER the finalize PUT. */\nlet inFlightCapture: Promise<SnapshotArtifact> | null = null;\n\n/** Serializes GCS PUTs process-wide: every upload (periodic tick, session\n * runner flush, finalize) waits for the previous one, so two captures can\n * never land on the fixed per-workspace GCS object out of order. */\nlet inFlightGcsUpload: Promise<GcsUploadResult> | null = null;\n\nexport interface GcsUploadResult {\n uploaded: boolean;\n fileCount: number;\n deletionCount: number;\n sizeBytes: number;\n pgDumped: boolean;\n}\n\nconst EMPTY_GCS_RESULT: GcsUploadResult = {\n uploaded: false,\n fileCount: 0,\n deletionCount: 0,\n sizeBytes: 0,\n pgDumped: false,\n};\n\nasync function doUploadSnapshotToGcs(\n cwd: string,\n uploadUrl: string | undefined,\n opts?: { pgDumpPath?: string; forceUpload?: boolean },\n): Promise<GcsUploadResult> {\n let tarResult: SnapshotTarResult;\n try {\n tarResult = await buildSnapshotTar(cwd, { pgDumpPath: opts?.pgDumpPath });\n } catch {\n // Never PUT anything on a failed build — the GCS path is fixed per\n // workspace, so a bogus upload would clobber the last good snapshot.\n return EMPTY_GCS_RESULT;\n }\n\n try {\n // Normally skip the PUT for an empty tar (nothing changed) so a periodic\n // capture never clobbers a good snapshot. The finalize path forces it so\n // `snapshotAt` is stamped and teardown confirms without waiting the cap.\n const uploaded =\n (opts?.forceUpload || tarResult.sizeBytes > 0) && uploadUrl\n ? await putSnapshotToGcs(uploadUrl, tarResult)\n : false;\n return {\n uploaded,\n fileCount: tarResult.fileCount,\n deletionCount: tarResult.deletionCount,\n sizeBytes: tarResult.sizeBytes,\n pgDumped: Boolean(opts?.pgDumpPath),\n };\n } finally {\n await tarResult.cleanup();\n }\n}\n\n/**\n * The GCS sink on its own: assemble the snapshot tar (the single capture\n * path) and PUT it to the capability URL. Exposed so a runner whose git-tier\n * flush is driven elsewhere (SessionRunner's periodic flushAllPendingWork)\n * can add the GCS sink to the SAME trigger instead of running a second,\n * racing snapshotter. Calls are serialized: a later capture always PUTs\n * after any earlier in-flight one has settled.\n */\nexport async function uploadSnapshotToGcs(\n cwd: string,\n uploadUrl: string | undefined,\n opts?: { pgDumpPath?: string; forceUpload?: boolean },\n): Promise<GcsUploadResult> {\n const previous = inFlightGcsUpload;\n const run = (async () => {\n if (previous) await previous.catch(() => {});\n return doUploadSnapshotToGcs(cwd, uploadUrl, opts);\n })();\n inFlightGcsUpload = run;\n try {\n return await run;\n } finally {\n if (inFlightGcsUpload === run) inFlightGcsUpload = null;\n }\n}\n\nexport async function captureSnapshot(ctx: CaptureContext): Promise<SnapshotArtifact> {\n // GCS failure is non-fatal; the wip push below still preserves this\n // generation.\n const gcs = await uploadSnapshotToGcs(ctx.cwd, ctx.snapshotUploadUrl, {\n pgDumpPath: ctx.pgDumpPath,\n forceUpload: ctx.forceUpload,\n });\n\n const wipResult = await flushPendingChanges(ctx.cwd, {\n wipMessage: ctx.wipMessage ?? \"WIP: WorkPreservation periodic snapshot\",\n refreshToken: ctx.refreshToken,\n });\n\n return {\n fileCount: gcs.fileCount,\n deletionCount: gcs.deletionCount,\n sizeBytes: gcs.sizeBytes,\n gcsUploaded: gcs.uploaded,\n wipPushed: wipResult.committed || wipResult.pushed,\n pgDumped: gcs.pgDumped,\n };\n}\n\nexport function startPeriodic(intervalMs: number, ctx: CaptureContext): void {\n stop();\n periodicTimer = setInterval(() => {\n if (inFlightCapture) return;\n const run = captureSnapshot(ctx);\n inFlightCapture = run;\n void run\n .catch(() => {})\n .finally(() => {\n if (inFlightCapture === run) inFlightCapture = null;\n });\n }, intervalMs);\n}\n\nexport function stop(): void {\n if (periodicTimer) {\n clearInterval(periodicTimer);\n periodicTimer = null;\n }\n}\n\nexport async function finalizeForSleep(ctx: CaptureContext): Promise<SnapshotArtifact> {\n stop();\n // Await any in-flight periodic capture BEFORE capturing: both PUT the same\n // fixed GCS object, and a slow pre-finalize upload landing after the\n // finalize upload would leave a stale tar as the \"confirmed\" snapshot.\n if (inFlightCapture) await inFlightCapture.catch(() => {});\n\n const dump = await dumpPostgresIfPresent();\n try {\n const artifact = await captureSnapshot({\n ...ctx,\n pgDumpPath: dump.path,\n wipMessage: ctx.wipMessage ?? \"WIP: WorkPreservation sleep finalize snapshot\",\n // Always stamp snapshotAt on sleep — even an empty workspace must confirm\n // the finalize so teardown doesn't wait out the reconciler's cap.\n forceUpload: true,\n });\n return { ...artifact, pgDumped: dump.dumped };\n } finally {\n // The dump lives in os.tmpdir (never cwd — a dump inside the worktree\n // would ride the wip stash's `git add -A` to GitHub); remove it once the\n // tar has been assembled.\n if (dump.path) await rm(dump.path, { force: true }).catch(() => {});\n }\n}\n\n/**\n * Restore precedence at boot: GCS snapshot (tracked+untracked+deletions),\n * else the conveyor-wip ref, else a clean checkout. Accepts the narrow slice\n * of the bundle it reads so v3 pods can call it from env-derived values\n * (CONVEYOR_SNAPSHOT_URL + the task branch) as well as from a full bundle.\n *\n * GCS is only authoritative when the archive's manifest HEAD matches the\n * current clone (checked BEFORE any tree mutation) — a stale or invalid\n * snapshot leaves the tree untouched and falls through to the wip ref, whose\n * own parent-HEAD guard handles staleness.\n */\nexport async function restoreOnBoot(\n bundle: Pick<BootstrapBundle, \"snapshotUrl\"> & {\n gitPlan: Pick<BootstrapBundle[\"gitPlan\"], \"branch\">;\n },\n cwd: string,\n): Promise<RestoreResult> {\n let gcsAvailable = false;\n let gcsFileCount: number | undefined;\n\n if (bundle.snapshotUrl) {\n // Streamed to disk — never hold the whole archive in memory.\n const tmpTar = await downloadSnapshotToTemp(bundle.snapshotUrl);\n if (tmpTar) {\n try {\n const result = await extractSnapshotTar(cwd, tmpTar);\n // Success is EXTRACTION success, not a non-zero deletion count — a\n // valid snapshot with zero files/deletions is still authoritative.\n if (result.status === \"extracted\") {\n gcsAvailable = true;\n gcsFileCount = result.filesExtracted;\n }\n } catch {\n gcsAvailable = false;\n } finally {\n await rm(tmpTar, { force: true }).catch(() => {});\n }\n }\n }\n\n const wipRestoreResult = gcsAvailable ? \"none\" : restoreWipSnapshot(cwd, bundle.gitPlan.branch);\n const source = selectRestoreSource({ gcsAvailable, wipRestoreResult });\n return source === \"gcs\" ? { source, fileCount: gcsFileCount } : { source };\n}\n","import { execSync } from \"node:child_process\";\nimport { randomUUID } from \"node:crypto\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\n\n/**\n * Fixed IN-ARCHIVE name for the postgres dump inside the snapshot tar. The\n * dump file itself NEVER lives in the workspace cwd: it is written to\n * os.tmpdir() and injected into the tar explicitly, so the git tier's\n * `git add -A` wip stash can never pick it up and push a full DB dump to the\n * conveyor-wip ref on GitHub.\n */\nexport const PG_DUMP_FILENAME = \".conveyor-pgdump.sql\";\n\n/** Injectable exec seam so restore/dump behavior is testable without a live\n * postgres. Matches execSync's (command, options) shape. */\nexport type ExecRunner = (command: string, options?: Parameters<typeof execSync>[1]) => unknown;\n\ninterface PgConnectionOpts {\n host?: string;\n port?: number;\n db?: string;\n}\n\nfunction connectionDefaults(opts: PgConnectionOpts): Required<PgConnectionOpts> {\n return {\n host: opts.host ?? \"localhost\",\n port: opts.port ?? 5432,\n db: opts.db ?? \"conveyor\",\n };\n}\n\nexport function buildPgDumpCommand(opts: PgConnectionOpts & { outputPath: string }): string {\n const { host, port, db } = connectionDefaults(opts);\n return `pg_dump -h ${host} -p ${port} -U postgres ${db} -f ${JSON.stringify(\n opts.outputPath,\n )} --no-owner --no-privileges`;\n}\n\nexport function buildPsqlRestoreCommand(opts: PgConnectionOpts & { dumpPath: string }): string {\n const { host, port, db } = connectionDefaults(opts);\n return `psql -h ${host} -p ${port} -U postgres -d ${db} -f ${JSON.stringify(opts.dumpPath)}`;\n}\n\nfunction hasPostgresDep(): boolean {\n return (process.env.CONVEYOR_DEPS ?? \"\")\n .split(\",\")\n .map((dep) => dep.trim())\n .includes(\"postgresql\");\n}\n\nfunction execErrorDetail(err: unknown): string {\n const withStreams = err as { message?: string; stderr?: Buffer | string };\n const stderr =\n withStreams.stderr instanceof Buffer\n ? withStreams.stderr.toString(\"utf8\").trim()\n : typeof withStreams.stderr === \"string\"\n ? withStreams.stderr.trim()\n : \"\";\n const message = withStreams.message ?? String(err);\n return stderr ? `${message} — stderr: ${stderr}` : message;\n}\n\n/**\n * Dump the postgres sidecar (when `CONVEYOR_DEPS` includes `postgresql`) to a\n * unique path under os.tmpdir() — deliberately OUTSIDE the workspace so the\n * dump can never ride the git tier to GitHub. Failures are logged with\n * pg_dump's stderr and surfaced as `dumped: false`; never throws.\n */\nexport function dumpPostgresIfPresent(\n exec: ExecRunner = execSync,\n): Promise<{ dumped: boolean; path?: string }> {\n if (!hasPostgresDep()) return Promise.resolve({ dumped: false });\n\n const outputPath = path.join(tmpdir(), `conveyor-pgdump-${randomUUID()}.sql`);\n try {\n exec(buildPgDumpCommand({ outputPath }), {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n timeout: 60_000,\n });\n return Promise.resolve({ dumped: true, path: outputPath });\n } catch (err) {\n process.stderr.write(`[conveyor-agent] pg_dump failed: ${execErrorDetail(err)}\\n`);\n return Promise.resolve({ dumped: false });\n }\n}\n\n/**\n * Best-effort apply of a restored dump file via psql, only when the pod\n * actually runs the postgres sidecar (`CONVEYOR_DEPS` includes `postgresql`).\n * Logged on failure; never throws. Callers own deleting `dumpPath`.\n */\nexport function applyPgDumpIfConfigured(dumpPath: string, exec: ExecRunner = execSync): boolean {\n if (!hasPostgresDep()) return false;\n try {\n exec(buildPsqlRestoreCommand({ dumpPath }), {\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n timeout: 120_000,\n });\n process.stderr.write(\"[conveyor-agent] Restored postgres state from snapshot pg dump\\n\");\n return true;\n } catch (err) {\n process.stderr.write(`[conveyor-agent] psql dump restore failed: ${execErrorDetail(err)}\\n`);\n return false;\n }\n}\n","export type RestoreSource = \"gcs\" | \"wip\" | \"clean\";\n\nexport interface RestoreProbe {\n gcsAvailable: boolean;\n wipRestoreResult: \"applied\" | \"stale\" | \"none\" | \"failed\";\n}\n\nexport function selectRestoreSource(probe: RestoreProbe): RestoreSource {\n if (probe.gcsAvailable) return \"gcs\";\n if (probe.wipRestoreResult === \"applied\") return \"wip\";\n return \"clean\";\n}\n","import { execSync } from \"node:child_process\";\nimport { createReadStream, createWriteStream, mkdtempSync } from \"node:fs\";\nimport { copyFile, mkdtemp, rm, stat, writeFile } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { pipeline } from \"node:stream/promises\";\nimport { createGzip } from \"node:zlib\";\nimport * as tar from \"tar\";\nimport { applyPgDumpIfConfigured, PG_DUMP_FILENAME, type ExecRunner } from \"./pg-dump.js\";\nimport { planSnapshotFiles, type GitSurface } from \"./snapshot-artifact.js\";\n\n/**\n * In-archive manifest binding a snapshot to the HEAD it was captured on and\n * carrying the deletion list. Lives ONLY inside the tar (assembled in a temp\n * staging dir) — never written into the workspace tree.\n */\nexport const SNAPSHOT_MANIFEST_NAME = \".conveyor-snapshot-manifest.json\";\n\nexport interface SnapshotManifest {\n /** `git rev-parse HEAD` at capture time — restore refuses to extract over a\n * different HEAD (a stale delta over a newer clone clobbers newer work). */\n head: string;\n /** Repo-relative paths restore must delete after extraction. */\n deletions: string[];\n /** Epoch ms when the tar was BUILT (not uploaded) — also sent as the\n * `x-snapshot-captured-at` header so the API can refuse out-of-order PUTs. */\n capturedAt: number;\n /** Whether the archive carries a postgres dump entry (PG_DUMP_FILENAME). */\n pgDump: boolean;\n}\n\n// git status --porcelain=v1 -z default maxBuffer (1MB) is too small for large\n// dirty trees; 64MB of NUL-delimited paths covers any realistic worktree.\nconst STATUS_MAX_BUFFER = 64 * 1024 * 1024;\n\n/**\n * Parse `git status --porcelain=v1 -z -uall` output. NUL-delimited and\n * unquoted, so unicode/space/quote filenames arrive verbatim (the LF-based\n * parse broke them via C-style quoting). Rename/copy entries deliver TWO\n * NUL-separated fields — `XY <new>\\0<orig>\\0`; the NEW path is included and,\n * for renames, the ORIGINAL path joins the deletion list (it exists in HEAD\n * but no longer on disk).\n */\nexport function parseStatusPorcelainZ(raw: string): { includes: string[]; deletions: string[] } {\n const includes: string[] = [];\n const deletions: string[] = [];\n const tokens = raw.split(\"\\0\");\n for (let i = 0; i < tokens.length; i++) {\n const token = tokens[i];\n if (!token || token.length < 4) continue;\n const x = token[0];\n const y = token[1];\n const filePath = token.slice(3);\n if (x === \"R\" || x === \"C\") {\n const origPath = tokens[++i];\n if (x === \"R\" && origPath) deletions.push(origPath);\n }\n // Ignored entries (only present with --ignored) never enter the plan.\n if (x === \"!\") continue;\n // The file is absent from the worktree when the worktree (Y) column is D\n // (covers ` D`, `AD`, `MD`, `RD`, `DD`), or on a staged-only deletion\n // (`D ` — deleted from index, gone from disk, worktree column blank).\n const missingFromWorktree = y === \"D\" || (x === \"D\" && y === \" \");\n if (missingFromWorktree) deletions.push(filePath);\n else includes.push(filePath);\n }\n return { includes, deletions };\n}\n\n/** Single `git status --porcelain=v1 -z -uall` call feeding both GitSurface\n * views — includes and deletions must come from one consistent status read. */\nfunction realGitSurface(cwd: string): GitSurface {\n let cached: { includes: string[]; deletions: string[] } | null = null;\n const load = (): { includes: string[]; deletions: string[] } => {\n if (!cached) {\n const out = execSync(\"git status --porcelain=v1 -z -uall\", {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n maxBuffer: STATUS_MAX_BUFFER,\n }).toString(\"utf8\");\n cached = parseStatusPorcelainZ(out);\n }\n return cached;\n };\n return {\n trackedAndUntracked: () => load().includes,\n deletedSinceHead: () => load().deletions,\n };\n}\n\nfunction gitHead(cwd: string): string | null {\n try {\n return (\n execSync(\"git rev-parse HEAD\", { cwd, stdio: [\"ignore\", \"pipe\", \"ignore\"] })\n .toString()\n .trim() || null\n );\n } catch {\n return null;\n }\n}\n\nexport interface SnapshotTarResult {\n /** Gzipped tar on disk inside a private temp staging dir. Callers stream it\n * (never buffer the whole archive) and MUST call cleanup() when done. */\n tarPath: string;\n sizeBytes: number;\n fileCount: number;\n deletionCount: number;\n /** Epoch ms the tar was built — the capture generation marker. */\n capturedAt: number;\n cleanup(): Promise<void>;\n}\n\n/**\n * Assemble the snapshot archive: manifest (+ optional pg dump) staged in a\n * temp dir, worktree files appended from the repo. The archive is written to\n * disk and returned as a path so upload can stream it — the tar is never\n * held in memory (pods have an OOM history; a single whole-tar Buffer was\n * up to 500MB).\n */\nexport async function buildSnapshotTar(\n cwd: string,\n opts?: { pgDumpPath?: string },\n): Promise<SnapshotTarResult> {\n const staging = await mkdtemp(path.join(tmpdir(), \"conveyor-snapshot-\"));\n const cleanup = async (): Promise<void> => {\n await rm(staging, { recursive: true, force: true }).catch(() => {});\n };\n\n try {\n const plan = planSnapshotFiles(realGitSurface(cwd));\n const head = gitHead(cwd);\n if (!head) throw new Error(\"cannot snapshot a repo without a resolvable HEAD\");\n const capturedAt = Date.now();\n\n const manifest: SnapshotManifest = {\n head,\n deletions: plan.deletions,\n capturedAt,\n pgDump: Boolean(opts?.pgDumpPath),\n };\n await writeFile(path.join(staging, SNAPSHOT_MANIFEST_NAME), JSON.stringify(manifest), \"utf8\");\n\n const stagedEntries = [SNAPSHOT_MANIFEST_NAME];\n if (opts?.pgDumpPath) {\n // The dump lives OUTSIDE cwd (see pg-dump.ts); it enters the archive via\n // the staging dir under its fixed in-archive name, never via the repo.\n await copyFile(opts.pgDumpPath, path.join(staging, PG_DUMP_FILENAME));\n stagedEntries.push(PG_DUMP_FILENAME);\n }\n\n // tar.replace can't operate on a compressed archive, so: create the\n // uncompressed tar from the staging entries, append the repo files with\n // cwd = the repo, then gzip file-to-file (all streaming).\n const rawTarPath = path.join(staging, \"snapshot.tar\");\n await tar.create({ cwd: staging, file: rawTarPath, portable: true }, stagedEntries);\n if (plan.include.length > 0) {\n await tar.replace({ file: rawTarPath, cwd, portable: true }, plan.include);\n }\n\n const tarPath = path.join(staging, \"snapshot.tar.gz\");\n await pipeline(createReadStream(rawTarPath), createGzip(), createWriteStream(tarPath));\n await rm(rawTarPath, { force: true });\n\n const { size } = await stat(tarPath);\n return {\n tarPath,\n sizeBytes: size,\n fileCount: plan.include.length,\n deletionCount: plan.deletions.length,\n capturedAt,\n cleanup,\n };\n } catch (err) {\n await cleanup();\n throw err;\n }\n}\n\nexport type SnapshotExtractResult =\n | {\n status: \"extracted\";\n filesExtracted: number;\n deletionsApplied: number;\n pgDumpApplied: boolean;\n }\n /** Manifest HEAD differs from the current clone's HEAD — extracting would\n * smear an old delta over newer commits. The tree is NOT touched. */\n | { status: \"stale-head\"; snapshotHead: string; currentHead: string | null }\n /** Missing/unreadable manifest — not a trustworthy snapshot. Tree untouched. */\n | { status: \"invalid\" };\n\n/** Repo-relative deletion entries must resolve inside the workspace — a\n * malicious/corrupt manifest must never delete outside cwd. */\nfunction isWithinWorkspace(cwd: string, rel: string): boolean {\n if (!rel || path.isAbsolute(rel)) return false;\n const root = path.resolve(cwd);\n const abs = path.resolve(root, rel);\n return abs !== root && abs.startsWith(root + path.sep);\n}\n\n/** Manifest plus (when the archive carried one) the pg dump streamed out to a\n * temp file during the SAME list pass. `cleanup` removes that temp and MUST be\n * called on every path. */\ninterface SnapshotArchiveRead {\n manifest: SnapshotManifest;\n /** Temp path of the streamed pg dump — present only when the archive actually\n * carried a `PG_DUMP_FILENAME` entry. The dump is never written into cwd. */\n pgDumpPath?: string;\n cleanup(): Promise<void>;\n}\n\n/**\n * Single `tar.list` pass over the archive: parse the manifest AND, when the\n * archive carries a pg dump entry, stream it to a temp file. This folds what\n * used to be two separate list passes (a manifest-only read plus a later\n * pg-dump-only read in restore) into one, leaving `extractSnapshotTar` at two\n * total archive scans (this list + the extract) instead of three. The temp dir\n * is created lazily — only when a dump entry is actually seen.\n */\nasync function readSnapshotArchive(tarPath: string): Promise<SnapshotArchiveRead | null> {\n let manifestRaw: Buffer | null = null;\n let pgDumpDir: string | null = null;\n let pgDumpPath: string | undefined;\n let pgDumpWritten: Promise<void> = Promise.resolve();\n const cleanup = async (): Promise<void> => {\n if (pgDumpDir) await rm(pgDumpDir, { recursive: true, force: true }).catch(() => {});\n };\n\n try {\n await tar.list({\n file: tarPath,\n onReadEntry: (entry) => {\n if (entry.path === SNAPSHOT_MANIFEST_NAME) {\n const chunks: Buffer[] = [];\n entry.on(\"data\", (chunk: Buffer) => chunks.push(chunk));\n entry.on(\"end\", () => {\n manifestRaw = Buffer.concat(chunks);\n });\n } else if (entry.path === PG_DUMP_FILENAME) {\n pgDumpDir = mkdtempSync(path.join(tmpdir(), \"conveyor-pgdump-restore-\"));\n pgDumpPath = path.join(pgDumpDir, \"dump.sql\");\n const dest = createWriteStream(pgDumpPath);\n pgDumpWritten = new Promise<void>((resolve, reject) => {\n dest.on(\"finish\", () => resolve());\n dest.on(\"error\", reject);\n });\n entry.pipe(dest);\n }\n },\n });\n await pgDumpWritten;\n } catch {\n await cleanup();\n return null;\n }\n\n if (!manifestRaw) {\n await cleanup();\n return null;\n }\n try {\n const parsed = JSON.parse((manifestRaw as Buffer).toString(\"utf8\")) as SnapshotManifest;\n if (typeof parsed.head !== \"string\" || !parsed.head) {\n await cleanup();\n return null;\n }\n return {\n manifest: {\n head: parsed.head,\n deletions: Array.isArray(parsed.deletions) ? parsed.deletions : [],\n capturedAt: typeof parsed.capturedAt === \"number\" ? parsed.capturedAt : 0,\n pgDump: parsed.pgDump === true,\n },\n ...(pgDumpPath ? { pgDumpPath } : {}),\n cleanup,\n };\n } catch {\n await cleanup();\n return null;\n }\n}\n\n/**\n * Extract a snapshot archive (path to a .tar.gz on disk) into the workspace.\n * Order matters: the manifest is read and the HEAD binding checked BEFORE any\n * tree mutation — a stale or invalid snapshot leaves the tree byte-identical.\n * A valid snapshot with zero files/deletions is still a SUCCESS (a clean tree\n * at capture time is a legitimate snapshot, not a failure).\n */\nexport async function extractSnapshotTar(\n cwd: string,\n tarPath: string,\n opts?: { pgExec?: ExecRunner },\n): Promise<SnapshotExtractResult> {\n // One list pass reads the manifest AND streams out any pg dump — so the\n // restore below applies it without re-scanning the archive.\n const read = await readSnapshotArchive(tarPath);\n if (!read) return { status: \"invalid\" };\n\n try {\n const { manifest, pgDumpPath } = read;\n const currentHead = gitHead(cwd);\n if (manifest.head !== currentHead) {\n return { status: \"stale-head\", snapshotHead: manifest.head, currentHead };\n }\n\n let filesExtracted = 0;\n await tar.extract({\n file: tarPath,\n cwd,\n filter: (entryPath) => {\n // Manifest and pg dump are archive metadata — they never land in cwd\n // (a dump in the worktree would ride the next wip stash to GitHub).\n if (entryPath === SNAPSHOT_MANIFEST_NAME || entryPath === PG_DUMP_FILENAME) return false;\n filesExtracted++;\n return true;\n },\n });\n\n let deletionsApplied = 0;\n for (const rel of manifest.deletions) {\n if (typeof rel !== \"string\" || !isWithinWorkspace(cwd, rel)) continue;\n await rm(path.resolve(cwd, rel), { recursive: true, force: true });\n deletionsApplied++;\n }\n\n // Apply the dump captured during the read pass (no second archive scan).\n // applyPgDumpIfConfigured is a no-op unless the postgres sidecar is\n // configured, so the gate matches the old restorePgDump path.\n const pgDumpApplied =\n manifest.pgDump && pgDumpPath ? applyPgDumpIfConfigured(pgDumpPath, opts?.pgExec) : false;\n\n return { status: \"extracted\", filesExtracted, deletionsApplied, pgDumpApplied };\n } finally {\n await read.cleanup();\n }\n}\n\n/** Test seam: read a manifest back out of an archive without extracting. */\nexport async function readSnapshotManifest(tarPath: string): Promise<SnapshotManifest | null> {\n const read = await readSnapshotArchive(tarPath);\n if (!read) return null;\n await read.cleanup();\n return read.manifest;\n}\n\n/** Test seam: list entry paths in an archive without extracting. */\nexport async function listSnapshotEntries(tarPath: string): Promise<string[]> {\n const entries: string[] = [];\n await tar.list({\n file: tarPath,\n onReadEntry: (entry) => {\n entries.push(String(entry.path));\n },\n });\n return entries;\n}\n","/**\n * Pure planning logic for the WorkPreservation source-tree snapshot:\n * tracked + untracked files are included in the archive, while deleted paths\n * are recorded separately for restore-time removal.\n */\n\nexport interface GitSurface {\n trackedAndUntracked(): string[];\n deletedSinceHead(): string[];\n}\n\nexport interface SnapshotFilePlan {\n include: string[];\n deletions: string[];\n}\n\nexport function planSnapshotFiles(git: GitSurface): SnapshotFilePlan {\n const include = git.trackedAndUntracked();\n const includeSet = new Set(include);\n const deletions = [...new Set(git.deletedSinceHead())].filter((path) => !includeSet.has(path));\n return { include, deletions };\n}\n","import { randomUUID } from \"node:crypto\";\nimport { createReadStream, createWriteStream } from \"node:fs\";\nimport { rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport path from \"node:path\";\nimport { Readable } from \"node:stream\";\nimport { pipeline } from \"node:stream/promises\";\nimport type { SnapshotTarResult } from \"./snapshot-tar.js\";\n\n// A hung upload/download must not stall capture forever (which would leave\n// the in-flight promise stuck and silently stop all periodic snapshots).\nexport const SNAPSHOT_HTTP_TIMEOUT_MS = 60_000;\n\n/** Header carrying the tar's BUILD time so the API can refuse to overwrite a\n * newer capture with a slower, older PUT (see snapshot-routes.ts). */\nexport const SNAPSHOT_CAPTURED_AT_HEADER = \"x-snapshot-captured-at\";\n\nexport async function putSnapshotToGcs(\n url: string,\n tarResult: SnapshotTarResult,\n): Promise<boolean> {\n try {\n // Stream the tar file straight into the request body — the archive is\n // never buffered whole in memory (pods have an OOM history; tars can hit\n // the 500MB route cap). `duplex: \"half\"` is required by undici for stream\n // bodies and ignored by runtimes that don't need it.\n const body = Readable.toWeb(createReadStream(tarResult.tarPath)) as ReadableStream;\n const res = await fetch(url, {\n method: \"PUT\",\n headers: {\n \"Content-Type\": \"application/gzip\",\n \"Content-Length\": String(tarResult.sizeBytes),\n [SNAPSHOT_CAPTURED_AT_HEADER]: String(tarResult.capturedAt),\n },\n body,\n duplex: \"half\",\n signal: AbortSignal.timeout(SNAPSHOT_HTTP_TIMEOUT_MS),\n } as RequestInit);\n return res.ok;\n } catch {\n return false;\n }\n}\n\n/**\n * Download a snapshot archive to a temp file, streaming (never buffering the\n * whole tar). Returns the temp path on success, null on any failure — the\n * caller owns removing the file.\n */\nexport async function downloadSnapshotToTemp(url: string): Promise<string | null> {\n const tmpTar = path.join(tmpdir(), `conveyor-snapshot-restore-${randomUUID()}.tar.gz`);\n try {\n const res = await fetch(url, {\n method: \"GET\",\n signal: AbortSignal.timeout(SNAPSHOT_HTTP_TIMEOUT_MS),\n });\n if (!res.ok || !res.body) return null;\n await pipeline(\n Readable.fromWeb(res.body as import(\"node:stream/web\").ReadableStream),\n createWriteStream(tmpTar),\n );\n return tmpTar;\n } catch {\n await rm(tmpTar, { force: true }).catch(() => {});\n return null;\n }\n}\n","// src/types/common.ts\nfunction isCuid(str) {\n return /^c[a-z0-9]{24}$/.test(str);\n}\n\n// src/constants/models.ts\nvar DEFAULT_SONNET_MODEL = \"claude-sonnet-5\";\nvar DEFAULT_OPUS_MODEL = \"claude-opus-4-8\";\nvar DEFAULT_HAIKU_MODEL = \"claude-haiku-4-5-20251001\";\nvar FABLE_MODEL = \"claude-fable-5\";\nvar PREVIOUS_SONNET_MODEL = \"claude-sonnet-4-6\";\nvar RETIRED_SONNET_MODEL = \"claude-sonnet-4-20250514\";\n\n// src/types/project-settings-types.ts\nvar PREVIEW_PORT_DENY_LIST = [5432, 6379, 9200];\nfunction isAllowablePreviewPort(port) {\n if (typeof port !== \"number\" || !Number.isInteger(port)) return false;\n if (port < 1 || port > 65535) return false;\n return !PREVIEW_PORT_DENY_LIST.includes(port);\n}\nfunction sanitizeSessionPreviewPorts(ports) {\n if (!Array.isArray(ports)) return [];\n const seen = /* @__PURE__ */ new Set();\n const out = [];\n for (const raw of ports) {\n if (!raw || typeof raw !== \"object\") continue;\n const portValue = raw.port;\n if (!isAllowablePreviewPort(portValue)) continue;\n if (seen.has(portValue)) continue;\n seen.add(portValue);\n const labelValue = raw.label;\n const visValue = raw.visibility;\n out.push({\n port: portValue,\n ...typeof labelValue === \"string\" ? { label: labelValue } : {},\n ...visValue === \"public\" || visValue === \"private\" ? { visibility: visValue } : {}\n });\n }\n return out;\n}\nfunction resolveAllowedPreviewPorts(sources) {\n const set = /* @__PURE__ */ new Set();\n const add = (p) => {\n if (isAllowablePreviewPort(p)) set.add(p);\n };\n add(sources.taskPreviewPort);\n add(sources.projectPreviewPort);\n if (Array.isArray(sources.sessionPreviewPorts)) {\n for (const entry of sources.sessionPreviewPorts) add(entry?.port);\n }\n return [...set].sort((a, b) => a - b);\n}\nfunction pickPreferredPreviewPort(sources) {\n const fallback = sources.defaultPort ?? 3050;\n if (isAllowablePreviewPort(sources.taskPreviewPort)) return sources.taskPreviewPort;\n const sessionPorts = sanitizeSessionPreviewPorts(sources.sessionPreviewPorts);\n const firstSession = sessionPorts[0]?.port;\n if (isAllowablePreviewPort(firstSession)) return firstSession;\n if (isAllowablePreviewPort(sources.projectPreviewPort)) return sources.projectPreviewPort;\n return fallback;\n}\nvar PROJECT_FUNCTION_DEFAULTS = {\n identification: {\n model: DEFAULT_SONNET_MODEL,\n effort: \"low\",\n thinking: { type: \"adaptive\" }\n },\n suggestionHandler: {\n model: DEFAULT_SONNET_MODEL,\n effort: \"high\",\n thinking: { type: \"adaptive\" }\n },\n prReview: {\n model: DEFAULT_SONNET_MODEL,\n effort: \"low\",\n thinking: { type: \"adaptive\" }\n }\n};\nfunction resolveProjectFunctionConfig(settings, functionId) {\n const defaults = PROJECT_FUNCTION_DEFAULTS[functionId];\n const override = settings?.functionSettings?.[functionId];\n return {\n model: override?.model ?? defaults.model,\n effort: override?.effort ?? defaults.effort,\n thinking: override?.thinking ?? defaults.thinking,\n instructions: override?.instructions\n };\n}\nfunction resolveCodeReviewMode(settings) {\n const s = settings ?? {};\n if (s.codeReviewMode) return s.codeReviewMode;\n if (s.codeReviewEnabled === true) return \"blocking\";\n return \"off\";\n}\nfunction resolveGcpEnvResources(settings) {\n const s = settings ?? {};\n if (s.gcpEnvResources) return s.gcpEnvResources;\n if (s.gcpCloudRunServices?.length || s.gcpCloudSqlInstances?.length) {\n return {\n prod: {\n cloudRunServices: s.gcpCloudRunServices,\n cloudSqlInstances: s.gcpCloudSqlInstances\n }\n };\n }\n return {};\n}\n\n// src/types/gcp-types.ts\nvar GCP_ENVS = [\"prod\", \"dev\", \"claudespace\"];\n\n// src/types/agent-project-types.ts\nvar TASK_STATUS_ORDER = [\n \"Planning\",\n \"Open\",\n \"InProgress\",\n \"ReviewPR\",\n \"ReviewDev\",\n \"ReviewLive\",\n \"Complete\",\n \"Cancelled\"\n];\n\n// src/types/task-types.ts\nvar CARD_TYPE_VALUES = [\"task\", \"incident\", \"suggestion\", \"ephemeral\"];\nvar UNIFIED_STATUSES = [\n \"Planning\",\n \"Open\",\n \"InProgress\",\n \"ReviewPR\",\n \"ReviewDev\",\n \"ReviewLive\",\n \"Complete\",\n \"Cancelled\"\n];\nvar CARD_TYPE_STATUSES = {\n task: UNIFIED_STATUSES,\n incident: UNIFIED_STATUSES,\n suggestion: UNIFIED_STATUSES,\n // Ephemeral cards (e.g. automated code review) are created past Planning and\n // only ever live in InProgress → Complete/Cancelled, but reuse the unified set\n // so status validation never rejects a shared transition.\n ephemeral: UNIFIED_STATUSES\n};\nfunction validateStatusForType(type, status) {\n return CARD_TYPE_STATUSES[type].includes(status);\n}\n\n// src/types/service-map.ts\nvar ALLOWED_FILE_MIME_TYPES = [\n \"image/png\",\n \"image/jpeg\",\n \"image/gif\",\n \"image/webp\",\n \"application/json\",\n \"text/csv\",\n \"text/plain\",\n \"text/markdown\",\n \"application/pdf\"\n];\nvar MAX_FILE_SIZE_BYTES = 25 * 1024 * 1024;\nvar EMBED_THRESHOLD_IMAGES = 5 * 1024 * 1024;\nvar EMBED_THRESHOLD_TEXT = 2 * 1024 * 1024;\nvar EMBEDDABLE_IMAGE_TYPES = [\n \"image/png\",\n \"image/jpeg\",\n \"image/gif\",\n \"image/webp\"\n];\nvar EMBEDDABLE_TEXT_TYPES = [\n \"text/plain\",\n \"text/csv\",\n \"text/markdown\",\n \"application/json\"\n];\nfunction isEmbeddableFile(mimeType, fileSize) {\n if (EMBEDDABLE_IMAGE_TYPES.some((t) => mimeType === t)) {\n return fileSize <= EMBED_THRESHOLD_IMAGES;\n }\n if (EMBEDDABLE_TEXT_TYPES.some((t) => mimeType === t)) {\n return fileSize <= EMBED_THRESHOLD_TEXT;\n }\n return false;\n}\n\n// src/types/connection-state.ts\nvar IDLE_HEARTBEAT_MS = 90 * 1e3;\nvar STRANDED_RUNNER_STATUSES = /* @__PURE__ */ new Set([\"stalled_heartbeat\", \"stranded\", \"crashed\"]);\nfunction deriveConnectionState(inputs, now = Date.now()) {\n const heartbeatAgeMs = inputs.lastHeartbeatAt ? Math.max(0, now - new Date(inputs.lastHeartbeatAt).getTime()) : null;\n if (inputs.deletionRequestedAt) {\n return { state: \"pendingDeletion\", heartbeatAgeMs };\n }\n const status = inputs.codespaceStatus;\n if (status === \"Deleted\") {\n return { state: \"deleted\", heartbeatAgeMs };\n }\n if (status === \"Creating\" || inputs.podStatus === \"Creating\") {\n return { state: \"creating\", heartbeatAgeMs };\n }\n if (inputs.agentRunnerStatus && STRANDED_RUNNER_STATUSES.has(inputs.agentRunnerStatus)) {\n return { state: \"stranded\", heartbeatAgeMs };\n }\n if (status === \"Stopped\" || inputs.podStatus === \"Stopped\" || inputs.podStatus === \"Sleeping\") {\n return { state: \"stopped\", heartbeatAgeMs };\n }\n if (status !== \"Running\" && !inputs.codespaceId && !inputs.podName) {\n return { state: \"none\", heartbeatAgeMs };\n }\n if (heartbeatAgeMs !== null && heartbeatAgeMs >= IDLE_HEARTBEAT_MS) {\n return { state: \"idle\", heartbeatAgeMs };\n }\n if (status === \"Running\") {\n return { state: \"active\", heartbeatAgeMs };\n }\n return { state: \"none\", heartbeatAgeMs };\n}\nfunction formatHeartbeatAge(ms) {\n if (ms === null) return \"never\";\n const sec = Math.floor(ms / 1e3);\n if (sec < 60) return `${sec}s ago`;\n const min = Math.floor(sec / 60);\n if (min < 60) return `${min}m ago`;\n const hr = Math.floor(min / 60);\n if (hr < 24) return `${hr}h ago`;\n const days = Math.floor(hr / 24);\n return `${days}d ago`;\n}\n\n// src/types/agent-session-requests.ts\nimport { z } from \"zod\";\nvar AgentHeartbeatSchema = z.object({\n sessionId: z.string().optional(),\n timestamp: z.string(),\n status: z.enum([\"active\", \"idle\", \"building\"]),\n currentAction: z.string().optional()\n});\nvar CreatePRInputSchema = z.object({\n title: z.string().min(1),\n body: z.string(),\n head: z.string().optional(),\n base: z.string().optional()\n});\nvar PostToChatInputSchema = z.object({\n message: z.string().min(1),\n type: z.enum([\"message\", \"question\", \"update\"]).optional().default(\"message\")\n});\nvar GetTaskContextRequestSchema = z.object({\n sessionId: z.string(),\n includeHistory: z.boolean().optional().default(false)\n});\nvar GetChatMessagesRequestSchema = z.object({\n sessionId: z.string(),\n limit: z.number().int().positive().optional().default(50),\n offset: z.number().int().nonnegative().optional().default(0)\n});\nvar GetTaskFilesRequestSchema = z.object({\n sessionId: z.string()\n});\nvar GetTaskFileRequestSchema = z.object({\n sessionId: z.string(),\n fileId: z.string()\n});\nvar GetTaskRequestSchema = z.object({\n sessionId: z.string(),\n taskSlugOrId: z.string()\n});\nvar GetCliHistoryRequestSchema = z.object({\n sessionId: z.string(),\n limit: z.number().int().positive().optional().default(100),\n source: z.enum([\"agent\", \"application\"]).optional()\n});\nvar ListSubtasksRequestSchema = z.object({\n sessionId: z.string()\n});\nvar GetDependenciesRequestSchema = z.object({\n sessionId: z.string()\n});\nvar GetSuggestionsRequestSchema = z.object({\n sessionId: z.string(),\n status: z.string().optional(),\n limit: z.number().int().min(1).max(100).optional()\n});\nvar ListManualTestsRequestSchema = z.object({\n sessionId: z.string()\n});\nvar QueryManualTestsRequestSchema = z.object({\n sessionId: z.string(),\n cardStatuses: z.array(z.string()).optional(),\n testStatuses: z.array(z.enum([\"open\", \"approved\", \"rejected\"])).optional()\n});\nvar PostToChatRequestSchema = PostToChatInputSchema;\nvar CreatePullRequestRequestSchema = CreatePRInputSchema.extend({ sessionId: z.string() });\nvar RequestFileUploadRequestSchema = z.object({\n sessionId: z.string(),\n fileName: z.string().min(1).max(255),\n mimeType: z.string().min(1).max(128),\n fileSize: z.number().int().positive().max(MAX_FILE_SIZE_BYTES)\n});\nvar ConfirmFileUploadRequestSchema = z.object({\n sessionId: z.string(),\n fileId: z.string(),\n title: z.string().max(500).optional()\n});\nvar UpdateTaskStatusRequestSchema = z.object({\n sessionId: z.string(),\n status: z.string(),\n force: z.boolean().optional().default(false)\n});\nvar StoreSessionIdRequestSchema = z.object({\n sessionId: z.string(),\n sdkSessionId: z.string()\n});\nvar SetManualTestsRequestSchema = z.object({\n sessionId: z.string(),\n items: z.array(z.object({ title: z.string().min(1) })).min(1)\n});\nvar EditManualTestRequestSchema = z.object({\n sessionId: z.string(),\n title: z.string().min(1),\n newTitle: z.string().min(1)\n});\nvar RemoveManualTestRequestSchema = z.object({\n sessionId: z.string(),\n title: z.string().min(1)\n});\nvar ApproveManualTestRequestSchema = z.object({\n sessionId: z.string(),\n title: z.string().min(1)\n});\nvar RejectManualTestRequestSchema = z.object({\n sessionId: z.string(),\n title: z.string().min(1),\n reason: z.string().min(1).max(2e3)\n});\nvar TrackSpendingRequestSchema = z.object({\n sessionId: z.string(),\n inputTokens: z.number().int().nonnegative(),\n outputTokens: z.number().int().nonnegative(),\n costUsd: z.number().nonnegative(),\n model: z.string()\n});\nvar HeartbeatRequestSchema = AgentHeartbeatSchema;\nvar SessionStartRequestSchema = z.object({\n sessionId: z.string(),\n agentVersion: z.string(),\n capabilities: z.array(z.string())\n});\nvar SessionStopRequestSchema = z.object({\n sessionId: z.string(),\n reason: z.string().optional()\n});\nvar ConnectAgentRequestSchema = z.object({\n sessionId: z.string()\n});\nvar ReportAgentStatusRequestSchema = z.object({\n sessionId: z.string(),\n status: z.string(),\n /** Why the agent reports this status (e.g. \"user_question\" while an AskUserQuestion questionnaire is pending in the TUI). */\n reason: z.string().optional()\n});\nvar NotifyAgentVersionRequestSchema = z.object({\n sessionId: z.string(),\n agentVersion: z.string()\n});\nvar DiscoveredPortSchema = z.object({\n port: z.number().int().min(1).max(65535),\n label: z.string().min(1).max(64).optional(),\n protocol: z.enum([\"http\", \"tcp\"]).optional(),\n detectedAt: z.string()\n});\nvar ReportDiscoveredPortsRequestSchema = z.object({\n sessionId: z.string(),\n ports: z.array(DiscoveredPortSchema).max(64)\n});\nvar CreateSubtaskRequestSchema = z.object({\n sessionId: z.string(),\n title: z.string().min(1),\n description: z.string().optional(),\n plan: z.string().optional(),\n storyPointValue: z.number().int().positive().optional(),\n ordinal: z.number().int().nonnegative().optional()\n});\nvar UpdateSubtaskRequestSchema = z.object({\n sessionId: z.string(),\n subtaskId: z.string(),\n title: z.string().min(1).optional(),\n description: z.string().optional(),\n plan: z.string().optional(),\n status: z.string().optional(),\n storyPointValue: z.number().int().positive().optional()\n});\nvar DeleteSubtaskRequestSchema = z.object({\n sessionId: z.string(),\n subtaskId: z.string()\n});\nvar GetTaskPropertiesRequestSchema = z.object({\n sessionId: z.string()\n});\nvar GetCumulativeSpendingRequestSchema = z.object({\n sessionId: z.string()\n});\nvar ModelUsageEntrySchema = z.object({\n model: z.string(),\n inputTokens: z.number().nonnegative(),\n outputTokens: z.number().nonnegative(),\n cacheReadInputTokens: z.number().nonnegative(),\n cacheCreationInputTokens: z.number().nonnegative(),\n costUSD: z.number().nonnegative()\n});\nvar GetCumulativeSpendingResponseSchema = z.object({\n totalCostUsd: z.number().nonnegative(),\n modelUsage: z.array(ModelUsageEntrySchema)\n});\nvar UpdateTaskFieldsRequestSchema = z.object({\n sessionId: z.string(),\n plan: z.string().optional(),\n description: z.string().optional()\n});\nvar UpdateTaskPropertiesRequestSchema = z.object({\n sessionId: z.string(),\n title: z.string().optional(),\n storyPointValue: z.number().int().positive().optional(),\n tagIds: z.array(z.string()).optional(),\n tagNames: z.array(z.string()).optional(),\n githubPRUrl: z.string().url().optional(),\n githubBranch: z.string().optional()\n});\nvar ListIconsRequestSchema = z.object({\n sessionId: z.string()\n});\nvar GenerateTaskIconRequestSchema = z.object({\n sessionId: z.string(),\n prompt: z.string().min(1),\n aspectRatio: z.string().optional()\n});\nvar SearchFaIconsRequestSchema = z.object({\n sessionId: z.string(),\n query: z.string().min(1),\n first: z.number().int().positive().optional()\n});\nvar PickFaIconRequestSchema = z.object({\n sessionId: z.string(),\n fontAwesomeId: z.string().min(1),\n fontAwesomeStyle: z.string().optional()\n});\nvar CreateFollowUpTaskRequestSchema = z.object({\n sessionId: z.string(),\n title: z.string().min(1),\n description: z.string().optional(),\n plan: z.string().optional(),\n storyPointValue: z.number().int().positive().optional()\n});\nvar AddDependencyRequestSchema = z.object({\n sessionId: z.string(),\n dependsOnSlugOrId: z.string()\n});\nvar RemoveDependencyRequestSchema = z.object({\n sessionId: z.string(),\n dependsOnSlugOrId: z.string()\n});\nvar CreateSuggestionRequestSchema = z.object({\n sessionId: z.string(),\n title: z.string().min(1),\n description: z.string().optional(),\n tagNames: z.array(z.string()).optional()\n});\nvar VoteSuggestionRequestSchema = z.object({\n sessionId: z.string(),\n suggestionId: z.string(),\n value: z.union([z.literal(1), z.literal(-1)])\n});\nvar TriggerIdentificationRequestSchema = z.object({\n sessionId: z.string()\n});\nvar SubmitCodeReviewResultRequestSchema = z.object({\n sessionId: z.string(),\n approved: z.boolean(),\n content: z.string()\n});\nvar StartChildCloudBuildRequestSchema = z.object({\n sessionId: z.string(),\n childTaskId: z.string()\n});\nvar StopChildBuildRequestSchema = z.object({\n sessionId: z.string(),\n childTaskId: z.string()\n});\nvar ApproveAndMergePRRequestSchema = z.object({\n sessionId: z.string(),\n childTaskId: z.string()\n});\nvar PostChildChatMessageRequestSchema = z.object({\n sessionId: z.string(),\n childTaskId: z.string(),\n message: z.string().min(1)\n});\nvar UpdateChildStatusRequestSchema = z.object({\n sessionId: z.string(),\n childTaskId: z.string(),\n status: z.string()\n});\nvar GetAgentStatusRequestSchema = z.object({\n taskId: z.string()\n});\nvar GetUiCliHistoryRequestSchema = z.object({\n taskId: z.string()\n});\nvar GetActivePtySessionRequestSchema = z.object({\n taskId: z.string()\n});\nvar SendSoftStopRequestSchema = z.object({\n taskId: z.string()\n});\nvar FlushTaskQueueRequestSchema = z.object({\n taskId: z.string(),\n softStop: z.boolean().optional()\n});\nvar CancelTaskQueuedMessageRequestSchema = z.object({\n taskId: z.string(),\n messageId: z.string()\n});\nvar FlushSingleQueuedMessageRequestSchema = z.object({\n taskId: z.string(),\n messageId: z.string(),\n softStop: z.boolean().optional()\n});\nvar AnswerAgentQuestionRequestSchema = z.object({\n taskId: z.string(),\n requestId: z.string(),\n answers: z.record(z.string(), z.string())\n});\nvar ClearAgentTodosRequestSchema = z.object({\n taskId: z.string()\n});\nvar AgentQuestionOptionSchema = z.object({\n label: z.string(),\n description: z.string(),\n preview: z.string().optional()\n});\nvar AgentQuestionSchema = z.object({\n question: z.string(),\n header: z.string(),\n options: z.array(AgentQuestionOptionSchema),\n multiSelect: z.boolean().optional()\n});\nvar AskUserQuestionRequestSchema = z.object({\n sessionId: z.string(),\n question: z.string().min(1),\n requestId: z.string().min(1),\n questions: z.array(AgentQuestionSchema).min(1)\n});\nvar AgentEventSchema = z.object({\n type: z.string().min(1)\n}).catchall(z.unknown());\nvar EmitAgentEventRequestSchema = z.object({\n sessionId: z.string(),\n events: z.array(AgentEventSchema).max(500)\n});\nvar RefreshGithubTokenRequestSchema = z.object({\n sessionId: z.string()\n});\nvar RefreshGithubTokenResponseSchema = z.object({\n token: z.string()\n});\nvar PTY_FRAME_MAX_CHARS = 256 * 1024;\nvar PTY_MAX_DIMENSION = 1e3;\nvar PtyOutputRequestSchema = z.object({\n sessionId: z.string(),\n data: z.string().max(PTY_FRAME_MAX_CHARS),\n cols: z.number().int().positive().max(PTY_MAX_DIMENSION).optional(),\n rows: z.number().int().positive().max(PTY_MAX_DIMENSION).optional()\n});\nvar PtyInputRequestSchema = z.object({\n sessionId: z.string(),\n data: z.string().max(PTY_FRAME_MAX_CHARS)\n});\nvar PtyResizeRequestSchema = z.object({\n sessionId: z.string(),\n cols: z.number().int().positive().max(PTY_MAX_DIMENSION),\n rows: z.number().int().positive().max(PTY_MAX_DIMENSION)\n});\nvar PtyAttachRequestSchema = z.object({\n sessionId: z.string()\n});\nvar CreatePRResponseSchema = z.object({\n prNumber: z.number().int().positive(),\n prUrl: z.string().url()\n});\nvar PostToChatResponseSchema = z.object({\n messageId: z.string()\n});\nvar UpdateTaskStatusResponseSchema = z.object({\n taskId: z.string(),\n status: z.string()\n});\nvar StoreSessionIdResponseSchema = z.object({\n success: z.boolean()\n});\nvar HeartbeatResponseSchema = z.object({\n acknowledged: z.boolean()\n});\nvar SessionStartResponseSchema = z.object({\n sessionId: z.string(),\n startedAt: z.string()\n});\nvar SessionStopResponseSchema = z.object({\n sessionId: z.string(),\n stoppedAt: z.string()\n});\nvar DeleteSubtaskResponseSchema = z.object({\n deleted: z.boolean()\n});\n\n// src/types/agent-session-project-requests.ts\nimport { z as z2 } from \"zod\";\nvar ListAccessibleProjectsRequestSchema = z2.object({\n pageSize: z2.number().int().positive().max(100).optional().default(100)\n});\nvar ListProjectTasksRequestSchema = z2.object({\n projectId: z2.string(),\n status: z2.string().optional(),\n assigneeId: z2.string().optional(),\n unassigned: z2.boolean().optional(),\n limit: z2.number().int().positive().optional().default(50)\n}).refine((p) => !(p.unassigned && p.assigneeId), {\n message: \"Pass either assigneeId or unassigned, not both\"\n});\nvar GetProjectTaskRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string()\n});\nvar SearchProjectTasksRequestSchema = z2.object({\n projectId: z2.string(),\n tagNames: z2.array(z2.string()).optional(),\n searchQuery: z2.string().optional(),\n statusFilters: z2.array(z2.string()).optional(),\n // Card types to include. Omitted/empty → defaults to [\"task\"] in the handler so\n // search doesn't surface incidents/suggestions unless asked. Enum validation lives\n // at the MCP tool layer (mirrors statusFilters).\n typeFilters: z2.array(z2.string()).optional(),\n assigneeId: z2.string().optional(),\n unassigned: z2.boolean().optional(),\n limit: z2.number().int().positive().optional().default(20)\n}).refine((p) => !(p.unassigned && p.assigneeId), {\n message: \"Pass either assigneeId or unassigned, not both\"\n});\nvar ListProjectTagsRequestSchema = z2.object({\n projectId: z2.string()\n});\nvar GetProjectSummaryRequestSchema = z2.object({\n projectId: z2.string()\n});\nvar CreateProjectTaskRequestSchema = z2.object({\n projectId: z2.string(),\n title: z2.string().min(1),\n description: z2.string().optional(),\n plan: z2.string().optional(),\n status: z2.string().optional(),\n requestingUserId: z2.string().optional()\n});\nvar UpdateProjectTaskRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string(),\n title: z2.string().optional(),\n description: z2.string().optional(),\n plan: z2.string().optional(),\n status: z2.string().optional(),\n assignedUserId: z2.string().nullish(),\n requestingUserId: z2.string().optional()\n});\nvar PostToProjectTaskChatRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string(),\n content: z2.string(),\n requestingUserId: z2.string().optional()\n});\nvar GetProjectTaskCliRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string(),\n limit: z2.number().int().positive().optional().default(50),\n source: z2.string().optional()\n});\nvar GetProjectTaskSessionsRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string()\n});\nvar QueryProjectGcpLogsRequestSchema = z2.object({\n projectId: z2.string(),\n env: z2.enum([\"prod\", \"dev\", \"claudespace\"]).optional(),\n severity: z2.enum([\"DEBUG\", \"INFO\", \"NOTICE\", \"WARNING\", \"ERROR\", \"CRITICAL\", \"ALERT\", \"EMERGENCY\"]).optional(),\n services: z2.array(z2.string().min(1).max(200)).max(25).optional(),\n sqlInstances: z2.array(z2.string().min(1).max(200)).max(25).optional(),\n allServices: z2.boolean().optional(),\n search: z2.string().max(256).optional(),\n filter: z2.string().max(1e3).optional(),\n startTime: z2.string().optional(),\n endTime: z2.string().optional(),\n limit: z2.number().int().min(1).max(200).optional().default(50),\n pageToken: z2.string().max(4096).optional()\n});\nvar StartProjectBuildRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string(),\n requestingUserId: z2.string().optional()\n});\nvar StopProjectBuildRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string(),\n requestingUserId: z2.string().optional()\n});\nvar StartProjectWorkspaceRequestSchema = z2.object({\n projectId: z2.string(),\n requestingUserId: z2.string().optional()\n});\nvar StopProjectWorkspaceRequestSchema = z2.object({\n projectId: z2.string(),\n destroy: z2.boolean().optional(),\n requestingUserId: z2.string().optional()\n});\nvar CreateProjectReleaseRequestSchema = z2.object({\n projectId: z2.string(),\n taskIds: z2.array(z2.string()).optional(),\n requestingUserId: z2.string().optional()\n});\nvar ApproveProjectMergePRRequestSchema = z2.object({\n projectId: z2.string(),\n childTaskId: z2.string(),\n requestingUserId: z2.string().optional()\n});\nvar ListProjectSubtasksRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string()\n});\nvar CreateProjectSubtaskRequestSchema = z2.object({\n projectId: z2.string(),\n parentTaskId: z2.string(),\n title: z2.string().min(1),\n description: z2.string().optional(),\n plan: z2.string().optional(),\n ordinal: z2.number().int().nonnegative().optional(),\n storyPointValue: z2.number().int().positive().optional(),\n requestingUserId: z2.string().optional()\n});\nvar UpdateProjectSubtaskRequestSchema = z2.object({\n projectId: z2.string(),\n subtaskId: z2.string(),\n title: z2.string().optional(),\n description: z2.string().optional(),\n plan: z2.string().optional(),\n status: z2.string().optional(),\n ordinal: z2.number().int().nonnegative().optional(),\n storyPointValue: z2.number().int().positive().optional(),\n requestingUserId: z2.string().optional()\n});\nvar DeleteProjectSubtaskRequestSchema = z2.object({\n projectId: z2.string(),\n subtaskId: z2.string(),\n requestingUserId: z2.string().optional()\n});\nvar GetProjectTaskChatRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string(),\n limit: z2.number().int().positive().optional().default(20)\n});\nvar AddProjectTaskDependencyRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string(),\n dependsOnSlugOrId: z2.string(),\n requestingUserId: z2.string().optional()\n});\nvar RemoveProjectTaskDependencyRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string(),\n dependsOnSlugOrId: z2.string(),\n requestingUserId: z2.string().optional()\n});\nvar VoteProjectSuggestionRequestSchema = z2.object({\n projectId: z2.string(),\n suggestionId: z2.string(),\n value: z2.union([z2.literal(1), z2.literal(-1)]),\n requestingUserId: z2.string().optional()\n});\nvar GetProjectTaskDependenciesRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string()\n});\nvar ListProjectTaskFilesRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string()\n});\nvar GetProjectAttachmentRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string(),\n fileId: z2.string(),\n /** Byte offset into text content (paging large logs/JSON). Default 0. */\n offset: z2.number().int().nonnegative().optional(),\n /** Max bytes of text content to return from `offset`. Server default applies. */\n maxBytes: z2.number().int().positive().optional()\n});\nvar RequestProjectFileUploadRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string(),\n fileName: z2.string().min(1).max(255),\n mimeType: z2.string().min(1).max(128),\n fileSize: z2.number().int().positive().max(MAX_FILE_SIZE_BYTES),\n requestingUserId: z2.string().optional()\n});\nvar ConfirmProjectFileUploadRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string(),\n fileId: z2.string(),\n /** When set, the attachment is also posted to the task chat with this text. */\n comment: z2.string().max(2e3).optional(),\n requestingUserId: z2.string().optional()\n});\nvar CreateProjectPullRequestRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string(),\n title: z2.string().min(1),\n body: z2.string(),\n head: z2.string().optional(),\n base: z2.string().optional(),\n requestingUserId: z2.string().optional()\n});\nvar ListProjectMembersRequestSchema = z2.object({\n projectId: z2.string()\n});\nvar AddProjectTaskReviewerRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string(),\n userId: z2.string(),\n requestingUserId: z2.string().optional()\n});\nvar RemoveProjectTaskReviewerRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string(),\n userId: z2.string(),\n requestingUserId: z2.string().optional()\n});\nvar ListProjectManualTestsRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string()\n});\nvar QueryProjectManualTestsRequestSchema = z2.object({\n projectId: z2.string(),\n cardStatuses: z2.array(z2.string()).optional(),\n testStatuses: z2.array(z2.enum([\"open\", \"approved\", \"rejected\"])).optional()\n});\nvar SetProjectManualTestsRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string(),\n items: z2.array(z2.object({ title: z2.string().min(1) })).min(1),\n requestingUserId: z2.string().optional()\n});\nvar EditProjectManualTestRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string(),\n title: z2.string().min(1),\n newTitle: z2.string().min(1),\n requestingUserId: z2.string().optional()\n});\nvar RemoveProjectManualTestRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string(),\n title: z2.string().min(1),\n requestingUserId: z2.string().optional()\n});\nvar ApproveProjectManualTestRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string(),\n title: z2.string().min(1),\n requestingUserId: z2.string().optional()\n});\nvar RejectProjectManualTestRequestSchema = z2.object({\n projectId: z2.string(),\n taskId: z2.string(),\n title: z2.string().min(1),\n reason: z2.string().min(1).max(2e3),\n requestingUserId: z2.string().optional()\n});\nvar CreateProjectSuggestionRequestSchema = z2.object({\n projectId: z2.string(),\n title: z2.string().min(1),\n description: z2.string().optional(),\n tagNames: z2.array(z2.string()).optional(),\n requestingUserId: z2.string().optional()\n});\n\n// src/types/agent-session-events.ts\nvar CRITICAL_AUTOMATED_SOURCES = /* @__PURE__ */ new Set([\n \"ci_failure\",\n \"review_trigger\",\n \"merge_conflict\",\n \"merge_failed\",\n \"pull_branch\"\n]);\nvar createAgentSessionRoom = (sessionId) => `agentSession:${sessionId}`;\nvar createProjectRoom = (projectId) => `project:${projectId}`;\n\n// src/types/workspace-v3.ts\nvar WORKSPACE_DESIRED_STATES = [\"Running\", \"Sleeping\", \"Destroyed\"];\nvar WORKSPACE_OBSERVED_STATES = [\n \"Pending\",\n \"Provisioning\",\n \"Running\",\n \"Sleeping\",\n \"Destroying\",\n \"Destroyed\",\n \"Failed\"\n];\nvar WORKSPACE_PURPOSES = [\"primary\", \"review\", \"project\"];\nvar WORKSPACE_POD_PHASES = [\n \"Creating\",\n \"Ready\",\n \"Bound\",\n \"Terminating\",\n \"Gone\",\n \"Failed\"\n];\nvar WORKSPACE_SESSION_ROLES = [\"writer\", \"reader\"];\nvar WORKSPACE_SESSION_MODES = [\"build\", \"review\", \"pm\", \"help\"];\nvar WORKSPACE_SESSION_STATUSES = [\"Pending\", \"Active\", \"Stranded\", \"Ended\"];\nvar MAX_DISCOVERED_PORTS = 16;\nfunction sanitizeDiscoveredPorts(raw) {\n if (!Array.isArray(raw)) return [];\n const seen = /* @__PURE__ */ new Set();\n const out = [];\n for (const entry of raw) {\n if (out.length >= MAX_DISCOVERED_PORTS) break;\n if (!entry || typeof entry !== \"object\") continue;\n const port = entry.port;\n if (!isAllowablePreviewPort(port)) continue;\n if (seen.has(port)) continue;\n seen.add(port);\n const label = entry.label;\n const protocol = entry.protocol;\n const detectedAt = entry.detectedAt;\n out.push({\n port,\n ...typeof label === \"string\" && label.length > 0 ? { label } : {},\n ...protocol === \"http\" || protocol === \"tcp\" ? { protocol } : {},\n detectedAt: typeof detectedAt === \"string\" ? detectedAt : (/* @__PURE__ */ new Date(0)).toISOString()\n });\n }\n return out;\n}\n\n// src/types/deployment-service-types.ts\nvar DEPLOYMENT_TARGET_PROVIDERS = [\n \"pm2-local\",\n \"github-actions\",\n \"vercel\",\n \"cloud-run\",\n \"gke\"\n];\nvar DEPLOYMENT_TARGET_ENVIRONMENTS = [\"dev\", \"prod\", \"staging\", \"custom\"];\n\n// src/generated/mcp-tool-registry.generated.ts\nvar MCP_TOOL_REGISTRY = [\n {\n name: \"upload_attachment\",\n description: \"Upload an image file (e.g. a Playwright screenshot) as a task attachment AND post it to the task chat in one step \\u2014 no follow-up post_to_chat call needed. Supports png/jpg/gif/webp.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/attachment-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (common tools)\"\n },\n {\n name: \"approve_manual_test\",\n description: \"Sign off on (approve) a manual test step on behalf of your authenticated user. Identify the test by its title (case-insensitive). Use after you have verified the step passes.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/checklist-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (common tools)\"\n },\n {\n name: \"edit_manual_test\",\n description: \"Rename an existing manual test step. Identify the test by its current title (case-insensitive); pass the new title to replace it. Use to correct or refine a recorded manual verification step.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/checklist-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (common tools)\"\n },\n {\n name: \"list_manual_tests\",\n description: \"List the manual test checklist items for the current task. Use to see what manual verification steps have already been recorded.\",\n readOnly: true,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/checklist-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (common tools)\"\n },\n {\n name: \"query_manual_tests\",\n description: \"Query manual tests across many tasks in this project, grouped by task. Filter by card status (ReviewDev, ReviewLive, Complete, ...) and/or test status (open | approved | rejected). Use to answer 'show all OPEN manual tests in ReviewDev' or 'show all REJECTED manual tests with the failing reason'. With no filters it defaults to the needs-attention view: open+rejected tests on ReviewDev/ReviewLive cards.\",\n readOnly: true,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/checklist-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (common tools)\"\n },\n {\n name: \"reject_manual_test\",\n description: \"Flag an issue with (reject) a manual test step on behalf of your authenticated user, recording the reason. Identify the test by its title (case-insensitive). Use when the step fails verification.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/checklist-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (common tools)\"\n },\n {\n name: \"remove_manual_test\",\n description: \"Remove an existing manual test step from the task checklist. Identify the test by its title (case-insensitive). Use to delete a stale or incorrect manual verification step.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/checklist-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (common tools)\"\n },\n {\n name: \"set_manual_tests\",\n description: \"Add manual test steps to the task checklist. Existing items with the same title are automatically skipped (deduplication). Use to record specific manual verification steps that reviewers should follow when testing this PR.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/checklist-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (common tools)\"\n },\n {\n name: \"approve_code_review\",\n description: \"Approve the code review and exit. Use when the diff passes all review criteria. Takes only a summary \\u2014 for changes, use request_code_changes with a structured issues[] list.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/code-review-tools.ts\",\n category: \"codeReview\",\n modes: \"review\"\n },\n {\n name: \"request_code_changes\",\n description: \"Request changes during code review and exit. Use when substantive issues must be fixed before merge. Each issue: { file, line?, severity: critical|major|minor, description }.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/code-review-tools.ts\",\n category: \"codeReview\",\n modes: \"review\"\n },\n {\n name: \"get_dependencies\",\n description: \"Get this task's dependencies and their met/unmet status (met = merged to dev). Use to confirm blockers merged, or see why a task cannot start. For task state use get_task.\",\n readOnly: true,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/dependency-suggestion-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (common tools)\"\n },\n {\n name: \"get_suggestions\",\n description: \"List project suggestions sorted by vote score. Filter by status or cap with limit (default 20). Suggestions are project-level ideas, not tasks \\u2014 use get_task for tasks.\",\n readOnly: true,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/dependency-suggestion-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (common tools)\"\n },\n {\n name: \"update_task_properties\",\n description: \"Set one or more task properties in a single call. All fields are optional \\u2014 only include the fields you want to update.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/discovery-tools.ts\",\n category: \"discovery\",\n modes: \"discovery, auto\"\n },\n {\n name: \"add_dependency\",\n description: \"Add a blocking dependency \\u2014 this task cannot start until the named task is merged to dev. For post-task follow-ups use create_follow_up_task instead.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/mutation-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (common tools)\"\n },\n {\n name: \"create_follow_up_task\",\n description: \"Create a follow-up task that depends on the current task. Use for out-of-scope work or cleanup that should land after this task merges. For blockers use add_dependency.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/mutation-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (common tools)\"\n },\n {\n name: \"create_pull_request\",\n description: \"Create a GitHub PR for this task. Auto-stages, commits (commitMessage or title default), pushes to origin, then opens the PR. Always use this instead of gh CLI or raw git.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/mutation-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (common tools)\"\n },\n {\n name: \"create_suggestion\",\n description: \"Suggest a feature, improvement, rule, or idea for the project. Duplicates are deduped and your upvote is recorded. For actionable work on this task open a follow-up task.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/mutation-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (common tools)\"\n },\n {\n name: \"force_update_task_status\",\n description: \"EMERGENCY ONLY: force-override a task's Kanban status. Use when an automatic transition failed and the task is wedged. Normal flow transitions status automatically.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/mutation-tools.ts\",\n category: \"global\",\n modes: \"all modes (emergency override; always exposed)\"\n },\n {\n name: \"post_to_chat\",\n description: \"Post a message to the task chat for the team to see. Your turn output is NOT shown in chat, so this is the only way the team sees your status, summaries, and questions. Omit task_id to post to the current task's chat; pass a child's ID to message its chat.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/mutation-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (common tools)\"\n },\n {\n name: \"remove_dependency\",\n description: \"Remove a previously added dependency from this task. When to use: the dependency was added in error or is no longer relevant. Returns: confirmation string.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/mutation-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (common tools)\"\n },\n {\n name: \"vote_suggestion\",\n description: \"Vote +1 or -1 on a project suggestion. Use to express support or disagreement with a specific suggestion returned by get_suggestions.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/mutation-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (common tools)\"\n },\n {\n name: \"approve_and_merge_pr\",\n description: \"Approve and merge a child task's PR. Preconditions: child in ReviewPR. Returns { merged }: true = merged (status\\u2192ReviewDev); false = automerge queued, wait for ReviewDev.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/pm-tools.ts\",\n category: \"packRunner\",\n modes: \"parent task only (review, auto, discovery, help, building)\"\n },\n {\n name: \"create_subtask\",\n description: \"Create a subtask under the current parent task. Use when breaking a complex parent into smaller pieces during planning. For post-task follow-ups use create_follow_up_task.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/pm-tools.ts\",\n category: \"pm\",\n modes: \"review, auto, discovery, help; building (parent task only). Pack tools (start_child_cloud_build, stop_child_build, approve_and_merge_pr) require parent task.\"\n },\n {\n name: \"delete_subtask\",\n description: \"Delete a subtask by id. When to use: a subtask was created in error or is no longer needed. Returns: confirmation string.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/pm-tools.ts\",\n category: \"pm\",\n modes: \"review, auto, discovery, help; building (parent task only). Pack tools (start_child_cloud_build, stop_child_build, approve_and_merge_pr) require parent task.\"\n },\n {\n name: \"list_subtasks\",\n description: \"List all subtasks under the current parent task. Use to coordinate child work \\u2014 check who is running, ready for review, or blocked. For non-child tasks use get_task.\",\n readOnly: true,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/pm-tools.ts\",\n category: \"pm\",\n modes: \"review, auto, discovery, help; building (parent task only). Pack tools (start_child_cloud_build, stop_child_build, approve_and_merge_pr) require parent task.\"\n },\n {\n name: \"start_child_cloud_build\",\n description: \"Start a cloud build (codespace) for a child task. Preconditions: child is in Open status, has a story point value, and has an agent assigned.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/pm-tools.ts\",\n category: \"packRunner\",\n modes: \"parent task only (review, auto, discovery, help, building)\"\n },\n {\n name: \"stop_child_build\",\n description: \"Send a graceful stop signal to a running child build's agent. Not a force-kill \\u2014 the agent may take a moment to wind down.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/pm-tools.ts\",\n category: \"packRunner\",\n modes: \"parent task only (review, auto, discovery, help, building)\"\n },\n {\n name: \"update_subtask\",\n description: \"Update an existing subtask's fields (title, description, plan, ordinal, storyPointValue). Use when refining a child's plan or reordering. For the current task use update_task_plan.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/pm-tools.ts\",\n category: \"pm\",\n modes: \"review, auto, discovery, help; building (parent task only). Pack tools (start_child_cloud_build, stop_child_build, approve_and_merge_pr) require parent task.\"\n },\n {\n name: \"update_task_plan\",\n description: \"Save the finalized plan and/or description to the current task. Use in Plan mode after alignment. For children use update_subtask; for title/tags/PR use update_task_properties.\",\n readOnly: false,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/pm-tools.ts\",\n category: \"pm\",\n modes: \"task mode: discovery, auto only. PM/agent modes: review, auto, discovery, help; building (parent task only).\"\n },\n {\n name: \"get_attachment\",\n description: \"Fetch one task file's content plus metadata by file ID. Call list_task_files first to discover IDs and check sizes \\u2014 large binaries may be truncated by the service's size limit.\",\n readOnly: true,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/task-context-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (read-only common tools)\"\n },\n {\n name: \"get_current_plan\",\n description: \"Re-read the current task's plan. Use when the user updated the plan or asked you to re-read it \\u2014 otherwise the plan is already in initial context. For task metadata use get_task.\",\n readOnly: true,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/task-context-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (read-only common tools)\"\n },\n {\n name: \"get_execution_logs\",\n description: \"Read CLI execution logs \\u2014 agent reasoning, tool calls, and setup/dev-server output. Filter via source='agent' or 'application'. For human chat use read_task_chat.\",\n readOnly: true,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/task-context-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (read-only common tools)\"\n },\n {\n name: \"get_task\",\n description: \"Look up any task by slug or ID. Returns JSON with id, slug, title, description, plan, status, branch, githubPRNumber, githubPRUrl, storyPoints. For children use list_subtasks.\",\n readOnly: true,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/task-context-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (read-only common tools)\"\n },\n {\n name: \"list_task_files\",\n description: \"List all files attached to this task with metadata. Use before fetching a specific file to see what is available and how large each is. For file contents use get_attachment.\",\n readOnly: true,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/task-context-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (read-only common tools)\"\n },\n {\n name: \"read_task_chat\",\n description: \"Read recent human/user chat messages for a task. Omit task_id for the current task; pass a child ID for a child's chat. For agent logs use get_execution_logs.\",\n readOnly: true,\n package: \"conveyor-agent\",\n sourceFile: \"packages/conveyor-agent/src/tools/task-context-tools.ts\",\n category: \"global\",\n modes: \"all PM/agent modes (read-only common tools)\"\n },\n {\n name: \"get_attachment\",\n description: \"Fetch one task file's content plus metadata by file ID (accepts task id or slug). Pass projectId to target a specific project; otherwise the configured default project is used. Images are returned as viewable image blocks. Large text files (logs, JSON) are returned in pages \\u2014 use `offset`/`maxBytes` to read more, or fetch `downloadUrl` for the whole file. Call list_task_files first to discover IDs and sizes.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/attachments.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"list_task_files\",\n description: \"List all files attached to a task with metadata (no contents \\u2014 fast and small). Pass projectId to target a specific project; otherwise the configured default project is used. Use before fetching a specific file to see what is available and how large each is. For file contents use get_attachment.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/attachments.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"upload_attachment\",\n description: \"Upload a local file as a task attachment (any file type, up to 25MB). Pass projectId to target a specific project; otherwise the configured default project is used. The file appears under the task's Files. Pass `comment` to also post it to the task chat in the same step.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/attachments.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"create_release\",\n description: \"Create a release for the project \\u2014 the same flow as the Release button in the web UI. Pass projectId to target a specific project; otherwise the configured default project is used. Creates a release task with a release/YYYY.MM.N branch and a PR from the dev branch to the default branch. Omit taskIds to release ALL cards currently in Review (Dev); pass a subset to cherry-pick \\u2014 a cloud build agent then cherry-picks those changes and resolves conflicts. Fails if a release is already in progress or no cards are in Review (Dev).\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/builds.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"delete_task_environment\",\n description: \"Delete a task environment, including durable Claudespace state. Pass projectId to target a specific project; otherwise the configured default project is used.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/builds.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"get_build_status\",\n description: \"Check codespace and agent status for a task. Pass projectId to target a specific project; otherwise the configured default project is used.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/builds.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"resume_task\",\n description: \"Resume a sleeping task Claudespace. Pass projectId to target a specific project; otherwise the configured default project is used.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/builds.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"sleep_task\",\n description: \"Sleep a task Claudespace, stopping compute while preserving durable state. Pass projectId to target a specific project; otherwise the configured default project is used.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/builds.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"start_task\",\n description: \"Start a cloud build (codespace) for a task. Pass projectId to target a specific project; otherwise the configured default project is used.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/builds.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"stop_task\",\n description: \"Compatibility alias for the legacy stop path. stop_task now performs the same durable sleep behavior as sleep_task, preserving task Claudespace state while stopping compute. Pass projectId to target a specific project; otherwise the configured default project is used.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/builds.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"approve_manual_test\",\n description: \"Sign off on (approve) a manual test step on a task on behalf of your authenticated user. Pass projectId to target a specific project; otherwise the configured default project is used. Identify the test by its title (case-insensitive). Use after you have verified the step passes.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/checklists.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"edit_manual_test\",\n description: \"Rename an existing manual test step on a task. Pass projectId to target a specific project; otherwise the configured default project is used. Identify the test by its current title (case-insensitive) and pass the new title to replace it.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/checklists.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"list_manual_tests\",\n description: \"List the manual test checklist items for a task. Pass projectId to target a specific project; otherwise the configured default project is used. Use to see what manual verification steps have already been recorded.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/checklists.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"query_manual_tests\",\n description: \"Query manual tests across many tasks in a project, grouped by task. Filter by card status (e.g. ReviewDev, ReviewLive, Complete) and/or test status (open | approved | rejected). Use to answer questions like 'show all OPEN manual tests in ReviewDev' or 'show all REJECTED manual tests in ReviewDev/ReviewLive with the failing reason'. With no filters it defaults to the needs-attention view: open+rejected tests on ReviewDev/ReviewLive cards. Pass projectId to target a specific project; otherwise the configured default project is used.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/checklists.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"reject_manual_test\",\n description: \"Flag an issue with (reject) a manual test step on a task on behalf of your authenticated user, recording the reason. Pass projectId to target a specific project; otherwise the configured default project is used. Identify the test by its title (case-insensitive). Use when the step fails verification.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/checklists.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"remove_manual_test\",\n description: \"Remove an existing manual test step from a task's checklist. Pass projectId to target a specific project; otherwise the configured default project is used. Identify the test by its title (case-insensitive).\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/checklists.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"set_manual_tests\",\n description: \"Add manual test steps to a task's checklist. Pass projectId to target a specific project; otherwise the configured default project is used. Existing items with the same title are automatically skipped (deduplication). Use to record specific manual verification steps that reviewers should follow when testing the task's PR.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/checklists.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"add_dependency\",\n description: \"Add a blocking dependency \\u2014 this task cannot start until the named task is merged to dev. Pass projectId to target a specific project; otherwise the configured default project is used.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/dependencies.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"get_dependencies\",\n description: \"Get a task's dependencies and their met/unmet status (met = merged to dev). Pass projectId to target a specific project; otherwise the configured default project is used. Use to confirm blockers merged, or see why a task cannot start. For task state use get_task.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/dependencies.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"remove_dependency\",\n description: \"Remove a previously added dependency from a task. Pass projectId to target a specific project; otherwise the configured default project is used. The task is no longer blocked by the named task. Returns: confirmation string.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/dependencies.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"query_gcp_logs\",\n description: \"Query Google Cloud Logging for a project's linked GCP environments \\u2014 use this to investigate production or dev issues directly ('something broke on prod'). Envs: 'prod' and 'dev' are the project's Cloud Run apps + Cloud SQL databases (scoped by default to the resources linked in project settings); 'claudespace' is the project's GKE agent-pod namespace. Start broad (severity=ERROR, sinceMinutes=60), then narrow with services/search. Returns compact lines: '<time> <SEVERITY> [<source>] <message>'. When the response ends with a pageToken line, pass that token back as pageToken for the next page. Pass projectId to target a specific project; otherwise the configured default project is used.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/logs.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"get_project_summary\",\n description: \"Get overall project status: task counts by status, active builds, repo info. Pass projectId to target a specific project; otherwise the configured default project is used.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/project.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"list_project_members\",\n description: \"List project members with user ID, name, email, and access level \\u2014 use to resolve a person's name or email to a user ID for task assignment or review. Pass projectId to target a specific project; otherwise the configured default project is used.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/project.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"list_projects\",\n description: \"List Conveyor projects available to this MCP token's user. Use a returned project id as projectId on other tools when no default project is configured or when targeting a different project.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/project.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"create_pull_request\",\n description: \"Open a GitHub pull request for a task's existing branch (the branch must already be pushed to origin). Pass projectId to target a specific project; otherwise the configured default project is used. Moves the task to ReviewPR. Returns the PR number and URL.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/pull-request.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"create_subtask\",\n description: \"Create a subtask under a parent task. Pass projectId to target a specific project; otherwise the configured default project is used. Subtasks break a larger task into independently buildable pieces.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/subtasks.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"delete_subtask\",\n description: \"Delete a subtask by ID. Pass projectId to target a specific project; otherwise the configured default project is used. This is permanent \\u2014 use update_subtask to set status to Cancelled if you only want to close it.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/subtasks.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"list_subtasks\",\n description: \"List all subtasks of a parent task with their status and ordering. Pass projectId to target a specific project; otherwise the configured default project is used.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/subtasks.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"update_subtask\",\n description: \"Update a subtask's fields: title, description, plan, status, ordering, or story points. Pass projectId to target a specific project; otherwise the configured default project is used. Moving a subtask beyond Planning auto-fills missing story points and agent assignment \\u2014 don't spend turns on them.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/subtasks.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"create_suggestion\",\n description: \"Suggest a feature, improvement, rule, or idea for the project. Pass projectId to target a specific project; otherwise the configured default project is used. Duplicates are deduped and your upvote is recorded.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/suggestions.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"add_reviewer\",\n description: \"Add a project member as a reviewer on a task. Pass projectId to target a specific project; otherwise the configured default project is used. Idempotent \\u2014 adding an existing reviewer is a no-op.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/tasks.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"approve_and_merge_pr\",\n description: \"Approve and merge a child task's pull request. Pass projectId to target a specific project; otherwise the configured default project is used. Only succeeds if all CI/CD checks are passing. The child task must be in ReviewPR status with a PR.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/tasks.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"approve_task\",\n description: \"Move a task forward in the review flow (ReviewPR -> ReviewDev, or -> Complete). Pass projectId to target a specific project; otherwise the configured default project is used.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/tasks.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"create_task\",\n description: \"Create a new task with title, description, and optional plan. Pass projectId to target a specific project; otherwise the configured default project is used. Icon, story points, and agent assignment are auto-filled when a task is created in (or later moved to) a status beyond Planning \\u2014 don't spend turns on them.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/tasks.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"get_card_by_slug\",\n description: \"Get full card details by the slug from a card URL (/cards/<slug>) instead of a task ID. Pass projectId to target a specific project; otherwise the configured default project is used.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/tasks.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"get_task\",\n description: \"Get full task details including plan, chat history, PR info, subtasks, and build status. Pass projectId to target a specific project; otherwise the configured default project is used.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/tasks.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"get_task_logs\",\n description: \"Read CLI execution logs from a task. Pass projectId to target a specific project; otherwise the configured default project is used. Returns agent reasoning, tool calls, setup output, and other execution events. For human chat use read_task_chat.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/tasks.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"get_task_sessions\",\n description: \"Read compute-session state for a task: legacy CodespaceSession rows plus v3 workspaces, including purpose=review review workspaces. Shows pod identity, liveness, lifecycle, and code-review claim state. Use to diagnose stalled/dead agents or code-review runs. Pass projectId to target a specific project; otherwise the configured default project is used.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/tasks.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"list_tags\",\n description: \"List all project tags with their names, IDs, and colors. Pass projectId to target a specific project; otherwise the configured default project is used.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/tasks.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"list_tasks\",\n description: \"List project tasks, optionally filtered by status or assignment (a specific assignee, or unassigned tasks). Pass projectId to target a specific project; otherwise the configured default project is used. Returns summaries \\u2014 plan omitted, description truncated; use get_task for full details.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/tasks.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"post_to_chat\",\n description: \"Post a message to a task's chat. Pass projectId to target a specific project; otherwise the configured default project is used.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/tasks.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"read_task_chat\",\n description: \"Read messages from a task's chat. Pass projectId to target a specific project; otherwise the configured default project is used. For agent execution logs use get_task_logs.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/tasks.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"remove_reviewer\",\n description: \"Remove a reviewer from a task. Pass projectId to target a specific project; otherwise the configured default project is used. Idempotent \\u2014 removing a non-reviewer is a no-op.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/tasks.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"request_changes\",\n description: \"Post feedback and send task back to InProgress for more work. Pass projectId to target a specific project; otherwise the configured default project is used.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/tasks.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"search_tasks\",\n description: \"Search cards by tag name, text query, status, type, and/or assignment. Defaults to type=task \\u2014 pass typeFilters to include incidents/suggestions. Pass projectId to target a specific project; otherwise the configured default project is used. Use tag names like 'agent-runner', not IDs. Returns summaries \\u2014 plan omitted, description truncated; use get_task for full details.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/tasks.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"update_task\",\n description: \"Update task fields: title, description, plan, status, or assignment. Pass projectId to target a specific project; otherwise the configured default project is used. Moving a task beyond Planning auto-fills any missing icon, story points, and agent assignment \\u2014 don't spend turns on them.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/tasks.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"workspace_attach_info\",\n description: \"Return SSH/SFTP attach metadata for a running task Claudespace, plus hosted preview URLs and configured preview ports. Optionally installs an OpenSSH public key for this attach session.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/workspace.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"workspace_preview_urls\",\n description: \"Return the hosted preview URLs and preview ports for a running task Claudespace. This mirrors the web UI preview link metadata.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/workspace.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"workspace_start_tunnel\",\n description: \"Start a local loopback tunnel through the MCP server to a running task Claudespace port. Use port 2222 for SSH/SFTP, or one of previewPorts for app access.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/workspace.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n },\n {\n name: \"workspace_stop_tunnel\",\n description: \"Stop a local workspace tunnel previously opened by workspace_start_tunnel.\",\n readOnly: false,\n package: \"conveyor-mcp\",\n sourceFile: \"packages/conveyor-mcp/src/tools/workspace.ts\",\n category: \"mcp\",\n modes: \"conveyor-mcp (MCP server)\"\n }\n];\n\n// src/types/agent-tool-registry.ts\nfunction getToolsByCategory(category) {\n return MCP_TOOL_REGISTRY.filter((tool) => tool.category === category);\n}\n\n// src/constants/timezone.ts\nvar PROJECT_TIMEZONE = \"America/Los_Angeles\";\n\n// src/constants/agent-session-runner.ts\nvar CODESPACE_SESSION_ACTIVE_RUNNER_STATUSES = [\n \"connected\",\n \"idle\",\n \"busy\",\n \"running\",\n \"fetching_context\",\n \"waiting_for_input\",\n \"setup\",\n \"connecting\"\n];\nvar TERMINAL_TASK_STATUSES = [\"Complete\", \"Cancelled\"];\nvar AGENT_STATUS_REASON_USER_QUESTION = \"user_question\";\n\n// src/constants/agent-chat-history.ts\nvar TASK_CHAT_HISTORY_LIMIT = 20;\nvar PM_CHAT_HISTORY_LIMIT = 40;\nvar AGENT_CHAT_HISTORY_FETCH_LIMIT = Math.max(TASK_CHAT_HISTORY_LIMIT, PM_CHAT_HISTORY_LIMIT) + 10;\n\n// src/room-helpers.ts\nfunction serviceRoom(service, entityId) {\n return `${service}:${entityId}`;\n}\nfunction userRoom(userId) {\n return `user:${userId}`;\n}\nfunction notificationUserRoom(userId) {\n return `notificationService:user:${userId}`;\n}\nfunction cliRoom(taskId) {\n return `task:${taskId}:cli`;\n}\nfunction projectCliRoom(projectId, userId) {\n return `project:${projectId}:cli:${userId}`;\n}\nfunction projectEventsRoom(projectId) {\n return `project:${projectId}:events`;\n}\n\n// src/utils/stat-date.ts\nfunction todayInProjectTZ() {\n return (/* @__PURE__ */ new Date()).toLocaleDateString(\"en-CA\", { timeZone: PROJECT_TIMEZONE });\n}\nfunction formatDateInProjectTZ(date) {\n return date.toLocaleDateString(\"en-CA\", { timeZone: PROJECT_TIMEZONE });\n}\nfunction resolveStatDateRange(statDate, fallbackDays) {\n const today = todayInProjectTZ();\n if (statDate) {\n if (statDate.mode === \"month\" && typeof statDate.month === \"number\") {\n const sinceDate3 = `${statDate.year}-${String(statDate.month).padStart(2, \"0\")}-01`;\n const lastDay = new Date(statDate.year, statDate.month, 0).getDate();\n const endStr2 = `${statDate.year}-${String(statDate.month).padStart(2, \"0\")}-${String(lastDay).padStart(2, \"0\")}`;\n return { sinceDate: sinceDate3, untilDate: endStr2 < today ? endStr2 : today };\n }\n const sinceDate2 = `${statDate.year}-01-01`;\n const endStr = `${statDate.year}-12-31`;\n return { sinceDate: sinceDate2, untilDate: endStr < today ? endStr : today };\n }\n const days = fallbackDays ?? 30;\n const d = /* @__PURE__ */ new Date();\n d.setDate(d.getDate() - days);\n const sinceDate = formatDateInProjectTZ(d);\n return { sinceDate, untilDate: today };\n}\nfunction generateDateRange(sinceStr, untilStr) {\n const dates = [];\n const [sy, sm, sd] = sinceStr.split(\"-\").map(Number);\n const [uy, um, ud] = untilStr.split(\"-\").map(Number);\n let current = Date.UTC(sy, sm - 1, sd);\n const end = Date.UTC(uy, um - 1, ud);\n while (current <= end) {\n const d = new Date(current);\n const yyyy = d.getUTCFullYear();\n const mm = String(d.getUTCMonth() + 1).padStart(2, \"0\");\n const dd = String(d.getUTCDate()).padStart(2, \"0\");\n dates.push(`${yyyy}-${mm}-${dd}`);\n current += 24 * 60 * 60 * 1e3;\n }\n return dates;\n}\n\n// src/utils/message-filter.ts\nfunction messageMatchesFilters(msg, channelFilters) {\n if (!channelFilters || channelFilters.length === 0) return true;\n if (msg.role === \"user\") return true;\n const filterSet = new Set(channelFilters);\n const isToolCall = msg.metadata?.type === \"activity_block\";\n if (isToolCall) return filterSet.has(\"tools\");\n return filterSet.has(msg.channel ?? \"agent\");\n}\n\n// src/utils/mentions.ts\nvar MENTION_TOKEN_REGEX = /@\\[(\\w+):([^\\]]+)\\]/g;\nfunction serializeMention(type, id) {\n return `@[${type}:${id}]`;\n}\nfunction buildMentionKey(type, id) {\n return `${type}:${id}`;\n}\nfunction parseMentions(content) {\n const tokens = [];\n for (const match of content.matchAll(MENTION_TOKEN_REGEX)) {\n tokens.push({ type: match[1], id: match[2] });\n }\n return tokens;\n}\nfunction resolveMentions(content, metadata) {\n if (!metadata || typeof metadata !== \"object\") return content;\n const meta = metadata;\n if (meta.type !== \"mentions\" || !meta.mentions) return content;\n const mentions = meta.mentions;\n return content.replace(MENTION_TOKEN_REGEX, (_match, type, id) => {\n const key = `${type}:${id}`;\n const mention = mentions[key];\n if (!mention) return _match;\n const prefix = mention.slug ? `#${mention.slug}` : `@${mention.label}`;\n return `${prefix} (${type}:${id})`;\n });\n}\n\n// src/utils/autopilot-ratio.ts\nvar AUTOPILOT_RATIO_MIN = 1;\nvar AUTOPILOT_RATIO_MAX = 6.5;\nfunction computeMemoryBounds(agentCpu, sidecarCpu, sidecarMemoryGi) {\n const totalCpu = agentCpu + sidecarCpu;\n const minPodMemory = totalCpu * AUTOPILOT_RATIO_MIN;\n const maxPodMemory = totalCpu * AUTOPILOT_RATIO_MAX;\n const minAgentMemory = minPodMemory - sidecarMemoryGi;\n const maxAgentMemory = maxPodMemory - sidecarMemoryGi;\n const minMemoryGi = Math.max(1, Math.ceil(minAgentMemory));\n const maxMemoryGi = Math.floor(maxAgentMemory);\n return { minMemoryGi, maxMemoryGi };\n}\nfunction computePodRatio(agentCpu, agentMemoryGi, sidecarCpu, sidecarMemoryGi) {\n const totalCpu = agentCpu + sidecarCpu;\n const totalMemory = agentMemoryGi + sidecarMemoryGi;\n if (totalCpu === 0) return 0;\n return totalMemory / totalCpu;\n}\nfunction isValidAutopilotConfig(agentCpu, agentMemoryGi, sidecarCpu, sidecarMemoryGi) {\n const ratio = computePodRatio(agentCpu, agentMemoryGi, sidecarCpu, sidecarMemoryGi);\n return ratio >= AUTOPILOT_RATIO_MIN && ratio <= AUTOPILOT_RATIO_MAX;\n}\n\n// src/utils/sidecar-overhead.ts\nvar SIDECAR_OVERHEAD = {\n postgresql: {\n // 50m\n cpu: 0.05,\n // 128Mi\n memoryGi: 0.125\n },\n redis: {\n // 25m\n cpu: 0.025,\n // 32Mi\n memoryGi: 0.03125\n },\n elasticsearch: {\n // 100m\n cpu: 0.1,\n // 256Mi\n memoryGi: 0.25\n },\n lgtm: {\n // 250m — bundles Grafana + Loki + Tempo + Mimir + OTEL Collector\n cpu: 0.25,\n // 1Gi\n memoryGi: 1\n },\n \"firebase-auth-emulator\": {\n // 100m\n cpu: 0.1,\n // 256Mi\n memoryGi: 0.25\n }\n};\nfunction sidecarRequestTotals(deps) {\n let totalCpu = 0;\n let totalMemoryGi = 0;\n for (const dep of deps) {\n const overhead = SIDECAR_OVERHEAD[dep];\n if (overhead) {\n totalCpu += overhead.cpu;\n totalMemoryGi += overhead.memoryGi;\n }\n }\n return { cpu: totalCpu, memoryGi: totalMemoryGi };\n}\n\n// src/utils/xp.ts\nvar SP_XP_RATE = 10;\nvar REPORT_XP_RATE = 10;\nvar REVIEW_XP_RATE = 5;\nvar MAX_LEVEL = 99;\nfunction xpToReachLevel(level) {\n if (level <= 1) return 0;\n return 5 * level * (level - 1);\n}\nfunction computeTotalXp({ spValueSum, reportCount, reviewCount }) {\n const spXp = spValueSum * SP_XP_RATE;\n const reportXp = reportCount * REPORT_XP_RATE;\n const reviewXp = reviewCount * REVIEW_XP_RATE;\n return { spXp, reportXp, reviewXp, totalXp: spXp + reportXp + reviewXp };\n}\nfunction levelFromXp(totalXp) {\n const xp = Number.isFinite(totalXp) && totalXp > 0 ? Math.floor(totalXp) : 0;\n let level = Math.floor((5 + Math.sqrt(25 + 20 * xp)) / 10);\n while (xpToReachLevel(level + 1) <= xp) level++;\n while (level > 1 && xpToReachLevel(level) > xp) level--;\n level = Math.min(MAX_LEVEL, Math.max(1, level));\n if (level >= MAX_LEVEL) {\n return {\n level: MAX_LEVEL,\n xpIntoLevel: xp - xpToReachLevel(MAX_LEVEL),\n xpForNextLevel: 0,\n progress: 1\n };\n }\n const floor = xpToReachLevel(level);\n const xpForNextLevel = xpToReachLevel(level + 1) - floor;\n const xpIntoLevel = xp - floor;\n const progress = xpForNextLevel === 0 ? 1 : Math.min(1, Math.max(0, xpIntoLevel / xpForNextLevel));\n return { level, xpIntoLevel, xpForNextLevel, progress };\n}\nexport {\n AGENT_CHAT_HISTORY_FETCH_LIMIT,\n AGENT_STATUS_REASON_USER_QUESTION,\n ALLOWED_FILE_MIME_TYPES,\n AUTOPILOT_RATIO_MAX,\n AUTOPILOT_RATIO_MIN,\n AddDependencyRequestSchema,\n AddProjectTaskDependencyRequestSchema,\n AddProjectTaskReviewerRequestSchema,\n AgentEventSchema,\n AgentHeartbeatSchema,\n AgentQuestionOptionSchema,\n AgentQuestionSchema,\n AnswerAgentQuestionRequestSchema,\n ApproveAndMergePRRequestSchema,\n ApproveManualTestRequestSchema,\n ApproveProjectManualTestRequestSchema,\n ApproveProjectMergePRRequestSchema,\n AskUserQuestionRequestSchema,\n CARD_TYPE_STATUSES,\n CARD_TYPE_VALUES,\n CODESPACE_SESSION_ACTIVE_RUNNER_STATUSES,\n CRITICAL_AUTOMATED_SOURCES,\n CancelTaskQueuedMessageRequestSchema,\n ClearAgentTodosRequestSchema,\n ConfirmFileUploadRequestSchema,\n ConfirmProjectFileUploadRequestSchema,\n ConnectAgentRequestSchema,\n CreateFollowUpTaskRequestSchema,\n CreatePRInputSchema,\n CreatePRResponseSchema,\n CreateProjectPullRequestRequestSchema,\n CreateProjectReleaseRequestSchema,\n CreateProjectSubtaskRequestSchema,\n CreateProjectSuggestionRequestSchema,\n CreateProjectTaskRequestSchema,\n CreatePullRequestRequestSchema,\n CreateSubtaskRequestSchema,\n CreateSuggestionRequestSchema,\n DEFAULT_HAIKU_MODEL,\n DEFAULT_OPUS_MODEL,\n DEFAULT_SONNET_MODEL,\n DEPLOYMENT_TARGET_ENVIRONMENTS,\n DEPLOYMENT_TARGET_PROVIDERS,\n DeleteProjectSubtaskRequestSchema,\n DeleteSubtaskRequestSchema,\n DeleteSubtaskResponseSchema,\n DiscoveredPortSchema,\n EMBEDDABLE_IMAGE_TYPES,\n EditManualTestRequestSchema,\n EditProjectManualTestRequestSchema,\n EmitAgentEventRequestSchema,\n FABLE_MODEL,\n FlushSingleQueuedMessageRequestSchema,\n FlushTaskQueueRequestSchema,\n GCP_ENVS,\n GenerateTaskIconRequestSchema,\n GetActivePtySessionRequestSchema,\n GetAgentStatusRequestSchema,\n GetChatMessagesRequestSchema,\n GetCliHistoryRequestSchema,\n GetCumulativeSpendingRequestSchema,\n GetCumulativeSpendingResponseSchema,\n GetDependenciesRequestSchema,\n GetProjectAttachmentRequestSchema,\n GetProjectSummaryRequestSchema,\n GetProjectTaskChatRequestSchema,\n GetProjectTaskCliRequestSchema,\n GetProjectTaskDependenciesRequestSchema,\n GetProjectTaskRequestSchema,\n GetProjectTaskSessionsRequestSchema,\n GetSuggestionsRequestSchema,\n GetTaskContextRequestSchema,\n GetTaskFileRequestSchema,\n GetTaskFilesRequestSchema,\n GetTaskPropertiesRequestSchema,\n GetTaskRequestSchema,\n GetUiCliHistoryRequestSchema,\n HeartbeatRequestSchema,\n HeartbeatResponseSchema,\n IDLE_HEARTBEAT_MS,\n ListAccessibleProjectsRequestSchema,\n ListIconsRequestSchema,\n ListManualTestsRequestSchema,\n ListProjectManualTestsRequestSchema,\n ListProjectMembersRequestSchema,\n ListProjectSubtasksRequestSchema,\n ListProjectTagsRequestSchema,\n ListProjectTaskFilesRequestSchema,\n ListProjectTasksRequestSchema,\n ListSubtasksRequestSchema,\n MAX_DISCOVERED_PORTS,\n MAX_FILE_SIZE_BYTES,\n MAX_LEVEL,\n MCP_TOOL_REGISTRY,\n MENTION_TOKEN_REGEX,\n ModelUsageEntrySchema,\n NotifyAgentVersionRequestSchema,\n PM_CHAT_HISTORY_LIMIT,\n PREVIEW_PORT_DENY_LIST,\n PREVIOUS_SONNET_MODEL,\n PROJECT_FUNCTION_DEFAULTS,\n PROJECT_TIMEZONE,\n PickFaIconRequestSchema,\n PostChildChatMessageRequestSchema,\n PostToChatInputSchema,\n PostToChatRequestSchema,\n PostToChatResponseSchema,\n PostToProjectTaskChatRequestSchema,\n PtyAttachRequestSchema,\n PtyInputRequestSchema,\n PtyOutputRequestSchema,\n PtyResizeRequestSchema,\n QueryManualTestsRequestSchema,\n QueryProjectGcpLogsRequestSchema,\n QueryProjectManualTestsRequestSchema,\n REPORT_XP_RATE,\n RETIRED_SONNET_MODEL,\n REVIEW_XP_RATE,\n RefreshGithubTokenRequestSchema,\n RefreshGithubTokenResponseSchema,\n RejectManualTestRequestSchema,\n RejectProjectManualTestRequestSchema,\n RemoveDependencyRequestSchema,\n RemoveManualTestRequestSchema,\n RemoveProjectManualTestRequestSchema,\n RemoveProjectTaskDependencyRequestSchema,\n RemoveProjectTaskReviewerRequestSchema,\n ReportAgentStatusRequestSchema,\n ReportDiscoveredPortsRequestSchema,\n RequestFileUploadRequestSchema,\n RequestProjectFileUploadRequestSchema,\n SIDECAR_OVERHEAD,\n SP_XP_RATE,\n STRANDED_RUNNER_STATUSES,\n SearchFaIconsRequestSchema,\n SearchProjectTasksRequestSchema,\n SendSoftStopRequestSchema,\n SessionStartRequestSchema,\n SessionStartResponseSchema,\n SessionStopRequestSchema,\n SessionStopResponseSchema,\n SetManualTestsRequestSchema,\n SetProjectManualTestsRequestSchema,\n StartChildCloudBuildRequestSchema,\n StartProjectBuildRequestSchema,\n StartProjectWorkspaceRequestSchema,\n StopChildBuildRequestSchema,\n StopProjectBuildRequestSchema,\n StopProjectWorkspaceRequestSchema,\n StoreSessionIdRequestSchema,\n StoreSessionIdResponseSchema,\n SubmitCodeReviewResultRequestSchema,\n TASK_CHAT_HISTORY_LIMIT,\n TASK_STATUS_ORDER,\n TERMINAL_TASK_STATUSES,\n TrackSpendingRequestSchema,\n TriggerIdentificationRequestSchema,\n UpdateChildStatusRequestSchema,\n UpdateProjectSubtaskRequestSchema,\n UpdateProjectTaskRequestSchema,\n UpdateSubtaskRequestSchema,\n UpdateTaskFieldsRequestSchema,\n UpdateTaskPropertiesRequestSchema,\n UpdateTaskStatusRequestSchema,\n UpdateTaskStatusResponseSchema,\n VoteProjectSuggestionRequestSchema,\n VoteSuggestionRequestSchema,\n WORKSPACE_DESIRED_STATES,\n WORKSPACE_OBSERVED_STATES,\n WORKSPACE_POD_PHASES,\n WORKSPACE_PURPOSES,\n WORKSPACE_SESSION_MODES,\n WORKSPACE_SESSION_ROLES,\n WORKSPACE_SESSION_STATUSES,\n buildMentionKey,\n cliRoom,\n computeMemoryBounds,\n computePodRatio,\n computeTotalXp,\n createAgentSessionRoom,\n createProjectRoom,\n deriveConnectionState,\n formatHeartbeatAge,\n generateDateRange,\n getToolsByCategory,\n isAllowablePreviewPort,\n isCuid,\n isEmbeddableFile,\n isValidAutopilotConfig,\n levelFromXp,\n messageMatchesFilters,\n notificationUserRoom,\n parseMentions,\n pickPreferredPreviewPort,\n projectCliRoom,\n projectEventsRoom,\n resolveAllowedPreviewPorts,\n resolveCodeReviewMode,\n resolveGcpEnvResources,\n resolveMentions,\n resolveProjectFunctionConfig,\n resolveStatDateRange,\n sanitizeDiscoveredPorts,\n sanitizeSessionPreviewPorts,\n serializeMention,\n serviceRoom,\n sidecarRequestTotals,\n todayInProjectTZ,\n userRoom,\n validateStatusForType,\n xpToReachLevel\n};\n","import type { AgentMode } from \"@project/shared\";\n\n// ── Mode action types ──────────────────────────────────────────────────────\n\nexport type ModeAction =\n | { type: \"noop\" }\n | { type: \"restart_query\"; newMode: AgentMode }\n | { type: \"soft_stop\" }\n | { type: \"start_auto\" };\n\n// ── Task context subset needed by ModeController ───────────────────────────\n\nexport interface ModeTaskContext {\n status: string;\n plan: string | null;\n storyPointId: string | null;\n isParentTask?: boolean;\n model: string;\n builderModel?: string | null;\n githubPRUrl?: string | null;\n}\n\n// ── ModeController: pure state machine with no I/O ─────────────────────────\n\nexport class ModeController {\n private _mode: AgentMode;\n private _hasExitedPlanMode = false;\n private _pendingModeRestart = false;\n private _runnerMode: \"task\" | \"pm\" | \"code-review\";\n private _isAuto: boolean;\n\n constructor(\n initialMode: AgentMode,\n runnerMode: \"task\" | \"pm\" | \"code-review\" = \"task\",\n isAuto = false,\n ) {\n this._mode = initialMode;\n this._runnerMode = runnerMode;\n this._isAuto = isAuto;\n }\n\n // ── Getters ────────────────────────────────────────────────────────\n\n get mode(): AgentMode {\n return this._mode;\n }\n\n get isAuto(): boolean {\n return this._isAuto;\n }\n\n get hasExitedPlanMode(): boolean {\n return this._hasExitedPlanMode;\n }\n\n set hasExitedPlanMode(val: boolean) {\n this._hasExitedPlanMode = val;\n }\n\n get pendingModeRestart(): boolean {\n return this._pendingModeRestart;\n }\n\n set pendingModeRestart(val: boolean) {\n this._pendingModeRestart = val;\n }\n\n /** Effective mode accounting for PM/task defaults */\n get effectiveMode(): AgentMode {\n if (this._mode) return this._mode;\n if (this._runnerMode === \"pm\") {\n return this._isAuto ? \"auto\" : \"discovery\";\n }\n return \"building\";\n }\n\n get isReadOnly(): boolean {\n const m = this.effectiveMode;\n if ([\"discovery\", \"help\"].includes(m)) return true;\n return m === \"auto\" && !this._hasExitedPlanMode;\n }\n\n get isAutoPlanning(): boolean {\n return this.effectiveMode === \"auto\" && !this._hasExitedPlanMode;\n }\n\n get isBuildCapable(): boolean {\n const m = this.effectiveMode;\n return m === \"building\" || m === \"review\" || (m === \"auto\" && this._hasExitedPlanMode);\n }\n\n /**\n * Apply authoritative mode from the server's task context.\n * Called after getTaskContext to override env-var defaults with the\n * actual task state — ensures pods that launch without CONVEYOR_AGENT_MODE\n * still get the correct mode.\n */\n applyServerMode(agentMode: AgentMode | null | undefined, isAuto: boolean | undefined): void {\n if (agentMode) {\n this._mode = agentMode;\n this._isAuto = agentMode === \"auto\" || !!isAuto;\n } else if (isAuto !== undefined) {\n this._isAuto = isAuto;\n if (isAuto && this._runnerMode === \"pm\" && !this._mode) {\n this._mode = \"auto\";\n }\n }\n\n // Safety net: discovery + isAuto means the server didn't set agentMode correctly\n if (this._isAuto && this._mode === \"discovery\") {\n this._mode = \"auto\";\n }\n }\n\n // ── Mode resolution ────────────────────────────────────────────────\n\n /** Resolve the initial mode based on task context */\n resolveInitialMode(context: ModeTaskContext): AgentMode {\n // Code-review runner maps to unified review mode\n if (this._runnerMode === \"code-review\") {\n this._mode = \"review\";\n return this._mode;\n }\n\n // Auto mode: check if we can bypass planning (already identified or past planning)\n if (this._mode === \"auto\" && this.canBypassPlanning(context)) {\n this.transitionToBuilding(context);\n return this._mode;\n }\n\n return this._mode;\n }\n\n /** Check if auto-mode can bypass planning (task already has plan + properties) */\n canBypassPlanning(context: ModeTaskContext): boolean {\n if (this._mode !== \"auto\") return false;\n if (context.status !== \"Planning\") return true;\n if (context.plan?.trim() && context.storyPointId) return true;\n return false;\n }\n\n // ── Mode transitions ───────────────────────────────────────────────\n\n /** Handle mode change from server */\n handleModeChange(newMode: AgentMode): ModeAction {\n if (newMode === this._mode) return { type: \"noop\" };\n\n // Task runners can transition to review mode (same-box code review)\n if (this._runnerMode === \"task\" && newMode === \"review\") {\n this._mode = newMode;\n return { type: \"restart_query\", newMode: \"review\" };\n }\n\n // Task runners can transition to building mode (server-side auto-advancement)\n if (this._runnerMode === \"task\" && newMode === \"building\") {\n this._mode = newMode;\n this._isAuto = true;\n this._hasExitedPlanMode = true;\n return { type: \"restart_query\", newMode: \"building\" };\n }\n\n // Task runners can transition to auto mode (e.g., Build button after discovery)\n if (this._runnerMode === \"task\" && newMode === \"auto\") {\n this._mode = newMode;\n this._isAuto = true;\n this._hasExitedPlanMode = true;\n return { type: \"restart_query\", newMode: \"auto\" };\n }\n\n // Already building in auto mode — server confirmed via wakeAgentForBuilding.\n // Update mode label but don't restart the running query.\n if (this._mode === \"auto\" && this._hasExitedPlanMode && newMode === \"building\") {\n this._mode = newMode;\n return { type: \"noop\" };\n }\n\n if (this._runnerMode !== \"pm\") return { type: \"noop\" };\n\n this._mode = newMode;\n this.updateExitedPlanModeFlag(newMode);\n\n if (this.isBuildCapable) {\n return { type: \"start_auto\" };\n }\n return { type: \"noop\" };\n }\n\n /** Handle ExitPlanMode call from the agent */\n handleExitPlanMode(context: ModeTaskContext): ModeAction {\n if (this._hasExitedPlanMode) return { type: \"noop\" };\n this.transitionToBuilding(context);\n this._pendingModeRestart = true;\n return { type: \"restart_query\", newMode: this._mode };\n }\n\n /** Check if pack runner behavior should be used */\n isPackRunner(context: ModeTaskContext): boolean {\n return !!context.isParentTask;\n }\n\n // ── Internal helpers ───────────────────────────────────────────────\n\n private transitionToBuilding(context: ModeTaskContext): void {\n this._hasExitedPlanMode = true;\n this._mode = context.isParentTask ? \"review\" : \"building\";\n }\n\n private updateExitedPlanModeFlag(newMode: AgentMode): void {\n if (newMode === \"building\") {\n this._hasExitedPlanMode = true;\n }\n // For auto mode, we can't set the flag without context — it gets\n // set during context fetch or when ExitPlanMode is called\n }\n}\n","// ── Configuration ──────────────────────────────────────────────────────────\n\nexport interface LifecycleConfig {\n /** Idle timeout before the agent stops (default: 30 min) */\n idleTimeoutMs: number;\n /** Dormant timeout — bound on dormant-after-completed wait (default: 60 min).\n * Defense-in-depth: the server-side polling is supposed to shut us down,\n * but if it regresses, the agent shuts itself down here. */\n dormantTimeoutMs: number;\n /** Heartbeat interval (default: 30s) */\n heartbeatIntervalMs: number;\n /** Token refresh interval (default: 45 min — before 1h GitHub token expiry) */\n tokenRefreshIntervalMs: number;\n /** Periodic WIP git flush interval (default: 2 min). Covers ungraceful\n * pod termination (OOMKilled, node eviction) where preStop doesn't run.\n * Set to `0` to disable the timer entirely — used for environments with\n * persistent state (local, workspace, GitHub Codespaces) that don't lose\n * in-flight work on a crash. */\n gitFlushIntervalMs: number;\n}\n\nexport interface LifecycleCallbacks {\n onHeartbeat: () => void;\n onIdleTimeout: () => void;\n onDormantTimeout: () => void;\n onTokenRefresh: () => void;\n onGitFlush: () => void;\n}\n\n// ── Default configuration ──────────────────────────────────────────────────\n\n/** 30 min idle, 60 min dormant, 30s heartbeat, 45 min token refresh, 2 min git flush */\nexport const DEFAULT_LIFECYCLE_CONFIG: LifecycleConfig = {\n idleTimeoutMs: 30 * 60 * 1000,\n dormantTimeoutMs: 60 * 60 * 1000,\n heartbeatIntervalMs: 30_000,\n tokenRefreshIntervalMs: 45 * 60 * 1000,\n gitFlushIntervalMs: 2 * 60 * 1000,\n};\n\n// ── Lifecycle: timer management for idle/heartbeat ───────────────────────\n\nexport class Lifecycle {\n readonly config: LifecycleConfig;\n private readonly callbacks: LifecycleCallbacks;\n\n private heartbeatTimer: ReturnType<typeof setInterval> | null = null;\n private tokenRefreshTimer: ReturnType<typeof setInterval> | null = null;\n private idleTimer: ReturnType<typeof setTimeout> | null = null;\n private idleCheckInterval: ReturnType<typeof setInterval> | null = null;\n private dormantTimer: ReturnType<typeof setTimeout> | null = null;\n private gitFlushTimer: ReturnType<typeof setInterval> | null = null;\n\n constructor(config: LifecycleConfig, callbacks: LifecycleCallbacks) {\n this.config = config;\n this.callbacks = callbacks;\n }\n\n // ── Heartbeat ──────────────────────────────────────────────────────\n\n startHeartbeat(): void {\n this.stopHeartbeat();\n this.heartbeatTimer = setInterval(() => {\n this.callbacks.onHeartbeat();\n }, this.config.heartbeatIntervalMs);\n }\n\n stopHeartbeat(): void {\n if (this.heartbeatTimer) {\n clearInterval(this.heartbeatTimer);\n this.heartbeatTimer = null;\n }\n }\n\n // ── Token refresh ─────────────────────────────────────────────────\n\n startTokenRefresh(): void {\n this.stopTokenRefresh();\n // Immediately refresh to ensure we have a fresh token at startup\n this.callbacks.onTokenRefresh();\n this.tokenRefreshTimer = setInterval(() => {\n this.callbacks.onTokenRefresh();\n }, this.config.tokenRefreshIntervalMs);\n }\n\n stopTokenRefresh(): void {\n if (this.tokenRefreshTimer) {\n clearInterval(this.tokenRefreshTimer);\n this.tokenRefreshTimer = null;\n }\n }\n\n // ── Periodic git flush ────────────────────────────────────────────\n\n startGitFlush(): void {\n this.stopGitFlush();\n if (this.config.gitFlushIntervalMs <= 0) return;\n this.gitFlushTimer = setInterval(() => {\n this.callbacks.onGitFlush();\n }, this.config.gitFlushIntervalMs);\n }\n\n stopGitFlush(): void {\n if (this.gitFlushTimer) {\n clearInterval(this.gitFlushTimer);\n this.gitFlushTimer = null;\n }\n }\n\n // ── Idle timer ─────────────────────────────────────────────────────\n\n startIdleTimer(): void {\n this.clearIdleTimers();\n this.idleTimer = setTimeout(() => {\n this.callbacks.onIdleTimeout();\n }, this.config.idleTimeoutMs);\n }\n\n cancelIdleTimer(): void {\n this.clearIdleTimers();\n }\n\n // ── Dormant timer ──────────────────────────────────────────────────\n\n /** Start (or restart) the dormant timer.\n * @param overrideMs Optional custom delay in ms. When provided, the timer\n * fires after exactly that delay instead of `dormantTimeoutMs`. SessionRunner\n * uses this to enforce an *absolute* deadline across cycles: even if the\n * dormant wait is interrupted by an inbound message, the next iteration\n * passes the remaining time, so the agent shuts down at the original\n * deadline regardless of message volume. */\n startDormantTimer(overrideMs?: number): void {\n this.cancelDormantTimer();\n const delay = Math.max(0, overrideMs ?? this.config.dormantTimeoutMs);\n this.dormantTimer = setTimeout(() => {\n this.callbacks.onDormantTimeout();\n }, delay);\n }\n\n cancelDormantTimer(): void {\n if (this.dormantTimer) {\n clearTimeout(this.dormantTimer);\n this.dormantTimer = null;\n }\n }\n\n // ── Cleanup ────────────────────────────────────────────────────────\n\n destroy(): void {\n this.stopHeartbeat();\n this.stopTokenRefresh();\n this.stopGitFlush();\n this.clearIdleTimers();\n this.cancelDormantTimer();\n }\n\n // ── Private ────────────────────────────────────────────────────────\n\n private clearIdleTimers(): void {\n if (this.idleTimer) {\n clearTimeout(this.idleTimer);\n this.idleTimer = null;\n }\n if (this.idleCheckInterval) {\n clearInterval(this.idleCheckInterval);\n this.idleCheckInterval = null;\n }\n }\n}\n","/**\n * Harness-neutral types for agent query execution.\n *\n * These types abstract the underlying agent SDK so that the runner,\n * execution, and tool layers never reference SDK-specific imports\n * directly. The only place that should import from\n * `@anthropic-ai/claude-agent-sdk` is `harness/claude-code/`.\n */\n\nimport type { z } from \"zod\";\n\n// ── Events emitted by the harness during a query ────────────────────────\n\nexport interface HarnessSystemInitEvent {\n type: \"system\";\n subtype: \"init\";\n session_id?: string;\n model: string;\n}\n\nexport interface HarnessCompactBoundaryEvent {\n type: \"system\";\n subtype: \"compact_boundary\";\n compact_metadata: { trigger: \"manual\" | \"auto\"; pre_tokens: number };\n}\n\nexport interface HarnessTaskStartedEvent {\n type: \"system\";\n subtype: \"task_started\";\n task_id: string;\n description: string;\n}\n\nexport interface HarnessTaskProgressEvent {\n type: \"system\";\n subtype: \"task_progress\";\n task_id: string;\n description: string;\n usage?: { tool_uses: number; duration_ms: number };\n}\n\nexport type HarnessSystemEvent =\n | HarnessSystemInitEvent\n | HarnessCompactBoundaryEvent\n | HarnessTaskStartedEvent\n | HarnessTaskProgressEvent;\n\nexport interface HarnessContentBlock {\n type: string;\n text?: string;\n name?: string;\n input?: unknown;\n id?: string;\n}\n\nexport interface HarnessAssistantEvent {\n type: \"assistant\";\n message: {\n role: \"assistant\";\n content: HarnessContentBlock[];\n usage?: {\n input_tokens?: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n };\n };\n}\n\nexport interface HarnessResultSuccessEvent {\n type: \"result\";\n subtype: \"success\";\n result: string;\n total_cost_usd: number;\n modelUsage?: Record<string, unknown>;\n sessionId?: string;\n}\n\nexport interface HarnessResultErrorEvent {\n type: \"result\";\n subtype: \"error\";\n errors: string[];\n sessionId?: string;\n}\n\nexport type HarnessResultEvent = HarnessResultSuccessEvent | HarnessResultErrorEvent;\n\nexport interface HarnessRateLimitEvent {\n type: \"rate_limit_event\";\n rate_limit_info: {\n status: string;\n rateLimitType?: string;\n utilization?: number;\n resetsAt?: unknown;\n };\n}\n\nexport interface HarnessToolProgressEvent {\n type: \"tool_progress\";\n tool_name?: string;\n elapsed_time_seconds?: number;\n}\n\nexport interface HarnessUserQuestion {\n question: string;\n header: string;\n options: { label: string; description: string }[];\n multiSelect?: boolean;\n}\n\n/**\n * PTY harness only: the interactive CLI is about to render an AskUserQuestion\n * questionnaire (observed via the PreToolUse hook). The TUI collects the\n * answer natively — this event exists so the runner can report\n * `waiting_for_input` while the questionnaire is pending. The SDK harness\n * never emits it (AskUserQuestion routes through `canUseTool` there).\n */\nexport interface HarnessUserQuestionEvent {\n type: \"user_question\";\n questions: HarnessUserQuestion[];\n}\n\nexport type HarnessEvent =\n | HarnessSystemEvent\n | HarnessAssistantEvent\n | HarnessResultEvent\n | HarnessRateLimitEvent\n | HarnessToolProgressEvent\n | HarnessUserQuestionEvent;\n\n// ── User message fed into a query ───────────────────────────────────────\n\nexport interface HarnessUserMessage {\n type: \"user\";\n session_id: string;\n message: { role: \"user\"; content: string | unknown[] };\n parent_tool_use_id: null;\n}\n\n// ── Tool definition (harness-neutral) ───────────────────────────────────\n\nexport interface HarnessToolAnnotations {\n readOnlyHint?: boolean;\n}\n\n/* eslint-disable @typescript-eslint/no-explicit-any -- generic tool handler */\nexport interface HarnessToolDefinition {\n name: string;\n description: string;\n schema: z.ZodRawShape;\n handler: (\n input: any,\n ) => Promise<{ content: { type: string; text?: string; data?: string; mimeType?: string }[] }>;\n annotations?: HarnessToolAnnotations;\n}\n/* eslint-enable @typescript-eslint/no-explicit-any */\n\n// ── Hook types ──────────────────────────────────────────────────────────\n\nexport interface HarnessHookInput {\n hook_event_name: string;\n tool_name: string;\n tool_response: unknown;\n}\n\nexport interface HarnessHookOutput {\n continue: boolean;\n}\n\nexport type HarnessPostToolUseHook = (input: HarnessHookInput) => Promise<HarnessHookOutput>;\n\n// ── MCP server handle (opaque to the runner) ────────────────────────────\n\n/** Opaque handle returned by `AgentHarness.createMcpServer()`. */\nexport type HarnessMcpServer = unknown;\n\n// ── PTY relay bridge ────────────────────────────────────────────────────\n\n/**\n * Bidirectional bridge between a PTY harness session and the S2 server relay.\n *\n * Kept harness-neutral (no AgentConnection import) so this module never depends\n * on the connection layer. Only the PTY harness consumes it; the SDK harness\n * ignores it. The runner adapts an `AgentConnection` into this shape.\n */\nexport interface PtyBridge {\n /** Forward a raw chunk of terminal output to the relay (fire-and-forget). */\n sendOutput(data: string, dims?: { cols: number; rows: number }): void;\n /** Subscribe to user keystrokes forwarded from the relay. Returns unsubscribe. */\n onInput(handler: (data: string) => void): () => void;\n /** Subscribe to reconciled terminal-resize events from the relay. Returns unsubscribe. */\n onResize(handler: (cols: number, rows: number) => void): () => void;\n}\n\n// ── Query options ───────────────────────────────────────────────────────\n\nexport interface HarnessQueryOptions {\n model: string;\n systemPrompt: unknown;\n cwd: string;\n permissionMode: \"plan\" | \"bypassPermissions\";\n allowDangerouslySkipPermissions: boolean;\n tools: { type: \"preset\"; preset: \"claude_code\" };\n mcpServers: Record<string, HarnessMcpServer>;\n settingSources?: (\"user\" | \"project\" | \"local\")[];\n sandbox?: { enabled: boolean };\n maxTurns?: number;\n effort?: string;\n thinking?: unknown;\n betas?: unknown;\n disallowedTools?: string[];\n abortController?: AbortController;\n enableFileCheckpointing?: boolean;\n canUseTool?: (\n toolName: string,\n input: Record<string, unknown>,\n ) => Promise<\n | { behavior: \"allow\"; updatedInput?: Record<string, unknown> }\n | { behavior: \"deny\"; message: string }\n >;\n hooks?: Record<string, { hooks: HarnessPostToolUseHook[]; timeout: number }[]>;\n resume?: string;\n sessionId?: string;\n stderr?: (data: string) => void;\n /**\n * How the PTY harness delivers the query prompt to the spawned CLI:\n * - \"submit\" (default): paste the prompt and press Enter — the turn runs\n * immediately (auto-mode tasks, follow-up chat messages, resumes).\n * - \"prefill\": paste the prompt into the TUI input WITHOUT submitting, so\n * a human at the Connected-TUI terminal can review/edit/Enter it\n * (manual-mode initial instructions).\n * The SDK harness has no interactive input box and ignores this option.\n */\n promptDelivery?: \"submit\" | \"prefill\";\n /**\n * Extra system-prompt text passed to the spawned CLI via\n * `--append-system-prompt`. PTY harness only — the SDK harness already\n * receives the full system prompt through `systemPrompt.append` and ignores\n * this field.\n */\n appendSystemPrompt?: string;\n /**\n * PTY harness only: after the PreToolUse hook allows an ExitPlanMode call,\n * the interactive CLI still shows the plan-approval dialog (a hook \"allow\"\n * does not bypass it). When set, the session presses Enter to accept the\n * default option (\"Yes, auto-accept edits\") so an autonomous agent\n * continues building in the same session without a human at the terminal.\n * Conveyor's validation already happened in the hook — the dialog is\n * residual UX at that point.\n */\n planDialogAutoAccept?: boolean;\n}\n\n// ── Tool definition helper ──────────────────────────────────────────────\n\n/**\n * Construct a `HarnessToolDefinition` with the same signature as the SDK's\n * `tool()` helper, but without importing the SDK. The harness implementation\n * converts these into SDK-native tools when `createMcpServer()` is called.\n */\nexport function defineTool<T extends z.ZodRawShape>(\n name: string,\n description: string,\n schema: T,\n handler: (\n input: z.infer<z.ZodObject<T>>,\n ) => Promise<{ content: { type: string; text?: string; data?: string; mimeType?: string }[] }>,\n options?: { annotations?: HarnessToolAnnotations },\n): HarnessToolDefinition {\n return {\n name,\n description,\n schema,\n handler: handler as HarnessToolDefinition[\"handler\"],\n annotations: options?.annotations,\n };\n}\n\n// ── AgentHarness interface ──────────────────────────────────────────────\n\nexport interface AgentHarness {\n /** Start a streaming query and return an async generator of events. */\n executeQuery(options: {\n prompt: string | AsyncGenerator<HarnessUserMessage, void, unknown>;\n options: HarnessQueryOptions;\n resume?: string;\n }): AsyncGenerator<HarnessEvent, void>;\n\n /** Wrap an array of harness-neutral tool definitions into an MCP server. */\n createMcpServer(config: { name: string; tools: HarnessToolDefinition[] }): HarnessMcpServer;\n\n /**\n * Force the active terminal (if any) to redraw its full screen. PTY-only:\n * used after a socket reconnect to re-seed the server's per-process\n * scrollback ring. Optional — the SDK harness has no terminal and omits it.\n */\n forceRepaint?(): void;\n}\n","/**\n * ClaudeCodeHarness — wraps `@anthropic-ai/claude-agent-sdk` behind the\n * generic `AgentHarness` interface.\n *\n * This is the ONLY module that should import from the SDK.\n */\n\nimport { query, tool, createSdkMcpServer } from \"@anthropic-ai/claude-agent-sdk\";\nimport type {\n AgentHarness,\n HarnessEvent,\n HarnessQueryOptions,\n HarnessToolDefinition,\n HarnessMcpServer,\n HarnessUserMessage,\n} from \"../types.js\";\n\nexport class ClaudeCodeHarness implements AgentHarness {\n async *executeQuery(opts: {\n prompt: string | AsyncGenerator<HarnessUserMessage, void, unknown>;\n options: HarnessQueryOptions;\n resume?: string;\n }): AsyncGenerator<HarnessEvent, void> {\n const sdkEvents = query({\n prompt: opts.prompt as Parameters<typeof query>[0][\"prompt\"],\n options: {\n ...(opts.options as Parameters<typeof query>[0][\"options\"]),\n ...(opts.resume ? { resume: opts.resume } : {}),\n ...(opts.options.sessionId ? { sessionId: opts.options.sessionId } : {}),\n ...(opts.options.abortController ? { abortController: opts.options.abortController } : {}),\n },\n });\n\n for await (const event of sdkEvents) {\n yield event as unknown as HarnessEvent;\n }\n }\n\n createMcpServer(config: { name: string; tools: HarnessToolDefinition[] }): HarnessMcpServer {\n const sdkTools = config.tools.map((t) =>\n tool(\n t.name,\n t.description,\n t.schema,\n t.handler as Parameters<typeof tool>[3],\n t.annotations ? { annotations: t.annotations } : undefined,\n ),\n );\n return createSdkMcpServer({ name: config.name, tools: sdkTools });\n }\n}\n","/* oxlint-disable import/max-dependencies -- session orchestrator aggregates the cohesive pty submodules (queue, tailer, hook socket, spawn args, settings, coalescer, tool server) */\n/**\n * PtySession — orchestrates one `claude` CLI run under a pseudo-terminal.\n *\n * It merges two event sources into a single stream:\n * 1. the on-disk transcript JSONL (tailed via JsonlTailer), and\n * 2. PostToolUse progress envelopes relayed over a Unix socket.\n *\n * Raw PTY stdout is never turned into HarnessEvents — only the trusted\n * transcript file and the validated socket envelopes become events. When a\n * PtyBridge is supplied, that raw stdout is instead mirrored verbatim to the\n * S2 relay so the S5 \"Connected TUI\" terminal can render it, and relayed\n * keystrokes / resizes are fed back into the pty.\n *\n * `node-pty` is loaded lazily so that SDK-only consumers never pull in the\n * native module.\n */\n\nimport { mkdtemp, mkdir, rm, stat } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join, dirname } from \"node:path\";\nimport type {\n HarnessEvent,\n HarnessQueryOptions,\n HarnessUserMessage,\n HarnessUserQuestion,\n PtyBridge,\n} from \"../types.js\";\nimport { AsyncEventQueue } from \"./event-queue.js\";\nimport {\n HookSocketServer,\n type ToolProgress,\n type PreToolUseRequest,\n type PreToolUseVerdict,\n} from \"./hook-socket.js\";\nimport { JsonlTailer } from \"./jsonl-tailer.js\";\nimport { buildSpawnArgs, resolveClaudeBinary, buildExitErrors } from \"./spawn-args.js\";\nimport { writeHookSettings, sessionTranscriptPath } from \"./settings.js\";\nimport { PtyOutputCoalescer } from \"./output-coalescer.js\";\nimport { PtyToolServer, startToolServers } from \"./tool-server.js\";\n\n// Cap on the rolling tail of raw terminal output retained for diagnostics when\n// `claude` exits without a result. Bounded so a long-running session can't grow\n// this unboundedly; only the most recent bytes (where a failure surfaces) matter.\nconst MAX_DIAGNOSTIC_OUTPUT = 4000;\n\ninterface PtyProcess {\n onData(listener: (data: string) => void): void;\n onExit(listener: (event: { exitCode: number }) => void): void;\n write(data: string): void;\n resize(cols: number, rows: number): void;\n kill(signal?: string): void;\n}\n\ninterface PtySpawnOptions {\n name: string;\n cols: number;\n rows: number;\n cwd: string;\n env: Record<string, string>;\n}\n\ntype PtySpawn = (file: string, args: string[], options: PtySpawnOptions) => PtyProcess;\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\nfunction extractSpawn(mod: unknown): PtySpawn | null {\n if (!isRecord(mod)) return null;\n if (typeof mod.spawn === \"function\") return mod.spawn as PtySpawn;\n const def = mod.default;\n if (isRecord(def) && typeof def.spawn === \"function\") return def.spawn as PtySpawn;\n return null;\n}\n\nasync function loadPtySpawn(): Promise<PtySpawn> {\n const mod: unknown = await import(\"node-pty\");\n const spawn = extractSpawn(mod);\n if (!spawn) throw new Error(\"node-pty: spawn export not found\");\n return spawn;\n}\n\nexport function inheritedEnv(socketPath: string): Record<string, string> {\n const env: Record<string, string> = {};\n for (const [key, value] of Object.entries(process.env)) {\n if (typeof value === \"string\") env[key] = value;\n }\n // Do NOT force CLAUDE_CONFIG_DIR. Forcing it to ~/.claude makes the CLI read\n // <dir>/.claude.json — a fresh, un-onboarded config — instead of the user's\n // real ~/.claude.json, which re-triggers the first-run theme picker + login\n // even though valid credentials already exist in ~/.claude/. The loop above\n // already propagates an explicitly-set CLAUDE_CONFIG_DIR (pods/codespaces),\n // and the config dir is unchanged either way, so transcript tailing (which\n // uses claudeConfigHome()) still resolves to the same projects/ directory.\n env.CONVEYOR_HOOK_SOCKET = socketPath;\n return env;\n}\n\n/**\n * The bracketed-paste bytes written to the CLI's stdin to deliver a prompt.\n * The text is wrapped in paste markers so embedded newlines land as literal\n * lines in the input box instead of submitting it early. The submitting Enter\n * is deliberately NOT part of these bytes: deliverPrompt() sends it as a\n * separate write after a settle window, because an Enter folded into the same\n * chunk as the paste can be swallowed by the CLI's paste-burst handling —\n * observed in production as an auto-mode prompt parked unsubmitted in the\n * input box. \"prefill\" delivery never sends an Enter at all.\n */\nexport function buildPromptBytes(text: string): string {\n return `\\x1b[200~${text}\\x1b[201~`;\n}\n\n/** Settle window between the paste write and the submitting Enter write. */\nconst SUBMIT_SETTLE_MS = 300;\n// Re-press cadence/bounds for the submit nudge (see armSubmitNudge). Fast\n// presses cover the Enter-swallowed-at-startup race; the slow phase covers\n// startup dialogs that render tens of seconds in on a cold pod (folder\n// trust, onboarding) — observed live 2026-07-02 parking code reviews ~13min+\n// when the trust dialog mounted after the fast window had expired.\nconst SUBMIT_NUDGE_INTERVAL_MS = 2000;\nconst SUBMIT_NUDGE_MAX_PRESSES = 5;\nconst SUBMIT_NUDGE_SLOW_INTERVAL_MS = 5000;\nconst SUBMIT_NUDGE_WINDOW_MS = 90_000;\n\nfunction sleep(ms: number): Promise<void> {\n return new Promise((resolve) => {\n setTimeout(resolve, ms);\n });\n}\n\n/** Current size of the transcript, or 0 if it does not exist yet. */\nasync function transcriptSize(path: string): Promise<number> {\n try {\n return (await stat(path)).size;\n } catch {\n return 0;\n }\n}\n\n/**\n * Defensive extraction of AskUserQuestion's `questions` input from the hook\n * payload. Malformed entries are dropped rather than thrown — the event is\n * observe-only, so an empty list still arms the waiting_for_input report.\n */\nexport function parseUserQuestions(input: Record<string, unknown>): HarnessUserQuestion[] {\n if (!Array.isArray(input.questions)) return [];\n const questions: HarnessUserQuestion[] = [];\n for (const entry of input.questions) {\n if (!isRecord(entry)) continue;\n if (typeof entry.question !== \"string\") continue;\n const options = Array.isArray(entry.options)\n ? entry.options\n .filter(isRecord)\n .filter((o) => typeof o.label === \"string\")\n .map((o) => ({\n label: o.label as string,\n description: typeof o.description === \"string\" ? o.description : \"\",\n }))\n : [];\n questions.push({\n question: entry.question,\n header: typeof entry.header === \"string\" ? entry.header : \"\",\n options,\n ...(typeof entry.multiSelect === \"boolean\" ? { multiSelect: entry.multiSelect } : {}),\n });\n }\n return questions;\n}\n\nexport class PtySession {\n private readonly queue = new AsyncEventQueue<HarnessEvent>();\n private socket: HookSocketServer | null = null;\n private tailer: JsonlTailer | null = null;\n private pty: PtyProcess | null = null;\n private tempDir = \"\";\n private sawResult = false;\n // Rolling tail of raw PTY output, retained only to enrich the error when the\n // CLI exits before emitting a result (the bytes are otherwise relayed to S5\n // and never become events). Trimmed to MAX_DIAGNOSTIC_OUTPUT on every write.\n private recentOutput = \"\";\n private coalescer: PtyOutputCoalescer | null = null;\n private _toreDown = false;\n private readonly exitListeners: ((code: number) => void)[] = [];\n private readonly idleListeners: (() => void)[] = [];\n private abortHandler: (() => void) | null = null;\n private cols = 120;\n private rows = 40;\n private unsubInput: (() => void) | null = null;\n private unsubResize: (() => void) | null = null;\n // In-process HTTP MCP servers exposing the harness tools to the spawned CLI,\n // plus the path to the `--mcp-config` that points at them.\n private toolServers: PtyToolServer[] = [];\n private mcpConfigPath: string | null = null;\n // Plan-dialog auto-accept state (see armPlanDialogAutoAccept).\n private pendingPlanApproval = false;\n private planApprovalTimer: NodeJS.Timeout | null = null;\n // Submit-nudge state (see armSubmitNudge).\n private pendingSubmitNudge = false;\n private submitNudgeTimer: NodeJS.Timeout | null = null;\n\n constructor(\n private readonly prompt: string | AsyncGenerator<HarnessUserMessage, void, unknown>,\n private readonly options: HarnessQueryOptions,\n private readonly resume?: string,\n private readonly bridge?: PtyBridge,\n ) {}\n\n onIdle(listener: () => void): void {\n this.idleListeners.push(listener);\n }\n\n onExit(listener: (code: number) => void): void {\n this.exitListeners.push(listener);\n }\n\n get isToreDown(): boolean {\n return this._toreDown;\n }\n\n get hookSocketPath(): string | null {\n return this.socket ? this.socket.socketPath : null;\n }\n\n events(): AsyncGenerator<HarnessEvent, void> {\n return this.queue.drain();\n }\n\n async start(): Promise<void> {\n // Fail fast before allocating resources: the tailer can only locate the\n // transcript if we know which session id the CLI will write to.\n const sessionId = this.resume ?? this.options.sessionId;\n if (!sessionId) {\n throw new Error(\"PtySession requires options.sessionId or a resume target\");\n }\n // stop()/softStop() abort the query's shared AbortController. The SDK\n // harness consumes it natively; under the PTY harness we must translate an\n // abort into teardown() — otherwise a mid-turn `claude` (which may never\n // emit a transcript `result` and does not exit) is left running while the\n // event consumer stays parked on the queue.\n const signal = this.options.abortController?.signal;\n if (signal?.aborted) {\n // Already aborted before we allocated anything — tear down (which closes\n // the empty queue so a parked consumer completes) and bail.\n await this.teardown();\n return;\n }\n try {\n this.tempDir = await mkdtemp(join(tmpdir(), \"conveyor-pty-\"));\n const socketPath = join(this.tempDir, \"hook.sock\");\n this.socket = new HookSocketServer(\n socketPath,\n (progress) => this.handleProgress(progress),\n (request) => this.handlePreToolUse(request),\n );\n await this.socket.listen();\n const { settingsPath } = await writeHookSettings(this.tempDir);\n // Expose the harness's in-process tools to the spawned CLI over a loopback\n // HTTP MCP server, written into a `--mcp-config` consumed by spawn().\n await this.setupToolServers();\n const transcriptPath = sessionTranscriptPath(this.options.cwd, sessionId);\n await mkdir(dirname(transcriptPath), { recursive: true });\n // On resume the transcript already holds the prior session's records; start\n // tailing at EOF so historical records aren't replayed as fresh events.\n const startOffset = this.resume ? await transcriptSize(transcriptPath) : 0;\n this.tailer = new JsonlTailer(transcriptPath, (event) => this.handleTranscriptEvent(event));\n this.tailer.start(startOffset);\n await this.spawn(settingsPath, socketPath);\n // Register after spawn so the handler has a live pty to kill, then\n // re-check: an abort racing with allocation (fired before the listener\n // attached) would otherwise be missed.\n if (signal) {\n this.abortHandler = () => {\n void this.teardown();\n };\n signal.addEventListener(\"abort\", this.abortHandler, { once: true });\n if (signal.aborted) {\n await this.teardown();\n return;\n }\n }\n // Wire relayed keystrokes / resizes into the live pty. Registered only\n // after a successful spawn so writeStdin/resizePty have a process to\n // target; the unsubscribers are cleared in teardown().\n if (this.bridge) {\n this.unsubInput = this.bridge.onInput((data) => this.writeStdin(data));\n this.unsubResize = this.bridge.onResize((cols, rows) => this.resizePty(cols, rows));\n }\n await this.feedPrompt();\n } catch (err) {\n // A failure after we begin allocating (socket listen, tailer interval,\n // temp dir, spawn) would otherwise leak those resources: the PtyHarness\n // consumer only calls teardown() once start() has resolved.\n await this.teardown();\n throw err;\n }\n }\n\n writeStdin(text: string): void {\n this.pty?.write(text);\n }\n\n /** Apply a relayed resize to the live pty (reconciled dims from the server). */\n private resizePty(cols: number, rows: number): void {\n if (cols <= 0 || rows <= 0) return;\n this.cols = cols;\n this.rows = rows;\n try {\n this.pty?.resize(cols, rows);\n } catch {\n /* pty already exited */\n }\n }\n\n /**\n * Force the CLI to repaint its full screen by wiggling the pty size\n * (SIGWINCH). Used after a socket reconnect: the server's scrollback ring is\n * per-process and starts empty on a new instance, so without a repaint a\n * quiet TUI would leave the Connected-TUI terminal blank (and hidden) until\n * the CLI next draws on its own.\n */\n forceRepaint(): void {\n if (!this.pty) return;\n try {\n this.pty.resize(this.cols, Math.max(1, this.rows - 1));\n this.pty.resize(this.cols, this.rows);\n } catch {\n /* pty already exited */\n }\n }\n\n async teardown(): Promise<void> {\n if (this._toreDown) return;\n this._toreDown = true;\n this.disarmPlanDialogAutoAccept();\n this.disarmSubmitNudge();\n this.unsubInput?.();\n this.unsubInput = null;\n this.unsubResize?.();\n this.unsubResize = null;\n if (this.abortHandler) {\n this.options.abortController?.signal.removeEventListener(\"abort\", this.abortHandler);\n this.abortHandler = null;\n }\n try {\n this.pty?.kill();\n } catch {\n /* pty already exited */\n }\n this.pty = null;\n this.coalescer?.dispose();\n this.coalescer = null;\n this.tailer?.close();\n this.tailer = null;\n if (this.socket) {\n await this.socket.close();\n this.socket = null;\n }\n for (const toolServer of this.toolServers) {\n try {\n await toolServer.close();\n } catch {\n /* already closed */\n }\n }\n this.toolServers = [];\n this.mcpConfigPath = null;\n this.queue.close();\n if (this.tempDir) {\n await rm(this.tempDir, { recursive: true, force: true });\n this.tempDir = \"\";\n }\n }\n\n /**\n * Serve the harness's in-process tools to the spawned CLI over loopback HTTP\n * (handlers run in THIS process against the live task-token connection) and\n * record the `--mcp-config` path for spawn(). No-op when the harness was\n * constructed without tools (e.g. SDK-only callers).\n */\n private async setupToolServers(): Promise<void> {\n const { servers, mcpConfigPath } = await startToolServers(\n this.options.mcpServers ?? {},\n this.tempDir,\n );\n this.toolServers = servers;\n this.mcpConfigPath = mcpConfigPath;\n }\n\n private async spawn(settingsPath: string, socketPath: string): Promise<void> {\n const args = buildSpawnArgs({\n resume: this.resume,\n sessionId: this.options.sessionId,\n model: this.options.model,\n permissionMode: this.options.permissionMode,\n settingsPath,\n ...(this.options.appendSystemPrompt\n ? { appendSystemPrompt: this.options.appendSystemPrompt }\n : {}),\n // Only this config: ignore the user's ~/.claude.json / project .mcp.json\n // so the agent's tool set is deterministic (and a stale personal conveyor\n // server doesn't load).\n ...(this.mcpConfigPath ? { mcpConfigPath: this.mcpConfigPath, strictMcpConfig: true } : {}),\n });\n const spawn = await loadPtySpawn();\n const pty = spawn(resolveClaudeBinary(), args, {\n name: \"xterm-color\",\n cols: this.cols,\n rows: this.rows,\n cwd: this.options.cwd,\n env: inheritedEnv(socketPath),\n });\n // Mirror raw terminal output to the relay (and on to the S5 terminal). The\n // first flush creates the server-side scrollback ring — which is what makes\n // the Connected-TUI terminal appear, i.e. this doubles as the attach\n // handshake. Output is coalesced (~40ms windows) so a busy redraw becomes\n // one relay call instead of tens — per-frame server cost was starving the\n // stream. Stdout is intentionally NOT turned into HarnessEvents.\n const bridge = this.bridge;\n if (bridge) {\n this.coalescer = new PtyOutputCoalescer(\n (data, dims) => {\n bridge.sendOutput(data, dims);\n },\n () => ({ cols: this.cols, rows: this.rows }),\n );\n }\n pty.onData((data) => {\n this.coalescer?.write(data);\n // Retain a bounded tail so finalizeOnExit can explain an early exit.\n this.recentOutput = (this.recentOutput + data).slice(-MAX_DIAGNOSTIC_OUTPUT);\n });\n pty.onExit((event) => {\n void this.finalizeOnExit(event.exitCode);\n });\n this.pty = pty;\n }\n\n private async deliverPrompt(text: string): Promise<void> {\n this.writeStdin(buildPromptBytes(text));\n if (this.options.promptDelivery === \"prefill\") return;\n // The Enter goes in a separate write after a settle window — folded into\n // the same chunk as the paste, the CLI can treat it as part of the paste\n // burst and leave the prompt parked unsubmitted in the input box.\n await sleep(SUBMIT_SETTLE_MS);\n if (this._toreDown) return;\n this.writeStdin(\"\\r\");\n this.armSubmitNudge();\n }\n\n private async feedPrompt(): Promise<void> {\n if (typeof this.prompt === \"string\") {\n await this.deliverPrompt(this.prompt);\n return;\n }\n for await (const message of this.prompt) {\n const content = message.message.content;\n const text = typeof content === \"string\" ? content : JSON.stringify(content);\n await this.deliverPrompt(text);\n }\n }\n\n /**\n * Even as a separate write, the submitting Enter can race CLI startup and\n * be swallowed, leaving the pasted prompt parked in the input box with\n * nothing to un-park it (the 45s parked-TUI watchdog only reports status).\n * Until the first transcript record proves the turn started, re-press Enter\n * on a bounded interval. Enter on an empty or mid-turn input box is a no-op.\n * Deliberate trade-off (same as the plan-dialog auto-accept below): a press\n * can accept the default of an unexpected startup dialog — in a headless\n * pod that unblocks the run rather than parking it forever.\n *\n * Two phases: SUBMIT_NUDGE_MAX_PRESSES fast presses for the swallowed-Enter\n * race, then a slow cadence out to SUBMIT_NUDGE_WINDOW_MS for startup\n * dialogs that render late on cold pods (the folder-trust dialog's default\n * is the accept option, so one late Enter un-parks the run).\n */\n private armSubmitNudge(): void {\n if (this.submitNudgeTimer) return;\n this.pendingSubmitNudge = true;\n const startedAt = Date.now();\n let presses = 0;\n const press = (): void => {\n if (\n this._toreDown ||\n !this.pendingSubmitNudge ||\n Date.now() - startedAt >= SUBMIT_NUDGE_WINDOW_MS\n ) {\n this.disarmSubmitNudge();\n return;\n }\n presses++;\n this.writeStdin(\"\\r\");\n if (presses === SUBMIT_NUDGE_MAX_PRESSES && this.submitNudgeTimer) {\n clearInterval(this.submitNudgeTimer);\n this.submitNudgeTimer = setInterval(press, SUBMIT_NUDGE_SLOW_INTERVAL_MS);\n }\n };\n this.submitNudgeTimer = setInterval(press, SUBMIT_NUDGE_INTERVAL_MS);\n }\n\n private disarmSubmitNudge(): void {\n this.pendingSubmitNudge = false;\n if (this.submitNudgeTimer) {\n clearInterval(this.submitNudgeTimer);\n this.submitNudgeTimer = null;\n }\n }\n\n private handleProgress(progress: ToolProgress): void {\n this.queue.push({\n type: \"tool_progress\",\n ...(progress.tool_name === undefined ? {} : { tool_name: progress.tool_name }),\n ...(progress.elapsed_time_seconds === undefined\n ? {}\n : { elapsed_time_seconds: progress.elapsed_time_seconds }),\n });\n }\n\n /**\n * PreToolUse request from the hook helper → the runner's `canUseTool`\n * verdict. ExitPlanMode is the Conveyor plan-exit gate (validation +\n * identification trigger run inside the callback); AskUserQuestion is\n * observed and always allowed. Absent callback → allow (mirrors the SDK\n * default).\n */\n private async handlePreToolUse(request: PreToolUseRequest): Promise<PreToolUseVerdict> {\n if (request.tool_name === \"AskUserQuestion\") {\n // Observe-only: the TUI renders the questionnaire and collects the\n // answer natively. Never delegate to `canUseTool` — the SDK-era handler\n // there parks on a blocking RPC, which under PTY would time the hook\n // out and deny the questionnaire. Disarm the submit nudge first: a\n // pending Enter press would answer the dialog's default option.\n this.disarmSubmitNudge();\n this.queue.push({ type: \"user_question\", questions: parseUserQuestions(request.tool_input) });\n return { decision: \"allow\" };\n }\n const canUseTool = this.options.canUseTool;\n let verdict: PreToolUseVerdict;\n if (canUseTool) {\n const result = await canUseTool(request.tool_name, request.tool_input);\n verdict =\n result.behavior === \"allow\"\n ? { decision: \"allow\" }\n : { decision: \"deny\", reason: result.message };\n } else {\n verdict = { decision: \"allow\" };\n }\n if (\n verdict.decision === \"allow\" &&\n request.tool_name === \"ExitPlanMode\" &&\n this.options.planDialogAutoAccept\n ) {\n this.armPlanDialogAutoAccept();\n }\n return verdict;\n }\n\n /**\n * A hook \"allow\" does not bypass the CLI's plan-approval dialog — it renders\n * right after the verdict. Press Enter (default: \"Yes, auto-accept edits\")\n * until the turn resumes; the next transcript record only lands once the\n * dialog is answered, so it doubles as the stop signal.\n */\n private armPlanDialogAutoAccept(): void {\n if (this.planApprovalTimer) return;\n this.pendingPlanApproval = true;\n let presses = 0;\n const press = (): void => {\n if (this._toreDown || !this.pendingPlanApproval || presses >= 6) {\n this.disarmPlanDialogAutoAccept();\n return;\n }\n presses++;\n this.writeStdin(\"\\r\");\n };\n this.planApprovalTimer = setInterval(press, 1500);\n setTimeout(press, 700);\n }\n\n private disarmPlanDialogAutoAccept(): void {\n this.pendingPlanApproval = false;\n if (this.planApprovalTimer) {\n clearInterval(this.planApprovalTimer);\n this.planApprovalTimer = null;\n }\n }\n\n private handleTranscriptEvent(event: HarnessEvent): void {\n // Any new transcript record after an allowed ExitPlanMode means the plan\n // dialog was answered — stop pressing Enter.\n if (this.pendingPlanApproval) this.disarmPlanDialogAutoAccept();\n // Any new transcript record proves the submitted prompt started a turn —\n // the submit nudge has done its job.\n if (this.pendingSubmitNudge) this.disarmSubmitNudge();\n this.queue.push(event);\n if (event.type === \"result\") {\n this.sawResult = true;\n for (const listener of this.idleListeners) listener();\n // A transcript `result` marks end-of-query. Close the stream so the\n // generator completes — mirroring the SDK harness's per-query model.\n // Interactive `claude` does not exit after a result, so we must not wait\n // for process exit to terminate the event stream.\n this.queue.close();\n }\n }\n\n private async finalizeOnExit(exitCode: number): Promise<void> {\n // Ship any buffered terminal tail (exit message, final repaint) before the\n // relay goes quiet — runs even on the teardown path, where dispose() below\n // may already have flushed (flush is a no-op when empty).\n this.coalescer?.flush();\n // A teardown-driven kill (stop/softStop/abort) fires this exit handler, but\n // the turn is already discarded — pushing a synthetic error result here\n // would be spurious and would race teardown()'s queue.close().\n if (this._toreDown) return;\n if (this.tailer) {\n this.tailer.close();\n await this.tailer.flush();\n }\n if (!this.sawResult) {\n // Fold the swallowed terminal tail into the error so a bare exit (missing\n // `claude` binary, auth stop, unknown flag) is diagnosable from the logs\n // rather than only from the live S5 terminal.\n this.queue.push({\n type: \"result\",\n subtype: \"error\",\n errors: buildExitErrors(exitCode, this.recentOutput, resolveClaudeBinary()),\n });\n }\n for (const listener of this.exitListeners) listener(exitCode);\n this.queue.close();\n }\n}\n","/**\n * AsyncEventQueue — bridges callback-style producers (transcript tailer, hook\n * socket) into a single async-generator consumer. Producers call `push`;\n * the consumer drains via the async generator returned by `drain()`.\n */\nexport class AsyncEventQueue<T> {\n private readonly items: T[] = [];\n private closed = false;\n private wake: (() => void) | null = null;\n\n push(item: T): void {\n if (this.closed) return;\n this.items.push(item);\n this.signal();\n }\n\n close(): void {\n this.closed = true;\n this.signal();\n }\n\n get isClosed(): boolean {\n return this.closed;\n }\n\n private signal(): void {\n const wake = this.wake;\n if (wake) {\n this.wake = null;\n wake();\n }\n }\n\n async *drain(): AsyncGenerator<T, void> {\n while (!this.closed || this.items.length > 0) {\n if (this.items.length > 0) {\n const item = this.items.shift();\n if (item !== undefined) yield item;\n continue;\n }\n await new Promise<void>((resolve) => {\n this.wake = resolve;\n });\n }\n }\n}\n","/**\n * Unix-domain socket server that receives hook envelopes from the hook helper:\n *\n * - PostToolUse progress envelopes (fire-and-forget) → `tool_progress` events\n * - PreToolUse requests (`kind: \"pre_tool_use\"`) → request/response: the\n * handler's verdict is written back on the SAME connection, correlated by\n * `id`, so the helper can print a permissionDecision for the CLI.\n *\n * Only newline-delimited JSON envelopes are parsed, and malformed lines are\n * dropped — raw PTY stdout is never parsed here.\n */\n\nimport { createServer, type Server, type Socket } from \"node:net\";\nimport { unlink } from \"node:fs/promises\";\n\nexport interface ToolProgress {\n tool_name?: string;\n elapsed_time_seconds?: number;\n}\n\nexport interface PreToolUseRequest {\n id: string;\n tool_name: string;\n tool_input: Record<string, unknown>;\n}\n\nexport interface PreToolUseVerdict {\n decision: \"allow\" | \"deny\";\n reason?: string;\n}\n\nexport type HookEnvelope =\n | { kind: \"progress\"; progress: ToolProgress }\n | { kind: \"pre_tool_use\"; request: PreToolUseRequest };\n\nexport function parseEnvelope(line: string): HookEnvelope | null {\n let parsed: unknown;\n try {\n parsed = JSON.parse(line);\n } catch {\n return null;\n }\n if (typeof parsed !== \"object\" || parsed === null) return null;\n const record = parsed as Record<string, unknown>;\n\n if (record.kind === \"pre_tool_use\") {\n if (typeof record.id !== \"string\" || typeof record.tool_name !== \"string\") return null;\n const toolInput =\n typeof record.tool_input === \"object\" && record.tool_input !== null\n ? (record.tool_input as Record<string, unknown>)\n : {};\n return {\n kind: \"pre_tool_use\",\n request: { id: record.id, tool_name: record.tool_name, tool_input: toolInput },\n };\n }\n\n // Legacy progress envelope: any line without a `kind` field.\n const result: ToolProgress = {};\n if (typeof record.tool_name === \"string\") result.tool_name = record.tool_name;\n if (typeof record.elapsed_time_seconds === \"number\") {\n result.elapsed_time_seconds = record.elapsed_time_seconds;\n }\n return { kind: \"progress\", progress: result };\n}\n\nexport class HookSocketServer {\n private server: Server | null = null;\n private _closed = false;\n\n constructor(\n public readonly socketPath: string,\n private readonly onProgress: (progress: ToolProgress) => void,\n private readonly onPreToolUse?: (request: PreToolUseRequest) => Promise<PreToolUseVerdict>,\n ) {}\n\n async listen(): Promise<void> {\n await unlink(this.socketPath).catch(() => undefined);\n await new Promise<void>((resolve, reject) => {\n const server = createServer((socket) => this.handleConnection(socket));\n server.on(\"error\", reject);\n server.listen(this.socketPath, () => {\n resolve();\n });\n this.server = server;\n });\n }\n\n get isClosed(): boolean {\n return this._closed;\n }\n\n async close(): Promise<void> {\n if (this._closed) return;\n this._closed = true;\n const server = this.server;\n this.server = null;\n if (server) {\n await new Promise<void>((resolve) => {\n server.close(() => {\n resolve();\n });\n });\n }\n await unlink(this.socketPath).catch(() => undefined);\n }\n\n private handleConnection(socket: Socket): void {\n // Swallow connection-level errors (e.g. ECONNRESET when the hook helper is\n // killed mid-write during teardown). Without an \"error\" listener Node\n // treats it as unhandled and crashes the process.\n socket.on(\"error\", () => undefined);\n // Per-connection buffer: concurrent hook helpers each get their own\n // accumulation so interleaved chunks from separate connections can't\n // corrupt one another's lines.\n let buffer = \"\";\n socket.on(\"data\", (chunk: Buffer) => {\n buffer += chunk.toString(\"utf8\");\n let index = buffer.indexOf(\"\\n\");\n while (index >= 0) {\n const line = buffer.slice(0, index);\n buffer = buffer.slice(index + 1);\n this.dispatch(line, socket);\n index = buffer.indexOf(\"\\n\");\n }\n });\n }\n\n private dispatch(line: string, socket: Socket): void {\n const envelope = parseEnvelope(line);\n if (!envelope) return;\n if (envelope.kind === \"progress\") {\n this.onProgress(envelope.progress);\n return;\n }\n void this.respondToPreToolUse(envelope.request, socket);\n }\n\n private async respondToPreToolUse(request: PreToolUseRequest, socket: Socket): Promise<void> {\n let verdict: PreToolUseVerdict;\n try {\n verdict = this.onPreToolUse\n ? await this.onPreToolUse(request)\n : { decision: \"allow\" as const };\n } catch (err) {\n verdict = {\n decision: \"deny\",\n reason: `Conveyor validation failed: ${err instanceof Error ? err.message : String(err)}. Fix the issue and try again.`,\n };\n }\n try {\n socket.write(`${JSON.stringify({ id: request.id, ...verdict })}\\n`);\n } catch {\n /* helper hung up — its own timeout fallback covers this */\n }\n }\n}\n","/**\n * Tails a Claude Code transcript JSONL file, emitting a `HarnessEvent` for\n * each newly-appended record. Polls on a short interval because the file is\n * written by a separate process (the `claude` CLI under the PTY).\n *\n * All reads are serialized through a promise chain so the polling interval\n * and the final `flush()` on exit can never read overlapping byte ranges.\n */\n\nimport { open } from \"node:fs/promises\";\nimport type { HarnessEvent } from \"../types.js\";\nimport { mapTranscriptRecord } from \"./record-mapper.js\";\n\nconst POLL_INTERVAL_MS = 25;\n\nexport class JsonlTailer {\n private offset = 0;\n private buffer = \"\";\n private timer: ReturnType<typeof setInterval> | null = null;\n private chain: Promise<void> = Promise.resolve();\n private _closed = false;\n\n constructor(\n private readonly path: string,\n private readonly onEvent: (event: HarnessEvent) => void,\n ) {}\n\n /**\n * Begin tailing. Pass `fromOffset` to skip bytes already present when the\n * tail starts (used on resume so the prior session's records aren't replayed).\n */\n start(fromOffset = 0): void {\n if (this.timer) return;\n this.offset = fromOffset;\n this.timer = setInterval(() => {\n if (this._closed) return;\n void this.enqueueRead();\n }, POLL_INTERVAL_MS);\n }\n\n close(): void {\n this._closed = true;\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n }\n\n /** Read any remaining bytes and flush a trailing line without a newline. */\n async flush(): Promise<void> {\n await this.enqueueRead();\n if (this.buffer.length > 0) {\n this.emitLine(this.buffer);\n this.buffer = \"\";\n }\n }\n\n private enqueueRead(): Promise<void> {\n this.chain = this.chain.then(() => this.readOnce());\n return this.chain;\n }\n\n private async readOnce(): Promise<void> {\n let handle: Awaited<ReturnType<typeof open>> | null = null;\n try {\n handle = await open(this.path, \"r\");\n const stats = await handle.stat();\n if (stats.size <= this.offset) return;\n const length = stats.size - this.offset;\n const buf = Buffer.alloc(length);\n await handle.read(buf, 0, length, this.offset);\n this.offset = stats.size;\n this.consume(buf.toString(\"utf8\"));\n } catch {\n /* transient read error (e.g. file not yet created); retry on next poll */\n } finally {\n if (handle) await handle.close();\n }\n }\n\n private consume(chunk: string): void {\n this.buffer += chunk;\n let index = this.buffer.indexOf(\"\\n\");\n while (index >= 0) {\n const line = this.buffer.slice(0, index);\n this.buffer = this.buffer.slice(index + 1);\n this.emitLine(line);\n index = this.buffer.indexOf(\"\\n\");\n }\n }\n\n private emitLine(line: string): void {\n const trimmed = line.trim();\n if (trimmed.length === 0) return;\n let parsed: unknown;\n try {\n parsed = JSON.parse(trimmed);\n } catch {\n return;\n }\n const event = mapTranscriptRecord(parsed);\n if (event) this.onEvent(event);\n }\n}\n","/**\n * Pure transforms from Claude Code transcript JSONL records into\n * harness-neutral `HarnessEvent`s. This is the parity core: the events it\n * produces must match what `ClaudeCodeHarness` yields for the same logical\n * messages (see `helpers/mock-sdk.ts`).\n *\n * Transcript files are a trusted on-disk artifact written by the `claude`\n * CLI, so parsing their lines is allowed — unlike raw PTY stdout, which is\n * never parsed.\n */\n\nimport type {\n HarnessEvent,\n HarnessAssistantEvent,\n HarnessContentBlock,\n HarnessResultEvent,\n HarnessSystemInitEvent,\n} from \"../types.js\";\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null;\n}\n\n/** Custom predicate so narrowing yields `unknown[]`, not `any[]`. */\nfunction isUnknownArray(value: unknown): value is unknown[] {\n return Array.isArray(value);\n}\n\nfunction stringField(record: Record<string, unknown>, ...keys: string[]): string | undefined {\n for (const key of keys) {\n const value = record[key];\n if (typeof value === \"string\") return value;\n }\n return undefined;\n}\n\nfunction numberField(record: Record<string, unknown>, ...keys: string[]): number | undefined {\n for (const key of keys) {\n const value = record[key];\n if (typeof value === \"number\") return value;\n }\n return undefined;\n}\n\nfunction mapSystem(record: Record<string, unknown>): HarnessSystemInitEvent | null {\n if (record.subtype !== \"init\") return null;\n const event: HarnessSystemInitEvent = {\n type: \"system\",\n subtype: \"init\",\n model: stringField(record, \"model\") ?? \"\",\n };\n const sessionId = stringField(record, \"session_id\", \"sessionId\");\n if (sessionId !== undefined) event.session_id = sessionId;\n return event;\n}\n\ntype AssistantUsage = NonNullable<HarnessAssistantEvent[\"message\"][\"usage\"]>;\n\nfunction mapUsage(message: Record<string, unknown>): AssistantUsage | undefined {\n const usage = message.usage;\n if (!isRecord(usage)) return undefined;\n const result: AssistantUsage = {};\n const input = numberField(usage, \"input_tokens\");\n const cacheRead = numberField(usage, \"cache_read_input_tokens\");\n const cacheCreation = numberField(usage, \"cache_creation_input_tokens\");\n if (input !== undefined) result.input_tokens = input;\n if (cacheRead !== undefined) result.cache_read_input_tokens = cacheRead;\n if (cacheCreation !== undefined) result.cache_creation_input_tokens = cacheCreation;\n return result;\n}\n\nfunction mapContentBlock(raw: unknown): HarnessContentBlock | null {\n if (!isRecord(raw)) return null;\n const type = stringField(raw, \"type\");\n if (type === undefined) return null;\n const block: HarnessContentBlock = { type };\n const text = stringField(raw, \"text\");\n if (text !== undefined) block.text = text;\n const name = stringField(raw, \"name\");\n if (name !== undefined) block.name = name;\n const id = stringField(raw, \"id\");\n if (id !== undefined) block.id = id;\n if (\"input\" in raw) block.input = raw.input;\n return block;\n}\n\nfunction mapAssistant(record: Record<string, unknown>): HarnessAssistantEvent | null {\n const message = record.message;\n if (!isRecord(message)) return null;\n const rawContent: unknown[] = isUnknownArray(message.content) ? message.content : [];\n const content: HarnessContentBlock[] = [];\n for (const item of rawContent) {\n const block = mapContentBlock(item);\n if (block) content.push(block);\n }\n const result: HarnessAssistantEvent = {\n type: \"assistant\",\n message: { role: \"assistant\", content },\n };\n const usage = mapUsage(message);\n if (usage !== undefined) result.message.usage = usage;\n return result;\n}\n\nfunction mapResultSuccess(record: Record<string, unknown>): HarnessResultEvent {\n const event: HarnessResultEvent = {\n type: \"result\",\n subtype: \"success\",\n result: stringField(record, \"result\") ?? \"\",\n total_cost_usd: numberField(record, \"total_cost_usd\", \"totalCostUsd\") ?? 0,\n };\n const modelUsage = record.modelUsage;\n if (isRecord(modelUsage)) event.modelUsage = modelUsage;\n const sessionId = stringField(record, \"session_id\", \"sessionId\");\n if (sessionId !== undefined) event.sessionId = sessionId;\n return event;\n}\n\nfunction mapResultError(record: Record<string, unknown>): HarnessResultEvent {\n const rawErrors = isUnknownArray(record.errors) ? record.errors : [];\n const errors = rawErrors.filter((e): e is string => typeof e === \"string\");\n const event: HarnessResultEvent = { type: \"result\", subtype: \"error\", errors };\n const sessionId = stringField(record, \"session_id\", \"sessionId\");\n if (sessionId !== undefined) event.sessionId = sessionId;\n return event;\n}\n\nfunction mapResult(record: Record<string, unknown>): HarnessResultEvent | null {\n if (record.subtype === \"success\") return mapResultSuccess(record);\n if (record.subtype === \"error\") return mapResultError(record);\n return null;\n}\n\nexport function mapTranscriptRecord(raw: unknown): HarnessEvent | null {\n if (!isRecord(raw)) return null;\n switch (raw.type) {\n case \"system\":\n return mapSystem(raw);\n case \"assistant\":\n return mapAssistant(raw);\n case \"result\":\n return mapResult(raw);\n default:\n return null;\n }\n}\n","/**\n * The `claude` CLI process boundary: resolve the binary, build its argv, and\n * interpret its exit when it dies before producing a result. Kept pure so it\n * can be unit-tested without a real spawn.\n */\n\nexport interface SpawnArgsInput {\n resume?: string;\n sessionId?: string;\n model: string;\n permissionMode: \"plan\" | \"bypassPermissions\";\n settingsPath: string;\n /** Extra system-prompt text appended via `--append-system-prompt`. */\n appendSystemPrompt?: string;\n mcpConfigPath?: string;\n /** When set with mcpConfigPath, the CLI uses ONLY that config and ignores the\n * user's `~/.claude.json` / project `.mcp.json` servers. */\n strictMcpConfig?: boolean;\n}\n\nexport function resolveClaudeBinary(): string {\n return process.env.CONVEYOR_CLAUDE_BIN ?? \"claude\";\n}\n\nexport function buildSpawnArgs(input: SpawnArgsInput): string[] {\n const args: string[] = [];\n if (input.resume) {\n args.push(\"--resume\", input.resume);\n } else if (input.sessionId) {\n args.push(\"--session-id\", input.sessionId);\n }\n args.push(\"--model\", input.model);\n if (input.permissionMode === \"bypassPermissions\") {\n args.push(\"--dangerously-skip-permissions\");\n } else {\n args.push(\"--permission-mode\", \"plan\");\n }\n args.push(\"--settings\", input.settingsPath);\n if (input.appendSystemPrompt) {\n args.push(\"--append-system-prompt\", input.appendSystemPrompt);\n }\n if (input.mcpConfigPath) {\n args.push(\"--mcp-config\", input.mcpConfigPath);\n if (input.strictMcpConfig) {\n args.push(\"--strict-mcp-config\");\n }\n }\n return args;\n}\n\n// ─── Exit diagnostics ──────────────────────────────────────────────────────\n// The PTY harness never turns raw `claude` stdout/stderr into HarnessEvents —\n// it relays them to the S5 terminal instead. So when `claude` dies before\n// emitting a transcript result, the captured agent logs show only the generic\n// \"claude exited (code N) without a result\"; the real reason (a missing binary,\n// an auth/onboarding stop, an unknown CLI flag) scrolled past in the live\n// terminal only. These helpers fold a bounded, ANSI-stripped tail of that\n// scrollback back into the error so the failure is self-describing in the logs.\n\n// ESC (0x1B) built via fromCharCode so no control char appears as a source\n// literal (keeps the no-control-regex lint rule happy). Matches CSI sequences\n// (ESC [ ... final-byte) — the bulk of TUI escape noise; any stray ESC bytes\n// from other sequences are removed by the control-char pass below.\nconst ANSI_CSI = new RegExp(`${String.fromCharCode(27)}\\\\[[0-9;?]*[ -/]*[@-~]`, \"g\");\n\n/**\n * Strip ANSI escapes + terminal control noise and collapse to the last few\n * readable lines, capped at `maxChars`. Returns \"\" when nothing printable\n * remains (e.g. the process produced no output at all).\n */\nexport function cleanTerminalOutput(raw: string, maxChars = 1200): string {\n const noAnsi = raw.replace(ANSI_CSI, \"\");\n // Drop C0 control chars (and DEL) except tab; fold CR into newline.\n let out = \"\";\n for (const ch of noAnsi) {\n const code = ch.charCodeAt(0);\n if (ch === \"\\r\" || ch === \"\\n\") out += \"\\n\";\n else if (ch === \"\\t\") out += ch;\n else if (code < 0x20 || code === 0x7f) continue;\n else out += ch;\n }\n const lines = out\n .split(\"\\n\")\n .map((line) => line.trimEnd())\n .filter((line) => line.trim().length > 0);\n const text = lines.join(\"\\n\").trim();\n return text.length > maxChars ? `…${text.slice(-maxChars)}` : text;\n}\n\n/**\n * True when the terminal tail shows node-pty failed to exec the target binary\n * (missing `claude` CLI on PATH). node-pty prints `execvp(3) failed.: No such\n * file or directory` to the pty and the child exits with code 1.\n */\nexport function isMissingBinaryFailure(tail: string): boolean {\n return /execvp\\(\\d+\\) failed|no such file or directory|command not found/i.test(tail);\n}\n\n/**\n * Build the `errors[]` for a `claude` process that exited before emitting a\n * transcript result. The first entry is kept byte-for-byte stable so existing\n * consumers/log scrapers that key off it keep working; richer context is\n * appended after it.\n */\nexport function buildExitErrors(exitCode: number, rawOutput: string, binary: string): string[] {\n const errors = [`claude exited (code ${exitCode}) without a result`];\n const tail = cleanTerminalOutput(rawOutput);\n if (isMissingBinaryFailure(tail)) {\n errors.push(\n `The \\`${binary}\\` CLI could not be started — it is not installed or not on PATH. ` +\n `Install the Claude Code CLI in this environment (npm i -g @anthropic-ai/claude-code) ` +\n `or set CONVEYOR_CLAUDE_BIN to its absolute path.`,\n );\n }\n if (tail) {\n errors.push(`Last terminal output before exit:\\n${tail}`);\n }\n return errors;\n}\n","/**\n * PtyOutputCoalescer — batches raw PTY stdout before it is relayed to the S2\n * server.\n *\n * node-pty surfaces a busy TUI redraw as tens of small data events per second;\n * relaying each one as its own socket.io call made the server-side relay cost\n * (auth + ring append + room fan-out per frame) the bottleneck of the\n * Connected-TUI stream. Buffering for a short window and shipping one\n * concatenated frame preserves byte order and ANSI integrity (the relay treats\n * frames as an opaque byte stream — chunk boundaries carry no meaning) while\n * cutting the call rate by an order of magnitude.\n *\n * Flush triggers:\n * - trailing timer (`flushMs`) after the first unflushed write,\n * - synchronous size flush when the buffer reaches `maxBufferChars`\n * (kept far below the 256KB PTY_FRAME_MAX_CHARS schema cap),\n * - explicit `flush()` from the session on pty exit / teardown so the tail\n * of output (exit messages, final repaint) is never lost.\n */\n\nconst DEFAULT_FLUSH_MS = 40;\nconst DEFAULT_MAX_BUFFER_CHARS = 48 * 1024;\n\nexport class PtyOutputCoalescer {\n private buffer = \"\";\n private timer: ReturnType<typeof setTimeout> | null = null;\n private disposed = false;\n\n constructor(\n private readonly sink: (data: string, dims: { cols: number; rows: number }) => void,\n private readonly getDims: () => { cols: number; rows: number },\n private readonly flushMs: number = DEFAULT_FLUSH_MS,\n private readonly maxBufferChars: number = DEFAULT_MAX_BUFFER_CHARS,\n ) {}\n\n /** Buffer a chunk; flushes synchronously when the size threshold is hit. */\n write(data: string): void {\n if (this.disposed || data === \"\") return;\n this.buffer += data;\n if (this.buffer.length >= this.maxBufferChars) {\n this.flush();\n return;\n }\n if (!this.timer) {\n this.timer = setTimeout(() => {\n this.flush();\n }, this.flushMs);\n }\n }\n\n /** Ship the buffered bytes now (no-op when empty). Dims are read at flush\n * time so a mid-buffer resize stamps the frame with the dims it will render\n * under. */\n flush(): void {\n if (this.timer) {\n clearTimeout(this.timer);\n this.timer = null;\n }\n if (this.buffer === \"\") return;\n const data = this.buffer;\n this.buffer = \"\";\n this.sink(data, this.getDims());\n }\n\n /** Final flush, then drop any future writes (session torn down). Idempotent. */\n dispose(): void {\n if (this.disposed) return;\n this.flush();\n this.disposed = true;\n }\n}\n","/**\n * In-process MCP server that exposes the agent's Conveyor tools to the spawned\n * `claude` CLI over Streamable HTTP on loopback.\n *\n * The tool handlers must run IN the agent process — they call\n * `connection.call(...)` on the live task-token `AgentConnection`. So instead of\n * spawning a separate stdio MCP child and bridging calls back over a socket, we\n * serve the same in-process handlers over an HTTP MCP transport bound to\n * `127.0.0.1`, and point `claude` at it via `--mcp-config` (type: \"http\"). This\n * is the wiring the PTY harness deferred (\"S4\"); the SDK harness already gets\n * these tools in-process.\n *\n * Security: bound to loopback only (never 0.0.0.0) and gated by a random\n * per-run bearer token that `claude` echoes from the generated mcp-config.\n */\n\nimport { createServer, type Server as HttpServer } from \"node:http\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\nimport { writeFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport { randomBytes } from \"node:crypto\";\nimport { McpServer } from \"@modelcontextprotocol/sdk/server/mcp.js\";\nimport { StreamableHTTPServerTransport } from \"@modelcontextprotocol/sdk/server/streamableHttp.js\";\nimport type { HarnessMcpServer, HarnessToolDefinition } from \"../types.js\";\nimport { PtyMcpServer } from \"./mcp-server.js\";\n\nconst LOOPBACK = \"127.0.0.1\";\n\nexport interface PtyToolServerHandle {\n /** `http://127.0.0.1:<port>/mcp` — the URL written into the mcp-config. */\n url: string;\n /** Bearer token required on every request (defense-in-depth over loopback). */\n token: string;\n}\n\nexport class PtyToolServer {\n private http: HttpServer | null = null;\n private transport: StreamableHTTPServerTransport | null = null;\n private mcp: McpServer | null = null;\n private readonly token = randomBytes(24).toString(\"base64url\");\n\n constructor(\n private readonly name: string,\n private readonly tools: HarnessToolDefinition[],\n ) {}\n\n async start(): Promise<PtyToolServerHandle> {\n const mcp = new McpServer({ name: this.name, version: \"1.0.0\" });\n // The SDK's `tool()` is heavily generic over the zod shape; our tool defs are\n // intentionally loose-typed (`schema: z.ZodRawShape`, handler returns MCP\n // content). Cast the registrar to a simpler shape to bridge the boundary\n // without widening to `any` — the SDK still validates input against `schema`.\n const register = mcp.tool.bind(mcp) as unknown as (\n name: string,\n description: string,\n schema: unknown,\n cb: (args: unknown) => unknown,\n ) => void;\n for (const tool of this.tools) {\n register(tool.name, tool.description, tool.schema, (args) => tool.handler(args));\n }\n\n const transport = new StreamableHTTPServerTransport({\n sessionIdGenerator: () => randomBytes(16).toString(\"hex\"),\n enableJsonResponse: true,\n });\n await mcp.connect(transport);\n\n const server = createServer((req, res) => {\n void this.handle(req, res, transport);\n });\n await new Promise<void>((resolve, reject) => {\n server.once(\"error\", reject);\n server.listen(0, LOOPBACK, () => resolve());\n });\n\n const address = server.address();\n const port = address && typeof address === \"object\" ? address.port : 0;\n\n this.http = server;\n this.transport = transport;\n this.mcp = mcp;\n return { url: `http://${LOOPBACK}:${port}/mcp`, token: this.token };\n }\n\n private async handle(\n req: IncomingMessage,\n res: ServerResponse,\n transport: StreamableHTTPServerTransport,\n ): Promise<void> {\n if (req.headers.authorization !== `Bearer ${this.token}`) {\n res.writeHead(401).end();\n return;\n }\n try {\n await transport.handleRequest(req, res);\n } catch {\n if (res.headersSent) res.end();\n else res.writeHead(500).end();\n }\n }\n\n async close(): Promise<void> {\n try {\n await this.transport?.close();\n } catch {\n /* already closed */\n }\n this.transport = null;\n try {\n await this.mcp?.close();\n } catch {\n /* already closed */\n }\n this.mcp = null;\n const http = this.http;\n this.http = null;\n if (http) {\n await new Promise<void>((resolve) => {\n http.close(() => resolve());\n });\n }\n }\n}\n\nexport interface ToolServersResult {\n servers: PtyToolServer[];\n /** Path to the written `--mcp-config`, or null when there were no tools. */\n mcpConfigPath: string | null;\n}\n\n/**\n * Start one loopback HTTP MCP server per harness tool group (in practice just\n * \"conveyor\") and write the `--mcp-config` the spawned `claude` consumes. No-op\n * (null config) when the harness was constructed without tools.\n */\nexport async function startToolServers(\n mcpServers: Record<string, HarnessMcpServer>,\n tempDir: string,\n): Promise<ToolServersResult> {\n const servers: PtyToolServer[] = [];\n const config: Record<string, { type: \"http\"; url: string; headers: Record<string, string> }> = {};\n for (const [name, handle] of Object.entries(mcpServers)) {\n const tools = handle instanceof PtyMcpServer ? handle.tools : [];\n if (tools.length === 0) continue;\n const server = new PtyToolServer(name, tools);\n const { url, token } = await server.start();\n servers.push(server);\n config[name] = { type: \"http\", url, headers: { Authorization: `Bearer ${token}` } };\n }\n if (Object.keys(config).length === 0) return { servers, mcpConfigPath: null };\n const mcpConfigPath = join(tempDir, \"mcp-config.json\");\n await writeFile(mcpConfigPath, JSON.stringify({ mcpServers: config }, null, 2), \"utf8\");\n return { servers, mcpConfigPath };\n}\n","import type { HarnessToolDefinition } from \"../types.js\";\n\ntype ToolResult = Awaited<ReturnType<HarnessToolDefinition[\"handler\"]>>;\n\n/**\n * In-process MCP server handle for the PTY harness.\n *\n * S1 materializes tools as a directly-invokable in-process handle: callers\n * resolve a tool by name and invoke its handler. Wiring these tools to the\n * `claude` CLI over a live stdio MCP transport (via `--mcp-config`) is\n * deferred to S4 — the spawn layer already threads `mcpConfigPath` through\n * for that purpose.\n */\nexport class PtyMcpServer {\n constructor(\n public readonly name: string,\n public readonly tools: HarnessToolDefinition[],\n ) {}\n\n getTool(name: string): HarnessToolDefinition | undefined {\n return this.tools.find((tool) => tool.name === name);\n }\n\n invokeTool(name: string, input: unknown): Promise<ToolResult> {\n const tool = this.getTool(name);\n if (!tool) return Promise.reject(new Error(`Unknown tool: ${name}`));\n return tool.handler(input);\n }\n}\n","/**\n * Synthesizes `<configHome>/.credentials.json` from CLAUDE_CODE_OAUTH_TOKEN so\n * the interactive `claude` TUI starts authenticated in Conveyor-managed cloud\n * environments. The interactive TUI does NOT read CLAUDE_CODE_OAUTH_TOKEN —\n * that env var is honored only in headless/CI runs — so without a credentials\n * file a fresh pod's Connected TUI lands on the login-method picker.\n *\n * Safety policy: a credentials file whose `claudeAiOauth` carries a\n * refreshToken was written by a real interactive `/login` (the OAuth code flow\n * always issues one) and is never touched. Our synthesized file never has one —\n * that absence IS the \"written by Conveyor\" marker. If live verification ever\n * disproves that assumption, the fallback hardening is a sidecar marker file\n * (e.g. `<configHome>/.conveyor-credentials.json` holding a hash of the token\n * we wrote) — noted here so the next person doesn't reinvent the policy.\n *\n * Decision core is pure (planCredentialsWrite) so the overwrite policy can be\n * unit-tested without fs; the effectful wrappers never throw — a GCS-FUSE\n * hiccup must not kill PtySession.start().\n */\n\nimport { chmod, mkdir, readFile, rm, writeFile } from \"node:fs/promises\";\nimport { homedir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { claudeConfigHome } from \"./settings.js\";\n\n// `claude setup-token` tokens are valid for ~1 year. The exact expiry is\n// unknowable from the token itself; claim a far-future expiresAt so the CLI\n// never decides the credential is expired and attempts a refresh it cannot\n// perform (no refreshToken). The file is re-synthesized on every spawn, so the\n// window slides.\nconst SYNTH_TOKEN_TTL_MS = 365 * 24 * 60 * 60 * 1000;\n// Rewrite our own file when it has less than this much runway left — a cheap\n// staleness guard for a long-lived file on the persistent user-home mount.\nconst REFRESH_SKEW_MS = 30 * 24 * 60 * 60 * 1000;\n\nexport function claudeCredentialsPath(): string {\n return join(claudeConfigHome(), \".credentials.json\");\n}\n\n/**\n * Only act inside Conveyor-managed cloud environments (GKE claudespace pods\n * export CLAUDESPACE_NAME in entrypoint.sh; GitHub Codespaces set\n * CODESPACE_NAME/CODESPACES) — never touch a developer's real ~/.claude.\n */\nexport function isConveyorCloudEnv(env: NodeJS.ProcessEnv = process.env): boolean {\n return Boolean(env.CLAUDESPACE_NAME || env.CODESPACE_NAME || env.CODESPACES);\n}\n\nexport interface CredentialsWriteInput {\n isCloud: boolean;\n /** CLAUDE_CODE_OAUTH_TOKEN from the environment. */\n token: string | undefined;\n /** Current file contents; null when the file is missing. */\n existingRaw: string | null;\n now: number;\n}\n\nexport type CredentialsPlan =\n | { action: \"skip\"; reason: \"not-cloud\" | \"no-token\" | \"foreign-credentials\" | \"current\" }\n | { action: \"write\"; contents: string };\n\ninterface ParsedOauth {\n accessToken: unknown;\n refreshToken: unknown;\n expiresAt: unknown;\n}\n\nfunction parseClaudeAiOauth(raw: string | null): ParsedOauth | null {\n if (!raw || raw.trim() === \"\") return null;\n try {\n const parsed: unknown = JSON.parse(raw);\n if (typeof parsed !== \"object\" || parsed === null) return null;\n const oauth = (parsed as Record<string, unknown>).claudeAiOauth;\n if (typeof oauth !== \"object\" || oauth === null) return null;\n const record = oauth as Record<string, unknown>;\n return {\n accessToken: record.accessToken,\n refreshToken: record.refreshToken,\n expiresAt: record.expiresAt,\n };\n } catch {\n return null;\n }\n}\n\n/**\n * The synthesized shape is the empirical-iteration point: if a live pod's TUI\n * still shows the login picker, adjust scopes/subscriptionType HERE and\n * re-verify on a Claudespace diagnostic card.\n */\nfunction buildSynthesizedCredentials(token: string, now: number): string {\n return JSON.stringify({\n claudeAiOauth: {\n accessToken: token,\n expiresAt: now + SYNTH_TOKEN_TTL_MS,\n scopes: [\"user:inference\", \"user:profile\"],\n subscriptionType: \"max\",\n },\n });\n}\n\n/** Pure overwrite-policy core — see the decision table in the tests. */\nexport function planCredentialsWrite(input: CredentialsWriteInput): CredentialsPlan {\n if (!input.isCloud) return { action: \"skip\", reason: \"not-cloud\" };\n if (!input.token) return { action: \"skip\", reason: \"no-token\" };\n\n const contents = buildSynthesizedCredentials(input.token, input.now);\n const existing = parseClaudeAiOauth(input.existingRaw);\n // Missing, empty, unparseable, or shapeless file — ours to (re)write.\n if (!existing) return { action: \"write\", contents };\n // A refreshToken means a genuine interactive /login — never clobber.\n if (typeof existing.refreshToken === \"string\" && existing.refreshToken.length > 0) {\n return { action: \"skip\", reason: \"foreign-credentials\" };\n }\n const fresh =\n existing.accessToken === input.token &&\n typeof existing.expiresAt === \"number\" &&\n existing.expiresAt > input.now + REFRESH_SKEW_MS;\n // Skip when current to avoid write churn on the GCS-FUSE mount.\n if (fresh) return { action: \"skip\", reason: \"current\" };\n return { action: \"write\", contents };\n}\n\nasync function readRaw(path: string): Promise<string | null> {\n try {\n return await readFile(path, \"utf8\");\n } catch {\n return null;\n }\n}\n\n/**\n * Materialize CLAUDE_CODE_OAUTH_TOKEN as a credentials file for the\n * interactive TUI. Best-effort: logs and returns on any failure.\n */\nexport async function ensureClaudeCredentials(env: NodeJS.ProcessEnv = process.env): Promise<void> {\n try {\n const path = claudeCredentialsPath();\n const plan = planCredentialsWrite({\n isCloud: isConveyorCloudEnv(env),\n token: env.CLAUDE_CODE_OAUTH_TOKEN,\n existingRaw: await readRaw(path),\n now: Date.now(),\n });\n if (plan.action === \"skip\") return;\n await mkdir(claudeConfigHome(), { recursive: true });\n await writeFile(path, plan.contents, { encoding: \"utf8\", mode: 0o600 });\n // The GCS-FUSE CSI mount (file-mode=700) may reject chmod; it already\n // enforces owner-only access, so this is belt-and-braces for local disks.\n await chmod(path, 0o600).catch(() => {});\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[conveyor-agent] claude credentials sync failed: ${message}\\n`);\n }\n}\n\n/**\n * Path of the CLI's main config. Lives at $HOME/.claude.json normally; when\n * CLAUDE_CONFIG_DIR is set the CLI relocates it under that directory.\n */\nexport function claudeJsonPath(): string {\n const configDir = process.env.CLAUDE_CONFIG_DIR;\n return configDir ? join(configDir, \".claude.json\") : join(homedir(), \".claude.json\");\n}\n\n/**\n * Pure decision core for the onboarding + trust seed. Returns the contents to\n * write, or null when no write is needed.\n *\n * Unlike the entrypoint's only-if-empty seeding, this MERGES into an existing\n * config: the CLI rewrites .claude.json during a first-run wizard (cache keys,\n * firstStartTime, …) WITHOUT setting hasCompletedOnboarding until the wizard\n * finishes. On a persistent user-home (GCS-FUSE) an abandoned wizard therefore\n * leaves a config that re-triggers onboarding on every subsequent pod — seen\n * live: credentials valid (`claude auth status` → loggedIn:true) yet the TUI\n * parked at the theme picker. All CLI-owned keys are preserved.\n *\n * `trustCwd` pre-accepts the folder-trust dialog for the workspace the TUI is\n * about to run in (`projects[\"<cwd>\"].hasTrustDialogAccepted`) — the dialog is\n * the third first-run gate after theme and login, also seen parking a live\n * pod. Trusting the Conveyor-managed repo clone is definitionally correct in\n * this environment. The theme default is only applied when creating a fresh\n * config: the CLI drops unused keys on rewrite, and re-adding theme on every\n * spawn would cause a guaranteed write per spawn for zero behavior change\n * (the theme picker is gated on hasCompletedOnboarding, not theme).\n */\nfunction asRecord(value: unknown): Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : {};\n}\n\n/** Parse the existing .claude.json; corrupt/non-object input becomes a fresh\n * config (the CLI treats unparseable files as fatal, so replacing is a repair). */\nfunction parseClaudeJson(existingRaw: string | null): Record<string, unknown> {\n if (!existingRaw || existingRaw.trim() === \"\") return {};\n try {\n return asRecord(JSON.parse(existingRaw));\n } catch {\n return {};\n }\n}\n\n/** Pre-accept the folder-trust dialog for `trustCwd`. Returns true if changed. */\nfunction seedWorkspaceTrust(config: Record<string, unknown>, trustCwd: string): boolean {\n const projects = asRecord(config.projects);\n const entry = asRecord(projects[trustCwd]);\n if (entry.hasTrustDialogAccepted === true) return false;\n entry.hasTrustDialogAccepted = true;\n projects[trustCwd] = entry;\n config.projects = projects;\n return true;\n}\n\nexport function planClaudeJsonSeed(existingRaw: string | null, trustCwd?: string): string | null {\n const config = parseClaudeJson(existingRaw);\n const isFresh = Object.keys(config).length === 0;\n let changed = false;\n if (config.hasCompletedOnboarding !== true) {\n config.hasCompletedOnboarding = true;\n changed = true;\n }\n // Pre-answer the \"Bypass Permissions mode\" warning dialog the CLI shows on\n // the first `--dangerously-skip-permissions` launch. Seeded unconditionally:\n // the flag is inert for plan-mode spawns, no human is at the keyboard in\n // cloud envs to press \"Yes, I accept\", and the permission mode can flip\n // between spawns sharing one persistent user-home.\n if (config.bypassPermissionsModeAccepted !== true) {\n config.bypassPermissionsModeAccepted = true;\n changed = true;\n }\n if (isFresh && typeof config.theme !== \"string\") {\n config.theme = \"dark\";\n changed = true;\n }\n if (trustCwd && seedWorkspaceTrust(config, trustCwd)) {\n changed = true;\n }\n return changed ? JSON.stringify(config) : null;\n}\n\n/**\n * Suppress the CLI's first-run wizard, the bypass-permissions warning dialog,\n * and (when `trustCwd` is given) the folder-trust dialog for that workspace\n * in Conveyor cloud envs so the spawned TUI boots straight into the REPL. Runs regardless of token presence\n * — with credentials the gates are pure friction; without them the\n * post-onboarding login screen is strictly better than the full wizard.\n * Best-effort, never throws.\n */\nexport async function ensureClaudeOnboarding(\n env: NodeJS.ProcessEnv = process.env,\n trustCwd?: string,\n): Promise<void> {\n try {\n if (!isConveyorCloudEnv(env)) return;\n const path = claudeJsonPath();\n const contents = planClaudeJsonSeed(await readRaw(path), trustCwd);\n if (contents === null) return;\n await writeFile(path, contents, \"utf8\");\n // Read-back check: on network-backed homes (GCS-FUSE) a write can report\n // success while a subsequent read still serves stale content — which the\n // CLI's startup read would too, re-surfacing the dialogs this seed exists\n // to suppress (seen live 2026-07-02: seed wrote silently, the folder-trust\n // dialog parked a code review anyway). Log both outcomes so pod logs show\n // what the CLI is about to read.\n const verify = await readRaw(path);\n if (verify === contents) {\n process.stderr.write(\n `[conveyor-agent] claude onboarding seeded${trustCwd ? ` (trust: ${trustCwd})` : \"\"}\\n`,\n );\n } else {\n process.stderr.write(\n `[conveyor-agent] claude onboarding seed read-back MISMATCH at ${path}: wrote ${contents.length}B, read ${verify?.length ?? 0}B — CLI may see stale config and park at a startup dialog\\n`,\n );\n }\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[conveyor-agent] claude onboarding seed failed: ${message}\\n`);\n }\n}\n\n/**\n * Delete the credentials file only when it is ours (no refreshToken). Used\n * when a runtime key update switches the agent to ANTHROPIC_API_KEY — stale\n * subscription credentials must not keep authenticating the next TUI spawn.\n */\nexport async function removeConveyorCredentials(\n env: NodeJS.ProcessEnv = process.env,\n): Promise<void> {\n try {\n if (!isConveyorCloudEnv(env)) return;\n const path = claudeCredentialsPath();\n const existing = parseClaudeAiOauth(await readRaw(path));\n if (existing && typeof existing.refreshToken === \"string\" && existing.refreshToken.length > 0) {\n return;\n }\n await rm(path, { force: true });\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[conveyor-agent] claude credentials removal failed: ${message}\\n`);\n }\n}\n","/**\n * PtyHarness — drives the `claude` CLI under a pseudo-terminal behind the\n * generic `AgentHarness` interface. Selected at runtime via\n * `createHarness(\"pty\")`. It is the UNCONDITIONAL harness for the task chat\n * (cards); see `resolveHarnessKind()` in `runner/query-bridge.ts`. The only way\n * to put a card on the SDK harness is the maintainer override\n * `CONVEYOR_FORCE_SDK_CARDS=1`.\n */\n\nimport type {\n AgentHarness,\n HarnessEvent,\n HarnessQueryOptions,\n HarnessToolDefinition,\n HarnessMcpServer,\n HarnessUserMessage,\n PtyBridge,\n} from \"../types.js\";\nimport { PtySession } from \"./session.js\";\nimport { PtyMcpServer } from \"./mcp-server.js\";\nimport { ensureClaudeCredentials, ensureClaudeOnboarding } from \"./credentials.js\";\n\nexport { PtySession, PtyMcpServer };\n\nexport class PtyHarness implements AgentHarness {\n /**\n * `bridge` relays raw terminal I/O to/from the S2 server (and on to the S5\n * terminal). It is undefined for SDK-only callers and PTY runs that never\n * attach a relay; the session simply discards stdout in that case.\n */\n constructor(private readonly bridge?: PtyBridge) {}\n\n /** The session currently streaming events, if any — repaint target. */\n private activeSession: PtySession | null = null;\n\n /**\n * Wiggle the live pty's size so the CLI repaints its whole screen. No-op\n * between queries or on the SDK harness. Called after a socket reconnect so\n * the server's (per-process, possibly brand-new) scrollback ring re-seeds\n * and the Connected-TUI terminal reappears.\n */\n forceRepaint(): void {\n this.activeSession?.forceRepaint();\n }\n\n async *executeQuery(opts: {\n prompt: string | AsyncGenerator<HarnessUserMessage, void, unknown>;\n options: HarnessQueryOptions;\n resume?: string;\n }): AsyncGenerator<HarnessEvent, void> {\n const session = new PtySession(\n opts.prompt,\n opts.options,\n opts.resume ?? opts.options.resume,\n this.bridge,\n );\n // The interactive TUI ignores CLAUDE_CODE_OAUTH_TOKEN (headless-only); in\n // Conveyor cloud envs, materialize it as `<configHome>/.credentials.json`\n // so the CLI starts authenticated instead of at the login-method picker,\n // and complete the onboarding flags + workspace trust in .claude.json so\n // neither an abandoned first-run wizard on the persistent user-home nor\n // the folder-trust dialog can park the TUI.\n // Every PTY spawn (fresh, follow-up, resume, retry, mode restart) flows\n // through here — this is the single PtySession construction site.\n await ensureClaudeCredentials();\n await ensureClaudeOnboarding(process.env, opts.options.cwd);\n await session.start();\n this.activeSession = session;\n try {\n for await (const event of session.events()) {\n yield event;\n }\n } finally {\n if (this.activeSession === session) this.activeSession = null;\n await session.teardown();\n }\n }\n\n createMcpServer(config: { name: string; tools: HarnessToolDefinition[] }): HarnessMcpServer {\n return new PtyMcpServer(config.name, config.tools);\n }\n}\n","export { defineTool } from \"./types.js\";\n\nexport type {\n AgentHarness,\n HarnessEvent,\n HarnessSystemEvent,\n HarnessSystemInitEvent,\n HarnessCompactBoundaryEvent,\n HarnessTaskStartedEvent,\n HarnessTaskProgressEvent,\n HarnessAssistantEvent,\n HarnessContentBlock,\n HarnessResultEvent,\n HarnessResultSuccessEvent,\n HarnessResultErrorEvent,\n HarnessRateLimitEvent,\n HarnessToolProgressEvent,\n HarnessUserQuestion,\n HarnessUserQuestionEvent,\n HarnessUserMessage,\n HarnessToolDefinition,\n HarnessToolAnnotations,\n HarnessMcpServer,\n HarnessQueryOptions,\n HarnessHookInput,\n HarnessHookOutput,\n HarnessPostToolUseHook,\n PtyBridge,\n} from \"./types.js\";\n\nexport { ClaudeCodeHarness } from \"./claude-code/index.js\";\nexport { PtyHarness } from \"./pty/index.js\";\n\nimport { ClaudeCodeHarness } from \"./claude-code/index.js\";\nimport { PtyHarness } from \"./pty/index.js\";\nimport type { AgentHarness, PtyBridge } from \"./types.js\";\n\nexport type HarnessKind = \"sdk\" | \"pty\";\n\n/**\n * Pick the harness implementation. `ptyBridge` is only consumed by the PTY\n * harness (to stream stdout to the S2 relay and receive keystrokes/resize);\n * the SDK harness ignores it.\n */\nexport function createHarness(kind: HarnessKind = \"sdk\", ptyBridge?: PtyBridge): AgentHarness {\n return kind === \"pty\" ? new PtyHarness(ptyBridge) : new ClaudeCodeHarness();\n}\n","/* oxlint-disable max-lines, max-dependencies -- query orchestration + retry logic is cohesive; splitting would scatter tightly-coupled control flow */\nimport { createHash } from \"node:crypto\";\nimport { existsSync, readFileSync, truncateSync } from \"node:fs\";\nimport { sessionTranscriptPath } from \"../harness/pty/settings.js\";\nimport type {\n AgentHarness,\n HarnessEvent,\n HarnessUserMessage,\n HarnessQueryOptions,\n HarnessHookInput,\n HarnessHookOutput,\n HarnessKind,\n} from \"../harness/index.js\";\nimport type { AgentConnection } from \"../connection/agent-connection.js\";\nimport { createServiceLogger } from \"../utils/logger.js\";\nimport type { TaskContext, MultimodalBlock, AgentMode } from \"@project/shared\";\nimport type { AgentRunnerConfig, AgentRunnerCallbacks } from \"../types.js\";\nimport { buildInitialPrompt } from \"./prompt-builder.js\";\nimport { buildSystemPrompt } from \"./system-prompt.js\";\nimport { createConveyorMcpServer } from \"../tools/index.js\";\nimport { processEvents } from \"./event-processor.js\";\nimport { API_ERROR_PATTERN, isAuthError } from \"./event-handlers.js\";\nimport type { ExplorationTracker } from \"./exploration-tracker.js\";\nimport { buildCanUseTool } from \"./tool-access.js\";\nimport { collectMissingProps } from \"./task-property-utils.js\";\nimport { redact } from \"./redactor.js\";\n\nconst logger = createServiceLogger(\"QueryExecutor\");\nconst IMAGE_ERROR_PATTERN = /Could not process image/i;\nconst RETRY_DELAYS_MS = [60_000, 120_000, 180_000, 300_000];\n\nexport interface QueryHost {\n config: AgentRunnerConfig;\n connection: AgentConnection;\n callbacks: AgentRunnerCallbacks;\n harness: AgentHarness;\n harnessKind: HarnessKind;\n setupLog: string[];\n explorationTracker: ExplorationTracker | null;\n agentMode: AgentMode;\n isAuto: boolean;\n isParentTask: boolean;\n hasExitedPlanMode: boolean;\n pendingModeRestart: boolean;\n discoveryCompleted: boolean;\n wasRateLimited: boolean;\n sessionIds: Map<string, string>;\n activeQuery: AsyncGenerator<HarnessEvent, void> | null;\n pendingToolOutputs: { tool: string; output: string }[];\n abortController: AbortController | null;\n isStopped(): boolean;\n requestStop(): void;\n requestSoftStop(): void;\n createInputStream(\n prompt: string | MultimodalBlock[],\n ): AsyncGenerator<HarnessUserMessage, void, unknown>;\n snapshotPlanFiles(): void;\n syncPlanFile(): Promise<void>;\n onModeTransition?: (newMode: AgentMode) => void;\n}\n\n// ── Query options builder ───────────────────────────────────────────────────\n\nfunction buildHooks(host: QueryHost): HarnessQueryOptions[\"hooks\"] {\n return {\n PostToolUse: [\n {\n hooks: [\n async (input: HarnessHookInput): Promise<HarnessHookOutput> => {\n if (host.isStopped()) return await Promise.resolve({ continue: false });\n if (input.hook_event_name === \"PostToolUse\") {\n const raw =\n typeof input.tool_response === \"string\"\n ? input.tool_response\n : JSON.stringify(input.tool_response);\n const { output: redacted, redacted: redactedCount } = redact(raw);\n const output = redacted.slice(0, 500);\n host.connection.sendEvent({\n type: \"tool_result\",\n tool: input.tool_name,\n output,\n isError: false,\n ...(redactedCount > 0 ? { redactedCount } : {}),\n });\n host.pendingToolOutputs.push({ tool: input.tool_name, output });\n\n // After PR creation, nudge agent to backfill missing task properties\n if (input.tool_name === \"mcp__conveyor__create_pull_request\") {\n try {\n const props = await host.connection.getTaskProperties();\n const missing = collectMissingProps(props);\n if (missing.length > 0) {\n host.connection.postChatMessage(\n `PR created! Please backfill missing task properties: ${missing.join(\", \")}`,\n );\n }\n } catch {\n /* best-effort */\n }\n }\n }\n return await Promise.resolve({ continue: true });\n },\n ],\n timeout: 5,\n },\n ],\n };\n}\n\n/**\n * Derive a deterministic UUID v8-style from a session lineage key.\n * The Claude SDK requires UUID format for sessionId; task IDs are cuids.\n * Using sha256(key) ensures the same lineage always maps to the same session.\n */\nfunction taskIdToSessionUuid(lineageKey: string): string {\n const hash = createHash(\"sha256\").update(lineageKey).digest(\"hex\");\n // Format as UUID: xxxxxxxx-xxxx-8xxx-axxx-xxxxxxxxxxxx (v8 + RFC 4122 variant)\n return `${hash.slice(0, 8)}-${hash.slice(8, 12)}-8${hash.slice(13, 16)}-a${hash.slice(17, 20)}-${hash.slice(20, 32)}`;\n}\n\n/**\n * Conversation lineage for a task. Review runs (code review, pack-runner\n * orchestration) get their OWN session lineage so:\n * - a review never resumes the building conversation (it may use a\n * different model — this was previously \"prevented\" by the server\n * clearing `sdkSessionId`, which never actually worked because resume is\n * filesystem-driven), and\n * - flipping back to building resumes the ORIGINAL building conversation\n * untouched.\n */\nexport function sessionLineageKey(\n taskId: string,\n agentMode: AgentMode,\n runnerMode: AgentRunnerConfig[\"mode\"],\n): string {\n return agentMode === \"review\" || runnerMode === \"code-review\" ? `${taskId}:review` : taskId;\n}\n\n/**\n * Check if a Claude session file exists for the given session UUID + cwd.\n * Session files live at <config-home>/projects/<cwd-slug>/<sessionId>.jsonl\n * (the same CLAUDE_CONFIG_DIR-aware path the PTY transcript tailer uses).\n */\nfunction sessionFileExists(sessionUuid: string, cwd: string): boolean {\n try {\n return existsSync(sessionTranscriptPath(cwd, sessionUuid));\n } catch {\n return false;\n }\n}\n\n/** Does a resumable Claude session already exist for this lineage + workspace? */\nexport function hasExistingSessionFile(\n taskId: string,\n cwd: string,\n lineage: { agentMode: AgentMode; runnerMode: AgentRunnerConfig[\"mode\"] },\n): boolean {\n const key = sessionLineageKey(taskId, lineage.agentMode, lineage.runnerMode);\n return sessionFileExists(taskIdToSessionUuid(key), cwd);\n}\n\n/**\n * Repair a transcript whose final record was torn by an ungraceful pod death\n * (SIGKILL mid-append, gcsfuse upload cut short): truncate to the end of the\n * last complete, parseable line so `--resume` gets a well-formed JSONL.\n * Returns true when a truncation was performed.\n */\nexport function repairTornSessionFile(path: string): boolean {\n try {\n if (!existsSync(path)) return false;\n const content = readFileSync(path, \"utf8\");\n if (content.length === 0) return false;\n\n // Phase 1: drop a trailing partial line (no terminating newline).\n let keepEnd = content.length;\n if (!content.endsWith(\"\\n\")) {\n // 0 when no newline exists at all.\n keepEnd = content.lastIndexOf(\"\\n\") + 1;\n }\n // Phase 2: drop trailing terminated lines that don't parse as JSON\n // (a write torn mid-line that still got its newline flushed).\n while (keepEnd > 0) {\n const prevNewline = content.lastIndexOf(\"\\n\", keepEnd - 2);\n const line = content.slice(prevNewline + 1, keepEnd - 1).trim();\n if (line.length > 0) {\n try {\n JSON.parse(line);\n // Trailing line is whole — done.\n break;\n } catch {\n /* unparseable — trim it */\n }\n }\n keepEnd = prevNewline + 1;\n }\n\n if (keepEnd === content.length) return false;\n truncateSync(path, Buffer.byteLength(content.slice(0, keepEnd), \"utf8\"));\n logger.warn(\"Repaired torn transcript before resume\", {\n path,\n trimmedBytes: content.length - keepEnd,\n });\n return true;\n } catch {\n // Best-effort — a failed repair falls through to the CLI.\n return false;\n }\n}\n\nexport interface PromptDeliveryInputs {\n harnessKind: HarnessKind;\n runnerMode: AgentRunnerConfig[\"mode\"];\n isAuto: boolean;\n agentMode: AgentMode;\n isFollowUp: boolean;\n hasExistingSession: boolean;\n}\n\n/**\n * Decide how a query's prompt reaches the agent.\n *\n * \"prefill\" (paste into the TUI input, let the human review/edit/Enter) applies\n * only to the INITIAL instructions of a manual-mode task chat under the PTY\n * harness. Everything else submits immediately:\n * - SDK harness: no interactive input box exists.\n * - code-review runner: autonomous, no human at the TUI.\n * - auto tasks (isAuto or agentMode \"auto\"): full-auto is the whole point.\n * - follow-ups: the human already directed the agent via chat.\n * - resumes: the conversation exists; re-prefilling the initial\n * instructions into it would be confusing.\n *\n * The pm runner mode is NOT excluded: fresh Planning-status cards boot their\n * task pod as a pm runner (computeRunnerMode server-side), so pm + manual\n * agentMode (discovery/help) IS the human-facing discovery card — exactly the\n * flow that should park a prefilled TUI. Autonomous pm flows are already\n * caught by the auto/isAuto check above.\n */\nexport function resolvePromptDelivery(inputs: PromptDeliveryInputs): \"submit\" | \"prefill\" {\n if (inputs.harnessKind !== \"pty\") return \"submit\";\n if (inputs.runnerMode === \"code-review\") return \"submit\";\n if (inputs.isFollowUp || inputs.hasExistingSession) return \"submit\";\n if (inputs.isAuto || inputs.agentMode === \"auto\") return \"submit\";\n // Only the human-facing planning modes park a prefill. building/review\n // initial queries must auto-run — a fresh-disk building boot with nobody at\n // the terminal would otherwise stall the build.\n if (inputs.agentMode !== \"discovery\" && inputs.agentMode !== \"help\") return \"submit\";\n return \"prefill\";\n}\n\nfunction isReadOnlyMode(mode: AgentMode, hasExitedPlanMode: boolean): boolean {\n return mode === \"discovery\" || mode === \"help\" || (mode === \"auto\" && !hasExitedPlanMode);\n}\n\nfunction buildDisallowedTools(\n settings: { disallowedTools?: string[] },\n mode: AgentMode,\n hasExitedPlanMode: boolean,\n): string[] | undefined {\n const modeDisallowed = isReadOnlyMode(mode, hasExitedPlanMode)\n ? [\"TodoWrite\", \"TodoRead\", \"NotebookEdit\"]\n : [];\n const configured = settings.disallowedTools ?? [];\n const combined = [...configured, ...modeDisallowed];\n return combined.length > 0 ? combined : undefined;\n}\n\nfunction buildQueryOptions(host: QueryHost, context: TaskContext): HarnessQueryOptions {\n const settings = context.agentSettings ?? host.config.agentSettings ?? {};\n const mode = host.agentMode;\n\n // Read-only modes (auto pre-exit, discovery, help) use the SDK's native \"plan\"\n // permission mode which enforces no-execution (blocks file edits and destructive commands).\n // canUseTool is still registered to intercept ExitPlanMode for custom validation\n // (plan/SP/title checks, triggerIdentification, mode restart).\n const isReadOnly = isReadOnlyMode(mode, host.hasExitedPlanMode);\n const needsCanUseTool = isReadOnly;\n\n const systemPromptText = buildSystemPrompt(\n host.config.mode,\n context,\n { ...host.config, isAuto: host.isAuto },\n host.setupLog,\n mode,\n );\n const settingSources = (settings.settingSources ?? [\"user\", \"project\"]) as (\n | \"user\"\n | \"project\"\n | \"local\"\n )[];\n\n return {\n model: context.model || host.config.model,\n systemPrompt: {\n type: \"preset\",\n preset: \"claude_code\",\n append: systemPromptText || undefined,\n },\n settingSources,\n cwd: host.config.workspaceDir,\n permissionMode: needsCanUseTool ? \"plan\" : \"bypassPermissions\",\n allowDangerouslySkipPermissions: !needsCanUseTool,\n canUseTool: buildCanUseTool(host),\n // The spawned CLI never sees `systemPrompt` (an SDK-only option) — deliver\n // the same text via `--append-system-prompt`. PTY-only: the SDK harness\n // already receives it through systemPrompt.append.\n ...(host.harnessKind === \"pty\" && systemPromptText\n ? { appendSystemPrompt: systemPromptText }\n : {}),\n // Auto mode pre-exit: after the ExitPlanMode hook allows the call, the\n // CLI's plan dialog still renders — press Enter so the autonomous agent\n // continues building in the same session (Conveyor validated in the hook).\n planDialogAutoAccept: mode === \"auto\" && !host.hasExitedPlanMode,\n tools: { type: \"preset\" as const, preset: \"claude_code\" as const },\n mcpServers: {\n conveyor: createConveyorMcpServer(host.harness, host.connection, host.config, context, mode),\n },\n sandbox: context.useSandbox ? { enabled: true } : { enabled: false },\n hooks: buildHooks(host),\n maxTurns: settings.maxTurns,\n effort: settings.effort,\n thinking: settings.thinking,\n betas: settings.betas,\n abortController: host.abortController ?? undefined,\n disallowedTools: buildDisallowedTools(settings, mode, host.hasExitedPlanMode),\n enableFileCheckpointing: settings.enableFileCheckpointing,\n stderr: (data: string) => {\n logger.warn(\"Claude Code stderr\", { data: data.trimEnd() });\n },\n };\n}\n\n// ── Multimodal prompt builder ────────────────────────────────────────────\n\ntype ImageMediaType = \"image/gif\" | \"image/jpeg\" | \"image/png\" | \"image/webp\";\n\nfunction buildMultimodalPrompt(\n textPrompt: string,\n context: TaskContext,\n skipImages = false,\n): string | MultimodalBlock[] {\n if (skipImages) return textPrompt;\n\n const taskImages = (context.files ?? []).filter(\n (f) => f.content && f.contentEncoding === \"base64\",\n );\n const chatImages: { fileName: string; mimeType: string; content: string }[] = [];\n for (const msg of context.chatHistory) {\n for (const f of msg.files ?? []) {\n if (f.content && f.contentEncoding === \"base64\") {\n chatImages.push({ fileName: f.fileName, mimeType: f.mimeType, content: f.content });\n }\n }\n }\n\n if (taskImages.length === 0 && chatImages.length === 0) return textPrompt;\n\n const blocks: MultimodalBlock[] = [{ type: \"text\", text: textPrompt }];\n for (const file of taskImages) {\n blocks.push({\n type: \"image\",\n source: {\n type: \"base64\",\n media_type: file.mimeType as ImageMediaType,\n data: file.content ?? \"\",\n },\n });\n blocks.push({ type: \"text\", text: `[Attached image: ${file.fileName} (${file.mimeType})]` });\n }\n for (const file of chatImages) {\n blocks.push({\n type: \"image\",\n source: { type: \"base64\", media_type: file.mimeType as ImageMediaType, data: file.content },\n });\n blocks.push({ type: \"text\", text: `[Chat image: ${file.fileName} (${file.mimeType})]` });\n }\n return blocks;\n}\n\n// ── Follow-up prompt builder ─────────────────────────────────────────────\n\nasync function buildFollowUpPrompt(\n host: QueryHost,\n context: TaskContext,\n followUpContent: string | MultimodalBlock[],\n): Promise<string | MultimodalBlock[]> {\n const isPmMode = host.config.mode === \"pm\";\n const followUpText =\n typeof followUpContent === \"string\"\n ? followUpContent\n : followUpContent\n .filter((b): b is Extract<MultimodalBlock, { type: \"text\" }> => b.type === \"text\")\n .map((b) => b.text)\n .join(\"\\n\");\n\n const followUpImages =\n typeof followUpContent === \"string\"\n ? []\n : followUpContent.filter(\n (b): b is Extract<MultimodalBlock, { type: \"image\" }> => b.type === \"image\",\n );\n\n const textPrompt = isPmMode\n ? `${await buildInitialPrompt(host.config.mode, context, host.isAuto, host.agentMode)}\\n\\n---\\n\\nThe team says:\\n${followUpText}`\n : followUpText;\n\n if (isPmMode) {\n const prompt = buildMultimodalPrompt(textPrompt, context);\n if (followUpImages.length > 0 && Array.isArray(prompt)) {\n prompt.push(...followUpImages);\n }\n return prompt;\n }\n if (followUpImages.length > 0) {\n return [{ type: \"text\", text: textPrompt }, ...followUpImages];\n }\n return textPrompt;\n}\n\n// ── SDK query execution ──────────────────────────────────────────────────\n\n/** Pass events through, firing `onFirst` before the first non-system event. */\nasync function* notifyOnFirstEvent(\n inner: AsyncGenerator<HarnessEvent, void>,\n onFirst: () => Promise<void>,\n): AsyncGenerator<HarnessEvent, void> {\n let fired = false;\n for await (const event of inner) {\n if (!fired && event.type !== \"system\") {\n fired = true;\n await onFirst();\n }\n yield event;\n }\n}\n\n// How long a submitted PTY query may stay silent (zero transcript events)\n// before the agent reports waiting_for_input instead of running. A healthy\n// turn writes its first transcript record well inside this window; a TUI\n// parked on an unexpected dialog (trust prompt, onboarding wizard, login\n// screen) never produces one, which previously left the card stuck on\n// \"working\" indefinitely.\nconst PARKED_TUI_GRACE_MS = 45_000;\n\n/**\n * Status-accuracy watchdog for submitted PTY queries. Display-only: the\n * query keeps draining either way, `_state` in SessionRunner is untouched\n * (so chat-message supersede and idle-timer behavior are unchanged), and the\n * first event flips the reported status back to running.\n */\nexport async function* watchForParkedTui(\n inner: AsyncGenerator<HarnessEvent, void>,\n host: Pick<QueryHost, \"connection\" | \"callbacks\">,\n): AsyncGenerator<HarnessEvent, void> {\n let parked = false;\n // The generator body runs lazily, so the timer starts when the consumer\n // begins draining — i.e. when the spawned CLI is live and the prompt has\n // been submitted.\n const timer = setTimeout(() => {\n parked = true;\n host.connection.emitStatus(\"waiting_for_input\");\n void host.callbacks.onStatusChange(\"waiting_for_input\");\n }, PARKED_TUI_GRACE_MS);\n try {\n for await (const event of inner) {\n clearTimeout(timer);\n if (parked) {\n parked = false;\n host.connection.emitStatus(\"running\");\n await host.callbacks.onStatusChange(\"running\");\n }\n yield event;\n }\n } finally {\n clearTimeout(timer);\n }\n}\n\nexport async function runSdkQuery(\n host: QueryHost,\n context: TaskContext,\n followUpContent?: string | MultimodalBlock[],\n promptDeliveryOverride?: \"submit\" | \"prefill\",\n): Promise<void> {\n if (host.isStopped()) return;\n\n const mode = host.agentMode;\n const isDiscoveryLike = mode === \"discovery\" || mode === \"help\";\n const needsPlanSync = isDiscoveryLike || (mode === \"auto\" && !host.hasExitedPlanMode);\n if (needsPlanSync) {\n host.snapshotPlanFiles();\n }\n\n // Use a deterministic UUID derived from the session lineage (taskId, with a\n // \":review\" variant for review runs) as the session ID. Sessions persist via\n // GCS-FUSE, so resuming by the derived UUID works across pod restarts\n // without tracking SDK-generated session IDs.\n //\n // The SDK's `sessionId` and `resume` options are mutually exclusive:\n // - `sessionId` creates a new session with a specific UUID\n // - `resume` loads an existing session\n // Pass `resume` only if the session file already exists on disk;\n // otherwise pass `sessionId` to create fresh with our deterministic ID.\n const sessionUuid = taskIdToSessionUuid(\n sessionLineageKey(context.taskId, mode, host.config.mode),\n );\n const hasExistingSession = sessionFileExists(sessionUuid, host.config.workspaceDir);\n if (hasExistingSession) {\n // An ungraceful pod death can tear the final transcript record mid-append;\n // trim it so --resume gets well-formed JSONL instead of failing outright.\n repairTornSessionFile(sessionTranscriptPath(host.config.workspaceDir, sessionUuid));\n }\n const promptDelivery =\n promptDeliveryOverride ??\n resolvePromptDelivery({\n harnessKind: host.harnessKind,\n runnerMode: host.config.mode,\n isAuto: host.isAuto,\n agentMode: mode,\n isFollowUp: !!followUpContent,\n hasExistingSession,\n });\n const options = {\n ...buildQueryOptions(host, context),\n promptDelivery,\n ...(hasExistingSession ? {} : { sessionId: sessionUuid }),\n };\n const resume = hasExistingSession ? sessionUuid : undefined;\n\n if (followUpContent) {\n await runFollowUpQuery(host, context, options, resume, followUpContent);\n } else if (isDiscoveryLike && promptDelivery !== \"prefill\") {\n // SDK harness (or a resumed session): there is no TUI input box to\n // pre-fill, and discovery must not auto-run — wait for a chat message.\n return;\n } else {\n await runInitialQuery(host, context, options, resume, promptDelivery);\n }\n\n if (needsPlanSync) {\n await host.syncPlanFile();\n }\n}\n\n/** Dispatch a follow-up to the prefill or submit path per the resolved delivery. */\nasync function runFollowUpQuery(\n host: QueryHost,\n context: TaskContext,\n options: HarnessQueryOptions,\n resume: string | undefined,\n followUpContent: string | MultimodalBlock[],\n): Promise<void> {\n if (options.promptDelivery === \"prefill\") {\n await runPrefilledFollowUp(host, context, options, resume, followUpContent);\n return;\n }\n const prompt = await buildFollowUpPrompt(host, context, followUpContent);\n const agentQuery = host.harness.executeQuery({\n prompt: typeof prompt === \"string\" ? prompt : host.createInputStream(prompt),\n options: { ...options },\n resume,\n });\n await trackAndRun(host, context, options, agentQuery);\n}\n\n/**\n * A follow-up delivered as a prefill: paste ONLY the message text into the TUI\n * input (the human reviews/edits/Enters it — e.g. a Refine prompt). Context\n * parity with the submitted pm follow-up (which prepends the full initial\n * prompt) is preserved by moving that text onto `--append-system-prompt`.\n * Images in the follow-up stay reachable via chat attachments.\n */\nasync function runPrefilledFollowUp(\n host: QueryHost,\n context: TaskContext,\n options: HarnessQueryOptions,\n resume: string | undefined,\n followUpContent: string | MultimodalBlock[],\n): Promise<void> {\n const followUpText =\n typeof followUpContent === \"string\"\n ? followUpContent\n : followUpContent\n .filter((b): b is Extract<MultimodalBlock, { type: \"text\" }> => b.type === \"text\")\n .map((b) => b.text)\n .join(\"\\n\");\n\n const queryOptions = { ...options };\n if (host.config.mode === \"pm\" && !resume) {\n // Fresh pm session: the submitted path would prepend the full initial\n // prompt — deliver that context via the system prompt instead.\n const initialPrompt = await buildInitialPrompt(\n host.config.mode,\n context,\n host.isAuto,\n host.agentMode,\n );\n queryOptions.appendSystemPrompt = [queryOptions.appendSystemPrompt, initialPrompt]\n .filter(Boolean)\n .join(\"\\n\\n\")\n .slice(0, APPEND_SYSTEM_PROMPT_MAX_CHARS);\n }\n\n let agentQuery = host.harness.executeQuery({\n prompt: followUpText,\n options: queryOptions,\n resume,\n });\n // Parked until the human submits — first transcript event flips to running.\n agentQuery = notifyOnFirstEvent(agentQuery, async () => {\n host.connection.emitStatus(\"running\");\n await host.callbacks.onStatusChange(\"running\");\n });\n await trackAndRun(host, context, queryOptions, agentQuery);\n}\n\n/** Track the active query while runWithRetry drains it. */\nasync function trackAndRun(\n host: QueryHost,\n context: TaskContext,\n options: HarnessQueryOptions,\n agentQuery: AsyncGenerator<HarnessEvent, void>,\n): Promise<void> {\n // Prefill queries are parked by design (already reported as\n // waiting_for_input); SDK queries emit an init event immediately. Only a\n // submitted PTY turn can silently park on an unexpected CLI dialog.\n if (host.harnessKind === \"pty\" && options.promptDelivery !== \"prefill\") {\n agentQuery = watchForParkedTui(agentQuery, host);\n }\n host.activeQuery = agentQuery;\n try {\n await runWithRetry(agentQuery, context, host, options);\n } finally {\n host.activeQuery = null;\n }\n}\n\n/** Defensive bound for `--append-system-prompt` argv size (Linux MAX_ARG_STRLEN is 128KiB). */\nconst APPEND_SYSTEM_PROMPT_MAX_CHARS = 96_000;\n\n/** The most recent non-empty user chat message — the text a human actually typed. */\nexport function latestUserMessageText(context: TaskContext): string | null {\n for (let i = context.chatHistory.length - 1; i >= 0; i--) {\n const msg = context.chatHistory[i];\n if (msg.role === \"user\" && msg.content.trim()) return msg.content.trim();\n }\n return null;\n}\n\n/**\n * Pick what lands in the TUI input for the INITIAL query, and what rides\n * `--append-system-prompt`, based on the resolved delivery.\n *\n * - **submit**: paste the full `initialPrompt` body — it auto-Enters, so nothing\n * is left parked in the input.\n * - **prefill**: paste ONLY the human's latest chat message, or an EMPTY box\n * when there is none — NEVER the full task body, which would park unsubmitted\n * and block the human from typing a follow-up (the original auto-mode\n * \"re-prefill\" bug). The full instructions/context move onto the system\n * prompt so the agent still has them once the human submits. The pasted\n * prefill is text-only; images stay reachable via chat/task attachments (MCP).\n */\nexport function selectInitialPromptInput(\n promptDelivery: \"submit\" | \"prefill\",\n initialPrompt: string,\n context: TaskContext,\n baseAppendSystemPrompt: string | undefined,\n): { prompt: string | MultimodalBlock[]; appendSystemPrompt: string | undefined } {\n if (promptDelivery === \"prefill\") {\n return {\n prompt: latestUserMessageText(context) ?? \"\",\n appendSystemPrompt: [baseAppendSystemPrompt, initialPrompt]\n .filter(Boolean)\n .join(\"\\n\\n\")\n .slice(0, APPEND_SYSTEM_PROMPT_MAX_CHARS),\n };\n }\n return {\n prompt: buildMultimodalPrompt(initialPrompt, context),\n appendSystemPrompt: baseAppendSystemPrompt,\n };\n}\n\n/** Build and run the initial (non-follow-up) query for the current mode. */\nasync function runInitialQuery(\n host: QueryHost,\n context: TaskContext,\n options: HarnessQueryOptions,\n resume: string | undefined,\n promptDelivery: \"submit\" | \"prefill\",\n): Promise<void> {\n const initialPrompt = await buildInitialPrompt(\n host.config.mode,\n context,\n host.isAuto,\n host.agentMode,\n );\n\n const { prompt, appendSystemPrompt } = selectInitialPromptInput(\n promptDelivery,\n initialPrompt,\n context,\n options.appendSystemPrompt,\n );\n const queryOptions = { ...options, appendSystemPrompt };\n\n let agentQuery = host.harness.executeQuery({\n prompt: host.createInputStream(prompt),\n options: queryOptions,\n resume,\n });\n if (promptDelivery === \"prefill\") {\n // The prompt sits unsubmitted in the TUI; the transcript stays empty\n // until the human presses Enter, so the first non-system event is the\n // \"human engaged\" signal — report running so the runner can leave\n // waiting_for_input and stop the prefill-wait idle timer.\n agentQuery = notifyOnFirstEvent(agentQuery, async () => {\n host.connection.emitStatus(\"running\");\n await host.callbacks.onStatusChange(\"running\");\n });\n }\n await trackAndRun(host, context, queryOptions, agentQuery);\n}\n\n// ── Retry logic ──────────────────────────────────────────────────────────\n\nasync function buildRetryQuery(\n host: QueryHost,\n context: TaskContext,\n options: HarnessQueryOptions,\n lastErrorWasImage: boolean,\n): Promise<AsyncGenerator<HarnessEvent, void>> {\n if (lastErrorWasImage) {\n host.connection.postChatMessage(\n \"An attached image could not be processed. Retrying without images...\",\n );\n }\n const retryPrompt = buildMultimodalPrompt(\n await buildInitialPrompt(host.config.mode, context, host.isAuto, host.agentMode),\n context,\n lastErrorWasImage,\n );\n return host.harness.executeQuery({\n prompt: host.createInputStream(retryPrompt),\n // Strip sessionId on retry — if the failing query partially created a\n // session with that ID, passing it again would error. Let the SDK\n // auto-generate on retry attempts.\n options: { ...options, sessionId: undefined },\n resume: undefined,\n });\n}\n\nexport async function handleAuthError(\n context: TaskContext,\n host: QueryHost,\n options: HarnessQueryOptions,\n): Promise<void> {\n host.connection.postChatMessage(\"Authentication expired. Re-bootstrapping credentials...\");\n\n const refreshed = await host.connection.refreshAuthToken();\n if (!refreshed) {\n // No Claude credential could be resolved (none configured, or the bootstrap\n // has no Claude token to hand back). Do NOT process.exit — that crash-loops\n // the pod, and an agent that can't run still leaves an empty workspace that\n // wedges teardown (2026-07-05 canary). Post an actionable message and return\n // so the runner falls back to its idle/dormant wait: stays connected, burns\n // no tokens, and resumes if a human configures a credential and re-sends.\n host.connection.postChatMessage(\n \"⚠️ No Claude credential is configured for this project — the agent can't run and \" +\n \"is now idle. Add a Claude Code OAuth token (or Anthropic API key) in Project \" +\n \"Settings, then resume this task.\",\n );\n host.connection.sendEvent({\n type: \"error\",\n message: \"No Claude credential available — agent idle (dormant)\",\n });\n return;\n }\n\n // Clear session since it's tied to the old token\n context.claudeSessionId = null;\n host.connection.storeSessionId(\"\");\n\n const freshPrompt = buildMultimodalPrompt(\n await buildInitialPrompt(host.config.mode, context, host.isAuto, host.agentMode),\n context,\n );\n const freshQuery = host.harness.executeQuery({\n prompt: host.createInputStream(freshPrompt),\n options: { ...options, sessionId: undefined },\n resume: undefined,\n });\n return runWithRetry(freshQuery, context, host, options);\n}\n\nasync function handleStaleSession(\n context: TaskContext,\n host: QueryHost,\n options: HarnessQueryOptions,\n): Promise<void> {\n context.claudeSessionId = null;\n host.connection.storeSessionId(\"\");\n const freshPrompt = buildMultimodalPrompt(\n await buildInitialPrompt(host.config.mode, context, host.isAuto, host.agentMode),\n context,\n );\n const freshQuery = host.harness.executeQuery({\n prompt: host.createInputStream(freshPrompt),\n options: { ...options, sessionId: undefined },\n resume: undefined,\n });\n return runWithRetry(freshQuery, context, host, options);\n}\n\nasync function waitForRetryDelay(host: QueryHost, delayMs: number): Promise<void> {\n await new Promise<void>((resolve) => {\n const timer = setTimeout(resolve, delayMs);\n const checkStopped = setInterval(() => {\n if (host.isStopped()) {\n clearTimeout(timer);\n clearInterval(checkStopped);\n resolve();\n }\n }, 1000);\n setTimeout(() => clearInterval(checkStopped), delayMs + 100);\n });\n}\n\nfunction isStaleOrExitedSession(error: unknown, context: TaskContext): boolean {\n if (!(error instanceof Error)) return false;\n if (error.message.includes(\"No conversation found with session ID\")) return true;\n return !!context.claudeSessionId && error.message.includes(\"process exited\");\n}\n\nfunction getErrorMessage(error: unknown): string {\n if (error instanceof Error) return error.message;\n if (typeof error === \"string\") return error;\n return String(error);\n}\n\nfunction isRetriableError(error: unknown): boolean {\n const message = getErrorMessage(error);\n return API_ERROR_PATTERN.test(message) || IMAGE_ERROR_PATTERN.test(message);\n}\n\nfunction classifyImageError(error: unknown): boolean {\n return IMAGE_ERROR_PATTERN.test(getErrorMessage(error));\n}\n\nasync function emitRetryStatus(host: QueryHost, attempt: number, delayMs: number): Promise<void> {\n const delayMin = Math.round(delayMs / 60_000);\n host.connection.postChatMessage(\n `API error encountered. Retrying in ${delayMin} minute${delayMin > 1 ? \"s\" : \"\"}... (attempt ${attempt + 1}/${RETRY_DELAYS_MS.length})`,\n );\n host.connection.sendEvent({\n type: \"error\",\n message: `API error, retrying in ${delayMin}m (${attempt + 1}/${RETRY_DELAYS_MS.length})`,\n });\n host.connection.emitStatus(\"waiting_for_input\");\n await host.callbacks.onStatusChange(\"waiting_for_input\");\n\n await waitForRetryDelay(host, delayMs);\n\n host.connection.emitStatus(\"running\");\n await host.callbacks.onStatusChange(\"running\");\n}\n\nfunction handleRateLimitPause(host: QueryHost, rateLimitResetsAt: string): void {\n host.wasRateLimited = true;\n host.connection.emitRateLimitPause(rateLimitResetsAt);\n host.connection.postChatMessage(\n `Rate limited. The task will be automatically re-queued and resume after ${new Date(rateLimitResetsAt).toLocaleString()}.`,\n );\n}\n\ntype RetryOutcome = { action: \"return\" } | { action: \"continue\"; lastErrorWasImage: boolean };\n\nfunction handleRetryError(\n error: unknown,\n context: TaskContext,\n host: QueryHost,\n options: HarnessQueryOptions,\n prevImageError: boolean,\n): RetryOutcome | Promise<void> {\n if (isStaleOrExitedSession(error, context) && context.claudeSessionId) {\n return handleStaleSession(context, host, options);\n }\n if (isAuthError(getErrorMessage(error))) {\n return handleAuthError(context, host, options);\n }\n if (!isRetriableError(error)) throw error;\n return { action: \"continue\", lastErrorWasImage: classifyImageError(error) || prevImageError };\n}\n\ntype ProcessResult =\n | { action: \"return\" }\n | { action: \"return_promise\"; promise: Promise<void> }\n | { action: \"continue\"; lastErrorWasImage: boolean };\n\nfunction handleProcessResult(\n result: Awaited<ReturnType<typeof processEvents>>,\n context: TaskContext,\n host: QueryHost,\n options: HarnessQueryOptions,\n): ProcessResult {\n if (result.modeRestart || host.isStopped()) return { action: \"return\" };\n\n if (result.rateLimitResetsAt) {\n handleRateLimitPause(host, result.rateLimitResetsAt);\n return { action: \"return\" };\n }\n\n // Handle stale session result errors (same recovery as thrown exceptions)\n if (result.staleSession && context.claudeSessionId) {\n return { action: \"return_promise\", promise: handleStaleSession(context, host, options) };\n }\n\n // Handle auth errors — re-bootstrap token and retry\n if (result.authError) {\n return { action: \"return_promise\", promise: handleAuthError(context, host, options) };\n }\n\n if (!result.retriable) return { action: \"return\" };\n return {\n action: \"continue\",\n lastErrorWasImage: IMAGE_ERROR_PATTERN.test(result.resultSummary ?? \"\"),\n };\n}\n\nasync function runWithRetry(\n initialQuery: AsyncGenerator<HarnessEvent, void>,\n context: TaskContext,\n host: QueryHost,\n options: HarnessQueryOptions,\n): Promise<void> {\n let lastErrorWasImage = false;\n\n for (let attempt = 0; attempt <= RETRY_DELAYS_MS.length; attempt++) {\n if (host.isStopped()) return;\n\n const agentQuery =\n attempt === 0\n ? initialQuery\n : await buildRetryQuery(host, context, options, lastErrorWasImage);\n\n try {\n const result = await processEvents(agentQuery, context, host);\n const outcome = handleProcessResult(result, context, host, options);\n if (outcome.action === \"return\") return;\n if (outcome.action === \"return_promise\") return outcome.promise;\n lastErrorWasImage = outcome.lastErrorWasImage;\n } catch (error) {\n const outcome = handleRetryError(error, context, host, options, lastErrorWasImage);\n if (outcome instanceof Promise) return outcome;\n if (outcome.action === \"return\") return;\n lastErrorWasImage = outcome.lastErrorWasImage;\n }\n\n if (attempt >= RETRY_DELAYS_MS.length) {\n host.connection.postChatMessage(\n `Agent shutting down after ${RETRY_DELAYS_MS.length} failed retry attempts due to API errors. ` +\n `The task will resume automatically when the codespace restarts.`,\n );\n return;\n }\n\n await emitRetryStatus(host, attempt, RETRY_DELAYS_MS[attempt]);\n }\n}\n","import type { TaskContext, ChatMessage } from \"@project/shared\";\n\nfunction findLastAgentMessageIndex(history: ChatMessage[]): number {\n for (let i = history.length - 1; i >= 0; i--) {\n if (history[i].role === \"assistant\") return i;\n }\n return -1;\n}\n\nfunction formatProjectAgents(projectAgents: NonNullable<TaskContext[\"projectAgents\"]>): string[] {\n const parts: string[] = [``, `## Project Agents`];\n for (const pa of projectAgents) {\n const role = pa.role ? `role: ${pa.role}` : \"role: unassigned\";\n const sp =\n pa.storyPoints === null || pa.storyPoints === undefined\n ? \"\"\n : `, story points: ${pa.storyPoints}`;\n parts.push(`- ${pa.agent.name} (${role}${sp})`);\n }\n return parts;\n}\n\nfunction formatStoryPoints(storyPoints: NonNullable<TaskContext[\"storyPoints\"]>): string[] {\n const parts: string[] = [``, `## Story Point Tiers`];\n for (const sp of storyPoints) {\n const desc = sp.description ? ` — ${sp.description}` : \"\";\n parts.push(`- Value ${sp.value}: \"${sp.name}\"${desc}`);\n }\n return parts;\n}\n\nexport function buildPackRunnerSystemPrompt(\n context: TaskContext,\n config: { instructions: string; workspaceDir: string },\n setupLog: string[],\n): string {\n const parts: string[] = [\n `You are an autonomous Pack Runner managing child tasks for the \"${context.title}\" project.`,\n `You are running locally with full access to the repository and task management tools.`,\n `Your job is to execute child tasks by firing cloud builds, reviewing their PRs, and merging them — respecting dependency chains for parallel execution.`,\n ``,\n `## Child Task Status Lifecycle`,\n `- \"Planning\" — Not ready for execution. Skip it (or escalate if blocking).`,\n `- \"Open\" — Ready to execute (if dependencies are met). Use start_child_cloud_build to fire it.`,\n `- \"InProgress\" — Currently being worked on by a Task Runner. Wait — it will move to ReviewPR when done.`,\n `- \"ReviewPR\" — Task Runner finished and opened a PR. Review and merge it.`,\n `- \"ReviewDev\" — PR was merged to dev. This child is complete. Move on.`,\n `- \"Complete\" — Fully done. Move on.`,\n ``,\n `## Autonomous Loop`,\n `Follow this loop each time you are launched or relaunched:`,\n ``,\n `1. Call list_subtasks to see the current state of all child tasks.`,\n ` The response includes PR info, agent assignment, and **dependency info** (dependencies array + allDependenciesMet flag).`,\n ``,\n `2. Evaluate children by status and dependency readiness:`,\n ` - \"ReviewPR\": Review and merge its PR with approve_and_merge_pr. (Highest priority)`,\n ` - If merge fails due to pending CI: post a status update to chat, state you are going idle.`,\n ` - If merge fails due to failed CI: use get_execution_logs(childTaskId) to check. Escalate to team.`,\n ` - \"InProgress\": A Task Runner is actively working. Do nothing — wait.`,\n ` - \"Open\" + allDependenciesMet=true: Ready to fire. Use start_child_cloud_build.`,\n ` - \"Open\" + allDependenciesMet=false: Blocked — skip for now. Will be unblocked when deps complete.`,\n ` - \"ReviewDev\" / \"Complete\": Already done. Skip.`,\n ` - \"Planning\": Not ready. If blocking progress, notify team.`,\n ``,\n `3. Fire ALL ready \"Open\" tasks whose dependencies are met, not just one. Independent tasks can run in parallel.`,\n ``,\n `4. After merging a PR: run \\`git pull origin ${context.baseBranch}\\` then re-check list_subtasks — previously blocked tasks may now be ready.`,\n ``,\n `5. After firing all ready tasks: report which tasks you fired to chat, then state you are going idle.`,\n ``,\n `6. When ALL children are in \"ReviewDev\" or \"Complete\" (no \"Open\", \"InProgress\", or \"ReviewPR\" remaining): do a final review, summarize results in chat, and mark this parent task complete with force_update_task_status(\"Complete\").`,\n ``,\n `## Important Rules`,\n `- When dependencies are set on children, use them to determine execution order. Fire all ready tasks in parallel.`,\n `- When NO dependencies are set on any children, fall back to ordinal order (one at a time). This preserves backward compatibility.`,\n `- After firing builds OR when waiting on CI, explicitly state you are going idle. The system will disconnect you and relaunch when there's a status change.`,\n `- Do NOT attempt to write code yourself. Your role is coordination only.`,\n `- If a child is stuck in \"InProgress\" for an unusually long time, use get_execution_logs(childTaskId) to check its logs and escalate to the team if it appears stuck.`,\n `- You can use get_task(childTaskId) to get a child's full details including PR URL and branch.`,\n `- list_subtasks returns PR info (githubPRNumber, githubPRUrl), agent assignment (agentId), and dependency info for each child — use this to verify readiness before firing builds.`,\n `- You can use read_task_chat to check for team messages.`,\n ];\n\n if (context.storyPoints && context.storyPoints.length > 0) {\n parts.push(...formatStoryPoints(context.storyPoints));\n }\n\n if (context.projectAgents && context.projectAgents.length > 0) {\n parts.push(...formatProjectAgents(context.projectAgents));\n }\n\n if (setupLog.length > 0) {\n parts.push(``, `## Environment setup log`, \"```\", ...setupLog, \"```\");\n }\n\n if (context.agentInstructions) {\n parts.push(``, `## Agent Instructions`, context.agentInstructions);\n }\n if (config.instructions) {\n parts.push(``, `## Additional Instructions`, config.instructions);\n }\n\n parts.push(\n ``,\n `Your turn output appears ONLY in the live agent terminal — it is NOT posted to the task chat. The team does NOT see your replies unless you post them.`,\n `Use post_to_chat (omit task_id → this task's chat) to report which children you fired, status as you orchestrate, and any blocker or escalation the team needs to act on.`,\n `Pass task_id only to message a DIFFERENT task's chat (e.g. a child task).`,\n `Use read_task_chat only if you need to re-read earlier messages beyond the chat context above.`,\n ``,\n `If a Conveyor tool call fails or reports the MCP server is unavailable/disconnected, this is almost always a transient socket reconnect — RETRY the same call; it will succeed once the connection re-establishes. A tool error is NOT a reason to go idle or stop the loop. (Going idle is only correct when you are genuinely waiting on child-task status changes or CI — see the loop above.)`,\n );\n\n return parts.join(\"\\n\");\n}\n\nexport function buildPackRunnerInstructions(\n context: TaskContext,\n scenario: \"fresh\" | \"idle_relaunch\" | \"feedback_relaunch\",\n): string[] {\n const parts: string[] = [`\\n## Instructions`];\n\n if (scenario === \"fresh\") {\n parts.push(\n `You are the Pack Runner for this task and its subtasks.`,\n `Begin your autonomous loop immediately: call list_subtasks to assess the current state.`,\n `If any child is in \"ReviewPR\" status, review and merge its PR first.`,\n `Then fire the next \"Open\" child task.`,\n );\n } else if (scenario === \"idle_relaunch\") {\n parts.push(\n `You have been relaunched — a child task likely changed status.`,\n `Call list_subtasks to check the current state of all children.`,\n `Look for children in \"ReviewPR\" status first — review and merge their PRs.`,\n `Check if any previously blocked tasks now have allDependenciesMet=true — fire them.`,\n `If a child you previously fired is now in \"ReviewDev\", pull latest with \\`git pull origin ${context.baseBranch}\\`.`,\n `If no children need action, state you are going idle.`,\n );\n } else {\n const lastAgentIdx = findLastAgentMessageIndex(context.chatHistory);\n const newMessages = context.chatHistory\n .slice(lastAgentIdx + 1)\n .filter((m) => m.role === \"user\");\n parts.push(\n `You have been relaunched with new messages.`,\n `\\nNew messages since your last run:`,\n ...newMessages.map((m) => `[${m.userName ?? \"user\"}]: ${m.content}`),\n `\\nAfter addressing the feedback, resume your autonomous loop: call list_subtasks and proceed accordingly.`,\n );\n }\n\n return parts;\n}\n","import { PM_CHAT_HISTORY_LIMIT, type TaskContext } from \"@project/shared\";\n\nexport { PM_CHAT_HISTORY_LIMIT };\n\nexport function formatFileSize(bytes: number | undefined): string {\n if (bytes === undefined) return \"\";\n if (bytes < 1024) return `${bytes}B`;\n if (bytes < 1024 * 1024) return `${Math.round(bytes / 1024)}KB`;\n return `${(bytes / (1024 * 1024)).toFixed(1)}MB`;\n}\n\nexport interface FileAttachment {\n fileName: string;\n mimeType: string;\n fileSize?: number;\n content?: string;\n contentEncoding?: string;\n downloadUrl?: string;\n fileId?: string;\n}\n\nexport function formatChatFile(file: FileAttachment): string[] {\n const sizeStr = file.fileSize ? `, ${formatFileSize(file.fileSize)}` : \"\";\n if (file.content && file.contentEncoding === \"utf-8\") {\n return [\n `[Attached: ${file.fileName} (${file.mimeType}${sizeStr})]`,\n \"```\",\n file.content,\n \"```\",\n ];\n }\n if (!file.content) {\n return [`[Attached: ${file.fileName} (${file.mimeType}${sizeStr})]: ${file.downloadUrl}`];\n }\n if (file.content && file.contentEncoding === \"base64\") {\n return [\n `[Attached image: ${file.fileName} (${file.mimeType}${sizeStr}) — use get_attachment(\"${file.fileId}\") to view]`,\n ];\n }\n return [`[Attached: ${file.fileName} (${file.mimeType}${sizeStr})]`];\n}\n\nexport function formatTaskFile(file: FileAttachment): string[] {\n if (file.content && file.contentEncoding === \"utf-8\") {\n return [`\\n### ${file.fileName} (${file.mimeType})`, \"```\", file.content, \"```\"];\n }\n if (file.content && file.contentEncoding === \"base64\") {\n const size = formatFileSize(file.fileSize);\n return [\n `- [Attached image: ${file.fileName} (${file.mimeType}${size ? `, ${size}` : \"\"}) — use get_attachment(\"${file.fileId}\") to view]`,\n ];\n }\n if (!file.content) {\n return [`- **${file.fileName}** (${file.mimeType}): ${file.downloadUrl}`];\n }\n return [];\n}\n\nexport function formatChatHistory(\n chatHistory: TaskContext[\"chatHistory\"],\n limit?: number,\n): string[] {\n const relevant = chatHistory.slice(-(limit ?? PM_CHAT_HISTORY_LIMIT));\n const parts = [`\\n## Recent Chat Context`];\n for (const msg of relevant) {\n const sender = msg.userName ?? msg.role;\n parts.push(`[${sender}]: ${msg.content}`);\n if (msg.files?.length) {\n for (const file of msg.files) {\n parts.push(...formatChatFile(file));\n }\n }\n }\n return parts;\n}\n\nexport function formatRepoRefs(repoRefs: NonNullable<TaskContext[\"repoRefs\"]>): string[] {\n const parts: string[] = [];\n parts.push(`\\n## Repository References`);\n for (const ref of repoRefs) {\n const icon = ref.refType === \"folder\" ? \"folder\" : \"file\";\n parts.push(`- [${icon}] \\`${ref.path}\\``);\n }\n return parts;\n}\n\nexport function formatReferenceProjects(\n referenceProjects: NonNullable<TaskContext[\"referenceProjects\"]>,\n): string[] {\n const parts: string[] = [];\n parts.push(`\\n## Reference Projects`);\n parts.push(\n `These sibling Conveyor projects have been shallow-cloned read-only into \\`/workspaces/references/<slug>/\\` for inspiration. You MAY grep/read them to compare approaches, but you MUST NOT modify them or commit anything from them into this task's repo.\\n`,\n );\n for (const ref of referenceProjects) {\n const repo =\n ref.githubRepoOwner && ref.githubRepoName\n ? ` (${ref.githubRepoOwner}/${ref.githubRepoName})`\n : \"\";\n parts.push(`- **${ref.name}**${repo} — \\`/workspaces/references/${ref.slug}/\\``);\n }\n return parts;\n}\n\nexport function formatProjectObjectives(\n objectives: NonNullable<TaskContext[\"projectObjectives\"]>,\n): string[] {\n const parts: string[] = [];\n parts.push(`\\n## Project Objectives`);\n for (const obj of objectives) {\n const dates = `${obj.startDate.split(\"T\")[0]} to ${obj.endDate.split(\"T\")[0]}`;\n parts.push(`- **${obj.name}** (${dates})${obj.description ? \": \" + obj.description : \"\"}`);\n }\n return parts;\n}\n\nexport function formatRecentRelatedTasks(\n tasks: NonNullable<TaskContext[\"recentRelatedTasks\"]>,\n): string[] {\n const parts: string[] = [];\n parts.push(`\\n## Recently Completed Related Tasks`);\n parts.push(\n `These tasks in the same domain were recently completed. Use them for context on recent changes and patterns.\\n`,\n );\n for (const task of tasks) {\n const tags = task.tagNames.length > 0 ? ` [${task.tagNames.join(\", \")}]` : \"\";\n const pr = task.githubPRUrl ? ` — PR: ${task.githubPRUrl}` : \"\";\n parts.push(`- **${task.title}**${tags}${pr}`);\n }\n return parts;\n}\n\nexport function formatIncidents(incidents: NonNullable<TaskContext[\"incidents\"]>): string[] {\n const parts: string[] = [];\n parts.push(`\\n## Linked Incidents`);\n parts.push(\n `This task has linked incidents. Review them for context on the problem being addressed.\\n`,\n );\n for (const inc of incidents) {\n const severity = inc.severity ? ` [${inc.severity}]` : \"\";\n const status = inc.status ? ` (${inc.status})` : \"\";\n parts.push(`### ${inc.title}${severity}${status}`);\n if (inc.description) parts.push(inc.description);\n if (inc.source) parts.push(`Source: ${inc.source}`);\n }\n return parts;\n}\n","import { readFile, readdir, stat } from \"node:fs/promises\";\nimport type { RunnerMode, TaskContext } from \"@project/shared\";\n\ninterface ResolvedEntry {\n type: \"rule\" | \"file\" | \"folder\" | \"doc\";\n path: string;\n label?: string;\n content: string | null;\n charCount: number;\n}\n\ninterface ResolvedTagContext {\n tagName: string;\n description: string | null;\n entries: ResolvedEntry[];\n}\n\nconst TYPE_PRIORITY: Record<string, number> = { rule: 0, file: 1, folder: 2, doc: 3 };\n\n// Binary file extensions to skip content injection\nconst BINARY_EXTENSIONS = new Set([\n \".png\",\n \".jpg\",\n \".jpeg\",\n \".gif\",\n \".webp\",\n \".ico\",\n \".svg\",\n \".bmp\",\n \".mp3\",\n \".mp4\",\n \".wav\",\n \".avi\",\n \".mov\",\n \".pdf\",\n \".zip\",\n \".tar\",\n \".gz\",\n \".woff\",\n \".woff2\",\n \".ttf\",\n \".eot\",\n \".otf\",\n \".exe\",\n \".dll\",\n \".so\",\n \".dylib\",\n \".wasm\",\n]);\n\nfunction isBinaryPath(filePath: string): boolean {\n const ext = filePath.slice(filePath.lastIndexOf(\".\")).toLowerCase();\n return BINARY_EXTENSIONS.has(ext);\n}\n\n// Module-scope cache of rule/file contents keyed by absolute path.\n// Entries are invalidated when mtime changes (post-merge rule updates)\n// and can be cleared wholesale on session boundaries via clearTagContextCache().\nconst fileContentCache = new Map<string, { mtimeMs: number; content: string }>();\nconst folderListingCache = new Map<string, { mtimeMs: number; listing: string }>();\nlet fileReadCount = 0;\nlet folderReadCount = 0;\n\nexport function clearTagContextCache(): void {\n fileContentCache.clear();\n folderListingCache.clear();\n}\n\nexport function _getTagContextCacheStatsForTest(): {\n files: number;\n folders: number;\n fileReads: number;\n folderReads: number;\n} {\n return {\n files: fileContentCache.size,\n folders: folderListingCache.size,\n fileReads: fileReadCount,\n folderReads: folderReadCount,\n };\n}\n\nexport function _resetTagContextReadCountsForTest(): void {\n fileReadCount = 0;\n folderReadCount = 0;\n}\n\nfunction getContextBudgetChars(_model: string, betas?: string[], runnerMode?: RunnerMode): number {\n const contextWindow = betas?.some((b) => b.includes(\"context-1m\")) ? 1_000_000 : 200_000;\n // Task agents get 15% budget (plan already captures key context); PM/code-review get 25%\n const budgetPct = runnerMode === \"task\" ? 0.15 : 0.25;\n // ~4 chars per token\n return contextWindow * budgetPct * 4;\n}\n\nasync function readFileContent(filePath: string, maxChars: number): Promise<string | null> {\n try {\n if (isBinaryPath(filePath)) return null;\n let rawContent: string;\n let mtimeMs: number;\n try {\n const st = await stat(filePath);\n mtimeMs = st.mtimeMs;\n } catch {\n return null;\n }\n const cached = fileContentCache.get(filePath);\n if (cached && cached.mtimeMs === mtimeMs) {\n rawContent = cached.content;\n } else {\n rawContent = await readFile(filePath, \"utf-8\");\n fileReadCount++;\n fileContentCache.set(filePath, { mtimeMs, content: rawContent });\n }\n if (rawContent.length > maxChars) {\n const omitted = rawContent.length - maxChars;\n return rawContent.slice(0, maxChars) + `\\n[... truncated, ${omitted} chars omitted]`;\n }\n return rawContent;\n } catch {\n return null;\n }\n}\n\nasync function readFolderListing(folderPath: string): Promise<string | null> {\n try {\n let mtimeMs: number;\n try {\n const st = await stat(folderPath);\n mtimeMs = st.mtimeMs;\n } catch {\n return null;\n }\n const cached = folderListingCache.get(folderPath);\n if (cached && cached.mtimeMs === mtimeMs) {\n return cached.listing;\n }\n const entries = await readdir(folderPath);\n folderReadCount++;\n const listing = `Files: ${entries.join(\", \")}`;\n folderListingCache.set(folderPath, { mtimeMs, listing });\n return listing;\n } catch {\n return null;\n }\n}\n\nasync function resolveEntry(\n entry: { type: string; path: string; label?: string },\n budget: { remaining: number },\n): Promise<ResolvedEntry> {\n const result: ResolvedEntry = {\n type: entry.type as ResolvedEntry[\"type\"],\n path: entry.path,\n label: entry.label,\n content: null,\n charCount: 0,\n };\n\n if (budget.remaining <= 0) return result;\n\n if (entry.type === \"doc\") {\n // doc type references project documents in DB — skip content injection\n return result;\n }\n\n if (entry.type === \"folder\") {\n const listing = await readFolderListing(entry.path);\n if (listing) {\n result.content = listing;\n result.charCount = listing.length;\n budget.remaining -= listing.length;\n }\n return result;\n }\n\n // rule or file — read from disk\n // Single file cap: 50% of remaining budget\n const maxChars = Math.floor(budget.remaining * 0.5) || budget.remaining;\n const content = await readFileContent(entry.path, maxChars);\n if (content) {\n result.content = content;\n result.charCount = content.length;\n budget.remaining -= content.length;\n }\n return result;\n}\n\nfunction formatEntry(entry: ResolvedEntry): string {\n const label = entry.label ? ` (${entry.label})` : \"\";\n const header = `#### ${entry.path}${label} (${entry.type})`;\n\n if (entry.content === null) {\n return `> ${entry.type}: ${entry.path}${label}`;\n }\n\n if (entry.type === \"folder\") {\n return `${header}\\n${entry.content}`;\n }\n\n // rule or file — wrap in code fence\n return `${header}\\n\\`\\`\\`\\n${entry.content}\\n\\`\\`\\``;\n}\n\nfunction formatResolvedTags(resolved: ResolvedTagContext[]): string {\n const parts: string[] = [`\\n## Tag Context`];\n\n for (const tag of resolved) {\n if (tag.entries.length === 0) continue;\n const desc = tag.description ? ` — ${tag.description}` : \"\";\n parts.push(`\\n### Tag: \"${tag.tagName}\"${desc}`);\n\n const contentEntries = tag.entries.filter((e) => e.content !== null);\n const pointerEntries = tag.entries.filter((e) => e.content === null);\n\n for (const entry of contentEntries) {\n parts.push(`\\n${formatEntry(entry)}`);\n }\n\n if (pointerEntries.length > 0) {\n parts.push(``);\n parts.push(`> Budget limit reached. Remaining linked files (read manually if needed):`);\n for (const entry of pointerEntries) {\n parts.push(formatEntry(entry));\n }\n }\n }\n\n return parts.join(\"\\n\");\n}\n\nexport async function resolveTagContext(\n projectTags: TaskContext[\"projectTags\"],\n taskTagIds: string[],\n model: string,\n betas?: string[],\n runnerMode?: RunnerMode,\n): Promise<{ injectedSection: string; stats: { injected: number; skipped: number } }> {\n if (!projectTags?.length || !taskTagIds.length) {\n return { injectedSection: \"\", stats: { injected: 0, skipped: 0 } };\n }\n\n const taskTagIdSet = new Set(taskTagIds);\n const assignedTags = projectTags.filter((t) => taskTagIdSet.has(t.id));\n\n if (assignedTags.length === 0) {\n return { injectedSection: \"\", stats: { injected: 0, skipped: 0 } };\n }\n\n // Collect all entries across tags, sorted by type priority\n const allEntries: { tagIndex: number; entry: { type: string; path: string; label?: string } }[] =\n [];\n for (let i = 0; i < assignedTags.length; i++) {\n const tag = assignedTags[i];\n if (!tag.contextPaths?.length) continue;\n const sorted = [...tag.contextPaths].sort(\n (a, b) => (TYPE_PRIORITY[a.type] ?? 99) - (TYPE_PRIORITY[b.type] ?? 99),\n );\n for (const entry of sorted) {\n allEntries.push({ tagIndex: i, entry });\n }\n }\n\n if (allEntries.length === 0) {\n return { injectedSection: \"\", stats: { injected: 0, skipped: 0 } };\n }\n\n const budgetChars = getContextBudgetChars(model, betas, runnerMode);\n const budget = { remaining: budgetChars };\n let injected = 0;\n let skipped = 0;\n\n // Resolve all entries\n const resolved: ResolvedTagContext[] = assignedTags.map((t) => ({\n tagName: t.name,\n description: t.description,\n entries: [],\n }));\n\n for (const { tagIndex, entry } of allEntries) {\n const result = await resolveEntry(entry, budget);\n resolved[tagIndex].entries.push(result);\n if (result.content === null) {\n skipped++;\n } else {\n injected++;\n }\n }\n\n return {\n injectedSection: formatResolvedTags(resolved),\n stats: { injected, skipped },\n };\n}\n","const PLAN_SOFT_CAP = 4000;\nconst PLAN_HEAD_CHARS = 3000;\nconst PLAN_TAIL_CHARS = 500;\nconst PLAN_TRUNCATION_MARKER =\n \"\\n\\n... plan truncated — call get_current_plan for full text ...\\n\\n\";\n\n/**\n * Soft-cap plan markdown to avoid duplicating 5–10K chars in every relaunch\n * context fetch. Agents that need the full plan can call `get_current_plan`\n * (or `get_task` with the current task's slug/id).\n */\nexport function truncatePlanForPrompt(plan: string): string {\n if (plan.length <= PLAN_SOFT_CAP) return plan;\n const head = plan.slice(0, PLAN_HEAD_CHARS);\n const tail = plan.slice(plan.length - PLAN_TAIL_CHARS);\n return `${head}${PLAN_TRUNCATION_MARKER}${tail}`;\n}\n\nexport const PLAN_TRUNCATION_CONSTANTS = {\n PLAN_SOFT_CAP,\n PLAN_HEAD_CHARS,\n PLAN_TAIL_CHARS,\n PLAN_TRUNCATION_MARKER,\n} as const;\n","import type { AgentMode, TaskContext } from \"@project/shared\";\n\nenum PmRelaunchIntent {\n Build = \"build\",\n Review = \"review\",\n AutoWithPlan = \"auto_with_plan\",\n AutoPlanning = \"auto_planning\",\n WaitForTeam = \"wait_for_team\",\n}\n\nfunction resolvePmRelaunchIntent(\n context: TaskContext,\n isAuto?: boolean,\n agentMode?: AgentMode | null,\n): PmRelaunchIntent {\n switch (agentMode) {\n case \"building\":\n return PmRelaunchIntent.Build;\n case \"review\":\n return PmRelaunchIntent.Review;\n default:\n break;\n }\n\n if (!isAuto) return PmRelaunchIntent.WaitForTeam;\n return context.plan?.trim() ? PmRelaunchIntent.AutoWithPlan : PmRelaunchIntent.AutoPlanning;\n}\n\nfunction buildRelaunchMessageSummary(context: TaskContext, lastAgentIdx: number): string[] {\n const newMessages = context.chatHistory.slice(lastAgentIdx + 1).filter((m) => m.role === \"user\");\n if (newMessages.length === 0) {\n return [`You have been relaunched. No new messages since your last session.`];\n }\n return [\n `You have been relaunched. Here are new messages since your last session:`,\n ...newMessages.map((m) => `[${m.userName ?? \"user\"}]: ${m.content}`),\n ];\n}\n\nfunction buildPmBuildRelaunchParts(context: TaskContext, isAuto?: boolean): string[] {\n const parts = [\n `\\nYour plan has been approved. Begin implementing it now.`,\n `Work on the git branch \"${context.githubBranch}\". Stay on this branch — do not checkout or create other branches.`,\n `Start by reading the relevant source files mentioned in the plan, then write code.`,\n `When finished, use the mcp__conveyor__create_pull_request tool to open a PR. Do NOT use gh CLI.`,\n ];\n if (isAuto) {\n parts.push(\n `\\nCRITICAL: You are in Auto mode. Do NOT report status, ask for confirmation, or go idle without making code changes.`,\n `Your FIRST action must be reading source files from the plan, then immediately writing code.`,\n `Do NOT summarize the plan or say \"ready to implement\" — start implementing.`,\n `If you are genuinely blocked, explain the specific blocker — do not go idle silently.`,\n );\n }\n return parts;\n}\n\nfunction buildPmReviewRelaunchParts(): string[] {\n return [\n `\\nResume reviewing and coordinating this task.`,\n `Call list_subtasks to check current child-task state and progress.`,\n `Review children in ReviewPR status first, then approve and merge passing PRs.`,\n `Fire next child builds with start_child_cloud_build when ready.`,\n `Do not implement code directly or create a new PR from the PM review session.`,\n ];\n}\n\nfunction buildPmAutoWithPlanRelaunchParts(): string[] {\n return [\n `\\nYou are in auto mode. A plan already exists for this task.`,\n `Verify that story points, title, and tags are set via get_current_plan, then call ExitPlanMode immediately to transition to building.`,\n `Do NOT wait for team input — proceed autonomously.`,\n ];\n}\n\nfunction buildPmAutoPlanningRelaunchParts(): string[] {\n return [\n `\\nYou are in auto mode. Continue planning autonomously.`,\n `When the plan and all required properties are set, call ExitPlanMode to transition to building.`,\n `Do NOT wait for team input — proceed autonomously.`,\n ];\n}\n\nfunction buildPmWaitForTeamRelaunchParts(): string[] {\n return [\n `\\nYou are the project manager for this task.`,\n `Review the context above and wait for the team to provide instructions before taking action.`,\n ];\n}\n\nexport function buildPmRelaunchParts(\n context: TaskContext,\n lastAgentIdx: number,\n isAuto?: boolean,\n agentMode?: AgentMode | null,\n): string[] {\n const parts = buildRelaunchMessageSummary(context, lastAgentIdx);\n const intent = resolvePmRelaunchIntent(context, isAuto, agentMode);\n const intentPartsByIntent: Record<PmRelaunchIntent, () => string[]> = {\n [PmRelaunchIntent.Build]: () => buildPmBuildRelaunchParts(context, isAuto),\n [PmRelaunchIntent.Review]: buildPmReviewRelaunchParts,\n [PmRelaunchIntent.AutoWithPlan]: buildPmAutoWithPlanRelaunchParts,\n [PmRelaunchIntent.AutoPlanning]: buildPmAutoPlanningRelaunchParts,\n [PmRelaunchIntent.WaitForTeam]: buildPmWaitForTeamRelaunchParts,\n };\n parts.push(...intentPartsByIntent[intent]());\n return parts;\n}\n","import type { AgentMode, RunnerMode, TaskContext } from \"@project/shared\";\n\nconst SP_DESC_MAX_CHARS = 80;\n\nfunction truncateDescription(desc: string, maxChars: number): string {\n if (desc.length <= maxChars) return desc;\n return desc.slice(0, maxChars) + \"…\";\n}\n\ntype ProjectTag = NonNullable<TaskContext[\"projectTags\"]>[number];\n\nfunction formatTagWithContextPaths(tag: ProjectTag): string[] {\n const desc = tag.description ? ` — ${tag.description}` : \"\";\n const lines = [`- Name: \"${tag.name}\"${desc}`];\n for (const link of tag.contextPaths ?? []) {\n const label = link.label ? ` (${link.label})` : \"\";\n lines.push(` → ${link.type}: ${link.path}${label}`);\n }\n return lines;\n}\n\nfunction buildPropertyInstructions(context: TaskContext, runnerMode?: RunnerMode): string[] {\n const isTask = runnerMode === \"task\";\n const parts: string[] = [];\n parts.push(\n ``,\n `### Proactive Property Management`,\n `As you plan this task, proactively fill in task properties when you have enough context:`,\n `- Use update_task_properties to set any combination of: title, story points, and tags`,\n `- You can update all properties at once or just one at a time as needed`,\n `- Icons are assigned automatically during identification — do not set icons manually`,\n ``,\n `Don't wait for the user to ask — fill these in naturally as the plan takes shape.`,\n `If the user adjusts the plan significantly, update the properties to match.`,\n );\n\n // Story points — PM/code-review only\n if (!isTask && context.storyPoints && context.storyPoints.length > 0) {\n parts.push(``, `Available story point tiers:`);\n for (const sp of context.storyPoints) {\n const desc = sp.description\n ? ` — ${truncateDescription(sp.description, SP_DESC_MAX_CHARS)}`\n : \"\";\n parts.push(`- Value ${sp.value}: \"${sp.name}\"${desc}`);\n }\n }\n\n if (context.projectTags && context.projectTags.length > 0) {\n const assignedIds = new Set(context.taskTagIds ?? []);\n const assigned = context.projectTags.filter((t) => assignedIds.has(t.id));\n const unassigned = context.projectTags.filter((t) => !assignedIds.has(t.id));\n\n if (assigned.length > 0) {\n parts.push(``, `Assigned tags:`);\n for (const tag of assigned) parts.push(...formatTagWithContextPaths(tag));\n }\n\n // Unassigned tags — PM/code-review only, include context paths so agents can see linked files\n if (!isTask && unassigned.length > 0) {\n parts.push(``, `Available project tags:`);\n for (const tag of unassigned) parts.push(...formatTagWithContextPaths(tag));\n }\n }\n\n return parts;\n}\n\nfunction buildExplorationMethodology(): string[] {\n return [\n ``,\n `### Exploration Methodology`,\n `Investigate efficiently — do not read files aimlessly:`,\n `- Search first, read second: use grep/glob to locate relevant code, then read only the files that matter`,\n `- Never re-read a file already in your context — you have a large context window, scroll up instead`,\n `- Start with 3-5 critical files, form a hypothesis about the approach, then validate with targeted reads`,\n `- Stop exploring when you can cite specific \\`file.ts:line\\` locations and function names for every step in your plan — that's enough`,\n ];\n}\n\nfunction buildPlanCitationFormat(): string[] {\n return [\n ``,\n `### Plan Citation Format`,\n `Plans must ground each change in the code. For every step that touches code:`,\n `- Cite the exact location as \\`path/from/repo/root.ts:lineNumber\\` (e.g. \\`packages/conveyor-agent/src/execution/mode-prompt.ts:129\\`).`,\n `- Name the specific function, class, constant, or JSX element being touched.`,\n `- When behavior hinges on a short piece of code, quote 1–3 lines inline instead of paraphrasing.`,\n `- Ranges are fine for larger edits (\\`foo.ts:120-145\\`). Do not cite whole files without a line.`,\n `- If a file doesn't exist yet, write \\`NEW: path/to/new-file.ts\\` and describe the surrounding module it fits into.`,\n ];\n}\n\nfunction buildDiscoveryPrompt(context?: TaskContext, runnerMode?: RunnerMode): string {\n const parts = [\n `\\n## Mode: Discovery`,\n `You are in Discovery mode — helping plan and scope this task.`,\n `- You have read-only codebase access (can read files, run git commands, search code)`,\n `- You can write plan files in .claude/plans/ only — no other file writes`,\n `- Do NOT attempt to edit, write, or modify source code files — these operations will be denied`,\n `- If you identify code changes needed, describe them in the plan instead of implementing them`,\n `- You can create and manage subtasks`,\n `- Goal: collaborate with the user to create a clear plan`,\n `- Proactively fill task properties (SP, tags) as the plan takes shape`,\n ``,\n `### Planning Checklist (complete ALL before calling ExitPlanMode)`,\n `Your PRIMARY goal is to create a thorough plan. Complete these steps in order:`,\n `1. Read the task description and chat history — respond to what's been discussed`,\n `2. Investigate the codebase using the methodology below — search first, read targeted files`,\n `3. Save a detailed plan via \\`update_task_plan\\``,\n `4. Set story points, tags, and title via \\`update_task_properties\\` (icon is set automatically)`,\n `5. Discuss the plan with the team if they're engaged, incorporate feedback`,\n `6. THEN call ExitPlanMode — it is the LAST step, not the first`,\n ...buildExplorationMethodology(),\n ...buildPlanCitationFormat(),\n ``,\n `### Self-Identification Tools`,\n `Use these MCP tools to set your own task properties:`,\n `- \\`update_task_plan\\` — save your plan and description`,\n `- \\`update_task_properties\\` — set title, story points, and tags (any combination)`,\n `Note: Icons are assigned automatically during identification after planning is complete.`,\n ``,\n `### Tags & Context`,\n `- Early in discovery, identify relevant project tags that match this task's domain`,\n `- Add matching tags using \\`update_task_properties\\` — this links relevant documentation and rules that help you plan more effectively`,\n `- Tags accelerate discovery by surfacing domain-specific context automatically`,\n ``,\n ...(context?.isParentTask\n ? [\n `### Parent Task Coordination`,\n `You are a parent task with child tasks. Focus on breaking work into child tasks with detailed plans, not planning implementation for yourself.`,\n `- Use \\`list_subtasks\\` to review existing children. Create or update child tasks using \\`create_subtask\\` / \\`update_subtask\\`.`,\n `- Each child task should be a self-contained unit of work with a clear plan.`,\n ]\n : [\n `### Self-Update vs Subtasks`,\n `- If the work fits in a single task (1-3 SP), update YOUR OWN plan and properties — do not create subtasks`,\n `- Only create subtasks when the work genuinely requires multiple independent pieces (e.g., Pack-tier work, 8+ SP)`,\n ]),\n ``,\n `### Subtask Plan Requirements`,\n `When creating subtasks, each MUST include a detailed \\`plan\\` field:`,\n `- Plans should be multi-step implementation guides, not vague descriptions`,\n `- Include concrete \\`file.ts:line\\` citations, function/symbol names, and short code snippets where relevant`,\n `- Reference existing implementations when relevant (e.g., \"follow the pattern in src/services/foo.ts\")`,\n `- Include testing requirements and acceptance criteria`,\n `- Set \\`storyPointValue\\` based on estimated complexity`,\n ``,\n `### Plan Verification Requirements`,\n `Every plan MUST include a **Testing / Verification** section so the build agent has a clear definition of \"done\". Enumerate:`,\n `- The quality gates the build agent should run: \\`bun run lint\\`, \\`bun run typecheck\\`, \\`bun run test\\` (or scoped equivalents)`,\n `- Any task-specific end-to-end checks (manual UI walk-through, API smoke test, migration dry-run, etc.)`,\n `You are NOT expected to run these gates yourself — discovery is read-only. Just describe them in the plan.`,\n ``,\n `### Completing Planning`,\n `Once ALL checklist items above are done, call the **ExitPlanMode** tool.`,\n `- Required before ExitPlanMode will succeed: **plan** (via update_task_plan), **story points** (via update_task_properties), **title** (via update_task_properties)`,\n `- ExitPlanMode validates these properties and marks planning as complete`,\n `- It does NOT start building — the team controls when to switch to Build mode`,\n `- Do NOT call ExitPlanMode until you have thoroughly explored the codebase and saved a detailed plan`,\n ];\n if (context) parts.push(...buildPropertyInstructions(context, runnerMode));\n return parts.join(\"\\n\");\n}\n\nfunction buildAutoPrompt(context?: TaskContext, runnerMode?: RunnerMode): string {\n const parts = [\n `\\n## Mode: Auto`,\n `You are in Auto mode — operating autonomously through planning → building → PR.`,\n ``,\n `### Phase 1: Discovery & Planning (current)`,\n `- You are in the SDK's plan mode — read-only access is enforced automatically`,\n `- You have MCP tools for task properties: update_task_plan, update_task_properties`,\n ``,\n `### Required before transitioning:`,\n `Before calling ExitPlanMode, you MUST fill in ALL of these:`,\n `1. **Plan** — Save a clear implementation plan using update_task_plan`,\n `2. **Story Points** — Assign via update_task_properties`,\n `3. **Title** — Set an accurate title via update_task_properties (if the current one is vague or \"Untitled\")`,\n ``,\n `### Transitioning to Building:`,\n `When your plan is complete and all required properties are set, call the **ExitPlanMode** tool.`,\n `- If any required properties are missing, ExitPlanMode will be denied with details on what's missing`,\n `- Once ExitPlanMode succeeds, you will seamlessly transition to full build access within the same session`,\n `- Continue directly with implementation — no restart or waiting is needed`,\n ``,\n `### Subtask Plan Requirements`,\n `When creating subtasks, each MUST include a detailed \\`plan\\` field:`,\n `- Plans should be multi-step implementation guides, not vague descriptions`,\n `- Include concrete \\`file.ts:line\\` citations, function/symbol names, and short code snippets where relevant`,\n `- Reference existing implementations when relevant`,\n `- Include testing requirements and acceptance criteria`,\n `- Set \\`storyPointValue\\` based on estimated complexity`,\n ``,\n ...buildPlanCitationFormat(),\n ``,\n ...(context?.isParentTask\n ? [\n ``,\n `### Parent Task Guidance`,\n `You are a parent task. Your plan should define child tasks with detailed plans, not direct implementation steps.`,\n `After ExitPlanMode, you'll transition to Review mode to coordinate child task execution.`,\n `Child task status lifecycle: Open → InProgress → ReviewPR → ReviewDev → Complete.`,\n ]\n : []),\n ``,\n `### Autonomous Guidelines:`,\n `- Make decisions independently — do not ask the team for approval at each step`,\n `- Only escalate when genuinely blocked (ambiguous requirements, missing access, conflicting instructions)`,\n `- Investigate efficiently: search (grep/glob) to locate code, read only critical files, form a hypothesis, validate, then plan`,\n ];\n if (context) parts.push(...buildPropertyInstructions(context, runnerMode));\n return parts.join(\"\\n\");\n}\n\nexport function buildModePrompt(\n agentMode: AgentMode | null | undefined,\n context?: TaskContext,\n runnerMode?: RunnerMode,\n): string | null {\n switch (agentMode) {\n case \"discovery\":\n return buildDiscoveryPrompt(context, runnerMode);\n case \"building\": {\n const parts = [\n `\\n## Mode: Building`,\n `You are in Building mode — executing the plan.`,\n `- You have full coding access (read, write, edit, bash, git)`,\n `- Safety rules: no destructive operations, use --force-with-lease instead of --force`,\n ...(context?.isParentTask\n ? [\n `- You are a parent task. Use \\`list_subtasks\\`, \\`start_child_cloud_build\\`, and subtask management tools to coordinate children.`,\n `- Do NOT implement code directly — fire child builds and review their work.`,\n `- Goal: coordinate child task execution and ensure all children complete successfully`,\n ]\n : [\n `- If this is a leaf task (no children): execute the plan directly`,\n `- Goal: implement the plan, verify quality gates, open a PR when done`,\n ``,\n `### Pre-PR Verification Checklist`,\n `Before calling \\`mcp__conveyor__create_pull_request\\`, verify ALL of the following pass:`,\n `1. \\`bun run lint\\` — no new lint errors`,\n `2. \\`bun run typecheck\\` — no new type errors`,\n `3. \\`bun run test\\` — relevant suites pass (scope to the affected package if the full run is prohibitively slow, and state the scope in the PR description)`,\n `If a gate fails, fix it before opening the PR. Do NOT open PRs with known failing gates.`,\n `For refactors: also run \\`git diff ${context?.baseBranch ?? \"dev\"}..HEAD\\` and confirm the public API surface (exports, function signatures) has no unintended breaking changes.`,\n ]),\n ];\n return parts.join(\"\\n\");\n }\n case \"review\":\n return buildReviewPrompt(context);\n case \"auto\":\n return buildAutoPrompt(context, runnerMode);\n default:\n return null;\n }\n}\n\n// oxlint-disable-next-line max-lines-per-function -- prompt construction is a single cohesive block\nfunction buildReviewPrompt(context?: TaskContext): string {\n const parts = [\n `\\n## Mode: Review`,\n `You are in Review mode — performing code review with fix capability.`,\n `- You have full write access — you can audit code, make fixes, push changes, and run tests`,\n `- Safety rules: no destructive operations, use --force-with-lease instead of --force`,\n ``,\n ];\n\n if (context?.isParentTask) {\n parts.push(\n `### Parent Task Review`,\n `You are reviewing and coordinating child tasks.`,\n `- Use \\`list_subtasks\\` to see current child task state and progress.`,\n `- For children in ReviewPR status: review their code quality and merge with \\`approve_and_merge_pr\\`.`,\n `- For children with failing CI: check with \\`get_execution_logs(childTaskId)\\` and escalate if stuck.`,\n `- Fire next child builds with \\`start_child_cloud_build\\` when ready.`,\n `- Create follow-up tasks for issues discovered during review.`,\n ``,\n `### Coordination Workflow`,\n `1. Check child task statuses with \\`list_subtasks\\``,\n `2. Review completed children — check PRs, run tests if needed`,\n `3. Approve and merge passing PRs`,\n `4. Fire builds for children that are ready`,\n `5. Create follow-up tasks for anything out of scope`,\n );\n } else {\n parts.push(\n `### Code Review Process`,\n `1. Run \\`git diff ${context?.baseBranch ?? \"dev\"}..HEAD\\` to see all changes in this PR`,\n `2. Read the task plan to understand the intended changes`,\n `3. Explore the surrounding codebase to verify pattern consistency`,\n `4. Review against the criteria below`,\n ``,\n `### Review Criteria`,\n `- **Correctness**: Does the code do what the plan says? Logic errors, off-by-one, race conditions?`,\n `- **Pattern Consistency**: Does the code follow existing patterns in the codebase? Check nearby files.`,\n `- **Security**: No hardcoded secrets, no injection vulnerabilities, proper input validation at boundaries.`,\n `- **Performance**: No unnecessary loops, no N+1 queries, no blocking in async contexts.`,\n `- **Error Handling**: Appropriate error handling at system boundaries. No swallowed errors.`,\n `- **Test Coverage**: Are new code paths tested? Edge cases covered?`,\n `- **TypeScript Best Practices**: Proper typing (no unnecessary \\`any\\`), correct React patterns, proper async/await.`,\n `- **Naming & Readability**: Clear names, no misleading comments, self-documenting code.`,\n ``,\n `### Fix Capability`,\n `You have full write access. If you find issues:`,\n `- **Small fixes**: Make the fix directly, commit, and push. Then re-review.`,\n `- **Larger issues**: Use \\`request_code_changes\\` to flag them for the team.`,\n `- After pushing fixes, wait for CI to pass before approving.`,\n ``,\n `### Output — You MUST do exactly ONE of:`,\n ``,\n `#### If code passes review (or after you've fixed all issues):`,\n `Use the \\`approve_code_review\\` tool with a brief summary of what looks good.`,\n ``,\n `#### If changes are needed that you cannot fix:`,\n `Use the \\`request_code_changes\\` tool with specific issues:`,\n `- Reference specific files and line numbers`,\n `- Explain what's wrong and suggest fixes`,\n `- Focus on substantive issues, not style nitpicks (linting handles that)`,\n ``,\n `### Previous Review Feedback`,\n `If previous review feedback is present in the chat history, verify those specific issues were addressed before raising new concerns.`,\n ``,\n `### Rules`,\n `- Do NOT re-review things CI already validates (formatting, lint rules).`,\n `- Be concise — actionable specifics over general observations.`,\n `- Max 5-7 issues per review. Prioritize the most important ones.`,\n );\n }\n\n return parts.join(\"\\n\");\n}\n","import type { RunnerMode, AgentMode, TaskContext } from \"@project/shared\";\nimport { buildPackRunnerSystemPrompt } from \"./pack-runner-prompt.js\";\nimport { buildModePrompt } from \"./mode-prompt.js\";\n\nfunction formatProjectAgentLine(pa: NonNullable<TaskContext[\"projectAgents\"]>[number]): string {\n const role = pa.role ? `role: ${pa.role}` : \"role: unassigned\";\n const sp =\n pa.storyPoints === null || pa.storyPoints === undefined\n ? \"\"\n : `, story points: ${pa.storyPoints}`;\n return `- ${pa.agent.name} (${role}${sp})`;\n}\n\nfunction buildPmPreamble(context: TaskContext): string[] {\n const parts = [\n `You are an AI project manager helping to plan tasks for the \"${context.title}\" project.`,\n `You are running locally with full access to the repository.`,\n `You can search code (grep, glob), read files, and run shell commands (e.g. git log, git diff). Search to locate relevant code before reading files. You cannot write or edit files.`,\n `\\nEnvironment (ready, no setup required):`,\n `- Repository is cloned at your current working directory.`,\n `- You can read files and run git commands to understand the codebase before writing task plans.`,\n `- Check the dev branch (e.g. run: git fetch && git checkout dev || git checkout main) to understand the current state of the codebase that agents will branch off of.`,\n `\\nWorkflow:`,\n `- You can draft and iterate on plans in .claude/plans/*.md — these files are automatically synced to the task.`,\n `- You can also use update_task_plan directly to save the plan to the task.`,\n `- After saving the plan, call post_to_chat with a short summary for the team (your turn output is NOT posted to chat — they only see what you post), then end your turn. Do NOT attempt to execute the plan yourself.`,\n `- A separate task agent will handle execution after the team reviews and approves your plan.`,\n ];\n if (context.isParentTask) {\n parts.push(\n `\\nYou are the Project Manager for this set of tasks.`,\n `This task has child tasks (subtasks) that are tracked on the board.`,\n `Your role is to coordinate, plan, and manage the subtasks — not to write code directly.`,\n `Use the subtask tools (create_subtask, update_subtask, list_subtasks) to manage work breakdown.`,\n );\n }\n if (context.projectAgents && context.projectAgents.length > 0) {\n parts.push(`\\nProject Agents:`);\n for (const pa of context.projectAgents) {\n parts.push(formatProjectAgentLine(pa));\n }\n }\n return parts;\n}\n\nfunction buildActivePreamble(context: TaskContext, workspaceDir: string): string[] {\n return [\n `You are an AI project manager in ACTIVE mode for the \"${context.title}\" project.`,\n `You have direct coding access to the repository at ${workspaceDir}.`,\n `You can edit files, run tests, and make commits.`,\n `You still have access to all PM tools (subtasks, update_task_plan, chat).`,\n `\\nEnvironment (ready, no setup required):`,\n `- Repository is cloned at your current working directory.`,\n `- You can read, write, and edit files directly.`,\n `- You can run shell commands including git, build tools, and test runners.`,\n context.githubBranch ? `- You are working on branch: \\`${context.githubBranch}\\`` : \"\",\n `\\nSafety rules:`,\n `- Stay within the project directory (${workspaceDir}).`,\n `- Do NOT run \\`git push --force\\` or \\`git reset --hard\\`. Use \\`--force-with-lease\\` if needed.`,\n `- Do NOT delete \\`.env\\` files or modify \\`node_modules\\`.`,\n `- Do NOT run destructive commands like \\`rm -rf /\\`.`,\n `\\nWorkflow:`,\n `- You can make code changes, fix bugs, run tests, and commit directly.`,\n `- When done with changes, summarize what you did in your reply.`,\n `- If you toggled into active mode temporarily, mention when you're done so the team can switch you back to planning mode.`,\n ].filter(Boolean);\n}\n\nfunction buildTaskAgentPreamble(context: TaskContext): string[] {\n return [\n `You are an AI agent working on a task for the \"${context.title}\" project.`,\n `You are running inside a GitHub Codespace with full access to the repository.`,\n `\\nEnvironment (fully ready — do NOT verify or set up):`,\n `- Repository is cloned at your current working directory.`,\n `- Branch \\`${context.githubBranch}\\` is already checked out.`,\n `- All dependencies are installed, database is migrated, and the dev server is running.`,\n `- Git is configured. Commit and push directly to this branch.`,\n `\\nIMPORTANT — Skip all environment verification. Do NOT run any of the following:`,\n `- bun/npm install, pip install, or any dependency installation`,\n `- bun build, bun lint, bun test, bun typecheck, or any build/check commands as a \"first step\"`,\n `- bun db:generate, bun db:push, prisma migrate, or any database setup`,\n `- bun dev, npm start, or any dev server startup commands`,\n `- pwd, ls, echo, or exploratory shell commands to \"check\" the environment`,\n `Only run these if you encounter a specific error that requires it.`,\n `Start reading the task plan and writing code immediately.`,\n `\\nGit safety — STRICT rules:`,\n `- NEVER run \\`git checkout main\\`, \\`git checkout dev\\`, or switch to any branch other than \\`${context.githubBranch}\\`.`,\n `- NEVER create new branches (no \\`git checkout -b\\`, \\`git switch -c\\`, etc.).`,\n `- This branch was created from \\`${context.baseBranch}\\`. PRs will automatically target that branch.`,\n `- If \\`git push\\` fails with \"non-fast-forward\", run \\`git push --force-with-lease origin ${context.githubBranch}\\`. This branch is exclusively yours — force-with-lease is safe.`,\n ];\n}\n\nexport function buildSystemPrompt(\n mode: RunnerMode | undefined,\n context: TaskContext,\n config: { instructions: string; workspaceDir: string; isAuto?: boolean },\n setupLog: string[],\n agentMode?: AgentMode | null,\n): string {\n const isPm = mode === \"pm\";\n const isPmActive = isPm && agentMode === \"building\";\n const isPackRunner = isPm && !!config.isAuto && !!context.isParentTask;\n\n if (isPackRunner) {\n return buildPackRunnerSystemPrompt(context, config, setupLog);\n }\n\n const parts = isPmActive\n ? buildActivePreamble(context, config.workspaceDir)\n : isPm\n ? buildPmPreamble(context)\n : buildTaskAgentPreamble(context);\n\n if (setupLog.length > 0) {\n parts.push(\n `\\nEnvironment setup log (already executed before you started — proof that setup succeeded):`,\n \"```\",\n ...setupLog,\n \"```\",\n );\n }\n\n if (context.agentInstructions) {\n parts.push(`\\nAgent Instructions:\\n${context.agentInstructions}`);\n }\n if (config.instructions) {\n parts.push(`\\nAdditional Instructions:\\n${config.instructions}`);\n }\n parts.push(\n `\\nYour turn output appears ONLY in the live agent terminal — it is NOT posted to the task chat. The team does NOT see your replies unless you post them.`,\n `Use post_to_chat (omit task_id → your own task's chat) to share meaningful status as you work, a summary when you finish, and any blocker or question you need a human to answer.`,\n `Pass task_id only to message a DIFFERENT task's chat (e.g. a parent task via get_task).`,\n `Use read_task_chat only if you need to re-read earlier messages beyond the chat context above.`,\n `\\nIf a Conveyor tool call fails or reports the MCP server is unavailable/disconnected, this is almost always a transient socket reconnect — simply RETRY the same call and it will succeed once the connection re-establishes. Do NOT stop work, go idle, or treat a tool error as a reason to end your turn. Keep making progress on the code; only post_to_chat to ask for a human if a tool keeps failing across several retries over a sustained period.`,\n );\n if (!isPm || isPmActive) {\n parts.push(\n `Use the mcp__conveyor__create_pull_request tool to open PRs — it automatically stages, commits, and pushes changes before creating the PR. Do NOT use gh CLI or shell commands for PR creation.`,\n );\n }\n\n const modePrompt = buildModePrompt(agentMode, context, mode);\n if (modePrompt) {\n parts.push(modePrompt);\n }\n\n return parts.join(\"\\n\");\n}\n","import {\n PM_CHAT_HISTORY_LIMIT,\n TASK_CHAT_HISTORY_LIMIT,\n type RunnerMode,\n type AgentMode,\n type TaskContext,\n type ChatMessage,\n} from \"@project/shared\";\nimport { buildPackRunnerInstructions } from \"./pack-runner-prompt.js\";\nimport {\n formatChatHistory,\n formatRepoRefs,\n formatReferenceProjects,\n formatProjectObjectives,\n formatRecentRelatedTasks,\n formatIncidents,\n formatTaskFile,\n} from \"./prompt-formatters.js\";\nimport { resolveTagContext } from \"./tag-context-resolver.js\";\nimport { truncatePlanForPrompt } from \"./prompt-truncation.js\";\nimport { buildPmRelaunchParts } from \"./pm-relaunch-instructions.js\";\n\nexport { buildSystemPrompt } from \"./system-prompt.js\";\n\nfunction findLastAgentMessageIndex(history: ChatMessage[]): number {\n for (let i = history.length - 1; i >= 0; i--) {\n if (history[i].role === \"assistant\") return i;\n }\n return -1;\n}\n\n/**\n * Messages newer than the relaunch cursor. The cursor is the id of the most\n * recent message in the chat at the end of the agent's last successful turn.\n *\n * - Cursor inside the visible window → everything after that index is new.\n * - Cursor older than the window (fell off the 20-msg tail) → the entire\n * window is newer than what the agent has seen, so treat all of it as new.\n * This is the bug the cursor fixes: urgent user messages outside the window\n * were previously invisible to `findLastAgentMessageIndex` and the agent\n * reported \"no new instructions.\"\n */\nfunction messagesAfterCursor(\n history: ChatMessage[],\n lastSeenMessageId: string | null | undefined,\n): ChatMessage[] {\n if (!lastSeenMessageId) return history;\n const idx = history.findIndex((m) => m.id === lastSeenMessageId);\n return idx === -1 ? history : history.slice(idx + 1);\n}\n\nfunction detectRelaunchScenario(\n context: TaskContext,\n trustChatHistory = false,\n): \"fresh\" | \"idle_relaunch\" | \"feedback_relaunch\" {\n // Cursor is the primary signal: if set, the agent has completed at least\n // one turn on this session, so this is a relaunch.\n if (context.lastSeenMessageId) {\n const newMessages = messagesAfterCursor(context.chatHistory, context.lastSeenMessageId);\n const hasNewUserMessages = newMessages.some((m) => m.role === \"user\");\n return hasNewUserMessages ? \"feedback_relaunch\" : \"idle_relaunch\";\n }\n\n // No cursor — fall back to chat-history heuristics for backward compatibility\n // with sessions that predate the cursor and for PM/Pack Runner agents whose\n // own prior chat messages are themselves a reliable \"prior work\" indicator.\n const lastAgentIdx = findLastAgentMessageIndex(context.chatHistory);\n if (lastAgentIdx === -1) return \"fresh\";\n\n // githubPRUrl signals prior work survived across restarts. claudeSessionId\n // is intentionally NOT consulted here: it persists across crashed sessions\n // and would cause a false \"prior work done\" reading on a fresh relaunch.\n const hasPriorWork = !!context.githubPRUrl || trustChatHistory;\n if (!hasPriorWork) return \"fresh\";\n\n const messagesAfterAgent = context.chatHistory.slice(lastAgentIdx + 1);\n const hasNewUserMessages = messagesAfterAgent.some((m) => m.role === \"user\");\n return hasNewUserMessages ? \"feedback_relaunch\" : \"idle_relaunch\";\n}\n\nfunction buildRelaunchWithSession(\n mode: RunnerMode | undefined,\n context: TaskContext,\n agentMode?: AgentMode | null,\n isAuto?: boolean,\n): string | null {\n const scenario = detectRelaunchScenario(context);\n // Cursor is the authoritative relaunch signal; claudeSessionId is kept as a\n // fallback for sessions predating the cursor. Either proves the agent has\n // completed at least one turn on this session, so a \"relaunch\" prompt —\n // rather than the fresh-start prompt — is appropriate.\n const hasPriorTurn = !!context.lastSeenMessageId || !!context.claudeSessionId;\n if (!hasPriorTurn || scenario === \"fresh\") return null;\n\n const parts: string[] = [];\n const lastAgentIdx = findLastAgentMessageIndex(context.chatHistory);\n\n if (mode === \"pm\") {\n parts.push(...buildPmRelaunchParts(context, lastAgentIdx, isAuto, agentMode));\n } else if (scenario === \"feedback_relaunch\") {\n const newMessages = (\n context.lastSeenMessageId\n ? messagesAfterCursor(context.chatHistory, context.lastSeenMessageId)\n : context.chatHistory.slice(lastAgentIdx + 1)\n ).filter((m) => m.role === \"user\");\n parts.push(\n `You have been relaunched with new feedback.`,\n `Work on the git branch \"${context.githubBranch}\". Stay on this branch — do not checkout or create other branches.`,\n `\\nNew messages since your last run:`,\n ...newMessages.map((m) => `[${m.userName ?? \"user\"}]: ${m.content}`),\n `\\nAddress the requested changes. Do NOT re-investigate the codebase from scratch or write a new plan — review the feedback and implement the changes directly.`,\n `Commit and push your updates.`,\n );\n if (context.githubPRUrl) {\n parts.push(\n `An existing PR is open at ${context.githubPRUrl} — push to the same branch. Do NOT create a new PR.`,\n );\n } else {\n parts.push(\n `When finished, use the mcp__conveyor__create_pull_request tool to open a PR. Do NOT use gh CLI.`,\n );\n }\n } else {\n parts.push(\n `You were relaunched but no new instructions have been given since your last run.`,\n `Work on the git branch \"${context.githubBranch}\". Stay on this branch — do not checkout or create other branches.`,\n `Run \\`git log --oneline -10\\` to review what you already committed.`,\n `Review the current state of the codebase and verify everything is working correctly.`,\n );\n if (agentMode === \"auto\" || agentMode === \"building\" || isAuto) {\n parts.push(\n `If work is incomplete, continue implementing the plan. When finished, commit, push, and use mcp__conveyor__create_pull_request to open a PR.`,\n `Do NOT go idle or wait for instructions — you are in auto mode.`,\n );\n } else {\n parts.push(\n `Post a brief status update with post_to_chat (your turn output is NOT shown in chat — post_to_chat is how the team sees it), then wait for further instructions.`,\n );\n }\n if (context.githubPRUrl) {\n parts.push(`An existing PR is open at ${context.githubPRUrl}. Do not create a new PR.`);\n }\n }\n\n return parts.join(\"\\n\");\n}\n\nasync function resolveTaskTagContext(\n context: TaskContext,\n runnerMode?: RunnerMode,\n): Promise<string | null> {\n if (!context.projectTags?.length || !context.taskTagIds?.length) return null;\n const { injectedSection } = await resolveTagContext(\n context.projectTags,\n context.taskTagIds,\n context.model,\n context.agentSettings?.betas,\n runnerMode,\n );\n return injectedSection || null;\n}\n\n// oxlint-disable-next-line complexity -- simple field mapping, not real branching complexity\nasync function buildTaskBody(context: TaskContext, runnerMode?: RunnerMode): Promise<string[]> {\n const parts: string[] = [];\n parts.push(`# Task: ${context.title}`);\n if (context.projectName) {\n const descLine = context.projectDescription ? `\\n${context.projectDescription}` : \"\";\n parts.push(`\\n## Project: ${context.projectName}${descLine}`);\n }\n if (context.description) {\n parts.push(`\\n## Description\\n${context.description}`);\n }\n if (context.plan) {\n parts.push(`\\n## Plan\\n${truncatePlanForPrompt(context.plan)}`);\n }\n\n if (context.files && context.files.length > 0) {\n parts.push(`\\n## Attached Files`);\n for (const file of context.files) {\n parts.push(...formatTaskFile(file));\n }\n }\n\n if (context.repoRefs && context.repoRefs.length > 0) {\n parts.push(...formatRepoRefs(context.repoRefs));\n }\n\n if (context.referenceProjects && context.referenceProjects.length > 0) {\n parts.push(...formatReferenceProjects(context.referenceProjects));\n }\n\n const tagSection = await resolveTaskTagContext(context, runnerMode);\n if (tagSection) parts.push(tagSection);\n\n // Project objectives and related tasks help PM planning but are redundant for task agents\n // (task agents already have a plan that incorporates this context)\n if (runnerMode !== \"task\") {\n if (context.projectObjectives && context.projectObjectives.length > 0) {\n parts.push(...formatProjectObjectives(context.projectObjectives));\n }\n if (context.recentRelatedTasks && context.recentRelatedTasks.length > 0) {\n parts.push(...formatRecentRelatedTasks(context.recentRelatedTasks));\n }\n }\n\n if (context.incidents && context.incidents.length > 0) {\n parts.push(...formatIncidents(context.incidents));\n }\n\n if (context.chatHistory.length > 0) {\n const chatLimit = runnerMode === \"task\" ? TASK_CHAT_HISTORY_LIMIT : PM_CHAT_HISTORY_LIMIT;\n parts.push(...formatChatHistory(context.chatHistory, chatLimit));\n }\n\n return parts;\n}\n\nfunction buildFreshInstructions(\n isPm: boolean,\n isCodeReview: boolean,\n isAutoMode: boolean,\n context: TaskContext,\n agentMode?: AgentMode | null,\n): string[] {\n if (isCodeReview) {\n return buildFreshCodeReviewInstructions(context);\n }\n\n // After auto→building transition, agent needs building instructions\n // PM→building only happens through auto mode, so always include anti-idle guidance\n if (isPm && agentMode === \"building\") {\n return [\n `Your plan has been approved. Begin implementing it now.`,\n `Work on the git branch \"${context.githubBranch}\". Stay on this branch — do not checkout or create other branches.`,\n `Start by reading the relevant source files mentioned in the plan, then write code.`,\n `When finished, use the mcp__conveyor__create_pull_request tool to open a PR. Do NOT use gh CLI.`,\n `\\nCRITICAL: You are in Auto mode. Do NOT report status, ask for confirmation, or go idle without making code changes.`,\n `Your FIRST action must be reading source files from the plan, then immediately writing code.`,\n `Do NOT summarize the plan or say \"ready to implement\" — start implementing.`,\n `When all changes are ready, use mcp__conveyor__create_pull_request to open a PR.`,\n `If you are genuinely blocked, explain the specific blocker — do not go idle silently.`,\n ];\n }\n if (isAutoMode && isPm) {\n if (context.plan?.trim()) {\n return [\n `You are operating autonomously. A plan already exists for this task.`,\n `Verify that story points, title, and tags are set, then call ExitPlanMode immediately to transition to building.`,\n `Do NOT re-plan or wait for team input — proceed autonomously.`,\n ];\n }\n return [\n `You are operating autonomously. Begin planning immediately.`,\n `1. Search the codebase (grep/glob) to locate relevant files, then read the critical ones`,\n `2. Draft a clear implementation plan and save it with update_task_plan`,\n `3. Set story points, tags, and title (update_task_properties)`,\n `4. When the plan and all required properties are set, call ExitPlanMode to transition to building`,\n `Do NOT wait for team input — proceed autonomously.`,\n ];\n }\n if (isPm && context.isParentTask) {\n return [\n `You are the project manager for this task and its subtasks.`,\n `Review existing subtasks via \\`list_subtasks\\` and the chat history before taking action.`,\n `Read the task description and chat history carefully — the team has provided the initial context below. Acknowledge what they've asked for and respond in chat before taking silent tool actions.`,\n `Start planning now — explore the codebase, ask clarifying questions if needed, and propose a subtask breakdown. Do not wait for additional team input before engaging.`,\n `When you finish planning, save the plan with update_task_plan, post a short summary for the team with post_to_chat (your turn output is NOT shown in chat), then end your turn.`,\n ];\n }\n if (isPm) {\n return [\n `You are the project manager for this task.`,\n `Read the task description and chat history carefully — the team has provided the initial context below. Acknowledge what they've asked for and respond in chat before taking silent tool actions.`,\n `Start planning now — explore the codebase, ask clarifying questions if needed, and draft a plan. Do not wait for additional team input before engaging; the initial message IS the team engaging.`,\n `When you finish planning, save the plan with update_task_plan, post a summary of the plan for the team with post_to_chat (your turn output is NOT shown in chat), then end your turn. A separate task agent will execute the plan after review.`,\n ];\n }\n const parts = [\n `Begin executing the task plan above immediately.`,\n `Your FIRST action should be reading the relevant source files mentioned in the plan, then writing code. Do NOT run install, build, lint, test, or dev server commands first — the environment is already set up.`,\n `Work on the git branch \"${context.githubBranch}\". Stay on this branch for the entire task. Do not checkout or create other branches.`,\n `Use post_to_chat to keep the team informed (your turn output is NOT shown in chat — post_to_chat is the only way they see it): briefly post what you're doing when you begin meaningful implementation, and again when the PR is ready.`,\n `Before opening the PR, run the quality gates: \\`bun run lint && bun run typecheck && bun run test\\`. Fix any failures. Do NOT open a PR with known failing gates — scope the test run to affected packages if the full suite is prohibitively slow, and state the scope in the PR body.`,\n `When finished, use the mcp__conveyor__create_pull_request tool to open a PR. Do NOT use gh CLI or any other method to create PRs.`,\n ];\n if (isAutoMode) {\n parts.push(\n `\\nCRITICAL: You are in Auto mode. Do NOT report status, ask for confirmation, or go idle without making code changes.`,\n `Do NOT summarize the plan or say \"ready to implement\" — start implementing immediately.`,\n `When all changes are ready, you MUST use mcp__conveyor__create_pull_request to open a PR before finishing.`,\n `If you are genuinely blocked, explain the specific blocker — do not go idle silently.`,\n );\n }\n return parts;\n}\n\nfunction buildFreshCodeReviewInstructions(context: TaskContext): string[] {\n const parts = [\n `Perform the automated code review for this PR.`,\n `Work on the git branch \"${context.githubBranch}\". Stay on this branch for the entire review. Do not checkout or create other branches.`,\n `Start by running \\`git diff ${context.baseBranch ?? \"dev\"}..HEAD\\` to inspect the submitted changes, then read the task plan and surrounding code as needed.`,\n `Review for correctness, security, performance, error handling, test coverage, and consistency with existing patterns.`,\n `If small fixes are needed, make them directly, commit, push, and re-review the result.`,\n `Use approve_code_review when the PR passes review.`,\n `Use request_code_changes when substantive issues remain that you cannot fix directly.`,\n ];\n if (context.githubPRUrl) {\n parts.push(`The PR under review is ${context.githubPRUrl}. Do not create a new PR.`);\n }\n return parts;\n}\n\nfunction buildFeedbackInstructions(\n context: TaskContext,\n isPm: boolean,\n agentMode?: AgentMode | null,\n isAuto?: boolean,\n): string[] {\n const lastAgentIdx = findLastAgentMessageIndex(context.chatHistory);\n const newMessages = context.chatHistory.slice(lastAgentIdx + 1).filter((m) => m.role === \"user\");\n if (isPm) {\n const parts = [\n `You were relaunched with new feedback since your last run.`,\n `You are the project manager for this task.`,\n `\\nNew messages since your last run:`,\n ...newMessages.map((m) => `[${m.userName ?? \"user\"}]: ${m.content}`),\n ];\n if (isAuto && (agentMode === \"building\" || agentMode === \"review\")) {\n parts.push(\n `\\nYour plan has been approved. Address the feedback above, then begin implementing.`,\n `Work on the git branch \"${context.githubBranch}\". Stay on this branch — do not checkout or create other branches.`,\n `Start by reading the relevant source files mentioned in the plan, then write code.`,\n `When finished, use the mcp__conveyor__create_pull_request tool to open a PR. Do NOT use gh CLI.`,\n );\n } else if (isAuto) {\n parts.push(\n `\\nYou are in auto mode. Address the feedback above — update the plan accordingly using update_task_plan.`,\n `When the plan and all required properties are set, call ExitPlanMode to transition to building.`,\n `Do NOT wait for additional team input — the messages above ARE the team's input. Proceed autonomously.`,\n );\n } else {\n parts.push(\n `\\nReview these messages and wait for the team to provide instructions before taking action.`,\n );\n }\n return parts;\n }\n const parts = [\n `You have been relaunched to address feedback on your previous work.`,\n `Work on the git branch \"${context.githubBranch}\". Stay on this branch — do not checkout or create other branches.`,\n `Start by running \\`git log --oneline -10\\` and \\`git diff HEAD~3 HEAD --stat\\` to review what you already committed.`,\n `\\nNew messages since your last run:`,\n ...newMessages.map((m) => `[${m.userName ?? \"user\"}]: ${m.content}`),\n `\\nAddress the requested changes directly. Do NOT re-investigate the codebase from scratch or write a new plan — go straight to implementing the feedback.`,\n `Before pushing or opening a PR, re-run the quality gates: \\`bun run lint && bun run typecheck && bun run test\\`. Fix any failures — relaunches are the most common place verification gets skipped.`,\n `Implement your updates and open a PR when finished.`,\n ];\n if (context.githubPRUrl) {\n parts.push(\n `An existing PR is open at ${context.githubPRUrl} — push to the same branch to update it. Do NOT create a new PR.`,\n );\n } else {\n parts.push(\n `When finished, use the mcp__conveyor__create_pull_request tool to open a PR. Do NOT use gh CLI or any other method to create PRs.`,\n );\n }\n return parts;\n}\n\nfunction buildIdleRelaunchInstructions(\n context: TaskContext,\n isPm: boolean,\n agentMode?: AgentMode | null,\n isAuto?: boolean,\n): string[] {\n if (isPm && agentMode === \"auto\" && context.status === \"Planning\") {\n if (context.plan?.trim()) {\n return [\n `You were relaunched in auto mode. A plan already exists for this task.`,\n `Verify that story points, title, and tags are set, then call ExitPlanMode immediately to transition to building.`,\n `Do NOT wait for instructions or go idle — you are in auto mode.`,\n ];\n }\n return [\n `You were relaunched in auto mode. Continue planning autonomously.`,\n `When the plan and all required properties are set, call ExitPlanMode to transition to building.`,\n `Do NOT wait for instructions or go idle — you are in auto mode.`,\n ];\n }\n\n if (isPm && !(agentMode === \"building\" || agentMode === \"review\" || agentMode === \"auto\")) {\n return [\n `You were relaunched but no new instructions have been given since your last run.`,\n `You are the project manager for this task.`,\n `Wait for the team to provide instructions before taking action.`,\n ];\n }\n\n // Task agent or PM in building/review/auto mode — check agentMode independently\n // of isAuto as defense-in-depth against stale isAuto values.\n const isAutoMode = agentMode === \"auto\" || agentMode === \"building\" || isAuto;\n const parts = [\n `You were relaunched but no new instructions have been given since your last run.`,\n `Work on the git branch \"${context.githubBranch}\". Stay on this branch — do not checkout or create other branches.`,\n `Run \\`git log --oneline -10\\` to review what you already committed, then verify the current state is correct.`,\n ];\n if (isAutoMode) {\n parts.push(\n `If work is incomplete, continue implementing the plan. When finished, use mcp__conveyor__create_pull_request to open a PR.`,\n `Do NOT go idle or wait for instructions — you are in auto mode.`,\n );\n } else {\n parts.push(\n `Post a brief status update summarizing where things stand with post_to_chat (your turn output is NOT shown in chat — post_to_chat is how the team sees it).`,\n `Then wait for further instructions — do NOT redo work that was already completed.`,\n );\n }\n if (context.githubPRUrl) {\n parts.push(`An existing PR is open at ${context.githubPRUrl}. Do not create a new PR.`);\n }\n return parts;\n}\n\nfunction buildInstructions(\n mode: RunnerMode | undefined,\n context: TaskContext,\n scenario: \"fresh\" | \"idle_relaunch\" | \"feedback_relaunch\",\n agentMode?: AgentMode | null,\n isAuto?: boolean,\n): string[] {\n const parts: string[] = [`\\n## Instructions`];\n\n const isPm = mode === \"pm\";\n const isCodeReview = mode === \"code-review\" || (!isPm && agentMode === \"review\");\n\n if (scenario === \"fresh\") {\n parts.push(\n ...buildFreshInstructions(isPm, isCodeReview, agentMode === \"auto\", context, agentMode),\n );\n return parts;\n }\n\n if (scenario === \"idle_relaunch\") {\n parts.push(...buildIdleRelaunchInstructions(context, isPm, agentMode, isAuto));\n return parts;\n }\n\n parts.push(...buildFeedbackInstructions(context, isPm, agentMode, isAuto));\n return parts;\n}\n\nexport async function buildInitialPrompt(\n mode: RunnerMode | undefined,\n context: TaskContext,\n isAuto?: boolean,\n agentMode?: AgentMode | null,\n): Promise<string> {\n const isPackRunner = mode === \"pm\" && !!isAuto && !!context.isParentTask;\n\n if (!isPackRunner) {\n const sessionRelaunch = buildRelaunchWithSession(mode, context, agentMode, isAuto);\n if (sessionRelaunch) return sessionRelaunch;\n }\n\n const isPm = mode === \"pm\";\n let scenario = detectRelaunchScenario(context, isPm);\n\n // After auto-mode transition from planning to building, planning-phase chat\n // history causes \"idle_relaunch\" even though no building work has started.\n // Override to \"fresh\" so the agent gets \"begin implementing\" instructions.\n if (\n isPm &&\n agentMode === \"building\" &&\n isAuto &&\n !context.claudeSessionId &&\n !context.githubPRUrl &&\n scenario === \"idle_relaunch\"\n ) {\n scenario = \"fresh\";\n }\n const body = await buildTaskBody(context, mode);\n const instructions = isPackRunner\n ? buildPackRunnerInstructions(context, scenario)\n : buildInstructions(mode, context, scenario, agentMode, isAuto);\n return [...body, ...instructions].join(\"\\n\");\n}\n","import { z } from \"zod\";\nimport { defineTool } from \"../harness/index.js\";\nimport type { AgentConnection } from \"../connection/agent-connection.js\";\nimport { textResult, imageBlock, isImageMimeType, formatCliEvent } from \"./helpers.js\";\n\ntype ContentBlock =\n | { type: \"text\"; text: string }\n | { type: \"image\"; data: string; mimeType: string };\n\nexport function buildReadTaskChatTool(connection: AgentConnection) {\n return defineTool(\n \"read_task_chat\",\n \"Read recent human/user chat messages for a task. Omit task_id for the current task; pass a child ID for a child's chat. For agent logs use get_execution_logs.\",\n {\n limit: z.number().optional().describe(\"Number of recent messages to fetch (default 20)\"),\n task_id: z\n .string()\n .optional()\n .describe(\"Child task ID to read chat from. Omit to read the current task's chat.\"),\n },\n async ({ limit, task_id }) => {\n try {\n const messages = await connection.call(\"getChatMessages\", {\n sessionId: connection.sessionId,\n limit,\n taskId: task_id,\n });\n return textResult(JSON.stringify(messages, null, 2));\n } catch {\n return textResult(\n JSON.stringify({\n note: \"Could not fetch live chat. Chat history was provided in the initial context.\",\n }),\n );\n }\n },\n { annotations: { readOnlyHint: true } },\n );\n}\n\nexport function buildGetCurrentPlanTool(connection: AgentConnection) {\n return defineTool(\n \"get_current_plan\",\n \"Re-read the current task's plan. Use when the user updated the plan or asked you to re-read it — otherwise the plan is already in initial context. For task metadata use get_task.\",\n {},\n async () => {\n try {\n const ctx = await connection.call(\"getTaskContext\", {\n sessionId: connection.sessionId,\n });\n return textResult(ctx.plan ?? \"No plan available.\");\n } catch {\n return textResult(\"Could not fetch updated plan.\");\n }\n },\n { annotations: { readOnlyHint: true } },\n );\n}\n\nexport function buildGetTaskTool(connection: AgentConnection) {\n return defineTool(\n \"get_task\",\n \"Look up any task by slug or ID. Returns JSON with id, slug, title, description, plan, status, branch, githubPRNumber, githubPRUrl, storyPoints. For children use list_subtasks.\",\n {\n slug_or_id: z.string().describe(\"The task slug (e.g. 'my-task') or CUID\"),\n },\n async ({ slug_or_id }) => {\n try {\n const task = await connection.call(\"getTask\", {\n sessionId: connection.sessionId,\n taskSlugOrId: slug_or_id,\n });\n return textResult(JSON.stringify(task, null, 2));\n } catch (error) {\n return textResult(\n `Failed to get task: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n },\n { annotations: { readOnlyHint: true } },\n );\n}\n\nexport function buildGetExecutionLogsTool(connection: AgentConnection) {\n return defineTool(\n \"get_execution_logs\",\n \"Read CLI execution logs — agent reasoning, tool calls, and setup/dev-server output. Filter via source='agent' or 'application'. For human chat use read_task_chat.\",\n {\n task_id: z\n .string()\n .optional()\n .describe(\"Task ID or slug. Omit to read logs from the current task.\"),\n source: z\n .enum([\"agent\", \"application\"])\n .optional()\n .describe(\"Filter by log source. Omit for all logs.\"),\n limit: z\n .number()\n .optional()\n .describe(\"Max number of log entries to return (default 50, max 500).\"),\n },\n async ({ task_id, source, limit }) => {\n try {\n const effectiveLimit = Math.min(limit ?? 50, 500);\n const result = await connection.call(\"getCliHistory\", {\n sessionId: connection.sessionId,\n limit: effectiveLimit,\n taskId: task_id,\n source,\n });\n const formatted = (result as Array<Record<string, unknown>>)\n .map((entry) => {\n const type = entry.type as string;\n const time = entry.timestamp as string;\n return `[${time}] [${type}] ${formatCliEvent(entry as Record<string, unknown>)}`;\n })\n .join(\"\\n\");\n return textResult(formatted || \"No CLI logs found.\");\n } catch (error) {\n return textResult(\n `Failed to fetch CLI logs: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n },\n { annotations: { readOnlyHint: true } },\n );\n}\n\nexport function buildListTaskFilesTool(connection: AgentConnection) {\n return defineTool(\n \"list_task_files\",\n \"List all files attached to this task with metadata. Use before fetching a specific file to see what is available and how large each is. For file contents use get_attachment.\",\n {},\n async () => {\n try {\n const files = await connection.call(\"getTaskFiles\", {\n sessionId: connection.sessionId,\n });\n const metadata = files.map((file) => {\n const { content: _c, ...rest } = file;\n return rest;\n });\n const content: ContentBlock[] = [\n { type: \"text\" as const, text: JSON.stringify(metadata, null, 2) },\n ];\n for (const file of files) {\n if (file.content && file.contentEncoding === \"base64\" && isImageMimeType(file.mimeType)) {\n content.push(imageBlock(file.content, file.mimeType));\n }\n }\n return { content };\n } catch {\n return textResult(\"Failed to list task files.\");\n }\n },\n { annotations: { readOnlyHint: true } },\n );\n}\n\nexport function buildGetAttachmentTool(connection: AgentConnection) {\n return defineTool(\n \"get_attachment\",\n \"Fetch one task file's content plus metadata by file ID. Call list_task_files first to discover IDs and check sizes — large binaries may be truncated by the service's size limit.\",\n { fileId: z.string().describe(\"The file ID to retrieve\") },\n async ({ fileId }) => {\n try {\n const file = await connection.call(\"getTaskFile\", {\n sessionId: connection.sessionId,\n fileId,\n });\n const { content: rawContent, ...metadata } = file;\n const content: ContentBlock[] = [\n { type: \"text\" as const, text: JSON.stringify(metadata, null, 2) },\n ];\n if (rawContent && file.contentEncoding === \"base64\" && isImageMimeType(file.mimeType)) {\n content.push(imageBlock(rawContent, file.mimeType));\n } else if (rawContent) {\n content[0] = { type: \"text\" as const, text: JSON.stringify(file, null, 2) };\n }\n return { content };\n } catch (error) {\n return textResult(\n `Failed to get task file: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n },\n { annotations: { readOnlyHint: true } },\n );\n}\n\n/** All read-only task context tools. */\nexport function buildTaskContextTools(connection: AgentConnection) {\n return [\n buildReadTaskChatTool(connection),\n buildGetCurrentPlanTool(connection),\n buildGetTaskTool(connection),\n buildGetExecutionLogsTool(connection),\n buildListTaskFilesTool(connection),\n buildGetAttachmentTool(connection),\n ];\n}\n","/** Shared result helpers for MCP tool handlers. */\n\nexport function textResult(text: string): { content: { type: \"text\"; text: string }[] } {\n return { content: [{ type: \"text\" as const, text }] };\n}\n\nexport function imageBlock(\n data: string,\n mimeType: string,\n): { type: \"image\"; data: string; mimeType: string } {\n return { type: \"image\" as const, data, mimeType };\n}\n\nexport function isImageMimeType(mimeType: string): boolean {\n return mimeType.startsWith(\"image/\");\n}\n\n// ── Event formatting for CLI logs ─────────────────────────────────────\n\ntype EventRecord = Record<string, unknown>;\n\nconst cliEventFormatters: Record<string, (e: EventRecord) => string> = {\n thinking: (e) => (e.message as string) ?? \"\",\n tool_use: (e) => `${e.tool}: ${(e.input as string)?.slice(0, 1000) ?? \"\"}`,\n tool_result: (e) =>\n `${e.tool} → ${(e.output as string)?.slice(0, 500) ?? \"\"}${e.isError ? \" [ERROR]\" : \"\"}`,\n message: (e) => (e.content as string) ?? \"\",\n error: (e) => `ERROR: ${(e.message as string) ?? \"\"}`,\n completed: (e) =>\n `Completed: ${(e.summary as string) ?? \"\"} (duration: ${e.durationMs ?? \"?\"}ms)`,\n setup_output: (e) => `[${(e.stream as string) ?? \"stdout\"}] ${(e.data as string) ?? \"\"}`,\n start_command_output: (e) => `[${(e.stream as string) ?? \"stdout\"}] ${(e.data as string) ?? \"\"}`,\n turn_end: (e) => `Turn complete (${(e.toolCalls as unknown[])?.length ?? 0} tool calls)`,\n};\n\nexport function formatCliEvent(e: EventRecord): string {\n const formatter = cliEventFormatters[e.type as string];\n return formatter ? formatter(e) : JSON.stringify(e);\n}\n","import { z } from \"zod\";\nimport { defineTool } from \"../harness/index.js\";\nimport type { AgentConnection } from \"../connection/agent-connection.js\";\nimport { textResult } from \"./helpers.js\";\n\nexport function buildGetDependenciesTool(connection: AgentConnection) {\n return defineTool(\n \"get_dependencies\",\n \"Get this task's dependencies and their met/unmet status (met = merged to dev). Use to confirm blockers merged, or see why a task cannot start. For task state use get_task.\",\n {},\n async () => {\n try {\n const deps = await connection.call(\"getDependencies\", {\n sessionId: connection.sessionId,\n });\n return textResult(JSON.stringify(deps, null, 2));\n } catch (error) {\n return textResult(\n `Failed to get dependencies: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n },\n { annotations: { readOnlyHint: true } },\n );\n}\n\nexport function buildGetSuggestionsTool(connection: AgentConnection) {\n return defineTool(\n \"get_suggestions\",\n \"List project suggestions sorted by vote score. Filter by status or cap with limit (default 20). Suggestions are project-level ideas, not tasks — use get_task for tasks.\",\n {\n status: z\n .string()\n .optional()\n .describe(\n \"Filter by status: Planning, Open, InProgress, ReviewPR, ReviewDev, ReviewLive, Complete, Cancelled\",\n ),\n limit: z.number().int().min(1).max(100).optional().describe(\"Max results (default 20)\"),\n },\n async ({ status, limit }) => {\n try {\n const suggestions = await connection.call(\"getSuggestions\", {\n sessionId: connection.sessionId,\n status,\n limit,\n });\n if (suggestions.length === 0) {\n return textResult(\"No suggestions found.\");\n }\n return textResult(JSON.stringify(suggestions, null, 2));\n } catch (error) {\n return textResult(\n `Failed to get suggestions: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n },\n { annotations: { readOnlyHint: true } },\n );\n}\n","import { z } from \"zod\";\nimport { defineTool } from \"../harness/index.js\";\nimport type { AgentConnection } from \"../connection/agent-connection.js\";\nimport type { AgentRunnerConfig } from \"../types.js\";\nimport { textResult } from \"./helpers.js\";\nimport {\n hasUncommittedChanges,\n stageAndCommit,\n hasUnpushedCommits,\n pushToOrigin,\n} from \"../runner/git-utils.js\";\n\nexport function buildPostToChatTool(connection: AgentConnection) {\n return defineTool(\n \"post_to_chat\",\n \"Post a message to the task chat for the team to see. Your turn output is NOT shown in chat, so this is the only way the team sees your status, summaries, and questions. Omit task_id to post to the current task's chat; pass a child's ID to message its chat.\",\n {\n message: z.string().describe(\"The message to post to the team\"),\n task_id: z\n .string()\n .optional()\n .describe(\"Child task ID to post to. Omit to post to the current task's chat.\"),\n },\n async ({ message, task_id }) => {\n try {\n if (task_id) {\n await connection.call(\"postChildChatMessage\", {\n sessionId: connection.sessionId,\n childTaskId: task_id,\n message,\n });\n return textResult(JSON.stringify({ posted: true, target: `child:${task_id}` }));\n }\n const dedup = connection.checkAndTrackDuplicate(message);\n if (dedup.duplicate) {\n return textResult(\n JSON.stringify({\n posted: false,\n reason: \"duplicate\",\n matchedMessagePreview: dedup.matchedMessagePreview,\n hint: \"A near-identical message (>70% word overlap) was posted within the last 30s. Rephrase with new information or skip this post.\",\n }),\n );\n }\n await connection.call(\"postToChat\", { message });\n return textResult(JSON.stringify({ posted: true }));\n } catch (error) {\n return textResult(\n `Failed to post message: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n },\n );\n}\n\nexport function buildForceUpdateTaskStatusTool(connection: AgentConnection) {\n return defineTool(\n \"force_update_task_status\",\n \"EMERGENCY ONLY: force-override a task's Kanban status. Use when an automatic transition failed and the task is wedged. Normal flow transitions status automatically.\",\n {\n status: z\n .enum([\"InProgress\", \"ReviewPR\", \"ReviewDev\", \"Complete\"])\n .describe(\"The new status for the task\"),\n task_id: z\n .string()\n .optional()\n .describe(\"Child task ID to update. Omit to update the current task.\"),\n },\n async ({ status, task_id }) => {\n try {\n if (task_id) {\n await connection.call(\"updateChildStatus\", {\n sessionId: connection.sessionId,\n childTaskId: task_id,\n status,\n });\n return textResult(`Child task ${task_id} status updated to ${status}.`);\n }\n await connection.call(\"updateTaskStatus\", {\n sessionId: connection.sessionId,\n status,\n force: true,\n });\n return textResult(`Task status updated to ${status}.`);\n } catch (error) {\n return textResult(\n `Failed to update status: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n },\n );\n}\n\n// oxlint-disable-next-line max-lines-per-function -- PR creation involves git staging, committing, pushing, and API call\nexport function buildCreatePullRequestTool(connection: AgentConnection, config: AgentRunnerConfig) {\n return defineTool(\n \"create_pull_request\",\n \"Create a GitHub PR for this task. Auto-stages, commits (commitMessage or title default), pushes to origin, then opens the PR. Always use this instead of gh CLI or raw git.\",\n {\n title: z.string().describe(\"The PR title\"),\n body: z.string().describe(\"The PR description/body in markdown\"),\n branch: z\n .string()\n .optional()\n .describe(\n \"The head branch name for the PR. If the task doesn't have a branch set, this will be used. Defaults to the task's existing branch.\",\n ),\n baseBranch: z\n .string()\n .optional()\n .describe(\n \"The base branch to target for the PR (e.g. 'main', 'develop'). Defaults to the project's configured dev branch.\",\n ),\n commitMessage: z\n .string()\n .optional()\n .describe(\n \"Commit message for staging uncommitted changes. If not provided, a default message based on the PR title will be used.\",\n ),\n skipVerify: z\n .boolean()\n .optional()\n .describe(\n \"Pass --no-verify to the git push, bypassing the local pre-push quality gate (lint/typecheck/test). Use this if a previous attempt failed on the pre-push hook in an environment where you've already run the gates yourself — CI still runs on the resulting PR.\",\n ),\n },\n async ({ title, body, branch, baseBranch, commitMessage, skipVerify }) => {\n try {\n const cwd = config.workspaceDir;\n\n if (hasUncommittedChanges(cwd)) {\n const message =\n commitMessage || `${title}\\n\\nCo-Authored-By: Claude Sonnet 4 <noreply@anthropic.com>`;\n const commitHash = stageAndCommit(cwd, message);\n if (commitHash) {\n connection.sendEvent({\n type: \"message\",\n content: `Auto-committed changes: ${commitHash.slice(0, 7)}`,\n });\n } else {\n return textResult(\n \"Failed to stage and commit changes. Please check git status and commit manually before creating PR.\",\n );\n }\n }\n\n if (hasUnpushedCommits(cwd)) {\n const pushSuccess = await pushToOrigin(\n cwd,\n async () => {\n try {\n const result = await connection.call(\"refreshGithubToken\", {\n sessionId: connection.sessionId,\n });\n return result.token;\n } catch {\n return undefined;\n }\n },\n skipVerify ?? false,\n );\n if (pushSuccess) {\n connection.sendEvent({\n type: \"message\",\n content: \"Auto-pushed committed changes to origin\",\n });\n } else {\n return textResult(\n \"Failed to push changes to origin. Please check git status and push manually before creating PR.\",\n );\n }\n }\n\n const result = await connection.call(\"createPullRequest\", {\n sessionId: connection.sessionId,\n title,\n body,\n head: branch,\n base: baseBranch,\n });\n connection.sendEvent({\n type: \"pr_created\",\n url: result.prUrl,\n number: result.prNumber,\n });\n return textResult(`Pull request #${result.prNumber} created: ${result.prUrl}`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : \"Unknown error\";\n return textResult(\n `Failed to create pull request: ${msg}\\n\\nTroubleshooting:\\n- Ensure all changes are committed and pushed to the remote branch\\n- Check that the branch exists on the remote (run: git push -u origin HEAD)\\n- Verify there isn't already an open PR for this branch\\n- If git auth fails, the token may have expired — retry the operation`,\n );\n }\n },\n );\n}\n\nexport function buildAddDependencyTool(connection: AgentConnection) {\n return defineTool(\n \"add_dependency\",\n \"Add a blocking dependency — this task cannot start until the named task is merged to dev. For post-task follow-ups use create_follow_up_task instead.\",\n {\n depends_on_slug_or_id: z.string().describe(\"Slug or ID of the task this task depends on\"),\n },\n async ({ depends_on_slug_or_id }) => {\n try {\n await connection.call(\"addDependency\", {\n sessionId: connection.sessionId,\n dependsOnSlugOrId: depends_on_slug_or_id,\n });\n return textResult(`Dependency added: this task now depends on \"${depends_on_slug_or_id}\"`);\n } catch (error) {\n return textResult(\n `Failed to add dependency: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n },\n );\n}\n\nexport function buildRemoveDependencyTool(connection: AgentConnection) {\n return defineTool(\n \"remove_dependency\",\n \"Remove a previously added dependency from this task. When to use: the dependency was added in error or is no longer relevant. Returns: confirmation string.\",\n {\n depends_on_slug_or_id: z.string().describe(\"Slug or ID of the task to remove as dependency\"),\n },\n async ({ depends_on_slug_or_id }) => {\n try {\n await connection.call(\"removeDependency\", {\n sessionId: connection.sessionId,\n dependsOnSlugOrId: depends_on_slug_or_id,\n });\n return textResult(\"Dependency removed\");\n } catch (error) {\n return textResult(\n `Failed to remove dependency: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n },\n );\n}\n\nexport function buildCreateFollowUpTaskTool(connection: AgentConnection) {\n return defineTool(\n \"create_follow_up_task\",\n \"Create a follow-up task that depends on the current task. Use for out-of-scope work or cleanup that should land after this task merges. For blockers use add_dependency.\",\n {\n title: z.string().describe(\"Follow-up task title\"),\n description: z.string().optional().describe(\"Brief description of the follow-up work\"),\n plan: z.string().optional().describe(\"Implementation plan if known\"),\n story_point_value: z\n .number()\n .optional()\n .describe(\"Story point estimate (1=Common, 2=Magic, 3=Rare, 5=Unique)\"),\n },\n async ({ title, description, plan, story_point_value }) => {\n try {\n const result = await connection.call(\"createFollowUpTask\", {\n sessionId: connection.sessionId,\n title,\n description,\n plan,\n storyPointValue: story_point_value,\n });\n return textResult(\n `Follow-up task created: \"${title}\" (slug: ${result.slug}). It depends on the current task and will be unblocked when this task is merged.`,\n );\n } catch (error) {\n return textResult(\n `Failed to create follow-up task: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n },\n );\n}\n\nexport function buildCreateSuggestionTool(connection: AgentConnection) {\n return defineTool(\n \"create_suggestion\",\n \"Suggest a feature, improvement, rule, or idea for the project. Duplicates are deduped and your upvote is recorded. For actionable work on this task open a follow-up task.\",\n {\n title: z.string().describe(\"Short title for the suggestion\"),\n description: z\n .string()\n .optional()\n .describe(\n \"1-2 sentence description of what should change and why. Keep concise and project-focused.\",\n ),\n tag_names: z.array(z.string()).optional().describe(\"Tag names to categorize the suggestion\"),\n },\n async ({ title, description, tag_names }) => {\n try {\n const result = await connection.call(\"createSuggestion\", {\n sessionId: connection.sessionId,\n title,\n description,\n tagNames: tag_names,\n });\n if (result.merged) {\n return textResult(\n `Your suggestion was merged into an existing one (ID: ${result.mergedIntoId ?? result.id}). Your upvote has been recorded.`,\n );\n }\n return textResult(`Suggestion created (ID: ${result.id}).`);\n } catch (error) {\n return textResult(\n `Failed to create suggestion: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n },\n );\n}\n\nexport function buildVoteSuggestionTool(connection: AgentConnection) {\n return defineTool(\n \"vote_suggestion\",\n \"Vote +1 or -1 on a project suggestion. Use to express support or disagreement with a specific suggestion returned by get_suggestions.\",\n {\n suggestion_id: z.string().describe(\"The suggestion ID to vote on\"),\n value: z\n .number()\n .refine((v) => v === 1 || v === -1, { message: \"Value must be 1 or -1\" })\n .describe(\"+1 to upvote, -1 to downvote\"),\n },\n async ({ suggestion_id, value }) => {\n try {\n const result = await connection.call(\"voteSuggestion\", {\n sessionId: connection.sessionId,\n suggestionId: suggestion_id,\n value: value as 1 | -1,\n });\n return textResult(`Vote recorded. Current score: ${result.score}`);\n } catch (error) {\n return textResult(\n `Failed to vote: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n },\n );\n}\n\n/** All write/mutation tools (excluding PR creation which needs config). */\nexport function buildMutationTools(connection: AgentConnection, config: AgentRunnerConfig) {\n return [\n buildPostToChatTool(connection),\n buildCreatePullRequestTool(connection, config),\n buildAddDependencyTool(connection),\n buildRemoveDependencyTool(connection),\n buildCreateFollowUpTaskTool(connection),\n buildCreateSuggestionTool(connection),\n buildVoteSuggestionTool(connection),\n ];\n}\n","import { readFile, stat } from \"node:fs/promises\";\nimport { basename, extname, isAbsolute, join } from \"node:path\";\nimport { z } from \"zod\";\nimport { MAX_FILE_SIZE_BYTES } from \"@project/shared\";\nimport { defineTool } from \"../harness/index.js\";\nimport type { AgentConnection } from \"../connection/agent-connection.js\";\nimport type { AgentRunnerConfig } from \"../types.js\";\nimport { textResult } from \"./helpers.js\";\n\nconst IMAGE_MIME_BY_EXT: Record<string, string> = {\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".webp\": \"image/webp\",\n};\n\nexport function buildUploadAttachmentTool(connection: AgentConnection, config: AgentRunnerConfig) {\n return defineTool(\n \"upload_attachment\",\n \"Upload an image file (e.g. a Playwright screenshot) as a task attachment AND post it to the task chat in one step — no follow-up post_to_chat call needed. Supports png/jpg/gif/webp.\",\n {\n path: z\n .string()\n .describe(\"Path to the image file — absolute, or relative to the workspace root\"),\n title: z\n .string()\n .optional()\n .describe(\"Short caption posted with the image (defaults to the file name)\"),\n },\n async ({ path, title }) => {\n try {\n const filePath = isAbsolute(path) ? path : join(config.workspaceDir, path);\n const mimeType = IMAGE_MIME_BY_EXT[extname(filePath).toLowerCase()];\n if (!mimeType) {\n return textResult(\n `Unsupported file type \"${extname(filePath) || \"(none)\"}\". Supported: ${Object.keys(IMAGE_MIME_BY_EXT).join(\", \")}`,\n );\n }\n\n const info = await stat(filePath).catch(() => null);\n if (!info?.isFile()) {\n return textResult(`File not found: ${filePath}`);\n }\n if (info.size > MAX_FILE_SIZE_BYTES) {\n return textResult(\n `File is ${info.size} bytes — exceeds the ${MAX_FILE_SIZE_BYTES} byte upload limit. Resize or crop the image first.`,\n );\n }\n\n const fileName = basename(filePath);\n const { fileId, uploadUrl } = await connection.call(\"requestFileUpload\", {\n sessionId: connection.sessionId,\n fileName,\n mimeType,\n fileSize: info.size,\n });\n\n const body = await readFile(filePath);\n const res = await fetch(uploadUrl, {\n method: \"PUT\",\n headers: { \"Content-Type\": mimeType },\n body,\n });\n if (!res.ok) {\n return textResult(\n `Upload to storage failed: HTTP ${res.status} ${await res.text().catch(() => \"\")}`,\n );\n }\n\n const result = await connection.call(\"confirmFileUpload\", {\n sessionId: connection.sessionId,\n fileId,\n title,\n });\n\n return textResult(\n `Uploaded ${fileName} (${info.size} bytes) and posted it to the task chat${title ? ` with caption \"${title}\"` : \"\"}. File ID: ${result.fileId}`,\n );\n } catch (error) {\n return textResult(\n `Failed to upload attachment: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n },\n );\n}\n","import { z } from \"zod\";\nimport type { TaskManualTestsGroupDTO } from \"@project/shared\";\nimport { defineTool } from \"../harness/index.js\";\nimport type { AgentConnection } from \"../connection/agent-connection.js\";\nimport { textResult } from \"./helpers.js\";\n\nexport function buildListManualTestsTool(connection: AgentConnection) {\n return defineTool(\n \"list_manual_tests\",\n \"List the manual test checklist items for the current task. Use to see what manual verification steps have already been recorded.\",\n {},\n async () => {\n try {\n const items = await connection.call(\"listManualTests\", {\n sessionId: connection.sessionId,\n });\n if (items.length === 0) return textResult(\"No manual tests recorded for this task.\");\n const lines = items.flatMap((item, i) => {\n const checked = item.checked ? \"[x]\" : \"[ ]\";\n const row = [`${i + 1}. ${checked} ${item.title}`];\n for (const f of item.failures ?? []) {\n const who = f.userName ?? \"Someone\";\n const reason = f.reason ?? \"(no message)\";\n row.push(` ⚠ Failed (${who}): ${reason}`);\n }\n return row;\n });\n return textResult(lines.join(\"\\n\"));\n } catch {\n return textResult(\"Failed to list manual tests.\");\n }\n },\n { annotations: { readOnlyHint: true } },\n );\n}\n\n/** Compact grouped rendering for cross-task manual-test queries: one header per\n * task, one line per test with a status glyph, and the failing reason indented\n * under each rejected test. */\nfunction renderManualTestGroups(groups: TaskManualTestsGroupDTO[]): string {\n const lines: string[] = [];\n for (const g of groups) {\n lines.push(`## ${g.title} [${g.status}] (${g.slug})`);\n for (const t of g.tests) {\n const mark = t.status === \"approved\" ? \"✓\" : t.status === \"rejected\" ? \"✗\" : \"○\";\n lines.push(` ${mark} ${t.title} — ${t.status}`);\n if (t.status === \"rejected\") {\n for (const f of t.failures ?? []) {\n lines.push(` ⚠ ${f.userName ?? \"Someone\"}: ${f.reason ?? \"(no message)\"}`);\n }\n }\n }\n lines.push(\"\");\n }\n return lines.join(\"\\n\").trimEnd();\n}\n\nexport function buildQueryManualTestsTool(connection: AgentConnection) {\n return defineTool(\n \"query_manual_tests\",\n \"Query manual tests across many tasks in this project, grouped by task. Filter by card status (ReviewDev, ReviewLive, Complete, ...) and/or test status (open | approved | rejected). Use to answer 'show all OPEN manual tests in ReviewDev' or 'show all REJECTED manual tests with the failing reason'. With no filters it defaults to the needs-attention view: open+rejected tests on ReviewDev/ReviewLive cards.\",\n {\n cardStatuses: z\n .array(z.string())\n .optional()\n .describe('Filter tasks by card status, e.g. [\"ReviewDev\", \"ReviewLive\"]'),\n testStatuses: z\n .array(z.enum([\"open\", \"approved\", \"rejected\"]))\n .optional()\n .describe(\"Filter tests by status: open | approved | rejected\"),\n },\n async ({ cardStatuses, testStatuses }) => {\n try {\n const groups = await connection.call(\"queryManualTests\", {\n sessionId: connection.sessionId,\n cardStatuses,\n testStatuses,\n });\n if (groups.length === 0) return textResult(\"No manual tests match those filters.\");\n return textResult(renderManualTestGroups(groups));\n } catch (error) {\n const msg = error instanceof Error ? error.message : \"Unknown error\";\n return textResult(`Failed to query manual tests: ${msg}`);\n }\n },\n { annotations: { readOnlyHint: true } },\n );\n}\n\nexport function buildSetManualTestsTool(connection: AgentConnection) {\n return defineTool(\n \"set_manual_tests\",\n \"Add manual test steps to the task checklist. Existing items with the same title are automatically skipped (deduplication). Use to record specific manual verification steps that reviewers should follow when testing this PR.\",\n {\n items: z\n .array(z.object({ title: z.string().min(1).describe(\"A concise, actionable test step\") }))\n .min(1)\n .describe(\"List of manual test steps to add\"),\n },\n async ({ items }) => {\n try {\n const result = await connection.call(\"setManualTests\", {\n sessionId: connection.sessionId,\n items,\n });\n const parts = [`Created ${result.created} manual test item(s).`];\n if (result.skipped > 0) parts.push(`Skipped ${result.skipped} duplicate(s).`);\n return textResult(parts.join(\" \"));\n } catch (error) {\n const msg = error instanceof Error ? error.message : \"Unknown error\";\n return textResult(`Failed to set manual tests: ${msg}`);\n }\n },\n );\n}\n\nexport function buildEditManualTestTool(connection: AgentConnection) {\n return defineTool(\n \"edit_manual_test\",\n \"Rename an existing manual test step. Identify the test by its current title (case-insensitive); pass the new title to replace it. Use to correct or refine a recorded manual verification step.\",\n {\n title: z.string().min(1).describe(\"The current title of the manual test to edit\"),\n newTitle: z.string().min(1).describe(\"The new title for the manual test\"),\n },\n async ({ title, newTitle }) => {\n try {\n await connection.call(\"editManualTest\", {\n sessionId: connection.sessionId,\n title,\n newTitle,\n });\n return textResult(`Updated manual test to \"${newTitle}\".`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : \"Unknown error\";\n return textResult(`Failed to edit manual test: ${msg}`);\n }\n },\n );\n}\n\nexport function buildRemoveManualTestTool(connection: AgentConnection) {\n return defineTool(\n \"remove_manual_test\",\n \"Remove an existing manual test step from the task checklist. Identify the test by its title (case-insensitive). Use to delete a stale or incorrect manual verification step.\",\n {\n title: z.string().min(1).describe(\"The title of the manual test to remove\"),\n },\n async ({ title }) => {\n try {\n await connection.call(\"removeManualTest\", {\n sessionId: connection.sessionId,\n title,\n });\n return textResult(`Removed manual test \"${title}\".`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : \"Unknown error\";\n return textResult(`Failed to remove manual test: ${msg}`);\n }\n },\n );\n}\n\nexport function buildApproveManualTestTool(connection: AgentConnection) {\n return defineTool(\n \"approve_manual_test\",\n \"Sign off on (approve) a manual test step on behalf of your authenticated user. Identify the test by its title (case-insensitive). Use after you have verified the step passes.\",\n {\n title: z.string().min(1).describe(\"The title of the manual test to approve\"),\n },\n async ({ title }) => {\n try {\n await connection.call(\"approveManualTest\", {\n sessionId: connection.sessionId,\n title,\n });\n return textResult(`Approved manual test \"${title}\".`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : \"Unknown error\";\n return textResult(`Failed to approve manual test: ${msg}`);\n }\n },\n );\n}\n\nexport function buildRejectManualTestTool(connection: AgentConnection) {\n return defineTool(\n \"reject_manual_test\",\n \"Flag an issue with (reject) a manual test step on behalf of your authenticated user, recording the reason. Identify the test by its title (case-insensitive). Use when the step fails verification.\",\n {\n title: z.string().min(1).describe(\"The title of the manual test to reject\"),\n reason: z\n .string()\n .min(1)\n .max(2000)\n .describe(\"Why the test failed — what went wrong, shown to the team\"),\n },\n async ({ title, reason }) => {\n try {\n await connection.call(\"rejectManualTest\", {\n sessionId: connection.sessionId,\n title,\n reason,\n });\n return textResult(`Flagged an issue with manual test \"${title}\": ${reason}`);\n } catch (error) {\n const msg = error instanceof Error ? error.message : \"Unknown error\";\n return textResult(`Failed to reject manual test: ${msg}`);\n }\n },\n );\n}\n","import type { AgentConnection } from \"../connection/agent-connection.js\";\nimport type { AgentRunnerConfig } from \"../types.js\";\nimport { buildTaskContextTools } from \"./task-context-tools.js\";\nimport {\n buildGetDependenciesTool,\n buildGetSuggestionsTool,\n} from \"./dependency-suggestion-tools.js\";\nimport { buildMutationTools } from \"./mutation-tools.js\";\nimport { buildUploadAttachmentTool } from \"./attachment-tools.js\";\nimport {\n buildApproveManualTestTool,\n buildEditManualTestTool,\n buildListManualTestsTool,\n buildQueryManualTestsTool,\n buildRejectManualTestTool,\n buildRemoveManualTestTool,\n buildSetManualTestsTool,\n} from \"./checklist-tools.js\";\n\n// Re-export individual builders for selective use\nexport {\n buildReadTaskChatTool,\n buildGetCurrentPlanTool,\n buildGetTaskTool,\n buildGetExecutionLogsTool,\n buildListTaskFilesTool,\n buildGetAttachmentTool,\n} from \"./task-context-tools.js\";\n\nexport { buildForceUpdateTaskStatusTool } from \"./mutation-tools.js\";\nexport { buildUploadAttachmentTool } from \"./attachment-tools.js\";\n\n// ── Aggregator ───────────────────────────────────────────────────────\n\nexport function buildCommonTools(connection: AgentConnection, config: AgentRunnerConfig) {\n return [\n ...buildTaskContextTools(connection),\n buildGetDependenciesTool(connection),\n buildGetSuggestionsTool(connection),\n buildListManualTestsTool(connection),\n buildQueryManualTestsTool(connection),\n buildSetManualTestsTool(connection),\n buildEditManualTestTool(connection),\n buildRemoveManualTestTool(connection),\n buildApproveManualTestTool(connection),\n buildRejectManualTestTool(connection),\n ...buildMutationTools(connection, config),\n buildUploadAttachmentTool(connection, config),\n ];\n}\n","import { z } from \"zod\";\nimport { defineTool } from \"../harness/index.js\";\nimport type { AgentConnection } from \"../connection/agent-connection.js\";\nimport { textResult } from \"./helpers.js\";\n\nconst SP_DESCRIPTION = \"Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique)\";\n\nexport function buildUpdateTaskTool(connection: AgentConnection) {\n return defineTool(\n \"update_task_plan\",\n \"Save the finalized plan and/or description to the current task. Use in Plan mode after alignment. For children use update_subtask; for title/tags/PR use update_task_properties.\",\n {\n plan: z.string().optional().describe(\"The task plan in markdown\"),\n description: z.string().optional().describe(\"Updated task description\"),\n },\n async ({ plan, description }) => {\n try {\n await connection.call(\"updateTaskFields\", {\n sessionId: connection.sessionId,\n plan,\n description,\n });\n return textResult(\"Task updated successfully.\");\n } catch {\n return textResult(\"Failed to update task.\");\n }\n },\n );\n}\n\nfunction buildCreateSubtaskTool(connection: AgentConnection) {\n return defineTool(\n \"create_subtask\",\n \"Create a subtask under the current parent task. Use when breaking a complex parent into smaller pieces during planning. For post-task follow-ups use create_follow_up_task.\",\n {\n title: z.string().describe(\"Subtask title\"),\n description: z.string().optional().describe(\"Brief description\"),\n plan: z.string().optional().describe(\"Implementation plan in markdown\"),\n ordinal: z.number().optional().describe(\"Step/order number (0-based)\"),\n storyPointValue: z.number().optional().describe(SP_DESCRIPTION),\n },\n async ({ title, description, plan, ordinal, storyPointValue }) => {\n try {\n const result = await connection.call(\"createSubtask\", {\n sessionId: connection.sessionId,\n title,\n ...(description !== undefined && { description }),\n ...(plan !== undefined && { plan }),\n ...(storyPointValue !== undefined && { storyPointValue }),\n ...(ordinal !== undefined && { ordinal }),\n });\n return textResult(`Subtask created with ID: ${result.id}`);\n } catch (error) {\n return textResult(\n `Failed to create subtask: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n },\n );\n}\n\nfunction buildUpdateSubtaskTool(connection: AgentConnection) {\n return defineTool(\n \"update_subtask\",\n \"Update an existing subtask's fields (title, description, plan, ordinal, storyPointValue). Use when refining a child's plan or reordering. For the current task use update_task_plan.\",\n {\n subtaskId: z.string().describe(\"The subtask ID to update\"),\n title: z.string().optional(),\n description: z.string().optional(),\n plan: z.string().optional(),\n ordinal: z.number().optional(),\n storyPointValue: z.number().optional().describe(SP_DESCRIPTION),\n },\n async ({ subtaskId, title, description, plan, storyPointValue }) => {\n try {\n await connection.call(\"updateSubtask\", {\n sessionId: connection.sessionId,\n subtaskId,\n ...(title !== undefined && { title }),\n ...(description !== undefined && { description }),\n ...(plan !== undefined && { plan }),\n ...(storyPointValue !== undefined && { storyPointValue }),\n });\n return textResult(\"Subtask updated.\");\n } catch (error) {\n return textResult(`Failed: ${error instanceof Error ? error.message : \"Unknown error\"}`);\n }\n },\n );\n}\n\nfunction buildDeleteSubtaskTool(connection: AgentConnection) {\n return defineTool(\n \"delete_subtask\",\n \"Delete a subtask by id. When to use: a subtask was created in error or is no longer needed. Returns: confirmation string.\",\n { subtaskId: z.string().describe(\"The subtask ID to delete\") },\n async ({ subtaskId }) => {\n try {\n await connection.call(\"deleteSubtask\", {\n sessionId: connection.sessionId,\n subtaskId,\n });\n return textResult(\"Subtask deleted.\");\n } catch (error) {\n return textResult(`Failed: ${error instanceof Error ? error.message : \"Unknown error\"}`);\n }\n },\n );\n}\n\nfunction buildListSubtasksTool(connection: AgentConnection) {\n return defineTool(\n \"list_subtasks\",\n \"List all subtasks under the current parent task. Use to coordinate child work — check who is running, ready for review, or blocked. For non-child tasks use get_task.\",\n {},\n async () => {\n try {\n const subtasks = await connection.call(\"listSubtasks\", {\n sessionId: connection.sessionId,\n });\n return textResult(JSON.stringify(subtasks, null, 2));\n } catch {\n return textResult(\"Failed to list subtasks.\");\n }\n },\n { annotations: { readOnlyHint: true } },\n );\n}\n\nfunction buildPackTools(connection: AgentConnection) {\n return [\n defineTool(\n \"start_child_cloud_build\",\n \"Start a cloud build (codespace) for a child task. Preconditions: child is in Open status, has a story point value, and has an agent assigned.\",\n {\n childTaskId: z.string().describe(\"The child task ID to start a cloud build for\"),\n },\n async ({ childTaskId }) => {\n try {\n const result = await connection.call(\"startChildCloudBuild\", {\n sessionId: connection.sessionId,\n childTaskId,\n });\n return textResult(`Cloud build started for child task: ${result.childTaskId}`);\n } catch (error) {\n return textResult(\n `Failed to start child cloud build: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n },\n ),\n defineTool(\n \"stop_child_build\",\n \"Send a graceful stop signal to a running child build's agent. Not a force-kill — the agent may take a moment to wind down.\",\n {\n childTaskId: z.string().describe(\"The child task ID whose build should be stopped\"),\n },\n async ({ childTaskId }) => {\n try {\n await connection.call(\"stopChildBuild\", {\n sessionId: connection.sessionId,\n childTaskId,\n });\n return textResult(`Stop signal sent to child task: ${childTaskId}`);\n } catch (error) {\n return textResult(\n `Failed to stop child build: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n },\n ),\n defineTool(\n \"approve_and_merge_pr\",\n \"Approve and merge a child task's PR. Preconditions: child in ReviewPR. Returns { merged }: true = merged (status→ReviewDev); false = automerge queued, wait for ReviewDev.\",\n {\n childTaskId: z\n .string()\n .describe(\"The child task ID whose PR should be approved and merged\"),\n },\n async ({ childTaskId }) => {\n try {\n const result = await connection.call(\"approveAndMergePR\", {\n sessionId: connection.sessionId,\n childTaskId,\n });\n if (result.merged) {\n return textResult(\n `PR #${result.prNumber} approved and merged for task ${result.childTaskId}. Task status updated to ReviewDev.`,\n );\n }\n return textResult(\n `PR #${result.prNumber} merge queued for task ${result.childTaskId} — CI checks still in progress. The PR will auto-merge when all checks pass. Do NOT proceed as if merged. Wait for the child task status to change to ReviewDev before continuing.`,\n );\n } catch (error) {\n return textResult(\n `Failed to approve and merge PR: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n },\n ),\n ];\n}\n\nexport function buildPmTools(\n connection: AgentConnection,\n options?: { includePackTools?: boolean },\n) {\n const tools = [\n buildUpdateTaskTool(connection),\n buildCreateSubtaskTool(connection),\n buildUpdateSubtaskTool(connection),\n buildDeleteSubtaskTool(connection),\n buildListSubtasksTool(connection),\n ];\n if (!options?.includePackTools) return tools;\n return [...tools, ...buildPackTools(connection)];\n}\n","import { z } from \"zod\";\nimport { defineTool } from \"../harness/index.js\";\nimport type { AgentConnection } from \"../connection/agent-connection.js\";\nimport { textResult } from \"./helpers.js\";\n\nconst SP_DESCRIPTION = \"Story point value (1=Common, 2=Magic, 3=Rare, 5=Unique)\";\n\nexport function buildDiscoveryTools(connection: AgentConnection) {\n return [\n defineTool(\n \"update_task_properties\",\n \"Set one or more task properties in a single call. All fields are optional — only include the fields you want to update.\",\n {\n title: z.string().optional().describe(\"The new task title\"),\n storyPointValue: z.number().optional().describe(SP_DESCRIPTION),\n tagNames: z.array(z.string()).optional().describe(\"Array of tag names to assign\"),\n githubPRUrl: z\n .string()\n .url()\n .optional()\n .describe(\"GitHub pull request URL to link to this task\"),\n githubBranch: z\n .string()\n .optional()\n .describe(\"Set the GitHub branch name for this task (e.g. 'conveyor/my-feature-abc123')\"),\n },\n async ({ title, storyPointValue, tagNames, githubPRUrl, githubBranch }) => {\n try {\n await connection.call(\"updateTaskProperties\", {\n sessionId: connection.sessionId,\n title,\n storyPointValue,\n tagNames,\n githubPRUrl,\n githubBranch,\n });\n\n const updatedFields = [];\n if (title !== undefined) updatedFields.push(`title to \"${title}\"`);\n if (storyPointValue !== undefined)\n updatedFields.push(`story points to ${storyPointValue}`);\n if (tagNames !== undefined) updatedFields.push(`tags (${tagNames.length} tag(s))`);\n if (githubPRUrl !== undefined) updatedFields.push(`PR link to \"${githubPRUrl}\"`);\n if (githubBranch !== undefined) updatedFields.push(`branch to \"${githubBranch}\"`);\n\n return textResult(`Task properties updated: ${updatedFields.join(\", \")}`);\n } catch (error) {\n return textResult(\n `Failed to update task properties: ${error instanceof Error ? error.message : \"Unknown error\"}`,\n );\n }\n },\n ),\n ];\n}\n","import { z } from \"zod\";\nimport { defineTool } from \"../harness/index.js\";\nimport type { AgentConnection } from \"../connection/agent-connection.js\";\nimport { textResult } from \"./helpers.js\";\n\nexport function buildCodeReviewTools(connection: AgentConnection) {\n return [\n defineTool(\n \"approve_code_review\",\n \"Approve the code review and exit. Use when the diff passes all review criteria. Takes only a summary — for changes, use request_code_changes with a structured issues[] list.\",\n {\n summary: z.string().describe(\"Brief summary of what was reviewed and why it looks good\"),\n },\n async ({ summary }) => {\n const content = `**Code Review: Approved** :white_check_mark:\\n\\n${summary}`;\n await connection.call(\"submitCodeReviewResult\", {\n sessionId: connection.sessionId,\n approved: true,\n content,\n });\n connection.sendEvent({\n type: \"code_review_complete\",\n result: \"approved\",\n summary,\n });\n return textResult(\"Code review approved. Exiting.\");\n },\n ),\n defineTool(\n \"request_code_changes\",\n \"Request changes during code review and exit. Use when substantive issues must be fixed before merge. Each issue: { file, line?, severity: critical|major|minor, description }.\",\n {\n issues: z\n .array(\n z.object({\n file: z.string().describe(\"File path where the issue was found\"),\n line: z.number().optional().describe(\"Line number (if applicable)\"),\n severity: z.enum([\"critical\", \"major\", \"minor\"]).describe(\"Issue severity\"),\n description: z.string().describe(\"What is wrong and how to fix it\"),\n }),\n )\n .describe(\"List of issues found during review\"),\n summary: z.string().describe(\"Brief overall summary of the review findings\"),\n },\n async ({ issues, summary }) => {\n const issueLines = issues\n .map((issue) => {\n const loc = issue.line ? `:${issue.line}` : \"\";\n return `- **[${issue.severity}]** \\`${issue.file}${loc}\\`: ${issue.description}`;\n })\n .join(\"\\n\");\n\n const content = `**Code Review: Changes Requested** :warning:\\n\\n${summary}\\n\\n${issueLines}`;\n await connection.call(\"submitCodeReviewResult\", {\n sessionId: connection.sessionId,\n approved: false,\n content,\n });\n connection.sendEvent({\n type: \"code_review_complete\",\n result: \"changes_requested\",\n summary,\n issues,\n });\n return textResult(\"Code review complete — changes requested. Exiting.\");\n },\n ),\n ];\n}\n","import type { AgentHarness, HarnessToolDefinition } from \"../harness/index.js\";\nimport type { AgentConnection } from \"../connection/agent-connection.js\";\nimport type { AgentRunnerConfig } from \"../types.js\";\nimport type { AgentMode, TaskContext } from \"@project/shared\";\nimport { buildCommonTools, buildForceUpdateTaskStatusTool } from \"./common-tools.js\";\nimport { buildPmTools, buildUpdateTaskTool } from \"./pm-tools.js\";\nimport { buildDiscoveryTools } from \"./discovery-tools.js\";\nimport { buildCodeReviewTools } from \"./code-review-tools.js\";\n\n// Re-export helpers\nexport { textResult, imageBlock } from \"./helpers.js\";\n\n// ── Mode-based tool selection ─────────────────────────────────────────\n\nfunction getTaskModeTools(agentMode: AgentMode | undefined, connection: AgentConnection) {\n if (agentMode === \"discovery\" || agentMode === \"auto\") {\n return [buildUpdateTaskTool(connection)];\n }\n return [];\n}\n\nfunction getModeTools(\n agentMode: AgentMode | undefined,\n connection: AgentConnection,\n config: AgentRunnerConfig,\n context?: TaskContext,\n) {\n if (config.mode === \"task\") return getTaskModeTools(agentMode, connection);\n\n switch (agentMode) {\n case \"building\":\n return context?.isParentTask ? buildPmTools(connection, { includePackTools: true }) : [];\n case \"review\":\n case \"auto\":\n case \"discovery\":\n case \"help\":\n return buildPmTools(connection, {\n includePackTools: !!context?.isParentTask,\n });\n default:\n return config.mode === \"pm\" ? buildPmTools(connection, { includePackTools: false }) : [];\n }\n}\n\n// ── Tool assembly ─────────────────────────────────────────────────────\n\n/** Collect all tools for the current mode as harness-neutral definitions. */\nexport function buildConveyorTools(\n connection: AgentConnection,\n config: AgentRunnerConfig,\n context?: TaskContext,\n agentMode?: AgentMode,\n): HarnessToolDefinition[] {\n const effectiveMode = agentMode ?? context?.agentMode ?? undefined;\n\n const commonTools = buildCommonTools(connection, config);\n const modeTools = getModeTools(effectiveMode, connection, config, context);\n\n const discoveryTools =\n effectiveMode === \"discovery\" || effectiveMode === \"auto\"\n ? buildDiscoveryTools(connection)\n : [];\n\n // Code review tools available in review mode\n const codeReviewTools = effectiveMode === \"review\" ? buildCodeReviewTools(connection) : [];\n\n const emergencyTools = [buildForceUpdateTaskStatusTool(connection)];\n\n return [...commonTools, ...modeTools, ...discoveryTools, ...codeReviewTools, ...emergencyTools];\n}\n\n// ── MCP server factory ────────────────────────────────────────────────\n\n// oxlint-disable-next-line typescript/explicit-function-return-type\nexport function createConveyorMcpServer(\n harness: AgentHarness,\n connection: AgentConnection,\n config: AgentRunnerConfig,\n context?: TaskContext,\n agentMode?: AgentMode,\n) {\n return harness.createMcpServer({\n name: \"conveyor\",\n tools: buildConveyorTools(connection, config, context, agentMode),\n });\n}\n","import type {\n HarnessAssistantEvent,\n HarnessResultEvent,\n HarnessResultSuccessEvent,\n HarnessResultErrorEvent,\n HarnessSystemInitEvent,\n HarnessCompactBoundaryEvent,\n HarnessTaskStartedEvent,\n HarnessTaskProgressEvent,\n HarnessRateLimitEvent,\n} from \"../harness/index.js\";\nimport type { TaskContext, ActivityEventSummary } from \"@project/shared\";\nimport type { QueryHost } from \"./query-executor.js\";\nimport { createServiceLogger } from \"../utils/logger.js\";\n\nconst logger = createServiceLogger(\"event-handlers\");\n\nfunction safeVoid(promise: void | Promise<unknown>, context: string): void {\n if (promise && typeof (promise as Promise<unknown>).catch === \"function\") {\n (promise as Promise<unknown>).catch((err) => {\n process.stderr.write(`[safeVoid] ${context}: ${err}\\n`);\n });\n }\n}\n\nexport type UsageInfo = {\n input_tokens?: number;\n cache_read_input_tokens?: number;\n cache_creation_input_tokens?: number;\n};\n\n/** Convert a resetsAt value (epoch seconds, epoch ms, or ISO string) to an ISO string. */\nfunction epochSecondsToISO(value: unknown): string | undefined {\n if (typeof value === \"string\") return value;\n if (typeof value !== \"number\" || value <= 0) return undefined;\n // Heuristic: epoch seconds for dates after 2000 are < 1e12; milliseconds are >= 1e12\n const ms = value < 1e12 ? value * 1000 : value;\n return new Date(ms).toISOString();\n}\n\nexport async function processAssistantEvent(\n event: HarnessAssistantEvent,\n host: QueryHost,\n turnToolCalls: ActivityEventSummary[],\n): Promise<void> {\n const { content } = event.message;\n const turnTextParts: string[] = [];\n\n for (const block of content) {\n if (block.type === \"text\" && block.text) {\n turnTextParts.push(block.text);\n host.connection.sendEvent({ type: \"message\", content: block.text });\n await host.callbacks.onEvent({ type: \"message\", content: block.text });\n } else if (block.type === \"tool_use\" && block.name) {\n const inputStr = typeof block.input === \"string\" ? block.input : JSON.stringify(block.input);\n const isContentTool = [\"edit\", \"write\"].includes(block.name.toLowerCase());\n const inputLimit = isContentTool ? 10_000 : 500;\n const summary: ActivityEventSummary = {\n tool: block.name,\n input: inputStr.slice(0, inputLimit),\n timestamp: new Date().toISOString(),\n };\n turnToolCalls.push(summary);\n host.connection.sendEvent({ type: \"tool_use\", tool: block.name, input: inputStr });\n await host.callbacks.onEvent({ type: \"tool_use\", tool: block.name, input: inputStr });\n }\n }\n}\n\nexport const API_ERROR_PATTERN = /API Error: (?:[45]\\d\\d|terminated)/;\nconst IMAGE_ERROR_PATTERN = /Could not process image/i;\nconst AUTH_ERROR_PATTERN =\n /Not logged in|Please run \\/login|authentication failed|invalid.*token|unauthorized/i;\n\nexport function isAuthError(msg: string): boolean {\n return AUTH_ERROR_PATTERN.test(msg);\n}\n\nfunction isRetriableMessage(msg: string): boolean {\n if (IMAGE_ERROR_PATTERN.test(msg)) return true;\n if (API_ERROR_PATTERN.test(msg)) return true;\n return false;\n}\n\nfunction aggregateModelUsage(modelUsage: Record<string, unknown>): {\n queryInputTokens: number;\n contextWindow: number;\n totalInputTokens: number;\n totalCacheRead: number;\n totalCacheCreation: number;\n} {\n let queryInputTokens = 0;\n let contextWindow = 0;\n let totalInputTokens = 0;\n let totalCacheRead = 0;\n let totalCacheCreation = 0;\n for (const data of Object.values(modelUsage)) {\n const d = data as {\n inputTokens?: number;\n cacheReadInputTokens?: number;\n cacheCreationInputTokens?: number;\n };\n const input = d.inputTokens ?? 0;\n const cacheRead = d.cacheReadInputTokens ?? 0;\n const cacheCreation = d.cacheCreationInputTokens ?? 0;\n totalInputTokens += input;\n totalCacheRead += cacheRead;\n totalCacheCreation += cacheCreation;\n queryInputTokens += input + cacheRead + cacheCreation;\n const cw = (data as { contextWindow?: number }).contextWindow ?? 0;\n if (cw > contextWindow) contextWindow = cw;\n }\n return { queryInputTokens, contextWindow, totalInputTokens, totalCacheRead, totalCacheCreation };\n}\n\nfunction emitContextUpdate(\n modelUsage: Record<string, unknown>,\n host: QueryHost,\n context: TaskContext,\n lastAssistantUsage?: UsageInfo,\n): void {\n const usage = aggregateModelUsage(modelUsage);\n let { contextWindow } = usage;\n\n // Override contextWindow when 1M beta is enabled but SDK reports ≤200K\n const settings = context.agentSettings ?? host.config.agentSettings ?? {};\n const has1mBeta = (settings.betas as string[] | undefined)?.includes(\"context-1m-2025-08-07\");\n if (has1mBeta && contextWindow > 0 && contextWindow <= 200_000) {\n contextWindow = 1_000_000;\n }\n\n if (contextWindow > 0) {\n // Current context fill = last API call's input tokens (per-call, not cumulative)\n const currentContextTokens = lastAssistantUsage\n ? (lastAssistantUsage.input_tokens ?? 0) +\n (lastAssistantUsage.cache_read_input_tokens ?? 0) +\n (lastAssistantUsage.cache_creation_input_tokens ?? 0)\n : usage.queryInputTokens;\n\n host.connection.sendEvent({\n type: \"context_update\",\n contextTokens: currentContextTokens,\n contextWindow,\n inputTokens: usage.totalInputTokens,\n cacheReadInputTokens: usage.totalCacheRead,\n cacheCreationInputTokens: usage.totalCacheCreation,\n totalTokensUsed: usage.queryInputTokens,\n });\n }\n}\n\nfunction handleSuccessResult(\n event: HarnessResultSuccessEvent,\n host: QueryHost,\n context: TaskContext,\n startTime: number,\n lastAssistantUsage?: UsageInfo,\n): { retriable: boolean } {\n const durationMs = Date.now() - startTime;\n const summary = event.result || \"Task completed.\";\n const retriable = isRetriableMessage(summary);\n\n host.connection.sendEvent({ type: \"completed\", summary, durationMs });\n\n const { modelUsage } = event;\n if (modelUsage && typeof modelUsage === \"object\") {\n emitContextUpdate(modelUsage as Record<string, unknown>, host, context, lastAssistantUsage);\n }\n\n return { retriable };\n}\n\nfunction handleErrorResult(\n event: HarnessResultErrorEvent,\n host: QueryHost,\n): { retriable: boolean; staleSession?: boolean; authError?: boolean } {\n const errorMsg =\n event.errors.length > 0 ? event.errors.join(\", \") : `Agent stopped: ${event.subtype}`;\n\n // Check for stale session error pattern\n const isStaleSession = errorMsg.includes(\"No conversation found with session ID\");\n\n if (isStaleSession) {\n // Suppress the error event for stale session - this will be handled by session recovery\n return { retriable: false, staleSession: true };\n }\n\n // Check for auth error pattern — will be handled by auth recovery\n if (isAuthError(errorMsg)) {\n host.connection.sendEvent({ type: \"error\", message: errorMsg });\n return { retriable: false, authError: true };\n }\n\n const retriable = isRetriableMessage(errorMsg);\n host.connection.sendEvent({ type: \"error\", message: errorMsg });\n return { retriable };\n}\n\nfunction handleResultEvent(\n event: HarnessResultEvent,\n host: QueryHost,\n context: TaskContext,\n startTime: number,\n lastAssistantUsage?: UsageInfo,\n): {\n retriable: boolean;\n resultSummary?: string;\n staleSession?: boolean;\n authError?: boolean;\n} {\n const resultSummary =\n event.subtype === \"success\"\n ? (event as HarnessResultSuccessEvent).result\n : (event as HarnessResultErrorEvent).errors.join(\", \");\n\n if (event.subtype === \"success\") {\n const result = handleSuccessResult(\n event as HarnessResultSuccessEvent,\n host,\n context,\n startTime,\n lastAssistantUsage,\n );\n return { ...result, resultSummary };\n }\n\n const result = handleErrorResult(event as HarnessResultErrorEvent, host);\n return { ...result, resultSummary };\n}\n\nexport async function emitResultEvent(\n event: HarnessResultEvent,\n host: QueryHost,\n context: TaskContext,\n startTime: number,\n lastAssistantUsage?: UsageInfo,\n): Promise<{\n retriable: boolean;\n resultSummary?: string;\n staleSession?: boolean;\n authError?: boolean;\n}> {\n const result = handleResultEvent(event, host, context, startTime, lastAssistantUsage);\n const durationMs = Date.now() - startTime;\n\n if (event.subtype === \"success\") {\n const successEvent = event as HarnessResultSuccessEvent;\n const summary = successEvent.result || \"Task completed.\";\n await host.callbacks.onEvent({\n type: \"completed\",\n summary,\n durationMs,\n });\n } else if (!result.staleSession) {\n // Only emit error event if it's not a stale session (which is handled by recovery logic)\n const errorEvent = event as HarnessResultErrorEvent;\n const errorMsg =\n errorEvent.errors.length > 0\n ? errorEvent.errors.join(\", \")\n : `Agent stopped: ${errorEvent.subtype}`;\n await host.callbacks.onEvent({ type: \"error\", message: errorMsg });\n }\n\n return {\n retriable: result.retriable,\n resultSummary: result.resultSummary,\n staleSession: result.staleSession,\n authError: result.authError,\n };\n}\n\nexport function handleRateLimitEvent(\n event: HarnessRateLimitEvent,\n host: QueryHost,\n): string | undefined {\n const { rate_limit_info } = event;\n logger.info(\"Rate limit event received\", { rate_limit_info });\n const status = rate_limit_info.status;\n\n // Send structured rate limit update for persistence\n // On rejection without explicit utilization, default to 1.0 (fully consumed)\n const utilization = rate_limit_info.utilization ?? (status === \"rejected\" ? 1.0 : undefined);\n if (utilization !== undefined && rate_limit_info.rateLimitType) {\n host.connection.sendEvent({\n type: \"rate_limit_update\",\n rateLimitType: rate_limit_info.rateLimitType,\n utilization,\n status,\n });\n }\n\n if (status === \"rejected\") {\n const resetsAt = epochSecondsToISO(rate_limit_info.resetsAt);\n const resetsAtDisplay = resetsAt ?? \"unknown\";\n const message = `Rate limit rejected (type: ${rate_limit_info.rateLimitType ?? \"unknown\"}, resets at: ${resetsAtDisplay})`;\n host.connection.sendEvent({ type: \"error\", message });\n safeVoid(host.callbacks.onEvent({ type: \"error\", message }), \"rateLimitRejected\");\n return resetsAt;\n } else if (status === \"allowed_warning\") {\n const utilizationLabel = rate_limit_info.utilization\n ? `${Math.round(rate_limit_info.utilization * 100)}%`\n : \"high\";\n const message = `Rate limit warning: ${utilizationLabel} utilization (type: ${rate_limit_info.rateLimitType ?? \"unknown\"})`;\n host.connection.sendEvent({ type: \"thinking\", message });\n safeVoid(host.callbacks.onEvent({ type: \"thinking\", message }), \"rateLimitWarning\");\n }\n return undefined;\n}\n\nexport async function handleSystemEvent(\n event: HarnessSystemInitEvent,\n host: QueryHost,\n context: TaskContext,\n sessionIdStored: boolean,\n): Promise<boolean> {\n if (event.subtype !== \"init\") return false;\n if (event.session_id && !sessionIdStored) {\n host.connection.storeSessionId(event.session_id);\n context.claudeSessionId = event.session_id;\n }\n await host.callbacks.onEvent({\n type: \"thinking\",\n message: `Agent initialized (model: ${event.model})`,\n });\n return !!(event.session_id && !sessionIdStored);\n}\n\nexport function handleSystemSubevents(\n systemEvent: HarnessCompactBoundaryEvent | HarnessTaskStartedEvent | HarnessTaskProgressEvent,\n host: QueryHost,\n): void {\n if (systemEvent.subtype === \"compact_boundary\") {\n safeVoid(\n host.callbacks.onEvent({\n type: \"context_compacted\",\n trigger: systemEvent.compact_metadata.trigger,\n preTokens: systemEvent.compact_metadata.pre_tokens,\n }),\n \"compactBoundary\",\n );\n } else if (systemEvent.subtype === \"task_started\") {\n safeVoid(\n host.callbacks.onEvent({\n type: \"subagent_started\",\n sdkTaskId: systemEvent.task_id,\n description: systemEvent.description,\n }),\n \"taskStarted\",\n );\n } else if (systemEvent.subtype === \"task_progress\") {\n safeVoid(\n host.callbacks.onEvent({\n type: \"subagent_progress\",\n sdkTaskId: systemEvent.task_id,\n description: systemEvent.description,\n toolUses: systemEvent.usage?.tool_uses ?? 0,\n durationMs: systemEvent.usage?.duration_ms ?? 0,\n }),\n \"taskProgress\",\n );\n }\n}\n\nexport function handleToolProgressEvent(event: unknown, host: QueryHost): void {\n const msg = event as { tool_name?: string; elapsed_time_seconds?: number };\n safeVoid(\n host.callbacks.onEvent({\n type: \"tool_progress\",\n toolName: msg.tool_name ?? \"\",\n elapsedSeconds: msg.elapsed_time_seconds ?? 0,\n }),\n \"toolProgress\",\n );\n}\n\nexport async function handleAssistantCase(\n event: HarnessAssistantEvent,\n host: QueryHost,\n turnToolCalls: ActivityEventSummary[],\n): Promise<UsageInfo | undefined> {\n await processAssistantEvent(event, host, turnToolCalls);\n const msgUsage = (event.message as { usage?: UsageInfo }).usage;\n return msgUsage ?? undefined;\n}\n\nexport async function handleResultCase(\n event: HarnessResultEvent,\n host: QueryHost,\n context: TaskContext,\n startTime: number,\n isTyping: boolean,\n lastAssistantUsage: UsageInfo | undefined,\n): Promise<{\n retriable: boolean;\n resultSummary?: string;\n staleSession?: boolean;\n authError?: boolean;\n stoppedTyping: boolean;\n}> {\n let stoppedTyping = false;\n if (isTyping) {\n host.connection.sendTypingStop();\n stoppedTyping = true;\n }\n const resultInfo = await emitResultEvent(event, host, context, startTime, lastAssistantUsage);\n return {\n retriable: resultInfo.retriable,\n resultSummary: resultInfo.resultSummary,\n staleSession: resultInfo.staleSession,\n authError: resultInfo.authError,\n stoppedTyping,\n };\n}\n","import type {\n HarnessEvent,\n HarnessAssistantEvent,\n HarnessResultEvent,\n HarnessSystemInitEvent,\n HarnessCompactBoundaryEvent,\n HarnessTaskStartedEvent,\n HarnessTaskProgressEvent,\n HarnessRateLimitEvent,\n} from \"../harness/index.js\";\nimport type { TaskContext, ActivityEventSummary } from \"@project/shared\";\nimport { AGENT_STATUS_REASON_USER_QUESTION } from \"@project/shared\";\nimport type { QueryHost } from \"./query-executor.js\";\nimport type { UsageInfo } from \"./event-handlers.js\";\nimport {\n API_ERROR_PATTERN,\n handleAssistantCase,\n handleResultCase,\n handleRateLimitEvent,\n handleSystemEvent,\n handleSystemSubevents,\n handleToolProgressEvent,\n} from \"./event-handlers.js\";\n\n/** Mutable state bag threaded through the event loop. */\ninterface EventLoopState {\n sessionIdStored: boolean;\n isTyping: boolean;\n retriable: boolean;\n sawApiError: boolean;\n resultSummary: string | undefined;\n rateLimitResetsAt: string | undefined;\n staleSession: boolean | undefined;\n authError: boolean | undefined;\n lastAssistantUsage: UsageInfo | undefined;\n turnToolCalls: ActivityEventSummary[];\n /**\n * A TUI AskUserQuestion questionnaire is pending (armed by the PTY\n * harness's `user_question` event). While set, the periodic \"running\"\n * re-emit is suppressed so it can't clobber the reported\n * `waiting_for_input`. Display-only — mirrors `watchForParkedTui`.\n */\n questionPending: boolean;\n}\n\n/** The arming assistant record contains the AskUserQuestion tool_use block —\n * it can arrive via the transcript tailer after the hook event and must not\n * clear the pending flag. */\nfunction hasAskUserQuestionBlock(event: HarnessAssistantEvent): boolean {\n return event.message.content.some((b) => b.type === \"tool_use\" && b.name === \"AskUserQuestion\");\n}\n\n/** Report `waiting_for_input` for a pending TUI questionnaire. Display-only:\n * SessionRunner `_state` is untouched (same semantics as `watchForParkedTui`),\n * so idle-timer and chat-supersede behavior are unchanged. */\nasync function armQuestionPending(host: QueryHost, state: EventLoopState): Promise<void> {\n state.questionPending = true;\n await host.connection.emitStatus(\"waiting_for_input\", AGENT_STATUS_REASON_USER_QUESTION);\n await host.callbacks.onStatusChange(\"waiting_for_input\");\n}\n\nasync function clearQuestionPending(\n host: QueryHost,\n state: EventLoopState,\n options: { emitRunning: boolean },\n): Promise<void> {\n if (!state.questionPending) return;\n state.questionPending = false;\n if (options.emitRunning) {\n await host.connection.emitStatus(\"running\");\n await host.callbacks.onStatusChange(\"running\");\n }\n}\n\n/**\n * Question-pending transitions driven by the event stream:\n * - user_question (PTY hook observed AskUserQuestion) → arm.\n * - tool_progress for AskUserQuestion (PostToolUse fires once the user\n * answered in the TUI) → clear + running (the deterministic clear).\n * - assistant WITHOUT an AskUserQuestion block → clear + running (backstop;\n * a new assistant record only exists after the questionnaire resolved).\n * Records WITH the block are the arming tool_use arriving late via the\n * transcript tailer and must not clear.\n * - result → clear silently (the result path owns the final status; covers\n * Esc/interrupt and turn end while parked).\n */\nasync function applyQuestionTransitions(\n event: HarnessEvent,\n host: QueryHost,\n state: EventLoopState,\n): Promise<void> {\n switch (event.type) {\n case \"user_question\":\n await armQuestionPending(host, state);\n return;\n case \"assistant\":\n if (!hasAskUserQuestionBlock(event as HarnessAssistantEvent)) {\n await clearQuestionPending(host, state, { emitRunning: true });\n }\n return;\n case \"tool_progress\":\n if (event.tool_name === \"AskUserQuestion\") {\n await clearQuestionPending(host, state, { emitRunning: true });\n }\n return;\n case \"result\":\n await clearQuestionPending(host, state, { emitRunning: false });\n return;\n default:\n break;\n }\n}\n\nfunction stopTypingIfNeeded(host: QueryHost, isTyping: boolean): void {\n if (isTyping) host.connection.sendTypingStop();\n}\n\n/** Merge pending tool outputs into accumulated tool call summaries and emit turn_end. */\nfunction flushPendingToolCalls(host: QueryHost, turnToolCalls: ActivityEventSummary[]): void {\n if (turnToolCalls.length === 0) {\n // Clear any orphaned outputs that arrived without matching tool_use blocks\n host.pendingToolOutputs.length = 0;\n return;\n }\n // Match outputs to tool calls by tool name (handles duplicate names via queue)\n const outputsByTool = new Map<string, string[]>();\n for (const entry of host.pendingToolOutputs) {\n const list = outputsByTool.get(entry.tool) ?? [];\n list.push(entry.output);\n outputsByTool.set(entry.tool, list);\n }\n for (const call of turnToolCalls) {\n const list = outputsByTool.get(call.tool);\n if (list && list.length > 0) {\n call.output = list.shift();\n }\n }\n host.connection.sendEvent({ type: \"turn_end\", toolCalls: [...turnToolCalls] });\n turnToolCalls.length = 0;\n host.pendingToolOutputs.length = 0;\n}\n\nasync function processSystemCase(\n event:\n | HarnessSystemInitEvent\n | HarnessCompactBoundaryEvent\n | HarnessTaskStartedEvent\n | HarnessTaskProgressEvent,\n host: QueryHost,\n context: TaskContext,\n state: EventLoopState,\n): Promise<void> {\n if (event.subtype === \"init\") {\n const stored = await handleSystemEvent(event, host, context, state.sessionIdStored);\n if (stored) state.sessionIdStored = true;\n } else {\n handleSystemSubevents(\n event as HarnessCompactBoundaryEvent | HarnessTaskStartedEvent | HarnessTaskProgressEvent,\n host,\n );\n }\n}\n\nasync function processAssistantCase(\n event: HarnessAssistantEvent,\n host: QueryHost,\n state: EventLoopState,\n): Promise<void> {\n if (!state.isTyping) {\n setTimeout(() => host.connection.sendTypingStart(), 200);\n state.isTyping = true;\n }\n const usage = await handleAssistantCase(event, host, state.turnToolCalls);\n if (usage) state.lastAssistantUsage = usage;\n\n // Check for API error patterns in assistant message text.\n // The SDK may emit API errors as assistant message content before ending\n // with a clean success result, which would bypass the result-level retry check.\n if (!state.sawApiError) {\n const fullText = event.message.content\n .filter((b: { type: string }) => b.type === \"text\")\n .map((b: { type: string; text?: string }) => (b as { text: string }).text)\n .join(\" \");\n if (API_ERROR_PATTERN.test(fullText)) {\n state.sawApiError = true;\n }\n }\n}\n\nasync function processResultCase(\n event: HarnessResultEvent,\n host: QueryHost,\n context: TaskContext,\n startTime: number,\n state: EventLoopState,\n): Promise<void> {\n const info = await handleResultCase(\n event,\n host,\n context,\n startTime,\n state.isTyping,\n state.lastAssistantUsage,\n );\n if (info.stoppedTyping) state.isTyping = false;\n state.retriable = info.retriable;\n // If the result itself is clean (not retriable), any API error the agent\n // mentioned in assistant text was already recovered from — don't retry.\n if (!info.retriable) state.sawApiError = false;\n state.resultSummary = info.resultSummary;\n if (info.staleSession) state.staleSession = true;\n if (info.authError) state.authError = true;\n}\n\nexport async function processEvents(\n events: AsyncGenerator<HarnessEvent, void>,\n context: TaskContext,\n host: QueryHost,\n): Promise<{\n retriable: boolean;\n resultSummary?: string;\n modeRestart?: boolean;\n rateLimitResetsAt?: string;\n staleSession?: boolean;\n authError?: boolean;\n}> {\n const startTime = Date.now();\n let lastStatusEmit = Date.now();\n const STATUS_REEMIT_INTERVAL_MS = 5_000;\n\n const state: EventLoopState = {\n sessionIdStored: false,\n isTyping: false,\n retriable: false,\n sawApiError: false,\n resultSummary: undefined,\n rateLimitResetsAt: undefined,\n staleSession: undefined,\n authError: undefined,\n lastAssistantUsage: undefined,\n turnToolCalls: [],\n questionPending: false,\n };\n\n for await (const event of events) {\n if (host.isStopped()) break;\n\n // Flush any pending tool calls from the previous assistant turn\n // (tool outputs have been collected by PostToolUse hooks between events)\n flushPendingToolCalls(host, state.turnToolCalls);\n\n // Re-emit \"running\" periodically so missed status events self-correct.\n // Suppressed while a questionnaire is pending — a stray tool_progress\n // (e.g. a parallel tool finishing) must not clobber waiting_for_input.\n const now = Date.now();\n if (now - lastStatusEmit >= STATUS_REEMIT_INTERVAL_MS && !state.questionPending) {\n host.connection.emitStatus(\"running\");\n lastStatusEmit = now;\n }\n\n if (host.pendingModeRestart) {\n stopTypingIfNeeded(host, state.isTyping);\n return { retriable: false, modeRestart: true };\n }\n\n await applyQuestionTransitions(event, host, state);\n\n switch (event.type) {\n case \"system\":\n await processSystemCase(event as HarnessSystemInitEvent, host, context, state);\n break;\n case \"assistant\":\n await processAssistantCase(event as HarnessAssistantEvent, host, state);\n break;\n case \"result\":\n await processResultCase(event as HarnessResultEvent, host, context, startTime, state);\n break;\n case \"rate_limit_event\": {\n const resetsAt = handleRateLimitEvent(event as HarnessRateLimitEvent, host);\n if (resetsAt) state.rateLimitResetsAt = resetsAt;\n break;\n }\n case \"tool_progress\":\n handleToolProgressEvent(event, host);\n break;\n }\n }\n\n flushPendingToolCalls(host, state.turnToolCalls);\n stopTypingIfNeeded(host, state.isTyping);\n\n return {\n retriable: state.retriable || state.sawApiError,\n resultSummary: state.resultSummary,\n rateLimitResetsAt: state.rateLimitResetsAt,\n ...(state.staleSession && { staleSession: state.staleSession }),\n ...(state.authError && { authError: state.authError }),\n };\n}\n","/**\n * Shared utility for checking missing task properties.\n * Used by both ExitPlanMode validation and post-PR backfill nudge.\n */\n\nexport function collectMissingProps(taskProps: {\n plan?: string | null;\n storyPointId?: string | null;\n title?: string | null;\n}): string[] {\n const missing: string[] = [];\n if (!taskProps.plan?.trim()) missing.push(\"plan (save via update_task_plan)\");\n if (!taskProps.storyPointId) missing.push(\"story points (use update_task_properties)\");\n if (!taskProps.title || taskProps.title === \"Untitled\")\n missing.push(\"title (use update_task_properties)\");\n return missing;\n}\n","import type { QueryHost } from \"./query-executor.js\";\nimport { collectMissingProps } from \"./task-property-utils.js\";\nimport type { ExplorationTracker, StalenessSignal } from \"./exploration-tracker.js\";\n\nconst PM_PLAN_FILE_TOOLS = new Set([\"Write\", \"Edit\", \"MultiEdit\"]);\n\nconst DESTRUCTIVE_PATTERNS: { name: string; re: RegExp }[] = [\n {\n name: \"git push --force (without --force-with-lease)\",\n re: /git\\s+push\\s+(?:-f\\b|--force(?!-with-lease))/,\n },\n { name: \"git push --delete\", re: /git\\s+push\\s+(?:-d\\b|--delete\\b)/ },\n { name: \"git reset --hard\", re: /git\\s+reset\\s+--hard\\b/ },\n {\n name: \"rm -rf /\",\n re: /rm\\s+(?:-[a-zA-Z]*r[a-zA-Z]*f|-[a-zA-Z]*f[a-zA-Z]*r|--recursive\\s+--force)\\s+\\/(?!\\S)/,\n },\n { name: \"sudo rm\", re: /\\bsudo\\s+rm\\b/ },\n { name: \"chmod world-writable\", re: /\\bchmod\\s+(?:-R\\s+)?[0-7]*7{2,3}\\b/ },\n { name: \"dd to device\", re: /\\bdd\\s+.*\\bof=\\/dev\\// },\n { name: \"redirect to block device\", re: />\\s*\\/dev\\/(?:sd[a-z]|nvme\\d|xvd[a-z])/ },\n { name: \"mkfs filesystem creation\", re: /\\bmkfs(?:\\.|\\s)/ },\n { name: \"shutdown/poweroff/halt/reboot\", re: /\\b(?:shutdown|poweroff|halt|reboot)\\b/ },\n { name: \"fork bomb\", re: /:\\(\\)\\s*\\{\\s*:\\|\\s*:&\\s*\\}\\s*;\\s*:/ },\n];\n\nfunction matchesDestructive(cmd: string): string | null {\n for (const { name, re } of DESTRUCTIVE_PATTERNS) {\n if (re.test(cmd)) return name;\n }\n return null;\n}\n\ntype ToolResult =\n | { behavior: \"allow\"; updatedInput?: Record<string, unknown> }\n | { behavior: \"deny\"; message: string };\n\nfunction isPlanFile(input: Record<string, unknown>): boolean {\n const filePath = String(input.file_path ?? input.path ?? \"\");\n return filePath.includes(\".claude/plans/\");\n}\n\nfunction handleDiscoveryToolAccess(toolName: string, input: Record<string, unknown>): ToolResult {\n if (PM_PLAN_FILE_TOOLS.has(toolName)) {\n if (isPlanFile(input)) {\n return { behavior: \"allow\", updatedInput: input };\n }\n return {\n behavior: \"deny\",\n message: \"Discovery mode is read-only. File writes are restricted to plan files.\",\n };\n }\n return { behavior: \"allow\", updatedInput: input };\n}\n\nfunction handleBuildingToolAccess(toolName: string, input: Record<string, unknown>): ToolResult {\n if (toolName === \"Bash\") {\n const cmd = String(input.command ?? \"\");\n const matched = matchesDestructive(cmd);\n if (matched) {\n return {\n behavior: \"deny\",\n message: `Destructive operation blocked (${matched}). Use safer alternatives.`,\n };\n }\n }\n return { behavior: \"allow\", updatedInput: input };\n}\n\nfunction handleReviewToolAccess(toolName: string, input: Record<string, unknown>): ToolResult {\n // Review mode has full write access — reviewer can make direct fixes\n return handleBuildingToolAccess(toolName, input);\n}\n\nfunction handleAutoToolAccess(\n toolName: string,\n input: Record<string, unknown>,\n hasExitedPlanMode: boolean,\n isParentTask: boolean,\n): ToolResult {\n if (hasExitedPlanMode) {\n return isParentTask\n ? handleReviewToolAccess(toolName, input)\n : handleBuildingToolAccess(toolName, input);\n }\n // Pre-ExitPlanMode: trust the SDK's native plan mode for restrictions.\n return { behavior: \"allow\", updatedInput: input };\n}\n\nfunction enforceMissingProps(\n host: QueryHost,\n input: Record<string, unknown>,\n missingProps: string[],\n): ToolResult | null {\n if (missingProps.length === 0) return null;\n if (input.bypassValidation !== true) {\n return {\n behavior: \"deny\" as const,\n message: [\n \"Cannot exit plan mode. Required task properties are missing:\",\n ...missingProps.map((p) => `- ${p}`),\n \"\",\n \"Fill these in using MCP tools (e.g. update_task_plan, update_task_properties), then call ExitPlanMode again.\",\n \"\",\n \"If you have a deliberate reason to proceed without them, you must explicitly bypass validation by calling ExitPlanMode with `bypassValidation: true` as a tool argument. Do not bypass unless the team has asked you to — it will be surfaced in chat.\",\n ].join(\"\\n\"),\n };\n }\n host.connection.postChatMessage(\n `⚠️ [BYPASS] ExitPlanMode forced through with \\`bypassValidation: true\\` despite missing required properties: ${missingProps.join(\", \")}. Please backfill these.`,\n );\n return null;\n}\n\nasync function handleExitPlanMode(\n host: QueryHost,\n input: Record<string, unknown>,\n): Promise<ToolResult> {\n if (host.hasExitedPlanMode) {\n return { behavior: \"allow\" as const, updatedInput: input };\n }\n\n try {\n // Flush any locally-written plan files to the server before validation.\n // Awaited so a failed sync surfaces in chat before getTaskProperties is\n // consulted — otherwise we'd validate against stale server-side plan state.\n await host.syncPlanFile();\n\n const taskProps = await host.connection.getTaskProperties();\n const missingProps = collectMissingProps(taskProps);\n\n // Validate subtasks have plans if this is a parent task\n if (host.isParentTask) {\n try {\n const subtasks = await host.connection.call(\"listSubtasks\", {\n sessionId: host.connection.sessionId,\n });\n const subtasksWithoutPlans = subtasks.filter(\n (s: { plan?: string | null; title: string }) => !s.plan?.trim(),\n );\n if (subtasksWithoutPlans.length > 0) {\n const names = subtasksWithoutPlans.map((s: { title: string }) => s.title).join(\", \");\n missingProps.push(\n `subtask plans — these subtasks are missing plans: ${names} (use update_subtask with plan field)`,\n );\n }\n } catch {\n // If we can't list subtasks, skip this validation\n }\n }\n\n const gate = enforceMissingProps(host, input, missingProps);\n if (gate) return gate;\n\n if (host.agentMode === \"discovery\") {\n host.hasExitedPlanMode = true;\n host.discoveryCompleted = true;\n // Await both the identification trigger and the confirmation chat post\n // before requesting stop. Previously these were fire-and-forget, so a\n // connection drop between the ExitPlanMode call and the stop could lose\n // either the identification event or the confirmation message, leaving\n // the agent with no visible signal that planning actually completed.\n try {\n await host.connection.triggerIdentification();\n } catch (triggerErr) {\n host.connection.postChatMessage(\n `Identification trigger encountered an issue (${triggerErr instanceof Error ? triggerErr.message : \"unknown error\"}). Icon and agent assignment may use fallbacks.`,\n );\n }\n await host.connection.postChatMessageAwait(\n \"Planning complete — awaiting team approval. Icon and agent assignment will be set automatically.\",\n );\n // requestStop aborts the SDK event loop only after the above acks land,\n // guaranteeing the team sees a confirmation message for this session.\n // Under the PTY harness this verdict travels back to the CLI over the\n // hook socket — defer the stop a tick so the allow response is written\n // before teardown closes the socket and kills the CLI. (The CLI dies at\n // its plan-approval dialog; the session resumes cleanly on Build.)\n if (host.harnessKind === \"pty\") {\n setTimeout(() => host.requestStop(), 250);\n } else {\n host.requestStop();\n }\n return { behavior: \"allow\" as const, updatedInput: input };\n }\n\n // Auto mode: trigger identification but don't let it block ExitPlanMode.\n // Identification runs asynchronously server-side with fallbacks,\n // and the agent should proceed to building mode regardless.\n try {\n await host.connection.triggerIdentification();\n } catch (triggerErr) {\n host.connection.postChatMessage(\n `Identification trigger encountered an issue (${triggerErr instanceof Error ? triggerErr.message : \"unknown error\"}). Proceeding to build phase — identification will use fallbacks.`,\n );\n }\n\n host.hasExitedPlanMode = true;\n\n // Same-session continuation on BOTH harnesses: the SDK upgrades plan→build\n // permissions natively; under PTY the session presses Enter on the residual\n // plan dialog (planDialogAutoAccept) and continues in acceptEdits with the\n // settings allow-list covering the rest. The mode_changed event below is\n // deliberately unhandled server-side — DB task.agentMode must stay \"auto\"\n // so computeRunnerMode/canBypassPlanning resolve correctly on pod restarts.\n const newMode = host.isParentTask ? \"review\" : \"building\";\n host.connection.sendEvent({ type: \"mode_transition\", from: \"auto\", to: newMode });\n host.connection.emitModeChanged(newMode);\n\n return { behavior: \"allow\" as const, updatedInput: input };\n } catch (err) {\n return {\n behavior: \"deny\" as const,\n message: `Identification failed: ${err instanceof Error ? err.message : String(err)}. Fix the issue and try again.`,\n };\n }\n}\n\nasync function handleAskUserQuestion(\n host: QueryHost,\n input: Record<string, unknown>,\n): Promise<ToolResult> {\n const QUESTION_TIMEOUT_MS = 5 * 60 * 1000;\n const questions = input.questions as {\n question: string;\n header: string;\n options: { label: string; description: string; preview?: string }[];\n multiSelect?: boolean;\n }[];\n\n host.connection.emitStatus(\"waiting_for_input\");\n host.connection.sendEvent({\n type: \"tool_use\",\n tool: \"AskUserQuestion\",\n input: JSON.stringify(input),\n });\n\n const answerPromise = host.connection.askUserQuestion(questions);\n const timeoutPromise = new Promise<null>((resolve) => {\n setTimeout(() => resolve(null), QUESTION_TIMEOUT_MS);\n });\n\n const answers = await Promise.race([answerPromise, timeoutPromise]);\n host.connection.emitStatus(\"running\");\n\n if (!answers || Object.keys(answers).length === 0) {\n return {\n behavior: \"deny\",\n message:\n \"User did not respond to clarifying questions in time. Proceed with your best judgment.\",\n };\n }\n\n return { behavior: \"allow\", updatedInput: { questions: input.questions, answers } };\n}\n\nconst EXPLORATION_TOOLS = new Set([\"Read\", \"Grep\", \"Glob\"]);\n\nfunction trackExploration(\n tracker: ExplorationTracker,\n toolName: string,\n input: Record<string, unknown>,\n): StalenessSignal | null {\n if (!EXPLORATION_TOOLS.has(toolName)) return null;\n\n if (toolName === \"Read\") {\n const filePath = String(input.file_path ?? \"\");\n if (filePath) return tracker.recordFileRead(filePath);\n }\n\n if (toolName === \"Grep\" || toolName === \"Glob\") {\n const pattern = String(input.pattern ?? \"\");\n if (pattern) return tracker.recordSearch(pattern);\n }\n\n return null;\n}\n\nconst DENIAL_WARNING_THRESHOLD = 3;\nconst DENIAL_FORCE_STOP_THRESHOLD = 8;\n\nfunction handleDenialEscalation(host: QueryHost, consecutiveDenials: number): void {\n if (consecutiveDenials === DENIAL_WARNING_THRESHOLD) {\n host.connection.postChatMessage(\n `⚠️ Multiple tool denials detected. You are in ${host.agentMode} mode — ` +\n `file writes outside .claude/plans/ are not permitted. ` +\n `Focus on creating a plan instead of implementing code changes.`,\n );\n }\n if (consecutiveDenials >= DENIAL_FORCE_STOP_THRESHOLD) {\n host.connection.postChatMessage(\n `Agent force-stopped after ${DENIAL_FORCE_STOP_THRESHOLD} consecutive tool denials. ` +\n `The agent appears stuck — send a message to resume.`,\n );\n host.requestStop();\n }\n}\n\nfunction resolveToolAccess(\n host: QueryHost,\n toolName: string,\n input: Record<string, unknown>,\n): ToolResult {\n switch (host.agentMode) {\n case \"discovery\":\n return handleDiscoveryToolAccess(toolName, input);\n case \"building\":\n return handleBuildingToolAccess(toolName, input);\n case \"review\":\n return handleReviewToolAccess(toolName, input);\n case \"auto\":\n return handleAutoToolAccess(toolName, input, host.hasExitedPlanMode, host.isParentTask);\n default:\n return { behavior: \"allow\", updatedInput: input };\n }\n}\n\nexport function buildCanUseTool(\n host: QueryHost,\n): (toolName: string, input: Record<string, unknown>) => Promise<ToolResult> {\n let consecutiveDenials = 0;\n\n return async (toolName, input) => {\n if (\n toolName === \"ExitPlanMode\" &&\n (host.agentMode === \"auto\" || host.agentMode === \"discovery\") &&\n !host.hasExitedPlanMode\n ) {\n return await handleExitPlanMode(host, input);\n }\n\n // Repeated ExitPlanMode calls after plan mode was already exited in discovery\n // mode should be denied to prevent burning budget without triggering force-stop.\n if (toolName === \"ExitPlanMode\" && host.agentMode === \"discovery\" && host.hasExitedPlanMode) {\n return {\n behavior: \"deny\" as const,\n message:\n \"Plan mode has already been exited. The team will transition you to Building mode when ready.\",\n };\n }\n\n if (toolName === \"AskUserQuestion\") {\n return await handleAskUserQuestion(host, input);\n }\n\n const result = resolveToolAccess(host, toolName, input);\n\n // Track exploration patterns during planning to detect analysis paralysis.\n // Only active when tracker exists (discovery/auto-planning) and plan mode hasn't been exited.\n if (result.behavior === \"allow\" && host.explorationTracker && !host.hasExitedPlanMode) {\n const signal = trackExploration(host.explorationTracker, toolName, input);\n if (signal) {\n host.connection.postChatMessage(signal.message);\n }\n }\n\n if (result.behavior === \"deny\") {\n consecutiveDenials++;\n handleDenialEscalation(host, consecutiveDenials);\n } else {\n consecutiveDenials = 0;\n }\n\n return result;\n };\n}\n","/**\n * Pure, dependency-free secret redactor for tool output.\n *\n * Applied in the PostToolUse hook before forwarding `tool_result` events to\n * the API and before buffering into `pendingToolOutputs`. Defense-in-depth\n * only — server-side must still treat tool output as potentially tainted.\n *\n * Patterns are intentionally conservative: we prefer false negatives over\n * false positives because agents rely on reading tool output to do work.\n * Commit SHAs (`[a-f0-9]{7,40}`) are deliberately NOT redacted.\n */\n\nconst REDACTED = \"<redacted>\";\n\nconst BEARER_RE = /\\b(Bearer\\s+)[A-Za-z0-9_\\-.]{20,}/g;\n\nconst VENDOR_KEY_RE =\n /\\b(?:sk-[a-zA-Z0-9_-]{20,}|ghp_[A-Za-z0-9]{36}|github_pat_[A-Za-z0-9_]{22,}|xoxb-[A-Za-z0-9-]+|xai-[A-Za-z0-9-]{20,})\\b/g;\n\nconst AWS_ACCESS_KEY_RE = /\\bAKIA[0-9A-Z]{16}\\b/g;\n\n// JWTs: three base64url segments separated by dots, starting with the\n// ubiquitous `eyJ` header prefix.\nconst JWT_RE = /\\beyJ[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\.[A-Za-z0-9_-]+\\b/g;\n\n// KEY=VALUE lines where KEY looks like a secret name. Matches optional\n// `export ` prefix and quoted or bare values. Captures KEY separately so we\n// preserve it in the replacement.\nconst ENV_SECRET_RE =\n /^(\\s*(?:export\\s+)?([A-Z][A-Z0-9_]*(?:TOKEN|SECRET|KEY|PASSWORD|PASS|CREDENTIAL|CREDENTIALS)[A-Z0-9_]*)\\s*=\\s*)['\"]?([^\\s'\"]+)['\"]?/gm;\n\nconst COOKIE_HEADER_RE = /(Cookie:\\s*)[^\\r\\n]+/gi;\n\n// Basic-auth URLs: keep the user visible, mask the password.\nconst BASIC_AUTH_URL_RE = /(https?:\\/\\/)([^:@\\s/]+):([^@\\s]+)@/g;\n\n// AWS secret access keys don't have a distinctive prefix. Apply only on\n// lines that mention \"secret\" / \"aws_secret\" to avoid matching commit SHAs,\n// base64 payloads, etc.\nconst AWS_SECRET_LINE_RE = /^.*(?:secret|aws_secret).*$/gim;\nconst AWS_SECRET_VALUE_RE = /\\b([A-Za-z0-9/+=]{40})\\b/g;\n\n// Strip prompt-injection attempts from tool output: we observed `<system-reminder>`\n// blocks being smuggled through bash output during discovery of this pipeline.\nconst SYSTEM_REMINDER_RE = /<system-reminder>[\\s\\S]*?<\\/system-reminder>/gi;\n\nexport interface RedactResult {\n output: string;\n redacted: number;\n}\n\nexport function redact(input: string): RedactResult {\n if (!input) return { output: input, redacted: 0 };\n\n let count = 0;\n let output = input;\n\n output = output.replace(SYSTEM_REMINDER_RE, () => {\n count++;\n return \"<!-- stripped injection -->\";\n });\n\n output = output.replace(BEARER_RE, (_match, prefix: string) => {\n count++;\n return `${prefix}${REDACTED}`;\n });\n\n output = output.replace(VENDOR_KEY_RE, () => {\n count++;\n return REDACTED;\n });\n\n output = output.replace(AWS_ACCESS_KEY_RE, () => {\n count++;\n return REDACTED;\n });\n\n output = output.replace(JWT_RE, () => {\n count++;\n return REDACTED;\n });\n\n output = output.replace(AWS_SECRET_LINE_RE, (line) =>\n line.replace(AWS_SECRET_VALUE_RE, (match) => {\n // Skip pure hex (commit SHAs, etc.) — AWS secrets use the full\n // base64 alphabet, so a match that's all-hex is almost certainly\n // not a secret.\n if (/^[a-f0-9]+$/i.test(match)) return match;\n count++;\n return REDACTED;\n }),\n );\n\n output = output.replace(ENV_SECRET_RE, (_match, prefix: string, _key: string, _value: string) => {\n count++;\n return `${prefix}${REDACTED}`;\n });\n\n output = output.replace(COOKIE_HEADER_RE, (_match, prefix: string) => {\n count++;\n return `${prefix}${REDACTED}`;\n });\n\n output = output.replace(BASIC_AUTH_URL_RE, (_match, scheme: string, user: string) => {\n count++;\n return `${scheme}${user}:${REDACTED}@`;\n });\n\n return { output, redacted: count };\n}\n","/**\n * ExplorationTracker — detects repetitive file reads and search patterns\n * during planning-mode queries to nudge agents past analysis paralysis.\n *\n * Follows the CostTracker pattern: stateful accumulator with read-only getters.\n * Instantiated per-query in QueryBridge.buildHost() for discovery/auto-planning\n * modes only. Building/review modes set this to null on QueryHost.\n */\n\nexport type NudgeLevel = 1 | 2;\n\nexport interface StalenessSignal {\n level: NudgeLevel;\n message: string;\n}\n\n// Base thresholds (before complexity scaling)\nconst FILE_REREAD_NUDGE_L1 = 3;\nconst FILE_REREAD_NUDGE_L2 = 5;\nconst SEARCH_REPEAT_NUDGE_L1 = 3;\nconst SEARCH_REPEAT_NUDGE_L2 = 5;\nconst RATIO_MIN_READS_L1 = 10;\nconst RATIO_THRESHOLD_L1 = 0.4;\nconst RATIO_MIN_READS_L2 = 15;\nconst RATIO_THRESHOLD_L2 = 0.3;\n\nfunction normalizePath(filePath: string): string {\n // Strip leading ./ for consistent tracking\n let normalized = filePath.replace(/^\\.\\//, \"\");\n // Collapse consecutive slashes\n normalized = normalized.replace(/\\/+/g, \"/\");\n return normalized;\n}\n\nexport class ExplorationTracker {\n private fileReadCounts = new Map<string, number>();\n private searchCounts = new Map<string, number>();\n private totalReads = 0;\n private highestNudgeEmitted: NudgeLevel | 0 = 0;\n private readonly complexityMultiplier: number;\n\n constructor(isParentTask: boolean) {\n this.complexityMultiplier = isParentTask ? 1.5 : 1.0;\n }\n\n /** Record a file read and return a staleness signal if thresholds are crossed. */\n recordFileRead(filePath: string): StalenessSignal | null {\n const normalized = normalizePath(filePath);\n const count = (this.fileReadCounts.get(normalized) ?? 0) + 1;\n this.fileReadCounts.set(normalized, count);\n this.totalReads++;\n\n // Check file re-read thresholds (higher level first for priority)\n return this.checkFileRereadSignal(normalized, count) ?? this.checkExplorationRatio();\n }\n\n /** Record a search pattern and return a staleness signal if thresholds are crossed. */\n recordSearch(pattern: string): StalenessSignal | null {\n const count = (this.searchCounts.get(pattern) ?? 0) + 1;\n this.searchCounts.set(pattern, count);\n\n return this.checkSearchRepeatSignal(pattern, count);\n }\n\n private scaledThreshold(base: number): number {\n return Math.ceil(base * this.complexityMultiplier);\n }\n\n private checkFileRereadSignal(filePath: string, count: number): StalenessSignal | null {\n const l2 = this.scaledThreshold(FILE_REREAD_NUDGE_L2);\n const l1 = this.scaledThreshold(FILE_REREAD_NUDGE_L1);\n\n if (count >= l2 && this.highestNudgeEmitted < 2) {\n this.highestNudgeEmitted = 2;\n return {\n level: 2,\n message:\n `⚠️ Exploration warning: You've read \"${filePath}\" ${count} times, suggesting analysis paralysis. ` +\n `Write your plan with the context you have and call ExitPlanMode. ` +\n `If something specific is blocking you, describe the blocker in your plan.`,\n };\n }\n\n if (count >= l1 && this.highestNudgeEmitted < 1) {\n this.highestNudgeEmitted = 1;\n return {\n level: 1,\n message:\n `Exploration note: You've read \"${filePath}\" ${count} times. ` +\n `Consider whether you have enough context to start writing your plan. ` +\n `If you're still exploring, try looking at different files.`,\n };\n }\n\n return null;\n }\n\n private checkSearchRepeatSignal(pattern: string, count: number): StalenessSignal | null {\n const l2 = this.scaledThreshold(SEARCH_REPEAT_NUDGE_L2);\n const l1 = this.scaledThreshold(SEARCH_REPEAT_NUDGE_L1);\n\n // Truncate pattern for display\n const displayPattern = pattern.length > 60 ? pattern.slice(0, 57) + \"...\" : pattern;\n\n if (count >= l2 && this.highestNudgeEmitted < 2) {\n this.highestNudgeEmitted = 2;\n return {\n level: 2,\n message:\n `⚠️ Exploration warning: You've searched for \"${displayPattern}\" ${count} times. ` +\n `Repeated searches for the same pattern suggest you may be stuck. ` +\n `Proceed with the information you have.`,\n };\n }\n\n if (count >= l1 && this.highestNudgeEmitted < 1) {\n this.highestNudgeEmitted = 1;\n return {\n level: 1,\n message:\n `Exploration note: You've searched for \"${displayPattern}\" ${count} times. ` +\n `If you're not finding what you need, try a different approach or broader pattern.`,\n };\n }\n\n return null;\n }\n\n private checkExplorationRatio(): StalenessSignal | null {\n const uniqueReads = this.fileReadCounts.size;\n const ratio = this.totalReads > 0 ? uniqueReads / this.totalReads : 1;\n\n const minReadsL2 = this.scaledThreshold(RATIO_MIN_READS_L2);\n if (\n this.totalReads >= minReadsL2 &&\n ratio < RATIO_THRESHOLD_L2 &&\n this.highestNudgeEmitted < 2\n ) {\n this.highestNudgeEmitted = 2;\n return {\n level: 2,\n message:\n `⚠️ Exploration warning: Only ${Math.round(ratio * 100)}% of your ${this.totalReads} file reads are unique. ` +\n `This indicates significant re-reading. Write your plan with the context you have.`,\n };\n }\n\n const minReadsL1 = this.scaledThreshold(RATIO_MIN_READS_L1);\n if (\n this.totalReads >= minReadsL1 &&\n ratio < RATIO_THRESHOLD_L1 &&\n this.highestNudgeEmitted < 1\n ) {\n this.highestNudgeEmitted = 1;\n return {\n level: 1,\n message:\n `Exploration note: ${Math.round(ratio * 100)}% of your ${this.totalReads} file reads are unique. ` +\n `You're re-reading files more than exploring new ones. Consider starting your plan.`,\n };\n }\n\n return null;\n }\n}\n","/**\n * QueryBridge — wires SessionRunner lifecycle state to QueryExecutor execution.\n *\n * SessionRunner handles connect/idle/message lifecycle.\n * QueryExecutor handles Claude SDK query orchestration.\n * QueryBridge adapts between them by constructing the QueryHost interface\n * that QueryExecutor expects, using live references to ModeController state.\n */\n\nimport type { HarnessEvent, HarnessUserMessage, PtyBridge } from \"../harness/index.js\";\nimport { createHarness, type HarnessKind } from \"../harness/index.js\";\nimport {\n runSdkQuery,\n resolvePromptDelivery,\n hasExistingSessionFile,\n type QueryHost,\n} from \"../execution/query-executor.js\";\nimport { ExplorationTracker } from \"../execution/exploration-tracker.js\";\nimport { PlanSync } from \"./plan-sync.js\";\nimport type { AgentConnection } from \"../connection/agent-connection.js\";\nimport type { ModeController } from \"./mode-controller.js\";\nimport type { AgentRunnerConfig, AgentRunnerCallbacks } from \"../types.js\";\nimport type { TaskContext, AgentMode, MultimodalBlock } from \"@project/shared\";\nimport { createServiceLogger } from \"../utils/logger.js\";\n\nconst logger = createServiceLogger(\"QueryBridge\");\n\n/**\n * Pick the harness implementation for the task chat path.\n *\n * Card/task chat is ALWAYS the PTY harness (drives the `claude` CLI under a\n * pseudo-terminal, rendered as the Connected TUI). This is unconditional: the\n * env var `CONVEYOR_HARNESS` is deliberately NOT consulted, so a stale value\n * (a leftover codespace secret, or one applied via the bootstrap envVars) can\n * never route a card to the headless SDK loop — the failure mode that left\n * auto-mode cards running SDK with no Connected-TUI tab.\n *\n * The ONLY way to put a card on the SDK harness is an explicit maintainer\n * override, `CONVEYOR_FORCE_SDK_CARDS=1`. It is a distinct name that is never\n * pushed as a codespace secret nor emitted in the bootstrap env, so it cannot\n * be triggered accidentally — it exists solely for emergency local debugging.\n *\n * Scope: this governs ONLY the task chat. The audit and project-chat paths\n * construct the SDK harness directly via `createHarness()` (no-arg) and never\n * call this function, so they stay on SDK regardless.\n */\nexport function resolveHarnessKind(): HarnessKind {\n return process.env.CONVEYOR_FORCE_SDK_CARDS === \"1\" ? \"sdk\" : \"pty\";\n}\n\n/**\n * Adapt an AgentConnection into the harness-neutral PtyBridge consumed by the\n * PTY harness. Keeps the harness package free of any connection-layer import.\n */\nfunction buildPtyBridge(connection: AgentConnection): PtyBridge {\n return {\n sendOutput: (data, dims) => connection.sendPtyOutput(data, dims),\n onInput: (handler) => connection.onPtyInput(handler),\n onResize: (handler) => connection.onPtyResize(handler),\n };\n}\n\nexport class QueryBridge {\n private readonly harness;\n /** Which harness drives this bridge (\"pty\" task chat; \"sdk\" only under the\n * CONVEYOR_FORCE_SDK_CARDS maintainer override). */\n readonly harnessKind: HarnessKind;\n private readonly planSync: PlanSync;\n private readonly sessionIds = new Map<string, string>();\n private activeQuery: AsyncGenerator<HarnessEvent, void> | null = null;\n private readonly pendingToolOutputs: { tool: string; output: string }[] = [];\n private _stopped = false;\n private _discoveryCompleted = false;\n private _isParentTask = false;\n private _wasRateLimited = false;\n private _abortController: AbortController | null = null;\n\n /** Called by SessionRunner when ExitPlanMode triggers a mode transition. */\n onModeTransition?: (newMode: AgentMode) => void;\n\n /** Called by tool handlers to soft-stop (abort query, keep session alive). */\n onSoftStop?: () => void;\n\n constructor(\n private readonly connection: AgentConnection,\n private readonly mode: ModeController,\n private readonly runnerConfig: AgentRunnerConfig,\n private readonly callbacks: AgentRunnerCallbacks,\n workspaceDir: string,\n ) {\n const harnessKind = resolveHarnessKind();\n this.harnessKind = harnessKind;\n this.harness = createHarness(\n harnessKind,\n harnessKind === \"pty\" ? buildPtyBridge(connection) : undefined,\n );\n this.planSync = new PlanSync(workspaceDir, connection);\n }\n\n get isStopped(): boolean {\n return this._stopped;\n }\n\n get isDiscoveryCompleted(): boolean {\n return this._discoveryCompleted;\n }\n\n set isDiscoveryCompleted(val: boolean) {\n this._discoveryCompleted = val;\n }\n\n get isParentTask(): boolean {\n return this._isParentTask;\n }\n\n set isParentTask(val: boolean) {\n this._isParentTask = val;\n }\n\n get wasRateLimited(): boolean {\n return this._wasRateLimited;\n }\n\n /**\n * Ask the live terminal (PTY harness only) to redraw its full screen.\n * Safe no-op on the SDK harness or between queries.\n */\n forceRepaint(): void {\n this.harness.forceRepaint?.();\n }\n\n stop(): void {\n this._stopped = true;\n this._abortController?.abort();\n }\n\n resume(): void {\n this._stopped = false;\n }\n\n /**\n * How the INITIAL instructions for this task would be delivered — \"prefill\"\n * means the TUI input is pre-filled but unsubmitted, awaiting the human.\n * Mirrors the decision runSdkQuery makes for the initial (non-follow-up)\n * query so SessionRunner can pick the matching state/timers.\n */\n initialPromptDelivery(context: TaskContext): \"submit\" | \"prefill\" {\n return resolvePromptDelivery({\n harnessKind: this.harnessKind,\n runnerMode: this.runnerConfig.mode,\n isAuto: this.mode.isAuto,\n agentMode: this.mode.effectiveMode,\n isFollowUp: false,\n hasExistingSession: hasExistingSessionFile(context.taskId, this.runnerConfig.workspaceDir, {\n agentMode: this.mode.effectiveMode,\n runnerMode: this.runnerConfig.mode,\n }),\n });\n }\n\n /**\n * Execute a Claude SDK query.\n * Without followUpContent: runs initial mode execution (build/plan).\n * With followUpContent: processes a follow-up user message.\n * `promptDelivery` overrides the executor's submit-vs-prefill resolution —\n * SessionRunner forces \"submit\" when pending chat messages already direct\n * the agent (prefilling would park them until a human touched the TUI).\n */\n async execute(\n context: TaskContext,\n followUpContent?: string | MultimodalBlock[],\n promptDelivery?: \"submit\" | \"prefill\",\n ): Promise<void> {\n this._stopped = false;\n this._wasRateLimited = false;\n this._abortController = new AbortController();\n const host = this.buildHost();\n try {\n await runSdkQuery(host, context, followUpContent, promptDelivery);\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n const isAbort = this._stopped || /abort/i.test(msg);\n if (isAbort) {\n logger.info(\"Query stopped by user\", { error: msg });\n } else {\n logger.error(\"Query execution failed\", { error: msg });\n this.connection.sendEvent({ type: \"error\", message: msg });\n }\n } finally {\n this.mode.pendingModeRestart = false;\n this._abortController = null;\n }\n }\n\n // ── QueryHost construction ──────────────────────────────────────────\n\n private buildHost(): QueryHost {\n // oxlint-disable-next-line no-this-alias -- closure needed for live getter/setter delegation\n const bridge = this;\n return {\n config: this.runnerConfig,\n connection: this.connection,\n callbacks: this.callbacks,\n harness: this.harness,\n harnessKind: this.harnessKind,\n setupLog: [],\n explorationTracker:\n bridge.mode.effectiveMode === \"discovery\" ||\n (bridge.mode.effectiveMode === \"auto\" && !bridge.mode.hasExitedPlanMode)\n ? new ExplorationTracker(bridge._isParentTask)\n : null,\n sessionIds: this.sessionIds,\n pendingToolOutputs: this.pendingToolOutputs,\n\n // Live getters/setters delegating to ModeController + bridge state\n get agentMode() {\n return bridge.mode.effectiveMode;\n },\n get isAuto() {\n return bridge.mode.isAuto;\n },\n get isParentTask() {\n return bridge._isParentTask;\n },\n get hasExitedPlanMode() {\n return bridge.mode.hasExitedPlanMode;\n },\n set hasExitedPlanMode(val: boolean) {\n bridge.mode.hasExitedPlanMode = val;\n },\n get pendingModeRestart() {\n return bridge.mode.pendingModeRestart;\n },\n set pendingModeRestart(val: boolean) {\n bridge.mode.pendingModeRestart = val;\n },\n get discoveryCompleted() {\n return bridge._discoveryCompleted;\n },\n set discoveryCompleted(val: boolean) {\n bridge._discoveryCompleted = val;\n },\n get wasRateLimited() {\n return bridge._wasRateLimited;\n },\n set wasRateLimited(val: boolean) {\n bridge._wasRateLimited = val;\n },\n get activeQuery() {\n return bridge.activeQuery;\n },\n set activeQuery(val: AsyncGenerator<HarnessEvent, void> | null) {\n bridge.activeQuery = val;\n },\n get abortController() {\n return bridge._abortController;\n },\n\n isStopped: () => bridge._stopped,\n requestStop: () => bridge.stop(),\n requestSoftStop: () => {\n if (bridge.onSoftStop) bridge.onSoftStop();\n },\n createInputStream: (prompt) => bridge.createInputStream(prompt),\n snapshotPlanFiles: () => bridge.planSync.snapshotPlanFiles(),\n syncPlanFile: () => bridge.planSync.syncPlanFile(),\n onModeTransition: bridge.onModeTransition,\n };\n }\n\n // ── Input stream for Claude SDK ─────────────────────────────────────\n\n private async *createInputStream(\n prompt: string | MultimodalBlock[],\n ): AsyncGenerator<HarnessUserMessage, void, unknown> {\n yield {\n type: \"user\" as const,\n session_id: \"\",\n message: { role: \"user\" as const, content: prompt },\n parent_tool_use_id: null,\n };\n }\n}\n","import { readFileSync } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { ChatMessage, TaskContextDTO } from \"@project/shared\";\n\nexport function mapChatHistory(\n messages: TaskContextDTO[\"chatHistory\"] | undefined | null,\n): ChatMessage[] {\n if (!messages) return [];\n return messages.map((m) => ({\n id: m.id,\n role: (m.role ?? \"user\") as \"user\" | \"assistant\" | \"system\",\n content: m.content ?? \"\",\n userId: m.userId,\n userName: m.user?.name ?? undefined,\n createdAt: m.createdAt,\n ...(m.files && m.files.length > 0\n ? {\n files: m.files.map((f) => ({\n fileId: f.id,\n fileName: f.fileName,\n mimeType: f.mimeType,\n fileSize: f.fileSize,\n downloadUrl: f.downloadUrl ?? \"\",\n content: f.content,\n contentEncoding: f.contentEncoding,\n })),\n }\n : {}),\n }));\n}\n\n/** Read this agent's version from its bundled package.json. */\nexport function readAgentVersion(): string | null {\n try {\n const here = dirname(fileURLToPath(import.meta.url));\n // Walk up: dist/runner/session-runner.js → dist/ → package.json\n for (const rel of [\"../package.json\", \"../../package.json\"]) {\n try {\n const pkg = JSON.parse(readFileSync(join(here, rel), \"utf-8\")) as { version?: string };\n if (pkg.version) return pkg.version;\n } catch {\n /* try next candidate */\n }\n }\n } catch {\n /* ignore */\n }\n return null;\n}\n","/**\n * Runtime preview-port discovery (Claudespace v3).\n *\n * Polls the pod's listening TCP sockets and reports the delta vs a baseline\n * scan taken at startup — i.e. before the start command has had a chance to\n * bind anything — so sshd (2222), the agent's own internals, and sidecar\n * services are never reported. The confirmed set is pushed to the API via\n * `reportDiscoveredPorts` only when it CHANGES (full-replacement semantics),\n * where it lands on `WorkspaceSession.discoveredPorts` and feeds the\n * workspace-attach preview-port list.\n *\n * Source of truth is /proc/net/tcp + /proc/net/tcp6 — present on every Linux\n * pod, needs no binaries (the base image has no `ss`/`netstat` from iproute2).\n * A `netstat` fallback exists for darwin so the real-listener test runs on\n * developer machines; production pods are always Linux.\n */\nimport { readFile } from \"node:fs/promises\";\nimport { execFile } from \"node:child_process\";\nimport type { WorkspaceDiscoveredPort } from \"@project/shared\";\n\n// ── Scanning ────────────────────────────────────────────────────────────────\n\n/** TCP state 0A = LISTEN in /proc/net/tcp[6]. */\nconst PROC_TCP_LISTEN_STATE = \"0A\";\n\n/**\n * Parse /proc/net/tcp or /proc/net/tcp6 content into the set of LISTEN local\n * ports. Format (fixed columns, header line first):\n * sl local_address rem_address st ...\n * 0: 0100007F:0BB8 00000000:0000 0A ...\n * local_address is hex ip:port; st is the hex socket state.\n */\nexport function parseProcNetTcpListeners(content: string): number[] {\n const ports: number[] = [];\n const lines = content.split(\"\\n\");\n for (let i = 1; i < lines.length; i++) {\n const line = lines[i];\n if (!line) continue;\n const cols = line.trim().split(/\\s+/);\n // cols: [sl, local_address, rem_address, st, ...]\n if (cols.length < 4 || cols[3] !== PROC_TCP_LISTEN_STATE) continue;\n const local = cols[1];\n if (!local) continue;\n const portHex = local.split(\":\").pop();\n if (!portHex) continue;\n const port = Number.parseInt(portHex, 16);\n if (Number.isInteger(port) && port >= 1 && port <= 65535) ports.push(port);\n }\n return ports;\n}\n\nconst DEFAULT_PROC_PATHS = [\"/proc/net/tcp\", \"/proc/net/tcp6\"];\n\n/** Union of LISTEN ports across the /proc sources. Null when none is readable\n * (non-Linux host) so the poller can disable itself. */\nexport async function readProcListeningPorts(\n procPaths: readonly string[] = DEFAULT_PROC_PATHS,\n): Promise<Set<number> | null> {\n const ports = new Set<number>();\n let readable = false;\n for (const path of procPaths) {\n try {\n const content = await readFile(path, \"utf8\");\n readable = true;\n for (const port of parseProcNetTcpListeners(content)) ports.add(port);\n } catch {\n // Missing tcp6 (or non-Linux) — try the next source.\n }\n }\n return readable ? ports : null;\n}\n\n/** darwin fallback for local dev/tests: parse `netstat -an -p tcp` LISTEN\n * rows (local address column ends in `.<port>`). Never used on pods. */\nasync function readNetstatListeningPorts(): Promise<Set<number> | null> {\n const output = await new Promise<string | null>((resolve) => {\n execFile(\"netstat\", [\"-an\", \"-p\", \"tcp\"], { timeout: 5000 }, (err, stdout) => {\n resolve(err ? null : stdout);\n });\n });\n if (output === null) return null;\n const ports = new Set<number>();\n for (const line of output.split(\"\\n\")) {\n if (!line.includes(\"LISTEN\")) continue;\n const cols = line.trim().split(/\\s+/);\n const local = cols[3];\n if (!local) continue;\n const portStr = local.split(\".\").pop();\n const port = Number(portStr);\n if (Number.isInteger(port) && port >= 1 && port <= 65535) ports.add(port);\n }\n return ports;\n}\n\n/** Platform-appropriate scan: /proc on Linux, netstat elsewhere (dev only). */\nexport async function readListeningPorts(): Promise<Set<number> | null> {\n const proc = await readProcListeningPorts();\n if (proc !== null) return proc;\n if (process.platform !== \"linux\") return readNetstatListeningPorts();\n return null;\n}\n\n// ── Poller ──────────────────────────────────────────────────────────────────\n\n/** Ports that are never preview candidates even when bound after baseline:\n * pod sshd (2222) plus the DB/cache sidecars the API also deny-lists\n * (authoritative filter is server-side; this is defense in depth). */\nconst DEFAULT_EXCLUDED_PORTS: readonly number[] = [2222, 5432, 6379, 9200];\n\n/** Linux's default ip_local_port_range lower bound. LISTEN sockets up here\n * are almost always transient auto-assigned ports (debug adapters, test\n * runners binding :0), not dev servers a human wants previewed. */\nconst DEFAULT_EPHEMERAL_PORT_MIN = 32768;\n\nconst DEFAULT_INTERVAL_MS = 15_000;\nconst DEFAULT_MAX_PORTS = 16;\n/** A port must survive this many consecutive scans to be reported, and be\n * absent this many to be dropped — filters processes that bind briefly. */\nconst CONFIRM_SCANS = 2;\n\nexport interface PortDiscoveryOptions {\n /** Push the FULL current confirmed set (called only on change). */\n report: (ports: WorkspaceDiscoveredPort[]) => Promise<void>;\n intervalMs?: number;\n maxPorts?: number;\n excludedPorts?: readonly number[];\n /** Ports >= this are ignored as transient/ephemeral. Tests override. */\n ephemeralPortMin?: number;\n /** Scan override for tests; defaults to the platform scanner. */\n scan?: () => Promise<Set<number> | null>;\n now?: () => Date;\n log?: (message: string) => void;\n}\n\ninterface TrackedPort {\n /** Consecutive scans the port has been present (seen) or absent (missed). */\n seen: number;\n missed: number;\n confirmed: boolean;\n detectedAt: string;\n}\n\nexport class PortDiscovery {\n private readonly opts: Required<Pick<PortDiscoveryOptions, \"report\">> & PortDiscoveryOptions;\n private readonly intervalMs: number;\n private readonly maxPorts: number;\n private readonly excluded: Set<number>;\n private readonly ephemeralPortMin: number;\n private readonly scan: () => Promise<Set<number> | null>;\n private readonly now: () => Date;\n private readonly log: (message: string) => void;\n\n private baseline: Set<number> | null = null;\n private readonly tracked = new Map<number, TrackedPort>();\n private timer: ReturnType<typeof setInterval> | null = null;\n private ticking = false;\n private disabled = false;\n /** Set when the confirmed set changed (or a report failed) — cleared only\n * after a successful report, so transient RPC failures retry next tick. */\n private reportPending = false;\n private lastReportedKey = \"\";\n\n constructor(options: PortDiscoveryOptions) {\n this.opts = options;\n this.intervalMs = options.intervalMs ?? DEFAULT_INTERVAL_MS;\n this.maxPorts = options.maxPorts ?? DEFAULT_MAX_PORTS;\n this.excluded = new Set(options.excludedPorts ?? DEFAULT_EXCLUDED_PORTS);\n this.ephemeralPortMin = options.ephemeralPortMin ?? DEFAULT_EPHEMERAL_PORT_MIN;\n this.scan = options.scan ?? readListeningPorts;\n this.now = options.now ?? (() => new Date());\n this.log = options.log ?? ((m) => process.stderr.write(`[conveyor-agent] ${m}\\n`));\n }\n\n /** Take the baseline scan and start polling. Safe to call once. */\n async start(): Promise<void> {\n if (this.timer || this.disabled) return;\n const baseline = await this.scanSafe();\n if (baseline === null) {\n // No readable socket source on this host — permanently disable.\n this.disabled = true;\n this.log(\"Port discovery disabled: no listening-socket source available\");\n return;\n }\n this.baseline = baseline;\n this.timer = setInterval(() => void this.tick(), this.intervalMs);\n // Do not hold the process open for the poller.\n this.timer.unref?.();\n }\n\n stop(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n }\n\n /** One poll cycle. Exposed for tests (deterministic, no timers needed). */\n async tick(): Promise<void> {\n if (this.ticking || this.disabled || !this.baseline) return;\n this.ticking = true;\n try {\n const current = await this.scanSafe();\n // Transient read failure — retry next tick.\n if (current === null) return;\n this.updateTracking(current);\n if (this.reportPending) await this.flushReport();\n } finally {\n this.ticking = false;\n }\n }\n\n private async scanSafe(): Promise<Set<number> | null> {\n try {\n return await this.scan();\n } catch {\n return null;\n }\n }\n\n private isCandidate(port: number): boolean {\n if (this.baseline?.has(port)) return false;\n if (this.excluded.has(port)) return false;\n if (port >= this.ephemeralPortMin) return false;\n return true;\n }\n\n private updateTracking(current: Set<number>): void {\n for (const port of current) {\n if (!this.isCandidate(port)) continue;\n const entry = this.tracked.get(port);\n if (!entry) {\n this.tracked.set(port, { seen: 1, missed: 0, confirmed: false, detectedAt: \"\" });\n continue;\n }\n entry.seen += 1;\n entry.missed = 0;\n if (!entry.confirmed && entry.seen >= CONFIRM_SCANS) {\n entry.confirmed = true;\n entry.detectedAt = this.now().toISOString();\n }\n }\n for (const [port, entry] of this.tracked) {\n if (current.has(port)) continue;\n entry.missed += 1;\n entry.seen = 0;\n if (entry.missed >= CONFIRM_SCANS || !entry.confirmed) this.tracked.delete(port);\n }\n const key = this.confirmedKey();\n if (key !== this.lastReportedKey) this.reportPending = true;\n }\n\n private confirmedPorts(): WorkspaceDiscoveredPort[] {\n const confirmed = [...this.tracked.entries()]\n .filter(([, entry]) => entry.confirmed)\n .sort(([a], [b]) => a - b)\n .slice(0, this.maxPorts);\n return confirmed.map(([port, entry]) => ({\n port,\n protocol: \"tcp\" as const,\n detectedAt: entry.detectedAt,\n }));\n }\n\n private confirmedKey(): string {\n return this.confirmedPorts()\n .map(({ port }) => port)\n .join(\",\");\n }\n\n private async flushReport(): Promise<void> {\n const ports = this.confirmedPorts();\n const key = ports.map(({ port }) => port).join(\",\");\n try {\n await this.opts.report(ports);\n this.lastReportedKey = key;\n this.reportPending = false;\n this.log(`Discovered preview ports: [${key || \"none\"}]`);\n } catch {\n // Keep reportPending set — retried on the next tick.\n }\n }\n}\n","import { execSync } from \"node:child_process\";\nimport { getCurrentBranch, hasUncommittedChanges } from \"./git-utils.js\";\n\n/**\n * Handler for `session:pullBranch` events. Fired against a parent task's\n * connected session when a child PR merges into the parent's branch (feature\n * branch packs). Performs a fast-forward `git pull` of the parent's own\n * branch so the workspace and preview reflect merged child work.\n *\n * No-op (with a warning) if the workspace is dirty or on a different branch —\n * we never want to surprise the agent or the user by overwriting in-flight work.\n */\nexport function handlePullBranch(workDir: string, branch: string): void {\n if (!branch) return;\n\n const current = getCurrentBranch(workDir);\n if (current !== branch) {\n process.stderr.write(\n `[conveyor-agent] pull_branch ignored — current branch ${current ?? \"(detached)\"} != ${branch}\\n`,\n );\n return;\n }\n\n if (hasUncommittedChanges(workDir)) {\n process.stderr.write(\n `[conveyor-agent] pull_branch ignored — uncommitted changes on ${branch}\\n`,\n );\n return;\n }\n\n try {\n execSync(`git fetch origin ${branch}`, { cwd: workDir, stdio: \"ignore\", timeout: 60_000 });\n } catch {\n process.stderr.write(`[conveyor-agent] pull_branch: fetch failed for ${branch}\\n`);\n return;\n }\n\n try {\n execSync(`git pull --ff-only origin ${branch}`, {\n cwd: workDir,\n stdio: \"ignore\",\n timeout: 60_000,\n });\n process.stderr.write(`[conveyor-agent] pull_branch: pulled origin/${branch}\\n`);\n } catch {\n process.stderr.write(\n `[conveyor-agent] pull_branch: ff-only pull failed for ${branch} (likely diverged)\\n`,\n );\n }\n}\n","/* oxlint-disable max-lines, import/max-dependencies -- lifecycle orchestrator, splitting would scatter tightly-coupled control flow; the WorkPreservation import pushes it one over the dependency cap */\nimport type { AgentRunnerStatus, AgentMode, TaskContext, TaskContextDTO } from \"@project/shared\";\nimport { DEFAULT_SONNET_MODEL } from \"@project/shared\";\nimport {\n AgentConnection,\n type AgentConnectionConfig,\n type IncomingMessage,\n} from \"../connection/agent-connection.js\";\nimport { ModeController, type ModeTaskContext } from \"./mode-controller.js\";\nimport { Lifecycle, DEFAULT_LIFECYCLE_CONFIG, type LifecycleConfig } from \"./lifecycle.js\";\nimport { QueryBridge } from \"./query-bridge.js\";\nimport type { AgentRunnerConfig } from \"../types.js\";\nimport {\n syncWithBaseBranch,\n ensureOnTaskBranch,\n flushAllPendingWork,\n restoreWipSnapshot,\n updateRemoteToken,\n} from \"./git-utils.js\";\nimport { mapChatHistory, readAgentVersion } from \"./session-runner-helpers.js\";\nimport { awaitGitReady } from \"../setup/git-ready.js\";\nimport { PortDiscovery } from \"./port-discovery.js\";\nimport { restoreOnBoot, uploadSnapshotToGcs, finalizeForSleep } from \"./work-preservation/index.js\";\nimport { handlePullBranch } from \"./parent-pull-handler.js\";\nimport { ensureClaudeCredentials, removeConveyorCredentials } from \"../harness/pty/credentials.js\";\n\n// ── Configuration ──────────────────────────────────────────────────────────\n\nexport interface SessionRunnerConfig {\n connection: AgentConnectionConfig;\n agentMode?: AgentMode;\n runnerMode?: \"task\" | \"pm\" | \"code-review\";\n isAuto?: boolean;\n workspaceDir: string;\n model?: string;\n lifecycle?: Partial<LifecycleConfig>;\n}\n\nexport interface SessionRunnerCallbacks {\n onStatusChange: (status: AgentRunnerStatus) => void | Promise<void>;\n onEvent: (event: Record<string, unknown>) => void | Promise<void>;\n}\n\n/** True for the `post_to_chat` tool by either its bare name or its MCP-namespaced\n * form (`mcp__conveyor__post_to_chat`), so detection is harness-agnostic. */\nexport function isPostToChatTool(name: unknown): boolean {\n return typeof name === \"string\" && (name === \"post_to_chat\" || name.endsWith(\"__post_to_chat\"));\n}\n\n// ── SessionRunner: main lifecycle orchestrator ─────────────────────────────\n\nexport class SessionRunner {\n readonly connection: AgentConnection;\n readonly mode: ModeController;\n readonly lifecycle: Lifecycle;\n\n private readonly config: SessionRunnerConfig;\n private readonly callbacks: SessionRunnerCallbacks;\n private _state: AgentRunnerStatus = \"connecting\";\n private stopped = false;\n private interrupted = false;\n /** Defense-in-depth: set when the agent emits a \"completed\" event.\n * Prevents the core loop from processing any further messages. */\n private completedThisTurn = false;\n /** Absolute deadline (ms epoch) at which the dormant idle wait must time\n * out. Set on the FIRST entry into dormant idle for a given completion\n * cycle and preserved across iterations so inbound critical messages\n * cannot extend the bound past the configured `dormantTimeoutMs`. Reset\n * to null when the agent transitions out of dormant idle (a wake actually\n * promotes it back to a working turn). */\n private dormantDeadline: number | null = null;\n\n private taskContext: ModeTaskContext | null = null;\n private fullContext: TaskContext | null = null;\n private queryBridge: QueryBridge | null = null;\n private inputResolver: ((msg: IncomingMessage | null) => void) | null = null;\n private pendingMessages: IncomingMessage[] = [];\n private prNudgeCount = 0;\n /** Set when the agent posts a substantive message to the task chat (the\n * `post_to_chat` tool) during the current turn; reset at the start of every\n * query. Read by the stuck-detection: an auto agent that finished without a\n * PR but DID explain itself / ask for help in chat is waiting on a human,\n * not silently stuck, so it is left attached rather than nudged. */\n private agentSpokeThisTurn = false;\n /** Guards overlapping runs of the periodic git flush. */\n private periodicFlushInFlight = false;\n /** Runtime preview-port poller (v3 dynamic port discovery). */\n private portDiscovery: PortDiscovery | null = null;\n\n constructor(config: SessionRunnerConfig, callbacks: SessionRunnerCallbacks) {\n this.config = config;\n this.callbacks = callbacks;\n\n // Compose components\n this.connection = new AgentConnection(config.connection);\n\n const initialMode =\n config.agentMode ??\n (config.runnerMode === \"pm\" ? (config.isAuto ? \"auto\" : \"discovery\") : \"building\");\n this.mode = new ModeController(initialMode, config.runnerMode, config.isAuto);\n\n const lifecycleConfig = { ...DEFAULT_LIFECYCLE_CONFIG, ...config.lifecycle };\n this.lifecycle = new Lifecycle(lifecycleConfig, {\n onHeartbeat: () => this.connection.sendHeartbeat(),\n onIdleTimeout: () => {\n process.stderr.write(\"[conveyor-agent] Idle timeout reached, stopping agent\\n\");\n this.stopped = true;\n // A prefilled initial query parks inside executeQuery (no\n // inputResolver) — abort it so the wait actually ends.\n this.queryBridge?.stop();\n if (this.inputResolver) {\n const resolver = this.inputResolver;\n this.inputResolver = null;\n resolver(null);\n }\n },\n onDormantTimeout: () => {\n process.stderr.write(\"[conveyor-agent] Dormant idle timeout reached, shutting down\\n\");\n this.stopped = true;\n this.queryBridge?.stop();\n if (this.inputResolver) {\n const resolver = this.inputResolver;\n this.inputResolver = null;\n resolver(null);\n }\n },\n onTokenRefresh: () => void this.refreshGithubToken(),\n onGitFlush: () => void this.periodicGitFlush(),\n });\n }\n\n get state(): AgentRunnerStatus {\n return this._state;\n }\n\n get sessionId(): string {\n return this.connection.sessionId;\n }\n\n get isStopped(): boolean {\n return this.stopped;\n }\n\n // ── Main lifecycle ─────────────────────────────────────────────────\n\n /**\n * Establish the API connection, wire callbacks, and join the session room.\n * Call this before run() when you need to send events (e.g. setup/start\n * command output) before the main agent lifecycle begins.\n */\n async connect(): Promise<void> {\n await this.setState(\"connecting\");\n\n // 1. Connect\n await this.connection.connect();\n await this.setState(\"connected\");\n this.connection.sendEvent({ type: \"connected\", sessionId: this.sessionId });\n\n // 2. Wire callbacks\n this.wireConnectionCallbacks();\n this.lifecycle.startHeartbeat();\n this.lifecycle.startTokenRefresh();\n // NOTE: the periodic git-flush timer is NOT started here. It touches the\n // repo (git add/stash/reset + force-push conveyor-wip/<branch>) with no\n // git-ready guard of its own, so starting it before `run()`'s\n // `awaitGitReady` gate resolves could race entrypoint.sh's backgrounded\n // checkout/merge (index.lock contention, or a force-push over a\n // not-yet-restored WIP snapshot). It is started in `run()` instead, only\n // once git prep is confirmed ready.\n\n // 2.5. Join session room and retrieve pending messages\n const { pendingMessages: serverMessages } = await this.connection.call(\"connectAgent\", {\n sessionId: this.sessionId,\n });\n for (const msg of serverMessages) {\n if (msg.content) {\n this.pendingMessages.push({ content: msg.content, userId: msg.userId });\n }\n }\n\n // 2.55. Start the preview-port discovery poller. The baseline scan runs\n // NOW — cli.ts kicks off the setup/start commands only after connect()\n // returns, so anything already listening (sshd 2222, sidecars, agent\n // internals) lands in the baseline and is never reported. Fire-and-forget:\n // a host without /proc/net/tcp disables itself.\n this.portDiscovery = new PortDiscovery({\n report: (ports) => this.connection.reportDiscoveredPorts(ports),\n });\n void this.portDiscovery.start().catch(() => {});\n\n // 2.6. Fire-and-forget: tell the API our agent version. If a newer\n // @rallycry/conveyor-agent is on NPM, the API will queue a base image\n // rebuild for the project (deduped per-project across concurrent agents).\n // We continue running with the current version regardless.\n const agentVersion = readAgentVersion();\n if (agentVersion) {\n this.connection\n .call(\"notifyAgentVersion\", { sessionId: this.sessionId, agentVersion })\n .catch(() => {\n // Best-effort — don't block agent startup if NPM lookup or rebuild fails\n });\n }\n }\n\n /**\n * Run the main agent lifecycle: fetch context, resolve mode, execute, loop.\n * Requires connect() to have been called first.\n */\n // oxlint-disable-next-line max-lines-per-function, complexity -- lifecycle orchestration is inherently sequential\n async run(): Promise<void> {\n // 3. Fetch context\n await this.setState(\"fetching_context\");\n try {\n const ctx = await this.connection.call(\"getTaskContext\", {\n sessionId: this.sessionId,\n includeHistory: true,\n });\n this.fullContext = this.buildFullContext(ctx);\n this.taskContext = {\n status: ctx.status,\n plan: ctx.plan,\n storyPointId:\n ctx.storyPoints === null || ctx.storyPoints === undefined\n ? null\n : String(ctx.storyPoints),\n model: ctx.model,\n githubPRUrl: ctx.githubPRUrl,\n isParentTask: this.fullContext.isParentTask,\n };\n } catch (error) {\n const message = error instanceof Error ? error.message : \"Failed to fetch task context\";\n this.connection.sendEvent({ type: \"error\", message });\n await this.callbacks.onEvent({ type: \"error\", message });\n await this.shutdown(\"error\");\n return;\n }\n\n // 3.5. Initial git setup. In claudespace v3, entrypoint.sh runs the\n // fetch + checkout + merge in the BACKGROUND (so the card lights up before\n // git finishes) and signals completion via a marker file. Gate Claude on\n // that marker: it must never spawn on a stale branch. `awaitGitReady`\n // returns \"not-gated\" immediately when no marker is configured (GitHub\n // Codespaces / local), preserving those environments' own git-sync below.\n const gitState = await awaitGitReady({\n onLog: (m) => process.stderr.write(`[conveyor-agent] ${m}\\n`),\n });\n if (gitState === \"failed\" || gitState === \"timeout\") {\n const message =\n gitState === \"failed\"\n ? \"Workspace git preparation failed (see pod logs)\"\n : \"Workspace git preparation timed out (see pod logs)\";\n this.connection.sendEvent({ type: \"error\", message });\n await this.callbacks.onEvent({ type: \"error\", message });\n // Do NOT spawn Claude on a broken/absent repo — mirror the context-fetch\n // failure handling above.\n await this.shutdown(\"error\");\n return;\n }\n\n // Entrypoint sets CONVEYOR_GIT_READY=1 when bash owns the git block. For\n // GitHub Codespaces / local dev (not gated), fall through and sync here.\n // This in-line checkout/merge must run BEFORE the WIP flush timer is armed\n // (below): the flush takes .git/index.lock and force-pushes\n // conveyor-wip/<branch> with no git-ready guard of its own, so a tick\n // firing mid-`git checkout -B` / merge would contend for index.lock —\n // exactly the race the git-ready reordering was meant to prevent.\n if (process.env.CONVEYOR_GIT_READY !== \"1\") {\n if (this.fullContext?.githubBranch) {\n ensureOnTaskBranch(this.config.workspaceDir, this.fullContext.githubBranch);\n }\n if (this.fullContext?.baseBranch) {\n syncWithBaseBranch(this.config.workspaceDir, this.fullContext.baseBranch);\n }\n }\n\n // Git prep is confirmed ready — the gated (v3) path had its entrypoint git\n // block complete before CONVEYOR_GIT_READY=1 (the invariant awaitGitReady\n // waits on), and the non-gated in-line checkout/merge above has now\n // finished — so it is finally safe to arm the periodic WIP flush timer.\n // Starting it any earlier (e.g. in connect(), or before the block above)\n // races either entrypoint.sh's backgrounded checkout/merge or the in-line\n // sync: the flush takes .git/index.lock and force-pushes\n // conveyor-wip/<branch> with no git-ready guard of its own. Skip arming it\n // if the runner is already stopping (e.g. idle/dormant timeout fired while\n // we were gated on git). `startGitFlush()` internally stops any prior timer\n // first, so even if this were reached twice there is no double-start.\n if (!this.stopped) {\n this.lifecycle.startGitFlush();\n }\n\n // 3.6. Recover uncommitted work a previous pod snapshotted before dying.\n // v3 pods (CONVEYOR_SNAPSHOT_URL from the bootstrap bundle) restore with\n // GCS-then-wip precedence via WorkPreservation; otherwise the wip ref\n // alone (the parent-HEAD guard makes a stale snapshot a no-op).\n if (this.fullContext?.githubBranch) {\n const snapshotUrl = process.env.CONVEYOR_SNAPSHOT_URL;\n if (snapshotUrl) {\n const restore = await restoreOnBoot(\n { snapshotUrl, gitPlan: { branch: this.fullContext.githubBranch } },\n this.config.workspaceDir,\n );\n if (restore.source !== \"clean\") {\n process.stderr.write(\n `[conveyor-agent] WorkPreservation restore: source=${restore.source}${\n restore.fileCount === undefined ? \"\" : ` files=${restore.fileCount}`\n }\\n`,\n );\n }\n } else {\n const restored = restoreWipSnapshot(\n this.config.workspaceDir,\n this.fullContext.githubBranch,\n );\n if (restored !== \"none\") {\n process.stderr.write(`[conveyor-agent] WIP snapshot restore: ${restored}\\n`);\n }\n }\n }\n\n // 4. Reconcile mode from server context (overrides env-var defaults)\n this.mode.applyServerMode(this.fullContext?.agentMode, this.fullContext?.isAuto);\n this.mode.resolveInitialMode(this.taskContext);\n\n // 4.1. When canBypassPlanning triggers for an auto task in \"Open\", the server\n // needs to transition the task to InProgress. Fire-and-forget — the agent\n // proceeds to build regardless; the status update is best-effort.\n if (\n this.fullContext?.isAuto &&\n this.taskContext.status === \"Open\" &&\n this.mode.isBuildCapable\n ) {\n void this.connection.triggerIdentification().catch(() => {});\n }\n\n // 4.5. Create query bridge for SDK execution\n this.queryBridge = this.createQueryBridge();\n\n // 5. Log initialization\n this.logInitialization();\n\n // 6. Execute initial mode\n const staleBatch = [...this.pendingMessages];\n const didExecuteInitialQuery = await this.executeInitialMode();\n\n // Clear stale pending messages from connectAgent — they were already\n // included in the initial task context (chat history). Any messages\n // that arrived via live socket events DURING initial mode are not in\n // the snapshot, so they survive. Removal is by object identity because\n // executeInitialMode may itself consume/fold entries (prefill paths).\n // Only splice when the initial mode actually ran a query (auto/building/\n // review/pack/prefill) — modes like discovery skip the query, so pending\n // messages must be retained for the core loop to process.\n if (staleBatch.length > 0 && didExecuteInitialQuery) {\n for (const stale of staleBatch) {\n const idx = this.pendingMessages.indexOf(stale);\n if (idx !== -1) this.pendingMessages.splice(idx, 1);\n }\n }\n\n // Discovery ExitPlanMode during the (prefilled) initial query: planning is\n // done and the runner falls through to the normal idle wait below. Clear\n // the flag so a later follow-up's completion isn't mistaken for a fresh\n // discovery completion (which would drain pending messages in coreLoop).\n if (this.queryBridge?.isDiscoveryCompleted) {\n process.stderr.write(\n \"[conveyor-agent] Discovery completed during initial query — entering idle\\n\",\n );\n this.queryBridge.isDiscoveryCompleted = false;\n }\n\n // 6.5. Auto-mode stuck check: if the agent finished without a PR and didn't\n // explain itself in chat, nudge it (or stay attached for a human).\n // Skip if a user message arrived during initial execution (it interrupted the query)\n if (!this.stopped && this.pendingMessages.length === 0) {\n await this.maybeHandleStuckAuto();\n }\n\n // 7. Core loop: idle → message → execute → idle\n if (!this.stopped) {\n process.stderr.write(\n `[conveyor-agent] Listening for messages (mode: ${this.mode.effectiveMode})\\n`,\n );\n }\n while (!this.stopped) {\n if (this._state !== \"idle\") await this.setState(\"idle\");\n await this.coreLoop();\n }\n\n // 8. Shutdown\n await this.shutdown(\"finished\");\n }\n\n /** Convenience wrapper: connect() then run(). */\n async start(): Promise<void> {\n await this.connect();\n await this.run();\n }\n\n // ── Core loop ──────────────────────────────────────────────────────\n\n // oxlint-disable-next-line complexity -- dormant idle paths add branches but are tightly coupled to the loop\n private async coreLoop(): Promise<void> {\n while (!this.stopped) {\n // Defense-in-depth: if the agent already emitted a \"completed\" event,\n // stop the loop. The server-side guard should prevent messages from\n // reaching us, but if one leaks through, this prevents the completion\n // cycle (agent says \"done\" → system message → agent says \"done\" → …).\n if (this.completedThisTurn) {\n const resumed = await this.handleDormantIdle();\n if (!resumed) break;\n continue;\n }\n if (this._state === \"idle\") {\n this.lifecycle.startIdleTimer();\n const msg = await this.waitForMessage();\n this.lifecycle.cancelIdleTimer();\n\n if (!msg) {\n if (this.interrupted && !this.stopped) {\n this.interrupted = false;\n continue;\n }\n break;\n }\n\n this.interrupted = false;\n await this.callbacks.onEvent({\n type: \"user_message\",\n content: msg.content,\n userId: msg.userId,\n });\n\n // Execute the Claude SDK query with the user's message. A hinted\n // refine message parks in the TUI input for the human instead of\n // auto-submitting.\n if (this.prefillEligible(msg)) {\n await this.runPrefilledMessage(msg, this.mode.effectiveMode);\n } else {\n await this.setState(\"running\");\n await this.executeQuery(msg.content);\n }\n\n // Discovery ExitPlanMode: agent completed its plan — shut down cleanly.\n // No idle state, no message waiting, no chance of being re-woken.\n if (this.queryBridge?.isDiscoveryCompleted) {\n process.stderr.write(\n \"[conveyor-agent] Discovery completed — entering dormant idle (staying connected)\\n\",\n );\n this.pendingMessages.length = 0;\n if (this._state !== \"idle\") await this.setState(\"idle\");\n const discoveryMsg = await this.waitForMessage();\n if (!discoveryMsg) break;\n process.stderr.write(\n \"[conveyor-agent] Received message while discovery-dormant, resuming\\n\",\n );\n this.queryBridge.isDiscoveryCompleted = false;\n this.completedThisTurn = false;\n this.pendingMessages.unshift(discoveryMsg);\n continue;\n }\n\n if (this.stopped) break;\n if (this.interrupted) {\n this.interrupted = false;\n continue;\n }\n\n // After user message execution, run the auto-mode stuck check.\n // Skip if a new message arrived during execution (it interrupted the query)\n if (!this.stopped && this.pendingMessages.length === 0) {\n await this.maybeHandleStuckAuto();\n }\n if (!this.stopped) await this.setState(\"idle\");\n } else if (this._state === \"error\") {\n await this.setState(\"idle\");\n } else {\n break;\n }\n }\n }\n\n /**\n * Handle dormant-after-completed idle. Returns true if a critical message\n * woke us (caller should `continue` the loop), false if we should break\n * (stop signal or dormant timeout fired).\n *\n * The absolute deadline is set on first entry per completion cycle and\n * preserved across re-entries: an inbound critical message cannot extend\n * the bound past `dormantTimeoutMs`. Only a genuine wake (clearing\n * `completedThisTurn`) resets the deadline so the next dormant entry\n * starts a fresh window.\n */\n private async handleDormantIdle(): Promise<boolean> {\n if (this.dormantDeadline === null) {\n this.dormantDeadline = Date.now() + this.lifecycle.config.dormantTimeoutMs;\n process.stderr.write(\n \"[conveyor-agent] Completed — entering dormant idle (staying connected)\\n\",\n );\n }\n this.pendingMessages.length = 0;\n if (this._state !== \"idle\") await this.setState(\"idle\");\n const remainingMs = Math.max(0, this.dormantDeadline - Date.now());\n this.lifecycle.startDormantTimer(remainingMs);\n const dormantMsg = await this.waitForMessage();\n this.lifecycle.cancelDormantTimer();\n if (!dormantMsg) return false;\n const contentPreview =\n dormantMsg.content.length > 80 ? `${dormantMsg.content.slice(0, 80)}...` : dormantMsg.content;\n process.stderr.write(\n `[conveyor-agent] Received message while dormant, resuming: ` +\n `userId=${dormantMsg.userId}, source=${dormantMsg.source || \"unknown\"}, ` +\n `content=\"${contentPreview.replace(/\\n/g, \"\\\\n\")}\"\\n`,\n );\n this.completedThisTurn = false;\n this.dormantDeadline = null;\n this.pendingMessages.unshift(dormantMsg);\n return true;\n }\n\n // ── Initial mode execution ─────────────────────────────────────────\n\n /** Returns true if an initial query was executed, false otherwise. */\n private async executeInitialMode(): Promise<boolean> {\n if (!this.taskContext || !this.fullContext) return false;\n const effectiveMode = this.mode.effectiveMode;\n\n const intrinsicDelivery = this.queryBridge?.initialPromptDelivery(this.fullContext) ?? \"submit\";\n\n // A single hinted message (Refine → Discovery/Review while the pod was\n // down) parks in the TUI input instead of auto-submitting.\n const hinted = this.prepareInitialPendingMessages(intrinsicDelivery);\n if (hinted) {\n await this.runPrefilledMessage(hinted, effectiveMode);\n return true;\n }\n\n // Remaining pending chat messages already direct the agent (they arrived\n // before it booted) — force submit semantics so they aren't parked behind\n // an unsubmitted prefill: building/review run the initial query as before,\n // discovery falls through to the core loop which processes them.\n const delivery = this.pendingMessages.length > 0 ? \"submit\" : intrinsicDelivery;\n\n // Submit modes auto-run their initial instructions. Prefill (PTY task\n // chat, manual mode, fresh session) spawns the TUI for ALL modes —\n // including discovery/help, which never auto-run — with the instructions\n // pre-filled and unsubmitted for the human.\n const shouldRun =\n effectiveMode === \"building\" ||\n effectiveMode === \"auto\" ||\n effectiveMode === \"review\" ||\n delivery === \"prefill\";\n\n if (!shouldRun) {\n await this.setState(\"idle\");\n return false;\n }\n\n if (delivery === \"prefill\") {\n // The query parks until the human submits in the TUI. Report\n // waiting_for_input (not running) and bound the wait with the idle\n // timer; the first harness event flips state to running via the\n // onStatusChange hook in createQueryBridge, cancelling the timer.\n await this.setState(\"waiting_for_input\");\n await this.callbacks.onEvent({ type: \"execute_mode\", mode: effectiveMode, delivery });\n // A chat message may have raced the awaits above — let coreLoop process\n // it instead of parking it behind an unsubmitted prefill.\n if (this.pendingMessages.length > 0) {\n if (!this.stopped) await this.setState(\"idle\");\n return false;\n }\n this.lifecycle.startIdleTimer();\n try {\n await this.executeQuery(undefined, delivery);\n } finally {\n this.lifecycle.cancelIdleTimer();\n }\n } else {\n await this.setState(\"running\");\n await this.callbacks.onEvent({ type: \"execute_mode\", mode: effectiveMode });\n await this.executeQuery(undefined, delivery);\n }\n if (!this.stopped) await this.setState(\"idle\");\n return true;\n }\n\n // ── Prefill-delivery helpers ───────────────────────────────────────\n\n /**\n * Startup-queue preamble: the card's initial message reaches a fresh pod\n * twice — inside the task context (chat history) AND as a queued pending\n * message. When the intrinsic delivery is prefill (manual-mode fresh TUI)\n * or a hinted message is queued (Refine), drop those context-duplicates so\n * they don't force submit semantics — a genuinely-new live message still\n * does. Returns the lone hinted message to park, if any.\n */\n private prepareInitialPendingMessages(\n intrinsicDelivery: \"submit\" | \"prefill\",\n ): IncomingMessage | null {\n const hasHintedPending = this.pendingMessages.some((m) => m.delivery === \"prefill\");\n if (this.pendingMessages.length > 0 && (intrinsicDelivery === \"prefill\" || hasHintedPending)) {\n this.foldContextDuplicatePendingMessages();\n }\n return this.takePrefillHintedMessage();\n }\n\n /**\n * Drop pending messages whose content is already present as a user message\n * in the task-context chat history (the card's initial message is delivered\n * both ways). Hinted (prefill) messages are kept — they are consumed by the\n * dedicated prefill path.\n */\n private foldContextDuplicatePendingMessages(): void {\n const userContents = new Set(\n (this.fullContext?.chatHistory ?? [])\n .filter((m) => m.role === \"user\" && m.content.trim())\n .map((m) => m.content.trim()),\n );\n const kept = this.pendingMessages.filter(\n (m) => m.delivery === \"prefill\" || !m.content.trim() || !userContents.has(m.content.trim()),\n );\n const dropped = this.pendingMessages.length - kept.length;\n if (dropped > 0) {\n this.pendingMessages.length = 0;\n this.pendingMessages.push(...kept);\n process.stderr.write(\n `[conveyor-agent] Folded ${dropped} pending message(s) already present in chat context\\n`,\n );\n }\n }\n\n /**\n * Honor a prefill hint only when it is unambiguous: PTY harness, a manual\n * (human-facing) agent mode, no other message queued behind it, and not an\n * automated-critical source. Everything else keeps submit semantics.\n */\n private prefillEligible(msg: IncomingMessage): boolean {\n if (msg.delivery !== \"prefill\") return false;\n if (this.pendingMessages.length > 0) return false;\n if (this.queryBridge?.harnessKind !== \"pty\") return false;\n // Auto cards must never park a prefill in the TUI — the whole point of auto\n // is to submit and keep working, and a parked prefill blocks the human from\n // typing a follow-up. Submit instead.\n if (this.mode.isAuto) return false;\n // \"user\" is the queue-flush default source; \"mode_change\" is the refine\n // wake. Anything else (system/ci_failure/review_trigger/…) must submit.\n if (msg.source && msg.source !== \"mode_change\" && msg.source !== \"user\") return false;\n // Manual modes only.\n const m = this.mode.effectiveMode;\n return m === \"discovery\" || m === \"review\" || m === \"help\";\n }\n\n /** Consume the sole pending message when it should park as a prefill. */\n private takePrefillHintedMessage(): IncomingMessage | null {\n if (this.pendingMessages.length !== 1) return null;\n const [first] = this.pendingMessages;\n if (!first || first.delivery !== \"prefill\") return null;\n this.pendingMessages.length = 0;\n if (this.prefillEligible(first)) return first;\n this.pendingMessages.push(first);\n return null;\n }\n\n /**\n * Park a message in the Connected-TUI input (prefill) and wait for the human\n * to submit. Empty content prefills the mode's initial prompt instead (the\n * latest user chat message — e.g. a Refine wake on a dormant agent). The\n * caller restores the idle state afterwards.\n */\n private async runPrefilledMessage(msg: IncomingMessage, effectiveMode: AgentMode): Promise<void> {\n await this.setState(\"waiting_for_input\");\n await this.callbacks.onEvent({\n type: \"execute_mode\",\n mode: effectiveMode,\n delivery: \"prefill\",\n });\n this.lifecycle.startIdleTimer();\n try {\n await this.executeQuery(msg.content.trim() ? msg.content : undefined, \"prefill\");\n } finally {\n this.lifecycle.cancelIdleTimer();\n }\n }\n\n // ── Message waiting ────────────────────────────────────────────────\n\n private waitForMessage(): Promise<IncomingMessage | null> {\n if (this.pendingMessages.length > 0) {\n return Promise.resolve(this.pendingMessages.shift() ?? null);\n }\n return new Promise<IncomingMessage | null>((resolve) => {\n this.inputResolver = resolve;\n });\n }\n\n /** Inject a message (from connection callback or external source) */\n injectMessage(msg: IncomingMessage): void {\n if (this.inputResolver) {\n const resolve = this.inputResolver;\n this.inputResolver = null;\n resolve(msg);\n } else {\n this.pendingMessages.push(msg);\n // Interrupt running query so the new message is processed quickly.\n // waiting_for_input covers a prefilled-but-unsubmitted TUI: the chat\n // message supersedes the prefill (teardown + respawn as follow-up).\n if (this._state === \"running\" || this._state === \"waiting_for_input\") {\n this.queryBridge?.stop();\n }\n }\n }\n\n // ── Query execution with abort handling ────────────────────────────\n\n /** Run queryBridge.execute, swallowing abort errors from stop/softStop. */\n private async executeQuery(\n followUpContent?: string,\n promptDelivery?: \"submit\" | \"prefill\",\n ): Promise<void> {\n if (!this.fullContext || !this.queryBridge) return;\n // Reset the per-turn \"agent communicated in chat\" signal so the\n // stuck-detection only sees post_to_chat activity from THIS turn.\n this.agentSpokeThisTurn = false;\n try {\n await this.queryBridge.execute(this.fullContext, followUpContent, promptDelivery);\n } catch (err) {\n if (this.interrupted || this.stopped) {\n process.stderr.write(\"[conveyor-agent] Query aborted by stop/softStop signal\\n\");\n return;\n }\n throw err;\n }\n }\n\n // ── Stop / soft-stop ───────────────────────────────────────────────\n\n /** Periodic best-effort WIP commit + push during normal agent execution.\n * Covers ungraceful pod termination (OOMKilled, node crash/eviction) where\n * the preStop hook + SIGTERM flush don't get a chance to run. No-ops on a\n * clean tree. Guarded so two ticks can't overlap. Never throws. */\n private async periodicGitFlush(): Promise<void> {\n if (this.periodicFlushInFlight || this.stopped) return;\n this.periodicFlushInFlight = true;\n try {\n const result = await flushAllPendingWork(this.config.workspaceDir, {\n wipMessage: \"WIP: periodic auto-commit\",\n refreshToken: async () => {\n try {\n const res = await this.connection.call(\"refreshGithubToken\", {\n sessionId: this.connection.sessionId,\n });\n return res.token;\n } catch {\n return undefined;\n }\n },\n });\n if (result.hadWork) {\n process.stderr.write(\n `[conveyor-agent] Periodic git flush: branchesBackedUp=${result.branchesBackedUp} worktreesSnapshotted=${result.worktreesSnapshotted}\\n`,\n );\n }\n // v3 GCS tier rides the SAME trigger as the git tier (one capture\n // cadence, two sinks — never two racing snapshotters).\n await this.uploadGcsSnapshotIfConfigured();\n } catch {\n // best effort — next tick will retry\n } finally {\n this.periodicFlushInFlight = false;\n }\n }\n\n /** PUT the WorkPreservation snapshot tar to the bundle's capability URL\n * when this pod is v3 (CONVEYOR_SNAPSHOT_UPLOAD_URL set). Never throws. */\n private async uploadGcsSnapshotIfConfigured(): Promise<void> {\n const uploadUrl = process.env.CONVEYOR_SNAPSHOT_UPLOAD_URL;\n if (!uploadUrl) return;\n try {\n const gcs = await uploadSnapshotToGcs(this.config.workspaceDir, uploadUrl);\n if (gcs.uploaded) {\n process.stderr.write(\n `[conveyor-agent] WorkPreservation GCS snapshot: files=${gcs.fileCount} bytes=${gcs.sizeBytes}\\n`,\n );\n }\n } catch {\n // best effort — the wip tier already preserved this generation\n }\n }\n\n /** Best-effort WIP commit + push on shutdown so in-flight work isn't lost\n * when a claudespace pod is killed. Must be called BEFORE stop() so the\n * connection is still alive for token refresh. Never throws. */\n async flushGitOnShutdown(): Promise<void> {\n try {\n const result = await flushAllPendingWork(this.config.workspaceDir, {\n wipMessage: \"WIP: auto-commit on conveyor-agent shutdown\",\n refreshToken: async () => {\n try {\n const res = await this.connection.call(\"refreshGithubToken\", {\n sessionId: this.connection.sessionId,\n });\n return res.token;\n } catch {\n return undefined;\n }\n },\n });\n if (result.hadWork) {\n process.stderr.write(\n `[conveyor-agent] Shutdown git flush: branchesBackedUp=${result.branchesBackedUp} worktreesSnapshotted=${result.worktreesSnapshotted}\\n`,\n );\n }\n // Final GCS capture so a stopping v3 pod leaves a restorable snapshot.\n await this.uploadGcsSnapshotIfConfigured();\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[conveyor-agent] Shutdown git flush failed: ${msg}\\n`);\n }\n }\n\n stop(): void {\n this.stopped = true;\n this.queryBridge?.stop();\n this.portDiscovery?.stop();\n this.lifecycle.destroy();\n this.connection.disconnect();\n if (this.inputResolver) {\n const resolver = this.inputResolver;\n this.inputResolver = null;\n resolver(null);\n }\n }\n\n softStop(): void {\n this.interrupted = true;\n this.queryBridge?.stop();\n // Only null-resolve if no flushed messages are already pending — a message\n // arriving via injectMessage() before the soft stop signal means the agent\n // should process it instead of discarding with a null resolution.\n if (this.inputResolver && this.pendingMessages.length === 0) {\n const resolver = this.inputResolver;\n this.inputResolver = null;\n resolver(null);\n }\n }\n\n // ── Auto-mode stuck detection & nudge ───────────────────────────────\n\n private static readonly MAX_STUCK_NUDGES = 3;\n\n /** The prompt delivered into the live TUI when an auto agent looks stuck. It\n * must offer BOTH escape routes so the agent never just goes idle. */\n private static readonly STUCK_PROMPT =\n \"You are in Auto mode, your task is still In Progress, and there is no open pull request. \" +\n \"Do ONE of these right now: (1) open a pull request with the create_pull_request tool, OR \" +\n \"(2) call post_to_chat to explain exactly where you are stuck and what you need from a human. \" +\n \"Do not finish or go idle silently.\";\n\n /**\n * An auto task is \"stuck\" when its last turn ended (the call sites run\n * post-turn, so the TUI is no longer actively working), it has no open PR,\n * AND the agent did not communicate in chat this turn. If the agent posted a\n * message (explained itself / asked for help) it is waiting on a human, not\n * silently stuck, so we leave it attached instead of nudging.\n */\n private isAutoStuck(): boolean {\n if (!this.mode.isAuto || this.stopped) return false;\n if (this.queryBridge?.wasRateLimited) return false;\n if (this.prNudgeCount > SessionRunner.MAX_STUCK_NUDGES) return false;\n if (this.agentSpokeThisTurn) return false;\n if (!this.taskContext) return false;\n return this.taskContext.status === \"InProgress\" && !this.taskContext.githubPRUrl;\n }\n\n /**\n * Stop driving the agent and route the core loop into dormant idle —\n * connected and attachable, but NOT running (so no tokens are spent while it\n * waits). A human reply (chat or TUI keystroke after the next wake) resumes\n * it. This replaces the old hard `stop()`: the auto agent must never kill its\n * own session, so a person can always take over.\n */\n private enterDormantForHumanTakeover(message: string): void {\n this.connection.postChatMessage(message);\n this.completedThisTurn = true;\n void this.connection.sendHeartbeat();\n }\n\n private async refreshTaskContext(): Promise<void> {\n try {\n const ctx = await this.connection.call(\"getTaskContext\", {\n sessionId: this.sessionId,\n includeHistory: false,\n });\n this.taskContext = {\n status: ctx.status,\n plan: ctx.plan,\n storyPointId:\n ctx.storyPoints === null || ctx.storyPoints === undefined\n ? null\n : String(ctx.storyPoints),\n model: ctx.model,\n githubPRUrl: ctx.githubPRUrl,\n };\n // Keep fullContext in sync for PR nudge execution\n if (this.fullContext) {\n this.fullContext.status = ctx.status;\n this.fullContext.plan = ctx.plan;\n this.fullContext.githubPRUrl = ctx.githubPRUrl;\n this.fullContext.model = ctx.model;\n }\n } catch {\n // Continue with stale context\n }\n }\n\n private async maybeHandleStuckAuto(): Promise<void> {\n await this.refreshTaskContext();\n if (!this.isAutoStuck()) return;\n\n while (!this.stopped && !this.interrupted && this.isAutoStuck()) {\n this.prNudgeCount++;\n\n if (this.prNudgeCount > SessionRunner.MAX_STUCK_NUDGES) {\n // Out of nudges and still no PR — DON'T shut down. Stay attached and\n // ask for a human; the agent goes dormant (not running) until someone\n // replies in chat or the TUI.\n this.enterDormantForHumanTakeover(\n `Auto-mode: I couldn't open a PR or get unstuck after ${SessionRunner.MAX_STUCK_NUDGES} attempts. ` +\n \"Staying connected — reply here or in the terminal and I'll keep working.\",\n );\n return;\n }\n\n const attempt = this.prNudgeCount;\n const chatMsg =\n attempt === 1\n ? \"Auto-nudge: still In Progress with no PR — prompting the agent to finish or explain where it's stuck...\"\n : `Auto-nudge (attempt ${attempt}/${SessionRunner.MAX_STUCK_NUDGES}): still no PR — prompting the agent again...`;\n\n this.connection.postChatMessage(chatMsg);\n await this.setState(\"running\");\n // The nudge is delivered to the live TUI via executeQuery so the agent\n // keeps working; the event lets the API/UI surface the nudge too.\n await this.callbacks.onEvent({ type: \"pr_nudge\", prompt: SessionRunner.STUCK_PROMPT });\n\n if (this.interrupted || this.stopped) return;\n await this.executeQuery(SessionRunner.STUCK_PROMPT);\n if (this.interrupted || this.stopped) return;\n\n await this.refreshTaskContext();\n\n // The agent explained itself / asked for help in chat this turn (and still\n // has no PR) → it's waiting on a human. Stop nudging and stay attached.\n if (this.agentSpokeThisTurn && !this.taskContext?.githubPRUrl) {\n this.enterDormantForHumanTakeover(\n \"Auto-mode: the agent posted an update and is waiting for input. \" +\n \"Staying connected — reply here or in the terminal to continue.\",\n );\n return;\n }\n }\n }\n\n // ── Context & bridge construction ────────────────────────────────\n\n // oxlint-disable-next-line complexity\n private buildFullContext(ctx: TaskContextDTO): TaskContext {\n const chatHistory = mapChatHistory(ctx.chatHistory);\n\n return {\n taskId: ctx.id,\n projectId: ctx.projectId ?? \"\",\n title: ctx.title,\n description: ctx.description,\n plan: ctx.plan,\n status: ctx.status,\n chatHistory,\n agentId: ctx.agentId ?? null,\n _runnerSessionId: this.sessionId,\n agentInstructions: ctx.agentInstructions ?? \"\",\n model: ctx.model,\n githubBranch: ctx.githubBranch ?? \"\",\n baseBranch: ctx.baseBranch ?? \"\",\n projectName: ctx.projectName ?? null,\n projectDescription: ctx.projectDescription ?? null,\n githubPRUrl: ctx.githubPRUrl,\n claudeSessionId: ctx.claudeSessionId ?? null,\n lastSeenMessageId: ctx.lastSeenMessageId ?? null,\n isParentTask: !!ctx.parentTaskId,\n storyPoints: ctx.storyPoints ?? undefined,\n projectAgents: ctx.projectAgents ?? undefined,\n projectTags: ctx.projectTags ?? undefined,\n taskTagIds: ctx.taskTagIds ?? undefined,\n projectObjectives: ctx.projectObjectives ?? undefined,\n incidents: ctx.incidents ?? undefined,\n recentRelatedTasks: ctx.recentRelatedTasks ?? undefined,\n agentSettings: ctx.agentSettings ?? null,\n agentMode: ctx.agentMode ?? undefined,\n isAuto: ctx.isAuto,\n };\n }\n\n private createQueryBridge(): QueryBridge {\n const runnerConfig: AgentRunnerConfig = {\n conveyorApiUrl: this.config.connection.apiUrl,\n taskToken: this.config.connection.taskToken,\n taskId: this.fullContext?.taskId ?? \"\",\n model: this.fullContext?.model ?? DEFAULT_SONNET_MODEL,\n instructions: this.fullContext?.agentInstructions ?? \"\",\n workspaceDir: this.config.workspaceDir,\n mode: this.config.runnerMode,\n isAuto: this.config.isAuto,\n };\n\n const bridge = new QueryBridge(\n this.connection,\n this.mode,\n runnerConfig,\n {\n onStatusChange: (status) => {\n // A prefilled initial query reports running when the human submits\n // in the TUI (first harness event) — leave waiting_for_input and\n // stop the prefill-wait idle timer so a long working turn isn't\n // killed by it.\n if (status === \"running\" && this._state === \"waiting_for_input\") {\n this._state = \"running\";\n this.lifecycle.cancelIdleTimer();\n }\n return this.callbacks.onStatusChange(status as AgentRunnerStatus);\n },\n onEvent: (event) => {\n // Track when the agent posts a substantive message to chat this turn\n // (the `post_to_chat` MCP tool — namespaced `mcp__conveyor__post_to_chat`\n // under the PTY harness). This is the \"Chat has a recent message from\n // the Agent\" signal the stuck-detection uses; the runner's own system\n // nudges go via a different path (postChatMessage) and never appear here.\n const evt = event as { type?: string; tool?: string };\n if (evt.type === \"tool_use\" && isPostToChatTool(evt.tool)) {\n this.agentSpokeThisTurn = true;\n }\n // Track completion for the agent-side guard — once the agent emits\n // \"completed\", the core loop will stop accepting further messages.\n if ((event as Record<string, unknown>).type === \"completed\") {\n this.completedThisTurn = true;\n // Immediately refresh the server's heartbeat timestamp so\n // lastHeartbeatAt can't drift stale while the agent sits dormant\n // waiting for a critical wake-up (e.g. review_trigger). The\n // periodic 30s timer would otherwise leave up to a ~29s gap\n // between the `completed` event and the next heartbeat.\n void this.connection.sendHeartbeat();\n }\n return this.callbacks.onEvent(event);\n },\n },\n this.config.workspaceDir,\n );\n\n bridge.isParentTask = this.fullContext?.isParentTask ?? false;\n bridge.onSoftStop = () => {\n process.stderr.write(\"[conveyor-agent] Soft stop requested (discovery ExitPlanMode)\\n\");\n this.softStop();\n };\n\n bridge.onModeTransition = (newMode: AgentMode) => {\n const oldMode = this.mode.effectiveMode;\n process.stderr.write(`[conveyor-agent] Mode transition: ${oldMode} → ${newMode}\\n`);\n this.connection.sendEvent({ type: \"mode_transition\", from: oldMode, to: newMode });\n this.mode.pendingModeRestart = true;\n this.connection.emitModeChanged(newMode);\n this.softStop();\n };\n\n return bridge;\n }\n\n // ── Private helpers ────────────────────────────────────────────────\n\n private wireConnectionCallbacks(): void {\n this.connection.onMessage((msg) => this.injectMessage(msg));\n this.connection.onStop(() => this.stop());\n this.connection.onSoftStop(() => this.softStop());\n // After a reconnect the API process may be a fresh instance (deploy,\n // restart) whose PTY scrollback ring is empty — force a repaint so the\n // Connected-TUI terminal re-seeds instead of staying blank/hidden until\n // the CLI happens to draw again.\n this.connection.onReconnected = () => this.queryBridge?.forceRepaint();\n this.connection.onModeChange((data) => {\n const action = this.mode.handleModeChange(data.agentMode);\n if (action.type === \"start_auto\") {\n this.connection.emitModeChanged(this.mode.effectiveMode);\n this.softStop();\n } else if (action.type === \"restart_query\") {\n // Server-initiated mode transition (e.g., CI-triggered review).\n // Clear claudeSessionId to prevent SDK resume across model changes\n // (reviewer agent may use a different model than the task agent).\n if (this.fullContext && action.newMode === \"review\") {\n this.fullContext.claudeSessionId = null;\n }\n // On building transition, re-fetch context to pick up the newly created\n // branch (branch creation is deferred until building mode).\n // Also refresh for \"auto\" post-exit (defense-in-depth if \"auto\" leaks through).\n if (\n this.fullContext &&\n (action.newMode === \"building\" ||\n (action.newMode === \"auto\" && this.mode.hasExitedPlanMode))\n ) {\n void this.refreshBranchForBuilding();\n }\n // Exit dormant idle so the review_trigger message that follows\n // is processed in the normal idle path (which handles interrupted\n // correctly without draining pendingMessages).\n this.completedThisTurn = false;\n this.connection.emitModeChanged(action.newMode);\n this.softStop();\n }\n });\n this.connection.onApiKeyUpdate((data) => {\n if (data.isSubscription) {\n process.env.CLAUDE_CODE_OAUTH_TOKEN = data.apiKey;\n delete process.env.ANTHROPIC_API_KEY;\n // The interactive TUI reads credentials from disk, not the env var —\n // refresh the synthesized file so the next PTY spawn (and any on-401\n // re-read by a live CLI) picks up the rotated subscription token.\n void ensureClaudeCredentials();\n } else {\n process.env.ANTHROPIC_API_KEY = data.apiKey;\n delete process.env.CLAUDE_CODE_OAUTH_TOKEN;\n // Drop our synthesized subscription credentials so a stale token\n // can't keep authenticating future TUI spawns over the API key.\n void removeConveyorCredentials();\n }\n });\n this.connection.onPullBranch(({ branch }) => {\n handlePullBranch(this.config.workspaceDir, branch);\n });\n this.connection.onFinalizeSnapshot(() => void this.finalizeSnapshotNow());\n }\n\n /** Eager finalize snapshot triggered by the reconciler's sleep signal\n * (session:finalizeSnapshot). Runs pg_dump + a full capture and uploads it\n * NOW so the sleep confirms on this snapshot instead of waiting for the\n * ~2min periodic flush — and so sidecar DB state (which ONLY finalizeForSleep\n * captures via pg_dump) actually lands. Best-effort: on failure the\n * periodic/shutdown path stays the fallback. No-op on non-v3 pods. */\n private async finalizeSnapshotNow(): Promise<void> {\n const uploadUrl = process.env.CONVEYOR_SNAPSHOT_UPLOAD_URL;\n if (!uploadUrl || this.stopped) return;\n try {\n await finalizeForSleep({\n cwd: this.config.workspaceDir,\n branch: this.fullContext?.githubBranch ?? \"\",\n snapshotUploadUrl: uploadUrl,\n refreshToken: async () => {\n try {\n const res = await this.connection.call(\"refreshGithubToken\", {\n sessionId: this.connection.sessionId,\n });\n return res.token;\n } catch {\n return undefined;\n }\n },\n });\n process.stderr.write(\n \"[conveyor-agent] Finalize snapshot (pg_dump) uploaded on sleep signal\\n\",\n );\n } catch {\n // best-effort — periodic/shutdown snapshot remains the fallback\n }\n }\n\n /** Proactively refresh the GitHub token before the 1-hour expiry. */\n private async refreshGithubToken(): Promise<void> {\n try {\n const res = await this.connection.call(\"refreshGithubToken\", {\n sessionId: this.connection.sessionId,\n });\n updateRemoteToken(this.config.workspaceDir, res.token);\n process.env.GITHUB_TOKEN = res.token;\n process.env.GH_TOKEN = res.token;\n process.stderr.write(\"[conveyor-agent] Proactively refreshed GitHub token\\n\");\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n process.stderr.write(`[conveyor-agent] Warning: proactive token refresh failed: ${msg}\\n`);\n }\n }\n\n /** Re-fetch task context to pick up a newly created branch and check it out. */\n private async refreshBranchForBuilding(): Promise<void> {\n try {\n const ctx = await this.connection.call(\"getTaskContext\", {\n sessionId: this.sessionId,\n includeHistory: false,\n });\n if (ctx?.githubBranch && this.fullContext) {\n this.fullContext.githubBranch = ctx.githubBranch;\n ensureOnTaskBranch(this.config.workspaceDir, ctx.githubBranch);\n }\n } catch {\n process.stderr.write(\n \"[conveyor-agent] Warning: failed to refresh branch for building transition\\n\",\n );\n }\n }\n\n private async setState(status: AgentRunnerStatus): Promise<void> {\n this._state = status;\n await this.connection.emitStatus(status);\n await this.callbacks.onStatusChange(status);\n }\n\n private async shutdown(finalState: AgentRunnerStatus): Promise<void> {\n process.stderr.write(`[conveyor-agent] Shutdown: reason=${finalState}\\n`);\n this.connection.sendEvent({ type: \"shutdown\", reason: finalState });\n this.portDiscovery?.stop();\n this.lifecycle.destroy();\n try {\n await this.setState(finalState);\n } catch {\n // Best effort — when stop() already tore down the connection the status\n // RPC rejects. A stopped agent should still finish run() cleanly so the\n // process exits 0 instead of taking the error path.\n }\n this.connection.disconnect();\n this._finalState = finalState;\n }\n\n private _finalState: AgentRunnerStatus | null = null;\n\n /** The final status after run() completes. Use to determine exit code. */\n get finalState(): AgentRunnerStatus | null {\n return this._finalState;\n }\n\n private buildTaskContextSnapshot(): Record<string, unknown> {\n return {\n isParentTask: this.fullContext?.isParentTask ?? false,\n status: this.taskContext?.status,\n taskTitle: this.fullContext?.title,\n hasExistingPR: !!this.fullContext?.githubPRUrl,\n hasExistingSession: !!this.fullContext?.claudeSessionId,\n chatHistoryLength: this.fullContext?.chatHistory?.length ?? 0,\n tagIds: this.fullContext?.taskTagIds ?? [],\n };\n }\n\n private buildInitializationContext(): Record<string, unknown> {\n return {\n mode: this.mode.effectiveMode,\n runnerMode: this.config.runnerMode ?? \"task\",\n sessionId: this.sessionId,\n ...this.buildTaskContextSnapshot(),\n model: this.taskContext?.model,\n isAuto: this.config.isAuto ?? false,\n subscriptionKeyLabel: process.env.CONVEYOR_SUBSCRIPTION_KEY_LABEL ?? null,\n };\n }\n\n private logInitialization(): void {\n const context = this.buildInitializationContext();\n process.stderr.write(`[conveyor-agent] Initialized: ${JSON.stringify(context)}\\n`);\n this.connection.sendEvent({ type: \"session_manifest\", ...context });\n }\n}\n","import { readFile } from \"node:fs/promises\";\nimport { join } from \"node:path\";\nimport type { SessionPreviewPort } from \"@project/shared\";\n\nexport interface ConveyorConfig {\n setupCommand?: string;\n startCommand?: string;\n previewPort?: number;\n}\n\nexport interface ForwardPortsResult {\n ports: number[];\n attributes: Record<string, { label?: string; visibility?: \"public\" | \"private\" }>;\n}\n\nconst DEVCONTAINER_PATH = \".devcontainer/conveyor/devcontainer.json\";\n\n/** Ports bound by sidecars (postgres/redis/elasticsearch) — never expose. */\nconst DEVCONTAINER_PORT_DENY_LIST = new Set([5432, 6379, 9200]);\n\nexport async function loadForwardPorts(workspaceDir: string): Promise<ForwardPortsResult> {\n try {\n const raw = await readFile(join(workspaceDir, DEVCONTAINER_PATH), \"utf-8\");\n const parsed = JSON.parse(raw) as {\n forwardPorts?: number[];\n portsAttributes?: Record<string, { label?: string; visibility?: string }>;\n };\n const ports = (parsed.forwardPorts ?? []).filter(\n (p) => typeof p === \"number\" && !DEVCONTAINER_PORT_DENY_LIST.has(p),\n );\n const attributes: ForwardPortsResult[\"attributes\"] = {};\n for (const [key, value] of Object.entries(parsed.portsAttributes ?? {})) {\n if (!value || typeof value !== \"object\") continue;\n const entry: { label?: string; visibility?: \"public\" | \"private\" } = {};\n if (typeof value.label === \"string\") entry.label = value.label;\n if (value.visibility === \"public\" || value.visibility === \"private\") {\n entry.visibility = value.visibility;\n }\n attributes[key] = entry;\n }\n return { ports, attributes };\n } catch {\n return { ports: [], attributes: {} };\n }\n}\n\n/** Merge forwardPorts + portsAttributes into a SessionPreviewPort[] the API\n * can persist directly onto CodespaceSession.previewPorts. Deny-listed\n * ports are filtered (defense-in-depth; authoritative filter lives API-side). */\nexport function buildSessionPreviewPorts(result: ForwardPortsResult): SessionPreviewPort[] {\n return result.ports\n .filter((port) => !DEVCONTAINER_PORT_DENY_LIST.has(port))\n .map((port) => {\n const attr = result.attributes[String(port)];\n const entry: SessionPreviewPort = { port };\n if (attr?.label) entry.label = attr.label;\n if (attr?.visibility) entry.visibility = attr.visibility;\n return entry;\n });\n}\n\n/** Load config from env vars (project-level settings injected via bootstrap). */\nexport function loadConveyorConfig(): ConveyorConfig | null {\n const envSetup = process.env.CONVEYOR_SETUP_COMMAND;\n const envStart = process.env.CONVEYOR_START_COMMAND;\n const envPort = process.env.CONVEYOR_PREVIEW_PORT;\n if (envSetup || envStart) {\n return {\n setupCommand: envSetup,\n startCommand: envStart,\n previewPort: envPort ? Number(envPort) : undefined,\n };\n }\n return null;\n}\n","import { spawn, execSync, type ChildProcess } from \"node:child_process\";\n\nexport function runSetupCommand(\n cmd: string,\n cwd: string,\n onOutput: (stream: \"stdout\" | \"stderr\", data: string) => void,\n): Promise<void> {\n return new Promise((resolve, reject) => {\n const child = spawn(\"sh\", [\"-c\", cmd], {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n env: { ...process.env },\n });\n\n child.stdout.on(\"data\", (chunk: Buffer) => {\n onOutput(\"stdout\", chunk.toString());\n });\n\n child.stderr.on(\"data\", (chunk: Buffer) => {\n onOutput(\"stderr\", chunk.toString());\n });\n\n child.on(\"close\", (code) => {\n if (code === 0) {\n resolve();\n } else {\n reject(new Error(`Setup command exited with code ${code}`));\n }\n });\n\n child.on(\"error\", (err) => {\n reject(err);\n });\n });\n}\n\nconst AUTH_TOKEN_TIMEOUT_MS = 30_000;\n\nexport function runAuthTokenCommand(cmd: string, userEmail: string, cwd: string): string | null {\n try {\n const output = execSync(`${cmd} ${JSON.stringify(userEmail)}`, {\n cwd,\n timeout: AUTH_TOKEN_TIMEOUT_MS,\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n env: { ...process.env },\n });\n const token = output.toString().trim();\n return token || null;\n } catch {\n return null;\n }\n}\n\nexport function runStartCommand(\n cmd: string,\n cwd: string,\n onOutput: (stream: \"stdout\" | \"stderr\", data: string) => void,\n): ChildProcess {\n const child = spawn(\"sh\", [\"-c\", cmd], {\n cwd,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n detached: true,\n env: { ...process.env },\n });\n\n child.stdout.on(\"data\", (chunk: Buffer) => {\n onOutput(\"stdout\", chunk.toString());\n });\n\n child.stderr.on(\"data\", (chunk: Buffer) => {\n onOutput(\"stderr\", chunk.toString());\n });\n\n child.unref();\n return child;\n}\n","import { execSync } from \"node:child_process\";\n\n/** Fetch full git history if the repo was cloned with --depth=1. */\nexport function unshallowRepo(workspaceDir: string): void {\n try {\n execSync(\"git fetch --unshallow\", {\n cwd: workspaceDir,\n timeout: 60_000,\n stdio: \"ignore\",\n });\n } catch {\n // Already unshallowed or not a shallow clone\n }\n}\n"],"mappings":"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","names":["sleep","join","join","stat","path","rm","execSync","execSync","stat","writeFile","tmpdir","path","path","execSync","path","tmpdir","writeFile","stat","randomUUID","createReadStream","createWriteStream","rm","tmpdir","path","pipeline","rm","mkdtemp","mkdir","rm","stat","tmpdir","join","path","createServer","writeFile","join","tool","tool","createServer","join","writeFile","isRecord","spawn","sleep","path","stat","mkdtemp","join","tmpdir","mkdir","rm","chmod","mkdir","rm","writeFile","homedir","join","join","path","mkdir","writeFile","chmod","homedir","rm","readFileSync","readFile","stat","stat","readFile","findLastAgentMessageIndex","hasNewUserMessages","parts","z","z","z","z","z","z","result","readFile","stat","join","z","z","path","join","stat","readFile","z","z","z","z","z","SP_DESCRIPTION","z","z","z","isAuthError","result","list","logger","IMAGE_ERROR_PATTERN","RETRY_DELAYS_MS","path","readFileSync","isAuthError","logger","readFileSync","dirname","join","readFile","path","execSync","execSync","readFile","join","execSync","execSync"]}