@rallycry/conveyor-agent 10.13.13 → 10.13.14
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.
- package/dist/{chunk-TB5SQIGX.js → chunk-J4UH5TOO.js} +192 -433
- package/dist/chunk-J4UH5TOO.js.map +1 -0
- package/dist/{chunk-YRC57EYG.js → chunk-LZM5OKAC.js} +2 -68
- package/dist/chunk-LZM5OKAC.js.map +1 -0
- package/dist/{chunk-2K6RRTQC.js → chunk-RSIW2UCR.js} +4 -180
- package/dist/chunk-RSIW2UCR.js.map +1 -0
- package/dist/{chunk-IE7EOKMD.js → chunk-VKZ5W2VO.js} +1 -1
- package/dist/chunk-VKZ5W2VO.js.map +1 -0
- package/dist/cli.js +27 -34
- package/dist/cli.js.map +1 -1
- package/dist/{client-ICIWKSK2.js → client-VQIBGPE6.js} +3 -3
- package/dist/index.d.ts +27 -76
- package/dist/index.js +5 -17
- package/dist/index.js.map +1 -1
- package/dist/{protocol-QJRHTTMQ.js → protocol-IHRTO5C4.js} +2 -2
- package/dist/{server-UGE67KIZ.js → server-TVIXWCAI.js} +7 -72
- package/dist/server-TVIXWCAI.js.map +1 -0
- package/package.json +1 -1
- package/runtime/entrypoint.sh +24 -98
- package/dist/chunk-2K6RRTQC.js.map +0 -1
- package/dist/chunk-IE7EOKMD.js.map +0 -1
- package/dist/chunk-TB5SQIGX.js.map +0 -1
- package/dist/chunk-YRC57EYG.js.map +0 -1
- package/dist/server-UGE67KIZ.js.map +0 -1
- /package/dist/{client-ICIWKSK2.js.map → client-VQIBGPE6.js.map} +0 -0
- /package/dist/{protocol-QJRHTTMQ.js.map → protocol-IHRTO5C4.js.map} +0 -0
package/dist/cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/cli.ts","../src/setup/sidecars.ts","../src/setup/boot-milestone.ts","../src/setup/workspace-command-supervisor.ts","../src/utils/session-identity.ts","../src/utils/agent-exit.ts","../src/setup/project-identity.ts","../src/runner/project-session-runner.ts","../src/usage/multi-key-probe.ts","../src/harness/pty/adapters/opencode-auth.ts","../src/harness/pty/adapters/opencode.ts","../src/harness/pty/adapters/index.ts","../src/tools/project-tools.ts","../src/runner/adhoc-session-runner.ts","../src/runner/review-child.ts","../src/runner/session-child.ts","../src/runner/shell-session-runner.ts","../src/runner/spawned-child-boot.ts"],"sourcesContent":["#!/usr/bin/env node\n/* oxlint-disable import/max-dependencies -- CLI entry point wires every runner variant (task/pm/code-review/adhoc) + setup; splitting would scatter the boot sequence */\nimport { readFileSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { SessionRunner } from \"./runner/session-runner.js\";\nimport type { AgentRunnerStatus, RunnerMode } from \"@project/shared\";\nimport { createServiceLogger } from \"./utils/logger.js\";\nimport { applyBootstrapToEnv, fetchBootstrap, loadConveyorConfig } from \"./setup/index.js\";\nimport {\n startWorkspaceCommandsAfterConnect,\n stopWorkspaceCommands,\n WorkspaceCommandSupervisor,\n} from \"./setup/workspace-command-supervisor.js\";\nimport { checkSessionTaskIdentity } from \"./utils/session-identity.js\";\nimport {\n buildAgentExitLog,\n exitLogLevel,\n type AgentExitIdentity,\n type AgentExitReason,\n} from \"./utils/agent-exit.js\";\nimport { resolveProjectRunnerIdentity } from \"./setup/project-identity.js\";\nimport { ProjectSessionRunner } from \"./runner/project-session-runner.js\";\nimport { AdhocSessionRunner, resolveInitialPrompt } from \"./runner/adhoc-session-runner.js\";\nimport { ReviewChildSupervisor } from \"./runner/review-child.js\";\nimport { SessionChildSupervisor } from \"./runner/session-child.js\";\nimport { createSpawnedChildRunner } from \"./runner/spawned-child-boot.js\";\n\n// Handle --version flag before any other initialization\nif (process.argv.includes(\"--version\")) {\n const __dirname = dirname(fileURLToPath(import.meta.url));\n const pkgPath = join(__dirname, \"..\", \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n process.stdout.write(pkg.version + \"\\n\");\n process.exit(0);\n}\n\nconst logger = createServiceLogger(\"CLI\");\n\n// Pod-exit observability. The reconciler can only infer *that* an agent stopped\n// (stale heartbeat → Stranded); it never sees *why*. We log the cause from the\n// pod side at every catchable exit, keyed on the same sessionId the API's\n// `session_stranded` line carries so the two ends can be joined. Populated once\n// env identity resolves below; the early crash handlers read it live. (SIGKILL /\n// OOM 137 is uncatchable — diagnosed from GKE kernel logs, not this line.)\nconst exitContext: AgentExitIdentity = {};\nlet exitLogged = false;\nfunction logAgentExit(\n reason: AgentExitReason,\n opts: { exitCode: number; signal?: string; finalState?: string },\n): void {\n // One line per process death; force_timeout is logged separately (it escalates\n // an already-logged signal shutdown) so it bypasses this guard at its call site.\n if (exitLogged) return;\n exitLogged = true;\n const payload = buildAgentExitLog({\n reason,\n exitCode: opts.exitCode,\n signal: opts.signal,\n finalState: opts.finalState,\n uptimeSec: process.uptime(),\n identity: exitContext,\n });\n logger[exitLogLevel(reason)](\"agent_exit\", payload as unknown as Record<string, unknown>);\n}\n\nasync function bootstrapFromCodespace(apiUrl: string, instanceName: string): Promise<void> {\n const bootstrapToken = process.env.CONVEYOR_BOOTSTRAP_TOKEN;\n const apiUrlFromEnv = Boolean(process.env.CONVEYOR_API_URL);\n logger.info(\"Bootstrapping from codespace\", {\n codespace: instanceName,\n apiUrl,\n apiUrlFromEnv,\n bootstrapTokenPresent: Boolean(bootstrapToken),\n });\n const result = await fetchBootstrap({\n apiUrl,\n instanceName,\n bootstrapToken,\n });\n if (!result.ok) {\n logger.error(\"Bootstrap failed after retries\", {\n reason: result.reason,\n attempts: result.attempts,\n status: result.status,\n detail: result.detail,\n apiUrl,\n apiUrlFromEnv,\n bootstrapTokenPresent: Boolean(bootstrapToken),\n hint: apiUrlFromEnv\n ? \"Verify the codespace was created by this Conveyor deployment and that the bootstrap token is current.\"\n : \"CONVEYOR_API_URL was not set as a codespace secret — agent fell back to the built-in default. Re-create the codespace, or push CONVEYOR_API_URL via project settings.\",\n });\n process.exit(1);\n }\n applyBootstrapToEnv(result.config);\n logger.info(\"Bootstrap complete\", {\n taskId: result.config.taskId,\n attempts: result.attempts,\n });\n}\n\n// Helper to detect expected abort errors from SDK cleanup\nfunction isExpectedAbortError(error: Error | NodeJS.ErrnoException): boolean {\n const message = error.message || \"\";\n const hasAbortMessage = /operation aborted/i.test(message) || /abort/i.test(message);\n const hasAbortCode = !(\"code\" in error) || error.code === undefined || error.code === \"ABORT_ERR\";\n return hasAbortMessage && hasAbortCode;\n}\n\nprocess.on(\"uncaughtException\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EPIPE\") return;\n\n if (isExpectedAbortError(err)) {\n logger.info(\"Ignored expected abort after shutdown\", { error: err.message, code: err.code });\n return;\n }\n\n logger.error(\"Uncaught exception\", { error: err.message, code: err.code });\n logAgentExit(\"uncaught_exception\", { exitCode: 1 });\n process.exit(1);\n});\n\nprocess.on(\"unhandledRejection\", (reason: unknown) => {\n const err = reason instanceof Error ? reason : new Error(String(reason));\n\n if (isExpectedAbortError(err)) {\n logger.info(\"Ignored expected abort rejection after shutdown\", { error: err.message });\n return;\n }\n\n logger.error(\"Unhandled rejection\", { error: err.message });\n logAgentExit(\"unhandled_rejection\", { exitCode: 1 });\n process.exit(1);\n});\n\n// Step 0: workbench launcher (split-mode pods). The workbench container runs\n// ONLY the exec daemon — no task token, no bootstrap, no runner lifecycle.\n// Checked before everything so it never falls through to the task paths.\nif (process.env.CONVEYOR_MODE === \"workbench\") {\n const { startWorkbenchServer } = await import(\"./workbench/server.js\");\n const { DEFAULT_WORKBENCH_PORT } = await import(\"./workbench/protocol.js\");\n const port = Number(process.env.CONVEYOR_WORKBENCH_PORT) || DEFAULT_WORKBENCH_PORT;\n const token = process.env.CONVEYOR_WORKBENCH_TOKEN ?? process.env.POD_BOOTSTRAP_TOKEN ?? \"\";\n if (!token) {\n logger.error(\"workbench mode requires POD_BOOTSTRAP_TOKEN (or CONVEYOR_WORKBENCH_TOKEN)\");\n process.exit(1);\n }\n const pkgDir = dirname(fileURLToPath(import.meta.url));\n const pkg = JSON.parse(readFileSync(join(pkgDir, \"..\", \"package.json\"), \"utf-8\")) as {\n version?: string;\n };\n const handle = await startWorkbenchServer({\n port,\n token,\n version: pkg.version ?? \"unknown\",\n });\n logger.info(`Workbench launcher listening on 127.0.0.1:${handle.port}`);\n // Park forever — the kubelet owns this container's lifecycle (native\n // sidecar, restartPolicy Always); SIGTERM just exits.\n process.on(\"SIGTERM\", () => process.exit(0));\n await new Promise(() => {});\n}\n\nconst DEFAULT_CONVEYOR_API_URL = \"https://api.conveyor.rallycryapp.com\";\nlet conveyorApiUrl = process.env.CONVEYOR_API_URL || DEFAULT_CONVEYOR_API_URL;\n\n// Step 1: Codespace bootstrap\nconst INSTANCE_NAME = process.env.CODESPACE_NAME || process.env.CLAUDESPACE_NAME;\nif (INSTANCE_NAME && !process.env.CONVEYOR_TASK_TOKEN) {\n if (!conveyorApiUrl) {\n logger.error(\"Could not resolve CONVEYOR_API_URL for codespace bootstrap\");\n process.exit(1);\n }\n await bootstrapFromCodespace(conveyorApiUrl, INSTANCE_NAME);\n conveyorApiUrl = process.env.CONVEYOR_API_URL ?? conveyorApiUrl;\n}\n\n// Step 2: Read env vars (bootstrap may have set them)\nconst CONVEYOR_TASK_TOKEN = process.env.CONVEYOR_TASK_TOKEN;\nconst CONVEYOR_TASK_ID = process.env.CONVEYOR_TASK_ID;\nconst CONVEYOR_WORKSPACE = process.env.CONVEYOR_WORKSPACE ?? process.cwd();\nconst CONVEYOR_MODE = (process.env.CONVEYOR_MODE ?? \"task\") as RunnerMode;\nconst CONVEYOR_AGENT_MODE = process.env.CONVEYOR_AGENT_MODE || undefined;\nconst CONVEYOR_IS_AUTO = CONVEYOR_AGENT_MODE\n ? CONVEYOR_AGENT_MODE === \"auto\"\n : process.env.CONVEYOR_IS_AUTO === \"true\";\n\n// Seed the pod-exit identity now that env is resolved (the specific runner\n// branches below refine sessionId/workspaceId to their own session).\nexitContext.taskId = CONVEYOR_TASK_ID;\nexitContext.workspaceId = process.env.CONVEYOR_WORKSPACE_ID;\nexitContext.runnerMode = CONVEYOR_MODE;\nexitContext.sessionId = process.env.CONVEYOR_SESSION_ID ?? CONVEYOR_TASK_ID;\n\n// Step 2.5: task-less PROJECT pods (Claudespace v3 project runners). The\n// bundle's session JWT carries {projectId, sessionId} and NO taskId; the\n// entrypoint exports CONVEYOR_PROJECT_ID (no CONVEYOR_TASK_ID) and sets\n// CONVEYOR_MODE=pm. Boot the project runner: connect + register session +\n// heartbeat + idle awaiting project-scoped messages. Never falls through to\n// the task lifecycle below.\nconst projectIdentity = resolveProjectRunnerIdentity(process.env);\n\n// Task-less ADHOC pods (Sessions view scratch pods). Same task-less identity as\n// a project pod (projectId + sessionId, no taskId), distinguished by\n// CONVEYOR_MODE=adhoc. Runs an interactive `claude` TUI relayed to the web\n// terminal — NOT the autonomous pm project runner below. Checked first so an\n// adhoc session never falls through to pm.\nif (!CONVEYOR_TASK_ID && projectIdentity && CONVEYOR_MODE === \"adhoc\") {\n logger.info(\"Starting ad-hoc agent\", { projectId: projectIdentity.projectId });\n const adhocRunner = new AdhocSessionRunner(\n {\n connection: {\n apiUrl: conveyorApiUrl ?? \"\",\n taskToken: projectIdentity.taskToken,\n sessionId: projectIdentity.sessionId,\n runnerMode: \"adhoc\",\n },\n projectId: projectIdentity.projectId,\n workspaceId: projectIdentity.workspaceId,\n workspaceDir: CONVEYOR_WORKSPACE,\n // Headless sessions: un-submitted audit instructions from the bundle.\n // Resolved ONLY here — spawned same-pod tabs must not inherit them.\n initialPrompt: resolveInitialPrompt(process.env),\n ...(process.env.CLAUDESPACE_NAME ? { lifecycle: { idleTimeoutMs: 60 * 60 * 1000 } } : {}),\n },\n {\n onEvent: (event) => {\n logger.info(\"Ad-hoc runner event\", { eventType: event.type as string });\n },\n },\n );\n exitContext.sessionId = projectIdentity.sessionId;\n exitContext.workspaceId = projectIdentity.workspaceId;\n exitContext.runnerMode = \"adhoc\";\n process.on(\"SIGTERM\", () => adhocRunner.stop());\n process.on(\"SIGINT\", () => adhocRunner.stop());\n await adhocRunner.run();\n const adhocError = adhocRunner.finalState === \"error\";\n logAgentExit(adhocError ? \"error\" : \"clean\", {\n exitCode: adhocError ? 1 : 0,\n finalState: adhocRunner.finalState ?? undefined,\n });\n process.exit(adhocError ? 1 : 0);\n}\n\nif (!CONVEYOR_TASK_ID && projectIdentity) {\n logger.info(\"Starting project agent\", { projectId: projectIdentity.projectId });\n const projectRunner = new ProjectSessionRunner(\n {\n connection: {\n apiUrl: conveyorApiUrl ?? \"\",\n taskToken: projectIdentity.taskToken,\n sessionId: projectIdentity.sessionId,\n runnerMode: \"pm\",\n },\n projectId: projectIdentity.projectId,\n // Same extended idle window claudespace task pods get.\n ...(process.env.CLAUDESPACE_NAME ? { lifecycle: { idleTimeoutMs: 60 * 60 * 1000 } } : {}),\n },\n {\n onEvent: (event) => {\n logger.info(\"Project runner event\", { eventType: event.type as string });\n },\n },\n );\n exitContext.sessionId = projectIdentity.sessionId;\n exitContext.workspaceId = projectIdentity.workspaceId;\n exitContext.runnerMode = \"pm\";\n process.on(\"SIGTERM\", () => projectRunner.stop());\n process.on(\"SIGINT\", () => projectRunner.stop());\n await projectRunner.run();\n const projectError = projectRunner.finalState === \"error\";\n logAgentExit(projectError ? \"error\" : \"clean\", {\n exitCode: projectError ? 1 : 0,\n finalState: projectRunner.finalState ?? undefined,\n });\n process.exit(projectError ? 1 : 0);\n}\n\nif (!CONVEYOR_TASK_TOKEN || !CONVEYOR_TASK_ID) {\n logger.error(\"Missing required environment variables\");\n logger.error(\" CONVEYOR_TASK_TOKEN - JWT token for task authentication\");\n logger.error(\" CONVEYOR_TASK_ID - ID of the task to execute\");\n logger.error(\"\");\n logger.error(\"CONVEYOR_API_URL is provided via codespace secret or bootstrap.\");\n logger.error(\"\");\n logger.error(\"Optional:\");\n logger.error(\" CONVEYOR_MODE - Runner mode: 'task' (default), 'pack', or 'pm'\");\n logger.error(\" CONVEYOR_WORKSPACE - Working directory (defaults to cwd)\");\n logger.error(\n \" Project pods instead require CONVEYOR_PROJECT_ID + CONVEYOR_SESSION_ID + CONVEYOR_MODE=pm\",\n );\n process.exit(1);\n}\n\nif (\n CONVEYOR_MODE !== \"task\" &&\n CONVEYOR_MODE !== \"pm\" &&\n CONVEYOR_MODE !== \"code-review\" &&\n CONVEYOR_MODE !== \"adhoc\" &&\n CONVEYOR_MODE !== \"pack\" &&\n CONVEYOR_MODE !== \"shell\"\n) {\n logger.error(\"Invalid CONVEYOR_MODE\", {\n mode: CONVEYOR_MODE,\n expected: [\"task\", \"pm\", \"code-review\", \"adhoc\", \"pack\", \"shell\"],\n });\n process.exit(1);\n}\n\n// Same-pod spawned children (session:spawnTui): TASK-BOUND extra tabs on the\n// builder's pod — a second Claude TUI (mode \"adhoc\" + a task id, unlike the\n// task-less Sessions-view branch above) or a raw login shell (mode \"shell\").\n// Both bind their own WorkspaceSession via env overrides set by\n// SessionChildSupervisor and never fall through to the task SessionRunner.\nif (CONVEYOR_MODE === \"shell\" || CONVEYOR_MODE === \"adhoc\") {\n const spawnedSessionId = process.env.CONVEYOR_SESSION_ID;\n if (!spawnedSessionId) {\n logger.error(\"Spawned child requires CONVEYOR_SESSION_ID\", { mode: CONVEYOR_MODE });\n process.exit(1);\n }\n exitContext.sessionId = spawnedSessionId;\n exitContext.runnerMode = CONVEYOR_MODE;\n\n const childRunner = createSpawnedChildRunner({\n mode: CONVEYOR_MODE,\n apiUrl: conveyorApiUrl ?? \"\",\n taskToken: CONVEYOR_TASK_TOKEN,\n sessionId: spawnedSessionId,\n workspaceDir: CONVEYOR_WORKSPACE,\n projectId: process.env.CONVEYOR_PROJECT_ID ?? \"\",\n });\n logger.info(\"Starting spawned session child\", {\n mode: CONVEYOR_MODE,\n sessionId: spawnedSessionId,\n });\n process.on(\"SIGTERM\", () => childRunner.stop());\n process.on(\"SIGINT\", () => childRunner.stop());\n await childRunner.run();\n const childError = childRunner.finalState === \"error\";\n logAgentExit(childError ? \"error\" : \"clean\", {\n exitCode: childError ? 1 : 0,\n finalState: childRunner.finalState ?? undefined,\n });\n process.exit(childError ? 1 : 0);\n}\n\nlogger.info(\"Starting agent\", { mode: CONVEYOR_MODE });\n\n// Claudespace pods: longer idle timeout to stay alive for incoming messages.\n// Non-claudespace environments (local, workspace, GitHub Codespaces) have\n// persistent state and don't need the periodic WIP commit safety net, so\n// disable the git flush timer for them.\nconst lifecycleOverrides = process.env.CLAUDESPACE_NAME\n ? { idleTimeoutMs: 60 * 60 * 1000 }\n : { gitFlushIntervalMs: 0 };\n\nconst runner = new SessionRunner(\n {\n connection: {\n apiUrl: conveyorApiUrl ?? \"\",\n taskToken: CONVEYOR_TASK_TOKEN,\n // CONVEYOR_SESSION_ID is the CodespaceSession ID for BaseService ACL.\n // Falls back to CONVEYOR_TASK_ID for backward compat (codespace bootstrap sets only task ID).\n sessionId: process.env.CONVEYOR_SESSION_ID ?? CONVEYOR_TASK_ID,\n runnerMode: CONVEYOR_MODE,\n },\n runnerMode: CONVEYOR_MODE,\n isAuto: CONVEYOR_IS_AUTO,\n workspaceDir: CONVEYOR_WORKSPACE,\n agentMode: CONVEYOR_AGENT_MODE as import(\"@project/shared\").AgentMode | undefined,\n lifecycle: lifecycleOverrides,\n },\n {\n onStatusChange: (status: AgentRunnerStatus) => {\n logger.info(\"Status changed\", { status });\n },\n onEvent: (event: Record<string, unknown>) => {\n const detail =\n (event.message as string) ?? (event.content as string) ?? (event.summary as string) ?? \"\";\n if (detail) {\n logger.info(detail, { eventType: event.type as string });\n }\n },\n },\n);\n\n// Same-pod review children (session:spawnReview). Wired only for the builder\n// (\"task\") runner mode below — a review child must never recursively spawn.\nconst reviewChildren = new ReviewChildSupervisor(runner.connection, CONVEYOR_WORKSPACE);\n\n// Same-pod TUI/shell children (session:spawnTui). Wired for builder-shaped\n// runners (task + pack) below — spawned children run adhoc/shell modes, which\n// exit above before this block, so recursion is impossible.\nconst sessionChildren = new SessionChildSupervisor(runner.connection, CONVEYOR_WORKSPACE);\n\nlet shutdownSignal: \"SIGTERM\" | \"SIGINT\" | undefined;\nlet workspaceCommandSupervisor: WorkspaceCommandSupervisor | null = null;\nlet shutdownCompletion: Promise<void> | null = null;\n\nconst shutdownAgent = (signal: \"SIGTERM\" | \"SIGINT\") => {\n logger.info(`Received ${signal}, flushing git and stopping agent`);\n const commandShutdown = stopWorkspaceCommands(workspaceCommandSupervisor);\n // Recorded (not logged yet) so the final agent_exit line — emitted once the\n // real exit code is known below — can still attribute the cause to this\n // signal. A graceful SIGTERM resolves runner.run() with finalState=\"finished\"\n // and exits 0, so guessing exitCode here up front would misreport it as 1.\n shutdownSignal = signal;\n // Flush WIP commit + push BEFORE stop() tears down the connection, since\n // the token-refresh RPC needs a live socket. Then stop the runner.\n shutdownCompletion ??= (async () => {\n try {\n await Promise.all([reviewChildren.stopAll(), sessionChildren.stopAll()]);\n } catch {\n /* best-effort */\n }\n try {\n await runner.flushGitOnShutdown();\n } finally {\n await commandShutdown;\n runner.stop();\n }\n })();\n void shutdownCompletion;\n setTimeout(() => {\n logger.warn(`Forcing exit after ${signal} timeout`);\n // The graceful flush/stop hung past the watchdog — emit directly (bypassing\n // the one-line guard in logAgentExit) since run() will never resolve to log\n // this exit itself.\n logger.warn(\n \"agent_exit\",\n buildAgentExitLog({\n reason: \"force_timeout\",\n exitCode: 1,\n signal,\n finalState: runner.finalState ?? undefined,\n uptimeSec: process.uptime(),\n identity: exitContext,\n }) as unknown as Record<string, unknown>,\n );\n process.exit(1);\n }, 45_000).unref();\n};\n\nprocess.on(\"SIGTERM\", () => shutdownAgent(\"SIGTERM\"));\nprocess.on(\"SIGINT\", () => shutdownAgent(\"SIGINT\"));\n\n// Connect first so setup/start output is forwarded to the API. The helper does\n// not release commands until preview discovery has captured its baseline and\n// re-checks synchronous shutdown intent after that await.\nworkspaceCommandSupervisor = await startWorkspaceCommandsAfterConnect({\n connect: () => runner.connect(),\n isShuttingDown: () => shutdownSignal !== undefined,\n create: () =>\n new WorkspaceCommandSupervisor({\n config: loadConveyorConfig(),\n workspaceDir: CONVEYOR_WORKSPACE,\n connection: runner.connection,\n }),\n});\nif (!workspaceCommandSupervisor) {\n logger.info(\"Agent stopped before workspace commands were started\");\n if (shutdownCompletion) await shutdownCompletion;\n logAgentExit(shutdownSignal ? \"signal\" : \"clean\", {\n exitCode: 0,\n signal: shutdownSignal,\n finalState: runner.finalState ?? undefined,\n });\n process.exit(0);\n}\n\n// Defense-in-depth: warn loudly if CONVEYOR_SESSION_ID decodes to a different\n// task than CONVEYOR_TASK_ID. Authoritative checks are server-side\n// (requireTaskAuth + partial-unique index on active CodespaceSessions). This\n// is a visibility net in case those regress — see SEC-9 postmortem in\n// .claude/rules/agent-codespace.md.\nvoid checkSessionTaskIdentity({\n sessionId: process.env.CONVEYOR_SESSION_ID,\n taskId: CONVEYOR_TASK_ID,\n fetchSessionTaskId: async (sessionId) => {\n const ctx = await runner.connection.call(\"getTaskContext\", { sessionId });\n return ctx.id;\n },\n logger,\n});\n\n// Same-pod review: only the builder runner hosts review children. The push\n// arrives on the BUILDER's session room; the child binds the review session\n// via env overrides (its own JWT/sessionId, CONVEYOR_MODE=code-review).\nif (CONVEYOR_MODE === \"task\") {\n runner.connection.onSpawnReview((data) => {\n void reviewChildren.spawn(data).catch((err: unknown) => {\n logger.error(\"Review child spawn threw\", {\n error: err instanceof Error ? err.message : String(err),\n });\n runner.connection.reportReviewSpawnFailure(\n data.sessionId,\n err instanceof Error ? err.message : String(err),\n );\n });\n });\n}\n\n// Same-pod TUI/shell tabs: builder-shaped runners (task + pack) host spawned\n// children. The push arrives on the BUILDER's session room; each child binds\n// its own session via env overrides (JWT/sessionId, CONVEYOR_MODE=adhoc|shell).\nif (CONVEYOR_MODE === \"task\" || CONVEYOR_MODE === \"pack\") {\n runner.connection.onSpawnTui((data) => {\n void sessionChildren.spawn(data).catch((err: unknown) => {\n logger.error(\"Session child spawn threw\", {\n error: err instanceof Error ? err.message : String(err),\n });\n runner.connection.reportSessionSpawnFailure(\n data.sessionId,\n err instanceof Error ? err.message : String(err),\n );\n });\n });\n}\n\n// Start the main agent lifecycle immediately in parallel with setup\n// (context fetch, mode resolution, core loop).\nrunner\n .run()\n .then(async () => {\n await stopWorkspaceCommands(workspaceCommandSupervisor);\n // Exit with code 0 for clean shutdown (entrypoint won't restart),\n // code 1 for errors (entrypoint will restart). A SIGTERM-initiated shutdown\n // resolves run() too (finalState=\"finished\"), so tag it \"signal\" rather\n // than \"clean\" — but the exit code still follows the real finalState, not\n // a guess made back when the signal first arrived.\n const errored = runner.finalState === \"error\";\n const reason: AgentExitReason = shutdownSignal ? \"signal\" : errored ? \"error\" : \"clean\";\n logAgentExit(reason, {\n exitCode: errored ? 1 : 0,\n signal: shutdownSignal,\n finalState: runner.finalState ?? undefined,\n });\n process.exit(errored ? 1 : 0);\n })\n .catch(async (error: unknown) => {\n await stopWorkspaceCommands(workspaceCommandSupervisor);\n const msg = error instanceof Error ? error.message : String(error);\n logger.error(\"Agent runner failed\", { error: msg });\n logAgentExit(\"error\", { exitCode: 1, finalState: runner.finalState ?? undefined });\n process.exit(1);\n });\n","import net from \"node:net\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\n\n/**\n * Sidecar readiness gate.\n *\n * Previously the pod entrypoint blocked on postgres/firebase coming up BEFORE it\n * launched the agent, so the agent's thinking loop paid for up to ~60s of\n * sidecar boot it never needed. That wait now lives here and runs inside the\n * agent's background setup IIFE — it gates only `setupCommand`/`startCommand`\n * (which genuinely need a warm postgres), never the agent loop.\n *\n * Semantics deliberately match the old entrypoint: best-effort, NON-FATAL on\n * timeout (log a warning and continue), and a no-op when no sidecar env vars are\n * present. Per-target timeouts mirror what the entrypoint learned the hard way —\n * the firebase auth emulator cold-boots slowly and doesn't bind 9099 until ~50s\n * after its container starts, so it gets 60s.\n *\n * Postgres gets 120s: on a durable-sleep/pool pod the postgres sidecar restores\n * prior state, and an ungraceful previous pod death (e.g. OOMKill) leaves a torn\n * WAL that triggers crash recovery on boot. Cold boot + WAL replay routinely runs\n * past 30s, so the old deadline expired before postgres bound 5432 — setup's seed\n * then hit `DatabaseNotReachable` (P1001) and the whole dev env came up broken.\n */\n\nexport interface SidecarTarget {\n /** Human label for logs (e.g. \"postgres\"). */\n name: string;\n host: string;\n port: number;\n /** Per-target readiness deadline in ms (overridden by an explicit opts.timeoutMs). */\n timeoutMs?: number;\n}\n\nexport interface WaitForSidecarsOptions {\n /** Env to read targets from. Defaults to `process.env`. */\n env?: NodeJS.ProcessEnv;\n /** Progress sink (one line per message, no trailing newline). */\n onLog?: (message: string) => void;\n /** Force a single deadline for every target, overriding per-target defaults. */\n timeoutMs?: number;\n /** Delay between probe attempts in ms. */\n pollIntervalMs?: number;\n /** TCP probe seam — returns true once the target accepts a connection. */\n probe?: (target: SidecarTarget, signal?: AbortSignal) => Promise<boolean>;\n /** Whether to create the lazy sidecar start marker before probing. Defaults to true. */\n startLazy?: boolean;\n /** Optional shutdown signal. Aborting rejects with AbortError. */\n signal?: AbortSignal;\n}\n\nconst POSTGRES_TIMEOUT_MS = 120_000;\nconst FIREBASE_TIMEOUT_MS = 60_000;\nconst FALLBACK_TIMEOUT_MS = 30_000;\nconst DEFAULT_SIDECAR_POLL_INTERVAL_MS = 1_000;\nconst DEFAULT_PROBE_TIMEOUT_MS = 2_000;\n\nconst POSTGRES_DEFAULT_PORT = 5432;\nconst FIREBASE_DEFAULT_PORT = 9099;\n\nexport async function startLazySidecars(\n env: NodeJS.ProcessEnv,\n onLog: (message: string) => void,\n signal?: AbortSignal,\n): Promise<void> {\n throwIfAborted(signal);\n const markerPath = env.CONVEYOR_SIDECAR_START_FILE;\n if (!markerPath) return;\n\n try {\n await mkdir(dirname(markerPath), { recursive: true });\n throwIfAborted(signal);\n await writeFile(markerPath, \"start\\n\", \"utf8\");\n throwIfAborted(signal);\n onLog(\"Started lazy sidecars\");\n } catch (err) {\n if (signal?.aborted) throw abortError();\n const message = err instanceof Error ? err.message : String(err);\n onLog(`WARNING: failed to start lazy sidecars: ${message}`);\n }\n}\n\nfunction parseHostPort(value: string, defaultPort: number): { host: string; port: number } | null {\n const trimmed = value.trim().replace(/^[a-z]+:\\/\\//i, \"\");\n if (!trimmed) return null;\n const idx = trimmed.lastIndexOf(\":\");\n if (idx === -1) {\n return { host: trimmed, port: defaultPort };\n }\n const host = trimmed.slice(0, idx) || \"localhost\";\n const port = Number(trimmed.slice(idx + 1));\n return { host, port: Number.isFinite(port) ? port : defaultPort };\n}\n\n/**\n * Resolve the sidecar targets the agent should wait for from env. Mirrors the\n * entrypoint's conditions: postgres when `DATABASE_URL` is set, firebase auth\n * emulator when `FIREBASE_AUTH_EMULATOR_HOST` is set.\n */\nexport function resolveSidecarTargets(env: NodeJS.ProcessEnv = process.env): SidecarTarget[] {\n const targets: SidecarTarget[] = [];\n\n const databaseUrl = env.DATABASE_URL;\n if (databaseUrl) {\n try {\n const url = new URL(databaseUrl);\n const host = url.hostname || \"localhost\";\n const port = url.port ? Number(url.port) : POSTGRES_DEFAULT_PORT;\n if (Number.isFinite(port)) {\n targets.push({ name: \"postgres\", host, port, timeoutMs: POSTGRES_TIMEOUT_MS });\n }\n } catch {\n // Unparseable DATABASE_URL — skip rather than crash the setup path.\n }\n }\n\n const firebaseHost = env.FIREBASE_AUTH_EMULATOR_HOST;\n if (firebaseHost) {\n const parsed = parseHostPort(firebaseHost, FIREBASE_DEFAULT_PORT);\n if (parsed) {\n targets.push({\n name: \"firebase auth emulator\",\n host: parsed.host,\n port: parsed.port,\n timeoutMs: FIREBASE_TIMEOUT_MS,\n });\n }\n }\n\n return targets;\n}\n\nfunction abortError(): Error {\n const error = new Error(\"Operation aborted\");\n error.name = \"AbortError\";\n return error;\n}\n\nfunction throwIfAborted(signal?: AbortSignal): void {\n if (signal?.aborted) throw abortError();\n}\n\nfunction defaultProbe(target: SidecarTarget, signal?: AbortSignal): Promise<boolean> {\n throwIfAborted(signal);\n return new Promise((resolve) => {\n let settled = false;\n const socket = net.createConnection({ host: target.host, port: target.port });\n const done = (ok: boolean) => {\n if (settled) return;\n settled = true;\n socket.destroy();\n signal?.removeEventListener(\"abort\", onAbort);\n resolve(ok);\n };\n const onAbort = (): void => done(false);\n socket.once(\"connect\", () => done(true));\n socket.once(\"error\", () => done(false));\n socket.setTimeout(DEFAULT_PROBE_TIMEOUT_MS, () => done(false));\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nconst delay = (ms: number, signal?: AbortSignal): Promise<void> => {\n throwIfAborted(signal);\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(abortError());\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n};\n\nfunction raceWithAbort<T>(promise: Promise<T>, signal?: AbortSignal): Promise<T> {\n if (!signal) return promise;\n throwIfAborted(signal);\n return new Promise((resolve, reject) => {\n const onAbort = (): void => reject(abortError());\n signal.addEventListener(\"abort\", onAbort, { once: true });\n void promise.then(\n (value) => {\n signal.removeEventListener(\"abort\", onAbort);\n resolve(value);\n },\n (error: unknown) => {\n signal.removeEventListener(\"abort\", onAbort);\n reject(error);\n },\n );\n });\n}\n\nasync function waitForTarget(\n target: SidecarTarget,\n opts: {\n onLog: (message: string) => void;\n timeoutMs?: number;\n pollIntervalMs: number;\n probe: (target: SidecarTarget, signal?: AbortSignal) => Promise<boolean>;\n signal?: AbortSignal;\n },\n): Promise<void> {\n const { onLog, pollIntervalMs, probe, signal } = opts;\n const timeoutMs = opts.timeoutMs ?? target.timeoutMs ?? FALLBACK_TIMEOUT_MS;\n const deadline = Date.now() + timeoutMs;\n onLog(`Waiting for ${target.name} on ${target.host}:${target.port}...`);\n\n while (true) {\n throwIfAborted(signal);\n if (await raceWithAbort(probe(target, signal), signal)) {\n onLog(`${target.name} is ready`);\n return;\n }\n if (Date.now() >= deadline) {\n onLog(\n `WARNING: ${target.name} not ready after ${Math.round(timeoutMs / 1000)}s, continuing anyway`,\n );\n return;\n }\n await delay(pollIntervalMs, signal);\n }\n}\n\n/**\n * Block until every configured sidecar is reachable (or its per-target deadline\n * elapses). Resolves immediately when no sidecar env vars are set. Readiness\n * failures remain non-fatal; an explicit shutdown abort rejects with AbortError.\n */\nexport async function waitForSidecars(opts: WaitForSidecarsOptions = {}): Promise<void> {\n const {\n env = process.env,\n onLog = () => {},\n timeoutMs,\n pollIntervalMs = DEFAULT_SIDECAR_POLL_INTERVAL_MS,\n probe = defaultProbe,\n startLazy = true,\n signal,\n } = opts;\n\n if (startLazy) {\n await startLazySidecars(env, onLog, signal);\n }\n throwIfAborted(signal);\n\n const targets = resolveSidecarTargets(env);\n if (targets.length === 0) return;\n\n await Promise.all(\n targets.map((target) =>\n waitForTarget(target, { onLog, timeoutMs, pollIntervalMs, probe, signal }),\n ),\n );\n}\n","/**\n * Pod-side bootstrap-milestone reporter. The pod alone observes when the\n * workspace git is up to date, when its sidecars are ready, and when configured\n * setup has finished; it reports those milestones to the API over the same\n * bootstrap-token channel the bundle poll and crash reporter use\n * (`POST /api/v3/pods/boot-milestone`). The API\n * records them on `Workspace.bootTimeline`, which drives the agent-tab progress\n * meter. Server-owned milestones (pod_created/image_ready/agent_connected) are\n * never reported from here — the API enforces the allow-list.\n *\n * Fire-and-forget: a failed or slow report must never delay setup/start, so\n * every path swallows errors and the whole thing no-ops off-pod (GitHub\n * Codespaces / local), where the bootstrap token is absent.\n */\nimport type { BootStepKey } from \"@project/shared\";\n\nconst REPORT_TIMEOUT_MS = 5_000;\n\n/** The steps a pod may report. Mirrors the API's `POD_REPORTABLE_BOOT_STEPS`. */\nexport type PodReportableBootStep = Extract<\n BootStepKey,\n \"git_ready\" | \"sidecars_ready\" | \"setup_complete\"\n>;\n\nexport interface ReportBootMilestoneOptions {\n key: PodReportableBootStep;\n /** Defaults to `process.env`. Injected for tests. */\n env?: NodeJS.ProcessEnv;\n /** Injected for tests; defaults to global fetch. */\n fetchFn?: typeof fetch;\n timeoutMs?: number;\n}\n\n/**\n * Best-effort POST of a boot milestone. Resolves to `true` when the API\n * acknowledged (HTTP 2xx), `false` otherwise — including the off-pod no-op.\n * Never throws.\n */\nexport async function reportBootMilestone(opts: ReportBootMilestoneOptions): Promise<boolean> {\n const env = opts.env ?? process.env;\n const apiUrl = env.CONVEYOR_API_URL;\n const token = env.POD_BOOTSTRAP_TOKEN;\n // Only claudespace v3 pods carry both — elsewhere there is no meter to feed.\n if (!apiUrl || !token) return false;\n\n const fetchFn = opts.fetchFn ?? fetch;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), opts.timeoutMs ?? REPORT_TIMEOUT_MS);\n try {\n const res = await fetchFn(`${apiUrl.replace(/\\/$/, \"\")}/api/v3/pods/boot-milestone`, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({ key: opts.key }),\n signal: controller.signal,\n });\n return res.ok;\n } catch {\n return false;\n } finally {\n clearTimeout(timer);\n }\n}\n","import {\n buildSessionPreviewPorts,\n loadForwardPorts,\n type ConveyorConfig,\n type ForwardPortsResult,\n} from \"./config.js\";\nimport { awaitGitReady, type GitReadyState } from \"./git-ready.js\";\nimport {\n runSetupCommand,\n runStartCommand,\n terminateProcessGroup,\n type ManagedChildProcess,\n} from \"./commands.js\";\nimport { startLazySidecars, waitForSidecars } from \"./sidecars.js\";\nimport { workbenchEnabled } from \"../workbench/mode.js\";\nimport { getWorkbenchClient } from \"../workbench/client.js\";\nimport { reportBootMilestone, type PodReportableBootStep } from \"./boot-milestone.js\";\n\ntype OutputStream = \"stdout\" | \"stderr\";\ntype StartCommandChild = ManagedChildProcess;\n\n/**\n * Split-mode pods run every workspace command in the workbench container;\n * everywhere else the local spawn paths are used unchanged. Resolved per\n * supervisor construction (not import) so tests can flip the env.\n */\nfunction defaultCommandExecutors(): {\n runSetupCommand: NonNullable<WorkspaceCommandSupervisorOptions[\"runSetupCommand\"]>;\n runStartCommand: (\n cmd: string,\n cwd: string,\n onOutput: (stream: OutputStream, data: string) => void,\n ) => StartCommandChild;\n} {\n if (workbenchEnabled()) {\n const client = getWorkbenchClient();\n return {\n runSetupCommand: (command, cwd, onOutput, signal) =>\n client.runSetupCommand(command, cwd, onOutput, signal),\n runStartCommand: (cmd, cwd, onOutput) => client.runStartCommand(cmd, cwd, onOutput),\n };\n }\n return {\n runSetupCommand: (command, cwd, onOutput, signal) =>\n runSetupCommand(command, cwd, onOutput, signal),\n runStartCommand,\n };\n}\n\nexport interface WorkspaceCommandConnection {\n sendEvent(event: { type: string; [key: string]: unknown }): void;\n onRunStartCommand(callback: () => void): void;\n}\n\nexport interface WorkspaceCommandSupervisorOptions {\n config: ConveyorConfig | null;\n workspaceDir: string;\n connection: WorkspaceCommandConnection;\n env?: NodeJS.ProcessEnv;\n awaitGitReady?: (options: {\n onLog: (message: string) => void;\n signal: AbortSignal;\n }) => Promise<GitReadyState>;\n startLazySidecars?: (\n env: NodeJS.ProcessEnv,\n onLog: (message: string) => void,\n signal: AbortSignal,\n ) => Promise<void>;\n waitForSidecars?: (options: {\n onLog: (message: string) => void;\n startLazy: false;\n signal: AbortSignal;\n }) => Promise<void>;\n runSetupCommand?: (\n command: string,\n cwd: string,\n onOutput: (stream: OutputStream, data: string) => void,\n signal: AbortSignal,\n ) => Promise<void>;\n runStartCommand?: (\n cmd: string,\n cwd: string,\n onOutput: (stream: OutputStream, data: string) => void,\n ) => StartCommandChild;\n loadForwardPorts?: (workspaceDir: string) => Promise<ForwardPortsResult>;\n writeOutput?: (stream: OutputStream, data: string) => void;\n terminateStartCommand?: (child: StartCommandChild) => void | Promise<void>;\n /** Report a pod-observed boot milestone to the API. Injected for tests. */\n reportBootMilestone?: (key: PodReportableBootStep) => void;\n}\n\nconst defaultWriteOutput = (stream: OutputStream, data: string): void => {\n (stream === \"stderr\" ? process.stderr : process.stdout).write(data);\n};\n\nexport function stopWorkspaceCommands(\n supervisor: { stop(): Promise<void> } | null | undefined,\n): Promise<void> {\n return supervisor?.stop() ?? Promise.resolve();\n}\n\nexport interface WorkspaceCommandStartupOptions<T extends { start(): void }> {\n connect: () => Promise<boolean>;\n isShuttingDown: () => boolean;\n create: () => T;\n}\n\n/**\n * Holds workspace commands behind both the runner's connection/baseline gate\n * and the CLI's synchronous shutdown intent. A signal can arrive while\n * connect() is awaiting discovery but before runner.stop() runs after the\n * graceful git flush; checking shutdown intent after the await closes that\n * window without constructing a supervisor.\n */\nexport async function startWorkspaceCommandsAfterConnect<T extends { start(): void }>(\n options: WorkspaceCommandStartupOptions<T>,\n): Promise<T | null> {\n const connected = await options.connect();\n if (!connected || options.isShuttingDown()) return null;\n const supervisor = options.create();\n supervisor.start();\n return supervisor;\n}\n\n/**\n * Owns setup and long-running workspace commands independently of the runner\n * that hosts them. start() is intentionally fire-and-forget: command failures\n * are user-visible events and never terminate the agent lifecycle.\n */\nexport class WorkspaceCommandSupervisor {\n private readonly abortController = new AbortController();\n private readonly expectedStartCommandStops = new WeakSet<StartCommandChild>();\n private readonly config: ConveyorConfig | null;\n private readonly workspaceDir: string;\n private readonly connection: WorkspaceCommandConnection;\n private readonly env: NodeJS.ProcessEnv;\n private readonly awaitGitReadyFn: NonNullable<WorkspaceCommandSupervisorOptions[\"awaitGitReady\"]>;\n private readonly startLazySidecarsFn: NonNullable<\n WorkspaceCommandSupervisorOptions[\"startLazySidecars\"]\n >;\n private readonly waitForSidecarsFn: NonNullable<\n WorkspaceCommandSupervisorOptions[\"waitForSidecars\"]\n >;\n private readonly runSetupCommandFn: NonNullable<\n WorkspaceCommandSupervisorOptions[\"runSetupCommand\"]\n >;\n private readonly runStartCommandFn: NonNullable<\n WorkspaceCommandSupervisorOptions[\"runStartCommand\"]\n >;\n private readonly loadForwardPortsFn: (workspaceDir: string) => Promise<ForwardPortsResult>;\n private readonly writeOutput: (stream: OutputStream, data: string) => void;\n private readonly terminateStartCommand: (child: StartCommandChild) => void | Promise<void>;\n private readonly reportBootMilestoneFn: (key: PodReportableBootStep) => void;\n\n private startCommandChild: StartCommandChild | null = null;\n private readonly liveStartCommandChildren = new Set<StartCommandChild>();\n private readonly startCommandTerminations = new WeakMap<StartCommandChild, Promise<void>>();\n private readonly startCommandEndPromises = new WeakMap<StartCommandChild, Promise<void>>();\n private readonly resolveStartCommandEnd = new WeakMap<StartCommandChild, () => void>();\n private readonly backgroundTasks = new Set<Promise<void>>();\n private startCommandQueue: Promise<void> = Promise.resolve();\n private shutdownPromise: Promise<void> | null = null;\n private startCommandLaunchRequested = false;\n private started = false;\n private stopped = false;\n\n constructor(options: WorkspaceCommandSupervisorOptions) {\n this.config = options.config;\n this.workspaceDir = options.workspaceDir;\n this.connection = options.connection;\n this.env = options.env ?? process.env;\n this.awaitGitReadyFn =\n options.awaitGitReady ??\n ((opts) =>\n awaitGitReady({\n onLog: opts.onLog,\n signal: opts.signal,\n }));\n this.startLazySidecarsFn =\n options.startLazySidecars ?? ((env, onLog, signal) => startLazySidecars(env, onLog, signal));\n this.waitForSidecarsFn =\n options.waitForSidecars ??\n ((opts) =>\n waitForSidecars({ onLog: opts.onLog, startLazy: opts.startLazy, signal: opts.signal }));\n const executors = defaultCommandExecutors();\n this.runSetupCommandFn = options.runSetupCommand ?? executors.runSetupCommand;\n this.runStartCommandFn = options.runStartCommand ?? executors.runStartCommand;\n this.loadForwardPortsFn = options.loadForwardPorts ?? loadForwardPorts;\n this.writeOutput = options.writeOutput ?? defaultWriteOutput;\n this.terminateStartCommand = options.terminateStartCommand ?? terminateProcessGroup;\n this.reportBootMilestoneFn =\n options.reportBootMilestone ??\n ((key) => {\n // Fire-and-forget: never let a boot-meter report delay setup/start.\n void reportBootMilestone({ key, env: this.env });\n });\n }\n\n start(): void {\n if (this.started || this.stopped) return;\n this.started = true;\n this.connection.onRunStartCommand(() => this.restartStartCommand());\n\n this.trackBackgroundTask(\n this.startLazySidecarsFn(\n this.env,\n (message) => this.forwardSetupOutput(\"stdout\", `[sidecars] ${message}\\n`),\n this.abortController.signal,\n ).catch((error: unknown) => this.reportUnexpectedError(error)),\n );\n\n if (this.config) {\n this.trackBackgroundTask(\n this.runSetupAndStart().catch((error: unknown) => this.reportUnexpectedError(error)),\n );\n }\n }\n\n stop(): Promise<void> {\n if (this.shutdownPromise) return this.shutdownPromise;\n this.stopped = true;\n this.abortController.abort();\n const backgroundTasks = [...this.backgroundTasks];\n const termination = this.terminateAllStartCommands();\n this.shutdownPromise = (async () => {\n await Promise.allSettled([termination, this.startCommandQueue, ...backgroundTasks]);\n await this.terminateAllStartCommands();\n })();\n return this.shutdownPromise;\n }\n\n private async runSetupAndStart(): Promise<void> {\n const gitState = await this.awaitGitReadyFn({\n onLog: (message) => this.forwardSetupOutput(\"stdout\", `[git] ${message}\\n`),\n signal: this.abortController.signal,\n });\n if (this.stopped) return;\n if (gitState === \"failed\" || gitState === \"timeout\") {\n this.connection.sendEvent({\n type: \"setup_error\",\n message: \"Workspace not ready — skipping setup/start\",\n });\n return;\n }\n // Repo is up to date — a boot milestone the pod alone can observe.\n if (gitState === \"ready\") this.reportBootMilestoneFn(\"git_ready\");\n\n await this.waitForSidecarsFn({\n onLog: (message) => this.forwardSetupOutput(\"stdout\", `[sidecars] ${message}\\n`),\n startLazy: false,\n signal: this.abortController.signal,\n });\n if (this.stopped) return;\n this.reportBootMilestoneFn(\"sidecars_ready\");\n\n await this.runConfiguredSetup();\n if (this.stopped) return;\n // Configured setup finished — the last boot milestone the pod observes.\n // Fires whether or not a setup command ran, so it stays the terminal step\n // for every project (a no-op setup completes instantly).\n this.reportBootMilestoneFn(\"setup_complete\");\n\n const startCommandRunning = this.config?.startCommand\n ? await this.ensureStartCommandLaunched(this.config.startCommand)\n : false;\n if (this.stopped) return;\n\n const forwardPorts = await this.loadForwardPortsFn(this.workspaceDir);\n if (this.stopped) return;\n const previewPorts = buildSessionPreviewPorts(forwardPorts);\n this.connection.sendEvent({\n type: \"setup_complete\",\n startCommandRunning,\n ...(previewPorts.length > 0 ? { previewPorts } : {}),\n });\n }\n\n private async runConfiguredSetup(): Promise<void> {\n const command = this.config?.setupCommand;\n if (!command) return;\n try {\n await this.runSetupCommandFn(\n command,\n this.workspaceDir,\n (stream, data) => this.forwardSetupOutput(stream, data),\n this.abortController.signal,\n );\n } catch (error) {\n if (this.stopped) return;\n this.connection.sendEvent({\n type: \"setup_error\",\n message: error instanceof Error ? error.message : \"Setup command failed\",\n });\n }\n }\n\n private restartStartCommand(): void {\n if (this.stopped || !this.config?.startCommand) return;\n this.connection.sendEvent({\n type: \"start_command_output\",\n stream: \"stdout\",\n data: \"[conveyor-agent] Restarting start command...\\n\",\n });\n void this.enqueueStartCommandReplacement(this.config.startCommand);\n }\n\n private async ensureStartCommandLaunched(command: string): Promise<boolean> {\n if (!this.startCommandLaunchRequested) {\n return this.enqueueStartCommandReplacement(command);\n }\n await this.startCommandQueue;\n return !this.stopped && this.liveStartCommandChildren.size > 0;\n }\n\n private enqueueStartCommandReplacement(command: string): Promise<boolean> {\n this.startCommandLaunchRequested = true;\n const operation = this.startCommandQueue.then(async () => {\n if (this.stopped) return false;\n await this.terminateAllStartCommands();\n if (this.stopped) return false;\n return this.launchStartCommand(command);\n });\n this.startCommandQueue = operation.then(\n () => undefined,\n () => undefined,\n );\n return operation;\n }\n\n private launchStartCommand(command: string): boolean {\n if (this.stopped) return false;\n this.connection.sendEvent({ type: \"start_command_started\" });\n try {\n const child = this.runStartCommandFn(command, this.workspaceDir, (stream, data) => {\n if (this.stopped) return;\n this.connection.sendEvent({ type: \"start_command_output\", stream, data });\n this.writeOutput(stream, data);\n });\n this.liveStartCommandChildren.add(child);\n const ended = new Promise<void>((resolve) => {\n this.resolveStartCommandEnd.set(child, resolve);\n });\n this.startCommandEndPromises.set(child, ended);\n if (this.stopped) {\n void this.terminateStartCommandChild(child);\n return false;\n }\n this.startCommandChild = child;\n child.on(\"exit\", (code, signal) => {\n if (this.startCommandChild === child) this.startCommandChild = null;\n this.liveStartCommandChildren.delete(child);\n this.settleStartCommandEnd(child);\n if (this.stopped || this.expectedStartCommandStops.has(child)) return;\n const message = `start command exited${code === null ? \"\" : ` with code ${code}`}${signal ? ` (signal: ${signal})` : \"\"}`;\n this.connection.sendEvent({ type: \"start_command_exited\", code, signal, message });\n if (code !== null && code !== 0) {\n this.connection.sendEvent({\n type: \"start_command_error\",\n message: `start command exited with code ${code}${signal ? ` (signal: ${signal})` : \"\"}`,\n });\n }\n });\n child.on(\"error\", (error) => {\n if (child.pid === undefined) {\n if (this.startCommandChild === child) this.startCommandChild = null;\n this.liveStartCommandChildren.delete(child);\n this.settleStartCommandEnd(child);\n this.startCommandTerminations.delete(child);\n }\n if (this.stopped) return;\n this.connection.sendEvent({ type: \"start_command_error\", message: error.message });\n });\n return true;\n } catch (error) {\n if (!this.stopped) {\n this.connection.sendEvent({\n type: \"start_command_error\",\n message: error instanceof Error ? error.message : String(error),\n });\n }\n return false;\n }\n }\n\n private terminateStartCommandChild(child: StartCommandChild): Promise<void> {\n const existing = this.startCommandTerminations.get(child);\n if (existing) return existing;\n this.expectedStartCommandStops.add(child);\n const processTermination = Promise.resolve(this.terminateStartCommand(child));\n const ended = this.startCommandEndPromises.get(child);\n const termination = (ended ? Promise.race([processTermination, ended]) : processTermination)\n .then(() => undefined)\n .finally(() => this.startCommandTerminations.delete(child));\n this.startCommandTerminations.set(child, termination);\n return termination;\n }\n\n private async terminateAllStartCommands(): Promise<void> {\n const live = [...this.liveStartCommandChildren].filter((child) => child.exitCode === null);\n await Promise.all(live.map((child) => this.terminateStartCommandChild(child)));\n }\n\n private settleStartCommandEnd(child: StartCommandChild): void {\n this.resolveStartCommandEnd.get(child)?.();\n this.resolveStartCommandEnd.delete(child);\n this.startCommandEndPromises.delete(child);\n }\n\n private trackBackgroundTask(task: Promise<void>): void {\n this.backgroundTasks.add(task);\n void task.finally(() => this.backgroundTasks.delete(task));\n }\n\n private forwardSetupOutput(stream: OutputStream, data: string): void {\n if (this.stopped) return;\n this.connection.sendEvent({ type: \"setup_output\", stream, data });\n this.writeOutput(stream, data);\n }\n\n private reportUnexpectedError(error: unknown): void {\n if (this.stopped) return;\n this.connection.sendEvent({\n type: \"setup_error\",\n message: error instanceof Error ? error.message : String(error),\n });\n }\n}\n","// Defense-in-depth startup check. The authoritative guarantee that a session is\n// bound to the right task lives server-side (requireTaskAuth + the Postgres\n// partial-unique index on active CodespaceSessions). This check exists so that\n// if those invariants ever regress, a human sees a loud WARN immediately\n// instead of the symptoms SEC-9 produced (multiple agents silently clobbering\n// the same branch).\nexport interface SessionIdentityLogger {\n warn(message: string, data?: Record<string, unknown>): void;\n info?(message: string, data?: Record<string, unknown>): void;\n}\n\nexport interface CheckSessionTaskIdentityParams {\n sessionId: string | undefined;\n taskId: string;\n fetchSessionTaskId: (sessionId: string) => Promise<string>;\n logger: SessionIdentityLogger;\n}\n\nexport async function checkSessionTaskIdentity(\n params: CheckSessionTaskIdentityParams,\n): Promise<\"match\" | \"mismatch\" | \"skipped\" | \"error\"> {\n const { sessionId, taskId, fetchSessionTaskId, logger } = params;\n if (!sessionId || sessionId === taskId) return \"skipped\";\n let sessionTaskId: string;\n try {\n sessionTaskId = await fetchSessionTaskId(sessionId);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n logger.warn(\"Could not verify session/task identity — continuing (defense-in-depth only)\", {\n sessionId,\n taskId,\n error: message,\n });\n return \"error\";\n }\n if (sessionTaskId !== taskId) {\n logger.warn(\n \"!!! CONVEYOR_SESSION_ID is bound to a different task than CONVEYOR_TASK_ID — server-side guards should still block mutations, but this indicates a misconfiguration or replayed token.\",\n { sessionId, envTaskId: taskId, sessionTaskId },\n );\n return \"mismatch\";\n }\n return \"match\";\n}\n","/**\n * Structured pod-exit log payload. The control plane (workspace reconciler) can\n * only ever infer *that* an agent stopped — it sees a stale heartbeat and marks\n * the session Stranded/Ended. It cannot see *why*. This log closes that gap from\n * the pod side: emitted at every catchable exit path so the claudespace pod logs\n * record the cause (teardown signal vs clean finish vs crash) alongside the\n * `sessionId` that joins to the API's `session_stranded` / reconcile logs.\n *\n * Caveat: an OOMKill (SIGKILL / 137) is uncatchable, so it never reaches here —\n * those are diagnosed from GKE kernel OOM logs, not this line.\n */\n// - signal: SIGTERM/SIGINT — teardown or a reaper asked us to stop\n// - clean: runner.run() resolved normally\n// - error: runner finalState=error, or run() rejected\n// - force_timeout: graceful-shutdown watchdog fired\nexport type AgentExitReason =\n | \"signal\"\n | \"clean\"\n | \"error\"\n | \"uncaught_exception\"\n | \"unhandled_rejection\"\n | \"force_timeout\";\n\nexport interface AgentExitIdentity {\n sessionId?: string | undefined;\n taskId?: string | undefined;\n workspaceId?: string | undefined;\n runnerMode?: string | undefined;\n}\n\nexport interface AgentExitLog extends AgentExitIdentity {\n event: \"agent_exit\";\n reason: AgentExitReason;\n exitCode: number;\n signal?: string;\n finalState?: string;\n uptimeSec: number;\n}\n\n/** Clean shutdowns are routine (info); every other exit is worth a warn so it\n * surfaces in severity-filtered log queries. */\nexport function exitLogLevel(reason: AgentExitReason): \"info\" | \"warn\" {\n return reason === \"clean\" ? \"info\" : \"warn\";\n}\n\n/**\n * Build the `agent_exit` payload, dropping any undefined optional/identity keys\n * so the serialized log line stays tidy (no `\"workspaceId\":undefined` noise).\n */\nexport function buildAgentExitLog(args: {\n reason: AgentExitReason;\n exitCode: number;\n uptimeSec: number;\n signal?: string | undefined;\n finalState?: string | undefined;\n identity?: AgentExitIdentity | undefined;\n}): AgentExitLog {\n const log: AgentExitLog = {\n event: \"agent_exit\",\n reason: args.reason,\n exitCode: args.exitCode,\n uptimeSec: Math.round(args.uptimeSec * 10) / 10,\n };\n if (args.signal !== undefined) log.signal = args.signal;\n if (args.finalState !== undefined) log.finalState = args.finalState;\n const id = args.identity;\n if (id) {\n if (id.sessionId !== undefined) log.sessionId = id.sessionId;\n if (id.taskId !== undefined) log.taskId = id.taskId;\n if (id.workspaceId !== undefined) log.workspaceId = id.workspaceId;\n if (id.runnerMode !== undefined) log.runnerMode = id.runnerMode;\n }\n return log;\n}\n","/**\n * Task-less pod identity detection (Claudespace v3 project runners AND adhoc\n * scratch pods).\n *\n * A v3 task-less pod's bootstrap bundle carries a session JWT with\n * {projectId, workspaceId, sessionId, role} and NO taskId claim; the entrypoint\n * exports CONVEYOR_PROJECT_ID / CONVEYOR_SESSION_ID / CONVEYOR_WORKSPACE_ID from\n * the claims, does NOT export CONVEYOR_TASK_ID, and sets CONVEYOR_MODE to \"pm\"\n * (project runner) or \"adhoc\" (interactive scratch TUI). Both share this\n * identity shape — cli.ts branches on CONVEYOR_MODE afterward to pick the\n * runner. Every condition below is required — anything else falls through to\n * the task-runner path, which fail-closed exits without a task id.\n *\n * `workspaceId` is the stable `Workspace` row id — unlike `sessionId` (the\n * `WorkspaceSession` row), it survives a sleep/wake cycle: a user-initiated\n * wake mints a brand-new writer `WorkspaceSession` (fresh-session semantics,\n * see `ensure-adhoc.ts`), so `sessionId` changes on every wake. The adhoc\n * runner keys its Claude session lineage on `workspaceId` for exactly this\n * reason — keying on `sessionId` would never resume the prior transcript.\n */\n\nexport interface ProjectRunnerIdentity {\n projectId: string;\n sessionId: string;\n workspaceId: string;\n taskToken: string;\n}\n\nexport function resolveProjectRunnerIdentity(\n env: Record<string, string | undefined>,\n): ProjectRunnerIdentity | null {\n // A task id always wins: this is a task pod, never a project runner.\n if (env.CONVEYOR_TASK_ID) return null;\n if (!env.CONVEYOR_TASK_TOKEN) return null;\n if (!env.CONVEYOR_PROJECT_ID || !env.CONVEYOR_SESSION_ID || !env.CONVEYOR_WORKSPACE_ID) {\n return null;\n }\n // Task-less identity is shared by the project runner (\"pm\") and the adhoc\n // scratch-pod TUI (\"adhoc\"); cli.ts branches on CONVEYOR_MODE afterward to\n // pick the runner. Any OTHER mode (reader/review/task/absent) is not a valid\n // task-less identity. NOTE: the adhoc branch in cli.ts gates on THIS resolver\n // returning non-null AND CONVEYOR_MODE === \"adhoc\" — omitting \"adhoc\" here\n // makes that branch unreachable and crash-loops every adhoc pod at the\n // task-mode fall-through.\n if (env.CONVEYOR_MODE !== \"pm\" && env.CONVEYOR_MODE !== \"adhoc\") return null;\n\n return {\n projectId: env.CONVEYOR_PROJECT_ID,\n sessionId: env.CONVEYOR_SESSION_ID,\n workspaceId: env.CONVEYOR_WORKSPACE_ID,\n taskToken: env.CONVEYOR_TASK_TOKEN,\n };\n}\n","/**\n * ProjectSessionRunner — the task-less PROJECT pod agent loop (Claudespace v3\n * project runners).\n *\n * What a project agent does today: connect, register its WorkspaceSession\n * (connectAgent), heartbeat (lease renewal via the server's v3 fallthrough),\n * and idle awaiting project-scoped messages. It deliberately does NOT run the\n * task-shaped SessionRunner lifecycle — getTaskContext, git branch sync, the\n * QueryBridge prompt loop and WIP flushing are all keyed on a Task, and the\n * server-side pm-conversation surface for project workspaces does not exist\n * yet (project chat is served by the server-side ProjectAgentService\n * responder). When that surface lands (project context RPC + project-keyed\n * message routing), this runner grows the message->query loop; until then an\n * inbound message is logged and acknowledged as activity only.\n */\nimport {\n AgentConnection,\n type AgentConnectionConfig,\n type IncomingMessage,\n} from \"../connection/agent-connection.js\";\nimport { Lifecycle, DEFAULT_LIFECYCLE_CONFIG, type LifecycleConfig } from \"./lifecycle.js\";\nimport { sampleKeyUsage } from \"../execution/usage-sampler.js\";\n\nexport interface ProjectSessionRunnerConfig {\n connection: AgentConnectionConfig;\n projectId: string;\n lifecycle?: Partial<LifecycleConfig>;\n}\n\nexport interface ProjectSessionRunnerCallbacks {\n onEvent?: (event: Record<string, unknown>) => void;\n}\n\n/** The AgentConnection surface the project runner uses (injectable for tests). */\nexport interface ProjectRunnerConnection {\n connect(): Promise<void>;\n disconnect(): void;\n call(\n method: \"connectAgent\",\n payload: { sessionId: string },\n ): Promise<{ sessionId: string; taskId: string | null; pendingMessages: unknown[] }>;\n sendEvent(event: { type: string; [key: string]: unknown }): void;\n sendHeartbeat(): void;\n emitStatus(status: string): Promise<void>;\n onMessage(callback: (msg: IncomingMessage) => void): void;\n onStop(callback: () => void): void;\n refreshTaskTokenFromBootstrap(): Promise<boolean>;\n}\n\nexport class ProjectSessionRunner {\n readonly connection: ProjectRunnerConnection;\n readonly lifecycle: Lifecycle;\n\n private readonly config: ProjectSessionRunnerConfig;\n private readonly callbacks: ProjectSessionRunnerCallbacks;\n private stopped = false;\n private stopResolver: (() => void) | null = null;\n private _finalState: \"finished\" | \"error\" | null = null;\n\n constructor(\n config: ProjectSessionRunnerConfig,\n callbacks: ProjectSessionRunnerCallbacks = {},\n connection?: ProjectRunnerConnection,\n ) {\n this.config = config;\n this.callbacks = callbacks;\n this.connection = connection ?? new AgentConnection(config.connection);\n this.lifecycle = new Lifecycle(\n // No git flush: the project runner does not (yet) mutate the checkout,\n // and the WIP snapshot machinery is branch/task-shaped.\n { ...DEFAULT_LIFECYCLE_CONFIG, gitFlushIntervalMs: 0, ...config.lifecycle },\n {\n onHeartbeat: () => this.connection.sendHeartbeat(),\n onIdleTimeout: () => {\n process.stderr.write(\"[conveyor-agent] Project runner idle timeout, shutting down\\n\");\n this.requestStop();\n },\n onDormantTimeout: () => this.requestStop(),\n // v3 credential refresh: re-poll the pod bootstrap route (session JWT,\n // GitHub token, keys are all swapped in place). The task-scoped\n // refreshGithubToken RPC does not apply to a task-less session.\n onTokenRefresh: () => void this.connection.refreshTaskTokenFromBootstrap().catch(() => {}),\n onGitFlush: () => {},\n onUsageSample: () => void this.sampleAndReportKeyUsage(),\n },\n );\n }\n\n get finalState(): \"finished\" | \"error\" | null {\n return this._finalState;\n }\n\n get isStopped(): boolean {\n return this.stopped;\n }\n\n /** Connect, register the session, then idle until stopped or idle-timeout. */\n async run(): Promise<void> {\n try {\n await this.connection.connect();\n this.connection.sendEvent({\n type: \"connected\",\n sessionId: this.config.connection.sessionId,\n projectId: this.config.projectId,\n });\n\n this.connection.onStop(() => this.requestStop());\n this.connection.onMessage((msg) => this.handleMessage(msg));\n this.lifecycle.startHeartbeat();\n this.lifecycle.startTokenRefresh();\n this.lifecycle.startUsageSample();\n\n // Join the session room + activate the lease (server v3 fallthrough).\n await this.connection.call(\"connectAgent\", {\n sessionId: this.config.connection.sessionId,\n });\n\n process.stderr.write(\n `[conveyor-agent] Project runner connected (project: ${this.config.projectId}) — idling\\n`,\n );\n await this.connection.emitStatus(\"idle\");\n this.callbacks.onEvent?.({ type: \"project_runner_idle\", projectId: this.config.projectId });\n\n this.lifecycle.startIdleTimer();\n await this.waitUntilStopped();\n this._finalState = \"finished\";\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[conveyor-agent] Project runner failed: ${message}\\n`);\n this.connection.sendEvent({ type: \"error\", message });\n this._finalState = \"error\";\n } finally {\n this.shutdown();\n }\n }\n\n /**\n * The pm-conversation surface is a follow-up: no server path routes chat to\n * a task-less session yet, so any message that does arrive is surfaced in\n * the logs and treated as activity (idle timer restarts) — never executed.\n */\n private handleMessage(msg: IncomingMessage): void {\n const preview = msg.content.length > 120 ? `${msg.content.slice(0, 120)}…` : msg.content;\n process.stderr.write(\n `[conveyor-agent] Project runner received message (pm surface not wired yet): \"${preview.replace(/\\n/g, \"\\\\n\")}\"\\n`,\n );\n this.callbacks.onEvent?.({ type: \"project_message_received\", content: msg.content });\n if (!this.stopped) this.lifecycle.startIdleTimer();\n }\n\n /** External stop (SIGTERM/SIGINT or server session:stop). */\n stop(): void {\n this.requestStop();\n }\n\n private requestStop(): void {\n if (this.stopped) return;\n this.stopped = true;\n if (this.stopResolver) {\n const resolve = this.stopResolver;\n this.stopResolver = null;\n resolve();\n }\n }\n\n private waitUntilStopped(): Promise<void> {\n if (this.stopped) return Promise.resolve();\n return new Promise<void>((resolve) => {\n this.stopResolver = resolve;\n });\n }\n\n /** Report the running subscription key's rate-limit utilization (same path as\n * the task runner). Best-effort — never throws, no-op without an OAuth token. */\n private async sampleAndReportKeyUsage(): Promise<void> {\n if (this.stopped) return;\n const samples = await sampleKeyUsage(process.env.CLAUDE_CODE_OAUTH_TOKEN);\n for (const sample of samples) {\n this.connection.sendEvent({\n type: \"rate_limit_update\",\n rateLimitType: sample.rateLimitType,\n utilization: sample.utilization,\n status: sample.status,\n resetsAt: sample.resetsAt ?? undefined,\n gauges: sample.gauges,\n });\n }\n }\n\n private shutdown(): void {\n this.stopped = true;\n this.lifecycle.destroy();\n this.connection.sendEvent({ type: \"shutdown\", reason: this._finalState ?? \"finished\" });\n this.connection.disconnect();\n }\n}\n","/**\n * Multi-key `/usage` probe — the on-demand \"refresh all keys from one box\" path.\n *\n * The normal sampler (`usage-sampler.ts`) can only report the ONE key the pod\n * booted under: it reads the pod's shared `~/.claude/.credentials.json` and an\n * attribution guard refuses to write another account's gauges. This module\n * instead probes an explicit list of keys, isolating EACH one in its own\n * temporary `CLAUDE_CONFIG_DIR` so the pod's shared credentials file (read by\n * the user's other concurrent pods on the GCS-FUSE mount) is never mutated.\n *\n * For each key: a temp config dir gets a synthesized `.credentials.json` for the\n * key's token plus a copy of the pod's onboarded `.claude.json` (so trust /\n * onboarding / model-cache carry over and the `/usage` panel renders without\n * parking at a first-run dialog). The `claude` CLI is then driven under a PTY\n * (`runUsageProbe`) with `CLAUDE_CONFIG_DIR` pointed at that dir.\n *\n * Best-effort throughout: a key whose probe fails or yields no gauges is simply\n * omitted — this never throws.\n */\nimport { mkdtemp, writeFile, copyFile, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { buildSynthesizedCredentials, claudeJsonPath } from \"../harness/pty/credentials.js\";\nimport { createServiceLogger } from \"../utils/logger.js\";\nimport { parseUsageGauges } from \"./parse-usage.js\";\nimport { runUsageProbe } from \"./run-probe.js\";\nimport type { KeyUsageSample } from \"../execution/usage-sampler.js\";\n\nconst logger = createServiceLogger(\"multi-key-probe\");\n\nexport interface ProbeKeyInput {\n codingAgentKeyId: string;\n /** Decrypted subscription OAuth token for this key. */\n oauthToken: string;\n}\n\nexport interface ProbedKeyUsage {\n codingAgentKeyId: string;\n samples: KeyUsageSample[];\n}\n\nexport interface MultiKeyProbeDeps {\n /**\n * Isolated single-key probe: prepare credentials for `token` and return the\n * raw `/usage` panel text. Injectable so the sequencing/mapping is testable\n * without spawning a PTY or touching the filesystem.\n */\n probeOne?: (token: string) => Promise<string>;\n now?: () => number;\n}\n\n/** Map a parsed `/usage` panel to rate-limit samples (mirrors usage-sampler). */\nfunction gaugesToSamples(stdout: string): KeyUsageSample[] {\n const { sessionUsage, weeklyUsage, sessionResetsAt, weeklyResetsAt, gauges } =\n parseUsageGauges(stdout);\n const samples: KeyUsageSample[] = [];\n if (sessionUsage !== null) {\n samples.push({\n rateLimitType: \"five_hour\",\n utilization: sessionUsage,\n status: \"allowed\",\n resetsAt: sessionResetsAt,\n gauges,\n });\n }\n if (weeklyUsage !== null) {\n samples.push({\n rateLimitType: \"seven_day\",\n utilization: weeklyUsage,\n status: \"allowed\",\n resetsAt: weeklyResetsAt,\n gauges,\n });\n }\n return samples;\n}\n\n/**\n * Default `probeOne`: build an isolated config dir for `token`, run the probe\n * under it, and clean up. Best-effort — resolves \"\" on any failure.\n */\nasync function isolatedProbe(token: string, now: number): Promise<string> {\n let dir: string | null = null;\n try {\n dir = await mkdtemp(join(tmpdir(), \"conveyor-usage-\"));\n await writeFile(join(dir, \".credentials.json\"), buildSynthesizedCredentials(token, now), {\n encoding: \"utf8\",\n mode: 0o600,\n });\n // Carry the pod's onboarding/trust/model-cache into the isolated dir so the\n // /usage panel renders instead of parking at a first-run dialog. Best-effort:\n // a missing source file just means a fresh config (the CLI onboards silently\n // for a read-only /usage panel).\n await copyFile(claudeJsonPath(), join(dir, \".claude.json\")).catch(() => {});\n return await runUsageProbe({ env: { ...process.env, CLAUDE_CONFIG_DIR: dir } });\n } catch (error) {\n logger.info(\"isolated usage probe failed\", {\n error: error instanceof Error ? error.message : String(error),\n });\n return \"\";\n } finally {\n if (dir) await rm(dir, { recursive: true, force: true }).catch(() => {});\n }\n}\n\n/**\n * Probe each key's `/usage` sequentially (avoid concurrent PTYs) and return the\n * samples per key. Keys that yield no gauges are omitted. Never throws.\n */\nexport async function probeKeysUsage(\n keys: ProbeKeyInput[],\n deps: MultiKeyProbeDeps = {},\n): Promise<ProbedKeyUsage[]> {\n const now = deps.now ?? Date.now;\n const probeOne = deps.probeOne ?? ((token: string) => isolatedProbe(token, now()));\n\n const results: ProbedKeyUsage[] = [];\n for (const key of keys) {\n if (!key.oauthToken) continue;\n try {\n const stdout = await probeOne(key.oauthToken);\n const samples = gaugesToSamples(stdout);\n if (samples.length > 0) {\n results.push({ codingAgentKeyId: key.codingAgentKeyId, samples });\n }\n } catch (error) {\n logger.info(\"usage probe for key failed\", {\n codingAgentKeyId: key.codingAgentKeyId,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n return results;\n}\n","/**\n * Seeds ChatGPT-subscription OAuth tokens into opencode's auth store.\n *\n * The API delivers CONVEYOR_OPENCODE_OAUTH = base64({access, refresh, expires})\n * (see apps/api project-key/methods/key-resolution.ts). We write it as the\n * `openai` entry of ~/.local/share/opencode/auth.json — the store the\n * opencode-openai-codex-auth plugin reads and lazily refreshes. That directory\n * is fuse-symlinked on GCP projects, so a refreshed store outlives the pod;\n * the seed therefore only wins when the existing entry is missing, malformed,\n * or STALER than the seed (re-sign-in on the site produces a newer seed —\n * that's the invalidation-recovery path). Best-effort like\n * ensureClaudeCredentials: IO failures log-and-continue, never throw.\n */\nimport { promises as fs } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { createServiceLogger } from \"../../../utils/logger.js\";\n\nconst logger = createServiceLogger(\"opencode-auth\");\n\n/** Bump deliberately: also pre-warmed in the pod image (Dockerfile.base). */\nexport const OPENCODE_CODEX_PLUGIN = \"opencode-openai-codex-auth@4.4.0\";\nconst PLUGIN_PACKAGE = \"opencode-openai-codex-auth\";\n\nexport interface OpenCodeOauthSeed {\n access: string;\n refresh: string;\n expires: number;\n}\n\nexport function opencodeAuthPath(env: NodeJS.ProcessEnv): string {\n const dataHome = env.XDG_DATA_HOME ?? join(env.HOME ?? homedir(), \".local\", \"share\");\n return join(dataHome, \"opencode\", \"auth.json\");\n}\n\nexport function opencodeConfigPath(env: NodeJS.ProcessEnv): string {\n const configHome = env.XDG_CONFIG_HOME ?? join(env.HOME ?? homedir(), \".config\");\n return join(configHome, \"opencode\", \"opencode.json\");\n}\n\nexport function parseOauthSeed(b64: string | undefined): OpenCodeOauthSeed | null {\n if (!b64) return null;\n try {\n const parsed = JSON.parse(Buffer.from(b64, \"base64\").toString(\"utf8\")) as Record<\n string,\n unknown\n >;\n if (\n typeof parsed.access === \"string\" &&\n typeof parsed.refresh === \"string\" &&\n typeof parsed.expires === \"number\"\n ) {\n return { access: parsed.access, refresh: parsed.refresh, expires: parsed.expires };\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/** Seed only when the store entry is missing/malformed or older than the seed. */\nexport function shouldSeed(existingEntry: unknown, seed: OpenCodeOauthSeed): boolean {\n if (!existingEntry || typeof existingEntry !== \"object\") return true;\n const entry = existingEntry as Record<string, unknown>;\n if (entry.type !== \"oauth\") return true;\n if (typeof entry.access !== \"string\" || typeof entry.refresh !== \"string\") return true;\n if (typeof entry.expires !== \"number\") return true;\n return entry.expires < seed.expires;\n}\n\nasync function readJsonFile(path: string): Promise<Record<string, unknown>> {\n try {\n return JSON.parse(await fs.readFile(path, \"utf8\")) as Record<string, unknown>;\n } catch {\n return {};\n }\n}\n\nasync function writeJsonFile(path: string, value: Record<string, unknown>): Promise<void> {\n await fs.mkdir(dirname(path), { recursive: true });\n await fs.writeFile(path, `${JSON.stringify(value, null, 2)}\\n`, { mode: 0o600 });\n}\n\nasync function ensureAuthEntry(env: NodeJS.ProcessEnv, seed: OpenCodeOauthSeed): Promise<void> {\n const path = opencodeAuthPath(env);\n const store = await readJsonFile(path);\n if (!shouldSeed(store.openai, seed)) {\n logger.info(\"opencode oauth store is fresher than the seed; leaving it alone\");\n return;\n }\n store.openai = {\n type: \"oauth\",\n access: seed.access,\n refresh: seed.refresh,\n expires: seed.expires,\n };\n await writeJsonFile(path, store);\n logger.info(\"seeded opencode oauth store entry\");\n}\n\nasync function ensurePluginConfig(env: NodeJS.ProcessEnv): Promise<void> {\n const path = opencodeConfigPath(env);\n const config = await readJsonFile(path);\n const plugins = Array.isArray(config.plugin) ? (config.plugin as unknown[]) : [];\n const isOurs = (p: unknown): boolean =>\n typeof p === \"string\" && (p === PLUGIN_PACKAGE || p.startsWith(`${PLUGIN_PACKAGE}@`));\n const hasExactPin = plugins.includes(OPENCODE_CODEX_PLUGIN);\n const hasStalePin = plugins.some((p) => isOurs(p) && p !== OPENCODE_CODEX_PLUGIN);\n // Already correct — don't churn the fuse file.\n if (hasExactPin && !hasStalePin) return;\n const kept = plugins.filter((p) => !isOurs(p));\n config.plugin = [...kept, OPENCODE_CODEX_PLUGIN];\n await writeJsonFile(path, config);\n logger.info(\"ensured opencode codex-auth plugin in config\");\n}\n\n/**\n * Best-effort seed of opencode's oauth store + plugin config. No-op when\n * CONVEYOR_OPENCODE_OAUTH is absent or unparseable. Never throws.\n */\nexport async function seedOpenCodeOauth(env: NodeJS.ProcessEnv): Promise<void> {\n const seed = parseOauthSeed(env.CONVEYOR_OPENCODE_OAUTH);\n if (!seed) return;\n try {\n await ensureAuthEntry(env, seed);\n await ensurePluginConfig(env);\n } catch (err) {\n logger.warn(\n `failed to seed opencode oauth store: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n","/**\n * OpenCodeTuiAdapter — drives the `opencode` TUI (https://opencode.ai) as a\n * raw relayed terminal. v1 declares NO structured events (no trusted\n * transcript/hook source is wired), no prefill, no passive turns, and no\n * resume (--continue behavior on an empty state dir is unverified; enable\n * after live verification). Auth is env-based for api_key keys\n * (CONVEYOR_AGENT_KEY → provider-native env var) and store-based for\n * chatgpt_oauth keys (CONVEYOR_OPENCODE_OAUTH seeded into opencode's\n * auth.json by prepareEnvironment — see opencode-auth.ts).\n */\nimport { buildPromptBytes, inheritedEnv } from \"../pty-support.js\";\nimport { cleanTerminalOutput } from \"../spawn-args.js\";\nimport { seedOpenCodeOauth } from \"./opencode-auth.js\";\nimport {\n findOnPath,\n TuiUnavailableError,\n type TuiAdapter,\n type TuiCapabilities,\n type TuiFingerprintInput,\n type TuiSpawnInput,\n type TuiSpawnSpec,\n} from \"./types.js\";\n\n/** provider → the env var its SDK/CLI reads natively. */\nconst PROVIDER_KEY_ENV: Record<string, string> = {\n openai: \"OPENAI_API_KEY\",\n anthropic: \"ANTHROPIC_API_KEY\",\n};\n\nexport class OpenCodeTuiAdapter implements TuiAdapter {\n readonly id = \"opencode\" as const;\n readonly capabilities: TuiCapabilities = {\n resume: false,\n structuredEvents: false,\n prefill: false,\n passiveTurns: false,\n };\n\n constructor(private readonly env: NodeJS.ProcessEnv = process.env) {}\n\n resolveBinary(env: NodeJS.ProcessEnv = this.env): string {\n const override = env.CONVEYOR_OPENCODE_BIN;\n const found = override ? findOnPath(override, env) : findOnPath(\"opencode\", env);\n if (!found) {\n throw new TuiUnavailableError(\n \"opencode\",\n \"The opencode CLI is not available in this environment. It must be baked \" +\n \"into the pod image (see Dockerfile.base) — re-run Build Image for this \" +\n \"project, or set CONVEYOR_OPENCODE_BIN to its absolute path.\",\n );\n }\n return found;\n }\n\n buildSpawn(input: TuiSpawnInput): TuiSpawnSpec {\n const env = { ...inheritedEnv() };\n delete env.CONVEYOR_AGENT_KEY;\n delete env.CONVEYOR_OPENCODE_OAUTH;\n const oauthActive = Boolean(this.env.CONVEYOR_OPENCODE_OAUTH);\n const key = this.env.CONVEYOR_AGENT_KEY;\n const provider = this.env.CONVEYOR_AGENT_PROVIDER ?? \"openai\";\n const keyEnvVar = PROVIDER_KEY_ENV[provider];\n // ChatGPT-subscription auth flows through the opencode auth store (see\n // opencode-auth.ts) — a provider API key would override it to paid billing.\n if (key && keyEnvVar && !oauthActive) env[keyEnvVar] = key;\n\n const model = this.env.CONVEYOR_AGENT_MODEL ?? input.options.model;\n const args: string[] = [];\n if (model) args.push(\"--model\", model.includes(\"/\") ? model : `${provider}/${model}`);\n return { file: this.resolveBinary(), args, env };\n }\n\n async prepareEnvironment(): Promise<void> {\n // ChatGPT-subscription tokens (when present) are seeded into opencode's\n // auth store; session-state persistence stays the entrypoint's job\n // (GCS-FUSE symlinks for ~/.local/share/opencode).\n await seedOpenCodeOauth(this.env);\n }\n\n spawnFingerprint(input: TuiFingerprintInput): string {\n return JSON.stringify([\"opencode\", input.model, input.cwd]);\n }\n\n encodePromptBytes(text: string): string {\n // Bracketed paste — standard for modern TUIs; revisit if live verification\n // shows opencode's input mishandles it.\n return buildPromptBytes(text);\n }\n\n buildExitErrors(exitCode: number, rawOutput: string): string[] {\n const errors = [`opencode exited (code ${exitCode}) without a result`];\n const tail = cleanTerminalOutput(rawOutput);\n if (tail) errors.push(`Last terminal output before exit:\\n${tail}`);\n return errors;\n }\n}\n","import type { TuiAdapter, TuiKind } from \"./types.js\";\nimport { ClaudeTuiAdapter } from \"./claude.js\";\nimport { OpenCodeTuiAdapter } from \"./opencode.js\";\n\nexport * from \"./types.js\";\nexport { ClaudeTuiAdapter } from \"./claude.js\";\nexport { OpenCodeTuiAdapter } from \"./opencode.js\";\n\n/** Adapter factory. */\nexport function resolveTuiAdapter(kind: TuiKind = \"claude-code\"): TuiAdapter {\n switch (kind) {\n case \"claude-code\":\n return new ClaudeTuiAdapter();\n case \"opencode\":\n return new OpenCodeTuiAdapter();\n default:\n throw new Error(`Unknown TUI kind: ${kind as string}`);\n }\n}\n","/**\n * Project-scoped tools for TASK-LESS sessions (headless audits on ad-hoc\n * pods). Everything is keyed on the projectId the runner was booted with —\n * there is no task, so none of these resolve state from the session's task.\n *\n * Two families:\n * - Tag-audit apply surface: list/create/update tags, suggestions, project chat.\n * - Task-audit evidence + reporting: cross-task reads (task, chat, execution\n * logs) and reportTaskAuditResult persistence.\n */\nimport { z } from \"zod\";\nimport type { AgentSessionServiceMethods } from \"@project/shared\";\nimport { defineTool } from \"../harness/index.js\";\nimport { textResult } from \"./helpers.js\";\n\n/**\n * The one connection capability these tools need — satisfied by the real\n * AgentConnection and by the adhoc runner's injectable AdhocRunnerConnection.\n */\nexport interface ProjectToolsConnection {\n call<M extends keyof AgentSessionServiceMethods>(\n method: M,\n payload: AgentSessionServiceMethods[M][\"payload\"],\n ): Promise<AgentSessionServiceMethods[M][\"response\"]>;\n}\n\nconst CONTEXT_PATH_SHAPE = z.object({\n type: z.enum([\"rule\", \"doc\", \"file\", \"folder\"]).describe(\"Link kind\"),\n path: z.string().min(1).max(500).describe(\"Repo-relative path\"),\n label: z.string().max(100).optional(),\n});\n\nfunction errText(prefix: string, error: unknown): { content: { type: \"text\"; text: string }[] } {\n return textResult(`${prefix}: ${error instanceof Error ? error.message : \"Unknown error\"}`);\n}\n\n// ── Tag audit surface ─────────────────────────────────────────────────\n\nfunction buildListTagsTool(connection: ProjectToolsConnection, projectId: string) {\n return defineTool(\n \"list_tags\",\n \"List this project's tags (id, name, color). Use the ids with update_tag.\",\n {},\n async () => {\n try {\n const tags = await connection.call(\"listProjectTags\", { projectId });\n return textResult(JSON.stringify(tags, null, 2));\n } catch (error) {\n return errText(\"Failed to list tags\", error);\n }\n },\n { annotations: { readOnlyHint: true } },\n );\n}\n\nfunction buildCreateTagTool(connection: ProjectToolsConnection, projectId: string) {\n return defineTool(\n \"create_tag\",\n \"Create a project tag. Include a crisp description and contextPaths (rule/doc/file/folder links agents auto-load when working on matching tasks). Fails if the name already exists.\",\n {\n name: z.string().min(1).max(50),\n color: z\n .string()\n .regex(/^#[0-9a-fA-F]{6}$/)\n .optional()\n .describe(\"#RRGGBB (default gray)\"),\n description: z.string().max(500).optional(),\n contextPaths: z.array(CONTEXT_PATH_SHAPE).max(20).optional(),\n },\n async ({ name, color, description, contextPaths }) => {\n try {\n const result = await connection.call(\"createProjectTag\", {\n projectId,\n name,\n color,\n description,\n contextPaths,\n });\n return textResult(`Tag created: ${result.id}`);\n } catch (error) {\n return errText(\"Failed to create tag\", error);\n }\n },\n );\n}\n\nfunction buildUpdateTagTool(connection: ProjectToolsConnection, projectId: string) {\n return defineTool(\n \"update_tag\",\n \"Update a tag's name, color, description, or contextPaths. contextPaths is a FULL replacement — include existing links you want to keep. Verify paths exist in the repo first.\",\n {\n tagId: z.string().describe(\"Tag id from list_tags\"),\n name: z.string().min(1).max(50).optional(),\n color: z\n .string()\n .regex(/^#[0-9a-fA-F]{6}$/)\n .optional(),\n description: z.string().max(500).optional(),\n contextPaths: z.array(CONTEXT_PATH_SHAPE).max(20).optional(),\n },\n async ({ tagId, name, color, description, contextPaths }) => {\n try {\n await connection.call(\"updateProjectTag\", {\n projectId,\n tagId,\n name,\n color,\n description,\n contextPaths,\n });\n return textResult(`Tag updated: ${tagId}`);\n } catch (error) {\n return errText(\"Failed to update tag\", error);\n }\n },\n );\n}\n\nfunction buildCreateSuggestionTool(connection: ProjectToolsConnection, projectId: string) {\n return defineTool(\n \"create_suggestion\",\n \"File a project suggestion (idea/improvement for maintainers to review). Duplicates are AI-deduped into an existing suggestion with an upvote. Returns the suggestion id.\",\n {\n title: z.string().min(1).describe(\"Short title\"),\n description: z.string().optional().describe(\"1-3 sentences: what should change and why\"),\n tag_names: z.array(z.string()).optional().describe(\"Tag names to categorize\"),\n },\n async ({ title, description, tag_names }) => {\n try {\n const result = await connection.call(\"createProjectSuggestion\", {\n projectId,\n title,\n description,\n tagNames: tag_names,\n });\n return textResult(\n result.merged\n ? `Merged into existing suggestion ${result.mergedIntoId ?? result.id} (id: ${result.id})`\n : `Suggestion created: ${result.id}`,\n );\n } catch (error) {\n return errText(\"Failed to create suggestion\", error);\n }\n },\n );\n}\n\nfunction buildPostToProjectChatTool(connection: ProjectToolsConnection, projectId: string) {\n return defineTool(\n \"post_to_project_chat\",\n \"Post a markdown message to the PROJECT chat — use once at the end of an audit for the summary the team reads.\",\n {\n message: z.string().min(1).max(20000),\n kind: z\n .enum([\"tag_audit_summary\"])\n .optional()\n .describe(\n \"Set to 'tag_audit_summary' when posting a tag-audit summary so it is also saved to the persistent tag history\",\n ),\n },\n async ({ message, kind }) => {\n try {\n await connection.call(\"postToProjectChat\", { projectId, content: message, kind });\n return textResult(\"Posted to project chat\");\n } catch (error) {\n return errText(\"Failed to post to project chat\", error);\n }\n },\n );\n}\n\n// ── Task audit surface ────────────────────────────────────────────────\n\nfunction buildGetProjectTaskTool(connection: ProjectToolsConnection, projectId: string) {\n return defineTool(\n \"get_project_task\",\n \"Fetch any task in the project by id or slug: title, description, plan, status, and metadata. The audit evidence trail starts here.\",\n {\n taskId: z.string().describe(\"Task id or slug\"),\n },\n async ({ taskId }) => {\n try {\n const task = await connection.call(\"getProjectTask\", { projectId, taskId });\n return textResult(JSON.stringify(task, null, 2));\n } catch (error) {\n return errText(\"Failed to get task\", error);\n }\n },\n { annotations: { readOnlyHint: true } },\n );\n}\n\nfunction buildReadProjectTaskChatTool(connection: ProjectToolsConnection, projectId: string) {\n return defineTool(\n \"read_project_task_chat\",\n \"Read any project task's chat messages (newest last). role 'user' rows are HUMAN turns; 'assistant'/'system' rows are agent posts and activity-log entries.\",\n {\n taskId: z.string().describe(\"Task id or slug\"),\n limit: z.number().int().min(1).max(200).optional().describe(\"Messages to fetch (default 50)\"),\n },\n async ({ taskId, limit }) => {\n try {\n const chat = await connection.call(\"getProjectTaskChat\", {\n projectId,\n taskId,\n limit: limit ?? 50,\n });\n return textResult(JSON.stringify(chat, null, 2));\n } catch (error) {\n return errText(\"Failed to read task chat\", error);\n }\n },\n { annotations: { readOnlyHint: true } },\n );\n}\n\nfunction buildGetProjectTaskLogsTool(connection: ProjectToolsConnection, projectId: string) {\n return defineTool(\n \"get_project_task_logs\",\n \"Read any project task's persisted agent event stream (message / tool_use / turn_end / error / completed). Turn boundaries are turn_end events. Entries are truncated to ~2KB each; max 500 per call.\",\n {\n taskId: z.string().describe(\"Task id or slug\"),\n limit: z.number().int().min(1).max(500).optional().describe(\"Entries to fetch (default 50)\"),\n source: z\n .enum([\"agent\", \"application\"])\n .optional()\n .describe(\"Filter: 'agent' = model events (default useful for grading)\"),\n },\n async ({ taskId, limit, source }) => {\n try {\n const logs = await connection.call(\"getProjectTaskCli\", {\n projectId,\n taskId,\n limit: limit ?? 50,\n source,\n });\n return textResult(JSON.stringify(logs, null, 2));\n } catch (error) {\n return errText(\"Failed to get task logs\", error);\n }\n },\n { annotations: { readOnlyHint: true } },\n );\n}\n\nconst TURN_GRADE_SHAPE = z.object({\n turnIndex: z.number().int().min(0),\n phase: z.enum([\"planning\", \"building\", \"human\"]),\n grade: z.enum([\"correct\", \"neutral\", \"blunder\"]),\n reasoning: z.string(),\n eventType: z.string().describe('e.g. \"message\", \"tool_use\", \"human_message\"'),\n eventSummary: z.string().max(200).describe(\"≤120 chars of what happened this turn\"),\n});\n\nconst HUMAN_EVAL_SHAPE = z.object({\n messageIndex: z.number().int().min(0).describe(\"Index into the task's human messages, oldest first\"),\n rating: z.number().int().min(-1).max(1),\n reasoning: z.string(),\n});\n\nfunction buildReportTaskAuditResultTool(connection: ProjectToolsConnection, projectId: string) {\n return defineTool(\n \"report_task_audit_result\",\n \"Persist one audited task's grades (call once per task after grading it). Pass error instead to mark the audit failed when the evidence is unusable.\",\n {\n taskId: z.string().describe(\"The audited task's id (NOT slug)\"),\n summary: z.string().describe(\"3-6 sentences: what went well, what was wasted\"),\n turnGrades: z.array(TURN_GRADE_SHAPE),\n planningAccuracy: z.number().min(0).max(1).nullable(),\n buildingAccuracy: z.number().min(0).max(1).nullable(),\n humanAccuracy: z.number().min(0).max(1).nullable(),\n planningCorrect: z.number().int().min(0),\n planningNeutral: z.number().int().min(0),\n planningBlunder: z.number().int().min(0),\n buildingCorrect: z.number().int().min(0),\n buildingNeutral: z.number().int().min(0),\n buildingBlunder: z.number().int().min(0),\n humanCorrect: z.number().int().min(0),\n humanNeutral: z.number().int().min(0),\n humanBlunder: z.number().int().min(0),\n humanEvaluations: z.array(HUMAN_EVAL_SHAPE).optional(),\n suggestionIds: z.array(z.string()).describe(\"Suggestion ids filed for this task, or []\"),\n auditCostUsd: z.number().nullable(),\n model: z.string().nullable().describe(\"The model you are running as\"),\n error: z.string().optional().describe(\"Set ONLY to mark this task's audit failed\"),\n },\n async (input) => {\n try {\n await connection.call(\"reportTaskAuditResult\", {\n projectId,\n ...input,\n humanEvaluations: (input.humanEvaluations ?? []) as Array<{\n messageIndex: number;\n rating: -1 | 0 | 1;\n reasoning: string;\n }>,\n });\n return textResult(\n input.error\n ? `Audit for ${input.taskId} marked failed`\n : `Audit result saved for ${input.taskId}`,\n );\n } catch (error) {\n return errText(\"Failed to report audit result\", error);\n }\n },\n );\n}\n\n// ── Assembly ──────────────────────────────────────────────────────────\n\n/** The full project-scoped tool surface a headless (task-less) session gets. */\nexport function buildProjectTools(connection: ProjectToolsConnection, projectId: string) {\n return [\n buildListTagsTool(connection, projectId),\n buildCreateTagTool(connection, projectId),\n buildUpdateTagTool(connection, projectId),\n buildCreateSuggestionTool(connection, projectId),\n buildPostToProjectChatTool(connection, projectId),\n buildGetProjectTaskTool(connection, projectId),\n buildReadProjectTaskChatTool(connection, projectId),\n buildGetProjectTaskLogsTool(connection, projectId),\n buildReportTaskAuditResultTool(connection, projectId),\n ];\n}\n","/* oxlint-disable import/max-dependencies -- cohesive ad-hoc runner lifecycle wiring */\n/**\n * AdhocSessionRunner — the task-less USER SCRATCH pod agent loop (Sessions view\n * \"Launch ad-hoc session\"). Claudespace v3, `Workspace.purpose = \"adhoc\"`.\n *\n * Unlike the ProjectSessionRunner (autonomous pm) it runs NO autonomous loop:\n * it spawns the `claude` CLI under a pseudo-terminal in interactive/prefill mode\n * (empty input box, no auto-submit) and relays raw terminal I/O to the S2 relay,\n * so the web Sessions terminal (S5) renders it and forwards keystrokes back. The\n * human drives it directly — there is no task, plan, or Conveyor MCP tool\n * surface. Connect / register / heartbeat / idle are shared with the project\n * runner; the difference is the interactive PTY spawn.\n *\n * Idle-sleep is server-owned (decideFate + activity/tunnel holds): an idle\n * adhoc pod sleeps after the idle window like any workspace; the human wakes it\n * from the Sessions list. The agent's own idle timer is the secondary backstop.\n */\nimport { AgentConnection, type AgentConnectionConfig } from \"../connection/agent-connection.js\";\nimport { Lifecycle, DEFAULT_LIFECYCLE_CONFIG, type LifecycleConfig } from \"./lifecycle.js\";\nimport { resolveSessionStart } from \"../execution/query-executor.js\";\nimport { resolvePlaywrightMcpServer } from \"../execution/playwright-mcp.js\";\nimport { sampleKeyUsage } from \"../execution/usage-sampler.js\";\nimport { probeKeysUsage } from \"../usage/multi-key-probe.js\";\nimport { PtyHarness } from \"../harness/pty/index.js\";\nimport { resolveTuiAdapter } from \"../harness/pty/adapters/index.js\";\nimport { TUI_KINDS, type TuiKind } from \"../harness/pty/adapters/types.js\";\nimport type {\n AgentHarness,\n HarnessMcpServer,\n HarnessQueryOptions,\n PtyBridge,\n} from \"../harness/types.js\";\nimport { PortDiscovery } from \"./port-discovery.js\";\nimport { loadConveyorConfig } from \"../setup/config.js\";\nimport { WorkspaceCommandSupervisor } from \"../setup/workspace-command-supervisor.js\";\nimport { buildProjectTools } from \"../tools/project-tools.js\";\nimport {\n DEFAULT_SONNET_MODEL,\n type AgentSessionServiceMethods,\n type PtyChatEventPayload,\n type WorkspaceDiscoveredPort,\n} from \"@project/shared\";\n\nconst ADHOC_SYSTEM_NOTE =\n \"You are running in an ad-hoc Conveyor scratch pod — an interactive terminal \" +\n \"on the project's repository checked out at its default branch. There is no \" +\n \"task or plan; help the human with whatever they ask directly.\";\n\nconst HEADLESS_SYSTEM_NOTE =\n \"You are running a HEADLESS Conveyor session on the project's repository — \" +\n \"your instructions were auto-submitted as the first message. Work them to \" +\n \"completion autonomously and never wait for user input; a human may attach \" +\n \"to this terminal to watch or interject, but none is required.\";\n\n/**\n * Headless sessions: the bootstrap bundle carries the server-assembled\n * instructions as base64 (only while un-submitted — see\n * build-bootstrap-bundle.ts). Absent/blank/undecodable → interactive ad-hoc.\n */\nexport function resolveInitialPrompt(env: NodeJS.ProcessEnv = process.env): string | null {\n const b64 = env.CONVEYOR_INITIAL_PROMPT_B64;\n if (!b64) return null;\n try {\n const decoded = Buffer.from(b64, \"base64\").toString(\"utf8\").trim();\n return decoded.length > 0 ? decoded : null;\n } catch {\n return null;\n }\n}\n\nexport interface AdhocSessionRunnerConfig {\n connection: AgentConnectionConfig;\n projectId: string;\n /**\n * Stable `Workspace` row id — the Claude session lineage key. Deliberately\n * NOT `connection.sessionId`: that's the `WorkspaceSession` row, which is\n * re-minted (fresh-session semantics) on every user-initiated wake, so\n * keying resume on it would never find the prior GCS-FUSE transcript.\n */\n workspaceId: string;\n /** Repo checkout the interactive CLI runs in. */\n workspaceDir: string;\n /** Model override; falls back to CONVEYOR_ADHOC_MODEL env, then the default. */\n model?: string;\n /**\n * Headless sessions: instructions to auto-submit as the first message\n * (flips prompt delivery to \"submit\" and mounts the project tool surface).\n * ONLY the top-level adhoc boot (cli.ts) resolves this from the bundle env —\n * spawned same-pod tabs must never inherit it, or a \"New Claude tab\" on a\n * headless pod would re-run the audit.\n */\n initialPrompt?: string | null;\n lifecycle?: Partial<LifecycleConfig>;\n}\n\nexport interface AdhocSessionRunnerCallbacks {\n onEvent?: (event: Record<string, unknown>) => void;\n}\n\n/** AgentConnection surface the adhoc runner needs (injectable for tests). */\nexport interface AdhocRunnerConnection {\n connect(): Promise<void>;\n disconnect(): void;\n call<M extends keyof AgentSessionServiceMethods>(\n method: M,\n payload: AgentSessionServiceMethods[M][\"payload\"],\n ): Promise<AgentSessionServiceMethods[M][\"response\"]>;\n sendEvent(event: { type: string; [key: string]: unknown }): void;\n sendHeartbeat(): void;\n emitStatus(status: string): Promise<void>;\n onStop(callback: () => void): void;\n refreshTaskTokenFromBootstrap(): Promise<boolean>;\n sendPtyOutput(data: string, dims?: { cols: number; rows: number }): void;\n sendPtyChatEvent(event: PtyChatEventPayload): void;\n onPtyInput(handler: (data: string) => void): () => void;\n onPtyResize(handler: (cols: number, rows: number) => void): () => void;\n reportDiscoveredPorts(ports: WorkspaceDiscoveredPort[]): Promise<void>;\n onRunStartCommand(callback: () => void): void;\n onProbeUsage(callback: () => void): void;\n}\n\nexport interface AdhocPortDiscovery {\n start(): Promise<void>;\n stop(): void;\n}\n\nexport interface AdhocWorkspaceCommandSupervisor {\n start(): void;\n stop(): Promise<void>;\n}\n\n/** Which TUI this adhoc pod runs — from the bootstrap bundle's CONVEYOR_TUI.\n * Unknown values throw (fail loudly): a typo'd config must not silently run\n * Claude. */\nexport function resolveAdhocTui(env: NodeJS.ProcessEnv): TuiKind {\n const raw = env.CONVEYOR_TUI ?? \"claude-code\";\n if ((TUI_KINDS as readonly string[]).includes(raw)) return raw as TuiKind;\n throw new Error(`Unknown TUI \"${raw}\" in CONVEYOR_TUI (expected: ${TUI_KINDS.join(\", \")})`);\n}\n\n/** Adapt an AdhocRunnerConnection into the harness-neutral PtyBridge. */\nexport function buildAdhocPtyBridge(connection: AdhocRunnerConnection): PtyBridge {\n return {\n sendOutput: (data, dims) => connection.sendPtyOutput(data, dims),\n sendChatEvent: (event) => connection.sendPtyChatEvent(event),\n onInput: (handler) => connection.onPtyInput(handler),\n onResize: (handler) => connection.onPtyResize(handler),\n };\n}\n\n/** The interactive-spawn options for an ad-hoc scratch TUI (no task context). */\nexport function buildAdhocQueryOptions(\n workspaceDir: string,\n model: string,\n abortController: AbortController,\n // Deterministic session start (fresh `sessionId` or `resume` target). Without\n // one, PtySession.start() throws \"requires options.sessionId or a resume\n // target\" and the pool crash-loops the runner — the interactive PTY never\n // spawns. Mutually exclusive: exactly one of the two is ever set.\n session?: { sessionId?: string; resume?: string },\n // Environment for PATH-based binary resolution (playwright-mcp). Injectable\n // so tests are deterministic regardless of what the host has baked on PATH\n // (claudespace pods ship /usr/local/bin/playwright-mcp; dev machines don't).\n env: NodeJS.ProcessEnv = process.env,\n // Headless mode: an initial prompt flips delivery to auto-submit and mounts\n // the project-scoped Conveyor tool surface (interactive adhoc gets neither).\n headless?: { initialPrompt: string; conveyorMcpServer?: HarnessMcpServer },\n): HarnessQueryOptions {\n const systemNote = headless ? HEADLESS_SYSTEM_NOTE : ADHOC_SYSTEM_NOTE;\n return {\n model,\n systemPrompt: { type: \"preset\", preset: \"claude_code\", append: systemNote },\n appendSystemPrompt: systemNote,\n cwd: workspaceDir,\n // Human-driven interactive shell — no plan-mode gating. (Headless audit\n // runs keep the same bypass: they must finish with no one at the terminal.)\n permissionMode: \"bypassPermissions\",\n allowDangerouslySkipPermissions: true,\n tools: { type: \"preset\", preset: \"claude_code\" },\n mcpServers: (() => {\n const playwright = resolvePlaywrightMcpServer(env);\n return {\n ...(playwright ? { playwright } : {}),\n ...(headless?.conveyorMcpServer ? { conveyor: headless.conveyorMcpServer } : {}),\n };\n })(),\n settingSources: [\"user\", \"project\"],\n // Interactive: empty box, unsubmitted — the human types the first prompt.\n // Headless: paste + submit the server-assembled instructions immediately.\n promptDelivery: headless ? \"submit\" : \"prefill\",\n abortController,\n ...(session?.sessionId ? { sessionId: session.sessionId } : {}),\n ...(session?.resume ? { resume: session.resume } : {}),\n };\n}\n\nexport class AdhocSessionRunner {\n readonly connection: AdhocRunnerConnection;\n readonly lifecycle: Lifecycle;\n private readonly harness: AgentHarness;\n private readonly portDiscovery: AdhocPortDiscovery;\n private readonly commandSupervisor: AdhocWorkspaceCommandSupervisor;\n\n private readonly config: AdhocSessionRunnerConfig;\n private readonly callbacks: AdhocSessionRunnerCallbacks;\n private readonly abortController = new AbortController();\n private stopped = false;\n private stopResolver: (() => void) | null = null;\n private _finalState: \"finished\" | \"error\" | null = null;\n\n constructor(\n config: AdhocSessionRunnerConfig,\n callbacks: AdhocSessionRunnerCallbacks = {},\n deps?: {\n connection?: AdhocRunnerConnection;\n harness?: AgentHarness;\n portDiscovery?: AdhocPortDiscovery;\n commandSupervisor?: AdhocWorkspaceCommandSupervisor;\n },\n ) {\n this.config = config;\n this.callbacks = callbacks;\n this.connection = deps?.connection ?? new AgentConnection(config.connection);\n this.harness =\n deps?.harness ??\n new PtyHarness(\n buildAdhocPtyBridge(this.connection),\n resolveTuiAdapter(resolveAdhocTui(process.env)),\n );\n this.portDiscovery =\n deps?.portDiscovery ??\n new PortDiscovery({\n report: (ports) => this.connection.reportDiscoveredPorts(ports),\n });\n this.commandSupervisor =\n deps?.commandSupervisor ??\n new WorkspaceCommandSupervisor({\n config: loadConveyorConfig(),\n workspaceDir: config.workspaceDir,\n connection: this.connection,\n });\n this.lifecycle = new Lifecycle(\n // No git flush: the WIP snapshot machinery is branch/task-shaped; the human\n // commits/pushes explicitly from the interactive shell.\n { ...DEFAULT_LIFECYCLE_CONFIG, gitFlushIntervalMs: 0, ...config.lifecycle },\n {\n onHeartbeat: () => this.connection.sendHeartbeat(),\n onIdleTimeout: () => this.requestStop(),\n onDormantTimeout: () => this.requestStop(),\n onTokenRefresh: () => void this.connection.refreshTaskTokenFromBootstrap().catch(() => {}),\n onGitFlush: () => {},\n onUsageSample: () => void this.sampleAndReportAllKeys(),\n },\n );\n }\n\n get finalState(): \"finished\" | \"error\" | null {\n return this._finalState;\n }\n\n get isStopped(): boolean {\n return this.stopped;\n }\n\n /** Connect, register, spawn the interactive TUI, and relay it until stopped. */\n async run(): Promise<void> {\n try {\n await this.connection.connect();\n this.connection.sendEvent({\n type: \"connected\",\n sessionId: this.config.connection.sessionId,\n projectId: this.config.projectId,\n });\n this.connection.onStop(() => this.requestStop());\n // On-demand \"Refresh usage\" push (server → pod): re-sample every key now.\n this.connection.onProbeUsage(() => void this.sampleAndReportAllKeys());\n this.lifecycle.startHeartbeat();\n this.lifecycle.startTokenRefresh();\n this.lifecycle.startUsageSample();\n\n await this.connection.call(\"connectAgent\", {\n sessionId: this.config.connection.sessionId,\n });\n await this.portDiscovery.start().catch(() => {});\n if (this.stopped) {\n this._finalState = \"finished\";\n return;\n }\n this.commandSupervisor.start();\n await this.connection.emitStatus(\"running\");\n this.callbacks.onEvent?.({ type: \"adhoc_runner_started\", projectId: this.config.projectId });\n this.lifecycle.startIdleTimer();\n\n await this.runInteractiveTui();\n this._finalState = \"finished\";\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[conveyor-agent] Ad-hoc runner failed: ${message}\\n`);\n this.connection.sendEvent({ type: \"error\", message });\n this._finalState = \"error\";\n } finally {\n await this.shutdown();\n }\n }\n\n /**\n * Drive the `claude` CLI under a PTY. The bridge relays raw stdout to S2/S5\n * and forwards keystrokes back, so consuming the event stream is enough — the\n * loop blocks (keeping the pod alive) until the human exits or stop() aborts.\n */\n private async runInteractiveTui(): Promise<void> {\n const model =\n this.config.model ??\n process.env.CONVEYOR_AGENT_MODEL ??\n process.env.CONVEYOR_ADHOC_MODEL ??\n DEFAULT_SONNET_MODEL;\n // Key the CLI session on the stable workspace id (NOT connection.sessionId\n // — see the field doc on AdhocSessionRunnerConfig.workspaceId): a fresh\n // pod spawns a new session, a woken pod resumes the GCS-FUSE-persisted\n // transcript.\n const session = resolveSessionStart(this.config.workspaceId, this.config.workspaceDir);\n // Headless: the bundle delivered un-submitted audit instructions — mount\n // the project tool surface and auto-submit them as the first message.\n const initialPrompt = this.config.initialPrompt ?? null;\n const headless = initialPrompt\n ? {\n initialPrompt,\n conveyorMcpServer: this.harness.createMcpServer({\n name: \"conveyor\",\n tools: buildProjectTools(this.connection, this.config.projectId),\n }),\n }\n : undefined;\n const options = buildAdhocQueryOptions(\n this.config.workspaceDir,\n model,\n this.abortController,\n session,\n process.env,\n headless,\n );\n let promptMarked = false;\n try {\n for await (const event of this.harness.executeQuery({\n prompt: initialPrompt ?? \"\",\n options,\n })) {\n if (this.stopped) break;\n if (initialPrompt && !promptMarked) {\n // First harness event = the CLI spawned and the submit landed. Mark\n // the prompt consumed so a sleep→wake (or pod replacement) boots\n // plain-interactive instead of re-running the audit. Best-effort:\n // the server-side gate is idempotent and a missed mark only risks a\n // re-run, never a crash.\n promptMarked = true;\n void this.connection\n .call(\"markInitialPromptSubmitted\", { sessionId: this.config.connection.sessionId })\n .catch(() => {});\n }\n if (event.type === \"result\" && event.subtype === \"error\") {\n // Raw-mode adapters surface spawn/exit failures as a result error —\n // fail the run loudly so the Sessions UI shows the reason.\n throw new Error(event.errors.join(\"\\n\"));\n }\n }\n } catch (error) {\n // An aborted interactive session is the normal stop path, not a failure.\n if (!this.stopped) throw error;\n }\n }\n\n stop(): void {\n this.requestStop();\n }\n\n private requestStop(): void {\n if (this.stopped) return;\n this.stopped = true;\n this.portDiscovery.stop();\n void this.commandSupervisor.stop();\n this.abortController.abort();\n if (this.stopResolver) {\n const resolve = this.stopResolver;\n this.stopResolver = null;\n resolve();\n }\n }\n\n /**\n * Multi-key usage refresh: ask the server for every subscription key the\n * OWNER has, probe each one's `/usage` from THIS pod (isolated per key), and\n * report each key's gauges tagged with its explicit `codingAgentKeyId`. Falls\n * back to the single-key self-sample when the owner has no probeable keys\n * (e.g. API-key-only, or all decrypts failed). Best-effort — never throws.\n */\n private async sampleAndReportAllKeys(): Promise<void> {\n if (this.stopped) return;\n let keys: { codingAgentKeyId: string; oauthToken: string }[] = [];\n try {\n const res = await this.connection.call(\"listKeysToProbe\", {\n sessionId: this.config.connection.sessionId,\n });\n keys = res?.keys ?? [];\n } catch {\n // Server unreachable / method unavailable — fall back to the self-sample.\n }\n if (keys.length === 0) {\n await this.sampleAndReportOwnKey();\n return;\n }\n const probed = await probeKeysUsage(keys);\n for (const { codingAgentKeyId, samples } of probed) {\n for (const sample of samples) {\n this.connection.sendEvent({\n type: \"rate_limit_update\",\n rateLimitType: sample.rateLimitType,\n utilization: sample.utilization,\n status: sample.status,\n resetsAt: sample.resetsAt ?? undefined,\n gauges: sample.gauges,\n codingAgentKeyId,\n });\n }\n }\n }\n\n /** Single-key fallback: sample only the key this pod booted under. */\n private async sampleAndReportOwnKey(): Promise<void> {\n if (this.stopped) return;\n const samples = await sampleKeyUsage(process.env.CLAUDE_CODE_OAUTH_TOKEN);\n for (const sample of samples) {\n this.connection.sendEvent({\n type: \"rate_limit_update\",\n rateLimitType: sample.rateLimitType,\n utilization: sample.utilization,\n status: sample.status,\n resetsAt: sample.resetsAt ?? undefined,\n gauges: sample.gauges,\n });\n }\n }\n\n private async shutdown(): Promise<void> {\n this.stopped = true;\n this.portDiscovery.stop();\n await this.commandSupervisor.stop();\n this.lifecycle.destroy();\n this.connection.sendEvent({ type: \"shutdown\", reason: this._finalState ?? \"finished\" });\n this.connection.disconnect();\n }\n}\n","/**\n * Same-pod review child supervisor. When the API parks a review session on\n * this (builder) pod and pushes `session:spawnReview`, the supervisor spawns a\n * SECOND conveyor-agent process — same CLI binary, same repo checkout — bound\n * to the review session via env overrides. The child owns its own\n * AgentConnection/PTY stream, so the card's \"Reviewer\" terminal tab appears\n * through the normal multi-session relay with no relay changes.\n *\n * Single-slot: a new spawn (re-review of a fresh push) kills and replaces the\n * previous child. Spawn failures are reported back to the API\n * (`reportReviewSpawnFailure`), which Ends the orphaned session and falls back\n * to a dedicated review pod.\n *\n * Shared-checkout caveat (v1, deliberate): the reviewer reads the builder's\n * working tree. At review time the builder is parked (ReviewPR + CI green),\n * so contention is low; a best-effort ff-only fetch freshens the branch. A\n * human typing in the builder TUI mid-review can still dirty the tree —\n * worktree isolation is a deferred follow-up.\n */\nimport { spawn as nodeSpawn, execFile, type ChildProcess } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { SpawnReviewData } from \"../connection/agent-connection.js\";\nimport { createServiceLogger } from \"../utils/logger.js\";\n\nconst execFileAsync = promisify(execFile);\nconst logger = createServiceLogger(\"ReviewChild\");\n\n/** Exit inside this window (non-zero) is treated as a spawn failure. */\nexport const SPAWN_FAILURE_GRACE_MS = 15_000;\n/** How long to wait for a SIGTERM'd child before SIGKILL. */\nexport const KILL_WAIT_MS = 5_000;\n\nexport interface ReviewChildConnection {\n reportReviewSpawnFailure(reviewSessionId: string, error?: string): void;\n}\n\nexport type SpawnFn = (\n command: string,\n args: string[],\n options: {\n cwd: string;\n env: NodeJS.ProcessEnv;\n stdio: [\"ignore\", \"pipe\", \"pipe\"];\n },\n) => ChildProcess;\n\n/**\n * Build the child env from the builder's env. The child is the same CLI in\n * `code-review` mode, so it reuses the pod's credentials (git, Anthropic)\n * while swapping in the review session's identity.\n */\nexport function buildReviewChildEnv(\n baseEnv: NodeJS.ProcessEnv,\n data: SpawnReviewData,\n): NodeJS.ProcessEnv {\n const env: NodeJS.ProcessEnv = { ...baseEnv };\n // The review session's identity: its own JWT + sessionId, review runner\n // mode. CONVEYOR_TASK_ID stays the parent's — same task (SEC-9 derives the\n // task from the JWT server-side).\n env.CONVEYOR_TASK_TOKEN = data.sessionJwt;\n env.CONVEYOR_SESSION_ID = data.sessionId;\n env.CONVEYOR_MODE = \"code-review\";\n\n // The bootstrap-refresh path would replace the child's review JWT with the\n // BUILDER's writer JWT (findBundleSession prefers the live writer), silently\n // re-identifying the child as the builder. Reviews finish well inside the\n // 24h JWT TTL, so the child never needs a refresh — remove the tokens.\n delete env.POD_BOOTSTRAP_TOKEN;\n delete env.CONVEYOR_BOOTSTRAP_TOKEN;\n\n // The builder already ran (or is running) setup/start on this shared\n // workspace — the child must never re-run `bun install` or spawn a second\n // dev server.\n delete env.CONVEYOR_SETUP_COMMAND;\n delete env.CONVEYOR_START_COMMAND;\n\n // The code-review runner forces its own mode (review + auto); a stale\n // builder agent-mode hint must not leak in.\n delete env.CONVEYOR_AGENT_MODE;\n delete env.CONVEYOR_IS_AUTO;\n return env;\n}\n\nexport class ReviewChildSupervisor {\n private child: ChildProcess | null = null;\n private childSessionId: string | null = null;\n\n constructor(\n private readonly connection: ReviewChildConnection,\n private readonly workspaceDir: string,\n private readonly spawnFn: SpawnFn = nodeSpawn as SpawnFn,\n ) {}\n\n /** Spawn (or replace) the review child for a `session:spawnReview` push. */\n async spawn(data: SpawnReviewData): Promise<void> {\n logger.info(\"Spawning same-pod review child\", {\n reviewSessionId: data.sessionId,\n branch: data.branch ?? undefined,\n prNumber: data.prNumber ?? undefined,\n });\n await this.stopCurrent(\"superseded by new review spawn\");\n await this.refreshCheckout(data.branch ?? null);\n\n const env = buildReviewChildEnv(process.env, data);\n const cliPath = process.argv[1];\n if (!cliPath) {\n this.connection.reportReviewSpawnFailure(data.sessionId, \"cannot resolve CLI entry path\");\n return;\n }\n\n let child: ChildProcess;\n try {\n child = this.spawnFn(process.execPath, [cliPath], {\n cwd: this.workspaceDir,\n env,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n } catch (err) {\n this.connection.reportReviewSpawnFailure(\n data.sessionId,\n err instanceof Error ? err.message : String(err),\n );\n return;\n }\n\n this.child = child;\n this.childSessionId = data.sessionId;\n const spawnedAt = Date.now();\n let reported = false;\n const reportOnce = (message: string): void => {\n if (reported) return;\n reported = true;\n this.connection.reportReviewSpawnFailure(data.sessionId, message);\n };\n\n // Child output lands in the pod log (the entrypoint tees our stdio),\n // prefixed so builder and reviewer streams stay distinguishable.\n child.stdout?.on(\"data\", (chunk: Buffer) => {\n process.stdout.write(`[review-child] ${chunk.toString()}`);\n });\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n process.stderr.write(`[review-child] ${chunk.toString()}`);\n });\n\n child.on(\"error\", (err) => {\n logger.error(\"Review child spawn error\", { error: err.message });\n if (this.child === child) {\n this.child = null;\n this.childSessionId = null;\n }\n reportOnce(err.message);\n });\n\n child.on(\"exit\", (code, signal) => {\n const wasCurrent = this.child === child;\n if (wasCurrent) {\n this.child = null;\n this.childSessionId = null;\n }\n logger.info(\"Review child exited\", { code, signal, reviewSessionId: data.sessionId });\n // A non-zero exit right after launch means the child never became the\n // review agent — recover via the dedicated-pod fallback. Later exits\n // (review finished, server-sent session:stop, supersede kill) are\n // normal lifecycle: the server owns the session state there.\n const withinGrace = Date.now() - spawnedAt < SPAWN_FAILURE_GRACE_MS;\n if (wasCurrent && withinGrace && code !== null && code !== 0) {\n reportOnce(`review child exited with code ${code} within startup grace`);\n }\n });\n }\n\n /** Stop any live child (parent shutdown / supersede). Best-effort. */\n async stopAll(): Promise<void> {\n await this.stopCurrent(\"parent shutting down\");\n }\n\n private async stopCurrent(reason: string): Promise<void> {\n const child = this.child;\n if (!child || child.exitCode !== null || child.killed) {\n this.child = null;\n this.childSessionId = null;\n return;\n }\n logger.info(\"Stopping review child\", { reason, reviewSessionId: this.childSessionId });\n // Detach bookkeeping first so the exit handler treats this as expected.\n this.child = null;\n this.childSessionId = null;\n\n await new Promise<void>((resolve) => {\n const timer = setTimeout(() => {\n try {\n child.kill(\"SIGKILL\");\n } catch {\n /* already gone */\n }\n resolve();\n }, KILL_WAIT_MS);\n timer.unref();\n child.once(\"exit\", () => {\n clearTimeout(timer);\n resolve();\n });\n try {\n child.kill(\"SIGTERM\");\n } catch {\n clearTimeout(timer);\n resolve();\n }\n });\n }\n\n /**\n * Best-effort branch freshen before the review reads the tree: fetch the PR\n * branch and fast-forward only (never clobber local work — the builder's\n * checkout is the source of truth on conflict). Failures are logged and\n * skipped; the reviewer still reads the diff via the GitHub API.\n */\n private async refreshCheckout(branch: string | null): Promise<void> {\n if (!branch) return;\n try {\n await execFileAsync(\"git\", [\"fetch\", \"origin\", branch], {\n cwd: this.workspaceDir,\n timeout: 60_000,\n });\n await execFileAsync(\"git\", [\"merge\", \"--ff-only\", `origin/${branch}`], {\n cwd: this.workspaceDir,\n timeout: 30_000,\n });\n } catch (err) {\n logger.warn(\"Review checkout freshen skipped\", {\n branch,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n}\n","/**\n * Same-pod TUI/shell child supervisor. When the API parks an extra interactive\n * session on this (builder) pod and pushes `session:spawnTui`, the supervisor\n * spawns another conveyor-agent process — same CLI binary, same repo checkout —\n * bound to it via env overrides (CONVEYOR_MODE \"adhoc\" = a second Claude TUI,\n * \"shell\" = a raw login shell). Each child owns its own AgentConnection/PTY\n * stream, so a new terminal tab appears through the normal multi-session relay\n * with no relay changes.\n *\n * Multi-slot (unlike ReviewChildSupervisor): tabs are additive — several TUI/\n * shell children can coexist, keyed by their sessionId. The server caps how\n * many it will park per workspace. Spawn failures are reported back\n * (`reportSessionSpawnFailure`), which Ends the orphaned session; there is no\n * fallback pod (a spawned tab only makes sense on this pod).\n *\n * Shared-checkout caveat (deliberate, same as the review child): children\n * operate on the builder's working tree. They never run setup/start commands\n * and never touch git themselves on spawn.\n */\nimport { spawn as nodeSpawn, type ChildProcess } from \"node:child_process\";\nimport type { SpawnTuiData } from \"../connection/agent-connection.js\";\nimport { createServiceLogger } from \"../utils/logger.js\";\nimport { KILL_WAIT_MS, SPAWN_FAILURE_GRACE_MS, type SpawnFn } from \"./review-child.js\";\n\nconst logger = createServiceLogger(\"SessionChild\");\n\nexport interface SessionChildConnection {\n reportSessionSpawnFailure(spawnedSessionId: string, error?: string): void;\n}\n\n/**\n * Build the child env from the builder's env. The child is the same CLI in\n * adhoc/shell mode, so it reuses the pod's credentials while swapping in the\n * spawned session's identity.\n */\nexport function buildSpawnedChildEnv(\n baseEnv: NodeJS.ProcessEnv,\n data: SpawnTuiData,\n): NodeJS.ProcessEnv {\n const env: NodeJS.ProcessEnv = { ...baseEnv };\n // The spawned session's identity: its own JWT + sessionId + runner mode.\n // CONVEYOR_TASK_ID stays the parent's — same task (SEC-9 derives the task\n // from the JWT server-side). CONVEYOR_PROJECT_ID feeds the adhoc runner's\n // connected-event payload.\n env.CONVEYOR_TASK_TOKEN = data.sessionJwt;\n env.CONVEYOR_SESSION_ID = data.sessionId;\n env.CONVEYOR_MODE = data.mode;\n env.CONVEYOR_PROJECT_ID = data.projectId;\n\n // The bootstrap-refresh path would replace the child's JWT with the\n // BUILDER's writer JWT (findBundleSession prefers the live writer), silently\n // re-identifying the child as the builder — remove the tokens (same as the\n // review child; the 24h JWT TTL outlives any tab).\n delete env.POD_BOOTSTRAP_TOKEN;\n delete env.CONVEYOR_BOOTSTRAP_TOKEN;\n\n // The builder already ran (or is running) setup/start on this shared\n // workspace — the child must never re-run `bun install` or spawn a second\n // dev server.\n delete env.CONVEYOR_SETUP_COMMAND;\n delete env.CONVEYOR_START_COMMAND;\n\n // Adhoc/shell runners have no agent-mode axis; a stale builder hint must\n // not leak in.\n delete env.CONVEYOR_AGENT_MODE;\n delete env.CONVEYOR_IS_AUTO;\n return env;\n}\n\nexport class SessionChildSupervisor {\n private readonly children = new Map<string, ChildProcess>();\n\n constructor(\n private readonly connection: SessionChildConnection,\n private readonly workspaceDir: string,\n private readonly spawnFn: SpawnFn = nodeSpawn as SpawnFn,\n ) {}\n\n /** Live child count (for tests/diagnostics). */\n get size(): number {\n return this.children.size;\n }\n\n /** Spawn a TUI/shell child for a `session:spawnTui` push. Additive per session. */\n async spawn(data: SpawnTuiData): Promise<void> {\n logger.info(\"Spawning same-pod session child\", {\n spawnedSessionId: data.sessionId,\n mode: data.mode,\n });\n // A duplicate push for the same session replaces its own slot only.\n await this.stopChild(data.sessionId, \"superseded by duplicate spawn\");\n\n const env = buildSpawnedChildEnv(process.env, data);\n const cliPath = process.argv[1];\n if (!cliPath) {\n this.connection.reportSessionSpawnFailure(data.sessionId, \"cannot resolve CLI entry path\");\n return;\n }\n\n let child: ChildProcess;\n try {\n child = this.spawnFn(process.execPath, [cliPath], {\n cwd: this.workspaceDir,\n env,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n } catch (err) {\n this.connection.reportSessionSpawnFailure(\n data.sessionId,\n err instanceof Error ? err.message : String(err),\n );\n return;\n }\n\n this.children.set(data.sessionId, child);\n const spawnedAt = Date.now();\n let reported = false;\n const reportOnce = (message: string): void => {\n if (reported) return;\n reported = true;\n this.connection.reportSessionSpawnFailure(data.sessionId, message);\n };\n\n // Child output lands in the pod log (the entrypoint tees our stdio),\n // prefixed so builder and tab streams stay distinguishable.\n const prefix = `[${data.mode}-child]`;\n child.stdout?.on(\"data\", (chunk: Buffer) => {\n process.stdout.write(`${prefix} ${chunk.toString()}`);\n });\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n process.stderr.write(`${prefix} ${chunk.toString()}`);\n });\n\n child.on(\"error\", (err) => {\n logger.error(\"Session child spawn error\", { error: err.message });\n if (this.children.get(data.sessionId) === child) {\n this.children.delete(data.sessionId);\n }\n reportOnce(err.message);\n });\n\n child.on(\"exit\", (code, signal) => {\n const wasCurrent = this.children.get(data.sessionId) === child;\n if (wasCurrent) this.children.delete(data.sessionId);\n logger.info(\"Session child exited\", {\n code,\n signal,\n spawnedSessionId: data.sessionId,\n mode: data.mode,\n });\n // A non-zero exit right after launch means the child never became the\n // tab's agent — End the orphaned session server-side. Later exits (user\n // typed `exit`, server-sent session:stop, supersede kill) are normal\n // lifecycle: the server owns the session state there.\n const withinGrace = Date.now() - spawnedAt < SPAWN_FAILURE_GRACE_MS;\n if (wasCurrent && withinGrace && code !== null && code !== 0) {\n reportOnce(`session child exited with code ${code} within startup grace`);\n }\n });\n }\n\n /** Stop every live child (parent shutdown). Best-effort. */\n async stopAll(): Promise<void> {\n const ids = [...this.children.keys()];\n await Promise.all(ids.map((id) => this.stopChild(id, \"parent shutting down\")));\n }\n\n private async stopChild(sessionId: string, reason: string): Promise<void> {\n const child = this.children.get(sessionId);\n this.children.delete(sessionId);\n if (!child || child.exitCode !== null || child.killed) return;\n logger.info(\"Stopping session child\", { reason, spawnedSessionId: sessionId });\n\n await new Promise<void>((resolve) => {\n const timer = setTimeout(() => {\n try {\n child.kill(\"SIGKILL\");\n } catch {\n /* already gone */\n }\n resolve();\n }, KILL_WAIT_MS);\n timer.unref();\n child.once(\"exit\", () => {\n clearTimeout(timer);\n resolve();\n });\n try {\n child.kill(\"SIGTERM\");\n } catch {\n clearTimeout(timer);\n resolve();\n }\n });\n }\n}\n","/**\n * ShellSessionRunner — a raw login shell relayed as a terminal tab. Spawned as\n * a same-pod child (`session:spawnTui` with mode \"shell\") so a human can poke\n * around the workspace manually from the card's App/terminal tabs.\n *\n * The sibling of AdhocSessionRunner minus the Claude harness: connect →\n * register → spawn `$SHELL -l` under node-pty in the workspace checkout →\n * relay raw bytes over the S2 relay (ptyOutput/ptyInput/ptyResize). The tab\n * ends when the human exits the shell, the roster kill sends session:stop, or\n * the pod goes down. Idle-sleep stays server-owned; the runner's own idle\n * timer is the backstop, re-armed on every keystroke so an actively-used\n * shell never trips it.\n */\nimport { AgentConnection, type AgentConnectionConfig } from \"../connection/agent-connection.js\";\nimport { Lifecycle, DEFAULT_LIFECYCLE_CONFIG, type LifecycleConfig } from \"./lifecycle.js\";\nimport {\n loadPtySpawn,\n inheritedEnv,\n type PtyProcess,\n type PtySpawn,\n} from \"../harness/pty/pty-support.js\";\n\nconst DEFAULT_COLS = 80;\nconst DEFAULT_ROWS = 24;\n\nexport interface ShellSessionRunnerConfig {\n connection: AgentConnectionConfig;\n /** Repo checkout the shell starts in. */\n workspaceDir: string;\n /** Shell binary override; falls back to $SHELL, then bash. */\n shell?: string;\n lifecycle?: Partial<LifecycleConfig>;\n}\n\n/** AgentConnection surface the shell runner needs (injectable for tests). */\nexport interface ShellRunnerConnection {\n connect(): Promise<void>;\n disconnect(): void;\n call(method: \"connectAgent\", payload: { sessionId: string }): Promise<unknown>;\n sendEvent(event: { type: string; [key: string]: unknown }): void;\n sendHeartbeat(): void;\n emitStatus(status: string): Promise<void>;\n onStop(callback: () => void): void;\n refreshTaskTokenFromBootstrap(): Promise<boolean>;\n sendPtyOutput(data: string, dims?: { cols: number; rows: number }): void;\n sendPtyEnded(): void;\n onPtyInput(handler: (data: string) => void): () => void;\n onPtyResize(handler: (cols: number, rows: number) => void): () => void;\n}\n\n/**\n * The shell's env: the pod env minus this session's Conveyor identity. The\n * human at the prompt doesn't need the session JWT sitting in `env` output —\n * and a copied token must not leak task authority into pasted shell logs.\n */\nexport function buildShellEnv(baseEnv: Record<string, string>): Record<string, string> {\n const env = { ...baseEnv };\n delete env.CONVEYOR_TASK_TOKEN;\n delete env.CONVEYOR_SESSION_ID;\n return env;\n}\n\nexport class ShellSessionRunner {\n readonly connection: ShellRunnerConnection;\n readonly lifecycle: Lifecycle;\n\n private readonly config: ShellSessionRunnerConfig;\n private readonly loadSpawn: () => Promise<PtySpawn>;\n private pty: PtyProcess | null = null;\n private dims = { cols: DEFAULT_COLS, rows: DEFAULT_ROWS };\n private stopped = false;\n private _finalState: \"finished\" | \"error\" | null = null;\n\n constructor(\n config: ShellSessionRunnerConfig,\n deps?: { connection?: ShellRunnerConnection; loadSpawn?: () => Promise<PtySpawn> },\n ) {\n this.config = config;\n this.connection = deps?.connection ?? new AgentConnection(config.connection);\n this.loadSpawn = deps?.loadSpawn ?? loadPtySpawn;\n this.lifecycle = new Lifecycle(\n // No git flush — the human commits/pushes explicitly from the shell.\n { ...DEFAULT_LIFECYCLE_CONFIG, gitFlushIntervalMs: 0, ...config.lifecycle },\n {\n onHeartbeat: () => this.connection.sendHeartbeat(),\n onIdleTimeout: () => this.requestStop(),\n onDormantTimeout: () => this.requestStop(),\n onTokenRefresh: () => void this.connection.refreshTaskTokenFromBootstrap().catch(() => {}),\n onGitFlush: () => {},\n onUsageSample: () => {},\n },\n );\n }\n\n get finalState(): \"finished\" | \"error\" | null {\n return this._finalState;\n }\n\n get isStopped(): boolean {\n return this.stopped;\n }\n\n /** Connect, register, spawn the shell, and relay it until exit or stop. */\n async run(): Promise<void> {\n try {\n await this.connection.connect();\n this.connection.sendEvent({\n type: \"connected\",\n sessionId: this.config.connection.sessionId,\n });\n this.connection.onStop(() => this.requestStop());\n this.lifecycle.startHeartbeat();\n this.lifecycle.startTokenRefresh();\n\n await this.connection.call(\"connectAgent\", {\n sessionId: this.config.connection.sessionId,\n });\n await this.connection.emitStatus(\"running\");\n this.lifecycle.startIdleTimer();\n\n await this.runShell();\n this._finalState = \"finished\";\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[conveyor-agent] Shell runner failed: ${message}\\n`);\n this.connection.sendEvent({ type: \"error\", message });\n this._finalState = \"error\";\n } finally {\n this.shutdown();\n }\n }\n\n /** Spawn the login shell under a PTY and block until it exits or stop(). */\n private async runShell(): Promise<void> {\n const spawn = await this.loadSpawn();\n const shell = this.config.shell ?? process.env.SHELL ?? \"bash\";\n const pty = spawn(shell, [\"-l\"], {\n name: \"xterm-256color\",\n cols: this.dims.cols,\n rows: this.dims.rows,\n cwd: this.config.workspaceDir,\n env: buildShellEnv(inheritedEnv()),\n });\n this.pty = pty;\n\n const unsubInput = this.connection.onPtyInput((data) => {\n // A keystroke is real human activity — re-arm the idle backstop.\n this.lifecycle.startIdleTimer();\n pty.write(data);\n });\n const unsubResize = this.connection.onPtyResize((cols, rows) => {\n this.dims = { cols, rows };\n pty.resize(cols, rows);\n });\n pty.onData((data) => this.connection.sendPtyOutput(data, this.dims));\n\n try {\n await new Promise<void>((resolve) => {\n pty.onExit(() => resolve());\n });\n } finally {\n unsubInput();\n unsubResize();\n this.pty = null;\n // The shell is gone and no respawn is coming — hide the tab now instead\n // of waiting for the lease to lapse.\n this.connection.sendPtyEnded();\n }\n }\n\n stop(): void {\n this.requestStop();\n }\n\n private requestStop(): void {\n if (this.stopped) return;\n this.stopped = true;\n try {\n this.pty?.kill();\n } catch {\n /* already gone */\n }\n }\n\n private shutdown(): void {\n this.stopped = true;\n this.lifecycle.destroy();\n this.connection.sendEvent({ type: \"shutdown\", reason: this._finalState ?? \"finished\" });\n this.connection.disconnect();\n }\n}\n","/**\n * Boot factory for same-pod spawned children (session:spawnTui). Keeps the\n * CLI entry lean: given the env-derived identity, constructs the right runner\n * — an interactive Claude TUI (mode \"adhoc\" WITH a task id, unlike the\n * task-less Sessions-view adhoc pods) or a raw login shell (mode \"shell\").\n */\nimport { createServiceLogger } from \"../utils/logger.js\";\nimport { AdhocSessionRunner } from \"./adhoc-session-runner.js\";\nimport { ShellSessionRunner } from \"./shell-session-runner.js\";\n\nconst logger = createServiceLogger(\"SpawnedChildBoot\");\n\nexport interface SpawnedChildInputs {\n mode: \"adhoc\" | \"shell\";\n apiUrl: string;\n taskToken: string;\n /** The spawned WorkspaceSession id (CONVEYOR_SESSION_ID on the child). */\n sessionId: string;\n workspaceDir: string;\n /** For the adhoc runner's connected-event payload (CONVEYOR_PROJECT_ID). */\n projectId: string;\n}\n\nexport interface SpawnedChildRunner {\n run(): Promise<void>;\n stop(): void;\n readonly finalState: \"finished\" | \"error\" | null;\n}\n\nexport function createSpawnedChildRunner(inputs: SpawnedChildInputs): SpawnedChildRunner {\n if (inputs.mode === \"shell\") {\n return new ShellSessionRunner({\n connection: {\n apiUrl: inputs.apiUrl,\n taskToken: inputs.taskToken,\n sessionId: inputs.sessionId,\n runnerMode: \"shell\",\n },\n workspaceDir: inputs.workspaceDir,\n });\n }\n return new AdhocSessionRunner(\n {\n connection: {\n apiUrl: inputs.apiUrl,\n taskToken: inputs.taskToken,\n sessionId: inputs.sessionId,\n runnerMode: \"adhoc\",\n },\n projectId: inputs.projectId,\n // Session lineage key. NOT the inherited CONVEYOR_WORKSPACE_ID — that's\n // the builder's lineage; concurrent tabs must each be their own Claude\n // conversation, so key on the spawned session id.\n workspaceId: inputs.sessionId,\n workspaceDir: inputs.workspaceDir,\n },\n {\n onEvent: (event) => {\n logger.info(\"Spawned TUI event\", { eventType: event.type as string });\n },\n },\n );\n}\n"],"mappings":"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","names":["join","dirname","logger","writeFile","writeFile","dirname","join","logger","join","dirname","logger","nodeSpawn","logger","nodeSpawn","logger","dirname","join","logger"]}
|
|
1
|
+
{"version":3,"sources":["../src/cli.ts","../src/setup/sidecars.ts","../src/setup/boot-milestone.ts","../src/setup/workspace-command-supervisor.ts","../src/utils/session-identity.ts","../src/utils/agent-exit.ts","../src/setup/project-identity.ts","../src/runner/project-session-runner.ts","../src/usage/multi-key-probe.ts","../src/harness/pty/adapters/opencode-auth.ts","../src/harness/pty/adapters/opencode.ts","../src/harness/pty/adapters/index.ts","../src/tools/project-tools.ts","../src/runner/adhoc-session-runner.ts","../src/runner/review-child.ts","../src/runner/session-child.ts","../src/runner/shell-session-runner.ts","../src/runner/spawned-child-boot.ts"],"sourcesContent":["#!/usr/bin/env node\n/* oxlint-disable import/max-dependencies -- CLI entry point wires every runner variant (task/pm/code-review/adhoc) + setup; splitting would scatter the boot sequence */\nimport { readFileSync } from \"node:fs\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { SessionRunner } from \"./runner/session-runner.js\";\nimport type { AgentRunnerStatus, RunnerMode } from \"@project/shared\";\nimport { createServiceLogger } from \"./utils/logger.js\";\nimport { applyBootstrapToEnv, fetchBootstrap, loadConveyorConfig } from \"./setup/index.js\";\nimport {\n startWorkspaceCommandsAfterConnect,\n stopWorkspaceCommands,\n WorkspaceCommandSupervisor,\n} from \"./setup/workspace-command-supervisor.js\";\nimport { checkSessionTaskIdentity } from \"./utils/session-identity.js\";\nimport {\n buildAgentExitLog,\n exitLogLevel,\n type AgentExitIdentity,\n type AgentExitReason,\n} from \"./utils/agent-exit.js\";\nimport { resolveProjectRunnerIdentity } from \"./setup/project-identity.js\";\nimport { ProjectSessionRunner } from \"./runner/project-session-runner.js\";\nimport { AdhocSessionRunner, resolveInitialPrompt } from \"./runner/adhoc-session-runner.js\";\nimport { ReviewChildSupervisor } from \"./runner/review-child.js\";\nimport { SessionChildSupervisor } from \"./runner/session-child.js\";\nimport { createSpawnedChildRunner } from \"./runner/spawned-child-boot.js\";\n\n// Handle --version flag before any other initialization\nif (process.argv.includes(\"--version\")) {\n const __dirname = dirname(fileURLToPath(import.meta.url));\n const pkgPath = join(__dirname, \"..\", \"package.json\");\n const pkg = JSON.parse(readFileSync(pkgPath, \"utf-8\"));\n process.stdout.write(pkg.version + \"\\n\");\n process.exit(0);\n}\n\nconst logger = createServiceLogger(\"CLI\");\n\n// Pod-exit observability. The reconciler can only infer *that* an agent stopped\n// (stale heartbeat → Stranded); it never sees *why*. We log the cause from the\n// pod side at every catchable exit, keyed on the same sessionId the API's\n// `session_stranded` line carries so the two ends can be joined. Populated once\n// env identity resolves below; the early crash handlers read it live. (SIGKILL /\n// OOM 137 is uncatchable — diagnosed from GKE kernel logs, not this line.)\nconst exitContext: AgentExitIdentity = {};\nlet exitLogged = false;\nfunction logAgentExit(\n reason: AgentExitReason,\n opts: { exitCode: number; signal?: string; finalState?: string },\n): void {\n // One line per process death; force_timeout is logged separately (it escalates\n // an already-logged signal shutdown) so it bypasses this guard at its call site.\n if (exitLogged) return;\n exitLogged = true;\n const payload = buildAgentExitLog({\n reason,\n exitCode: opts.exitCode,\n signal: opts.signal,\n finalState: opts.finalState,\n uptimeSec: process.uptime(),\n identity: exitContext,\n });\n logger[exitLogLevel(reason)](\"agent_exit\", payload as unknown as Record<string, unknown>);\n}\n\nasync function bootstrapFromCodespace(apiUrl: string, instanceName: string): Promise<void> {\n const bootstrapToken = process.env.CONVEYOR_BOOTSTRAP_TOKEN;\n const apiUrlFromEnv = Boolean(process.env.CONVEYOR_API_URL);\n logger.info(\"Bootstrapping from codespace\", {\n codespace: instanceName,\n apiUrl,\n apiUrlFromEnv,\n bootstrapTokenPresent: Boolean(bootstrapToken),\n });\n const result = await fetchBootstrap({\n apiUrl,\n instanceName,\n bootstrapToken,\n });\n if (!result.ok) {\n logger.error(\"Bootstrap failed after retries\", {\n reason: result.reason,\n attempts: result.attempts,\n status: result.status,\n detail: result.detail,\n apiUrl,\n apiUrlFromEnv,\n bootstrapTokenPresent: Boolean(bootstrapToken),\n hint: apiUrlFromEnv\n ? \"Verify the codespace was created by this Conveyor deployment and that the bootstrap token is current.\"\n : \"CONVEYOR_API_URL was not set as a codespace secret — agent fell back to the built-in default. Re-create the codespace, or push CONVEYOR_API_URL via project settings.\",\n });\n process.exit(1);\n }\n applyBootstrapToEnv(result.config);\n logger.info(\"Bootstrap complete\", {\n taskId: result.config.taskId,\n attempts: result.attempts,\n });\n}\n\n// Helper to detect expected abort errors from SDK cleanup\nfunction isExpectedAbortError(error: Error | NodeJS.ErrnoException): boolean {\n const message = error.message || \"\";\n const hasAbortMessage = /operation aborted/i.test(message) || /abort/i.test(message);\n const hasAbortCode = !(\"code\" in error) || error.code === undefined || error.code === \"ABORT_ERR\";\n return hasAbortMessage && hasAbortCode;\n}\n\nprocess.on(\"uncaughtException\", (err: NodeJS.ErrnoException) => {\n if (err.code === \"EPIPE\") return;\n\n if (isExpectedAbortError(err)) {\n logger.info(\"Ignored expected abort after shutdown\", { error: err.message, code: err.code });\n return;\n }\n\n logger.error(\"Uncaught exception\", { error: err.message, code: err.code });\n logAgentExit(\"uncaught_exception\", { exitCode: 1 });\n process.exit(1);\n});\n\nprocess.on(\"unhandledRejection\", (reason: unknown) => {\n const err = reason instanceof Error ? reason : new Error(String(reason));\n\n if (isExpectedAbortError(err)) {\n logger.info(\"Ignored expected abort rejection after shutdown\", { error: err.message });\n return;\n }\n\n logger.error(\"Unhandled rejection\", { error: err.message });\n logAgentExit(\"unhandled_rejection\", { exitCode: 1 });\n process.exit(1);\n});\n\n// Step 0: workbench launcher (split-mode pods). The workbench container runs\n// ONLY the exec daemon — no task token, no bootstrap, no runner lifecycle.\n// Checked before everything so it never falls through to the task paths.\nif (process.env.CONVEYOR_MODE === \"workbench\") {\n const { startWorkbenchServer } = await import(\"./workbench/server.js\");\n const { DEFAULT_WORKBENCH_PORT } = await import(\"./workbench/protocol.js\");\n const port = Number(process.env.CONVEYOR_WORKBENCH_PORT) || DEFAULT_WORKBENCH_PORT;\n const token = process.env.CONVEYOR_WORKBENCH_TOKEN ?? process.env.POD_BOOTSTRAP_TOKEN ?? \"\";\n if (!token) {\n logger.error(\"workbench mode requires POD_BOOTSTRAP_TOKEN (or CONVEYOR_WORKBENCH_TOKEN)\");\n process.exit(1);\n }\n const pkgDir = dirname(fileURLToPath(import.meta.url));\n const pkg = JSON.parse(readFileSync(join(pkgDir, \"..\", \"package.json\"), \"utf-8\")) as {\n version?: string;\n };\n const handle = await startWorkbenchServer({\n port,\n token,\n version: pkg.version ?? \"unknown\",\n });\n logger.info(`Workbench launcher listening on 127.0.0.1:${handle.port}`);\n // Park forever — the kubelet owns this container's lifecycle (native\n // sidecar, restartPolicy Always); SIGTERM just exits.\n process.on(\"SIGTERM\", () => process.exit(0));\n await new Promise(() => {});\n}\n\nconst DEFAULT_CONVEYOR_API_URL = \"https://api.conveyor.rallycryapp.com\";\nlet conveyorApiUrl = process.env.CONVEYOR_API_URL || DEFAULT_CONVEYOR_API_URL;\n\n// Step 1: Codespace bootstrap\nconst INSTANCE_NAME = process.env.CODESPACE_NAME || process.env.CLAUDESPACE_NAME;\nif (INSTANCE_NAME && !process.env.CONVEYOR_TASK_TOKEN) {\n if (!conveyorApiUrl) {\n logger.error(\"Could not resolve CONVEYOR_API_URL for codespace bootstrap\");\n process.exit(1);\n }\n await bootstrapFromCodespace(conveyorApiUrl, INSTANCE_NAME);\n conveyorApiUrl = process.env.CONVEYOR_API_URL ?? conveyorApiUrl;\n}\n\n// Step 2: Read env vars (bootstrap may have set them)\nconst CONVEYOR_TASK_TOKEN = process.env.CONVEYOR_TASK_TOKEN;\nconst CONVEYOR_TASK_ID = process.env.CONVEYOR_TASK_ID;\nconst CONVEYOR_WORKSPACE = process.env.CONVEYOR_WORKSPACE ?? process.cwd();\nconst CONVEYOR_MODE = (process.env.CONVEYOR_MODE ?? \"task\") as RunnerMode;\nconst CONVEYOR_AGENT_MODE = process.env.CONVEYOR_AGENT_MODE || undefined;\nconst CONVEYOR_IS_AUTO = CONVEYOR_AGENT_MODE\n ? CONVEYOR_AGENT_MODE === \"auto\"\n : process.env.CONVEYOR_IS_AUTO === \"true\";\n\n// Seed the pod-exit identity now that env is resolved (the specific runner\n// branches below refine sessionId/workspaceId to their own session).\nexitContext.taskId = CONVEYOR_TASK_ID;\nexitContext.workspaceId = process.env.CONVEYOR_WORKSPACE_ID;\nexitContext.runnerMode = CONVEYOR_MODE;\nexitContext.sessionId = process.env.CONVEYOR_SESSION_ID ?? CONVEYOR_TASK_ID;\n\n// Step 2.5: task-less PROJECT pods (Claudespace v3 project runners). The\n// bundle's session JWT carries {projectId, sessionId} and NO taskId; the\n// entrypoint exports CONVEYOR_PROJECT_ID (no CONVEYOR_TASK_ID) and sets\n// CONVEYOR_MODE=pm. Boot the project runner: connect + register session +\n// heartbeat + idle awaiting project-scoped messages. Never falls through to\n// the task lifecycle below.\nconst projectIdentity = resolveProjectRunnerIdentity(process.env);\n\n// Task-less ADHOC pods (Sessions view scratch pods). Same task-less identity as\n// a project pod (projectId + sessionId, no taskId), distinguished by\n// CONVEYOR_MODE=adhoc. Runs an interactive `claude` TUI relayed to the web\n// terminal — NOT the autonomous pm project runner below. Checked first so an\n// adhoc session never falls through to pm.\nif (!CONVEYOR_TASK_ID && projectIdentity && CONVEYOR_MODE === \"adhoc\") {\n logger.info(\"Starting ad-hoc agent\", { projectId: projectIdentity.projectId });\n const adhocRunner = new AdhocSessionRunner(\n {\n connection: {\n apiUrl: conveyorApiUrl ?? \"\",\n taskToken: projectIdentity.taskToken,\n sessionId: projectIdentity.sessionId,\n runnerMode: \"adhoc\",\n },\n projectId: projectIdentity.projectId,\n workspaceId: projectIdentity.workspaceId,\n workspaceDir: CONVEYOR_WORKSPACE,\n // Headless sessions: un-submitted audit instructions from the bundle.\n // Resolved ONLY here — spawned same-pod tabs must not inherit them.\n initialPrompt: resolveInitialPrompt(process.env),\n ...(process.env.CLAUDESPACE_NAME ? { lifecycle: { idleTimeoutMs: 60 * 60 * 1000 } } : {}),\n },\n {\n onEvent: (event) => {\n logger.info(\"Ad-hoc runner event\", { eventType: event.type as string });\n },\n },\n );\n exitContext.sessionId = projectIdentity.sessionId;\n exitContext.workspaceId = projectIdentity.workspaceId;\n exitContext.runnerMode = \"adhoc\";\n process.on(\"SIGTERM\", () => adhocRunner.stop());\n process.on(\"SIGINT\", () => adhocRunner.stop());\n await adhocRunner.run();\n const adhocError = adhocRunner.finalState === \"error\";\n logAgentExit(adhocError ? \"error\" : \"clean\", {\n exitCode: adhocError ? 1 : 0,\n finalState: adhocRunner.finalState ?? undefined,\n });\n process.exit(adhocError ? 1 : 0);\n}\n\nif (!CONVEYOR_TASK_ID && projectIdentity) {\n logger.info(\"Starting project agent\", { projectId: projectIdentity.projectId });\n const projectRunner = new ProjectSessionRunner(\n {\n connection: {\n apiUrl: conveyorApiUrl ?? \"\",\n taskToken: projectIdentity.taskToken,\n sessionId: projectIdentity.sessionId,\n runnerMode: \"pm\",\n },\n projectId: projectIdentity.projectId,\n // Same extended idle window claudespace task pods get.\n ...(process.env.CLAUDESPACE_NAME ? { lifecycle: { idleTimeoutMs: 60 * 60 * 1000 } } : {}),\n },\n {\n onEvent: (event) => {\n logger.info(\"Project runner event\", { eventType: event.type as string });\n },\n },\n );\n exitContext.sessionId = projectIdentity.sessionId;\n exitContext.workspaceId = projectIdentity.workspaceId;\n exitContext.runnerMode = \"pm\";\n process.on(\"SIGTERM\", () => projectRunner.stop());\n process.on(\"SIGINT\", () => projectRunner.stop());\n await projectRunner.run();\n const projectError = projectRunner.finalState === \"error\";\n logAgentExit(projectError ? \"error\" : \"clean\", {\n exitCode: projectError ? 1 : 0,\n finalState: projectRunner.finalState ?? undefined,\n });\n process.exit(projectError ? 1 : 0);\n}\n\nif (!CONVEYOR_TASK_TOKEN || !CONVEYOR_TASK_ID) {\n logger.error(\"Missing required environment variables\");\n logger.error(\" CONVEYOR_TASK_TOKEN - JWT token for task authentication\");\n logger.error(\" CONVEYOR_TASK_ID - ID of the task to execute\");\n logger.error(\"\");\n logger.error(\"CONVEYOR_API_URL is provided via codespace secret or bootstrap.\");\n logger.error(\"\");\n logger.error(\"Optional:\");\n logger.error(\" CONVEYOR_MODE - Runner mode: 'task' (default), 'pack', or 'pm'\");\n logger.error(\" CONVEYOR_WORKSPACE - Working directory (defaults to cwd)\");\n logger.error(\n \" Project pods instead require CONVEYOR_PROJECT_ID + CONVEYOR_SESSION_ID + CONVEYOR_MODE=pm\",\n );\n process.exit(1);\n}\n\nif (\n CONVEYOR_MODE !== \"task\" &&\n CONVEYOR_MODE !== \"pm\" &&\n CONVEYOR_MODE !== \"code-review\" &&\n CONVEYOR_MODE !== \"adhoc\" &&\n CONVEYOR_MODE !== \"pack\" &&\n CONVEYOR_MODE !== \"shell\"\n) {\n logger.error(\"Invalid CONVEYOR_MODE\", {\n mode: CONVEYOR_MODE,\n expected: [\"task\", \"pm\", \"code-review\", \"adhoc\", \"pack\", \"shell\"],\n });\n process.exit(1);\n}\n\n// Same-pod spawned children (session:spawnTui): TASK-BOUND extra tabs on the\n// builder's pod — a second Claude TUI (mode \"adhoc\" + a task id, unlike the\n// task-less Sessions-view branch above) or a raw login shell (mode \"shell\").\n// Both bind their own WorkspaceSession via env overrides set by\n// SessionChildSupervisor and never fall through to the task SessionRunner.\nif (CONVEYOR_MODE === \"shell\" || CONVEYOR_MODE === \"adhoc\") {\n const spawnedSessionId = process.env.CONVEYOR_SESSION_ID;\n if (!spawnedSessionId) {\n logger.error(\"Spawned child requires CONVEYOR_SESSION_ID\", { mode: CONVEYOR_MODE });\n process.exit(1);\n }\n exitContext.sessionId = spawnedSessionId;\n exitContext.runnerMode = CONVEYOR_MODE;\n\n const childRunner = createSpawnedChildRunner({\n mode: CONVEYOR_MODE,\n apiUrl: conveyorApiUrl ?? \"\",\n taskToken: CONVEYOR_TASK_TOKEN,\n sessionId: spawnedSessionId,\n workspaceDir: CONVEYOR_WORKSPACE,\n projectId: process.env.CONVEYOR_PROJECT_ID ?? \"\",\n });\n logger.info(\"Starting spawned session child\", {\n mode: CONVEYOR_MODE,\n sessionId: spawnedSessionId,\n });\n process.on(\"SIGTERM\", () => childRunner.stop());\n process.on(\"SIGINT\", () => childRunner.stop());\n await childRunner.run();\n const childError = childRunner.finalState === \"error\";\n logAgentExit(childError ? \"error\" : \"clean\", {\n exitCode: childError ? 1 : 0,\n finalState: childRunner.finalState ?? undefined,\n });\n process.exit(childError ? 1 : 0);\n}\n\nlogger.info(\"Starting agent\", { mode: CONVEYOR_MODE });\n\n// Claudespace pods: longer idle timeout to stay alive for incoming messages.\n// Non-claudespace environments (local, workspace, GitHub Codespaces) have\n// persistent state and don't need the periodic WIP commit safety net, so\n// disable the git flush timer for them.\nconst lifecycleOverrides = process.env.CLAUDESPACE_NAME\n ? { idleTimeoutMs: 60 * 60 * 1000 }\n : { gitFlushIntervalMs: 0 };\n\nconst runner = new SessionRunner(\n {\n connection: {\n apiUrl: conveyorApiUrl ?? \"\",\n taskToken: CONVEYOR_TASK_TOKEN,\n // CONVEYOR_SESSION_ID is the CodespaceSession ID for BaseService ACL.\n // Falls back to CONVEYOR_TASK_ID for backward compat (codespace bootstrap sets only task ID).\n sessionId: process.env.CONVEYOR_SESSION_ID ?? CONVEYOR_TASK_ID,\n runnerMode: CONVEYOR_MODE,\n },\n runnerMode: CONVEYOR_MODE,\n isAuto: CONVEYOR_IS_AUTO,\n workspaceDir: CONVEYOR_WORKSPACE,\n agentMode: CONVEYOR_AGENT_MODE as import(\"@project/shared\").AgentMode | undefined,\n lifecycle: lifecycleOverrides,\n },\n {\n onStatusChange: (status: AgentRunnerStatus) => {\n logger.info(\"Status changed\", { status });\n },\n onEvent: (event: Record<string, unknown>) => {\n const detail =\n (event.message as string) ?? (event.content as string) ?? (event.summary as string) ?? \"\";\n if (detail) {\n logger.info(detail, { eventType: event.type as string });\n }\n },\n },\n);\n\n// Same-pod review children (session:spawnReview). Wired only for the builder\n// (\"task\") runner mode below — a review child must never recursively spawn.\nconst reviewChildren = new ReviewChildSupervisor(runner.connection, CONVEYOR_WORKSPACE);\n\n// Same-pod TUI/shell children (session:spawnTui). Wired for builder-shaped\n// runners (task + pack) below — spawned children run adhoc/shell modes, which\n// exit above before this block, so recursion is impossible.\nconst sessionChildren = new SessionChildSupervisor(runner.connection, CONVEYOR_WORKSPACE);\n\nlet shutdownSignal: \"SIGTERM\" | \"SIGINT\" | undefined;\nlet workspaceCommandSupervisor: WorkspaceCommandSupervisor | null = null;\nlet shutdownCompletion: Promise<void> | null = null;\n\nconst shutdownAgent = (signal: \"SIGTERM\" | \"SIGINT\") => {\n logger.info(`Received ${signal}, flushing git and stopping agent`);\n const commandShutdown = stopWorkspaceCommands(workspaceCommandSupervisor);\n // Recorded (not logged yet) so the final agent_exit line — emitted once the\n // real exit code is known below — can still attribute the cause to this\n // signal. A graceful SIGTERM resolves runner.run() with finalState=\"finished\"\n // and exits 0, so guessing exitCode here up front would misreport it as 1.\n shutdownSignal = signal;\n // Flush WIP commit + push BEFORE stop() tears down the connection, since\n // the token-refresh RPC needs a live socket. Then stop the runner.\n shutdownCompletion ??= (async () => {\n try {\n await Promise.all([reviewChildren.stopAll(), sessionChildren.stopAll()]);\n } catch {\n /* best-effort */\n }\n try {\n await runner.flushGitOnShutdown();\n } finally {\n await commandShutdown;\n runner.stop();\n }\n })();\n void shutdownCompletion;\n setTimeout(() => {\n logger.warn(`Forcing exit after ${signal} timeout`);\n // The graceful flush/stop hung past the watchdog — emit directly (bypassing\n // the one-line guard in logAgentExit) since run() will never resolve to log\n // this exit itself.\n logger.warn(\n \"agent_exit\",\n buildAgentExitLog({\n reason: \"force_timeout\",\n exitCode: 1,\n signal,\n finalState: runner.finalState ?? undefined,\n uptimeSec: process.uptime(),\n identity: exitContext,\n }) as unknown as Record<string, unknown>,\n );\n process.exit(1);\n }, 45_000).unref();\n};\n\nprocess.on(\"SIGTERM\", () => shutdownAgent(\"SIGTERM\"));\nprocess.on(\"SIGINT\", () => shutdownAgent(\"SIGINT\"));\n\n// Connect first so setup/start output is forwarded to the API. The helper does\n// not release commands until preview discovery has captured its baseline and\n// re-checks synchronous shutdown intent after that await.\nworkspaceCommandSupervisor = await startWorkspaceCommandsAfterConnect({\n connect: () => runner.connect(),\n isShuttingDown: () => shutdownSignal !== undefined,\n create: () =>\n new WorkspaceCommandSupervisor({\n config: loadConveyorConfig(),\n workspaceDir: CONVEYOR_WORKSPACE,\n connection: runner.connection,\n }),\n});\nif (!workspaceCommandSupervisor) {\n logger.info(\"Agent stopped before workspace commands were started\");\n if (shutdownCompletion) await shutdownCompletion;\n logAgentExit(shutdownSignal ? \"signal\" : \"clean\", {\n exitCode: 0,\n signal: shutdownSignal,\n finalState: runner.finalState ?? undefined,\n });\n process.exit(0);\n}\n\n// Hold the supervisor's start-command launch until the core loop signals it's\n// live (session-runner.ts run(), just before the core-loop while) — see\n// workspace-command-supervisor.ts's loopReady gate.\nrunner.setWorkspaceCommands(workspaceCommandSupervisor);\n\n// Defense-in-depth: warn loudly if CONVEYOR_SESSION_ID decodes to a different\n// task than CONVEYOR_TASK_ID. Authoritative checks are server-side\n// (requireTaskAuth + partial-unique index on active CodespaceSessions). This\n// is a visibility net in case those regress — see SEC-9 postmortem in\n// .claude/rules/agent-codespace.md.\nvoid checkSessionTaskIdentity({\n sessionId: process.env.CONVEYOR_SESSION_ID,\n taskId: CONVEYOR_TASK_ID,\n fetchSessionTaskId: async (sessionId) => {\n const ctx = await runner.connection.call(\"getTaskContext\", { sessionId });\n return ctx.id;\n },\n logger,\n});\n\n// Same-pod review: only the builder runner hosts review children. The push\n// arrives on the BUILDER's session room; the child binds the review session\n// via env overrides (its own JWT/sessionId, CONVEYOR_MODE=code-review).\nif (CONVEYOR_MODE === \"task\") {\n runner.connection.onSpawnReview((data) => {\n void reviewChildren.spawn(data).catch((err: unknown) => {\n logger.error(\"Review child spawn threw\", {\n error: err instanceof Error ? err.message : String(err),\n });\n runner.connection.reportReviewSpawnFailure(\n data.sessionId,\n err instanceof Error ? err.message : String(err),\n );\n });\n });\n}\n\n// Same-pod TUI/shell tabs: builder-shaped runners (task + pack) host spawned\n// children. The push arrives on the BUILDER's session room; each child binds\n// its own session via env overrides (JWT/sessionId, CONVEYOR_MODE=adhoc|shell).\nif (CONVEYOR_MODE === \"task\" || CONVEYOR_MODE === \"pack\") {\n runner.connection.onSpawnTui((data) => {\n void sessionChildren.spawn(data).catch((err: unknown) => {\n logger.error(\"Session child spawn threw\", {\n error: err instanceof Error ? err.message : String(err),\n });\n runner.connection.reportSessionSpawnFailure(\n data.sessionId,\n err instanceof Error ? err.message : String(err),\n );\n });\n });\n}\n\n// Start the main agent lifecycle immediately in parallel with setup\n// (context fetch, mode resolution, core loop).\nrunner\n .run()\n .then(async () => {\n await stopWorkspaceCommands(workspaceCommandSupervisor);\n // Exit with code 0 for clean shutdown (entrypoint won't restart),\n // code 1 for errors (entrypoint will restart). A SIGTERM-initiated shutdown\n // resolves run() too (finalState=\"finished\"), so tag it \"signal\" rather\n // than \"clean\" — but the exit code still follows the real finalState, not\n // a guess made back when the signal first arrived.\n const errored = runner.finalState === \"error\";\n const reason: AgentExitReason = shutdownSignal ? \"signal\" : errored ? \"error\" : \"clean\";\n logAgentExit(reason, {\n exitCode: errored ? 1 : 0,\n signal: shutdownSignal,\n finalState: runner.finalState ?? undefined,\n });\n process.exit(errored ? 1 : 0);\n })\n .catch(async (error: unknown) => {\n await stopWorkspaceCommands(workspaceCommandSupervisor);\n const msg = error instanceof Error ? error.message : String(error);\n logger.error(\"Agent runner failed\", { error: msg });\n logAgentExit(\"error\", { exitCode: 1, finalState: runner.finalState ?? undefined });\n process.exit(1);\n });\n","import net from \"node:net\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport { dirname } from \"node:path\";\n\n/**\n * Sidecar readiness gate.\n *\n * Previously the pod entrypoint blocked on postgres/firebase coming up BEFORE it\n * launched the agent, so the agent's thinking loop paid for up to ~60s of\n * sidecar boot it never needed. That wait now lives here and runs inside the\n * agent's background setup IIFE — it gates only `setupCommand`/`startCommand`\n * (which genuinely need a warm postgres), never the agent loop.\n *\n * Semantics deliberately match the old entrypoint: best-effort, NON-FATAL on\n * timeout (log a warning and continue), and a no-op when no sidecar env vars are\n * present. Per-target timeouts mirror what the entrypoint learned the hard way —\n * the firebase auth emulator cold-boots slowly and doesn't bind 9099 until ~50s\n * after its container starts, so it gets 60s.\n *\n * Postgres gets 120s: on a durable-sleep/pool pod the postgres sidecar restores\n * prior state, and an ungraceful previous pod death (e.g. OOMKill) leaves a torn\n * WAL that triggers crash recovery on boot. Cold boot + WAL replay routinely runs\n * past 30s, so the old deadline expired before postgres bound 5432 — setup's seed\n * then hit `DatabaseNotReachable` (P1001) and the whole dev env came up broken.\n */\n\nexport interface SidecarTarget {\n /** Human label for logs (e.g. \"postgres\"). */\n name: string;\n host: string;\n port: number;\n /** Per-target readiness deadline in ms (overridden by an explicit opts.timeoutMs). */\n timeoutMs?: number;\n}\n\nexport interface WaitForSidecarsOptions {\n /** Env to read targets from. Defaults to `process.env`. */\n env?: NodeJS.ProcessEnv;\n /** Progress sink (one line per message, no trailing newline). */\n onLog?: (message: string) => void;\n /** Force a single deadline for every target, overriding per-target defaults. */\n timeoutMs?: number;\n /** Delay between probe attempts in ms. */\n pollIntervalMs?: number;\n /** TCP probe seam — returns true once the target accepts a connection. */\n probe?: (target: SidecarTarget, signal?: AbortSignal) => Promise<boolean>;\n /** Whether to create the lazy sidecar start marker before probing. Defaults to true. */\n startLazy?: boolean;\n /** Optional shutdown signal. Aborting rejects with AbortError. */\n signal?: AbortSignal;\n}\n\nconst POSTGRES_TIMEOUT_MS = 120_000;\nconst FIREBASE_TIMEOUT_MS = 60_000;\nconst FALLBACK_TIMEOUT_MS = 30_000;\nconst DEFAULT_SIDECAR_POLL_INTERVAL_MS = 1_000;\nconst DEFAULT_PROBE_TIMEOUT_MS = 2_000;\n\nconst POSTGRES_DEFAULT_PORT = 5432;\nconst FIREBASE_DEFAULT_PORT = 9099;\n\nexport async function startLazySidecars(\n env: NodeJS.ProcessEnv,\n onLog: (message: string) => void,\n signal?: AbortSignal,\n): Promise<void> {\n throwIfAborted(signal);\n const markerPath = env.CONVEYOR_SIDECAR_START_FILE;\n if (!markerPath) return;\n\n try {\n await mkdir(dirname(markerPath), { recursive: true });\n throwIfAborted(signal);\n await writeFile(markerPath, \"start\\n\", \"utf8\");\n throwIfAborted(signal);\n onLog(\"Started lazy sidecars\");\n } catch (err) {\n if (signal?.aborted) throw abortError();\n const message = err instanceof Error ? err.message : String(err);\n onLog(`WARNING: failed to start lazy sidecars: ${message}`);\n }\n}\n\nfunction parseHostPort(value: string, defaultPort: number): { host: string; port: number } | null {\n const trimmed = value.trim().replace(/^[a-z]+:\\/\\//i, \"\");\n if (!trimmed) return null;\n const idx = trimmed.lastIndexOf(\":\");\n if (idx === -1) {\n return { host: trimmed, port: defaultPort };\n }\n const host = trimmed.slice(0, idx) || \"localhost\";\n const port = Number(trimmed.slice(idx + 1));\n return { host, port: Number.isFinite(port) ? port : defaultPort };\n}\n\n/**\n * Resolve the sidecar targets the agent should wait for from env. Mirrors the\n * entrypoint's conditions: postgres when `DATABASE_URL` is set, firebase auth\n * emulator when `FIREBASE_AUTH_EMULATOR_HOST` is set.\n */\nexport function resolveSidecarTargets(env: NodeJS.ProcessEnv = process.env): SidecarTarget[] {\n const targets: SidecarTarget[] = [];\n\n const databaseUrl = env.DATABASE_URL;\n if (databaseUrl) {\n try {\n const url = new URL(databaseUrl);\n const host = url.hostname || \"localhost\";\n const port = url.port ? Number(url.port) : POSTGRES_DEFAULT_PORT;\n if (Number.isFinite(port)) {\n targets.push({ name: \"postgres\", host, port, timeoutMs: POSTGRES_TIMEOUT_MS });\n }\n } catch {\n // Unparseable DATABASE_URL — skip rather than crash the setup path.\n }\n }\n\n const firebaseHost = env.FIREBASE_AUTH_EMULATOR_HOST;\n if (firebaseHost) {\n const parsed = parseHostPort(firebaseHost, FIREBASE_DEFAULT_PORT);\n if (parsed) {\n targets.push({\n name: \"firebase auth emulator\",\n host: parsed.host,\n port: parsed.port,\n timeoutMs: FIREBASE_TIMEOUT_MS,\n });\n }\n }\n\n return targets;\n}\n\nfunction abortError(): Error {\n const error = new Error(\"Operation aborted\");\n error.name = \"AbortError\";\n return error;\n}\n\nfunction throwIfAborted(signal?: AbortSignal): void {\n if (signal?.aborted) throw abortError();\n}\n\nfunction defaultProbe(target: SidecarTarget, signal?: AbortSignal): Promise<boolean> {\n throwIfAborted(signal);\n return new Promise((resolve) => {\n let settled = false;\n const socket = net.createConnection({ host: target.host, port: target.port });\n const done = (ok: boolean) => {\n if (settled) return;\n settled = true;\n socket.destroy();\n signal?.removeEventListener(\"abort\", onAbort);\n resolve(ok);\n };\n const onAbort = (): void => done(false);\n socket.once(\"connect\", () => done(true));\n socket.once(\"error\", () => done(false));\n socket.setTimeout(DEFAULT_PROBE_TIMEOUT_MS, () => done(false));\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n}\n\nconst delay = (ms: number, signal?: AbortSignal): Promise<void> => {\n throwIfAborted(signal);\n return new Promise((resolve, reject) => {\n const timer = setTimeout(() => {\n signal?.removeEventListener(\"abort\", onAbort);\n resolve();\n }, ms);\n const onAbort = (): void => {\n clearTimeout(timer);\n reject(abortError());\n };\n signal?.addEventListener(\"abort\", onAbort, { once: true });\n });\n};\n\nfunction raceWithAbort<T>(promise: Promise<T>, signal?: AbortSignal): Promise<T> {\n if (!signal) return promise;\n throwIfAborted(signal);\n return new Promise((resolve, reject) => {\n const onAbort = (): void => reject(abortError());\n signal.addEventListener(\"abort\", onAbort, { once: true });\n void promise.then(\n (value) => {\n signal.removeEventListener(\"abort\", onAbort);\n resolve(value);\n },\n (error: unknown) => {\n signal.removeEventListener(\"abort\", onAbort);\n reject(error);\n },\n );\n });\n}\n\nasync function waitForTarget(\n target: SidecarTarget,\n opts: {\n onLog: (message: string) => void;\n timeoutMs?: number;\n pollIntervalMs: number;\n probe: (target: SidecarTarget, signal?: AbortSignal) => Promise<boolean>;\n signal?: AbortSignal;\n },\n): Promise<void> {\n const { onLog, pollIntervalMs, probe, signal } = opts;\n const timeoutMs = opts.timeoutMs ?? target.timeoutMs ?? FALLBACK_TIMEOUT_MS;\n const deadline = Date.now() + timeoutMs;\n onLog(`Waiting for ${target.name} on ${target.host}:${target.port}...`);\n\n while (true) {\n throwIfAborted(signal);\n if (await raceWithAbort(probe(target, signal), signal)) {\n onLog(`${target.name} is ready`);\n return;\n }\n if (Date.now() >= deadline) {\n onLog(\n `WARNING: ${target.name} not ready after ${Math.round(timeoutMs / 1000)}s, continuing anyway`,\n );\n return;\n }\n await delay(pollIntervalMs, signal);\n }\n}\n\n/**\n * Block until every configured sidecar is reachable (or its per-target deadline\n * elapses). Resolves immediately when no sidecar env vars are set. Readiness\n * failures remain non-fatal; an explicit shutdown abort rejects with AbortError.\n */\nexport async function waitForSidecars(opts: WaitForSidecarsOptions = {}): Promise<void> {\n const {\n env = process.env,\n onLog = () => {},\n timeoutMs,\n pollIntervalMs = DEFAULT_SIDECAR_POLL_INTERVAL_MS,\n probe = defaultProbe,\n startLazy = true,\n signal,\n } = opts;\n\n if (startLazy) {\n await startLazySidecars(env, onLog, signal);\n }\n throwIfAborted(signal);\n\n const targets = resolveSidecarTargets(env);\n if (targets.length === 0) return;\n\n await Promise.all(\n targets.map((target) =>\n waitForTarget(target, { onLog, timeoutMs, pollIntervalMs, probe, signal }),\n ),\n );\n}\n","/**\n * Pod-side bootstrap-milestone reporter. The pod alone observes when the\n * workspace git is up to date, when its sidecars are ready, and when the\n * start command has launched; it reports those milestones to the API over the\n * same bootstrap-token channel the bundle poll and crash reporter use\n * (`POST /api/v3/pods/boot-milestone`). The API\n * records them on `Workspace.bootTimeline`, which drives the agent-tab progress\n * meter. Server-owned milestones (pod_created/image_ready/agent_connected) are\n * never reported from here — the API enforces the allow-list.\n *\n * Fire-and-forget: a failed or slow report must never delay start, so\n * every path swallows errors and the whole thing no-ops off-pod (GitHub\n * Codespaces / local), where the bootstrap token is absent.\n */\nimport type { BootStepKey } from \"@project/shared\";\n\nconst REPORT_TIMEOUT_MS = 5_000;\n\n/** The steps a pod may report. Mirrors the API's `POD_REPORTABLE_BOOT_STEPS`. */\nexport type PodReportableBootStep = Extract<\n BootStepKey,\n \"git_ready\" | \"sidecars_ready\" | \"start_command_launched\"\n>;\n\nexport interface ReportBootMilestoneOptions {\n key: PodReportableBootStep;\n /** Defaults to `process.env`. Injected for tests. */\n env?: NodeJS.ProcessEnv;\n /** Injected for tests; defaults to global fetch. */\n fetchFn?: typeof fetch;\n timeoutMs?: number;\n}\n\n/**\n * Best-effort POST of a boot milestone. Resolves to `true` when the API\n * acknowledged (HTTP 2xx), `false` otherwise — including the off-pod no-op.\n * Never throws.\n */\nexport async function reportBootMilestone(opts: ReportBootMilestoneOptions): Promise<boolean> {\n const env = opts.env ?? process.env;\n const apiUrl = env.CONVEYOR_API_URL;\n const token = env.POD_BOOTSTRAP_TOKEN;\n // Only claudespace v3 pods carry both — elsewhere there is no meter to feed.\n if (!apiUrl || !token) return false;\n\n const fetchFn = opts.fetchFn ?? fetch;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), opts.timeoutMs ?? REPORT_TIMEOUT_MS);\n try {\n const res = await fetchFn(`${apiUrl.replace(/\\/$/, \"\")}/api/v3/pods/boot-milestone`, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n authorization: `Bearer ${token}`,\n },\n body: JSON.stringify({ key: opts.key }),\n signal: controller.signal,\n });\n return res.ok;\n } catch {\n return false;\n } finally {\n clearTimeout(timer);\n }\n}\n","import {\n buildSessionPreviewPorts,\n loadForwardPorts,\n type ConveyorConfig,\n type ForwardPortsResult,\n} from \"./config.js\";\nimport { awaitGitReady, type GitReadyState } from \"./git-ready.js\";\nimport { runStartCommand, terminateProcessGroup, type ManagedChildProcess } from \"./commands.js\";\nimport { startLazySidecars, waitForSidecars } from \"./sidecars.js\";\nimport { workbenchEnabled } from \"../workbench/mode.js\";\nimport { getWorkbenchClient } from \"../workbench/client.js\";\nimport { reportBootMilestone, type PodReportableBootStep } from \"./boot-milestone.js\";\n\ntype OutputStream = \"stdout\" | \"stderr\";\ntype StartCommandChild = ManagedChildProcess;\n\n/**\n * Split-mode pods run every workspace command in the workbench container;\n * everywhere else the local spawn paths are used unchanged. Resolved per\n * supervisor construction (not import) so tests can flip the env.\n */\nfunction defaultCommandExecutors(): {\n runStartCommand: (\n cmd: string,\n cwd: string,\n onOutput: (stream: OutputStream, data: string) => void,\n ) => StartCommandChild;\n} {\n if (workbenchEnabled()) {\n const client = getWorkbenchClient();\n return {\n runStartCommand: (cmd, cwd, onOutput) => client.runStartCommand(cmd, cwd, onOutput),\n };\n }\n return { runStartCommand };\n}\n\nexport interface WorkspaceCommandConnection {\n sendEvent(event: { type: string; [key: string]: unknown }): void;\n onRunStartCommand(callback: () => void): void;\n}\n\nexport interface WorkspaceCommandSupervisorOptions {\n config: ConveyorConfig | null;\n workspaceDir: string;\n connection: WorkspaceCommandConnection;\n env?: NodeJS.ProcessEnv;\n awaitGitReady?: (options: {\n onLog: (message: string) => void;\n signal: AbortSignal;\n }) => Promise<GitReadyState>;\n startLazySidecars?: (\n env: NodeJS.ProcessEnv,\n onLog: (message: string) => void,\n signal: AbortSignal,\n ) => Promise<void>;\n waitForSidecars?: (options: {\n onLog: (message: string) => void;\n startLazy: false;\n signal: AbortSignal;\n }) => Promise<void>;\n runStartCommand?: (\n cmd: string,\n cwd: string,\n onOutput: (stream: OutputStream, data: string) => void,\n ) => StartCommandChild;\n loadForwardPorts?: (workspaceDir: string) => Promise<ForwardPortsResult>;\n writeOutput?: (stream: OutputStream, data: string) => void;\n terminateStartCommand?: (child: StartCommandChild) => void | Promise<void>;\n /** Report a pod-observed boot milestone to the API. Injected for tests. */\n reportBootMilestone?: (key: PodReportableBootStep) => void;\n}\n\nconst defaultWriteOutput = (stream: OutputStream, data: string): void => {\n (stream === \"stderr\" ? process.stderr : process.stdout).write(data);\n};\n\nexport function stopWorkspaceCommands(\n supervisor: { stop(): Promise<void> } | null | undefined,\n): Promise<void> {\n return supervisor?.stop() ?? Promise.resolve();\n}\n\nexport interface WorkspaceCommandStartupOptions<T extends { start(): void }> {\n connect: () => Promise<boolean>;\n isShuttingDown: () => boolean;\n create: () => T;\n}\n\n/**\n * Holds workspace commands behind both the runner's connection/baseline gate\n * and the CLI's synchronous shutdown intent. A signal can arrive while\n * connect() is awaiting discovery but before runner.stop() runs after the\n * graceful git flush; checking shutdown intent after the await closes that\n * window without constructing a supervisor.\n */\nexport async function startWorkspaceCommandsAfterConnect<T extends { start(): void }>(\n options: WorkspaceCommandStartupOptions<T>,\n): Promise<T | null> {\n const connected = await options.connect();\n if (!connected || options.isShuttingDown()) return null;\n const supervisor = options.create();\n supervisor.start();\n return supervisor;\n}\n\n/**\n * Owns setup and long-running workspace commands independently of the runner\n * that hosts them. start() is intentionally fire-and-forget: command failures\n * are user-visible events and never terminate the agent lifecycle.\n */\nexport class WorkspaceCommandSupervisor {\n private readonly abortController = new AbortController();\n private readonly expectedStartCommandStops = new WeakSet<StartCommandChild>();\n private readonly config: ConveyorConfig | null;\n private readonly workspaceDir: string;\n private readonly connection: WorkspaceCommandConnection;\n private readonly env: NodeJS.ProcessEnv;\n private readonly awaitGitReadyFn: NonNullable<WorkspaceCommandSupervisorOptions[\"awaitGitReady\"]>;\n private readonly startLazySidecarsFn: NonNullable<\n WorkspaceCommandSupervisorOptions[\"startLazySidecars\"]\n >;\n private readonly waitForSidecarsFn: NonNullable<\n WorkspaceCommandSupervisorOptions[\"waitForSidecars\"]\n >;\n private readonly runStartCommandFn: NonNullable<\n WorkspaceCommandSupervisorOptions[\"runStartCommand\"]\n >;\n private readonly loadForwardPortsFn: (workspaceDir: string) => Promise<ForwardPortsResult>;\n private readonly writeOutput: (stream: OutputStream, data: string) => void;\n private readonly terminateStartCommand: (child: StartCommandChild) => void | Promise<void>;\n private readonly reportBootMilestoneFn: (key: PodReportableBootStep) => void;\n\n private startCommandChild: StartCommandChild | null = null;\n private readonly liveStartCommandChildren = new Set<StartCommandChild>();\n private readonly startCommandTerminations = new WeakMap<StartCommandChild, Promise<void>>();\n private readonly startCommandEndPromises = new WeakMap<StartCommandChild, Promise<void>>();\n private readonly resolveStartCommandEnd = new WeakMap<StartCommandChild, () => void>();\n private readonly backgroundTasks = new Set<Promise<void>>();\n private startCommandQueue: Promise<void> = Promise.resolve();\n private shutdownPromise: Promise<void> | null = null;\n private startCommandLaunchRequested = false;\n private started = false;\n private stopped = false;\n /** Resolved by notifyLoopReady() once the runner's core loop (the PTY) is\n * live, or by stop() if shutdown arrives first — either way unblocks the\n * awaiter in runSetupAndStart so a supervisor stopped before the loop ever\n * signals doesn't hang its background task (and therefore stop()) forever. */\n private resolveLoopReady!: () => void;\n private readonly loopReady = new Promise<void>((resolve) => {\n this.resolveLoopReady = resolve;\n });\n\n constructor(options: WorkspaceCommandSupervisorOptions) {\n this.config = options.config;\n this.workspaceDir = options.workspaceDir;\n this.connection = options.connection;\n this.env = options.env ?? process.env;\n this.awaitGitReadyFn =\n options.awaitGitReady ??\n ((opts) =>\n awaitGitReady({\n onLog: opts.onLog,\n signal: opts.signal,\n }));\n this.startLazySidecarsFn =\n options.startLazySidecars ?? ((env, onLog, signal) => startLazySidecars(env, onLog, signal));\n this.waitForSidecarsFn =\n options.waitForSidecars ??\n ((opts) =>\n waitForSidecars({ onLog: opts.onLog, startLazy: opts.startLazy, signal: opts.signal }));\n const executors = defaultCommandExecutors();\n this.runStartCommandFn = options.runStartCommand ?? executors.runStartCommand;\n this.loadForwardPortsFn = options.loadForwardPorts ?? loadForwardPorts;\n this.writeOutput = options.writeOutput ?? defaultWriteOutput;\n this.terminateStartCommand = options.terminateStartCommand ?? terminateProcessGroup;\n this.reportBootMilestoneFn =\n options.reportBootMilestone ??\n ((key) => {\n // Fire-and-forget: never let a boot-meter report delay setup/start.\n void reportBootMilestone({ key, env: this.env });\n });\n }\n\n start(): void {\n if (this.started || this.stopped) return;\n this.started = true;\n this.connection.onRunStartCommand(() => this.restartStartCommand());\n\n this.trackBackgroundTask(\n this.startLazySidecarsFn(\n this.env,\n (message) => this.forwardSetupOutput(\"stdout\", `[sidecars] ${message}\\n`),\n this.abortController.signal,\n ).catch((error: unknown) => this.reportUnexpectedError(error)),\n );\n\n if (this.config) {\n this.trackBackgroundTask(\n this.runSetupAndStart().catch((error: unknown) => this.reportUnexpectedError(error)),\n );\n }\n }\n\n /** Release the start-command launch — called once the runner's core loop\n * (the PTY) is live. Idempotent; resolving an already-settled promise is a\n * no-op, so a late/duplicate call (or one after stop() already resolved\n * it) is harmless. */\n notifyLoopReady(): void {\n this.resolveLoopReady();\n }\n\n stop(): Promise<void> {\n if (this.shutdownPromise) return this.shutdownPromise;\n this.stopped = true;\n // Unblock a runSetupAndStart() background task parked on `await\n // this.loopReady` — without this, stop() would await backgroundTasks\n // forever whenever shutdown lands before the loop ever signals ready.\n this.resolveLoopReady();\n this.abortController.abort();\n const backgroundTasks = [...this.backgroundTasks];\n const termination = this.terminateAllStartCommands();\n this.shutdownPromise = (async () => {\n await Promise.allSettled([termination, this.startCommandQueue, ...backgroundTasks]);\n await this.terminateAllStartCommands();\n })();\n return this.shutdownPromise;\n }\n\n private async runSetupAndStart(): Promise<void> {\n const gitState = await this.awaitGitReadyFn({\n onLog: (message) => this.forwardSetupOutput(\"stdout\", `[git] ${message}\\n`),\n signal: this.abortController.signal,\n });\n if (this.stopped) return;\n if (gitState === \"failed\" || gitState === \"timeout\") {\n this.connection.sendEvent({\n type: \"setup_error\",\n message: \"Workspace not ready — skipping setup/start\",\n });\n return;\n }\n // Repo is up to date — a boot milestone the pod alone can observe.\n if (gitState === \"ready\") this.reportBootMilestoneFn(\"git_ready\");\n\n await this.waitForSidecarsFn({\n onLog: (message) => this.forwardSetupOutput(\"stdout\", `[sidecars] ${message}\\n`),\n startLazy: false,\n signal: this.abortController.signal,\n });\n if (this.stopped) return;\n this.reportBootMilestoneFn(\"sidecars_ready\");\n\n // Hold the app until the runner's core loop (the PTY) is live — Task 9:\n // launching the start command in parallel with agent boot let it win the\n // CPU/git-lock race against the agent during startup. See notifyLoopReady().\n await this.loopReady;\n if (this.stopped) return;\n\n // setupCommand runs at image-bake time, not here — see workspace-command-\n // supervisor's module docs. The pod goes straight from sidecars to start.\n const startCommandRunning = this.config?.startCommand\n ? await this.ensureStartCommandLaunched(this.config.startCommand)\n : false;\n if (this.stopped) return;\n // Start command launched (or there was none to launch) — the last boot\n // milestone the pod observes. Fires unconditionally so it stays the\n // terminal step for every project.\n this.reportBootMilestoneFn(\"start_command_launched\");\n\n const forwardPorts = await this.loadForwardPortsFn(this.workspaceDir);\n if (this.stopped) return;\n const previewPorts = buildSessionPreviewPorts(forwardPorts);\n this.connection.sendEvent({\n type: \"setup_complete\",\n startCommandRunning,\n ...(previewPorts.length > 0 ? { previewPorts } : {}),\n });\n }\n\n private restartStartCommand(): void {\n if (this.stopped || !this.config?.startCommand) return;\n this.connection.sendEvent({\n type: \"start_command_output\",\n stream: \"stdout\",\n data: \"[conveyor-agent] Restarting start command...\\n\",\n });\n void this.enqueueStartCommandReplacement(this.config.startCommand);\n }\n\n private async ensureStartCommandLaunched(command: string): Promise<boolean> {\n if (!this.startCommandLaunchRequested) {\n return this.enqueueStartCommandReplacement(command);\n }\n await this.startCommandQueue;\n return !this.stopped && this.liveStartCommandChildren.size > 0;\n }\n\n private enqueueStartCommandReplacement(command: string): Promise<boolean> {\n this.startCommandLaunchRequested = true;\n const operation = this.startCommandQueue.then(async () => {\n if (this.stopped) return false;\n await this.terminateAllStartCommands();\n if (this.stopped) return false;\n return this.launchStartCommand(command);\n });\n this.startCommandQueue = operation.then(\n () => undefined,\n () => undefined,\n );\n return operation;\n }\n\n private launchStartCommand(command: string): boolean {\n if (this.stopped) return false;\n this.connection.sendEvent({ type: \"start_command_started\" });\n try {\n const child = this.runStartCommandFn(command, this.workspaceDir, (stream, data) => {\n if (this.stopped) return;\n this.connection.sendEvent({ type: \"start_command_output\", stream, data });\n this.writeOutput(stream, data);\n });\n this.liveStartCommandChildren.add(child);\n const ended = new Promise<void>((resolve) => {\n this.resolveStartCommandEnd.set(child, resolve);\n });\n this.startCommandEndPromises.set(child, ended);\n if (this.stopped) {\n void this.terminateStartCommandChild(child);\n return false;\n }\n this.startCommandChild = child;\n child.on(\"exit\", (code, signal) => {\n if (this.startCommandChild === child) this.startCommandChild = null;\n this.liveStartCommandChildren.delete(child);\n this.settleStartCommandEnd(child);\n if (this.stopped || this.expectedStartCommandStops.has(child)) return;\n const message = `start command exited${code === null ? \"\" : ` with code ${code}`}${signal ? ` (signal: ${signal})` : \"\"}`;\n this.connection.sendEvent({ type: \"start_command_exited\", code, signal, message });\n if (code !== null && code !== 0) {\n this.connection.sendEvent({\n type: \"start_command_error\",\n message: `start command exited with code ${code}${signal ? ` (signal: ${signal})` : \"\"}`,\n });\n }\n });\n child.on(\"error\", (error) => {\n if (child.pid === undefined) {\n if (this.startCommandChild === child) this.startCommandChild = null;\n this.liveStartCommandChildren.delete(child);\n this.settleStartCommandEnd(child);\n this.startCommandTerminations.delete(child);\n }\n if (this.stopped) return;\n this.connection.sendEvent({ type: \"start_command_error\", message: error.message });\n });\n return true;\n } catch (error) {\n if (!this.stopped) {\n this.connection.sendEvent({\n type: \"start_command_error\",\n message: error instanceof Error ? error.message : String(error),\n });\n }\n return false;\n }\n }\n\n private terminateStartCommandChild(child: StartCommandChild): Promise<void> {\n const existing = this.startCommandTerminations.get(child);\n if (existing) return existing;\n this.expectedStartCommandStops.add(child);\n const processTermination = Promise.resolve(this.terminateStartCommand(child));\n const ended = this.startCommandEndPromises.get(child);\n const termination = (ended ? Promise.race([processTermination, ended]) : processTermination)\n .then(() => undefined)\n .finally(() => this.startCommandTerminations.delete(child));\n this.startCommandTerminations.set(child, termination);\n return termination;\n }\n\n private async terminateAllStartCommands(): Promise<void> {\n const live = [...this.liveStartCommandChildren].filter((child) => child.exitCode === null);\n await Promise.all(live.map((child) => this.terminateStartCommandChild(child)));\n }\n\n private settleStartCommandEnd(child: StartCommandChild): void {\n this.resolveStartCommandEnd.get(child)?.();\n this.resolveStartCommandEnd.delete(child);\n this.startCommandEndPromises.delete(child);\n }\n\n private trackBackgroundTask(task: Promise<void>): void {\n this.backgroundTasks.add(task);\n void task.finally(() => this.backgroundTasks.delete(task));\n }\n\n private forwardSetupOutput(stream: OutputStream, data: string): void {\n if (this.stopped) return;\n this.connection.sendEvent({ type: \"setup_output\", stream, data });\n this.writeOutput(stream, data);\n }\n\n private reportUnexpectedError(error: unknown): void {\n if (this.stopped) return;\n this.connection.sendEvent({\n type: \"setup_error\",\n message: error instanceof Error ? error.message : String(error),\n });\n }\n}\n","// Defense-in-depth startup check. The authoritative guarantee that a session is\n// bound to the right task lives server-side (requireTaskAuth + the Postgres\n// partial-unique index on active CodespaceSessions). This check exists so that\n// if those invariants ever regress, a human sees a loud WARN immediately\n// instead of the symptoms SEC-9 produced (multiple agents silently clobbering\n// the same branch).\nexport interface SessionIdentityLogger {\n warn(message: string, data?: Record<string, unknown>): void;\n info?(message: string, data?: Record<string, unknown>): void;\n}\n\nexport interface CheckSessionTaskIdentityParams {\n sessionId: string | undefined;\n taskId: string;\n fetchSessionTaskId: (sessionId: string) => Promise<string>;\n logger: SessionIdentityLogger;\n}\n\nexport async function checkSessionTaskIdentity(\n params: CheckSessionTaskIdentityParams,\n): Promise<\"match\" | \"mismatch\" | \"skipped\" | \"error\"> {\n const { sessionId, taskId, fetchSessionTaskId, logger } = params;\n if (!sessionId || sessionId === taskId) return \"skipped\";\n let sessionTaskId: string;\n try {\n sessionTaskId = await fetchSessionTaskId(sessionId);\n } catch (err) {\n const message = err instanceof Error ? err.message : String(err);\n logger.warn(\"Could not verify session/task identity — continuing (defense-in-depth only)\", {\n sessionId,\n taskId,\n error: message,\n });\n return \"error\";\n }\n if (sessionTaskId !== taskId) {\n logger.warn(\n \"!!! CONVEYOR_SESSION_ID is bound to a different task than CONVEYOR_TASK_ID — server-side guards should still block mutations, but this indicates a misconfiguration or replayed token.\",\n { sessionId, envTaskId: taskId, sessionTaskId },\n );\n return \"mismatch\";\n }\n return \"match\";\n}\n","/**\n * Structured pod-exit log payload. The control plane (workspace reconciler) can\n * only ever infer *that* an agent stopped — it sees a stale heartbeat and marks\n * the session Stranded/Ended. It cannot see *why*. This log closes that gap from\n * the pod side: emitted at every catchable exit path so the claudespace pod logs\n * record the cause (teardown signal vs clean finish vs crash) alongside the\n * `sessionId` that joins to the API's `session_stranded` / reconcile logs.\n *\n * Caveat: an OOMKill (SIGKILL / 137) is uncatchable, so it never reaches here —\n * those are diagnosed from GKE kernel OOM logs, not this line.\n */\n// - signal: SIGTERM/SIGINT — teardown or a reaper asked us to stop\n// - clean: runner.run() resolved normally\n// - error: runner finalState=error, or run() rejected\n// - force_timeout: graceful-shutdown watchdog fired\nexport type AgentExitReason =\n | \"signal\"\n | \"clean\"\n | \"error\"\n | \"uncaught_exception\"\n | \"unhandled_rejection\"\n | \"force_timeout\";\n\nexport interface AgentExitIdentity {\n sessionId?: string | undefined;\n taskId?: string | undefined;\n workspaceId?: string | undefined;\n runnerMode?: string | undefined;\n}\n\nexport interface AgentExitLog extends AgentExitIdentity {\n event: \"agent_exit\";\n reason: AgentExitReason;\n exitCode: number;\n signal?: string;\n finalState?: string;\n uptimeSec: number;\n}\n\n/** Clean shutdowns are routine (info); every other exit is worth a warn so it\n * surfaces in severity-filtered log queries. */\nexport function exitLogLevel(reason: AgentExitReason): \"info\" | \"warn\" {\n return reason === \"clean\" ? \"info\" : \"warn\";\n}\n\n/**\n * Build the `agent_exit` payload, dropping any undefined optional/identity keys\n * so the serialized log line stays tidy (no `\"workspaceId\":undefined` noise).\n */\nexport function buildAgentExitLog(args: {\n reason: AgentExitReason;\n exitCode: number;\n uptimeSec: number;\n signal?: string | undefined;\n finalState?: string | undefined;\n identity?: AgentExitIdentity | undefined;\n}): AgentExitLog {\n const log: AgentExitLog = {\n event: \"agent_exit\",\n reason: args.reason,\n exitCode: args.exitCode,\n uptimeSec: Math.round(args.uptimeSec * 10) / 10,\n };\n if (args.signal !== undefined) log.signal = args.signal;\n if (args.finalState !== undefined) log.finalState = args.finalState;\n const id = args.identity;\n if (id) {\n if (id.sessionId !== undefined) log.sessionId = id.sessionId;\n if (id.taskId !== undefined) log.taskId = id.taskId;\n if (id.workspaceId !== undefined) log.workspaceId = id.workspaceId;\n if (id.runnerMode !== undefined) log.runnerMode = id.runnerMode;\n }\n return log;\n}\n","/**\n * Task-less pod identity detection (Claudespace v3 project runners AND adhoc\n * scratch pods).\n *\n * A v3 task-less pod's bootstrap bundle carries a session JWT with\n * {projectId, workspaceId, sessionId, role} and NO taskId claim; the entrypoint\n * exports CONVEYOR_PROJECT_ID / CONVEYOR_SESSION_ID / CONVEYOR_WORKSPACE_ID from\n * the claims, does NOT export CONVEYOR_TASK_ID, and sets CONVEYOR_MODE to \"pm\"\n * (project runner) or \"adhoc\" (interactive scratch TUI). Both share this\n * identity shape — cli.ts branches on CONVEYOR_MODE afterward to pick the\n * runner. Every condition below is required — anything else falls through to\n * the task-runner path, which fail-closed exits without a task id.\n *\n * `workspaceId` is the stable `Workspace` row id — unlike `sessionId` (the\n * `WorkspaceSession` row), it survives a sleep/wake cycle: a user-initiated\n * wake mints a brand-new writer `WorkspaceSession` (fresh-session semantics,\n * see `ensure-adhoc.ts`), so `sessionId` changes on every wake. The adhoc\n * runner keys its Claude session lineage on `workspaceId` for exactly this\n * reason — keying on `sessionId` would never resume the prior transcript.\n */\n\nexport interface ProjectRunnerIdentity {\n projectId: string;\n sessionId: string;\n workspaceId: string;\n taskToken: string;\n}\n\nexport function resolveProjectRunnerIdentity(\n env: Record<string, string | undefined>,\n): ProjectRunnerIdentity | null {\n // A task id always wins: this is a task pod, never a project runner.\n if (env.CONVEYOR_TASK_ID) return null;\n if (!env.CONVEYOR_TASK_TOKEN) return null;\n if (!env.CONVEYOR_PROJECT_ID || !env.CONVEYOR_SESSION_ID || !env.CONVEYOR_WORKSPACE_ID) {\n return null;\n }\n // Task-less identity is shared by the project runner (\"pm\") and the adhoc\n // scratch-pod TUI (\"adhoc\"); cli.ts branches on CONVEYOR_MODE afterward to\n // pick the runner. Any OTHER mode (reader/review/task/absent) is not a valid\n // task-less identity. NOTE: the adhoc branch in cli.ts gates on THIS resolver\n // returning non-null AND CONVEYOR_MODE === \"adhoc\" — omitting \"adhoc\" here\n // makes that branch unreachable and crash-loops every adhoc pod at the\n // task-mode fall-through.\n if (env.CONVEYOR_MODE !== \"pm\" && env.CONVEYOR_MODE !== \"adhoc\") return null;\n\n return {\n projectId: env.CONVEYOR_PROJECT_ID,\n sessionId: env.CONVEYOR_SESSION_ID,\n workspaceId: env.CONVEYOR_WORKSPACE_ID,\n taskToken: env.CONVEYOR_TASK_TOKEN,\n };\n}\n","/**\n * ProjectSessionRunner — the task-less PROJECT pod agent loop (Claudespace v3\n * project runners).\n *\n * What a project agent does today: connect, register its WorkspaceSession\n * (connectAgent), heartbeat (lease renewal via the server's v3 fallthrough),\n * and idle awaiting project-scoped messages. It deliberately does NOT run the\n * task-shaped SessionRunner lifecycle — getTaskContext, git branch sync, the\n * QueryBridge prompt loop and WIP flushing are all keyed on a Task, and the\n * server-side pm-conversation surface for project workspaces does not exist\n * yet (project chat is served by the server-side ProjectAgentService\n * responder). When that surface lands (project context RPC + project-keyed\n * message routing), this runner grows the message->query loop; until then an\n * inbound message is logged and acknowledged as activity only.\n */\nimport {\n AgentConnection,\n type AgentConnectionConfig,\n type IncomingMessage,\n} from \"../connection/agent-connection.js\";\nimport { Lifecycle, DEFAULT_LIFECYCLE_CONFIG, type LifecycleConfig } from \"./lifecycle.js\";\nimport { sampleKeyUsage } from \"../execution/usage-sampler.js\";\n\nexport interface ProjectSessionRunnerConfig {\n connection: AgentConnectionConfig;\n projectId: string;\n lifecycle?: Partial<LifecycleConfig>;\n}\n\nexport interface ProjectSessionRunnerCallbacks {\n onEvent?: (event: Record<string, unknown>) => void;\n}\n\n/** The AgentConnection surface the project runner uses (injectable for tests). */\nexport interface ProjectRunnerConnection {\n connect(): Promise<void>;\n disconnect(): void;\n call(\n method: \"connectAgent\",\n payload: { sessionId: string },\n ): Promise<{ sessionId: string; taskId: string | null; pendingMessages: unknown[] }>;\n sendEvent(event: { type: string; [key: string]: unknown }): void;\n sendHeartbeat(): void;\n emitStatus(status: string): Promise<void>;\n onMessage(callback: (msg: IncomingMessage) => void): void;\n onStop(callback: () => void): void;\n refreshTaskTokenFromBootstrap(): Promise<boolean>;\n}\n\nexport class ProjectSessionRunner {\n readonly connection: ProjectRunnerConnection;\n readonly lifecycle: Lifecycle;\n\n private readonly config: ProjectSessionRunnerConfig;\n private readonly callbacks: ProjectSessionRunnerCallbacks;\n private stopped = false;\n private stopResolver: (() => void) | null = null;\n private _finalState: \"finished\" | \"error\" | null = null;\n\n constructor(\n config: ProjectSessionRunnerConfig,\n callbacks: ProjectSessionRunnerCallbacks = {},\n connection?: ProjectRunnerConnection,\n ) {\n this.config = config;\n this.callbacks = callbacks;\n this.connection = connection ?? new AgentConnection(config.connection);\n this.lifecycle = new Lifecycle(\n // No git flush: the project runner does not (yet) mutate the checkout,\n // and the WIP snapshot machinery is branch/task-shaped.\n { ...DEFAULT_LIFECYCLE_CONFIG, gitFlushIntervalMs: 0, ...config.lifecycle },\n {\n onHeartbeat: () => this.connection.sendHeartbeat(),\n onIdleTimeout: () => {\n process.stderr.write(\"[conveyor-agent] Project runner idle timeout, shutting down\\n\");\n this.requestStop();\n },\n onDormantTimeout: () => this.requestStop(),\n // v3 credential refresh: re-poll the pod bootstrap route (session JWT,\n // GitHub token, keys are all swapped in place). The task-scoped\n // refreshGithubToken RPC does not apply to a task-less session.\n onTokenRefresh: () => void this.connection.refreshTaskTokenFromBootstrap().catch(() => {}),\n onGitFlush: () => {},\n onUsageSample: () => void this.sampleAndReportKeyUsage(),\n },\n );\n }\n\n get finalState(): \"finished\" | \"error\" | null {\n return this._finalState;\n }\n\n get isStopped(): boolean {\n return this.stopped;\n }\n\n /** Connect, register the session, then idle until stopped or idle-timeout. */\n async run(): Promise<void> {\n try {\n await this.connection.connect();\n this.connection.sendEvent({\n type: \"connected\",\n sessionId: this.config.connection.sessionId,\n projectId: this.config.projectId,\n });\n\n this.connection.onStop(() => this.requestStop());\n this.connection.onMessage((msg) => this.handleMessage(msg));\n this.lifecycle.startHeartbeat();\n this.lifecycle.startTokenRefresh();\n this.lifecycle.startUsageSample();\n\n // Join the session room + activate the lease (server v3 fallthrough).\n await this.connection.call(\"connectAgent\", {\n sessionId: this.config.connection.sessionId,\n });\n\n process.stderr.write(\n `[conveyor-agent] Project runner connected (project: ${this.config.projectId}) — idling\\n`,\n );\n await this.connection.emitStatus(\"idle\");\n this.callbacks.onEvent?.({ type: \"project_runner_idle\", projectId: this.config.projectId });\n\n this.lifecycle.startIdleTimer();\n await this.waitUntilStopped();\n this._finalState = \"finished\";\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[conveyor-agent] Project runner failed: ${message}\\n`);\n this.connection.sendEvent({ type: \"error\", message });\n this._finalState = \"error\";\n } finally {\n this.shutdown();\n }\n }\n\n /**\n * The pm-conversation surface is a follow-up: no server path routes chat to\n * a task-less session yet, so any message that does arrive is surfaced in\n * the logs and treated as activity (idle timer restarts) — never executed.\n */\n private handleMessage(msg: IncomingMessage): void {\n const preview = msg.content.length > 120 ? `${msg.content.slice(0, 120)}…` : msg.content;\n process.stderr.write(\n `[conveyor-agent] Project runner received message (pm surface not wired yet): \"${preview.replace(/\\n/g, \"\\\\n\")}\"\\n`,\n );\n this.callbacks.onEvent?.({ type: \"project_message_received\", content: msg.content });\n if (!this.stopped) this.lifecycle.startIdleTimer();\n }\n\n /** External stop (SIGTERM/SIGINT or server session:stop). */\n stop(): void {\n this.requestStop();\n }\n\n private requestStop(): void {\n if (this.stopped) return;\n this.stopped = true;\n if (this.stopResolver) {\n const resolve = this.stopResolver;\n this.stopResolver = null;\n resolve();\n }\n }\n\n private waitUntilStopped(): Promise<void> {\n if (this.stopped) return Promise.resolve();\n return new Promise<void>((resolve) => {\n this.stopResolver = resolve;\n });\n }\n\n /** Report the running subscription key's rate-limit utilization (same path as\n * the task runner). Best-effort — never throws, no-op without an OAuth token. */\n private async sampleAndReportKeyUsage(): Promise<void> {\n if (this.stopped) return;\n const samples = await sampleKeyUsage(process.env.CLAUDE_CODE_OAUTH_TOKEN);\n for (const sample of samples) {\n this.connection.sendEvent({\n type: \"rate_limit_update\",\n rateLimitType: sample.rateLimitType,\n utilization: sample.utilization,\n status: sample.status,\n resetsAt: sample.resetsAt ?? undefined,\n gauges: sample.gauges,\n });\n }\n }\n\n private shutdown(): void {\n this.stopped = true;\n this.lifecycle.destroy();\n this.connection.sendEvent({ type: \"shutdown\", reason: this._finalState ?? \"finished\" });\n this.connection.disconnect();\n }\n}\n","/**\n * Multi-key `/usage` probe — the on-demand \"refresh all keys from one box\" path.\n *\n * The normal sampler (`usage-sampler.ts`) can only report the ONE key the pod\n * booted under: it reads the pod's shared `~/.claude/.credentials.json` and an\n * attribution guard refuses to write another account's gauges. This module\n * instead probes an explicit list of keys, isolating EACH one in its own\n * temporary `CLAUDE_CONFIG_DIR` so the pod's shared credentials file (read by\n * the user's other concurrent pods on the GCS-FUSE mount) is never mutated.\n *\n * For each key: a temp config dir gets a synthesized `.credentials.json` for the\n * key's token plus a copy of the pod's onboarded `.claude.json` (so trust /\n * onboarding / model-cache carry over and the `/usage` panel renders without\n * parking at a first-run dialog). The `claude` CLI is then driven under a PTY\n * (`runUsageProbe`) with `CLAUDE_CONFIG_DIR` pointed at that dir.\n *\n * Best-effort throughout: a key whose probe fails or yields no gauges is simply\n * omitted — this never throws.\n */\nimport { mkdtemp, writeFile, copyFile, rm } from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { buildSynthesizedCredentials, claudeJsonPath } from \"../harness/pty/credentials.js\";\nimport { createServiceLogger } from \"../utils/logger.js\";\nimport { parseUsageGauges } from \"./parse-usage.js\";\nimport { runUsageProbe } from \"./run-probe.js\";\nimport type { KeyUsageSample } from \"../execution/usage-sampler.js\";\n\nconst logger = createServiceLogger(\"multi-key-probe\");\n\nexport interface ProbeKeyInput {\n codingAgentKeyId: string;\n /** Decrypted subscription OAuth token for this key. */\n oauthToken: string;\n}\n\nexport interface ProbedKeyUsage {\n codingAgentKeyId: string;\n samples: KeyUsageSample[];\n}\n\nexport interface MultiKeyProbeDeps {\n /**\n * Isolated single-key probe: prepare credentials for `token` and return the\n * raw `/usage` panel text. Injectable so the sequencing/mapping is testable\n * without spawning a PTY or touching the filesystem.\n */\n probeOne?: (token: string) => Promise<string>;\n now?: () => number;\n}\n\n/** Map a parsed `/usage` panel to rate-limit samples (mirrors usage-sampler). */\nfunction gaugesToSamples(stdout: string): KeyUsageSample[] {\n const { sessionUsage, weeklyUsage, sessionResetsAt, weeklyResetsAt, gauges } =\n parseUsageGauges(stdout);\n const samples: KeyUsageSample[] = [];\n if (sessionUsage !== null) {\n samples.push({\n rateLimitType: \"five_hour\",\n utilization: sessionUsage,\n status: \"allowed\",\n resetsAt: sessionResetsAt,\n gauges,\n });\n }\n if (weeklyUsage !== null) {\n samples.push({\n rateLimitType: \"seven_day\",\n utilization: weeklyUsage,\n status: \"allowed\",\n resetsAt: weeklyResetsAt,\n gauges,\n });\n }\n return samples;\n}\n\n/**\n * Default `probeOne`: build an isolated config dir for `token`, run the probe\n * under it, and clean up. Best-effort — resolves \"\" on any failure.\n */\nasync function isolatedProbe(token: string, now: number): Promise<string> {\n let dir: string | null = null;\n try {\n dir = await mkdtemp(join(tmpdir(), \"conveyor-usage-\"));\n await writeFile(join(dir, \".credentials.json\"), buildSynthesizedCredentials(token, now), {\n encoding: \"utf8\",\n mode: 0o600,\n });\n // Carry the pod's onboarding/trust/model-cache into the isolated dir so the\n // /usage panel renders instead of parking at a first-run dialog. Best-effort:\n // a missing source file just means a fresh config (the CLI onboards silently\n // for a read-only /usage panel).\n await copyFile(claudeJsonPath(), join(dir, \".claude.json\")).catch(() => {});\n return await runUsageProbe({ env: { ...process.env, CLAUDE_CONFIG_DIR: dir } });\n } catch (error) {\n logger.info(\"isolated usage probe failed\", {\n error: error instanceof Error ? error.message : String(error),\n });\n return \"\";\n } finally {\n if (dir) await rm(dir, { recursive: true, force: true }).catch(() => {});\n }\n}\n\n/**\n * Probe each key's `/usage` sequentially (avoid concurrent PTYs) and return the\n * samples per key. Keys that yield no gauges are omitted. Never throws.\n */\nexport async function probeKeysUsage(\n keys: ProbeKeyInput[],\n deps: MultiKeyProbeDeps = {},\n): Promise<ProbedKeyUsage[]> {\n const now = deps.now ?? Date.now;\n const probeOne = deps.probeOne ?? ((token: string) => isolatedProbe(token, now()));\n\n const results: ProbedKeyUsage[] = [];\n for (const key of keys) {\n if (!key.oauthToken) continue;\n try {\n const stdout = await probeOne(key.oauthToken);\n const samples = gaugesToSamples(stdout);\n if (samples.length > 0) {\n results.push({ codingAgentKeyId: key.codingAgentKeyId, samples });\n }\n } catch (error) {\n logger.info(\"usage probe for key failed\", {\n codingAgentKeyId: key.codingAgentKeyId,\n error: error instanceof Error ? error.message : String(error),\n });\n }\n }\n return results;\n}\n","/**\n * Seeds ChatGPT-subscription OAuth tokens into opencode's auth store.\n *\n * The API delivers CONVEYOR_OPENCODE_OAUTH = base64({access, refresh, expires})\n * (see apps/api project-key/methods/key-resolution.ts). We write it as the\n * `openai` entry of ~/.local/share/opencode/auth.json — the store the\n * opencode-openai-codex-auth plugin reads and lazily refreshes. That directory\n * is fuse-symlinked on GCP projects, so a refreshed store outlives the pod;\n * the seed therefore only wins when the existing entry is missing, malformed,\n * or STALER than the seed (re-sign-in on the site produces a newer seed —\n * that's the invalidation-recovery path). Best-effort like\n * ensureClaudeCredentials: IO failures log-and-continue, never throw.\n */\nimport { promises as fs } from \"node:fs\";\nimport { dirname, join } from \"node:path\";\nimport { homedir } from \"node:os\";\nimport { createServiceLogger } from \"../../../utils/logger.js\";\n\nconst logger = createServiceLogger(\"opencode-auth\");\n\n/** Bump deliberately: also pre-warmed in the pod image (Dockerfile.base). */\nexport const OPENCODE_CODEX_PLUGIN = \"opencode-openai-codex-auth@4.4.0\";\nconst PLUGIN_PACKAGE = \"opencode-openai-codex-auth\";\n\nexport interface OpenCodeOauthSeed {\n access: string;\n refresh: string;\n expires: number;\n}\n\nexport function opencodeAuthPath(env: NodeJS.ProcessEnv): string {\n const dataHome = env.XDG_DATA_HOME ?? join(env.HOME ?? homedir(), \".local\", \"share\");\n return join(dataHome, \"opencode\", \"auth.json\");\n}\n\nexport function opencodeConfigPath(env: NodeJS.ProcessEnv): string {\n const configHome = env.XDG_CONFIG_HOME ?? join(env.HOME ?? homedir(), \".config\");\n return join(configHome, \"opencode\", \"opencode.json\");\n}\n\nexport function parseOauthSeed(b64: string | undefined): OpenCodeOauthSeed | null {\n if (!b64) return null;\n try {\n const parsed = JSON.parse(Buffer.from(b64, \"base64\").toString(\"utf8\")) as Record<\n string,\n unknown\n >;\n if (\n typeof parsed.access === \"string\" &&\n typeof parsed.refresh === \"string\" &&\n typeof parsed.expires === \"number\"\n ) {\n return { access: parsed.access, refresh: parsed.refresh, expires: parsed.expires };\n }\n return null;\n } catch {\n return null;\n }\n}\n\n/** Seed only when the store entry is missing/malformed or older than the seed. */\nexport function shouldSeed(existingEntry: unknown, seed: OpenCodeOauthSeed): boolean {\n if (!existingEntry || typeof existingEntry !== \"object\") return true;\n const entry = existingEntry as Record<string, unknown>;\n if (entry.type !== \"oauth\") return true;\n if (typeof entry.access !== \"string\" || typeof entry.refresh !== \"string\") return true;\n if (typeof entry.expires !== \"number\") return true;\n return entry.expires < seed.expires;\n}\n\nasync function readJsonFile(path: string): Promise<Record<string, unknown>> {\n try {\n return JSON.parse(await fs.readFile(path, \"utf8\")) as Record<string, unknown>;\n } catch {\n return {};\n }\n}\n\nasync function writeJsonFile(path: string, value: Record<string, unknown>): Promise<void> {\n await fs.mkdir(dirname(path), { recursive: true });\n await fs.writeFile(path, `${JSON.stringify(value, null, 2)}\\n`, { mode: 0o600 });\n}\n\nasync function ensureAuthEntry(env: NodeJS.ProcessEnv, seed: OpenCodeOauthSeed): Promise<void> {\n const path = opencodeAuthPath(env);\n const store = await readJsonFile(path);\n if (!shouldSeed(store.openai, seed)) {\n logger.info(\"opencode oauth store is fresher than the seed; leaving it alone\");\n return;\n }\n store.openai = {\n type: \"oauth\",\n access: seed.access,\n refresh: seed.refresh,\n expires: seed.expires,\n };\n await writeJsonFile(path, store);\n logger.info(\"seeded opencode oauth store entry\");\n}\n\nasync function ensurePluginConfig(env: NodeJS.ProcessEnv): Promise<void> {\n const path = opencodeConfigPath(env);\n const config = await readJsonFile(path);\n const plugins = Array.isArray(config.plugin) ? (config.plugin as unknown[]) : [];\n const isOurs = (p: unknown): boolean =>\n typeof p === \"string\" && (p === PLUGIN_PACKAGE || p.startsWith(`${PLUGIN_PACKAGE}@`));\n const hasExactPin = plugins.includes(OPENCODE_CODEX_PLUGIN);\n const hasStalePin = plugins.some((p) => isOurs(p) && p !== OPENCODE_CODEX_PLUGIN);\n // Already correct — don't churn the fuse file.\n if (hasExactPin && !hasStalePin) return;\n const kept = plugins.filter((p) => !isOurs(p));\n config.plugin = [...kept, OPENCODE_CODEX_PLUGIN];\n await writeJsonFile(path, config);\n logger.info(\"ensured opencode codex-auth plugin in config\");\n}\n\n/**\n * Best-effort seed of opencode's oauth store + plugin config. No-op when\n * CONVEYOR_OPENCODE_OAUTH is absent or unparseable. Never throws.\n */\nexport async function seedOpenCodeOauth(env: NodeJS.ProcessEnv): Promise<void> {\n const seed = parseOauthSeed(env.CONVEYOR_OPENCODE_OAUTH);\n if (!seed) return;\n try {\n await ensureAuthEntry(env, seed);\n await ensurePluginConfig(env);\n } catch (err) {\n logger.warn(\n `failed to seed opencode oauth store: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n}\n","/**\n * OpenCodeTuiAdapter — drives the `opencode` TUI (https://opencode.ai) as a\n * raw relayed terminal. v1 declares NO structured events (no trusted\n * transcript/hook source is wired), no prefill, no passive turns, and no\n * resume (--continue behavior on an empty state dir is unverified; enable\n * after live verification). Auth is env-based for api_key keys\n * (CONVEYOR_AGENT_KEY → provider-native env var) and store-based for\n * chatgpt_oauth keys (CONVEYOR_OPENCODE_OAUTH seeded into opencode's\n * auth.json by prepareEnvironment — see opencode-auth.ts).\n */\nimport { buildPromptBytes, inheritedEnv } from \"../pty-support.js\";\nimport { cleanTerminalOutput } from \"../spawn-args.js\";\nimport { seedOpenCodeOauth } from \"./opencode-auth.js\";\nimport {\n findOnPath,\n TuiUnavailableError,\n type TuiAdapter,\n type TuiCapabilities,\n type TuiFingerprintInput,\n type TuiSpawnInput,\n type TuiSpawnSpec,\n} from \"./types.js\";\n\n/** provider → the env var its SDK/CLI reads natively. */\nconst PROVIDER_KEY_ENV: Record<string, string> = {\n openai: \"OPENAI_API_KEY\",\n anthropic: \"ANTHROPIC_API_KEY\",\n};\n\nexport class OpenCodeTuiAdapter implements TuiAdapter {\n readonly id = \"opencode\" as const;\n readonly capabilities: TuiCapabilities = {\n resume: false,\n structuredEvents: false,\n prefill: false,\n passiveTurns: false,\n };\n\n constructor(private readonly env: NodeJS.ProcessEnv = process.env) {}\n\n resolveBinary(env: NodeJS.ProcessEnv = this.env): string {\n const override = env.CONVEYOR_OPENCODE_BIN;\n const found = override ? findOnPath(override, env) : findOnPath(\"opencode\", env);\n if (!found) {\n throw new TuiUnavailableError(\n \"opencode\",\n \"The opencode CLI is not available in this environment. It must be baked \" +\n \"into the pod image (see Dockerfile.base) — re-run Build Image for this \" +\n \"project, or set CONVEYOR_OPENCODE_BIN to its absolute path.\",\n );\n }\n return found;\n }\n\n buildSpawn(input: TuiSpawnInput): TuiSpawnSpec {\n const env = { ...inheritedEnv() };\n delete env.CONVEYOR_AGENT_KEY;\n delete env.CONVEYOR_OPENCODE_OAUTH;\n const oauthActive = Boolean(this.env.CONVEYOR_OPENCODE_OAUTH);\n const key = this.env.CONVEYOR_AGENT_KEY;\n const provider = this.env.CONVEYOR_AGENT_PROVIDER ?? \"openai\";\n const keyEnvVar = PROVIDER_KEY_ENV[provider];\n // ChatGPT-subscription auth flows through the opencode auth store (see\n // opencode-auth.ts) — a provider API key would override it to paid billing.\n if (key && keyEnvVar && !oauthActive) env[keyEnvVar] = key;\n\n const model = this.env.CONVEYOR_AGENT_MODEL ?? input.options.model;\n const args: string[] = [];\n if (model) args.push(\"--model\", model.includes(\"/\") ? model : `${provider}/${model}`);\n return { file: this.resolveBinary(), args, env };\n }\n\n async prepareEnvironment(): Promise<void> {\n // ChatGPT-subscription tokens (when present) are seeded into opencode's\n // auth store; session-state persistence stays the entrypoint's job\n // (GCS-FUSE symlinks for ~/.local/share/opencode).\n await seedOpenCodeOauth(this.env);\n }\n\n spawnFingerprint(input: TuiFingerprintInput): string {\n return JSON.stringify([\"opencode\", input.model, input.cwd]);\n }\n\n encodePromptBytes(text: string): string {\n // Bracketed paste — standard for modern TUIs; revisit if live verification\n // shows opencode's input mishandles it.\n return buildPromptBytes(text);\n }\n\n buildExitErrors(exitCode: number, rawOutput: string): string[] {\n const errors = [`opencode exited (code ${exitCode}) without a result`];\n const tail = cleanTerminalOutput(rawOutput);\n if (tail) errors.push(`Last terminal output before exit:\\n${tail}`);\n return errors;\n }\n}\n","import type { TuiAdapter, TuiKind } from \"./types.js\";\nimport { ClaudeTuiAdapter } from \"./claude.js\";\nimport { OpenCodeTuiAdapter } from \"./opencode.js\";\n\nexport * from \"./types.js\";\nexport { ClaudeTuiAdapter } from \"./claude.js\";\nexport { OpenCodeTuiAdapter } from \"./opencode.js\";\n\n/** Adapter factory. */\nexport function resolveTuiAdapter(kind: TuiKind = \"claude-code\"): TuiAdapter {\n switch (kind) {\n case \"claude-code\":\n return new ClaudeTuiAdapter();\n case \"opencode\":\n return new OpenCodeTuiAdapter();\n default:\n throw new Error(`Unknown TUI kind: ${kind as string}`);\n }\n}\n","/**\n * Project-scoped tools for TASK-LESS sessions (headless audits on ad-hoc\n * pods). Everything is keyed on the projectId the runner was booted with —\n * there is no task, so none of these resolve state from the session's task.\n *\n * Two families:\n * - Tag-audit apply surface: list/create/update tags, suggestions, project chat.\n * - Task-audit evidence + reporting: cross-task reads (task, chat, execution\n * logs) and reportTaskAuditResult persistence.\n */\nimport { z } from \"zod\";\nimport type { AgentSessionServiceMethods } from \"@project/shared\";\nimport { defineTool } from \"../harness/index.js\";\nimport { textResult } from \"./helpers.js\";\n\n/**\n * The one connection capability these tools need — satisfied by the real\n * AgentConnection and by the adhoc runner's injectable AdhocRunnerConnection.\n */\nexport interface ProjectToolsConnection {\n call<M extends keyof AgentSessionServiceMethods>(\n method: M,\n payload: AgentSessionServiceMethods[M][\"payload\"],\n ): Promise<AgentSessionServiceMethods[M][\"response\"]>;\n}\n\nconst CONTEXT_PATH_SHAPE = z.object({\n type: z.enum([\"rule\", \"doc\", \"file\", \"folder\"]).describe(\"Link kind\"),\n path: z.string().min(1).max(500).describe(\"Repo-relative path\"),\n label: z.string().max(100).optional(),\n});\n\nfunction errText(prefix: string, error: unknown): { content: { type: \"text\"; text: string }[] } {\n return textResult(`${prefix}: ${error instanceof Error ? error.message : \"Unknown error\"}`);\n}\n\n// ── Tag audit surface ─────────────────────────────────────────────────\n\nfunction buildListTagsTool(connection: ProjectToolsConnection, projectId: string) {\n return defineTool(\n \"list_tags\",\n \"List this project's tags (id, name, color). Use the ids with update_tag.\",\n {},\n async () => {\n try {\n const tags = await connection.call(\"listProjectTags\", { projectId });\n return textResult(JSON.stringify(tags, null, 2));\n } catch (error) {\n return errText(\"Failed to list tags\", error);\n }\n },\n { annotations: { readOnlyHint: true } },\n );\n}\n\nfunction buildCreateTagTool(connection: ProjectToolsConnection, projectId: string) {\n return defineTool(\n \"create_tag\",\n \"Create a project tag. Include a crisp description and contextPaths (rule/doc/file/folder links agents auto-load when working on matching tasks). Fails if the name already exists.\",\n {\n name: z.string().min(1).max(50),\n color: z\n .string()\n .regex(/^#[0-9a-fA-F]{6}$/)\n .optional()\n .describe(\"#RRGGBB (default gray)\"),\n description: z.string().max(500).optional(),\n contextPaths: z.array(CONTEXT_PATH_SHAPE).max(20).optional(),\n },\n async ({ name, color, description, contextPaths }) => {\n try {\n const result = await connection.call(\"createProjectTag\", {\n projectId,\n name,\n color,\n description,\n contextPaths,\n });\n return textResult(`Tag created: ${result.id}`);\n } catch (error) {\n return errText(\"Failed to create tag\", error);\n }\n },\n );\n}\n\nfunction buildUpdateTagTool(connection: ProjectToolsConnection, projectId: string) {\n return defineTool(\n \"update_tag\",\n \"Update a tag's name, color, description, or contextPaths. contextPaths is a FULL replacement — include existing links you want to keep. Verify paths exist in the repo first.\",\n {\n tagId: z.string().describe(\"Tag id from list_tags\"),\n name: z.string().min(1).max(50).optional(),\n color: z\n .string()\n .regex(/^#[0-9a-fA-F]{6}$/)\n .optional(),\n description: z.string().max(500).optional(),\n contextPaths: z.array(CONTEXT_PATH_SHAPE).max(20).optional(),\n },\n async ({ tagId, name, color, description, contextPaths }) => {\n try {\n await connection.call(\"updateProjectTag\", {\n projectId,\n tagId,\n name,\n color,\n description,\n contextPaths,\n });\n return textResult(`Tag updated: ${tagId}`);\n } catch (error) {\n return errText(\"Failed to update tag\", error);\n }\n },\n );\n}\n\nfunction buildCreateSuggestionTool(connection: ProjectToolsConnection, projectId: string) {\n return defineTool(\n \"create_suggestion\",\n \"File a project suggestion (idea/improvement for maintainers to review). Duplicates are AI-deduped into an existing suggestion with an upvote. Returns the suggestion id.\",\n {\n title: z.string().min(1).describe(\"Short title\"),\n description: z.string().optional().describe(\"1-3 sentences: what should change and why\"),\n tag_names: z.array(z.string()).optional().describe(\"Tag names to categorize\"),\n },\n async ({ title, description, tag_names }) => {\n try {\n const result = await connection.call(\"createProjectSuggestion\", {\n projectId,\n title,\n description,\n tagNames: tag_names,\n });\n return textResult(\n result.merged\n ? `Merged into existing suggestion ${result.mergedIntoId ?? result.id} (id: ${result.id})`\n : `Suggestion created: ${result.id}`,\n );\n } catch (error) {\n return errText(\"Failed to create suggestion\", error);\n }\n },\n );\n}\n\nfunction buildPostToProjectChatTool(connection: ProjectToolsConnection, projectId: string) {\n return defineTool(\n \"post_to_project_chat\",\n \"Post a markdown message to the PROJECT chat — use once at the end of an audit for the summary the team reads.\",\n {\n message: z.string().min(1).max(20000),\n kind: z\n .enum([\"tag_audit_summary\"])\n .optional()\n .describe(\n \"Set to 'tag_audit_summary' when posting a tag-audit summary so it is also saved to the persistent tag history\",\n ),\n },\n async ({ message, kind }) => {\n try {\n await connection.call(\"postToProjectChat\", { projectId, content: message, kind });\n return textResult(\"Posted to project chat\");\n } catch (error) {\n return errText(\"Failed to post to project chat\", error);\n }\n },\n );\n}\n\n// ── Task audit surface ────────────────────────────────────────────────\n\nfunction buildGetProjectTaskTool(connection: ProjectToolsConnection, projectId: string) {\n return defineTool(\n \"get_project_task\",\n \"Fetch any task in the project by id or slug: title, description, plan, status, and metadata. The audit evidence trail starts here.\",\n {\n taskId: z.string().describe(\"Task id or slug\"),\n },\n async ({ taskId }) => {\n try {\n const task = await connection.call(\"getProjectTask\", { projectId, taskId });\n return textResult(JSON.stringify(task, null, 2));\n } catch (error) {\n return errText(\"Failed to get task\", error);\n }\n },\n { annotations: { readOnlyHint: true } },\n );\n}\n\nfunction buildReadProjectTaskChatTool(connection: ProjectToolsConnection, projectId: string) {\n return defineTool(\n \"read_project_task_chat\",\n \"Read any project task's chat messages (newest last). role 'user' rows are HUMAN turns; 'assistant'/'system' rows are agent posts and activity-log entries.\",\n {\n taskId: z.string().describe(\"Task id or slug\"),\n limit: z.number().int().min(1).max(200).optional().describe(\"Messages to fetch (default 50)\"),\n },\n async ({ taskId, limit }) => {\n try {\n const chat = await connection.call(\"getProjectTaskChat\", {\n projectId,\n taskId,\n limit: limit ?? 50,\n });\n return textResult(JSON.stringify(chat, null, 2));\n } catch (error) {\n return errText(\"Failed to read task chat\", error);\n }\n },\n { annotations: { readOnlyHint: true } },\n );\n}\n\nfunction buildGetProjectTaskLogsTool(connection: ProjectToolsConnection, projectId: string) {\n return defineTool(\n \"get_project_task_logs\",\n \"Read any project task's persisted agent event stream (message / tool_use / turn_end / error / completed). Turn boundaries are turn_end events. Entries are truncated to ~2KB each; max 500 per call.\",\n {\n taskId: z.string().describe(\"Task id or slug\"),\n limit: z.number().int().min(1).max(500).optional().describe(\"Entries to fetch (default 50)\"),\n source: z\n .enum([\"agent\", \"application\"])\n .optional()\n .describe(\"Filter: 'agent' = model events (default useful for grading)\"),\n },\n async ({ taskId, limit, source }) => {\n try {\n const logs = await connection.call(\"getProjectTaskCli\", {\n projectId,\n taskId,\n limit: limit ?? 50,\n source,\n });\n return textResult(JSON.stringify(logs, null, 2));\n } catch (error) {\n return errText(\"Failed to get task logs\", error);\n }\n },\n { annotations: { readOnlyHint: true } },\n );\n}\n\nconst TURN_GRADE_SHAPE = z.object({\n turnIndex: z.number().int().min(0),\n phase: z.enum([\"planning\", \"building\", \"human\"]),\n grade: z.enum([\"correct\", \"neutral\", \"blunder\"]),\n reasoning: z.string(),\n eventType: z.string().describe('e.g. \"message\", \"tool_use\", \"human_message\"'),\n eventSummary: z.string().max(200).describe(\"≤120 chars of what happened this turn\"),\n});\n\nconst HUMAN_EVAL_SHAPE = z.object({\n messageIndex: z.number().int().min(0).describe(\"Index into the task's human messages, oldest first\"),\n rating: z.number().int().min(-1).max(1),\n reasoning: z.string(),\n});\n\nfunction buildReportTaskAuditResultTool(connection: ProjectToolsConnection, projectId: string) {\n return defineTool(\n \"report_task_audit_result\",\n \"Persist one audited task's grades (call once per task after grading it). Pass error instead to mark the audit failed when the evidence is unusable.\",\n {\n taskId: z.string().describe(\"The audited task's id (NOT slug)\"),\n summary: z.string().describe(\"3-6 sentences: what went well, what was wasted\"),\n turnGrades: z.array(TURN_GRADE_SHAPE),\n planningAccuracy: z.number().min(0).max(1).nullable(),\n buildingAccuracy: z.number().min(0).max(1).nullable(),\n humanAccuracy: z.number().min(0).max(1).nullable(),\n planningCorrect: z.number().int().min(0),\n planningNeutral: z.number().int().min(0),\n planningBlunder: z.number().int().min(0),\n buildingCorrect: z.number().int().min(0),\n buildingNeutral: z.number().int().min(0),\n buildingBlunder: z.number().int().min(0),\n humanCorrect: z.number().int().min(0),\n humanNeutral: z.number().int().min(0),\n humanBlunder: z.number().int().min(0),\n humanEvaluations: z.array(HUMAN_EVAL_SHAPE).optional(),\n suggestionIds: z.array(z.string()).describe(\"Suggestion ids filed for this task, or []\"),\n auditCostUsd: z.number().nullable(),\n model: z.string().nullable().describe(\"The model you are running as\"),\n error: z.string().optional().describe(\"Set ONLY to mark this task's audit failed\"),\n },\n async (input) => {\n try {\n await connection.call(\"reportTaskAuditResult\", {\n projectId,\n ...input,\n humanEvaluations: (input.humanEvaluations ?? []) as Array<{\n messageIndex: number;\n rating: -1 | 0 | 1;\n reasoning: string;\n }>,\n });\n return textResult(\n input.error\n ? `Audit for ${input.taskId} marked failed`\n : `Audit result saved for ${input.taskId}`,\n );\n } catch (error) {\n return errText(\"Failed to report audit result\", error);\n }\n },\n );\n}\n\n// ── Assembly ──────────────────────────────────────────────────────────\n\n/** The full project-scoped tool surface a headless (task-less) session gets. */\nexport function buildProjectTools(connection: ProjectToolsConnection, projectId: string) {\n return [\n buildListTagsTool(connection, projectId),\n buildCreateTagTool(connection, projectId),\n buildUpdateTagTool(connection, projectId),\n buildCreateSuggestionTool(connection, projectId),\n buildPostToProjectChatTool(connection, projectId),\n buildGetProjectTaskTool(connection, projectId),\n buildReadProjectTaskChatTool(connection, projectId),\n buildGetProjectTaskLogsTool(connection, projectId),\n buildReportTaskAuditResultTool(connection, projectId),\n ];\n}\n","/* oxlint-disable import/max-dependencies -- cohesive ad-hoc runner lifecycle wiring */\n/**\n * AdhocSessionRunner — the task-less USER SCRATCH pod agent loop (Sessions view\n * \"Launch ad-hoc session\"). Claudespace v3, `Workspace.purpose = \"adhoc\"`.\n *\n * Unlike the ProjectSessionRunner (autonomous pm) it runs NO autonomous loop:\n * it spawns the `claude` CLI under a pseudo-terminal in interactive/prefill mode\n * (empty input box, no auto-submit) and relays raw terminal I/O to the S2 relay,\n * so the web Sessions terminal (S5) renders it and forwards keystrokes back. The\n * human drives it directly — there is no task, plan, or Conveyor MCP tool\n * surface. Connect / register / heartbeat / idle are shared with the project\n * runner; the difference is the interactive PTY spawn.\n *\n * Idle-sleep is server-owned (decideFate + activity/tunnel holds): an idle\n * adhoc pod sleeps after the idle window like any workspace; the human wakes it\n * from the Sessions list. The agent's own idle timer is the secondary backstop.\n */\nimport { AgentConnection, type AgentConnectionConfig } from \"../connection/agent-connection.js\";\nimport { Lifecycle, DEFAULT_LIFECYCLE_CONFIG, type LifecycleConfig } from \"./lifecycle.js\";\nimport { resolveSessionStart } from \"../execution/query-executor.js\";\nimport { resolvePlaywrightMcpServer } from \"../execution/playwright-mcp.js\";\nimport { sampleKeyUsage } from \"../execution/usage-sampler.js\";\nimport { probeKeysUsage } from \"../usage/multi-key-probe.js\";\nimport { PtyHarness } from \"../harness/pty/index.js\";\nimport { resolveTuiAdapter } from \"../harness/pty/adapters/index.js\";\nimport { TUI_KINDS, type TuiKind } from \"../harness/pty/adapters/types.js\";\nimport type {\n AgentHarness,\n HarnessMcpServer,\n HarnessQueryOptions,\n PtyBridge,\n} from \"../harness/types.js\";\nimport { PortDiscovery } from \"./port-discovery.js\";\nimport { loadConveyorConfig } from \"../setup/config.js\";\nimport { WorkspaceCommandSupervisor } from \"../setup/workspace-command-supervisor.js\";\nimport { buildProjectTools } from \"../tools/project-tools.js\";\nimport {\n DEFAULT_SONNET_MODEL,\n type AgentSessionServiceMethods,\n type PtyChatEventPayload,\n type WorkspaceDiscoveredPort,\n} from \"@project/shared\";\n\nconst ADHOC_SYSTEM_NOTE =\n \"You are running in an ad-hoc Conveyor scratch pod — an interactive terminal \" +\n \"on the project's repository checked out at its default branch. There is no \" +\n \"task or plan; help the human with whatever they ask directly.\";\n\nconst HEADLESS_SYSTEM_NOTE =\n \"You are running a HEADLESS Conveyor session on the project's repository — \" +\n \"your instructions were auto-submitted as the first message. Work them to \" +\n \"completion autonomously and never wait for user input; a human may attach \" +\n \"to this terminal to watch or interject, but none is required.\";\n\n/**\n * Headless sessions: the bootstrap bundle carries the server-assembled\n * instructions as base64 (only while un-submitted — see\n * build-bootstrap-bundle.ts). Absent/blank/undecodable → interactive ad-hoc.\n */\nexport function resolveInitialPrompt(env: NodeJS.ProcessEnv = process.env): string | null {\n const b64 = env.CONVEYOR_INITIAL_PROMPT_B64;\n if (!b64) return null;\n try {\n const decoded = Buffer.from(b64, \"base64\").toString(\"utf8\").trim();\n return decoded.length > 0 ? decoded : null;\n } catch {\n return null;\n }\n}\n\nexport interface AdhocSessionRunnerConfig {\n connection: AgentConnectionConfig;\n projectId: string;\n /**\n * Stable `Workspace` row id — the Claude session lineage key. Deliberately\n * NOT `connection.sessionId`: that's the `WorkspaceSession` row, which is\n * re-minted (fresh-session semantics) on every user-initiated wake, so\n * keying resume on it would never find the prior GCS-FUSE transcript.\n */\n workspaceId: string;\n /** Repo checkout the interactive CLI runs in. */\n workspaceDir: string;\n /** Model override; falls back to CONVEYOR_ADHOC_MODEL env, then the default. */\n model?: string;\n /**\n * Headless sessions: instructions to auto-submit as the first message\n * (flips prompt delivery to \"submit\" and mounts the project tool surface).\n * ONLY the top-level adhoc boot (cli.ts) resolves this from the bundle env —\n * spawned same-pod tabs must never inherit it, or a \"New Claude tab\" on a\n * headless pod would re-run the audit.\n */\n initialPrompt?: string | null;\n lifecycle?: Partial<LifecycleConfig>;\n}\n\nexport interface AdhocSessionRunnerCallbacks {\n onEvent?: (event: Record<string, unknown>) => void;\n}\n\n/** AgentConnection surface the adhoc runner needs (injectable for tests). */\nexport interface AdhocRunnerConnection {\n connect(): Promise<void>;\n disconnect(): void;\n call<M extends keyof AgentSessionServiceMethods>(\n method: M,\n payload: AgentSessionServiceMethods[M][\"payload\"],\n ): Promise<AgentSessionServiceMethods[M][\"response\"]>;\n sendEvent(event: { type: string; [key: string]: unknown }): void;\n sendHeartbeat(): void;\n emitStatus(status: string): Promise<void>;\n onStop(callback: () => void): void;\n refreshTaskTokenFromBootstrap(): Promise<boolean>;\n sendPtyOutput(data: string, dims?: { cols: number; rows: number }): void;\n sendPtyChatEvent(event: PtyChatEventPayload): void;\n onPtyInput(handler: (data: string) => void): () => void;\n onPtyResize(handler: (cols: number, rows: number) => void): () => void;\n reportDiscoveredPorts(ports: WorkspaceDiscoveredPort[]): Promise<void>;\n onRunStartCommand(callback: () => void): void;\n onProbeUsage(callback: () => void): void;\n}\n\nexport interface AdhocPortDiscovery {\n start(): Promise<void>;\n stop(): void;\n}\n\nexport interface AdhocWorkspaceCommandSupervisor {\n start(): void;\n stop(): Promise<void>;\n /** WorkspaceCommandSupervisor now holds its start-command launch behind a\n * loopReady signal (see workspace-command-supervisor.ts). Ad-hoc pods have\n * no separate core-loop boundary to gate on — the interactive TUI IS the\n * loop — so we release it immediately, right where start() used to launch\n * it unconditionally, preserving pre-existing behavior. Optional so\n * existing/simplified test doubles don't need updating. */\n notifyLoopReady?(): void;\n}\n\n/** Which TUI this adhoc pod runs — from the bootstrap bundle's CONVEYOR_TUI.\n * Unknown values throw (fail loudly): a typo'd config must not silently run\n * Claude. */\nexport function resolveAdhocTui(env: NodeJS.ProcessEnv): TuiKind {\n const raw = env.CONVEYOR_TUI ?? \"claude-code\";\n if ((TUI_KINDS as readonly string[]).includes(raw)) return raw as TuiKind;\n throw new Error(`Unknown TUI \"${raw}\" in CONVEYOR_TUI (expected: ${TUI_KINDS.join(\", \")})`);\n}\n\n/** Adapt an AdhocRunnerConnection into the harness-neutral PtyBridge. */\nexport function buildAdhocPtyBridge(connection: AdhocRunnerConnection): PtyBridge {\n return {\n sendOutput: (data, dims) => connection.sendPtyOutput(data, dims),\n sendChatEvent: (event) => connection.sendPtyChatEvent(event),\n onInput: (handler) => connection.onPtyInput(handler),\n onResize: (handler) => connection.onPtyResize(handler),\n };\n}\n\n/** The interactive-spawn options for an ad-hoc scratch TUI (no task context). */\nexport function buildAdhocQueryOptions(\n workspaceDir: string,\n model: string,\n abortController: AbortController,\n // Deterministic session start (fresh `sessionId` or `resume` target). Without\n // one, PtySession.start() throws \"requires options.sessionId or a resume\n // target\" and the pool crash-loops the runner — the interactive PTY never\n // spawns. Mutually exclusive: exactly one of the two is ever set.\n session?: { sessionId?: string; resume?: string },\n // Environment for PATH-based binary resolution (playwright-mcp). Injectable\n // so tests are deterministic regardless of what the host has baked on PATH\n // (claudespace pods ship /usr/local/bin/playwright-mcp; dev machines don't).\n env: NodeJS.ProcessEnv = process.env,\n // Headless mode: an initial prompt flips delivery to auto-submit and mounts\n // the project-scoped Conveyor tool surface (interactive adhoc gets neither).\n headless?: { initialPrompt: string; conveyorMcpServer?: HarnessMcpServer },\n): HarnessQueryOptions {\n const systemNote = headless ? HEADLESS_SYSTEM_NOTE : ADHOC_SYSTEM_NOTE;\n return {\n model,\n systemPrompt: { type: \"preset\", preset: \"claude_code\", append: systemNote },\n appendSystemPrompt: systemNote,\n cwd: workspaceDir,\n // Human-driven interactive shell — no plan-mode gating. (Headless audit\n // runs keep the same bypass: they must finish with no one at the terminal.)\n permissionMode: \"bypassPermissions\",\n allowDangerouslySkipPermissions: true,\n tools: { type: \"preset\", preset: \"claude_code\" },\n mcpServers: (() => {\n const playwright = resolvePlaywrightMcpServer(env);\n return {\n ...(playwright ? { playwright } : {}),\n ...(headless?.conveyorMcpServer ? { conveyor: headless.conveyorMcpServer } : {}),\n };\n })(),\n settingSources: [\"user\", \"project\"],\n // Interactive: empty box, unsubmitted — the human types the first prompt.\n // Headless: paste + submit the server-assembled instructions immediately.\n promptDelivery: headless ? \"submit\" : \"prefill\",\n abortController,\n ...(session?.sessionId ? { sessionId: session.sessionId } : {}),\n ...(session?.resume ? { resume: session.resume } : {}),\n };\n}\n\nexport class AdhocSessionRunner {\n readonly connection: AdhocRunnerConnection;\n readonly lifecycle: Lifecycle;\n private readonly harness: AgentHarness;\n private readonly portDiscovery: AdhocPortDiscovery;\n private readonly commandSupervisor: AdhocWorkspaceCommandSupervisor;\n\n private readonly config: AdhocSessionRunnerConfig;\n private readonly callbacks: AdhocSessionRunnerCallbacks;\n private readonly abortController = new AbortController();\n private stopped = false;\n private stopResolver: (() => void) | null = null;\n private _finalState: \"finished\" | \"error\" | null = null;\n\n constructor(\n config: AdhocSessionRunnerConfig,\n callbacks: AdhocSessionRunnerCallbacks = {},\n deps?: {\n connection?: AdhocRunnerConnection;\n harness?: AgentHarness;\n portDiscovery?: AdhocPortDiscovery;\n commandSupervisor?: AdhocWorkspaceCommandSupervisor;\n },\n ) {\n this.config = config;\n this.callbacks = callbacks;\n this.connection = deps?.connection ?? new AgentConnection(config.connection);\n this.harness =\n deps?.harness ??\n new PtyHarness(\n buildAdhocPtyBridge(this.connection),\n resolveTuiAdapter(resolveAdhocTui(process.env)),\n );\n this.portDiscovery =\n deps?.portDiscovery ??\n new PortDiscovery({\n report: (ports) => this.connection.reportDiscoveredPorts(ports),\n });\n this.commandSupervisor =\n deps?.commandSupervisor ??\n new WorkspaceCommandSupervisor({\n config: loadConveyorConfig(),\n workspaceDir: config.workspaceDir,\n connection: this.connection,\n });\n this.lifecycle = new Lifecycle(\n // No git flush: the WIP snapshot machinery is branch/task-shaped; the human\n // commits/pushes explicitly from the interactive shell.\n { ...DEFAULT_LIFECYCLE_CONFIG, gitFlushIntervalMs: 0, ...config.lifecycle },\n {\n onHeartbeat: () => this.connection.sendHeartbeat(),\n onIdleTimeout: () => this.requestStop(),\n onDormantTimeout: () => this.requestStop(),\n onTokenRefresh: () => void this.connection.refreshTaskTokenFromBootstrap().catch(() => {}),\n onGitFlush: () => {},\n onUsageSample: () => void this.sampleAndReportAllKeys(),\n },\n );\n }\n\n get finalState(): \"finished\" | \"error\" | null {\n return this._finalState;\n }\n\n get isStopped(): boolean {\n return this.stopped;\n }\n\n /** Connect, register, spawn the interactive TUI, and relay it until stopped. */\n async run(): Promise<void> {\n try {\n await this.connection.connect();\n this.connection.sendEvent({\n type: \"connected\",\n sessionId: this.config.connection.sessionId,\n projectId: this.config.projectId,\n });\n this.connection.onStop(() => this.requestStop());\n // On-demand \"Refresh usage\" push (server → pod): re-sample every key now.\n this.connection.onProbeUsage(() => void this.sampleAndReportAllKeys());\n this.lifecycle.startHeartbeat();\n this.lifecycle.startTokenRefresh();\n this.lifecycle.startUsageSample();\n\n await this.connection.call(\"connectAgent\", {\n sessionId: this.config.connection.sessionId,\n });\n await this.portDiscovery.start().catch(() => {});\n if (this.stopped) {\n this._finalState = \"finished\";\n return;\n }\n this.commandSupervisor.start();\n // No boot-race to gate here (unlike the task/pack SessionRunner) — the\n // interactive TUI is about to become the loop, so release the start\n // command immediately rather than leaving it parked on loopReady forever.\n this.commandSupervisor.notifyLoopReady?.();\n await this.connection.emitStatus(\"running\");\n this.callbacks.onEvent?.({ type: \"adhoc_runner_started\", projectId: this.config.projectId });\n this.lifecycle.startIdleTimer();\n\n await this.runInteractiveTui();\n this._finalState = \"finished\";\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[conveyor-agent] Ad-hoc runner failed: ${message}\\n`);\n this.connection.sendEvent({ type: \"error\", message });\n this._finalState = \"error\";\n } finally {\n await this.shutdown();\n }\n }\n\n /**\n * Drive the `claude` CLI under a PTY. The bridge relays raw stdout to S2/S5\n * and forwards keystrokes back, so consuming the event stream is enough — the\n * loop blocks (keeping the pod alive) until the human exits or stop() aborts.\n */\n private async runInteractiveTui(): Promise<void> {\n const model =\n this.config.model ??\n process.env.CONVEYOR_AGENT_MODEL ??\n process.env.CONVEYOR_ADHOC_MODEL ??\n DEFAULT_SONNET_MODEL;\n // Key the CLI session on the stable workspace id (NOT connection.sessionId\n // — see the field doc on AdhocSessionRunnerConfig.workspaceId): a fresh\n // pod spawns a new session, a woken pod resumes the GCS-FUSE-persisted\n // transcript.\n const session = resolveSessionStart(this.config.workspaceId, this.config.workspaceDir);\n // Headless: the bundle delivered un-submitted audit instructions — mount\n // the project tool surface and auto-submit them as the first message.\n const initialPrompt = this.config.initialPrompt ?? null;\n const headless = initialPrompt\n ? {\n initialPrompt,\n conveyorMcpServer: this.harness.createMcpServer({\n name: \"conveyor\",\n tools: buildProjectTools(this.connection, this.config.projectId),\n }),\n }\n : undefined;\n const options = buildAdhocQueryOptions(\n this.config.workspaceDir,\n model,\n this.abortController,\n session,\n process.env,\n headless,\n );\n let promptMarked = false;\n try {\n for await (const event of this.harness.executeQuery({\n prompt: initialPrompt ?? \"\",\n options,\n })) {\n if (this.stopped) break;\n if (initialPrompt && !promptMarked) {\n // First harness event = the CLI spawned and the submit landed. Mark\n // the prompt consumed so a sleep→wake (or pod replacement) boots\n // plain-interactive instead of re-running the audit. Best-effort:\n // the server-side gate is idempotent and a missed mark only risks a\n // re-run, never a crash.\n promptMarked = true;\n void this.connection\n .call(\"markInitialPromptSubmitted\", { sessionId: this.config.connection.sessionId })\n .catch(() => {});\n }\n if (event.type === \"result\" && event.subtype === \"error\") {\n // Raw-mode adapters surface spawn/exit failures as a result error —\n // fail the run loudly so the Sessions UI shows the reason.\n throw new Error(event.errors.join(\"\\n\"));\n }\n }\n } catch (error) {\n // An aborted interactive session is the normal stop path, not a failure.\n if (!this.stopped) throw error;\n }\n }\n\n stop(): void {\n this.requestStop();\n }\n\n private requestStop(): void {\n if (this.stopped) return;\n this.stopped = true;\n this.portDiscovery.stop();\n void this.commandSupervisor.stop();\n this.abortController.abort();\n if (this.stopResolver) {\n const resolve = this.stopResolver;\n this.stopResolver = null;\n resolve();\n }\n }\n\n /**\n * Multi-key usage refresh: ask the server for every subscription key the\n * OWNER has, probe each one's `/usage` from THIS pod (isolated per key), and\n * report each key's gauges tagged with its explicit `codingAgentKeyId`. Falls\n * back to the single-key self-sample when the owner has no probeable keys\n * (e.g. API-key-only, or all decrypts failed). Best-effort — never throws.\n */\n private async sampleAndReportAllKeys(): Promise<void> {\n if (this.stopped) return;\n let keys: { codingAgentKeyId: string; oauthToken: string }[] = [];\n try {\n const res = await this.connection.call(\"listKeysToProbe\", {\n sessionId: this.config.connection.sessionId,\n });\n keys = res?.keys ?? [];\n } catch {\n // Server unreachable / method unavailable — fall back to the self-sample.\n }\n if (keys.length === 0) {\n await this.sampleAndReportOwnKey();\n return;\n }\n const probed = await probeKeysUsage(keys);\n for (const { codingAgentKeyId, samples } of probed) {\n for (const sample of samples) {\n this.connection.sendEvent({\n type: \"rate_limit_update\",\n rateLimitType: sample.rateLimitType,\n utilization: sample.utilization,\n status: sample.status,\n resetsAt: sample.resetsAt ?? undefined,\n gauges: sample.gauges,\n codingAgentKeyId,\n });\n }\n }\n }\n\n /** Single-key fallback: sample only the key this pod booted under. */\n private async sampleAndReportOwnKey(): Promise<void> {\n if (this.stopped) return;\n const samples = await sampleKeyUsage(process.env.CLAUDE_CODE_OAUTH_TOKEN);\n for (const sample of samples) {\n this.connection.sendEvent({\n type: \"rate_limit_update\",\n rateLimitType: sample.rateLimitType,\n utilization: sample.utilization,\n status: sample.status,\n resetsAt: sample.resetsAt ?? undefined,\n gauges: sample.gauges,\n });\n }\n }\n\n private async shutdown(): Promise<void> {\n this.stopped = true;\n this.portDiscovery.stop();\n await this.commandSupervisor.stop();\n this.lifecycle.destroy();\n this.connection.sendEvent({ type: \"shutdown\", reason: this._finalState ?? \"finished\" });\n this.connection.disconnect();\n }\n}\n","/**\n * Same-pod review child supervisor. When the API parks a review session on\n * this (builder) pod and pushes `session:spawnReview`, the supervisor spawns a\n * SECOND conveyor-agent process — same CLI binary, same repo checkout — bound\n * to the review session via env overrides. The child owns its own\n * AgentConnection/PTY stream, so the card's \"Reviewer\" terminal tab appears\n * through the normal multi-session relay with no relay changes.\n *\n * Single-slot: a new spawn (re-review of a fresh push) kills and replaces the\n * previous child. Spawn failures are reported back to the API\n * (`reportReviewSpawnFailure`), which Ends the orphaned session and falls back\n * to a dedicated review pod.\n *\n * Shared-checkout caveat (v1, deliberate): the reviewer reads the builder's\n * working tree. At review time the builder is parked (ReviewPR + CI green),\n * so contention is low; a best-effort ff-only fetch freshens the branch. A\n * human typing in the builder TUI mid-review can still dirty the tree —\n * worktree isolation is a deferred follow-up.\n */\nimport { spawn as nodeSpawn, execFile, type ChildProcess } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport type { SpawnReviewData } from \"../connection/agent-connection.js\";\nimport { createServiceLogger } from \"../utils/logger.js\";\n\nconst execFileAsync = promisify(execFile);\nconst logger = createServiceLogger(\"ReviewChild\");\n\n/** Exit inside this window (non-zero) is treated as a spawn failure. */\nexport const SPAWN_FAILURE_GRACE_MS = 15_000;\n/** How long to wait for a SIGTERM'd child before SIGKILL. */\nexport const KILL_WAIT_MS = 5_000;\n\nexport interface ReviewChildConnection {\n reportReviewSpawnFailure(reviewSessionId: string, error?: string): void;\n}\n\nexport type SpawnFn = (\n command: string,\n args: string[],\n options: {\n cwd: string;\n env: NodeJS.ProcessEnv;\n stdio: [\"ignore\", \"pipe\", \"pipe\"];\n },\n) => ChildProcess;\n\n/**\n * Build the child env from the builder's env. The child is the same CLI in\n * `code-review` mode, so it reuses the pod's credentials (git, Anthropic)\n * while swapping in the review session's identity.\n */\nexport function buildReviewChildEnv(\n baseEnv: NodeJS.ProcessEnv,\n data: SpawnReviewData,\n): NodeJS.ProcessEnv {\n const env: NodeJS.ProcessEnv = { ...baseEnv };\n // The review session's identity: its own JWT + sessionId, review runner\n // mode. CONVEYOR_TASK_ID stays the parent's — same task (SEC-9 derives the\n // task from the JWT server-side).\n env.CONVEYOR_TASK_TOKEN = data.sessionJwt;\n env.CONVEYOR_SESSION_ID = data.sessionId;\n env.CONVEYOR_MODE = \"code-review\";\n\n // The bootstrap-refresh path would replace the child's review JWT with the\n // BUILDER's writer JWT (findBundleSession prefers the live writer), silently\n // re-identifying the child as the builder. Reviews finish well inside the\n // 24h JWT TTL, so the child never needs a refresh — remove the tokens.\n delete env.POD_BOOTSTRAP_TOKEN;\n delete env.CONVEYOR_BOOTSTRAP_TOKEN;\n\n // The builder already ran (or is running) setup/start on this shared\n // workspace — the child must never re-run `bun install` or spawn a second\n // dev server.\n delete env.CONVEYOR_SETUP_COMMAND;\n delete env.CONVEYOR_START_COMMAND;\n\n // The code-review runner forces its own mode (review + auto); a stale\n // builder agent-mode hint must not leak in.\n delete env.CONVEYOR_AGENT_MODE;\n delete env.CONVEYOR_IS_AUTO;\n return env;\n}\n\nexport class ReviewChildSupervisor {\n private child: ChildProcess | null = null;\n private childSessionId: string | null = null;\n\n constructor(\n private readonly connection: ReviewChildConnection,\n private readonly workspaceDir: string,\n private readonly spawnFn: SpawnFn = nodeSpawn as SpawnFn,\n ) {}\n\n /** Spawn (or replace) the review child for a `session:spawnReview` push. */\n async spawn(data: SpawnReviewData): Promise<void> {\n logger.info(\"Spawning same-pod review child\", {\n reviewSessionId: data.sessionId,\n branch: data.branch ?? undefined,\n prNumber: data.prNumber ?? undefined,\n });\n await this.stopCurrent(\"superseded by new review spawn\");\n await this.refreshCheckout(data.branch ?? null);\n\n const env = buildReviewChildEnv(process.env, data);\n const cliPath = process.argv[1];\n if (!cliPath) {\n this.connection.reportReviewSpawnFailure(data.sessionId, \"cannot resolve CLI entry path\");\n return;\n }\n\n let child: ChildProcess;\n try {\n child = this.spawnFn(process.execPath, [cliPath], {\n cwd: this.workspaceDir,\n env,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n } catch (err) {\n this.connection.reportReviewSpawnFailure(\n data.sessionId,\n err instanceof Error ? err.message : String(err),\n );\n return;\n }\n\n this.child = child;\n this.childSessionId = data.sessionId;\n const spawnedAt = Date.now();\n let reported = false;\n const reportOnce = (message: string): void => {\n if (reported) return;\n reported = true;\n this.connection.reportReviewSpawnFailure(data.sessionId, message);\n };\n\n // Child output lands in the pod log (the entrypoint tees our stdio),\n // prefixed so builder and reviewer streams stay distinguishable.\n child.stdout?.on(\"data\", (chunk: Buffer) => {\n process.stdout.write(`[review-child] ${chunk.toString()}`);\n });\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n process.stderr.write(`[review-child] ${chunk.toString()}`);\n });\n\n child.on(\"error\", (err) => {\n logger.error(\"Review child spawn error\", { error: err.message });\n if (this.child === child) {\n this.child = null;\n this.childSessionId = null;\n }\n reportOnce(err.message);\n });\n\n child.on(\"exit\", (code, signal) => {\n const wasCurrent = this.child === child;\n if (wasCurrent) {\n this.child = null;\n this.childSessionId = null;\n }\n logger.info(\"Review child exited\", { code, signal, reviewSessionId: data.sessionId });\n // A non-zero exit right after launch means the child never became the\n // review agent — recover via the dedicated-pod fallback. Later exits\n // (review finished, server-sent session:stop, supersede kill) are\n // normal lifecycle: the server owns the session state there.\n const withinGrace = Date.now() - spawnedAt < SPAWN_FAILURE_GRACE_MS;\n if (wasCurrent && withinGrace && code !== null && code !== 0) {\n reportOnce(`review child exited with code ${code} within startup grace`);\n }\n });\n }\n\n /** Stop any live child (parent shutdown / supersede). Best-effort. */\n async stopAll(): Promise<void> {\n await this.stopCurrent(\"parent shutting down\");\n }\n\n private async stopCurrent(reason: string): Promise<void> {\n const child = this.child;\n if (!child || child.exitCode !== null || child.killed) {\n this.child = null;\n this.childSessionId = null;\n return;\n }\n logger.info(\"Stopping review child\", { reason, reviewSessionId: this.childSessionId });\n // Detach bookkeeping first so the exit handler treats this as expected.\n this.child = null;\n this.childSessionId = null;\n\n await new Promise<void>((resolve) => {\n const timer = setTimeout(() => {\n try {\n child.kill(\"SIGKILL\");\n } catch {\n /* already gone */\n }\n resolve();\n }, KILL_WAIT_MS);\n timer.unref();\n child.once(\"exit\", () => {\n clearTimeout(timer);\n resolve();\n });\n try {\n child.kill(\"SIGTERM\");\n } catch {\n clearTimeout(timer);\n resolve();\n }\n });\n }\n\n /**\n * Best-effort branch freshen before the review reads the tree: fetch the PR\n * branch and fast-forward only (never clobber local work — the builder's\n * checkout is the source of truth on conflict). Failures are logged and\n * skipped; the reviewer still reads the diff via the GitHub API.\n */\n private async refreshCheckout(branch: string | null): Promise<void> {\n if (!branch) return;\n try {\n await execFileAsync(\"git\", [\"fetch\", \"origin\", branch], {\n cwd: this.workspaceDir,\n timeout: 60_000,\n });\n await execFileAsync(\"git\", [\"merge\", \"--ff-only\", `origin/${branch}`], {\n cwd: this.workspaceDir,\n timeout: 30_000,\n });\n } catch (err) {\n logger.warn(\"Review checkout freshen skipped\", {\n branch,\n error: err instanceof Error ? err.message : String(err),\n });\n }\n }\n}\n","/**\n * Same-pod TUI/shell child supervisor. When the API parks an extra interactive\n * session on this (builder) pod and pushes `session:spawnTui`, the supervisor\n * spawns another conveyor-agent process — same CLI binary, same repo checkout —\n * bound to it via env overrides (CONVEYOR_MODE \"adhoc\" = a second Claude TUI,\n * \"shell\" = a raw login shell). Each child owns its own AgentConnection/PTY\n * stream, so a new terminal tab appears through the normal multi-session relay\n * with no relay changes.\n *\n * Multi-slot (unlike ReviewChildSupervisor): tabs are additive — several TUI/\n * shell children can coexist, keyed by their sessionId. The server caps how\n * many it will park per workspace. Spawn failures are reported back\n * (`reportSessionSpawnFailure`), which Ends the orphaned session; there is no\n * fallback pod (a spawned tab only makes sense on this pod).\n *\n * Shared-checkout caveat (deliberate, same as the review child): children\n * operate on the builder's working tree. They never run setup/start commands\n * and never touch git themselves on spawn.\n */\nimport { spawn as nodeSpawn, type ChildProcess } from \"node:child_process\";\nimport type { SpawnTuiData } from \"../connection/agent-connection.js\";\nimport { createServiceLogger } from \"../utils/logger.js\";\nimport { KILL_WAIT_MS, SPAWN_FAILURE_GRACE_MS, type SpawnFn } from \"./review-child.js\";\n\nconst logger = createServiceLogger(\"SessionChild\");\n\nexport interface SessionChildConnection {\n reportSessionSpawnFailure(spawnedSessionId: string, error?: string): void;\n}\n\n/**\n * Build the child env from the builder's env. The child is the same CLI in\n * adhoc/shell mode, so it reuses the pod's credentials while swapping in the\n * spawned session's identity.\n */\nexport function buildSpawnedChildEnv(\n baseEnv: NodeJS.ProcessEnv,\n data: SpawnTuiData,\n): NodeJS.ProcessEnv {\n const env: NodeJS.ProcessEnv = { ...baseEnv };\n // The spawned session's identity: its own JWT + sessionId + runner mode.\n // CONVEYOR_TASK_ID stays the parent's — same task (SEC-9 derives the task\n // from the JWT server-side). CONVEYOR_PROJECT_ID feeds the adhoc runner's\n // connected-event payload.\n env.CONVEYOR_TASK_TOKEN = data.sessionJwt;\n env.CONVEYOR_SESSION_ID = data.sessionId;\n env.CONVEYOR_MODE = data.mode;\n env.CONVEYOR_PROJECT_ID = data.projectId;\n\n // The bootstrap-refresh path would replace the child's JWT with the\n // BUILDER's writer JWT (findBundleSession prefers the live writer), silently\n // re-identifying the child as the builder — remove the tokens (same as the\n // review child; the 24h JWT TTL outlives any tab).\n delete env.POD_BOOTSTRAP_TOKEN;\n delete env.CONVEYOR_BOOTSTRAP_TOKEN;\n\n // The builder already ran (or is running) setup/start on this shared\n // workspace — the child must never re-run `bun install` or spawn a second\n // dev server.\n delete env.CONVEYOR_SETUP_COMMAND;\n delete env.CONVEYOR_START_COMMAND;\n\n // Adhoc/shell runners have no agent-mode axis; a stale builder hint must\n // not leak in.\n delete env.CONVEYOR_AGENT_MODE;\n delete env.CONVEYOR_IS_AUTO;\n return env;\n}\n\nexport class SessionChildSupervisor {\n private readonly children = new Map<string, ChildProcess>();\n\n constructor(\n private readonly connection: SessionChildConnection,\n private readonly workspaceDir: string,\n private readonly spawnFn: SpawnFn = nodeSpawn as SpawnFn,\n ) {}\n\n /** Live child count (for tests/diagnostics). */\n get size(): number {\n return this.children.size;\n }\n\n /** Spawn a TUI/shell child for a `session:spawnTui` push. Additive per session. */\n async spawn(data: SpawnTuiData): Promise<void> {\n logger.info(\"Spawning same-pod session child\", {\n spawnedSessionId: data.sessionId,\n mode: data.mode,\n });\n // A duplicate push for the same session replaces its own slot only.\n await this.stopChild(data.sessionId, \"superseded by duplicate spawn\");\n\n const env = buildSpawnedChildEnv(process.env, data);\n const cliPath = process.argv[1];\n if (!cliPath) {\n this.connection.reportSessionSpawnFailure(data.sessionId, \"cannot resolve CLI entry path\");\n return;\n }\n\n let child: ChildProcess;\n try {\n child = this.spawnFn(process.execPath, [cliPath], {\n cwd: this.workspaceDir,\n env,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n });\n } catch (err) {\n this.connection.reportSessionSpawnFailure(\n data.sessionId,\n err instanceof Error ? err.message : String(err),\n );\n return;\n }\n\n this.children.set(data.sessionId, child);\n const spawnedAt = Date.now();\n let reported = false;\n const reportOnce = (message: string): void => {\n if (reported) return;\n reported = true;\n this.connection.reportSessionSpawnFailure(data.sessionId, message);\n };\n\n // Child output lands in the pod log (the entrypoint tees our stdio),\n // prefixed so builder and tab streams stay distinguishable.\n const prefix = `[${data.mode}-child]`;\n child.stdout?.on(\"data\", (chunk: Buffer) => {\n process.stdout.write(`${prefix} ${chunk.toString()}`);\n });\n child.stderr?.on(\"data\", (chunk: Buffer) => {\n process.stderr.write(`${prefix} ${chunk.toString()}`);\n });\n\n child.on(\"error\", (err) => {\n logger.error(\"Session child spawn error\", { error: err.message });\n if (this.children.get(data.sessionId) === child) {\n this.children.delete(data.sessionId);\n }\n reportOnce(err.message);\n });\n\n child.on(\"exit\", (code, signal) => {\n const wasCurrent = this.children.get(data.sessionId) === child;\n if (wasCurrent) this.children.delete(data.sessionId);\n logger.info(\"Session child exited\", {\n code,\n signal,\n spawnedSessionId: data.sessionId,\n mode: data.mode,\n });\n // A non-zero exit right after launch means the child never became the\n // tab's agent — End the orphaned session server-side. Later exits (user\n // typed `exit`, server-sent session:stop, supersede kill) are normal\n // lifecycle: the server owns the session state there.\n const withinGrace = Date.now() - spawnedAt < SPAWN_FAILURE_GRACE_MS;\n if (wasCurrent && withinGrace && code !== null && code !== 0) {\n reportOnce(`session child exited with code ${code} within startup grace`);\n }\n });\n }\n\n /** Stop every live child (parent shutdown). Best-effort. */\n async stopAll(): Promise<void> {\n const ids = [...this.children.keys()];\n await Promise.all(ids.map((id) => this.stopChild(id, \"parent shutting down\")));\n }\n\n private async stopChild(sessionId: string, reason: string): Promise<void> {\n const child = this.children.get(sessionId);\n this.children.delete(sessionId);\n if (!child || child.exitCode !== null || child.killed) return;\n logger.info(\"Stopping session child\", { reason, spawnedSessionId: sessionId });\n\n await new Promise<void>((resolve) => {\n const timer = setTimeout(() => {\n try {\n child.kill(\"SIGKILL\");\n } catch {\n /* already gone */\n }\n resolve();\n }, KILL_WAIT_MS);\n timer.unref();\n child.once(\"exit\", () => {\n clearTimeout(timer);\n resolve();\n });\n try {\n child.kill(\"SIGTERM\");\n } catch {\n clearTimeout(timer);\n resolve();\n }\n });\n }\n}\n","/**\n * ShellSessionRunner — a raw login shell relayed as a terminal tab. Spawned as\n * a same-pod child (`session:spawnTui` with mode \"shell\") so a human can poke\n * around the workspace manually from the card's App/terminal tabs.\n *\n * The sibling of AdhocSessionRunner minus the Claude harness: connect →\n * register → spawn `$SHELL -l` under node-pty in the workspace checkout →\n * relay raw bytes over the S2 relay (ptyOutput/ptyInput/ptyResize). The tab\n * ends when the human exits the shell, the roster kill sends session:stop, or\n * the pod goes down. Idle-sleep stays server-owned; the runner's own idle\n * timer is the backstop, re-armed on every keystroke so an actively-used\n * shell never trips it.\n */\nimport { AgentConnection, type AgentConnectionConfig } from \"../connection/agent-connection.js\";\nimport { Lifecycle, DEFAULT_LIFECYCLE_CONFIG, type LifecycleConfig } from \"./lifecycle.js\";\nimport {\n loadPtySpawn,\n inheritedEnv,\n type PtyProcess,\n type PtySpawn,\n} from \"../harness/pty/pty-support.js\";\n\nconst DEFAULT_COLS = 80;\nconst DEFAULT_ROWS = 24;\n\nexport interface ShellSessionRunnerConfig {\n connection: AgentConnectionConfig;\n /** Repo checkout the shell starts in. */\n workspaceDir: string;\n /** Shell binary override; falls back to $SHELL, then bash. */\n shell?: string;\n lifecycle?: Partial<LifecycleConfig>;\n}\n\n/** AgentConnection surface the shell runner needs (injectable for tests). */\nexport interface ShellRunnerConnection {\n connect(): Promise<void>;\n disconnect(): void;\n call(method: \"connectAgent\", payload: { sessionId: string }): Promise<unknown>;\n sendEvent(event: { type: string; [key: string]: unknown }): void;\n sendHeartbeat(): void;\n emitStatus(status: string): Promise<void>;\n onStop(callback: () => void): void;\n refreshTaskTokenFromBootstrap(): Promise<boolean>;\n sendPtyOutput(data: string, dims?: { cols: number; rows: number }): void;\n sendPtyEnded(): void;\n onPtyInput(handler: (data: string) => void): () => void;\n onPtyResize(handler: (cols: number, rows: number) => void): () => void;\n}\n\n/**\n * The shell's env: the pod env minus this session's Conveyor identity. The\n * human at the prompt doesn't need the session JWT sitting in `env` output —\n * and a copied token must not leak task authority into pasted shell logs.\n */\nexport function buildShellEnv(baseEnv: Record<string, string>): Record<string, string> {\n const env = { ...baseEnv };\n delete env.CONVEYOR_TASK_TOKEN;\n delete env.CONVEYOR_SESSION_ID;\n return env;\n}\n\nexport class ShellSessionRunner {\n readonly connection: ShellRunnerConnection;\n readonly lifecycle: Lifecycle;\n\n private readonly config: ShellSessionRunnerConfig;\n private readonly loadSpawn: () => Promise<PtySpawn>;\n private pty: PtyProcess | null = null;\n private dims = { cols: DEFAULT_COLS, rows: DEFAULT_ROWS };\n private stopped = false;\n private _finalState: \"finished\" | \"error\" | null = null;\n\n constructor(\n config: ShellSessionRunnerConfig,\n deps?: { connection?: ShellRunnerConnection; loadSpawn?: () => Promise<PtySpawn> },\n ) {\n this.config = config;\n this.connection = deps?.connection ?? new AgentConnection(config.connection);\n this.loadSpawn = deps?.loadSpawn ?? loadPtySpawn;\n this.lifecycle = new Lifecycle(\n // No git flush — the human commits/pushes explicitly from the shell.\n { ...DEFAULT_LIFECYCLE_CONFIG, gitFlushIntervalMs: 0, ...config.lifecycle },\n {\n onHeartbeat: () => this.connection.sendHeartbeat(),\n onIdleTimeout: () => this.requestStop(),\n onDormantTimeout: () => this.requestStop(),\n onTokenRefresh: () => void this.connection.refreshTaskTokenFromBootstrap().catch(() => {}),\n onGitFlush: () => {},\n onUsageSample: () => {},\n },\n );\n }\n\n get finalState(): \"finished\" | \"error\" | null {\n return this._finalState;\n }\n\n get isStopped(): boolean {\n return this.stopped;\n }\n\n /** Connect, register, spawn the shell, and relay it until exit or stop. */\n async run(): Promise<void> {\n try {\n await this.connection.connect();\n this.connection.sendEvent({\n type: \"connected\",\n sessionId: this.config.connection.sessionId,\n });\n this.connection.onStop(() => this.requestStop());\n this.lifecycle.startHeartbeat();\n this.lifecycle.startTokenRefresh();\n\n await this.connection.call(\"connectAgent\", {\n sessionId: this.config.connection.sessionId,\n });\n await this.connection.emitStatus(\"running\");\n this.lifecycle.startIdleTimer();\n\n await this.runShell();\n this._finalState = \"finished\";\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n process.stderr.write(`[conveyor-agent] Shell runner failed: ${message}\\n`);\n this.connection.sendEvent({ type: \"error\", message });\n this._finalState = \"error\";\n } finally {\n this.shutdown();\n }\n }\n\n /** Spawn the login shell under a PTY and block until it exits or stop(). */\n private async runShell(): Promise<void> {\n const spawn = await this.loadSpawn();\n const shell = this.config.shell ?? process.env.SHELL ?? \"bash\";\n const pty = spawn(shell, [\"-l\"], {\n name: \"xterm-256color\",\n cols: this.dims.cols,\n rows: this.dims.rows,\n cwd: this.config.workspaceDir,\n env: buildShellEnv(inheritedEnv()),\n });\n this.pty = pty;\n\n const unsubInput = this.connection.onPtyInput((data) => {\n // A keystroke is real human activity — re-arm the idle backstop.\n this.lifecycle.startIdleTimer();\n pty.write(data);\n });\n const unsubResize = this.connection.onPtyResize((cols, rows) => {\n this.dims = { cols, rows };\n pty.resize(cols, rows);\n });\n pty.onData((data) => this.connection.sendPtyOutput(data, this.dims));\n\n try {\n await new Promise<void>((resolve) => {\n pty.onExit(() => resolve());\n });\n } finally {\n unsubInput();\n unsubResize();\n this.pty = null;\n // The shell is gone and no respawn is coming — hide the tab now instead\n // of waiting for the lease to lapse.\n this.connection.sendPtyEnded();\n }\n }\n\n stop(): void {\n this.requestStop();\n }\n\n private requestStop(): void {\n if (this.stopped) return;\n this.stopped = true;\n try {\n this.pty?.kill();\n } catch {\n /* already gone */\n }\n }\n\n private shutdown(): void {\n this.stopped = true;\n this.lifecycle.destroy();\n this.connection.sendEvent({ type: \"shutdown\", reason: this._finalState ?? \"finished\" });\n this.connection.disconnect();\n }\n}\n","/**\n * Boot factory for same-pod spawned children (session:spawnTui). Keeps the\n * CLI entry lean: given the env-derived identity, constructs the right runner\n * — an interactive Claude TUI (mode \"adhoc\" WITH a task id, unlike the\n * task-less Sessions-view adhoc pods) or a raw login shell (mode \"shell\").\n */\nimport { createServiceLogger } from \"../utils/logger.js\";\nimport { AdhocSessionRunner } from \"./adhoc-session-runner.js\";\nimport { ShellSessionRunner } from \"./shell-session-runner.js\";\n\nconst logger = createServiceLogger(\"SpawnedChildBoot\");\n\nexport interface SpawnedChildInputs {\n mode: \"adhoc\" | \"shell\";\n apiUrl: string;\n taskToken: string;\n /** The spawned WorkspaceSession id (CONVEYOR_SESSION_ID on the child). */\n sessionId: string;\n workspaceDir: string;\n /** For the adhoc runner's connected-event payload (CONVEYOR_PROJECT_ID). */\n projectId: string;\n}\n\nexport interface SpawnedChildRunner {\n run(): Promise<void>;\n stop(): void;\n readonly finalState: \"finished\" | \"error\" | null;\n}\n\nexport function createSpawnedChildRunner(inputs: SpawnedChildInputs): SpawnedChildRunner {\n if (inputs.mode === \"shell\") {\n return new ShellSessionRunner({\n connection: {\n apiUrl: inputs.apiUrl,\n taskToken: inputs.taskToken,\n sessionId: inputs.sessionId,\n runnerMode: \"shell\",\n },\n workspaceDir: inputs.workspaceDir,\n });\n }\n return new AdhocSessionRunner(\n {\n connection: {\n apiUrl: inputs.apiUrl,\n taskToken: inputs.taskToken,\n sessionId: inputs.sessionId,\n runnerMode: \"adhoc\",\n },\n projectId: inputs.projectId,\n // Session lineage key. NOT the inherited CONVEYOR_WORKSPACE_ID — that's\n // the builder's lineage; concurrent tabs must each be their own Claude\n // conversation, so key on the spawned session id.\n workspaceId: inputs.sessionId,\n workspaceDir: inputs.workspaceDir,\n },\n {\n onEvent: (event) => {\n logger.info(\"Spawned TUI event\", { eventType: event.type as string });\n },\n },\n );\n}\n"],"mappings":"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","names":["join","dirname","logger","writeFile","writeFile","dirname","join","logger","join","dirname","logger","nodeSpawn","logger","nodeSpawn","logger","dirname","join","logger"]}
|