@jentrix/runner 0.5.13 → 0.5.15
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/README.md +2 -2
- package/dist/chunk-PTARP62V.js +7 -0
- package/dist/{chunk-QBB7WO4L.js.map → chunk-PTARP62V.js.map} +1 -1
- package/dist/runner-cli.js +2 -2
- package/dist/runner-cli.js.map +2 -2
- package/dist/{session-host-X4B43PJJ.js → session-host-DMDLRICG.js} +10 -4
- package/dist/session-host-DMDLRICG.js.map +7 -0
- package/dist/workflow-runner.js +14 -7
- package/dist/workflow-runner.js.map +2 -2
- package/package.json +1 -1
- package/dist/chunk-QBB7WO4L.js +0 -7
- package/dist/session-host-X4B43PJJ.js.map +0 -7
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../workflow-runner.ts", "../lib/providers/claude.ts", "../lib/executor-hooks.ts", "../lib/providers/codex.ts", "../lib/jentrix.ts", "../../packages/execution/src/schemas.ts", "../../packages/execution/src/revision.ts", "../../packages/execution/src/worktree.ts", "../../packages/execution/src/backend.ts", "../../packages/execution/src/drivers/shared.ts", "../../packages/execution/src/drivers/host-process.ts", "../../packages/execution/src/drivers/local-docker.ts", "../lib/turn-protocol.ts", "../lib/runner-pool.ts", "../lib/execution.ts", "../lib/runner-auth.ts", "../lib/standing-pat-policy.ts", "../lib/managed-auth.ts", "../lib/token-roles.ts", "../lib/harness-runner.ts", "../lib/providers/capabilities.ts", "../lib/runtime-routing.ts", "../lib/project-context.ts", "../lib/rubrics.ts", "../lib/role-repo-access.ts", "../lib/harness-worktree.ts", "../../services/sandbox-controller/src/adapters.ts", "../lib/sandbox-broker-adapters.ts", "../lib/sandbox-broker-runtime.ts", "../lib/poll-scope.ts", "../lib/run-once.ts", "../lib/tick-watchdog.ts", "../lib/revision-stamp.ts", "../lib/preflight.ts"],
|
|
4
|
-
"sourcesContent": ["/**\n * Workflow runner (M7) \u2014 drives the plan \u2192 review \u2192 execute \u2192 review loop.\n *\n * Jentrix fires `agent.handoff` (HMAC-signed) on every turn\n * \u2192 this receiver verifies the signature\n * \u2192 claims the turn with the RUNNER admin token (claim_agent_job \u2192 runId)\n * \u2192 spawns the role runtime (Claude planner/executor, Codex reviewer) with\n * the ROLE token and the stacks-review-loop skill, passing the runId\n * \u2192 heartbeats the run while the session works; fails it on a provider error\n *\n * Two principals, by design: the runner's ADMIN token does claim/heartbeat/fail;\n * each session uses its ROLE token so the server-side turn-guard (planner submits\n * plans, reviewer submits reviews) passes. Configure both below.\n *\n * Setup: create a webhook for the `agent.handoff` event pointing at this server\n * and put its secret in STACKS_WEBHOOK_SECRET.\n *\n * AUTH (M12.4b, AGE-174; standing PATs deleted 2026-07, D4/AGE-509) \u2014 role\n * tokens (runner/planner/reviewer) are provisioned by a mode-selected provider\n * (`lib/runner-auth.ts`), refreshed at each drive so short-lived tokens never\n * expire mid-server. Select with STACKS_RUNNER_MODE (required):\n * managed \u2014 workload identity + per-run capability tokens (M12.4a); ZERO\n * standing PATs (STACKS_TOKEN_EXCHANGE_URL + STACKS_WORKLOAD_SVID\n * + STACKS_RUN_ID + STACKS_WORKSPACE_ID).\n * self-hosted \u2014 the M11.1 bootstrap + claim-URL flow: a one-time bootstrap\n * token redeemed at a claim URL for short-lived role tokens\n * (STACKS_BOOTSTRAP_TOKEN + STACKS_CLAIM_URL). No standing PAT.\n * Other env:\n * STACKS_MCP_URL \u2014 defaults to http://localhost:3000/api/mcp\n * STACKS_CODEX_MODEL \u2014 reviewer (Codex) model pin; default gpt-5.5. The\n * codex binary reads ~/.codex/config.toml as base\n * config, so the runner always pins model + effort\n * (STACKS_CODEX_EFFORT, default medium) explicitly.\n * STACKS_RUNNER_REPOS \u2014 optional JSON map \"owner/name\" -> local checkout\n * STACKS_POLL_MS \u2014 > 0 enables webhook-less POLL mode (drives the\n * same loop by polling; use when the Jentrix\n * deployment cannot reach this machine \u2014 its SSRF\n * guard rightly refuses localhost webhook targets)\n * Run: pnpm workflow-runner (listens on PORT, default 8788)\n */\nimport { createHmac, timingSafeEqual } from \"node:crypto\";\nimport { spawn } from \"node:child_process\";\nimport { existsSync, readdirSync } from \"node:fs\";\nimport { createServer } from \"node:http\";\nimport { setTimeout as delay } from \"node:timers/promises\";\n\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\n\nimport { agentProvider, runJentrixAgent } from \"./lib/jentrix.js\";\nimport type { AgentTurnUsage } from \"./lib/jentrix.js\";\nimport { claudeLegModel } from \"./lib/providers/claude.js\";\nimport { codexModel } from \"./lib/providers/codex.js\";\nimport { workerCapabilities } from \"./lib/providers/capabilities.js\";\nimport { RUNNER_VERSION } from \"./lib/version.js\";\nimport {\n makeExecutionBackend,\n preflightManagedVerification,\n runManagedVerificationCommand,\n runTurnThroughBackend,\n} from \"./lib/execution.js\";\nimport { resolveRevisionStamp } from \"../packages/execution/src/revision.js\";\nimport {\n assertBearerPresent,\n resolveRunnerAuth,\n type RunnerRole,\n type RunnerTokenProvider,\n} from \"./lib/runner-auth.js\";\nimport { rememberTokenRole, roleForKnownToken } from \"./lib/token-roles.js\";\nimport {\n claimPresentation,\n DEFAULT_RUNNER_EVIDENCE_TIER,\n driveHarnessStage,\n driveHarnessStageCommit,\n getHarnessStageJob,\n listStageStatuses,\n resolveStageBranch,\n type HarnessRunnerConfig,\n type HarnessRunnerDeps,\n type RunGit,\n} from \"./lib/harness-runner.js\";\nimport {\n checkoutMap,\n parseRunnerRepos,\n RunnerWorktreeManager,\n type OwnerVerdict,\n type OwnerStateReader,\n} from \"./lib/harness-worktree.js\";\nimport { buildProjectContext } from \"./lib/project-context.js\";\nimport { loadRubric } from \"./lib/rubrics.js\";\nimport { repoAccessForRole } from \"./lib/role-repo-access.js\";\nimport { makeSandboxEgress } from \"./lib/sandbox-broker-runtime.js\";\nimport {\n BoundedDedupPool,\n parseBoundedMax,\n parsePositiveInt,\n} from \"./lib/runner-pool.js\";\nimport { jobHarnessRunId, pollScopeAllows } from \"./lib/poll-scope.js\";\nimport { IDLE_TICKS_TO_EXIT, nextIdleTicks } from \"./lib/run-once.js\";\nimport { createStallWatchdog } from \"./lib/tick-watchdog.js\";\nimport {\n probeRevisionHealth,\n resolveSchemaRevision,\n} from \"./lib/revision-stamp.js\";\nimport {\n applyStaleCheckoutOverride,\n checkRepos,\n renderTable,\n STALE_CHECKOUT_OVERRIDE,\n} from \"./lib/preflight.js\";\nimport {\n parseRoleBindings,\n resolveClaimExecution,\n type ExpectedRoleBinding,\n type RunnerRoleBindings,\n} from \"./lib/runtime-routing.js\";\n\ndeclare const __STACKS_BUNDLED_SCHEMA_REVISION__: string | undefined;\ndeclare const __STACKS_BUNDLED_APP_REVISION__: string | undefined;\n\n// F8 (AGE-505): every numeric env knob parses NaN-safe with its documented\n// default \u2014 a typo'd value can no longer produce a NaN timeout (fires\n// immediately) or a NaN turn budget (disables the budget).\nconst PORT = parsePositiveInt(process.env.PORT, 8788);\nconst HOST = process.env.STACKS_RUNNER_HOST ?? \"0.0.0.0\";\nconst SECRET = process.env.STACKS_WEBHOOK_SECRET ?? \"\";\nconst MCP_URL = process.env.STACKS_MCP_URL ?? \"http://localhost:3000/api/mcp\";\nconst STACKS_BASE_URL = process.env.STACKS_BASE_URL ?? new URL(MCP_URL).origin;\nconst ROLE_BINDINGS: RunnerRoleBindings | null = process.env\n .STACKS_RUNNER_ROLE_BINDINGS\n ? parseRoleBindings(process.env.STACKS_RUNNER_ROLE_BINDINGS)\n : null;\nlet shutdownRequested = false;\nif (!ROLE_BINDINGS) {\n console.error(\n \"DEPRECATED: no durable STACKS_RUNNER_ROLE_BINDINGS configured; using legacy STACKS_AGENT_PROVIDER routing for this compatibility window.\",\n );\n}\n\nasync function mintClaimCredential(\n binding: ExpectedRoleBinding,\n): Promise<string | undefined> {\n if (!binding.requiresClaimCredential) return undefined;\n const runnerToken = process.env.STACKS_WORKER_HEARTBEAT_TOKEN;\n if (!runnerToken) {\n throw new Error(\n \"ATTESTATION_FAILED: subscription routing requires the enrolled worker heartbeat token.\",\n );\n }\n const response = await fetch(\n new URL(\"/api/providers/claim-credential\", STACKS_BASE_URL),\n {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n runnerToken,\n connectionId: binding.providerConnectionId,\n }),\n signal: AbortSignal.timeout(30_000),\n },\n );\n const value = (await response.json().catch(() => null)) as {\n claimToken?: unknown;\n } | null;\n if (!response.ok || typeof value?.claimToken !== \"string\") {\n throw new Error(\n `ATTESTATION_FAILED: node-bound claim credential was refused (HTTP ${response.status}).`,\n );\n }\n return value.claimToken;\n}\n// M12.4b (AGE-174): the runner NEVER reads standing PATs directly. Role tokens\n// are provisioned by the mode-selected provider (managed / self-hosted / legacy)\n// and refreshed at each drive via refreshRoleTokens(), so a long-running server\n// with short-lived tokens never presents an expired one. Populated before listen.\nlet RUNNER_TOKEN = \"\";\nlet PLANNER_TOKEN = \"\";\nlet REVIEWER_TOKEN = \"\";\nconst HEARTBEAT_MS = 60_000;\nconst MAX_SKEW_MS = 5 * 60 * 1000;\n// A provider session that never returns (a network stall mid-turn) must not\n// wedge the runner: after this long the turn is failed (job parks BLOCKED,\n// recoverable via retry_harness_stage) and the pool frees the slot.\nconst TURN_TIMEOUT_MS = parsePositiveInt(\n process.env.STACKS_TURN_TIMEOUT_MS,\n 30 * 60 * 1000,\n);\n// AGE-414: in-run session retries when the stacks MCP server fails to connect\n// at SDK init (thrown before any model turn burns \u2014 see providers/claude.ts).\n// F7 (AGE-504): the SDK reports http MCP servers as \"pending\" at init (the M17\n// lesson \u2014 never abort on pending); the provider only fails on a terminal\n// status or the session's own tool-less sentinel. The [5s,15s] window still\n// lost to real Vercel cold-start/limit windows and failed planner jobs \u2014 the\n// bounded wait is now ~2.5 minutes across 5 attempts.\nconst MCP_CONNECT_RETRY_DELAYS_MS = [5_000, 15_000, 45_000, 90_000];\n// Turn budgets by turn type. Plan/review turns are a handful of MCP calls;\n// EXECUTION turns implement a real change in a checkout (S1 of the i18n run\n// burned 40 turns mid-migration) and need a far larger budget. A retried\n// execution turn continues from the surviving working tree, so even a\n// budget-death makes monotone progress \u2014 but hitting it should be rare.\nconst PLAN_MAX_TURNS = parsePositiveInt(process.env.STACKS_PLAN_MAX_TURNS, 40);\nconst EXEC_MAX_TURNS = parsePositiveInt(process.env.STACKS_EXEC_MAX_TURNS, 150);\n// Pool watchdog: a hard upper bound on ANY pooled task (turn or commit\n// boundary). Slightly above the turn timeout so the clean fail path wins;\n// when it fires, the pool releases the slot while the orphaned work keeps\n// running detached (attempt-guarded, worktree retained) \u2014 the server-side\n// claim CAS makes a superseding claim safe.\n// A pooled Harness drive also performs runner-attested verification after the\n// model turn, so the watchdog leaves headroom past the turn timeout for the\n// bounded verification commands instead of orphaning valid evidence.\nconst WATCHDOG_MS = parsePositiveInt(\n process.env.STACKS_JOB_WATCHDOG_MS,\n TURN_TIMEOUT_MS + 30 * 60 * 1000,\n);\n\n// ---------------------------------------------------------------------------\n// Stage 4 (S4): two bounded, job-id-deduplicating work pools replace the single\n// serialized promise chains. STACKS_RUNNER_MAX_CONCURRENT_JOBS bounds the\n// planner/reviewer/executor AGENT turns (default 1); STACKS_RUNNER_MAX_CONCURRENT_COMMITS\n// bounds the post-validation commit/push CONTINUATIONS on a DEDICATED pool\n// (default 1), so a freshly-approved commit never queues behind a long model\n// turn even when the agent-turn pool is full. Both parse to a FINITE documented\n// maximum (clamped by parseBoundedMax \u2014 never unbounded).\n// ponytail: fixed hard caps; bump the constant if a real deployment needs more.\nconst MAX_AGENT_JOBS_HARD = 16; // documented finite max for the agent-turn pool\nconst MAX_COMMIT_JOBS_HARD = 8; // documented finite max for the commit pool\nconst MAX_CONCURRENT_JOBS = parseBoundedMax(\n process.env.STACKS_RUNNER_MAX_CONCURRENT_JOBS,\n 1,\n MAX_AGENT_JOBS_HARD,\n);\nconst MAX_CONCURRENT_COMMITS = parseBoundedMax(\n process.env.STACKS_RUNNER_MAX_CONCURRENT_COMMITS,\n 1,\n MAX_COMMIT_JOBS_HARD,\n);\nconst AGENT_JOBS_CONFIGURED = process.env.STACKS_RUNNER_MAX_CONCURRENT_JOBS\n ? Number(process.env.STACKS_RUNNER_MAX_CONCURRENT_JOBS)\n : MAX_CONCURRENT_JOBS;\nconst COMMIT_JOBS_CONFIGURED = process.env.STACKS_RUNNER_MAX_CONCURRENT_COMMITS\n ? Number(process.env.STACKS_RUNNER_MAX_CONCURRENT_COMMITS)\n : MAX_CONCURRENT_COMMITS;\n\n// S4 telemetry state. jobEnqueuedAt mirrors the pools' inflight registries (set\n// on accept, cleared on TRUE settle) so we report the oldest in-flight job age;\n// lastClaimToExecMs is the most recent submit\u2192start (queue) latency; and\n// branchOwnershipConflicts counts stage-branch collisions the ownership reader\n// evaluated (a peer attempt already holds the resolved branch).\nconst jobEnqueuedAt = new Map<string, number>();\nlet lastClaimToExecMs = 0;\nlet branchOwnershipConflicts = 0;\n\n// STACKS_RUNNER_REPOS: \"owner/name\" -> a checkout path (string) OR an operator\n// object { cwd, bootstrap:[[argv]], copyIgnoredFiles, worktreeRoot } (Stage 3).\n// Parsed into per-repo entries the worktree manager drives; REPOS is the derived\n// owner->checkout map the generic (non-worktree) drive() path still uses.\nconst REPO_ENTRIES = (() => {\n let raw: unknown;\n try {\n raw = JSON.parse(process.env.STACKS_RUNNER_REPOS ?? \"{}\");\n } catch {\n console.error(\"STACKS_RUNNER_REPOS is not valid JSON \u2014 ignoring.\");\n return {};\n }\n try {\n return parseRunnerRepos(raw);\n } catch (err) {\n console.error(err instanceof Error ? err.message : String(err));\n return {};\n }\n})();\nconst REPOS: Record<string, string> = checkoutMap(REPO_ENTRIES);\nconst EXECUTION_PHASES = new Set([\"EXECUTING\", \"EXECUTION_REVISION\"]);\n\n// Webhook-less poll mode: > 0 turns on polling every N ms. A deployed Jentrix\n// cannot deliver webhooks to a localhost runner (the outbound SSRF guard\n// rejects private destinations, correctly), so without a public tunnel the\n// webhook path simply cannot fire \u2014 this fallback drives the SAME loop by\n// polling list_agent_jobs / the harness commit boundary instead. The webhook\n// server still runs (both can coexist; claims are CAS-guarded server-side, so\n// a webhook and a poll racing the same turn can never double-claim).\n// 0 = poll mode off (webhook only); an invalid value falls back to off.\nconst POLL_MS = process.env.STACKS_POLL_MS\n ? parsePositiveInt(process.env.STACKS_POLL_MS, 0)\n : 0;\nconst POLL_HARNESS_RUN_ID =\n process.env.STACKS_POLL_HARNESS_RUN_ID?.trim() || undefined;\n// AGE-836: once mode \u2014 a launchd-respawned dispatcher that lives for the\n// duration of the work it finds, then exits (lib/run-once.ts holds the exit\n// decision). Drives the SAME tick as poll mode; skips the webhook listener so\n// a canary can run beside a long-lived runner without fighting over PORT.\nconst RUN_ONCE = process.env.STACKS_RUNNER_ONCE === \"1\";\n// Once mode must not require the poll-mode env to be useful: tick at\n// STACKS_POLL_MS when set, else a sane default.\nconst ONCE_TICK_MS = POLL_MS > 0 ? POLL_MS : 15_000;\n// AGE-497: how often a LONG-LIVED runner re-asks the control plane whether its\n// stamp still matches. Prod redeploys while this process stays up, so a start-up\n// check alone goes stale; once mode re-checks by respawning instead.\nconst REVISION_PROBE_MS = 5 * 60_000;\n\n// In poll/once mode the webhook secret is optional (no deliveries expected);\n// unsigned posts are still rejected by verifySignature's empty-secret check.\nif (POLL_MS <= 0 && !RUN_ONCE && !SECRET) {\n console.error(\n \"Missing STACKS_WEBHOOK_SECRET \u2014 see the header of workflow-runner.ts.\",\n );\n process.exit(1);\n}\n\n// Select the auth provider from STACKS_RUNNER_MODE (managed / self-hosted /\n// legacy-PAT). A misconfiguration (no mode + no standing PATs) fails closed here\n// with a legible error, same as the old missing-token check \u2014 but the managed\n// path never reads a standing PAT.\nlet authProvider: RunnerTokenProvider;\ntry {\n // Default 30s expiry skew. Do NOT widen it: every mint ROTATES the\n // server-side bearer, and the poll loop refreshes each tick \u2014 a wide skew\n // rotates the token out from under an in-flight agent session (found live\n // 2026-07-24, twice). Fresh-per-leg tokens come from the leg-start\n // invalidation in refreshRoleTokens({ legStart: true }) instead.\n authProvider = resolveRunnerAuth();\n} catch (err) {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n}\n\n/** The P2.6 signature scheme (timestamp.body), same as bug-triage.ts. */\nfunction verifySignature(\n headers: Record<string, string | string[] | undefined>,\n rawBody: string,\n): boolean {\n const signature = headers[\"x-stacks-signature\"];\n const timestamp = headers[\"x-stacks-timestamp\"];\n if (typeof signature !== \"string\" || typeof timestamp !== \"string\") {\n return false;\n }\n const age = Math.abs(Date.now() - new Date(timestamp).getTime());\n if (!Number.isFinite(age) || age > MAX_SKEW_MS) return false;\n const expected =\n \"sha256=\" +\n createHmac(\"sha256\", SECRET)\n .update(`${timestamp}.${rawBody}`)\n .digest(\"hex\");\n const a = Buffer.from(expected);\n const b = Buffer.from(signature);\n return a.length === b.length && timingSafeEqual(a, b);\n}\n\n// Transport-level failures (Vercel 5xx blips, dropped sockets) are retried \u2014\n// a 504 on the runner's OWN recording call after a 25-minute green executor\n// turn parked stage 1 of the M17 run. App-level tool errors (the `isError`\n// envelope) are NEVER retried here. A retry of a call whose first attempt\n// actually landed can surface as CONFLICT \u2014 the state machine already\n// advanced, which the caller/sweep resolves from durable state.\nconst TRANSIENT_CALL_DELAYS_MS = [2_000, 8_000];\nconst TRANSIENT_CALL_RE =\n /Streamable HTTP error|fetch failed|ECONNRESET|socket hang up|Request timed out|\"code\":\\s*\"50[234]\"/;\n// AGE-835: fail fast so retries fit inside the 60s heartbeat cadence \u2014 the\n// SDK's 60s default meant ONE stalled connection consumed the whole beat, and\n// consecutive stalls outlived the server's run TTL (observed: a 12-min executor\n// turn expired mid-flight). 15s \u00D7 3 attempts + backoff \u2248 55s worst case.\nconst CALL_TIMEOUT_MS = 15_000;\n\n/** One MCP tool call with a specific token (the runner's admin token). */\n/**\n * AGE-840/899: which role a bearer belongs to, so a 401 can invalidate THAT\n * role. Current tokens match by identity; a bearer that has since been rotated\n * out resolves through the minted-token history in `lib/token-roles.ts` \u2014\n * identity ALONE left a long call's captured bearer unattributable, so the\n * re-mint declined and the caller wedged for the token's remaining TTL. An\n * unrecognized string still yields null, correctly declining to re-mint.\n */\nfunction roleForToken(token: string): RunnerRole | null {\n if (!token) return null;\n if (token === RUNNER_TOKEN) return \"runner\";\n if (token === PLANNER_TOKEN) return \"planner\";\n if (token === REVIEWER_TOKEN) return \"reviewer\";\n // A bearer captured before the last rotation is still ours \u2014 see token-roles.\n return roleForKnownToken(token);\n}\n\nfunction tokenForRole(role: RunnerRole): string {\n return role === \"runner\"\n ? RUNNER_TOKEN\n : role === \"planner\"\n ? PLANNER_TOKEN\n : REVIEWER_TOKEN;\n}\n\nasync function callTool(\n token: string,\n name: string,\n args: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n // AGE-687: never POST `Bearer ` \u2014 see assertBearerPresent. Checked OUTSIDE the\n // retry loop: an absent local token is not transient at this call site.\n assertBearerPresent(token, name);\n // AGE-840: a role token can be revoked SERVER-side BEFORE its own expiry \u2014\n // every claim rotates the bearer \u2014 while `createCachingTokenProvider` re-mints\n // only on timestamp expiry. The cache then serves a dead token for up to its\n // full 1h TTL and EVERY call 401s with no self-heal (observed twice: a wedged\n // poll loop, then a lost executor turn). Retrying the same string is futile,\n // so the first 401 invalidates that role and re-mints ONCE. Bounded to one\n // attempt: a second 401 on a freshly minted token is a real authorization\n // failure, not staleness, and must surface rather than loop.\n let bearer = token;\n let reMinted = false;\n // AGE-923: `retryAfterSeconds` is `60 - now.getUTCSeconds()` server-side, so\n // four honored waits are ~244s inside ONE call \u2014 longer than the tick\n // watchdog supervising it, which is how a live tick read as a wedge. Waiting\n // out the bucket needs one wait (two if the next minute re-trips), which is\n // what the evidence-submission burst this retry was built for actually took;\n // beyond that the cap is being re-tripped immediately and failing the call to\n // the caller's own retry beats sleeping through four minutes of it.\n const RATE_LIMIT_BUDGET_MS = 120_000;\n let rateLimitWaitedMs = 0;\n for (let attempt = 0; ; attempt++) {\n try {\n const transport = new StreamableHTTPClientTransport(new URL(MCP_URL), {\n requestInit: { headers: { Authorization: `Bearer ${bearer}` } },\n });\n const client = new Client({\n name: \"stacks-workflow-runner\",\n version: RUNNER_VERSION,\n });\n await client.connect(transport, { timeout: CALL_TIMEOUT_MS });\n try {\n const res = await client.callTool(\n { name, arguments: args },\n undefined,\n {\n timeout: CALL_TIMEOUT_MS,\n },\n );\n if (res.isError) {\n const text =\n Array.isArray(res.content) &&\n res.content[0] &&\n \"text\" in res.content[0]\n ? (res.content[0] as { text: string }).text\n : JSON.stringify(res.content);\n throw new Error(`${name} failed: ${text}`);\n }\n return (res.structuredContent ?? {}) as Record<string, unknown>;\n } finally {\n await client.close();\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n // RATE_LIMITED is app-level but explicitly retriable: the server did not\n // process the call and tells us how long to wait. An evidence-submission\n // burst after a green executor turn tripped the 60/min cap and parked\n // stage 1 \u2014 honor retryAfterSeconds instead of failing the turn.\n if (msg.includes('\"RATE_LIMITED\"') && attempt < 4) {\n const m = msg.match(/\"retryAfterSeconds\":\\s*(\\d+)/);\n const waitMs = ((m ? Number(m[1]) : 5) + 1) * 1000;\n if (rateLimitWaitedMs + waitMs <= RATE_LIMIT_BUDGET_MS) {\n rateLimitWaitedMs += waitMs;\n console.error(\n `[callTool ${name}] rate-limited (attempt ${attempt + 1}) \u2014 waiting ${waitMs}ms`,\n );\n await new Promise((r) => setTimeout(r, waitMs));\n continue;\n }\n console.error(\n `[callTool ${name}] rate-limited past the ${RATE_LIMIT_BUDGET_MS}ms backoff budget \u2014 failing to the caller (AGE-923)`,\n );\n }\n // AGE-840: a revoked-but-unexpired cached token. Invalidate that role,\n // re-mint, and retry with the NEW bearer \u2014 retrying the same string can\n // only 401 again. Once only; `reMinted` also guards the case where the\n // re-mint itself hands back a token the server rejects.\n if (/invalid_token|\"code\":\\s*\"401\"/.test(msg) && !reMinted) {\n const role = roleForToken(bearer);\n if (role) {\n reMinted = true;\n authProvider.invalidate?.(role);\n try {\n await refreshRoleTokens();\n } catch (refreshErr) {\n // Re-minting failed (a spent/revoked grant chain) \u2014 that is the\n // operator-actionable error, not the 401 it was masking.\n throw refreshErr;\n }\n bearer = tokenForRole(role);\n assertBearerPresent(bearer, name);\n console.error(\n `[callTool ${name}] 401 on a cached ${role} token \u2014 re-minted and retrying once (AGE-840)`,\n );\n continue;\n }\n }\n const transient =\n !msg.startsWith(`${name} failed:`) && TRANSIENT_CALL_RE.test(msg);\n if (!transient || attempt >= TRANSIENT_CALL_DELAYS_MS.length) throw err;\n console.error(\n `[callTool ${name}] transient failure (attempt ${attempt + 1}): ${msg.slice(0, 120)} \u2014 retrying`,\n );\n await new Promise((r) =>\n setTimeout(r, TRANSIENT_CALL_DELAYS_MS[attempt]),\n );\n }\n }\n}\n\nconst PLANNER_PROMPT = `You are the PLANNER/EXECUTOR in a Jentrix review loop.\nYou have been handed a runId for the current turn. Work ONLY through the Jentrix\nMCP tools (the stacks-review-loop skill explains the protocol). If the phase is a\nplan phase: read the job with get_agent_job, read any open findings, then call\nsubmit_plan(jobId, runId, ...) with the plan's objective/acceptanceCriteria and,\nif revising, resolutions that say how you fixed each finding.\nIF the job's templateKey is \"decomposition\", submit_plan MUST ALSO include a\nharnessStages array \u2014 the concrete ordered stages the accept gate will mint. Each\nstage: { title, objective, approach, expectedBranchBehavior, acceptanceCriteria[],\nsuggestedTests[], riskNotes[], tracesToCriteria[], verificationCommands[],\ncriterionEvidence[] }. tracesToCriteria must quote\nthe ACCEPTED spec's structured definitionOfDone verbatim (see get_spec /\nget_agent_job) \u2014 never invent criterion labels. criterionEvidence maps each\ntraced criterion to its proof: { criterion (verbatim), mode: \"AUTOMATED\" |\n\"OPERATOR\", requiredTier: \"UNIT_MOCKED\" | \"INTEGRATION_LOCAL\" |\n\"PROD_TOPOLOGY_LOCAL\" | \"MANAGED_STAGING\" | \"PRODUCTION_DRILL\",\nverificationCommands[] } \u2014 across the WHOLE run every spec criterion must be\nmapped exactly once, an AUTOMATED criterion needs at least one runnable\ncommand, and a human action (deploy, env var, restart) is OPERATOR, never\nhidden behind stage completion. verificationCommands (stage level) is the\nunion of the stage's AUTOMATED commands \u2014 the RUNNER executes them itself to\nmint attested test evidence; executor prose never satisfies the gate. Put the\ndetailed per-surface requirements in each stage's own acceptanceCriteria.\nDescribing stages only in the objective prose is NOT enough \u2014 without the\nharnessStages array the gate has nothing to mint and the reviewer cannot\nverify the plan.\nTHIS PROPOSAL IS THE ENTIRE PLAN (AGE-781): stages execute with NO per-stage\nplan loop \u2014 each stage attempt opens directly at execution with your frozen\nstage plan as its whole brief. Two consequences. (1) approach is the\nexecutor's brief: name the files/modules to touch, the mechanism, and the\nordering, per stage \u2014 an executor cannot re-plan a vague stage, it can only\nfail it. (2) GROUND every criterion (AGE-782/M19): a criterion that asserts\nbehavior over EXISTING code or schema must name the artifact it depends on\n(file path, model.field), and you must VERIFY each named artifact exists in\nthe mapped planning checkout (Read/Glob/Grep) before submitting. A criterion\nrequiring a schema field that does not exist, in a stage that declares \"no\nmigration\", is an unsatisfiable frozen contract \u2014 it deadlocked a real run\nfor 11 rounds. State each stage's grounding facts in its riskNotes (e.g.\n\"grounded: Workspace.updatedAt exists at prisma/schema.prisma:NN\"). Criteria\nmust be jointly satisfiable AGAINST THE CODEBASE AS IT EXISTS, not merely\nwell-formed.\nIF the job's templateKey is \"authoring\" (AGE-521 \u2014 PRD\u2192spec is the lossy hop;\nmake the loss explicit): you are drafting the run's spec FROM the PRD named in\nthe objective. Read the PRD file in the mapped checkout. EVERY definitionOfDone\ncriterion must cite its PRD source inline (append \"\u2014 [PRD \u00A7<section>]\"), and\nevery PRD section you deliberately exclude must appear in nonGoals with a\nreason. A PRD section that is neither cited by a criterion nor excluded in\nnonGoals is a coverage hole the reviewer will reject.\nIF the job is a harness STAGE job (get_agent_job shows a harness block) and the\nphase is a plan phase (AGE-520 \u2014 stage scope contract): fetch the run's\naccepted spec (get_harness gives specId \u2192 get_spec) and the sibling registry\n(list_harness_stages, response_format \"detailed\"). Your stage owns EXACTLY the\nharness block's criteria. Plan to satisfy those and nothing else: never pull a\nsibling stage's criterion into this stage, and never drop an owned one \u2014 the\nspec is your read-only global context, the stage slice is your contract.\nIf the phase is an execution phase: do the work in the mapped repo, then\nsubmit_execution_result(jobId, runId, executionSummary, artifactIds). Do NOT call\nclaim/heartbeat/fail. Finish with a one-line summary.`;\n\nconst REVIEWER_PROMPT = `You are the REVIEWER in a Jentrix review loop. You have\na runId for the current turn. Read the job with get_agent_job (and the latest\nplan version / execution summary), then call submit_review(jobId, runId, verdict,\nreviewerSummary, findings[], verifiedFindingIds[]). Mark any previously-addressed\nfindings you have verified. ALWAYS pass reviewerSummary \u2014 it is the only thing a\nhuman operator reads to learn why the job moved, and a rejection that reopens an\nexisting finding submits no new ones, so without it the job page shows a revision\nphase with no explanation.\n${loadRubric(\"reviewer-disposition\")}\nIF the job's templateKey is \"decomposition\", review the get_agent_job\ndecompositionProposal array (the exact ordered stages the accept gate will\nmint): verify the stages are ordered + independently shippable, each has its own\nacceptanceCriteria + suggestedTests, tracesToCriteria references only the accepted\nspec's stored criteria, and every spec concern is owned by some stage (no orphan).\nIf decompositionProposal is null/empty, the planner did not submit harnessStages \u2014\nCHANGES_REQUESTED asking for the harnessStages array.\nTHIS REVIEW IS THE LAST GATE BEFORE EXECUTION (AGE-781): stages run with NO\nper-stage plan loop \u2014 what you approve here is frozen as each stage's entire\ncontract and brief, and after the mint NOTHING can amend it short of a human\nre-decomposition. Therefore: (1) verify each stage's approach is a concrete,\nexecutable brief (files/mechanism/ordering), not a restatement of the title;\n(2) GROUND-CHECK the criteria against the checkout \u2014 for every criterion that\nasserts behavior over existing code or schema, grep the named artifact\n(schema field, module, function) in your checkout and REJECT (severity >= 60,\nbasisKind BASELINE_REQUIREMENT) any criterion that depends on an artifact\nthat does not exist unless the same stage explicitly creates it; (3) check\nthe stage's criteria are JOINTLY satisfiable \u2014 a criterion demanding a\nmechanism (e.g. an updatedAt-based CAS) next to a constraint that forbids its\nprerequisite (e.g. \"no migration\" with no such column) is an unsatisfiable\nfrozen contract and MUST be rejected here, because the executor cannot fix\nscope and the run will burn its bounded attempts re-proving the conflict.\nIF the job's templateKey is \"authoring\" (AGE-521): verify PRD coverage. Read\nthe PRD file in the checkout. Every PRD section must be either cited by a\ndefinitionOfDone criterion (\"[PRD \u00A7<section>]\") or excluded in nonGoals with a\nreason. An uncited, unexcluded PRD section is a blocking finding (severity\n>=60, basisKind BASELINE_REQUIREMENT, basisRef the PRD section) \u2014 the spec is\nthe only place downstream coverage guards can see the PRD, so a hole here\npropagates silently.\nSTAGE SCOPE CONTRACT (AGE-520 \u2014 harness stage jobs): judge this stage ONLY\nagainst ITS OWN criteria (the harness block / the frozen stage plan; confirm\nownership with list_harness_stages response_format \"detailed\" and the accepted\nspec via get_harness \u2192 get_spec). Evidence for criteria owned by OTHER stages\nis OUT OF SCOPE here: file such observations as severity <40 follow-ups naming\nthe owning stage, never as blockers \u2014 a whole-PRD expectation held against one\nstage parks the run for nothing.\nIF get_agent_job shows a \"harness\" block (a harness stage job), ALSO reconcile\nthe findings ledger: call list_harness_findings({harnessRunId, harnessStageId})\nand judge every OPEN/FIXED row against the evidence in front of you \u2014 for each\nFIXED claim the evidence GENUINELY covers, call\nupdate_harness_finding({findingId, status: \"VERIFIED\", verifiedRunId: <your runId>});\nREOPEN a hollow claim (status: \"OPEN\", resolutionNote explaining what is missing);\na covered row still sitting OPEN goes OPEN\u2192FIXED\u2192VERIFIED (two calls). Never\nreject solely because ledger rows predate this job \u2014 verify what the current\nevidence covers and reject only for what genuinely remains. submit_review's\nverifiedFindingIds reaches only THIS job's findings; the ledger tools cover\nprior rounds. Execution evidence for a harness stage NEVER includes a commit\nSHA: the stage commit happens AFTER validation, behind the governed commit\nboundary \u2014 the recorded stage result plus diff/test artifacts ARE the complete\nexecution-time record, so never request a commit as execution evidence.\nWhen an acceptance criterion names a trust or exactly-once boundary, review the\nliteral production path, not a similarly-shaped test double: comments, an\nunwired adapter seam, an in-memory Set/Map, or a caller promise to authenticate\ndo not prove it. Distinguish at-least-once model generation from exactly-once\nresult application, and require irreversible git/GitHub effects to reconcile\nfrom provider-authoritative state after success-before-finalize. For signed gate\nsignals, require authenticated source-record consumption, signature mint, and\ndurable signal-outbox insert to share the stated atomic ingress; then verify the\nworkflow rejects bad binding/version/nonce/signature and worker authority.\nDo NOT call claim/heartbeat/fail. Finish with a one-line summary.`;\n\n/** AGE-926: a turn that ENDS without submitting is a failed turn, not a quiet\n * one. A provider can deliver a terminal API error \u2014 an exceeded output\n * ceiling, a refusal \u2014 as the session's RESULT TEXT rather than by throwing,\n * so the runner sees a clean return, logs the text as if it were a summary,\n * and walks away leaving the job claimed until its heartbeat lapses. Observed\n * on a planner leg that died at 02:14:45 whose job did not park until\n * 03:05:24, recorded as the generic \"Agent run heartbeat expired\" with the\n * real cause visible only in this process's stdout.\n *\n * The check reads a DURABLE fact rather than pattern-matching the text: every\n * plan and review turn ends by calling its submit tool, and that submit\n * settles this run SUCCEEDED server-side. A run still open once the session\n * has returned means nothing was submitted, whatever the text claims.\n *\n * Deliberately one-sided \u2014 it only fails a turn it can PROVE did not submit.\n * An unreadable job or an unrecognized run returns silently and leaves the\n * pre-existing heartbeat path as the backstop: failing a live turn on a bad\n * read would be a worse defect than the slow park this replaces. */\nasync function assertTurnSubmitted(\n jobId: string,\n runId: string,\n role: string,\n summary: string,\n): Promise<void> {\n let run: { id?: string; status?: string } | undefined;\n try {\n const res = await callTool(RUNNER_TOKEN, \"get_agent_job\", { jobId });\n const job = (res.job ?? res) as {\n runs?: { id?: string; status?: string }[];\n };\n run = job.runs?.find((r) => r.id === runId);\n } catch (e) {\n console.error(\n `[job ${jobId}] could not verify ${role} submission: ${e instanceof Error ? e.message : e}`,\n );\n return;\n }\n if (!run?.status || run.status === \"SUCCEEDED\") return;\n throw new Error(\n `${role} turn ended without submitting a result (run ${run.status}). ` +\n `Provider's final output: ${summary.slice(0, 400)}`,\n );\n}\n\nasync function drive(\n jobId: string,\n toRole: string,\n phase: string,\n repoOwnerName: string | undefined,\n // Stage 3: for a harness reviewer turn, the stage's WORKTREE (read-only) \u2014 the\n // uncommitted changes live there now, not the shared checkout. A GENERIC (non-\n // harness) reviewer has none and legitimately reads the shared checkout.\n reviewerWorktreeCwd?: string,\n // Stage 3 (fail-closed): true when this is a HARNESS reviewer whose read-only\n // review MUST run against the stage worktree (the uncommitted change lives\n // there). When required-but-absent we refuse to fall back to the shared\n // checkout \u2014 approving against a tree without the stage's changes is worse\n // than parking the stage for a human.\n reviewerWorktreeRequired?: boolean,\n groundingError?: string,\n): Promise<void> {\n if (shutdownRequested) return;\n const isReviewer = toRole === \"REVIEWER\";\n const isExecution = EXECUTION_PHASES.has(phase);\n const expectedBinding =\n ROLE_BINDINGS?.[\n isReviewer ? \"reviewer\" : isExecution ? \"executor\" : \"planner\"\n ];\n const provider =\n expectedBinding?.runtimeAdapterKey ??\n (isReviewer ? \"codex\" : agentProvider());\n // Per-leg Claude model pin: planner legs (authoring/planning/revision) and\n // executor legs may run different models (STACKS_PLANNER_MODEL /\n // STACKS_EXECUTOR_MODEL). Codex reviewer legs pin via STACKS_CODEX_MODEL.\n const turnModel =\n expectedBinding?.model ??\n (provider === \"claude\"\n ? claudeLegModel(isExecution ? \"executor\" : \"planner\")\n : codexModel());\n const workerClaimToken = expectedBinding\n ? await mintClaimCredential(expectedBinding)\n : undefined;\n if (shutdownRequested) return;\n // 1. Claim the current turn (admin token) \u2192 runId. The presentation (pinned\n // model + build-stamped revision + capabilities) rides claimPresentation \u2014\n // the control plane refuses a schema-incompatible worker, an unattested\n // validator lane, or an unrunnable model BEFORE any model turn burns\n // (M12.3b/M13.4b; un-stamped dev leaves the compatibility guard inert).\n const claim = await callTool(RUNNER_TOKEN, \"claim_agent_job\", {\n jobId,\n ...claimPresentation(provider, { model: turnModel }),\n ...(expectedBinding ? { provider: expectedBinding.provider } : {}),\n ...(workerClaimToken ? { workerClaimToken } : {}),\n });\n const runId = String(claim.runId);\n let execution = null;\n try {\n execution = expectedBinding\n ? resolveClaimExecution(claim, expectedBinding)\n : null;\n } catch (error) {\n await callTool(RUNNER_TOKEN, \"fail_agent_job\", {\n jobId,\n runId,\n error: error instanceof Error ? error.message : \"role route refused\",\n }).catch(() => {});\n throw error;\n }\n\n // Execution turns get repo tools scoped to the mapped checkout, so the\n // executor actually implements the change instead of only recording it.\n // REVIEWER turns get the SAME checkout READ-ONLY, so the review verifies\n // claims against the actual working tree (which holds the stage's\n // uncommitted changes) instead of judging the executor's prose \u2014 a reviewer\n // that can check reality rejects less and its approvals mean more.\n const checkout = repoOwnerName ? REPOS[repoOwnerName] : undefined;\n // M18.3 R7: the checkout decision comes from the DURABLE run role the control\n // plane just returned, through the same total, fail-closed map the harness\n // path uses (agents/lib/role-repo-access.ts). Behaviour-preserving for every\n // shipped leg \u2014 EXECUTING/EXECUTION_REVISION open as EXECUTOR (writable),\n // PLAN_*/EXECUTION_REVIEW as PLANNER/REVIEWER (read-only) \u2014 but now a role\n // this runner does not recognize can only ever get a read-only tree, instead\n // of whatever the phase happened to imply.\n const repoAccess = repoAccessForRole(\n typeof claim.role === \"string\" ? claim.role : null,\n );\n const repoCwd = repoAccess.provisionWorktree ? checkout : undefined;\n // A harness reviewer reads the stage's WORKTREE (where the uncommitted change\n // lives); a generic reviewer reads the shared checkout.\n const reviewerCwd = isReviewer\n ? (reviewerWorktreeCwd ?? checkout)\n : undefined;\n // AGE-523: PLANNING/authoring legs read the shared checkout READ-ONLY so the\n // planner can ingest in-repo sources (PRDs under prds/, docs) \u2014 the M18\n // authoring contract requires the PRD body verbatim, and it exists only in\n // the repo. Only execution legs get a writable tree; no mapped repo keeps\n // the old MCP-only world.\n const planningReadCwd =\n !repoAccess.provisionWorktree && !isReviewer ? checkout : undefined;\n if (isExecution && (!repoOwnerName || !repoCwd)) {\n // No checkout to work in \u2014 FAIL the run instead of producing a hollow\n // \"execution\" with no code changes. The job blocks for a human.\n const reason = repoOwnerName\n ? `No STACKS_RUNNER_REPOS entry for ${repoOwnerName} \u2014 cannot execute.`\n : \"Job has no repoOwnerName \u2014 cannot execute in a checkout.\";\n console.error(`[job ${jobId}] ${reason}`);\n await callTool(RUNNER_TOKEN, \"fail_agent_job\", {\n jobId,\n runId,\n error: reason,\n }).catch((e) => console.error(`[fail ${jobId}]`, e));\n return;\n }\n\n // Stage 3 fail-closed: a HARNESS reviewer must read the stage's WORKTREE (its\n // uncommitted changes live there, not in the shared checkout). If the worktree\n // could not be adopted (missing, pruned, or marker-mismatched), FAIL the run\n // instead of falling back to the shared checkout \u2014 reviewing/approving against\n // the wrong tree is worse than parking the stage for a human to resolve.\n if (isReviewer && reviewerWorktreeRequired && !reviewerWorktreeCwd) {\n const reason =\n \"Harness reviewer could not adopt the stage worktree (missing, pruned, or marker-mismatched); refusing to review against the shared checkout, which lacks the stage's uncommitted changes. Resolve the worktree, then retry the stage.\";\n console.error(`[job ${jobId}] ${reason}`);\n await callTool(RUNNER_TOKEN, \"fail_agent_job\", {\n jobId,\n runId,\n error: reason,\n }).catch((e) => console.error(`[fail ${jobId}]`, e));\n return;\n }\n // AGE-497: every role that reads the shared checkout fails here, not just the\n // reviewer. An executor grounding a stage on a checkout that could not reach\n // its base cuts the stage branch from an older tree \u2014 the failure this used to\n // let through silently.\n if (groundingError) {\n const reason = `Harness grounding checkout is stale or unavailable: ${groundingError}`;\n console.error(`[job ${jobId}] ${reason}`);\n await callTool(RUNNER_TOKEN, \"fail_agent_job\", {\n jobId,\n runId,\n error: reason,\n }).catch((e) => console.error(`[fail ${jobId}]`, e));\n return;\n }\n\n // 2. Heartbeat the run while the session works (admin token). Self-stops on\n // CONFLICT: the turn was superseded externally (job failed + stage retried),\n // so hammering a dead run is pure noise.\n let sessionDone = false;\n const heartbeat: ReturnType<typeof setInterval> = setInterval(() => {\n void callTool(RUNNER_TOKEN, \"heartbeat_agent_job\", { jobId, runId }).catch(\n (e) => {\n if (sessionDone) {\n // The turn already finished locally (returned, threw, or timed out) \u2014\n // the run's fate is decided, so a straggler tick's CONFLICT/expiry is\n // expected; don't misreport a finished turn as superseded.\n clearInterval(heartbeat);\n return;\n }\n const msg = e instanceof Error ? e.message : String(e);\n console.error(`[heartbeat ${jobId}] ${msg}`);\n if (msg.includes(\"not the job's active run\")) {\n console.error(\n `[job ${jobId}] turn superseded externally \u2014 stopping its heartbeat.`,\n );\n clearInterval(heartbeat);\n }\n },\n );\n }, HEARTBEAT_MS);\n\n // AGE-938: the provider-reported usage for this attempt, recorded post-turn\n // via record_run_usage (runner-attested \u2014 the model's own submit cannot\n // carry a receipt it does not have).\n let turnUsage: AgentTurnUsage | null = null;\n\n try {\n // 3. Run the role session with its OWN token (turn-guard passes). Raced\n // against the turn timeout: a session that never returns fails the job\n // (recoverable) instead of wedging its pool slot forever.\n const repoNote =\n repoCwd && !isReviewer\n ? ` Your checkout is at ${repoCwd}; implement the change there with the file/bash tools, then attach evidence as artifacts.`\n : reviewerCwd\n ? ` A READ-ONLY checkout is at ${reviewerCwd} \u2014 verify the executor's claims and the current diff against the actual working tree (it holds the stage's uncommitted changes). Never modify it.`\n : planningReadCwd\n ? ` A READ-ONLY checkout is at ${planningReadCwd} \u2014 read in-repo sources from there (e.g. the PRD under prds/). Never modify it.`\n : \"\";\n // Same conventions + parallel-work block the executor gets (harness-runner\n // injects the executor's own). Only for a leg that HAS a checkout to read\n // it in; fail-soft \u2014 a context read never costs a turn.\n const contextCwd = reviewerCwd ?? planningReadCwd ?? repoCwd ?? null;\n const projectContext = contextCwd\n ? await buildProjectContext(\n { git: (dir, args) => runGit(dir, args) },\n { cwd: contextCwd, role: isReviewer ? \"reviewer\" : \"planner\" },\n ).catch(() => \"\")\n : \"\";\n const runSessionOnce = async (): Promise<string> => {\n const session = runJentrixAgent(\n `Act on Jentrix agent job ${jobId}. Your runId is ${runId}.${repoNote}${projectContext}`,\n {\n systemPrompt: isReviewer ? REVIEWER_PROMPT : PLANNER_PROMPT,\n // AGE-938: capture the provider-reported usage for THIS attempt.\n // Last report wins across in-run session retries \u2014 a retried session\n // is an init failure with zero model turns, so nothing real is lost.\n onUsage: (usage) => {\n turnUsage = usage;\n },\n maxTurns: isExecution ? EXEC_MAX_TURNS : PLAN_MAX_TURNS,\n model: execution?.model ?? turnModel,\n ...(typeof execution?.generationControls?.reasoningMode === \"string\"\n ? {\n reasoningMode: execution.generationControls.reasoningMode,\n }\n : {}),\n ...(provider === \"claude\" && process.env.STACKS_CLAUDE_EXECUTABLE\n ? { executablePath: process.env.STACKS_CLAUDE_EXECUTABLE }\n : {}),\n ...(provider === \"codex\" && process.env.STACKS_CODEX_EXECUTABLE\n ? { executablePath: process.env.STACKS_CODEX_EXECUTABLE }\n : {}),\n // The Claude executor turn gets a WRITABLE checkout; the Codex reviewer\n // turn gets the same checkout READ-ONLY (shell reads under the\n // read-only sandbox \u2014 see providers/codex.ts). Every repoReadOnly here\n // is MAP-DERIVED (M18.3 R7) \u2014 never a hand-written literal, so a role\n // the map calls read-only cannot be handed a writable tree by a leg\n // that forgot to pass the flag.\n ...(repoCwd && !isReviewer\n ? { repoCwd, repoReadOnly: repoAccess.repoReadOnly }\n : {}),\n ...(isReviewer && reviewerCwd\n ? { repoCwd: reviewerCwd, repoReadOnly: repoAccess.repoReadOnly }\n : {}),\n ...(planningReadCwd\n ? {\n repoCwd: planningReadCwd,\n repoReadOnly: repoAccess.repoReadOnly,\n }\n : {}),\n },\n {\n connection: {\n url: MCP_URL,\n token: isReviewer ? REVIEWER_TOKEN : PLANNER_TOKEN,\n },\n provider,\n },\n );\n // Orphan-safety: if the timeout wins the race, a late rejection from the\n // abandoned session must not crash the process.\n session.catch(() => {});\n let turnTimer: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n session,\n new Promise<never>((_, reject) => {\n turnTimer = setTimeout(\n () =>\n reject(\n new Error(\n `turn timed out after ${TURN_TIMEOUT_MS}ms (provider session stalled)`,\n ),\n ),\n TURN_TIMEOUT_MS,\n );\n }),\n ]);\n } finally {\n clearTimeout(turnTimer);\n }\n };\n try {\n // AGE-414: a session whose stacks MCP server failed to connect throws at\n // init with ZERO model turns burned. The claim + heartbeat are still\n // valid, so retry the SESSION in-run before failing the job \u2014 a\n // transient connect failure becomes a non-event instead of a 15-minute\n // heartbeat rot into BLOCKED.\n let summary: string;\n for (let attempt = 0; ; attempt++) {\n try {\n summary = await runSessionOnce();\n break;\n } catch (err) {\n // Retriable in-run: a tool-less session (AGE-414/423) or a transient\n // HTTP failure from the MCP endpoint (Vercel 504/502 blips killed a\n // stage-1 executor turn after its plan was already approved).\n const retriable =\n err instanceof Error &&\n (err.name === \"JentrixMcpUnavailableError\" ||\n /Streamable HTTP error|fetch failed|50[234]/.test(err.message));\n if (!retriable || attempt >= MCP_CONNECT_RETRY_DELAYS_MS.length)\n throw err;\n console.error(\n `[job ${jobId}] retriable session failure (attempt ${attempt + 1}): ${err instanceof Error ? err.message.slice(0, 120) : err} \u2014 retrying session`,\n );\n await new Promise((r) =>\n setTimeout(r, MCP_CONNECT_RETRY_DELAYS_MS[attempt]),\n );\n }\n }\n console.log(`[job ${jobId}] ${toRole}: ${summary}`);\n // Throws into the catch below, which fails the job with this reason \u2014\n // so the real cause is the recorded blockedReason instead of a heartbeat\n // expiry ~51 minutes later that names the wrong subsystem.\n await assertTurnSubmitted(jobId, runId, toRole, summary);\n } finally {\n sessionDone = true;\n }\n } catch (err) {\n // 4. Provider/agent error \u2192 fail the run (admin token); the job blocks.\n console.error(`[job ${jobId}] ${toRole} failed:`, err);\n await callTool(RUNNER_TOKEN, \"fail_agent_job\", {\n jobId,\n runId,\n error: err instanceof Error ? err.message : \"runner error\",\n }).catch((e) => console.error(`[fail ${jobId}]`, e));\n } finally {\n clearInterval(heartbeat);\n // AGE-938: record the attempt's usage AFTER the turn settled, on both\n // outcomes (a failed turn still spent tokens). Legal on the closed run;\n // write-once server-side; loss here must never affect the job.\n if (turnUsage) {\n await callTool(RUNNER_TOKEN, \"record_run_usage\", {\n jobId,\n runId,\n usage: turnUsage,\n }).catch((e) => console.error(`[usage ${jobId}]`, e));\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Harness-aware routing (H10.6). A Harness Automation STAGE rides the same\n// stage_execution loop, but its EXECUTOR turn must record stage evidence + commit\n// evidence, cross the authorize/commit/push boundary, and honor freeze by THIS\n// process. The agent.handoff webhook carries only the jobId, so we poll\n// get_agent_job to detect the `harness` block and route the executor turn to the\n// harness protocol. Plan/review turns stay on the generic path (they only operate\n// MCP \u2014 no checkout needed).\n// ---------------------------------------------------------------------------\n\n/** Run one git command in a checkout (the runner's shell-capable leg, BOUNDED to\n * STACKS_RUNNER_REPOS by the harness-runner module before it is ever called).\n * `env` carries a single-use push token to git's credential helper WITHOUT\n * placing it in argv (the token never appears in a process listing). */\nconst runGit: RunGit = (cwd, args, env) =>\n new Promise<string>((resolve, reject) => {\n const child = spawn(\"git\", args, {\n cwd,\n env: env ? { ...process.env, ...env } : process.env,\n });\n let out = \"\";\n let err = \"\";\n child.stdout.on(\"data\", (d) => (out += d));\n child.stderr.on(\"data\", (d) => (err += d));\n child.on(\"error\", reject);\n child.on(\"close\", (code) =>\n code === 0\n ? resolve(out.trim())\n : reject(new Error(`git ${args[0]} failed (${code}): ${err.trim()}`)),\n );\n });\n\n/**\n * S1 documentation commit guard, PRODUCTION wiring. Runs `pnpm docs:sync` /\n * `pnpm docs:check` in the managed verification container over the stage worktree.\n * `sync` regenerates the checked-in\n * generated docs before the reviewer turn; `check` reports whether a public\n * contract is stale (non-zero exit) so the runner blocks the local commit via the\n * server's checksum-bound DOCUMENTATION_REVIEW finding. Adds NO dependency \u2014 pnpm\n * is already the toolchain.\n */\nconst touchesPublicContract = (changedFiles: readonly string[]): boolean =>\n changedFiles.some(\n (file) =>\n file.startsWith(\"src/lib/mcp/\") ||\n file === \"scripts/tool-workflows.ts\" ||\n file === \"docs/agent-platform.md\" ||\n /^src\\/server\\/.+\\/schemas\\.ts$/.test(file),\n );\n\nconst docsGuard: HarnessRunnerDeps[\"docsGuard\"] = {\n sync: async (cwd, changedFiles) => {\n // Internal UI/test changes cannot move generated public-contract docs \u2014\n // skip the sandboxed regeneration for them; contract changes retain it.\n if (!touchesPublicContract(changedFiles)) return;\n const result = await runManagedVerificationCommand({\n cwd,\n command: \"pnpm docs:sync\",\n timeoutMs: 900_000,\n });\n if (result.exitCode !== 0) {\n throw new Error(\n `docs:sync failed (${result.exitCode}): ${(result.stderr || result.stdout).trim()}`,\n );\n }\n },\n check: async (cwd, changedFiles) => {\n if (!touchesPublicContract(changedFiles)) {\n return {\n ok: true,\n staleDocs: [],\n output:\n \"No public-contract changes in the diff \u2014 documentation guard passed.\",\n };\n }\n const result = await runManagedVerificationCommand({\n cwd,\n command: \"pnpm docs:check\",\n timeoutMs: 900_000,\n });\n const output = `${result.stdout}${result.stderr}`;\n const staleDocs: string[] = [];\n if (/tool-registry\\.generated\\.json/.test(output))\n staleDocs.push(\"src/lib/mcp/tool-registry.generated.json\");\n if (/agent-platform\\.md/.test(output))\n staleDocs.push(\"docs/agent-platform.md\");\n return { ok: result.exitCode === 0, staleDocs, output };\n },\n};\n\n// D5 (2026-07): the raw-token push/PR seams (brokerPushCredential /\n// createPullRequest, always null-wired here) were DELETED \u2014 push/PR egress is\n// the sandbox-side broker (M12.5) or a fail-closed defer to the governed\n// delivery path / an operator.\n\n// M12.1: the reference runner executes every agent turn THROUGH an\n// ExecutionBackend (host driver by default \u2192 identical Jentrix-side records;\n// STACKS_EXECUTION_DRIVER=docker runs the turn in an ephemeral, resource-limited,\n// deny-by-default-egress container). The backend enforces the turn's wall-time\n// budget, so a stalled turn is killed with a structured failure rather than hanging.\nconst { backend: executionBackend, kind: executionKind } =\n makeExecutionBackend();\nconsole.log(`workflow-runner: execution driver = ${executionKind}`);\n\n/**\n * Read FRESH Jentrix state to decide whether the attempt that owns a colliding\n * stage branch is still live, is confirmed superseded, or is unprovable (Stage 3\n * ownership check). Uses the runner's ADMIN token to read get_agent_job for BOTH\n * the owning attempt and the current one:\n * \u2022 LIVE \u2014 the old job has an active run, a non-terminal phase, or a pending\n * commit/merge gate (a commit continuation) \u2192 conflict, change nothing.\n * \u2022 SUPERSEDED \u2014 the old job is terminal (DONE/CANCELLED/BLOCKED, incl. a lease\n * takeover that blocked it) with NO active run and NO pending commit, AND the\n * current attempt is a NEWER job for the SAME stage \u2192 detach + reuse the branch.\n * \u2022 UNPROVABLE \u2014 anything unreadable or unconfirmable \u2192 fail closed.\n */\nconst readOwnerState: OwnerStateReader = async (owner, current) => {\n // Reaching here means the worktree manager found the resolved stage branch\n // already checked out by ANOTHER attempt \u2014 a branch-ownership conflict. Count\n // every evaluation for telemetry (the verdict below decides live/superseded/\n // unprovable; all three are collisions that had to be adjudicated).\n branchOwnershipConflicts += 1;\n let oldJob: Record<string, unknown>;\n try {\n oldJob = await callTool(RUNNER_TOKEN, \"get_agent_job\", {\n jobId: owner.jobId,\n });\n } catch (e) {\n return {\n status: \"unprovable\",\n detail: `get_agent_job(${owner.jobId}) failed: ${e instanceof Error ? e.message : String(e)}`,\n };\n }\n const phase = String(oldJob.phase ?? \"\");\n const hasActiveRun = oldJob.activeRunId != null;\n const terminal = [\"DONE\", \"CANCELLED\", \"BLOCKED\"].includes(phase);\n const approvals = Array.isArray(oldJob.approvals)\n ? (oldJob.approvals as Array<Record<string, unknown>>)\n : [];\n const pendingCommit = approvals.some(\n (a) =>\n a?.status === \"PENDING\" && (a?.kind === \"COMMIT\" || a?.kind === \"MERGE\"),\n );\n if (hasActiveRun || !terminal || pendingCommit) {\n const why = hasActiveRun\n ? \"with an active run\"\n : pendingCommit\n ? \"with a pending commit gate\"\n : \"still in flight\";\n return {\n status: \"live\",\n detail: `owning job ${owner.jobId} is ${phase} ${why}`,\n };\n }\n // Terminal, no active run, no pending commit continuation. Confirm a NEWER stage\n // job (this current attempt) replaced it \u2014 else we can't prove supersession.\n let curJob: Record<string, unknown>;\n try {\n curJob = await callTool(RUNNER_TOKEN, \"get_agent_job\", {\n jobId: current.jobId,\n });\n } catch (e) {\n return {\n status: \"unprovable\",\n detail: `get_agent_job(${current.jobId}) failed: ${e instanceof Error ? e.message : String(e)}`,\n };\n }\n const curStageId =\n (curJob.harness as { stageId?: string } | null | undefined)?.stageId ??\n null;\n const sameStage = curStageId === owner.stageId;\n const newer =\n typeof curJob.createdAt === \"string\" && typeof oldJob.createdAt === \"string\"\n ? curJob.createdAt > oldJob.createdAt\n : true;\n if (sameStage && newer) {\n return {\n status: \"superseded\",\n detail: `owning job ${owner.jobId} is ${phase} with no active run or pending commit; replaced by newer job ${current.jobId}`,\n } satisfies OwnerVerdict;\n }\n return {\n status: \"unprovable\",\n detail: `owning job ${owner.jobId} is ${phase}, but the current attempt ${current.jobId} is not a confirmed superseding successor (stage ${curStageId ?? \"?\"} vs ${owner.stageId})`,\n };\n};\n\n// Stage 3: the per-job worktree manager over the parsed repo entries + the runner's\n// git seam + the fresh-Jentrix-state owner reader. This is the PRODUCTION wiring of\n// the executor's per-job worktree; the smoke tests inject a deterministic fake.\nconst worktreeManager = new RunnerWorktreeManager(\n REPO_ENTRIES,\n runGit,\n readOwnerState,\n { log: (msg) => console.log(msg) },\n);\n\nconst harnessDeps: HarnessRunnerDeps = {\n callTool,\n worktree: worktreeManager,\n // S1 documentation commit guard: docs:sync before final review, docs:check\n // before authorizing the local commit (a stale public contract blocks it).\n docsGuard,\n preflightVerification: preflightManagedVerification,\n // HAI S3: the runner executes the stage's DECLARED verification commands\n // itself (foreground, timed) to mint attested TEST_EVIDENCE. The command\n // text is gate-approved stage-plan content and runs inside an ephemeral,\n // env-scrubbed, deny-egress container over the stage worktree. A startup\n // failure reports exitCode 127 so the attestation records the honest outcome.\n runCommand: runManagedVerificationCommand,\n runAgentTurn: ({\n prompt,\n systemPrompt,\n repoCwd,\n repoReadOnly,\n signal,\n runnerOwnsSubmissions,\n execution,\n }) =>\n runTurnThroughBackend(executionBackend, executionKind, {\n prompt,\n systemPrompt,\n repoCwd,\n ...(runnerOwnsSubmissions ? { runnerOwnsSubmissions } : {}),\n // M18.3 R7: forwarded from the dispatch role's map entry \u2014 the providers\n // enforce it (claude withholds write/edit tools, codex sandboxes the\n // shell read-only). Undefined for the executor lane = today's behavior.\n ...(repoReadOnly ? { repoReadOnly } : {}),\n maxTurns:\n typeof execution?.generationControls?.maxTurns === \"number\"\n ? execution.generationControls.maxTurns\n : EXEC_MAX_TURNS,\n model: execution?.model,\n ...(typeof execution?.generationControls?.reasoningMode === \"string\"\n ? { reasoningMode: execution.generationControls.reasoningMode }\n : {}),\n ...(execution?.runtimeAdapterKey === \"claude\" &&\n process.env.STACKS_CLAUDE_EXECUTABLE\n ? { executablePath: process.env.STACKS_CLAUDE_EXECUTABLE }\n : {}),\n ...(execution?.runtimeAdapterKey === \"codex\" &&\n process.env.STACKS_CODEX_EXECUTABLE\n ? { executablePath: process.env.STACKS_CODEX_EXECUTABLE }\n : {}),\n connection: { url: MCP_URL, token: PLANNER_TOKEN },\n provider: execution?.runtimeAdapterKey ?? agentProvider(),\n signal,\n }),\n git: runGit,\n // M12.5 (AGE-175): when STACKS_SANDBOX_BROKER_ENABLED=1 + a grant transport is\n // configured, the push/PR egress goes THROUGH the sandbox-side broker (which owns\n // credential injection) and this runner never holds the raw token. Undefined by\n // default \u21D2 push/PR defers fail-closed to the governed path / an operator (D5).\n sandboxEgress: makeSandboxEgress(),\n sleep: (ms) => delay(ms),\n};\n\nconst harnessCfg: HarnessRunnerConfig = {\n tokens: { runner: RUNNER_TOKEN, planner: PLANNER_TOKEN },\n repos: REPOS,\n evidenceTier:\n process.env.STACKS_VERIFICATION_EVIDENCE_TIER ??\n DEFAULT_RUNNER_EVIDENCE_TIER,\n heartbeatMs: HEARTBEAT_MS,\n commitPollMs: 10_000,\n commitPollMax: 30,\n // M12.3b (AGE-173): present this runner's build-stamped revision on the harness\n // stage claim \u2014 the SAME single source of truth the generic drive() claim uses \u2014\n // so an incompatible harness worker is refused fail-closed by the control plane.\n revision: resolveRevisionStamp(),\n executorBinding: ROLE_BINDINGS?.executor,\n mintClaimCredential,\n stopping: () => shutdownRequested,\n log: (msg) => console.log(msg),\n};\n\n// ---------------------------------------------------------------------------\n// S4 pools + telemetry. BOTH the webhook and the poll input submit to these SAME\n// two pool objects, so the queued/running job-id dedup registry SPANS both\n// inputs: a webhook delivery and a poll delivery for one job collapse before\n// consuming a slot in either pool. The server-side claim CAS remains the FINAL\n// ownership guard \u2014 these pools only avoid wasting a slot on a peer-owned job.\n// ---------------------------------------------------------------------------\nfunction poolTelemetry(): Record<string, number> {\n const now = Date.now();\n let oldestJobAgeMs = 0;\n for (const at of jobEnqueuedAt.values()) {\n oldestJobAgeMs = Math.max(oldestJobAgeMs, now - at);\n }\n const a = agentPool.snapshot();\n const c = commitPool.snapshot();\n return {\n agentQueueDepth: a.queueDepth,\n agentActive: a.active,\n agentMax: a.effectiveMax,\n agentInflight: a.inflight,\n commitQueueDepth: c.queueDepth,\n commitActive: c.active,\n commitMax: c.effectiveMax,\n commitInflight: c.inflight,\n oldestJobAgeMs,\n claimToExecMs: lastClaimToExecMs,\n branchOwnershipConflicts,\n };\n}\nfunction emitPoolTelemetry(reason: string): void {\n console.log(\n `[runner-pool] ${JSON.stringify({ reason, ...poolTelemetry() })}`,\n );\n}\n\nconst agentPool = new BoundedDedupPool(\n \"agent-turn\",\n MAX_CONCURRENT_JOBS,\n AGENT_JOBS_CONFIGURED,\n {\n watchdogMs: WATCHDOG_MS,\n log: (m) => console.log(m),\n onStart: (jobId, queueLatencyMs) => {\n lastClaimToExecMs = queueLatencyMs;\n emitPoolTelemetry(`start:${jobId}`);\n },\n onSettle: () => emitPoolTelemetry(\"settle\"),\n },\n);\nconst commitPool = new BoundedDedupPool(\n \"commit\",\n MAX_CONCURRENT_COMMITS,\n COMMIT_JOBS_CONFIGURED,\n {\n watchdogMs: WATCHDOG_MS,\n log: (m) => console.log(m),\n onStart: (jobId, queueLatencyMs) => {\n lastClaimToExecMs = queueLatencyMs;\n emitPoolTelemetry(`commit-start:${jobId}`);\n },\n onSettle: () => emitPoolTelemetry(\"commit-settle\"),\n },\n);\n\n/**\n * Submit `work` for `jobId` to `pool`. Records the enqueue time for job-age\n * telemetry and clears it on TRUE settle (so a watchdog-detached orphan keeps\n * ageing until it really finishes). Returns false when the pool collapsed a\n * duplicate delivery (already queued/running/watchdog-detached).\n */\nfunction submitJob(\n pool: BoundedDedupPool,\n jobId: string,\n work: () => Promise<void>,\n): boolean {\n if (shutdownRequested) return false;\n const enqueuedAt = Date.now();\n const accepted = pool.submit(jobId, async () => {\n if (shutdownRequested) return;\n try {\n await work();\n } finally {\n jobEnqueuedAt.delete(jobId);\n }\n });\n if (accepted) {\n jobEnqueuedAt.set(jobId, enqueuedAt);\n emitPoolTelemetry(`enqueue:${jobId}`);\n } else {\n emitPoolTelemetry(`dedupe:${jobId}`);\n }\n return accepted;\n}\n\n/**\n * Resolve the current bearer token for each role from the mode-selected provider\n * and mirror the two harness tokens into harnessCfg. The provider caches +\n * refreshes short-lived tokens, so calling this at each drive keeps a\n * long-running managed / self-hosted server's tokens fresh; the deprecated\n * legacy-PAT path just returns the static tokens (a cheap no-op). Every generic\n * drive() call site reads the module-level RUNNER_TOKEN / PLANNER_TOKEN /\n * REVIEWER_TOKEN at use-time, so a refresh here is picked up by the next call.\n */\nasync function refreshRoleTokens(\n opts: { legStart?: boolean } = {},\n): Promise<void> {\n // Leg start: force FRESH planner/reviewer tokens (full 1h TTL) \u2014 the agent\n // session embeds its role token in MCP headers for the whole leg, and a mint\n // ROTATES the bearer server-side, so the leg must start fresh and nothing\n // may re-mint that role until the leg ends. Safe at agentMax=1 (one agent\n // leg in flight); a concurrency raise needs per-leg tokens instead.\n if (opts.legStart) {\n authProvider.invalidate?.(\"planner\");\n authProvider.invalidate?.(\"reviewer\");\n }\n const [runner, planner, reviewer] = await Promise.all([\n authProvider.tokenFor(\"runner\"),\n authProvider.tokenFor(\"planner\"),\n authProvider.tokenFor(\"reviewer\"),\n ]);\n RUNNER_TOKEN = runner;\n PLANNER_TOKEN = planner;\n REVIEWER_TOKEN = reviewer;\n // AGE-899: record BEFORE anything can rotate them again, so a bearer captured\n // by an in-flight call stays attributable to its role after it is superseded.\n rememberTokenRole(runner, \"runner\");\n rememberTokenRole(planner, \"planner\");\n rememberTokenRole(reviewer, \"reviewer\");\n // harnessCfg.tokens was captured at module load \u2014 refresh it in place so the\n // harness protocol reads the current short-lived tokens.\n harnessCfg.tokens.runner = RUNNER_TOKEN;\n harnessCfg.tokens.planner = PLANNER_TOKEN;\n}\n\n/**\n * Route one actionable handoff. A harness stage EXECUTOR turn goes to the harness\n * protocol; everything else (plan/review turns, and non-harness jobs) stays on the\n * generic M7 `drive()`. Detection polls get_agent_job (the only place the harness\n * binding is surfaced).\n */\nasync function driveTurn(\n jobId: string,\n toRole: string,\n phase: string,\n repoOwnerName: string | undefined,\n): Promise<void> {\n // Refresh short-lived role tokens before touching MCP \u2014 leg start forces\n // FRESH planner/reviewer tokens so the session's embedded bearer spans the\n // whole leg (mints rotate; see refreshRoleTokens).\n await refreshRoleTokens({ legStart: true });\n const currentJob =\n toRole === \"REVIEWER\" || EXECUTION_PHASES.has(phase)\n ? await getHarnessStageJob(harnessDeps, harnessCfg, jobId).catch(\n () => null,\n )\n : null;\n if (EXECUTION_PHASES.has(phase)) {\n const job = currentJob;\n if (job?.harness) {\n const { disposition } = await driveHarnessStage(harnessDeps, harnessCfg, {\n jobId,\n });\n console.log(`[harness ${jobId}] ${disposition}`);\n return;\n }\n }\n // A harness EXECUTION reviewer gets the stage's WORKTREE read-only (Stage 3):\n // adopt the executor's worktree so the reviewer verifies against the actual\n // uncommitted change. For that turn the worktree is REQUIRED \u2014 if it can't be\n // adopted, drive() FAILS CLOSED rather than reviewing against the shared checkout\n // (which lacks the stage's uncommitted changes). A PLAN reviewer needs none:\n // the stage worktree is only created at the first execution turn\n // (ensureExecutionCwd), so requiring adoption at PLAN_REVIEW fails closed on a\n // legitimately absent tree (AGE-350, found live in the M15 run).\n let reviewerWorktreeCwd: string | undefined;\n let reviewerWorktreeRequired = false;\n let groundingError: string | undefined;\n if (toRole === \"REVIEWER\" && phase === \"EXECUTION_REVIEW\") {\n const job = currentJob;\n const h = job?.harness;\n if (h?.repo && REPOS[h.repo]) {\n // This IS a harness stage reviewer \u2014 the read-only stage worktree is\n // mandatory; a failed adoption must not silently degrade to the checkout.\n reviewerWorktreeRequired = true;\n const branch = resolveStageBranch(h);\n reviewerWorktreeCwd =\n (await worktreeManager\n .adoptExecutionCwd({\n repo: h.repo,\n jobId,\n stageId: h.stageId,\n branch,\n })\n .catch(() => null)) ?? undefined;\n }\n }\n // AGE-497: refresh + ASSERT the shared checkout for every leg that touches it,\n // not just the reviewer's. `refreshGroundingCheckout` fetches, fast-forwards,\n // and throws when HEAD did not reach the base \u2014 it would have caught the stale\n // m14 clone on day one, but it only ever ran on the reviewer leg. The executor\n // is the leg that CUTS STAGE BRANCHES from this checkout, so it is the one that\n // most needs the base to be real. A reviewer holding its own per-job worktree\n // is the one case that does not read the shared checkout at all.\n if (\n currentJob?.harnessRun &&\n !(toRole === \"REVIEWER\" && reviewerWorktreeRequired)\n ) {\n const run = currentJob.harnessRun;\n const repo = run.repo ?? repoOwnerName;\n if (!repo || !REPOS[repo]) {\n groundingError = repo\n ? `no STACKS_RUNNER_REPOS entry for ${repo}`\n : \"harness run has no repository\";\n } else {\n try {\n await worktreeManager.refreshGroundingCheckout(\n repo,\n run.baseBranch ?? \"main\",\n );\n } catch (e) {\n groundingError = e instanceof Error ? e.message : String(e);\n }\n }\n }\n await drive(\n jobId,\n toRole,\n phase,\n repoOwnerName,\n reviewerWorktreeCwd,\n reviewerWorktreeRequired,\n groundingError,\n );\n}\n\nconst server = createServer((req, res) => {\n if (req.method !== \"POST\") {\n res.writeHead(405).end();\n return;\n }\n let rawBody = \"\";\n req.on(\"data\", (chunk) => (rawBody += chunk));\n req.on(\"end\", () => {\n // No secret configured (poll mode): the webhook leg is disabled outright \u2014\n // an HMAC with an empty key would otherwise \"verify\" for anyone who knows\n // the scheme.\n if (!SECRET) {\n res.writeHead(503).end(\"webhook disabled (no secret; poll mode)\");\n return;\n }\n if (!verifySignature(req.headers, rawBody)) {\n res.writeHead(401).end(\"bad signature\");\n return;\n }\n const event = req.headers[\"x-stacks-event\"];\n const body = JSON.parse(rawBody) as {\n data?: {\n jobId?: string;\n toRole?: string;\n turn?: string;\n phase?: string;\n repoOwnerName?: string;\n };\n };\n const jobId = body.data?.jobId;\n const toRole = body.data?.toRole ?? body.data?.turn;\n const phase = body.data?.phase ?? \"\";\n const repoOwnerName = body.data?.repoOwnerName;\n\n // Ack fast \u2014 Jentrix retries failed deliveries; the run can take a while.\n res.writeHead(202).end(\"queued\");\n\n // A harness stage is validated LATER than its execution turn (after the\n // reviewer + the human FINAL_ACCEPTANCE gate). Jentrix emits\n // `harness.stage_validated` (carrying the stage's jobId) when the commit\n // boundary is ready \u2014 react by driving the post-validation commit boundary.\n if (event === \"harness.stage_validated\" && jobId) {\n // Post-validation commit continuation \u2192 the DEDICATED commit pool (kept\n // low-latency even when the agent-turn pool is full). Dedup spans webhook +\n // poll: a poll commit-watch for the same jobId collapses on this pool.\n submitJob(commitPool, jobId, async () => {\n // Refresh short-lived role tokens before the commit boundary.\n await refreshRoleTokens();\n const { disposition } = await driveHarnessStageCommit(\n harnessDeps,\n harnessCfg,\n { jobId },\n );\n console.log(`[harness commit ${jobId}] ${disposition}`);\n });\n return;\n }\n\n // Only agent turns are actionable here; HUMAN turns wait for the gate UI.\n if (event !== \"agent.handoff\" || !jobId || !toRole) return;\n if (toRole !== \"PLANNER\" && toRole !== \"REVIEWER\") return;\n // Agent turn \u2192 the bounded agent-turn pool. A retried/duplicate delivery or a\n // racing poll drive for the SAME jobId collapses before consuming a slot.\n submitJob(agentPool, jobId, () =>\n driveTurn(jobId, toRole, phase, repoOwnerName),\n );\n });\n});\n\n// ---------------------------------------------------------------------------\n// Poll mode (STACKS_POLL_MS > 0) \u2014 the webhook-less fallback. Each tick:\n// 1. list_agent_jobs per agent-turn phase \u2192 submit PLANNER/REVIEWER turns to\n// the SAME bounded agentPool the webhook path uses (shared job-id dedup, so\n// a poll and a webhook drive for one job collapse; get_agent_job re-reads\n// turn/phase fresh so a stale list row never mis-drives; claim_agent_job's\n// server-side CAS is the ultimate double-claim guard).\n// 2. Jobs whose executor turn we drove \u2014 plus jobs parked at the human\n// FINAL_ACCEPTANCE gate \u2014 are watched for the post-validation commit\n// boundary and submitted to the DEDICATED commitPool, so a commit-gate wait\n// can never block the next agent turn (which may be the very reviewer that\n// unblocks the gate).\n// ---------------------------------------------------------------------------\n\nconst AGENT_TURN_PHASES = [\n \"PLAN_DRAFTING\",\n \"PLAN_REVIEW\",\n \"PLAN_REVISION\",\n \"EXECUTING\",\n \"EXECUTION_REVIEW\",\n \"EXECUTION_REVISION\",\n] as const;\n\n// Jobs parked awaiting the post-validation commit boundary \u2014 a PERSISTENT watch\n// keyed by jobId, carrying the stage coordinates once known (null until the\n// first context read). F5 (AGE-502): the watch is STATUS-SCOPED \u2014 each tick\n// reads every watched run's stage statuses in ONE list_harness_stages call and\n// drives the commit boundary ONLY for stages actually at VALIDATED/COMMIT_GATE/\n// COMMITTED. A stage still EXECUTING used to be blind-driven every tick\n// (multi-call, \"not committable\"), which is what filled runner.log with\n// sub-second commit-start/settle cycles and burned the 60/min token budget.\nconst commitWatch = new Map<\n string,\n { harnessRunId: string; stageId: string } | null\n>();\n// AGE-415: ids dropped for TERMINAL reasons (committed, run cancelled/archived,\n// stage blocked/skipped, not a harness job, unmapped repo). pollTick re-adds\n// every FINAL_ACCEPTANCE_GATE job each tick \u2014 a zombie job of a cancelled run\n// sits in that phase forever, so without this the watch busy-loops on it.\nconst commitWatchDead = new Set<string>();\n// Stage statuses the commit boundary acts on; everything else is a silent keep\n// (the stage may still validate) or a dead drop (it never will).\nconst COMMIT_ADJACENT_STATUSES = new Set([\n \"VALIDATED\",\n \"COMMIT_GATE\",\n \"COMMITTED\",\n]);\nconst DEAD_STAGE_STATUSES = new Set([\"BLOCKED\", \"SKIPPED\"]);\n\n/** Jobs listed for one phase (first page \u2014 actionable turns are few). */\nasync function jobsInPhase(\n workspaceId: string,\n phase: string,\n): Promise<{ id: string; turn: string }[]> {\n // AGE-835: per-phase isolation \u2014 under a degraded network one failed list\n // used to abort the WHOLE tick (and sequential retry ladders across the six\n // phase lists could outlive the tick watchdog), so no phase ever got\n // claimed. A phase whose list fails is skipped THIS tick; the others proceed.\n try {\n const res = await callTool(RUNNER_TOKEN, \"list_agent_jobs\", {\n workspaceId,\n phase,\n });\n return (res.jobs as { id: string; turn: string }[] | undefined) ?? [];\n } catch (err) {\n console.error(\n `[poll] list ${phase} failed (skipping this tick): ${err instanceof Error ? err.message.slice(0, 120) : String(err)}`,\n );\n return [];\n }\n}\n\n/** Submit one watched job's commit-boundary drive to the commit pool (the pool\n * bounds concurrency + collapses a re-submit while one is still in flight). */\nfunction driveWatchedCommit(jobId: string): void {\n submitJob(commitPool, jobId, async () => {\n if (!commitWatch.has(jobId)) return;\n // Refresh short-lived role tokens before the commit boundary \u2014 the commit\n // pool runs independently of the agent-turn pool, so it must re-provision.\n await refreshRoleTokens();\n try {\n const { disposition } = await driveHarnessStageCommit(\n harnessDeps,\n harnessCfg,\n { jobId },\n );\n if (\n disposition.startsWith(\"committed\") ||\n disposition === \"not_a_harness_stage_job\" ||\n // AGE-410: a CANCELLED/ARCHIVED run can never authorize the commit.\n disposition.startsWith(\"run terminal\") ||\n /stage (BLOCKED|SKIPPED)/.test(disposition)\n ) {\n commitWatch.delete(jobId);\n commitWatchDead.add(jobId);\n }\n if (disposition !== \"not_a_harness_stage_job\") {\n console.log(`[poll commit ${jobId}] ${disposition}`);\n }\n } catch (err) {\n // An unmapped repo can never succeed \u2014 stop watching; anything else\n // (transient network, freeze) stays watched for the next tick.\n if (err instanceof Error && err.name === \"UnmappedRepoError\") {\n commitWatch.delete(jobId);\n commitWatchDead.add(jobId);\n }\n throw err;\n }\n });\n}\n\n/** F5 (AGE-502): the status-scoped commit-watch pump. Learns each watched\n * job's stage coordinates once, then reads every watched run's stage statuses\n * in ONE list call per tick and drives ONLY commit-adjacent stages. Paced\n * inherently to the poll interval (this runs once per tick; the commit pool's\n * dedup collapses re-submits while a drive is still in flight). */\nasync function pumpCommitWatch(): Promise<void> {\n // Learn missing stage coordinates (one get_agent_job, once per job ever).\n for (const [jobId, ctx] of [...commitWatch]) {\n if (ctx) continue;\n const job = await getHarnessStageJob(harnessDeps, harnessCfg, jobId).catch(\n () => null,\n );\n if (!job) continue; // transient read failure \u2014 keep watched, retry next tick\n if (!job.harness) {\n // Not a harness stage job \u2014 it will never have a commit boundary.\n commitWatch.delete(jobId);\n commitWatchDead.add(jobId);\n continue;\n }\n commitWatch.set(jobId, {\n harnessRunId: job.harness.harnessRunId,\n stageId: job.harness.stageId,\n });\n }\n // One status list per watched run.\n const runIds = new Set(\n [...commitWatch.values()].flatMap((c) => (c ? [c.harnessRunId] : [])),\n );\n const statusesByRun = new Map<string, Map<string, string>>();\n for (const runId of runIds) {\n const statuses = await listStageStatuses(\n harnessDeps,\n harnessCfg,\n runId,\n ).catch(() => null);\n if (statuses) statusesByRun.set(runId, statuses);\n }\n for (const [jobId, ctx] of [...commitWatch]) {\n if (!ctx) continue; // coordinates unknown this tick\n const statuses = statusesByRun.get(ctx.harnessRunId);\n if (!statuses) continue; // list failed \u2014 keep watched, retry next tick\n const status = statuses.get(ctx.stageId);\n if (status === undefined || DEAD_STAGE_STATUSES.has(status)) {\n // Archived/missing or terminally parked \u2014 the boundary will never open\n // for this attempt (a retry mints a NEW job that re-enters the watch).\n commitWatch.delete(jobId);\n commitWatchDead.add(jobId);\n continue;\n }\n if (!COMMIT_ADJACENT_STATUSES.has(status)) continue; // silent keep\n driveWatchedCommit(jobId);\n }\n}\n\n/** AGE-923: the tick's stall detector. 180s of NO reported progress \u2014 not 180s\n * of work \u2014 is a wedge. Every await in the tick path reports its step. */\nconst tickWatchdog = createStallWatchdog({ stallMs: 180_000 });\n\nasync function pollTick(workspaceId: string): Promise<void> {\n for (const phase of AGENT_TURN_PHASES) {\n const rows = await jobsInPhase(workspaceId, phase);\n tickWatchdog.progress(`jobsInPhase(${phase})`);\n for (const row of rows) {\n if (row.turn !== \"PLANNER\" && row.turn !== \"REVIEWER\") continue;\n // Already queued/running in the shared registry \u2192 skip the fresh re-read;\n // submitJob() below is the authoritative dedup (a webhook racing this poll\n // read collapses on submit).\n if (agentPool.has(row.id)) continue;\n // Re-read the full job fresh: the list row can be a tick stale, and the\n // full view carries repoOwnerName + the harness block for routing.\n const job = await getHarnessStageJob(\n harnessDeps,\n harnessCfg,\n row.id,\n ).catch(() => null);\n tickWatchdog.progress(`getHarnessStageJob(${row.id})`);\n if (!job || (job.turn !== \"PLANNER\" && job.turn !== \"REVIEWER\")) continue;\n // F6 (AGE-503): a job with an ACTIVE run cannot be claimed \u2014 every claim\n // would CONFLICT (\"it has an active run\"). A live peer owns it, or a\n // zombie run is awaiting sweep expiry; either way the next tick\n // re-evaluates from fresh state. This ends the identical-claim storms\n // (10+ CONFLICTs per job per tick in runner.log). Never blind-claim.\n if (job.activeRunId) continue;\n const isExecution = EXECUTION_PHASES.has(job.phase);\n const harnessJob = job.harness;\n if (!pollScopeAllows(POLL_HARNESS_RUN_ID, jobHarnessRunId(job))) continue;\n submitJob(agentPool, job.id, () =>\n driveTurn(\n job.id,\n job.turn,\n job.phase,\n job.repoOwnerName ?? undefined,\n ).finally(() => {\n // An executor turn on a harness stage will need its commit boundary\n // driven once validated (reviewer + human gate happen in between).\n if (isExecution && harnessJob && !commitWatchDead.has(job.id))\n commitWatch.set(job.id, {\n harnessRunId: harnessJob.harnessRunId,\n stageId: harnessJob.stageId,\n });\n }),\n );\n }\n }\n // Harness jobs parked at the human FINAL_ACCEPTANCE gate: once a human\n // approves, the stage validates with NO further handoff a poller could see \u2014\n // watch them for the commit boundary (non-harness jobs settle out of the\n // watch on their first \"not_a_harness_stage_job\").\n const gateRows = await jobsInPhase(workspaceId, \"FINAL_ACCEPTANCE_GATE\");\n tickWatchdog.progress(\"jobsInPhase(FINAL_ACCEPTANCE_GATE)\");\n for (const row of gateRows) {\n if (commitWatchDead.has(row.id)) continue;\n if (POLL_HARNESS_RUN_ID) {\n const job = await getHarnessStageJob(\n harnessDeps,\n harnessCfg,\n row.id,\n ).catch(() => null);\n tickWatchdog.progress(`getHarnessStageJob(gate ${row.id})`);\n if (!job || !pollScopeAllows(POLL_HARNESS_RUN_ID, jobHarnessRunId(job)))\n continue;\n // Store the coordinates we just read (saves pumpCommitWatch a learn call).\n if (!commitWatch.get(row.id) && job.harness) {\n commitWatch.set(row.id, {\n harnessRunId: job.harness.harnessRunId,\n stageId: job.harness.stageId,\n });\n continue;\n }\n }\n if (!commitWatch.has(row.id)) commitWatch.set(row.id, null);\n }\n // AGE-835: a harness job that reached DONE while no runner was watching (a\n // wedged poll loop, or a restart between the acceptance gate and the commit)\n // leaves its stage parked at VALIDATED/COMMIT_GATE with nobody driving the\n // boundary \u2014 the FINAL_ACCEPTANCE_GATE sweep above never re-discovers it and\n // the harness.stage_validated webhook leg is disabled in poll mode. Sweep the\n // first page of DONE jobs (newest-first) into the same watch; non-harness and\n // out-of-scope rows are dead-marked so each costs one read per process, and\n // pumpCommitWatch's status-scoping ignores stages that are not commit-adjacent.\n const doneRows = await jobsInPhase(workspaceId, \"DONE\");\n tickWatchdog.progress(\"jobsInPhase(DONE)\");\n for (const row of doneRows) {\n if (commitWatchDead.has(row.id) || commitWatch.has(row.id)) continue;\n const job = await getHarnessStageJob(harnessDeps, harnessCfg, row.id).catch(\n () => null,\n );\n tickWatchdog.progress(`getHarnessStageJob(done ${row.id})`);\n if (!job) continue;\n if (\n !job.harness ||\n !pollScopeAllows(POLL_HARNESS_RUN_ID, jobHarnessRunId(job))\n ) {\n commitWatchDead.add(row.id);\n continue;\n }\n commitWatch.set(row.id, {\n harnessRunId: job.harness.harnessRunId,\n stageId: job.harness.stageId,\n });\n }\n await pumpCommitWatch();\n tickWatchdog.progress(\"pumpCommitWatch\");\n}\n\n/** Resolve the single workspace the runner token is pinned to (poll + once). */\nasync function resolvePollWorkspace(): Promise<string> {\n const res = await callTool(RUNNER_TOKEN, \"list_workspaces\", {});\n const workspaces = (res.workspaces as { id: string }[] | undefined) ?? [];\n const workspaceId = workspaces[0]?.id;\n if (!workspaceId) {\n console.error(\"[poll] runner token sees no workspace \u2014 cannot poll.\");\n process.exit(1);\n }\n if (workspaces.length > 1) {\n console.error(\n `[poll] runner token sees ${workspaces.length} workspaces \u2014 polling ${workspaceId}. Pin the token to one workspace.`,\n );\n }\n return workspaceId;\n}\n\n/** One watchdog-raced tick, shared by the immortal poll loop and once mode.\n * AGE-835: the loop wedged twice on a tick that HUNG instead of throwing (a\n * stalled auth fetch serialized every later obtain behind it; an MCP connect\n * had no timeout). Tick work is reads + pool submits, so abandoning a stuck\n * tick loses nothing.\n * AGE-923: the watchdog supervises PROGRESS, not total elapsed \u2014 see\n * lib/tick-watchdog.ts for why a flat budget fired on ticks that then\n * succeeded. Every await below reports the step it finished. */\nasync function tickWithWatchdog(workspaceId: string): Promise<void> {\n await tickWatchdog.guard(\n (async () => {\n // Refresh short-lived role tokens each tick (no-op for legacy PATs).\n await refreshRoleTokens();\n tickWatchdog.progress(\"refreshRoleTokens\");\n await pollTick(workspaceId);\n })(),\n );\n}\n\n/** AGE-836 once mode: tick until the workspace has nothing for us AND nothing\n * is in flight \u2014 two consecutive quiet ticks; lib/run-once.ts explains why\n * `inflight` (a watchdog-detached orphan still counts) and why two \u2014 then\n * exit 0. launchd's StartInterval provides the cadence, the sweep (AGE-292)\n * the convergence: an exit at any point strands nothing. A tick that FAILS\n * while the pools sit idle also walks toward exit \u2014 under a dead network the\n * right move is a fresh process in one respawn interval, not a wedged loop. */\nasync function runOnce(workspaceId: string): Promise<never> {\n console.log(\n `[once] dispatch mode: workspace ${workspaceId}, tick ${ONCE_TICK_MS}ms${\n POLL_HARNESS_RUN_ID ? `, scope harness ${POLL_HARNESS_RUN_ID}` : \"\"\n }`,\n );\n let idleTicks = 0;\n for (;;) {\n if (shutdownRequested) await finishShutdown();\n try {\n await tickWithWatchdog(workspaceId);\n } catch (err) {\n console.error(\"[once] tick failed:\", err);\n }\n idleTicks = nextIdleTicks(\n [agentPool.snapshot(), commitPool.snapshot()],\n idleTicks,\n );\n if (idleTicks >= IDLE_TICKS_TO_EXIT) {\n console.log(\"[once] idle \u2014 exiting for launchd respawn.\");\n process.exit(0);\n }\n await delay(ONCE_TICK_MS);\n }\n}\n\nasync function finishShutdown(): Promise<never> {\n let waitedMs = 0;\n while (\n nextIdleTicks([agentPool.snapshot(), commitPool.snapshot()], 0) === 0\n ) {\n await delay(50);\n waitedMs += 50;\n // AGE-927: a turn can legitimately hold this loop for tens of minutes (a\n // reviewer leg observed at 35min). Silence reads as a hang and is exactly\n // what invites the `kill -9` that abandons the turn \u2014 say what we are\n // waiting on, periodically, so the wait is legible as progress.\n if (waitedMs % DRAIN_PROGRESS_MS === 0) {\n console.log(\n `workflow-runner: still draining \u2014 ${agentPool.snapshot().inflight} agent turn(s), ` +\n `${commitPool.snapshot().inflight} commit(s) in flight after ${Math.round(waitedMs / 1000)}s.`,\n );\n }\n }\n console.log(\"workflow-runner: shutdown complete.\");\n process.exit(0);\n}\n\n/** How often the drain reports what it is still waiting on. */\nconst DRAIN_PROGRESS_MS = 30_000;\n\nfunction requestShutdown(signal: NodeJS.Signals): void {\n shutdownRequested = true;\n console.log(`workflow-runner: ${signal} received; stopping new claims.`);\n const inflight =\n agentPool.snapshot().inflight + commitPool.snapshot().inflight;\n if (inflight > 0) {\n // AGE-927: the drain below protects these turns, but ONLY if this process\n // is the one that got the signal. `pnpm workflow-runner` forks node under a\n // pnpm parent, so signalling the parent \u2014 or `pkill -f workflow-runner`,\n // which matches BOTH \u2014 tears the child down before the drain can run. An\n // abandoned turn is invisible until its heartbeat TTL expires (~12min\n // observed), and the job then parks reporting \"heartbeat expired\" rather\n // than the real cause. Warn at the moment the operator can still back out.\n console.log(\n `workflow-runner: WAITING on ${inflight} in-flight turn(s) before exit. ` +\n `Do not kill this process or its parent \u2014 an abandoned turn is discarded ` +\n `and its job parks on the heartbeat TTL with a misleading reason.`,\n );\n }\n if (server.listening) server.close();\n void finishShutdown();\n}\n\n/**\n * AGE-497. Two things, both at start-up and both non-fatal:\n *\n * 1. DERIVE `STACKS_SCHEMA_REVISION` from the checkout when it is unset, and\n * write it into `process.env` so the shared `resolveRevisionStamp()` \u2014 which\n * every claim presents through `claimPresentation` \u2014 picks it up with no\n * change to the mirrored revision contract or to any call site.\n * 2. PROBE the control plane's `/api/health` with the resulting stamp, so a\n * mismatch is reported here instead of at the first burnt claim.\n *\n * Neither exits: an un-stamped dev runner against an un-stamped dev control\n * plane is legitimate, and the probe reports what actually matters.\n */\nlet lastRevisionProbeAt = 0;\n\nasync function reportRevisionHealth(): Promise<void> {\n lastRevisionProbeAt = Date.now();\n const probe = await probeRevisionHealth({\n mcpUrl: MCP_URL,\n stamp: resolveRevisionStamp(),\n });\n const line = `[revision] ${probe.status}: ${probe.message}`;\n if (probe.status === \"incompatible\") console.error(line);\n else console.log(line);\n}\n\n/**\n * AGE-497. REFUSE to start on a checkout a stage cannot legitimately be grounded\n * from \u2014 parked on a stage branch, detached, behind its upstream, or pointing at\n * the wrong repository.\n *\n * The check itself is not new (`checkRepos` computed the right numbers all\n * along); what was missing is that it only ever ran inside the manually-invoked\n * `pnpm harness:preflight`, and its verdict was a WARN. A runner was pointed at a\n * spent execution clone for over a week because nothing ran it. This runs on every\n * launch \u2014 and once mode is launchd-respawned per unit of work, so it re-runs\n * there too.\n *\n * Placed BEFORE `refreshRoleTokens()` so a misconfigured runner exits without\n * spending the one-time self-hosted bootstrap grant.\n */\nasync function assertReposUsable(): Promise<void> {\n const override = process.env[STALE_CHECKOUT_OVERRIDE] === \"1\";\n let rows;\n try {\n rows = applyStaleCheckoutOverride(\n await checkRepos({\n env: process.env,\n exists: existsSync,\n git: (cwd, args) => runGit(cwd, args),\n }),\n override,\n );\n } catch (err) {\n console.error(\n \"workflow-runner: could not validate STACKS_RUNNER_REPOS:\",\n err instanceof Error ? err.message : String(err),\n );\n process.exit(1);\n }\n console.log(renderTable(rows));\n if (rows.some((r) => r.status === \"FAIL\")) {\n console.error(\n `workflow-runner: refusing to start \u2014 STACKS_RUNNER_REPOS points at a checkout that cannot ground a stage (see the FAIL rows above). Fix agents/.env, or set ${STALE_CHECKOUT_OVERRIDE}=1 to start anyway.`,\n );\n process.exit(1);\n }\n}\n\nfunction stampSchemaRevision(): void {\n if (\n !process.env.STACKS_SCHEMA_REVISION &&\n typeof __STACKS_BUNDLED_SCHEMA_REVISION__ === \"string\"\n ) {\n process.env.STACKS_SCHEMA_REVISION = __STACKS_BUNDLED_SCHEMA_REVISION__;\n }\n if (\n !process.env.STACKS_APP_REVISION &&\n typeof __STACKS_BUNDLED_APP_REVISION__ === \"string\"\n ) {\n process.env.STACKS_APP_REVISION = __STACKS_BUNDLED_APP_REVISION__;\n }\n const resolved = resolveSchemaRevision(process.env, (p) => readdirSync(p));\n if (resolved.source === \"migrations\" && resolved.revision) {\n process.env.STACKS_SCHEMA_REVISION = resolved.revision;\n }\n const line = `workflow-runner: schema revision \u2014 ${resolved.detail}`;\n if (resolved.source === \"none\") console.warn(line);\n else console.log(line);\n}\n\nvoid (async () => {\n process.once(\"SIGINT\", () => requestShutdown(\"SIGINT\"));\n process.once(\"SIGTERM\", () => requestShutdown(\"SIGTERM\"));\n stampSchemaRevision();\n await assertReposUsable();\n\n // Provision role tokens BEFORE accepting any handoff \u2014 a drive must never\n // present an empty/expired token. Fail closed: exit if auth can't be provisioned\n // (a bad bootstrap token, an unreachable exchange, or a missing legacy PAT).\n try {\n await refreshRoleTokens();\n } catch (err) {\n console.error(\n \"Failed to provision runner auth:\",\n err instanceof Error ? err.message : String(err),\n );\n process.exit(1);\n }\n console.log(`workflow-runner: auth mode = ${authProvider.mode}`);\n console.log(\n `workflow-runner: pools \u2014 agent-turn max ${MAX_CONCURRENT_JOBS} (hard cap ${MAX_AGENT_JOBS_HARD}), commit max ${MAX_CONCURRENT_COMMITS} (hard cap ${MAX_COMMIT_JOBS_HARD}); job-id dedup shared across webhook + poll.`,\n );\n await reportRevisionHealth();\n\n if (RUN_ONCE) {\n // Once mode: no webhook listener (the sweep covers that leg's latency;\n // skipping it lets a canary run beside a long-lived runner on this host).\n await runOnce(await resolvePollWorkspace());\n }\n\n server.listen(PORT, HOST, () => {\n console.log(\n `workflow-runner listening on ${HOST}:${PORT} (POST agent.handoff here${POLL_MS > 0 ? `; poll mode every ${POLL_MS}ms` : \"\"})`,\n );\n });\n\n if (POLL_MS > 0) {\n const workspaceId = await resolvePollWorkspace();\n console.log(\n `[poll] webhook-less mode: polling workspace ${workspaceId} every ${POLL_MS}ms`,\n );\n if (POLL_HARNESS_RUN_ID) {\n console.log(\n `[poll] scope: harness ${POLL_HARNESS_RUN_ID} (all other workspace jobs ignored)`,\n );\n }\n while (!shutdownRequested) {\n try {\n await tickWithWatchdog(workspaceId);\n } catch (err) {\n console.error(\"[poll] tick failed:\", err);\n }\n // AGE-497: prod redeploys under a long-lived runner, so re-ask on a slow\n // timer \u2014 the drift is otherwise silent until a claim fails closed.\n if (Date.now() - lastRevisionProbeAt >= REVISION_PROBE_MS) {\n await reportRevisionHealth();\n }\n await delay(POLL_MS);\n }\n }\n})();\n", "/**\n * Claude Agent SDK runtime (the default). Auth: ANTHROPIC_API_KEY from the\n * environment (or a local Claude Code login).\n */\nimport {\n query,\n type EffortLevel,\n type Options,\n} from \"@anthropic-ai/claude-agent-sdk\";\n\nimport { buildExecutorHooks } from \"../executor-hooks.js\";\nimport type { JentrixAgentConfig, JentrixConnection } from \"../jentrix.js\";\n\n/** The pinned Claude model (STACKS_AGENT_MODEL override). Exported so the\n * workflow runner can record it on claim_agent_job \u2014 a silent model change\n * must be diagnosable from the run ledger. */\nexport function claudeModel(): string {\n return process.env.STACKS_AGENT_MODEL ?? \"claude-opus-4-8\";\n}\n\n/** Per-leg Claude model pins. Planner legs (authoring / planning / plan\n * revision) and executor legs (stage execution) may run different models:\n * STACKS_PLANNER_MODEL / STACKS_EXECUTOR_MODEL override per leg, both\n * falling back to the process-wide STACKS_AGENT_MODEL pin. */\nexport function claudeLegModel(leg: \"planner\" | \"executor\"): string {\n const override =\n leg === \"planner\"\n ? process.env.STACKS_PLANNER_MODEL\n : process.env.STACKS_EXECUTOR_MODEL;\n const trimmed = override?.trim();\n return trimmed ? trimmed : claudeModel();\n}\n\nconst CLAUDE_EFFORTS: readonly EffortLevel[] = [\n \"low\",\n \"medium\",\n \"high\",\n \"xhigh\",\n \"max\",\n];\n\nconst SCRUBBED_ENV_KEYS = new Set([\n \"STACKS_TOKEN\",\n \"STACKS_RUNNER_TOKEN\",\n \"STACKS_PLANNER_TOKEN\",\n \"STACKS_REVIEWER_TOKEN\",\n \"STACKS_WEBHOOK_SECRET\",\n \"STACKS_BOOTSTRAP_TOKEN\",\n \"STACKS_CLAIM_URL\",\n \"STACKS_RUNNER_AUTH_STATE\",\n \"STACKS_WORKER_HEARTBEAT_TOKEN\",\n \"STACKS_RUNNER_ROLE_BINDINGS\",\n]);\n\n/** AGE-926: the output ceiling a leg gets when the host sets none. A submit\n * payload grows with the work it carries \u2014 a 50-criterion `submit_plan` blew\n * the SDK's 32000 default and killed the leg *mid-submit*, discarding a\n * 19-minute planning turn whose only remaining artifact was the error text.\n * The failure lands at the most expensive moment of the most expensive turn,\n * so the default belongs here rather than in each operator's env. 64000 is the\n * SDK's documented streaming default and half of what claude-opus-5 allows:\n * high enough that hitting it means the payload should be split, not that the\n * ceiling should grow again. An explicit host value always wins. */\nexport const DEFAULT_MAX_OUTPUT_TOKENS = 64_000;\n\nexport function claudeEnv(): Record<string, string> {\n const env = Object.fromEntries(\n Object.entries(process.env).filter(\n (entry): entry is [string, string] =>\n entry[1] !== undefined && !SCRUBBED_ENV_KEYS.has(entry[0]),\n ),\n );\n // `??=` and not `||=`: an explicit \"0\" is a deliberate (if odd) host choice,\n // and silently replacing it would be the same class of surprise this fixes.\n env.CLAUDE_CODE_MAX_OUTPUT_TOKENS ??= String(DEFAULT_MAX_OUTPUT_TOKENS);\n return env;\n}\n\n/** Pinned reasoning effort for Claude turns (STACKS_CLAUDE_EFFORT). Unset \u21D2\n * the SDK default; an unknown value warns and uses the default \u2014 mirroring\n * codexReasoningEffort's never-silently-escalate posture. */\nexport function claudeEffort(): EffortLevel | undefined {\n const raw = process.env.STACKS_CLAUDE_EFFORT?.trim();\n if (!raw) return undefined;\n if ((CLAUDE_EFFORTS as readonly string[]).includes(raw)) {\n return raw as EffortLevel;\n }\n console.error(\n `Unknown STACKS_CLAUDE_EFFORT \"${raw}\" \u2014 using the SDK default (valid: ${CLAUDE_EFFORTS.join(\", \")}).`,\n );\n return undefined;\n}\n\n/** AGE-414: thrown when the jentrix MCP server is not connected at session init.\n * Without the Jentrix surface the model can only refuse (burning the turn) \u2014\n * and a refusal still counts as a \"successful\" result, so the claimed run\n * would rot until heartbeat expiry. Throwing here lets the runner retry the\n * session in-run (claim + heartbeat stay valid) or fail the job immediately. */\nexport class JentrixMcpUnavailableError extends Error {\n override name = \"JentrixMcpUnavailableError\";\n}\n\nfunction claudeOptions(\n config: JentrixAgentConfig,\n connection: JentrixConnection,\n abortController: AbortController,\n): Options {\n // Default world: the Jentrix tool surface and nothing else. An M7 executor\n // turn opts into repo tools scoped to its checkout so it can implement a\n // change (Read/Write/Edit/Bash + cwd); a REVIEWER turn opts into read-only\n // inspection (repoReadOnly) so it can verify claims without being able to\n // touch the tree. Server-side scopes still gate Jentrix.\n const allowedTools = config.repoCwd\n ? config.repoReadOnly\n ? [\"mcp__jentrix__*\", \"Read\", \"Glob\", \"Grep\"]\n : [\"mcp__jentrix__*\", \"Read\", \"Write\", \"Edit\", \"Bash\"]\n : [\"mcp__jentrix__*\"];\n // AGE-402: allowedTools only AUTO-APPROVES \u2014 every other harness tool stays\n // visible, and each attempt costs a turn plus a permission denial (the M17\n // authoring planner burned 37/40 turns on denied Bash/Read probes). Remove\n // out-of-world tools from the model's view entirely: disallow the mutating/\n // escape hatches a tools-only or read-only turn must never reach. Names not\n // present in a given SDK version are ignored, so the list is a superset.\n const disallowedTools = config.repoCwd\n ? config.repoReadOnly\n ? [\n \"Write\",\n \"Edit\",\n \"NotebookEdit\",\n \"Bash\",\n \"Task\",\n \"WebFetch\",\n \"WebSearch\",\n ]\n : // \"Skill\" joins the deny list now that `settingSources: ['project']`\n // makes the checkout's `.claude/skills` discoverable: those include the\n // operator's harness-driving skill, and a stage turn must never be\n // taught to drive the lifecycle it is being run by. CLAUDE.md is the\n // context this turn needs; the skills are not.\n [\"Task\", \"WebFetch\", \"WebSearch\", \"Skill\"]\n : [\n \"Bash\",\n \"Read\",\n \"Write\",\n \"Edit\",\n \"NotebookEdit\",\n \"Glob\",\n \"Grep\",\n \"Task\",\n \"WebFetch\",\n \"WebSearch\",\n \"Skill\",\n // ToolSearch deliberately NOT denied (AGE-423): when the host CLI\n // defers MCP tools, ToolSearch is the only path to the jentrix surface.\n ];\n // Freeze (H10.6): the SDK cancels the query when its abortController fires.\n // Bridge the incoming AbortSignal (raised by the runner's heartbeat pump on a\n // frozen run) to the controller the SDK understands (also used by the AGE-414\n // init check to cancel a session whose jentrix MCP server failed to connect).\n if (config.signal) {\n if (config.signal.aborted) abortController.abort();\n else\n config.signal.addEventListener(\"abort\", () => abortController.abort(), {\n once: true,\n });\n }\n const effort = CLAUDE_EFFORTS.includes(config.reasoningMode as EffortLevel)\n ? (config.reasoningMode as EffortLevel)\n : claudeEffort();\n return {\n model: config.model ?? claudeModel(),\n ...(effort ? { effort } : {}),\n // AGE-423: the host runtime may DEFER MCP tools behind ToolSearch (a\n // server-gated behavior that flipped on mid-day 2026-07-20) \u2014 teach the\n // model the load path. The sentinel makes a genuinely tool-less session\n // self-report in one cheap turn instead of producing a plausible refusal\n // that reads as success and orphans the claimed run.\n systemPrompt: `${config.systemPrompt}\\n\\nThe mcp__jentrix__ tools may be DEFERRED: if they are not in your tool list, load them with ToolSearch (e.g. query \"select:mcp__jentrix__get_agent_job\" or a keyword search) before use \u2014 verified to work. Only if the mcp__jentrix__ tools are absent AND ToolSearch is unavailable or cannot find them, reply with exactly STACKS_MCP_UNAVAILABLE and nothing else.`,\n maxTurns: config.maxTurns ?? 30,\n ...(config.repoCwd ? { cwd: config.repoCwd } : {}),\n abortController,\n env: claudeEnv(),\n ...(config.executablePath\n ? { pathToClaudeCodeExecutable: config.executablePath }\n : {}),\n // AGE-423: never load the operator's USER/LOCAL Claude Code settings \u2014\n // without that the session inherits every user-level MCP server (claude.ai\n // connectors, plugins; 25 servers observed) into the harness agent world.\n // 'project' is required for the checkout's CLAUDE.md (\"Must include\n // 'project' to load CLAUDE.md files\" \u2014 SDK Options) and loads only\n // .claude/settings.json from the repo, never ~/.claude: a checkout turn\n // that cannot read the project's own architecture rules re-invents\n // conventions the reviewer then rejects. Tools-only turns keep total\n // isolation \u2014 they have no checkout and would only pay the token cost.\n settingSources: config.repoCwd ? [\"project\"] : [],\n mcpServers: {\n jentrix: {\n type: \"http\",\n url: connection.url,\n headers: { Authorization: `Bearer ${connection.token}` },\n },\n },\n allowedTools,\n disallowedTools,\n // W3: mechanical enforcement of the two executor contracts that were prose\n // only \u2014 the runner owns a stage's submissions, and a turn may not end with\n // verification still running in the background. Harness stage executor legs\n // only (see JentrixAgentConfig.runnerOwnsSubmissions).\n ...(config.runnerOwnsSubmissions && config.repoCwd\n ? { hooks: buildExecutorHooks({ cwd: config.repoCwd }) }\n : {}),\n };\n}\n\nexport async function runClaudeAgent(\n prompt: string,\n config: JentrixAgentConfig,\n connection: JentrixConnection,\n): Promise<string> {\n const verbose = process.env.STACKS_AGENT_VERBOSE === \"1\";\n const abortController = new AbortController();\n const session = query({\n prompt,\n options: claudeOptions(config, connection, abortController),\n });\n for await (const message of session) {\n // AGE-414/423: fail fast ONLY on a terminal init status. \"pending\" is the\n // NORMAL init state for HTTP servers (connect in flight), and the tools\n // may be deferred behind ToolSearch anyway \u2014 the prompt's ToolSearch\n // guidance + STACKS_MCP_UNAVAILABLE sentinel handle everything else.\n if (message.type === \"system\" && message.subtype === \"init\") {\n const servers = (\n message as unknown as {\n mcp_servers?: { name: string; status: string }[];\n }\n ).mcp_servers;\n const status = servers?.find((s) => s.name === \"jentrix\")?.status;\n if (\n status === \"failed\" ||\n status === \"needs-auth\" ||\n status === \"disabled\"\n ) {\n abortController.abort();\n throw new JentrixMcpUnavailableError(\n `jentrix MCP server failed at session init (status: ${status})`,\n );\n }\n }\n if (verbose && message.type === \"assistant\") {\n for (const block of message.message.content) {\n if (block.type === \"text\") console.error(`[agent] ${block.text}`);\n if (block.type === \"tool_use\") console.error(`[tool] ${block.name}`);\n }\n }\n if (message.type === \"result\") {\n // AGE-938: the result message carries the session's provider-reported\n // usage \u2014 report it on BOTH outcomes (a failed turn still spent tokens).\n // Anthropic's input_tokens EXCLUDES the cache fields (siblings), so\n // total input is the three summed; the split rides beside it.\n const usage = (\n message as {\n usage?: {\n input_tokens?: number;\n cache_creation_input_tokens?: number;\n cache_read_input_tokens?: number;\n output_tokens?: number;\n };\n }\n ).usage;\n const costUsd = (message as { total_cost_usd?: number }).total_cost_usd;\n if (config.onUsage && usage) {\n try {\n config.onUsage({\n inputTokens:\n (usage.input_tokens ?? 0) +\n (usage.cache_creation_input_tokens ?? 0) +\n (usage.cache_read_input_tokens ?? 0),\n outputTokens: usage.output_tokens ?? 0,\n ...(typeof usage.cache_read_input_tokens === \"number\"\n ? { cacheReadTokens: usage.cache_read_input_tokens }\n : {}),\n ...(typeof usage.cache_creation_input_tokens === \"number\"\n ? { cacheCreationTokens: usage.cache_creation_input_tokens }\n : {}),\n ...(typeof costUsd === \"number\" ? { costUsd } : {}),\n });\n } catch {\n /* usage reporting must never break the turn */\n }\n }\n if (message.subtype === \"success\") {\n // AGE-423: the sentinel means the session started tool-less (jentrix\n // MCP lost the connect race) \u2014 surface it as the retriable error.\n if (message.result.trim() === \"STACKS_MCP_UNAVAILABLE\") {\n throw new JentrixMcpUnavailableError(\n \"session self-reported missing mcp__jentrix__ tools (connect race lost)\",\n );\n }\n return message.result;\n }\n throw new Error(`Agent run failed: ${message.subtype}`);\n }\n }\n throw new Error(\"Agent run ended without a result message\");\n}\n", "/**\n * Agent SDK hooks for harness EXECUTOR legs (Harness Reliability W3).\n *\n * Every role contract used to be prose in a system prompt, and the runner\n * registered zero hooks \u2014 so a model could narrate compliance it did not have\n * and nothing stopped it at the boundary. These are the two contracts worth\n * enforcing mechanically, both observed failing on the M18 run:\n *\n * 1. The RUNNER owns a harness stage's submissions. It executes the declared\n * verification commands itself, captures the diff, and attests the\n * evidence; the executor's job is to change the tree and describe what it\n * changed. An executor that submits anyway races the runner and lands a\n * claim about a tree nobody captured. PreToolUse DENIES those calls while\n * the worktree still has uncommitted changes, naming the dirty paths, so\n * the ledger never receives a claim about work that is not in the subject\n * the evidence binds to.\n *\n * 2. Evidence is an observed result, never an intention (AGENT_GUIDELINES \u00A75).\n * A turn ends the moment the model produces its final message: a suite\n * still running in the background at that point is evidence LOST, and the\n * summary that says \"tests are running\" becomes the stage's execution\n * record. Stop BLOCKS that ending \u2014 bounded to two nudges per turn, then\n * allows, because an unbounded Stop block against a confused model is a new\n * wedge and W1's park checkpoint is the backstop.\n *\n * Deliberately NOT enforced: \"ends with a dirty tree\" is the NORMAL, correct\n * ending for a harness executor turn \u2014 the runner captures the diff from that\n * tree straight afterwards. Blocking it would fire on every healthy turn.\n *\n * Claude legs only; Codex legs cannot be hooked (their honesty is enforced\n * server-side by the attested evidence gate and the review disposition rules).\n */\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nimport type {\n HookCallbackMatcher,\n HookEvent,\n HookInput,\n HookJSONOutput,\n PreToolUseHookInput,\n StopHookInput,\n} from \"@anthropic-ai/claude-agent-sdk\";\n\nconst execFileP = promisify(execFile);\n\n/** Read git state in the turn's worktree. Injected so the hooks are testable. */\nexport type HookGit = (cwd: string, args: string[]) => Promise<string>;\n\nconst defaultGit: HookGit = async (cwd, args) => {\n const { stdout } = await execFileP(\"git\", args, {\n cwd,\n maxBuffer: 16 * 1024 * 1024,\n });\n return stdout;\n};\n\n/** How many times one turn may be nudged before Stop is allowed through. */\nexport const STOP_BLOCK_LIMIT = 2;\n\n/** Artifact kinds whose body IS a claim about the tree \u2014 the runner authors\n * these from what it actually observed, never the model. */\nconst TREE_CLAIMING_ARTIFACT_KINDS = new Set([\n \"DIFF_OR_PATCH\",\n \"TEST_EVIDENCE\",\n \"EXECUTION_SUMMARY\",\n]);\n\n/**\n * Does this tool call make a claim about the working tree that the RUNNER owns?\n * PURE \u2014 exported for the smoke test. Tool names arrive MCP-prefixed\n * (`mcp__jentrix__\u2026`), and a bare name is accepted too so the check does not\n * depend on the server label.\n */\nexport function isRunnerOwnedSubmission(\n toolName: string,\n toolInput: unknown,\n): boolean {\n const name = toolName.replace(/^mcp__[^_]+__/, \"\");\n if (name === \"submit_execution_result\") return true;\n if (name === \"submit_harness_stage_result\") return true;\n if (name === \"submit_harness_artifact\") {\n const kind = (toolInput as { kind?: unknown } | null)?.kind;\n return typeof kind === \"string\" && TREE_CLAIMING_ARTIFACT_KINDS.has(kind);\n }\n return false;\n}\n\n/** Porcelain lines for the worktree; [] when git cannot be read (fail-soft \u2014 a\n * hook must never be the reason a turn dies). */\nasync function dirtyPaths(git: HookGit, cwd: string): Promise<string[]> {\n try {\n const out = await git(cwd, [\"status\", \"--porcelain\"]);\n return out\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter(Boolean);\n } catch {\n return [];\n }\n}\n\nexport interface ExecutorHookOptions {\n /** The job's worktree \u2014 the tree every claim is about. */\n cwd: string;\n git?: HookGit;\n log?: (msg: string) => void;\n}\n\n/**\n * Build the `hooks` option for one harness executor turn. The Stop counter is\n * per-turn because this returns a fresh closure per session.\n */\nexport function buildExecutorHooks(\n opts: ExecutorHookOptions,\n): Partial<Record<HookEvent, HookCallbackMatcher[]>> {\n const git = opts.git ?? defaultGit;\n const log = opts.log ?? (() => {});\n let stopBlocks = 0;\n\n const preToolUse = async (input: HookInput): Promise<HookJSONOutput> => {\n const call = input as PreToolUseHookInput;\n if (!isRunnerOwnedSubmission(call.tool_name, call.tool_input)) return {};\n const dirty = await dirtyPaths(git, opts.cwd);\n if (dirty.length === 0) return {};\n const named = dirty.slice(0, 10).join(\"; \");\n const more = dirty.length > 10 ? ` (+${dirty.length - 10} more)` : \"\";\n log(\n `[executor-hook] denied ${call.tool_name}: ${dirty.length} uncommitted change(s) in ${opts.cwd}`,\n );\n return {\n hookSpecificOutput: {\n hookEventName: \"PreToolUse\",\n permissionDecision: \"deny\",\n permissionDecisionReason:\n `${call.tool_name} is the RUNNER's to submit, and the worktree still has ` +\n `${dirty.length} uncommitted change(s): ${named}${more}. The runner captures the diff, ` +\n `executes the stage's declared verification commands itself, and attests the evidence ` +\n `after your turn ends \u2014 a submission now would record a claim about a tree nothing has ` +\n `captured. Finish your edits and end the turn with your summary (including the ` +\n `ADDRESSED_FINDINGS line); if this stage commits locally, commit first so the claim ` +\n `matches HEAD.`,\n },\n };\n };\n\n const stop = async (input: HookInput): Promise<HookJSONOutput> => {\n const end = input as StopHookInput;\n const pending = end.background_tasks ?? [];\n if (pending.length === 0) return {};\n if (stopBlocks >= STOP_BLOCK_LIMIT) {\n // Bounded on purpose: an unbounded block against a model that cannot\n // resolve the nudge is a new wedge, and the park checkpoint (W1) plus the\n // runner's own foreground verification are the backstops.\n log(\n `[executor-hook] stop allowed after ${stopBlocks} block(s) with ${pending.length} background task(s) still in flight`,\n );\n return {};\n }\n stopBlocks += 1;\n log(\n `[executor-hook] blocked stop #${stopBlocks}: ${pending.length} background task(s) still running`,\n );\n return {\n decision: \"block\",\n reason:\n `${pending.length} background task(s) are still running. Your session ends the moment ` +\n `you produce a final message, so a suite left in the background is evidence LOST and the ` +\n `summary becomes this stage's execution record. Wait for each command in the FOREGROUND, ` +\n `read its actual exit code, and report the real result \u2014 a red result reported honestly ` +\n `is a working system; a result you did not see is not evidence.`,\n };\n };\n\n return {\n PreToolUse: [{ hooks: [preToolUse] }],\n Stop: [{ hooks: [stop] }],\n };\n}\n", "/**\n * OpenAI Codex runtime \u2014 runs the same agents on a ChatGPT subscription.\n *\n * Auth: the SDK spawns the bundled `codex` binary, which reads the\n * credentials cached by `codex login` (~/.codex/auth.json). No OpenAI API\n * key needed. The Jentrix MCP server is injected per-run via config\n * overrides \u2014 your global ~/.codex/config.toml is never edited. It IS still\n * read as the base config, though, so every behavior-critical knob (model,\n * reasoning effort) is pinned explicitly below \u2014 an interactive `codex`\n * model switch must never silently re-model an unattended agent turn.\n *\n * Tool surface parity with the Claude runtime: web search and image viewing\n * are disabled. Tools-only agents (no repoCwd) run with the shell OFF and a\n * read-only sandbox, so their only world is the Jentrix MCP tools (the PAT's\n * scopes are enforced server-side regardless \u2014 P2.1). A repo turn enables the\n * shell with the orchestrator's credentials scrubbed from the child env:\n * reviewers remain read-only while executors receive workspace-write access to\n * their isolated worktree.\n */\nimport { Codex, type ModelReasoningEffort } from \"@openai/codex-sdk\";\n\nimport type { JentrixAgentConfig, JentrixConnection } from \"../jentrix.js\";\n\n// The model every Codex turn runs unless explicitly overridden. Pinned (never\n// \"the CLI's current default\"): the SDK-spawned codex binary reads\n// ~/.codex/config.toml as its BASE config, so an unset model here silently\n// follows whatever the operator last picked interactively \u2014 that is how the\n// Jul-2026 gpt-5.6-sol@high rollout re-modeled the harness reviewer and turned\n// the review loop non-convergent. gpt-5.5 is the loop's validated model;\n// gpt-5.6-terra@medium is the calibrated 5.6-generation alternative.\nconst DEFAULT_CODEX_MODEL = \"gpt-5.5\";\n\nconst REASONING_EFFORTS: readonly ModelReasoningEffort[] = [\n \"minimal\",\n \"low\",\n \"medium\",\n \"high\",\n \"xhigh\",\n];\n\n/** Resolve the Codex model pin. STACKS_CODEX_MODEL wins \u2014 the per-provider\n * override the multi-provider workflow runner needs (STACKS_AGENT_MODEL would\n * also repoint the Claude planner/executor turns); STACKS_AGENT_MODEL keeps\n * its documented applies-to-the-active-provider meaning for the single-provider\n * reference agents. */\nexport function codexModel(): string {\n return (\n process.env.STACKS_CODEX_MODEL ??\n process.env.STACKS_AGENT_MODEL ??\n DEFAULT_CODEX_MODEL\n );\n}\n\n/** Resolve the pinned reasoning effort (STACKS_CODEX_EFFORT, default medium \u2014\n * the provider default; explicit so a config.toml `model_reasoning_effort`\n * can never silently escalate an unattended reviewer to high/xhigh). */\nexport function codexReasoningEffort(): ModelReasoningEffort {\n const raw = process.env.STACKS_CODEX_EFFORT ?? \"medium\";\n if ((REASONING_EFFORTS as readonly string[]).includes(raw)) {\n return raw as ModelReasoningEffort;\n }\n console.error(\n `Unknown STACKS_CODEX_EFFORT \"${raw}\" \u2014 using \"medium\" (valid: ${REASONING_EFFORTS.join(\", \")}).`,\n );\n return \"medium\";\n}\n\n/**\n * Credentials STRIPPED from the codex child environment. Shell commands run as\n * children of the codex process and inherit its env, so with the shell enabled\n * (checkout-inspection turns, below) a prompt-injected `env` would otherwise\n * read the ORCHESTRATOR's credentials \u2014 the runner admin token, the other\n * roles' tokens, the Claude API key. The per-turn bearer (STACKS_MCP_BEARER)\n * is the only Jentrix credential a codex turn needs.\n */\nconst SCRUBBED_ENV_KEYS = new Set([\n \"ANTHROPIC_API_KEY\",\n \"STACKS_TOKEN\",\n \"STACKS_RUNNER_TOKEN\",\n \"STACKS_PLANNER_TOKEN\",\n \"STACKS_REVIEWER_TOKEN\",\n \"STACKS_WEBHOOK_SECRET\",\n \"STACKS_BOOTSTRAP_TOKEN\",\n \"STACKS_CLAIM_URL\",\n \"STACKS_RUNNER_AUTH_STATE\",\n \"STACKS_WORKER_HEARTBEAT_TOKEN\",\n \"STACKS_RUNNER_ROLE_BINDINGS\",\n]);\n\n/** The child env: process.env (HOME for ~/.codex login, PATH, \u2026) minus the\n * orchestrator credentials, plus this turn's MCP bearer. */\nexport function codexEnv(bearer: string): Record<string, string> {\n const env: Record<string, string> = {};\n for (const [key, value] of Object.entries(process.env)) {\n if (value !== undefined && !SCRUBBED_ENV_KEYS.has(key)) env[key] = value;\n }\n env.STACKS_MCP_BEARER = bearer;\n return env;\n}\n\nexport async function runCodexAgent(\n prompt: string,\n config: JentrixAgentConfig,\n connection: JentrixConnection,\n): Promise<string> {\n const verbose = process.env.STACKS_AGENT_VERBOSE === \"1\";\n // Repo turns use the shell against the explicitly scoped checkout. Reviewers\n // are marked repoReadOnly and stay in the read-only sandbox; executors run in\n // an isolated harness worktree and need workspace-write to implement changes.\n const hasCheckout = Boolean(config.repoCwd);\n const canWriteCheckout = hasCheckout && !config.repoReadOnly;\n const codex = new Codex({\n ...(config.executablePath\n ? { codexPathOverride: config.executablePath }\n : {}),\n // The Codex CLI reads the MCP bearer from the env var named below. It must be\n // the PER-ROLE token this run was handed (connection.token) \u2014 NOT the process\n // STACKS_TOKEN \u2014 so a multi-token orchestrator (the workflow runner: reviewer\n // \u2260 runner \u2260 planner) authenticates each turn as the right principal and the\n // server turn-guard (the submitting token must equal the phase's role token)\n // passes. Without this every Codex turn authenticates as the process\n // STACKS_TOKEN and a reviewer submit_review is rejected CONFLICT \"workflow\n // expects a different role\". The env is SCRUBBED of the orchestrator's other\n // credentials (see codexEnv).\n env: codexEnv(connection.token),\n config: {\n mcp_servers: {\n jentrix: {\n url: connection.url,\n bearer_token_env_var: \"STACKS_MCP_BEARER\",\n },\n },\n features: { shell_tool: hasCheckout },\n tools: { web_search: false, view_image: false },\n },\n });\n const thread = codex.startThread({\n // ALWAYS pinned (see codexModel/codexReasoningEffort above) \u2014 never left to\n // the CLI default, which is really the operator's ~/.codex/config.toml.\n model: config.model ?? codexModel(),\n modelReasoningEffort: REASONING_EFFORTS.includes(\n config.reasoningMode as ModelReasoningEffort,\n )\n ? (config.reasoningMode as ModelReasoningEffort)\n : codexReasoningEffort(),\n sandboxMode: canWriteCheckout ? \"workspace-write\" : \"read-only\",\n approvalPolicy: \"never\",\n skipGitRepoCheck: true,\n ...(config.repoCwd ? { workingDirectory: config.repoCwd } : {}),\n });\n\n // Codex threads take one prompt \u2014 the persona rides in front.\n const fullPrompt = `${config.systemPrompt}\\n\\n---\\n\\n${prompt}`;\n\n // AGE-938: sum provider-reported per-turn usage and hand it to the caller.\n // OpenAI's input_tokens INCLUDES cached (cached_input_tokens is a subset \u2192\n // cacheReadTokens); Codex has no cache-creation concept and reports no cost\n // (subscription auth) \u2014 those fields stay unreported, never fabricated.\n interface CodexUsage {\n input_tokens?: number;\n cached_input_tokens?: number;\n output_tokens?: number;\n }\n const sums = { input: 0, cached: 0, output: 0 };\n let sawUsage = false;\n let sawCached = false;\n const addUsage = (usage: CodexUsage | undefined) => {\n if (!usage) return;\n sawUsage = true;\n sums.input += usage.input_tokens ?? 0;\n sums.output += usage.output_tokens ?? 0;\n if (typeof usage.cached_input_tokens === \"number\") {\n sawCached = true;\n sums.cached += usage.cached_input_tokens;\n }\n };\n const reportUsage = () => {\n if (!config.onUsage || !sawUsage) return;\n try {\n config.onUsage({\n inputTokens: sums.input,\n outputTokens: sums.output,\n ...(sawCached ? { cacheReadTokens: sums.cached } : {}),\n });\n } catch {\n /* usage reporting must never break the turn */\n }\n };\n\n if (verbose) {\n const { events } = await thread.runStreamed(fullPrompt);\n let final = \"\";\n for await (const event of events) {\n if (event.type === \"item.completed\") {\n const item = event.item as { type?: string; text?: string };\n if (item.type === \"agent_message\" && item.text) final = item.text;\n console.error(`[codex] ${item.type ?? \"item\"}`);\n }\n if (event.type === \"turn.completed\") {\n addUsage((event as { usage?: CodexUsage }).usage);\n }\n if (event.type === \"turn.failed\") {\n reportUsage();\n throw new Error(\"Codex run failed\");\n }\n }\n reportUsage();\n if (!final) throw new Error(\"Codex run ended without a final response\");\n return final;\n }\n\n const turn = await thread.run(fullPrompt);\n addUsage((turn as { usage?: CodexUsage }).usage);\n reportUsage();\n if (!turn.finalResponse) {\n throw new Error(\"Codex run ended without a final response\");\n }\n return turn.finalResponse;\n}\n", "/**\n * Shared plumbing for the Jentrix reference agents (P4.2).\n *\n * Every agent talks to Jentrix EXCLUSIVELY through the MCP server \u2014 the same\n * surface any third-party agent uses \u2014 authenticated by a PAT minted on\n * /account/tokens. No filesystem or bash tools are allowed: the agent's\n * world is the Jentrix tool surface.\n *\n * Two interchangeable runtimes (STACKS_AGENT_PROVIDER):\n * \"claude\" (default) \u2014 Claude Agent SDK; needs ANTHROPIC_API_KEY.\n * \"codex\" \u2014 OpenAI Codex SDK; uses your `codex login`\n * credentials (ChatGPT subscription, no API key).\n * Same prompts, same MCP server, same badges \u2014 the Jentrix platform is\n * runtime-neutral by construction.\n */\nimport { runClaudeAgent } from \"./providers/claude.js\";\nimport { runCodexAgent } from \"./providers/codex.js\";\n\n/**\n * AGE-938: provider-reported usage for one agent turn \u2014 the shape\n * `record_run_usage` accepts. inputTokens is TOTAL input; the cache fields\n * are disjoint subsets of it. Absent field = the runtime did not report it.\n */\nexport interface AgentTurnUsage {\n inputTokens?: number;\n outputTokens?: number;\n cacheReadTokens?: number;\n cacheCreationTokens?: number;\n costUsd?: number;\n}\n\nexport interface JentrixAgentConfig {\n /** Agent persona + task rules. Keep it short; the tools carry the schema. */\n systemPrompt: string;\n /**\n * AGE-938: called with the provider-reported usage when the runtime exposes\n * it (Claude: the result message; Codex: summed turn.completed events).\n * Never called with estimated values. Failures in the callback are the\n * caller's problem \u2014 providers invoke it fire-and-forget.\n */\n onUsage?: (usage: AgentTurnUsage) => void;\n /**\n * Upper bound on agentic turns \u2014 a runaway guard, not a target.\n * Claude-only: Codex manages its own loop budget.\n */\n maxTurns?: number;\n /**\n * Model override for THIS turn. Claude-only: Codex pins its model via\n * STACKS_CODEX_MODEL. Unset \u21D2 the process-wide claudeModel() pin. Lets the\n * multi-role runner pin planner and executor legs to different models\n * (STACKS_PLANNER_MODEL / STACKS_EXECUTOR_MODEL \u2014 see claudeLegModel).\n */\n model?: string;\n /** Durable release-selected reasoning mode for this turn. */\n reasoningMode?: string;\n /** Absolute provider executable selected by the local runtime probe. */\n executablePath?: string;\n /**\n * Repo-execution context (M7 executor turns). When set, the Claude runtime\n * additionally gets Read/Write/Edit/Bash scoped to `cwd` so the agent can\n * actually implement a change in a checkout \u2014 NOT just operate Jentrix. Leave\n * unset for the default tools-only world (every other agent).\n */\n repoCwd?: string;\n /**\n * Read-only checkout INSPECTION (M7 reviewer turns): the agent can read the\n * working tree at `repoCwd` to verify claims against reality, but cannot\n * modify it. Claude: Read/Glob/Grep only (no Write/Edit/Bash); Codex: the\n * shell under its read-only sandbox. Ignored without `repoCwd`.\n */\n repoReadOnly?: boolean;\n /**\n * Abort signal (H10.6). When a harness run is frozen mid-turn, the runner\n * aborts this signal so the runtime stops the in-flight subprocess \u2014 freeze is\n * honored by the external process, not only by Jentrix server guards.\n */\n signal?: AbortSignal;\n /**\n * W3: this is a HARNESS stage executor leg, where the RUNNER submits the\n * stage result and attests the evidence. The Claude runtime then registers the\n * executor hooks (see lib/executor-hooks.ts): a submission attempted while the\n * worktree is dirty is denied, and a turn ending with background work still\n * running is nudged (twice, then allowed).\n *\n * Scoped deliberately: on a GENERIC M7 execution leg the model is supposed to\n * call `submit_execution_result` itself, from a checkout that is legitimately\n * dirty (nothing commits there), so an unscoped hook would deny every healthy\n * non-harness execution turn.\n */\n runnerOwnsSubmissions?: boolean;\n}\n\nexport interface JentrixConnection {\n url: string;\n token: string;\n}\n\nfunction requireEnv(name: string): string {\n const value = process.env[name];\n if (!value) {\n console.error(\n `Missing ${name}. Copy agents/.env.example to agents/.env and fill it in ` +\n `(export the vars or use \\`node --env-file=.env\\`).`,\n );\n process.exit(1);\n }\n return value;\n}\n\nexport function stacksConnection(): JentrixConnection {\n return {\n url: process.env.STACKS_MCP_URL ?? \"http://localhost:3000/api/mcp\",\n token: requireEnv(\"STACKS_TOKEN\"),\n };\n}\n\nexport type AgentProvider = \"claude\" | \"codex\";\n\nexport function agentProvider(): AgentProvider {\n const raw = process.env.STACKS_AGENT_PROVIDER ?? \"claude\";\n if (raw === \"claude\" || raw === \"codex\") return raw;\n console.error(\n `Unknown STACKS_AGENT_PROVIDER \"${raw}\" \u2014 use \"claude\" (Claude Agent SDK, ` +\n `ANTHROPIC_API_KEY) or \"codex\" (OpenAI Codex SDK, \\`codex login\\`).`,\n );\n process.exit(1);\n}\n\n/**\n * Run one agent task to completion on the configured runtime and return the\n * final result text. Streams progress to stderr when STACKS_AGENT_VERBOSE=1.\n *\n * `opts` lets a multi-agent orchestrator (the M7 workflow runner) override the\n * connection (a per-role PAT, so the turn-guard sees the right token) and the\n * provider per call (planner on Claude, reviewer on Codex) without touching the\n * process-wide env. Both default to the env-derived values.\n */\nexport async function runJentrixAgent(\n prompt: string,\n config: JentrixAgentConfig,\n opts: {\n connection?: JentrixConnection;\n provider?: AgentProvider;\n /** Abort the in-flight turn (freeze) \u2014 threaded into config.signal. */\n signal?: AbortSignal;\n } = {},\n): Promise<string> {\n const connection = opts.connection ?? stacksConnection();\n const provider = opts.provider ?? agentProvider();\n const cfg = opts.signal ? { ...config, signal: opts.signal } : config;\n return provider === \"codex\"\n ? runCodexAgent(prompt, cfg, connection)\n : runClaudeAgent(prompt, cfg, connection);\n}\n\n/** ISO timestamp for \"N hours ago\" \u2014 used for list_activity `since` params. */\nexport function hoursAgo(hours: number): string {\n return new Date(Date.now() - hours * 60 * 60 * 1000).toISOString();\n}\n", "/**\n * Execution contracts \u2014 Zod schemas + inferred types (M12.1).\n *\n * These are the wire/data contracts every ExecutionBackend and SandboxDriver\n * speaks. A RUN is one bounded unit of sandboxed work (a harness stage turn, a\n * standup digest, \u2026) described entirely by a {@link RunManifest}: what code it\n * runs over, what it may mount, which env it inherits, which capabilities it may\n * reach, its resource ceilings, and its egress posture. The backend returns a\n * single structured {@link ResultEnvelope} \u2014 success OR a typed failure (crucially,\n * a resource-limit kill is a *structured failure*, never a silent hang/timeout).\n *\n * Everything here is pure data (no Node imports) so it is equally usable by the\n * app, the reference runner, and tests.\n */\nimport { z } from \"zod\";\n\n/** A POSIX-ish env var name (used for the env allowlist). */\nconst ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\n// ---------------------------------------------------------------------------\n// Mounts + code snapshot\n// ---------------------------------------------------------------------------\n\nexport const MountModeSchema = z.enum([\"ro\", \"rw\"]);\nexport type MountMode = z.infer<typeof MountModeSchema>;\n\n/** A declared bind mount: a host path made visible inside the sandbox. */\nexport const MountSchema = z.object({\n /** Host source path (absolute) or a named volume. */\n source: z.string().min(1),\n /** Mount point inside the sandbox (absolute). */\n target: z.string().min(1),\n /** Read-only by default \u2014 writable mounts must be declared explicitly. */\n mode: MountModeSchema.default(\"ro\"),\n});\nexport type Mount = z.infer<typeof MountSchema>;\n\n/**\n * A reference to the code the run executes over. The preconfigured-checkout case\n * (`kind: \"checkout\"`, `ref` = an absolute host path) is what the reference runner\n * uses; `git`/`image` are provided for a hosted deployment that provisions the\n * snapshot itself.\n */\nexport const CodeSnapshotSchema = z.object({\n kind: z.enum([\"checkout\", \"git\", \"image\"]).default(\"checkout\"),\n /** checkout \u2192 host path; git \u2192 repo url/slug; image \u2192 container image ref. */\n ref: z.string().min(1),\n /** Optional pinned commit/branch (git snapshots). */\n commit: z.string().optional(),\n /** Optional sub-path within the snapshot to treat as the workdir. */\n path: z.string().optional(),\n});\nexport type CodeSnapshot = z.infer<typeof CodeSnapshotSchema>;\n\n// ---------------------------------------------------------------------------\n// Resource limits\n// ---------------------------------------------------------------------------\n\n/**\n * The run's resource ceilings. `wallMs` is REQUIRED \u2014 every run is deadline-bound\n * so a stalled turn is killed, not left to hang. `cpuMs` is the CPU-time budget\n * (enforced via `ulimit -t` on the host driver and `--ulimit cpu` on Docker); a\n * run that burns past it is killed with a structured resource-limit failure.\n */\nexport const ResourceLimitsSchema = z.object({\n /** Fractional CPU cores for throttling (Docker `--cpus`). Advisory on host. */\n cpus: z.number().positive().optional(),\n /** Hard CPU-time budget in ms \u2014 breaching it KILLS the run (SIGXCPU). */\n cpuMs: z.number().int().positive().optional(),\n /** Memory ceiling in bytes (Docker `--memory`; best-effort on host). */\n memoryBytes: z.number().int().positive().optional(),\n /** Disk/file-size ceiling in bytes (Docker `--ulimit fsize`). */\n diskBytes: z.number().int().positive().optional(),\n /** Wall-clock deadline in ms \u2014 REQUIRED. Breaching it KILLS the run. */\n wallMs: z.number().int().positive(),\n /** Max process/thread count (Docker `--pids-limit`). */\n pids: z.number().int().positive().optional(),\n});\nexport type ResourceLimits = z.infer<typeof ResourceLimitsSchema>;\n\n// ---------------------------------------------------------------------------\n// Egress profile\n// ---------------------------------------------------------------------------\n\n/**\n * The run's network posture. DENY-BY-DEFAULT: absent an explicit profile a run\n * gets no network. `allowlist` requests egress to specific hosts; `open` requests\n * unrestricted egress. Enforcement is the driver's job \u2014 and the LocalDockerDriver\n * only honors a non-deny profile when the operator has set STACKS_SANDBOX_ALLOW_NET=1\n * (the single dev bypass, mirroring the webhook SSRF allow-flag). Off by default.\n */\nexport const EgressProfileSchema = z.object({\n mode: z.enum([\"deny\", \"allowlist\", \"open\"]).default(\"deny\"),\n /** Hosts permitted when `mode === \"allowlist\"` (advisory; needs a proxy to filter per-host). */\n allow: z.array(z.string()).default([]),\n});\nexport type EgressProfile = z.infer<typeof EgressProfileSchema>;\n\n// ---------------------------------------------------------------------------\n// Runtime class + risk class\n// ---------------------------------------------------------------------------\n\n/**\n * The container/VM runtime the sandbox runs under. `runc` is the stock OCI runtime\n * (a shared-kernel container \u2014 NOT a trust boundary for hostile code). `gvisor`\n * (runsc) interposes an application kernel; `microvm` (Firecracker/Kata-class) is\n * a hardware-virtualized boundary for the most hostile code. Selection is\n * RISK-CLASS-DRIVEN (see {@link RiskClass}) and expressed here on the manifest so\n * the driver can pick `--runtime` \u2014 even though the MANAGED runtime is brought up\n * in M12 infra-a/infra-b; the local Docker driver honors whatever `--runtime` the\n * host has installed and otherwise runs stock runc.\n */\nexport const RuntimeClassSchema = z.enum([\"runc\", \"gvisor\", \"microvm\"]);\nexport type RuntimeClass = z.infer<typeof RuntimeClassSchema>;\n\n/**\n * The trust posture of a capability (and, aggregated, of the whole run). Drives\n * the runtime-class selection: `trusted` code may run under stock runc, `standard`\n * work is isolated under gVisor, and `hostile` code (untrusted input, third-party\n * plugins) is pushed to a microVM boundary.\n */\nexport const RiskClassSchema = z.enum([\"trusted\", \"standard\", \"hostile\"]);\nexport type RiskClass = z.infer<typeof RiskClassSchema>;\n\n// ---------------------------------------------------------------------------\n// Capability handles\n// ---------------------------------------------------------------------------\n\n/**\n * A capability the run may exercise, referenced by an OPAQUE handle \u2014 never raw\n * secret material. The host resolves/injects the real thing at the sandbox\n * boundary (e.g. an MCP bearer, a single-use git push token). Keeping capabilities\n * as handles is what lets a manifest be logged/persisted without leaking secrets.\n *\n * `riskClass` is the per-capability trust posture. The sandbox controller reduces\n * the capabilities' risk classes to the run's {@link RuntimeClass} (the strictest\n * wins) \u2014 this is the \"per-capability, risk-class-driven\" runtime selection.\n */\nexport const CapabilityHandleSchema = z.object({\n id: z.string().min(1),\n kind: z.enum([\"mcp\", \"git\", \"secret\", \"network\", \"custom\"]).default(\"custom\"),\n /** Opaque reference the host resolves at injection time (never the secret itself). */\n ref: z.string().optional(),\n /** Trust posture of this capability \u2014 drives runtime-class selection. */\n riskClass: RiskClassSchema.default(\"standard\"),\n});\nexport type CapabilityHandle = z.infer<typeof CapabilityHandleSchema>;\n\n/** The env allowlist: only these names may be inherited into the sandbox. */\nexport const EnvAllowlistSchema = z.array(z.string().regex(ENV_NAME));\n\n// ---------------------------------------------------------------------------\n// Run manifest\n// ---------------------------------------------------------------------------\n\nexport const RunManifestSchema = z.object({\n /** Correlation id for the run (the ExecutionBackend keys everything on this). */\n runId: z.string().min(1),\n /** Optional Jentrix AgentJob id this run backs (for record correlation). */\n jobId: z.string().optional(),\n /**\n * The argv executed inside the sandbox. REQUIRED for container/subprocess\n * drivers; may be empty for an in-process host run (see `inProcess`).\n */\n command: z.array(z.string()).default([]),\n /** The code the run executes over. */\n codeSnapshot: CodeSnapshotSchema,\n /**\n * The PINNED OCI base image the sandbox boots from (e.g. `ghcr.io/acme/runner@sha256:\u2026`).\n * When set it wins over the driver's default image and a `codeSnapshot.kind:\"image\"`\n * ref \u2014 the base image is declared in the manifest so a run starts from immutable,\n * reproducible material. The sandbox controller REQUIRES this to be digest-pinned.\n */\n image: z.string().min(1).optional(),\n /**\n * The runtime class the sandbox runs under (runc | gvisor | microvm). Absent \u21D2 the\n * driver's default (stock runc). Risk-class-driven \u2014 set by the controller from the\n * capabilities' risk classes.\n */\n runtimeClass: RuntimeClassSchema.optional(),\n /** Working directory inside the sandbox (defaults to the snapshot path/mount). */\n workdir: z.string().optional(),\n /** Declared bind mounts (read-only unless a mount opts into rw). */\n mounts: z.array(MountSchema).default([]),\n /** The ONLY env names that may be inherited from the host into the sandbox. */\n envAllowlist: EnvAllowlistSchema.default([]),\n /** Explicit env values (still gated by the allowlist for pass-through). */\n env: z.record(z.string(), z.string()).default({}),\n /** Capability handles the run may exercise (opaque references, never secrets). */\n capabilities: z.array(CapabilityHandleSchema).default([]),\n /** Resource ceilings \u2014 wall-time required; others optional. */\n limits: ResourceLimitsSchema,\n /** Network posture \u2014 deny by default. */\n egress: EgressProfileSchema.default({ mode: \"deny\", allow: [] }),\n /**\n * When true, the HostProcessDriver runs the caller-supplied in-process runner\n * (the reference runner's agent turn) INSTEAD of spawning `command` \u2014 this is\n * the \"former direct-exec path\" preserved behind the same contract. Container\n * drivers ignore this and always run `command`.\n */\n inProcess: z.boolean().default(false),\n /** Free-form labels for observability (never load-bearing). */\n labels: z.record(z.string(), z.string()).default({}),\n});\nexport type RunManifest = z.infer<typeof RunManifestSchema>;\nexport type RunManifestInput = z.input<typeof RunManifestSchema>;\n\n/** Parse + fill defaults, throwing on an invalid manifest. */\nexport function parseManifest(input: RunManifestInput): RunManifest {\n return RunManifestSchema.parse(input);\n}\n\n// ---------------------------------------------------------------------------\n// Lifecycle + heartbeat + cancel\n// ---------------------------------------------------------------------------\n\n/** The lifecycle a run moves through. Terminal: SUCCEEDED/FAILED/CANCELED/TIMED_OUT/KILLED. */\nexport const LifecycleStateSchema = z.enum([\n \"PENDING\", // claimed, not yet started\n \"STARTING\", // sandbox provisioning\n \"RUNNING\", // command executing\n \"SUCCEEDED\", // exited 0\n \"FAILED\", // exited non-zero, or a resource kill other than wall-time\n \"CANCELED\", // canceled/frozen by the caller\n \"TIMED_OUT\", // wall-time budget exceeded \u2192 killed\n \"KILLED\", // killed by a CPU/memory/disk limit or an external signal\n]);\nexport type LifecycleState = z.infer<typeof LifecycleStateSchema>;\n\nconst TERMINAL: ReadonlySet<LifecycleState> = new Set<LifecycleState>([\n \"SUCCEEDED\",\n \"FAILED\",\n \"CANCELED\",\n \"TIMED_OUT\",\n \"KILLED\",\n]);\nexport function isTerminalState(state: LifecycleState): boolean {\n return TERMINAL.has(state);\n}\n\nexport const ResourceUsageSchema = z.object({\n wallMs: z.number().int().nonnegative(),\n cpuMs: z.number().int().nonnegative().optional(),\n memoryBytes: z.number().int().nonnegative().optional(),\n});\nexport type ResourceUsage = z.infer<typeof ResourceUsageSchema>;\n\n/**\n * A liveness + usage sample for an in-flight run. The backend emits these on a\n * cadence (and one final terminal beat); a stalled run is one whose wall budget\n * has gone negative \u2014 the backend's own wall timer will already be killing it.\n */\nexport const HeartbeatSchema = z.object({\n runId: z.string(),\n state: LifecycleStateSchema,\n at: z.string(),\n usage: ResourceUsageSchema,\n /** Wall budget left (ms); negative \u21D2 over budget (cancel imminent). */\n wallRemainingMs: z.number().int().optional(),\n});\nexport type Heartbeat = z.infer<typeof HeartbeatSchema>;\n\n/** A cancel/freeze request: SIGTERM, then SIGKILL after `graceMs`. */\nexport const CancelRequestSchema = z.object({\n runId: z.string(),\n reason: z.string().default(\"canceled\"),\n graceMs: z.number().int().nonnegative().default(2000),\n});\nexport type CancelRequest = z.infer<typeof CancelRequestSchema>;\n/** Loose caller shape (reason/graceMs optional \u2014 the backend fills defaults). */\nexport type CancelRequestInput = z.input<typeof CancelRequestSchema>;\n\n// ---------------------------------------------------------------------------\n// Result envelope\n// ---------------------------------------------------------------------------\n\n/** Which declared limit a resource kill attributed to. */\nexport const ResourceLimitKindSchema = z.enum([\n \"cpu\",\n \"memory\",\n \"disk\",\n \"wall_time\",\n \"pids\",\n]);\nexport type ResourceLimitKind = z.infer<typeof ResourceLimitKindSchema>;\n\n/** The category of a run failure. */\nexport const FailureKindSchema = z.enum([\n \"resource_limit_exceeded\", // killed for breaching cpu/memory/disk/wall-time/pids\n \"nonzero_exit\", // the command exited non-zero\n \"canceled\", // canceled/frozen by the caller\n \"driver_error\", // the sandbox faulted (docker/spawn failure)\n \"startup_error\", // the sandbox could not be provisioned\n]);\nexport type FailureKind = z.infer<typeof FailureKindSchema>;\n\nexport const ResultFailureSchema = z.object({\n kind: FailureKindSchema,\n /** The specific limit breached \u2014 set iff `kind === \"resource_limit_exceeded\"`. */\n limit: ResourceLimitKindSchema.nullable().default(null),\n message: z.string(),\n /** The POSIX signal the run died from, when known (e.g. \"SIGKILL\", \"SIGXCPU\"). */\n signal: z.string().nullable().default(null),\n});\nexport type ResultFailure = z.infer<typeof ResultFailureSchema>;\n\n/**\n * The single structured result of a run. A resource-limit kill is reported here\n * as `status: \"failed\" | \"timed_out\"` with a populated `failure` naming the exact\n * limit \u2014 never as an unstructured hang. `summary` carries the agent-turn text the\n * reference runner records as evidence.\n */\nexport const ResultEnvelopeSchema = z.object({\n runId: z.string(),\n /** The driver that produced this result (\"host-process\" | \"local-docker\"). */\n driver: z.string(),\n status: z.enum([\"succeeded\", \"failed\", \"canceled\", \"timed_out\"]),\n state: LifecycleStateSchema,\n exitCode: z.number().int().nullable(),\n startedAt: z.string(),\n endedAt: z.string(),\n usage: ResourceUsageSchema,\n stdout: z.string().default(\"\"),\n stderr: z.string().default(\"\"),\n /** Agent-turn summary text (reference-runner evidence); defaults to stdout. */\n summary: z.string().default(\"\"),\n failure: ResultFailureSchema.nullable().default(null),\n});\nexport type ResultEnvelope = z.infer<typeof ResultEnvelopeSchema>;\n\n/** True when the run was killed for breaching a declared resource budget. */\nexport function isResourceLimitExceeded(env: ResultEnvelope): boolean {\n return env.failure?.kind === \"resource_limit_exceeded\";\n}\n\n/** True when the run finished cleanly (exit 0). */\nexport function isSuccess(env: ResultEnvelope): boolean {\n return env.status === \"succeeded\";\n}\n", "/**\n * Deployment-compatibility revisions \u2014 the SINGLE SOURCE OF TRUTH contract\n * (M12.3b, AGE-173).\n *\n * A deployed Jentrix plane is assembled from independently-shipped images \u2014 the\n * CONTROL PLANE (the Next app), the WORKER (the polling reference runner), and the\n * SANDBOX images (the sandbox controller). Each is BUILD-STAMPED with two revisions:\n *\n * \u2022 schemaRevision \u2014 the database/contract schema the image was built against\n * (the latest Prisma migration id). A worker running against a control plane\n * whose schema has moved on is EXACTLY the \"silent unknown-field / stale-client\"\n * failure mode this module exists to make LOUD and fail-closed.\n * \u2022 appRevision \u2014 the application build the image was cut from (the git SHA).\n *\n * Both are read from the environment (`STACKS_SCHEMA_REVISION` / `STACKS_APP_REVISION`,\n * with `VERCEL_GIT_COMMIT_SHA` as an app-revision fallback) so ONE build stamps ALL\n * images identically \u2014 that shared build stamp is the single source of truth. An\n * un-stamped process resolves to {@link UNKNOWN_REVISION}.\n *\n * The guard is FAIL-CLOSED but never a FALSE POSITIVE: it rejects only when the\n * control plane HAS a known revision that the worker's presented revision does not\n * match (including a stale worker presenting `unknown` against a stamped control\n * plane). An un-stamped control plane (dev/test) cannot meaningfully compare, so the\n * guard is inert \u2014 matched AND un-stamped deployments claim and run normally.\n *\n * Pure data \u2014 ZERO imports (only reads env + compares strings) \u2014 so the app, the\n * worker, the sandbox controller, and the reference runner all speak the identical\n * contract without dragging in a dependency (the worker package has no `zod`). The\n * app keeps a byte-for-byte MIRROR at `src/lib/revision.ts` because Next cannot\n * import from `packages/`; a mismatch is caught by the two sides' unit tests.\n */\n\n/** The sentinel an UN-STAMPED (dev / test / legacy) process resolves to. */\nexport const UNKNOWN_REVISION = \"unknown\";\n\n/** A component's build-stamped identity. */\nexport interface RevisionStamp {\n /** The schema/contract revision (latest Prisma migration id). */\n schemaRevision: string;\n /** The application build revision (git SHA). */\n appRevision: string;\n}\n\n/** A minimal env shape \u2014 avoids a hard Node dependency in the pure contract. */\nexport type RevisionEnv = Record<string, string | undefined>;\n\nfunction clean(value: string | undefined): string {\n return (value ?? \"\").trim();\n}\n\nfunction safeProcessEnv(): RevisionEnv {\n return typeof process !== \"undefined\" && process.env ? process.env : {};\n}\n\n/**\n * Resolve a component's build-stamped revision from the environment. Because every\n * image is stamped from ONE build, the control plane and a compatible worker resolve\n * identical stamps; an un-stamped process resolves to {@link UNKNOWN_REVISION}.\n */\nexport function resolveRevisionStamp(\n env: RevisionEnv = safeProcessEnv(),\n): RevisionStamp {\n const schema = clean(env.STACKS_SCHEMA_REVISION);\n const app =\n clean(env.STACKS_APP_REVISION) || clean(env.VERCEL_GIT_COMMIT_SHA);\n return {\n schemaRevision: schema || UNKNOWN_REVISION,\n appRevision: app || UNKNOWN_REVISION,\n };\n}\n\n/** True when a revision carries a real (build-stamped) value, not the sentinel. */\nexport function isStamped(revision: string): boolean {\n return revision.length > 0 && revision !== UNKNOWN_REVISION;\n}\n\n/**\n * STRICTLY: is this worker positively known to be running THIS build?\n *\n * Deliberately narrower than {@link compareRevisions}. That comparison is\n * *inert* when the control plane is un-stamped \u2014 nothing to compare against, so\n * it reports a match and refuses nobody, which is right for a compatibility gate\n * that must not break dev. This predicate answers the opposite question, the one\n * you ask before granting a capability ON THE STRENGTH of the worker's code:\n * both dimensions must be stamped on BOTH sides and equal. Un-stamped anywhere\n * \u21D2 false, because \"we cannot tell\" must never read as \"yes\".\n *\n * M18.3 R7 uses it at the validator dispatch boundary: an attempt is opened\n * read-only only for a runner whose build the control plane can positively\n * identify as carrying the read-only checkout lane.\n */\nexport function isRevisionAttested(\n control: RevisionStamp,\n worker: RevisionStamp,\n): boolean {\n return (\n isStamped(control.schemaRevision) &&\n isStamped(control.appRevision) &&\n control.schemaRevision === worker.schemaRevision &&\n control.appRevision === worker.appRevision\n );\n}\n\nexport type RevisionDimension = \"schema\" | \"app\";\n\n/** The verdict of comparing a worker's revision against the control plane's. */\nexport interface RevisionCompatibility {\n compatible: boolean;\n schemaMatch: boolean;\n appMatch: boolean;\n /** Which dimensions disagreed (empty when compatible). */\n mismatches: RevisionDimension[];\n control: RevisionStamp;\n worker: RevisionStamp;\n /** A legible one-line reason, or null when compatible. */\n reason: string | null;\n}\n\n/**\n * Compare a worker's presented revision against the control plane's own. FAIL-CLOSED\n * on a KNOWN-vs-different mismatch (including a worker presenting `unknown` against a\n * stamped control plane \u2014 a stale / legacy client). INERT when the control plane is\n * itself un-stamped: there is nothing to compare against, so no false positives in\n * dev / test.\n */\nexport function compareRevisions(\n control: RevisionStamp,\n worker: RevisionStamp,\n): RevisionCompatibility {\n const schemaMatch =\n !isStamped(control.schemaRevision) ||\n control.schemaRevision === worker.schemaRevision;\n const appMatch =\n !isStamped(control.appRevision) ||\n control.appRevision === worker.appRevision;\n const mismatches: RevisionDimension[] = [];\n if (!schemaMatch) mismatches.push(\"schema\");\n if (!appMatch) mismatches.push(\"app\");\n const compatible = mismatches.length === 0;\n return {\n compatible,\n schemaMatch,\n appMatch,\n mismatches,\n control,\n worker,\n reason: compatible\n ? null\n : describeRevisionMismatch(control, worker, mismatches),\n };\n}\n\n/** A legible, operator-facing one-liner describing a revision mismatch. */\nexport function describeRevisionMismatch(\n control: RevisionStamp,\n worker: RevisionStamp,\n mismatches: RevisionDimension[],\n): string {\n const parts = mismatches.map((dimension) =>\n dimension === \"schema\"\n ? `schema revision ${worker.schemaRevision} != control plane ${control.schemaRevision}`\n : `app revision ${worker.appRevision} != control plane ${control.appRevision}`,\n );\n return (\n `Worker deployment is incompatible with the control plane: ${parts.join(\"; \")}. ` +\n `Redeploy the worker to match \u2014 it will not claim runs until it does.`\n );\n}\n\nexport type RevisionHealthStatus = \"ok\" | \"incompatible\" | \"unstamped\";\n\n/** A legible health summary of the revision state, for a probe or a banner. */\nexport interface RevisionHealth {\n status: RevisionHealthStatus;\n control: RevisionStamp;\n /** The worker under comparison, when a stamp was presented. */\n worker: RevisionStamp | null;\n compatibility: RevisionCompatibility | null;\n /** A legible operator-facing message (always set). */\n message: string;\n}\n\n/**\n * Summarize the revision state legibly. With a worker stamp it reports\n * ok / incompatible; without one it reports whether the control plane is itself\n * build-stamped (an un-stamped plane runs with the guard inert).\n */\nexport function revisionHealth(\n control: RevisionStamp,\n worker?: RevisionStamp | null,\n): RevisionHealth {\n if (worker) {\n const compatibility = compareRevisions(control, worker);\n if (!compatibility.compatible) {\n return {\n status: \"incompatible\",\n control,\n worker,\n compatibility,\n message: compatibility.reason as string,\n };\n }\n return {\n status: \"ok\",\n control,\n worker,\n compatibility,\n message: `Worker matches the control plane (schema ${control.schemaRevision}, app ${control.appRevision}).`,\n };\n }\n const stamped =\n isStamped(control.schemaRevision) && isStamped(control.appRevision);\n if (!stamped) {\n return {\n status: \"unstamped\",\n control,\n worker: null,\n compatibility: null,\n message: `Control plane is not build-stamped (schema ${control.schemaRevision}, app ${control.appRevision}) \u2014 the revision compatibility guard is inert.`,\n };\n }\n return {\n status: \"ok\",\n control,\n worker: null,\n compatibility: null,\n message: `Control plane revision: schema ${control.schemaRevision}, app ${control.appRevision}.`,\n };\n}\n", "/**\n * Shared worktree lifecycle helper (Concurrent Harness Execution PRD, Decision 11).\n *\n * ONE native-Git worktree per harness execution attempt (`AgentJob`). Both the\n * reference runner and the Temporal worker use THIS helper for path derivation,\n * create/adopt validation, superseded-branch detach, and safe cleanup, so the two\n * processes can never drift.\n *\n * Contract (deliberately narrow):\n * \u2022 Shells out to `git` with argv ARRAYS only (injectable {@link RunGit} seam)\n * and uses Node stdlib fs/path/crypto only \u2014 NO runtime dependency (the\n * Temporal worker package has no zod), NO Jentrix API / workflow-policy logic.\n * \u2022 The worktree dir + sibling marker are DETERMINISTICALLY derived from trusted\n * repo config + the opaque jobId; every resolved path is proven to stay under\n * the configured root after normalization AND realpath/symlink resolution.\n * \u2022 The ownership marker is a SIBLING of the worktree, never inside it (the\n * runner uses `git add -A`), and holds identifiers only.\n * \u2022 Adoption, detach, and cleanup all fail CLOSED on a mismatched marker, a path\n * outside the root, or a symlink escape \u2014 nothing is ever overwritten or\n * recursively deleted.\n */\nimport { execFile } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport {\n lstat,\n mkdir,\n readFile,\n realpath,\n rm,\n writeFile,\n} from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { promisify } from \"node:util\";\n\nconst execFileP = promisify(execFile);\n\n/** Trusted repo mapping for one configured repository (from STACKS_RUNNER_REPOS). */\nexport interface WorktreeRepoConfig {\n /** \"owner/name\" \u2014 the configured repo identity. Filesystem paths NEVER come from\n * tool/MCP input; only this operator-configured identity + checkout are trusted. */\n repo: string;\n /** Absolute path to the configured source checkout (the Git source). */\n checkout: string;\n /** STACKS_RUNNER_WORKTREE_ROOT \u2014 the worktree parent. When omitted, a sibling\n * `.stacks-worktrees` directory next to {@link checkout} is used. */\n worktreeRoot?: string;\n}\n\n/** The four opaque identifiers that key + validate an attempt's worktree. */\nexport interface WorktreeIdentity {\n /** \"owner/name\" \u2014 must equal the resolving config's repo. */\n repo: string;\n /** The AgentJob id \u2014 the durable attempt identity. Validated as an opaque id,\n * NEVER interpreted as a path. */\n jobId: string;\n /** The harness stage identity. */\n stageId: string;\n /** The resolved stage branch (e.g. `harness/{taskKey}-{slug}-stage-{n}`). */\n branch: string;\n}\n\nexport type WorktreeMarkerStatus = \"active\" | \"superseded-detached\";\n\n/** The on-disk ownership marker \u2014 identifiers only (no paths, no secrets). */\nexport interface WorktreeMarker extends WorktreeIdentity {\n status: WorktreeMarkerStatus;\n}\n\n/** Purely-derived paths for an attempt's worktree (no filesystem access). */\nexport interface ResolvedWorktree {\n /** The worktree parent root (`<worktreeRoot>` or the `.stacks-worktrees` sibling). */\n root: string;\n /** Filesystem-safe encoding of the repo identity. */\n repoKey: string;\n /** `<root>/<repoKey>/<jobId>/` \u2014 the linked worktree directory. */\n dir: string;\n /** `<root>/<repoKey>/<jobId>.marker.json` \u2014 the SIBLING ownership marker. */\n markerPath: string;\n}\n\nexport interface EnsureWorktreeResult {\n dir: string;\n markerPath: string;\n marker: WorktreeMarker;\n /** true when the worktree was freshly created, false when an existing one was adopted. */\n created: boolean;\n}\n\nexport interface CleanupResult {\n removed: boolean;\n reason: \"clean\" | \"source-dirty\" | \"absent\";\n /** Porcelain status lines when retained as source-dirty (for operator reporting). */\n dirty?: string[];\n}\n\n/** The outcome of a park/rescue checkpoint (see {@link checkpointWorktree}). */\nexport interface CheckpointResult {\n committed: boolean;\n reason: \"committed\" | \"clean\" | \"absent\";\n /** The stage branch's new tip when a checkpoint landed. */\n sha?: string;\n /** Paths the checkpoint captured (operator reporting). */\n files?: string[];\n}\n\n/**\n * Run a git command; returns stdout. `env` (when given) is merged into the child's\n * environment (used to hand a credential helper a single-use token WITHOUT placing\n * it in argv). Structurally identical to the runner's own git seam so the runner\n * can pass its instrumented implementation in.\n */\nexport type RunGit = (\n cwd: string,\n args: string[],\n env?: Record<string, string>,\n) => Promise<string>;\n\nexport const defaultRunGit: RunGit = async (cwd, args, env) => {\n const { stdout } = await execFileP(\"git\", args, {\n cwd,\n env: env ? { ...process.env, ...env } : process.env,\n maxBuffer: 64 * 1024 * 1024,\n });\n return stdout;\n};\n\n/** A fail-closed lifecycle error carrying a machine-readable code + actionable message. */\nexport class WorktreeError extends Error {\n constructor(\n readonly code:\n | \"INVALID_JOB_ID\"\n | \"PATH_ESCAPE\"\n | \"MARKER_MISSING\"\n | \"MARKER_INVALID\"\n | \"MARKER_MISMATCH\"\n | \"REPO_MISMATCH\"\n | \"BRANCH_MISMATCH\"\n | \"NOT_A_WORKTREE\"\n | \"MISSING_REF\"\n | \"CREATE_FAILED\"\n | \"NOT_FOUND\"\n | \"CHECKPOINT_UNREACHABLE\",\n message: string,\n ) {\n super(message);\n this.name = \"WorktreeError\";\n }\n}\n\n// A cuid/uuid-shaped opaque id: no path separators, no dots (so it can never be\n// `..`, a traversal segment, or collide with the `.marker.json` sibling suffix).\nconst JOB_ID_RE = /^[A-Za-z0-9_-]{1,200}$/;\n\nfunction validateJobId(jobId: string): void {\n if (!JOB_ID_RE.test(jobId)) {\n throw new WorktreeError(\n \"INVALID_JOB_ID\",\n `jobId ${JSON.stringify(jobId)} is not an opaque id (expected ${JOB_ID_RE}); refusing to interpret it as a path.`,\n );\n }\n}\n\n/** Filesystem-safe encoding of a repo identity: readable slug + disambiguating hash. */\nexport function repoKeyFor(repo: string): string {\n const slug = repo\n .replace(/[^A-Za-z0-9._-]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\")\n .slice(0, 64);\n const hash = createHash(\"sha256\").update(repo).digest(\"hex\").slice(0, 12);\n return slug ? `${slug}-${hash}` : hash;\n}\n\nfunction assertUnder(base: string, target: string): void {\n const b = path.resolve(base);\n const t = path.resolve(target);\n if (t !== b && !t.startsWith(b + path.sep)) {\n throw new WorktreeError(\"PATH_ESCAPE\", `path ${t} escapes ${b}`);\n }\n}\n\n/**\n * Deterministically derive the worktree dir + sibling marker path. Pure: validates\n * the jobId and normalizes/contains the paths, but touches no filesystem.\n */\nexport function resolveWorktreePaths(\n config: WorktreeRepoConfig,\n identity: WorktreeIdentity,\n): ResolvedWorktree {\n validateJobId(identity.jobId);\n const root = path.resolve(\n config.worktreeRoot ??\n path.join(\n path.dirname(path.resolve(config.checkout)),\n \".stacks-worktrees\",\n ),\n );\n const repoKey = repoKeyFor(config.repo);\n const base = path.join(root, repoKey);\n const dir = path.join(base, identity.jobId);\n const markerPath = path.join(base, `${identity.jobId}.marker.json`);\n // repoKey is sanitized and jobId is validated, so these hold by construction \u2014\n // check anyway (defense in depth against a future change loosening either).\n assertUnder(base, dir);\n assertUnder(base, markerPath);\n return { root, repoKey, dir, markerPath };\n}\n\n/**\n * Resolve `target` under `root` following symlinks, tolerating a not-yet-created\n * leaf (probes the deepest EXISTING ancestor). Throws PATH_ESCAPE on any escape.\n * `root` must already exist.\n */\nasync function realpathContained(\n root: string,\n target: string,\n): Promise<string> {\n const realRoot = await realpath(root);\n let probe = path.resolve(target);\n const tail: string[] = [];\n while (!existsSync(probe)) {\n tail.unshift(path.basename(probe));\n const parent = path.dirname(probe);\n if (parent === probe) break;\n probe = parent;\n }\n const realProbe = await realpath(probe);\n const realTarget = tail.length ? path.join(realProbe, ...tail) : realProbe;\n if (realTarget !== realRoot && !realTarget.startsWith(realRoot + path.sep)) {\n throw new WorktreeError(\n \"PATH_ESCAPE\",\n `resolved path ${realTarget} escapes worktree root ${realRoot} (symlink escape refused)`,\n );\n }\n return realTarget;\n}\n\n/**\n * Prove the sibling ownership marker stays under `root` after symlink resolution\n * AND that the marker itself is not a symlink. The marker is a regular file THIS\n * helper owns, so a symlink there is only ever an escape attempt \u2014 including a\n * broken one whose target `realpath` can't resolve (which `realpathContained`\n * would otherwise walk past when probing existing ancestors). Tolerates a\n * not-yet-written marker (create writes it after this check).\n */\nasync function assertMarkerContained(\n root: string,\n markerPath: string,\n): Promise<void> {\n try {\n if ((await lstat(markerPath)).isSymbolicLink()) {\n throw new WorktreeError(\n \"PATH_ESCAPE\",\n `ownership marker path ${markerPath} is a symlink; refusing to follow it (symlink escape refused).`,\n );\n }\n } catch (err) {\n if (err instanceof WorktreeError) throw err;\n // ENOENT: marker not present yet \u2014 fall through to ancestor containment.\n }\n await realpathContained(root, markerPath);\n}\n\nfunction markerMatches(\n marker: WorktreeMarker,\n identity: WorktreeIdentity,\n): boolean {\n return (\n marker.repo === identity.repo &&\n marker.jobId === identity.jobId &&\n marker.stageId === identity.stageId &&\n marker.branch === identity.branch\n );\n}\n\nasync function writeMarker(\n markerPath: string,\n marker: WorktreeMarker,\n): Promise<void> {\n // Owner-only perms: a marker never holds secrets, but the worktree tree beside it\n // may hold copied ignored config, so keep the whole area owner-only by default.\n await writeFile(markerPath, JSON.stringify(marker, null, 2) + \"\\n\", {\n encoding: \"utf8\",\n mode: 0o600,\n });\n}\n\nexport async function readMarker(markerPath: string): Promise<WorktreeMarker> {\n let raw: string;\n try {\n raw = await readFile(markerPath, \"utf8\");\n } catch {\n throw new WorktreeError(\n \"MARKER_MISSING\",\n `ownership marker not found at ${markerPath}`,\n );\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw new WorktreeError(\n \"MARKER_INVALID\",\n `ownership marker at ${markerPath} is not valid JSON`,\n );\n }\n const m = parsed as Record<string, unknown>;\n const ok =\n m &&\n typeof m.repo === \"string\" &&\n typeof m.jobId === \"string\" &&\n typeof m.stageId === \"string\" &&\n typeof m.branch === \"string\" &&\n (m.status === \"active\" || m.status === \"superseded-detached\");\n if (!ok) {\n throw new WorktreeError(\n \"MARKER_INVALID\",\n `ownership marker at ${markerPath} is missing required identifiers`,\n );\n }\n return m as unknown as WorktreeMarker;\n}\n\nasync function branchExists(\n runGit: RunGit,\n checkout: string,\n branch: string,\n): Promise<boolean> {\n const out = (await runGit(checkout, [\"branch\", \"--list\", branch])).trim();\n return out.length > 0;\n}\n\n/**\n * True iff `ref` resolves to a commit in `checkout`. `rev-parse --verify\n * --quiet <ref>^{commit}` prints the commit sha (exit 0) when it resolves and\n * fails (non-zero / empty) otherwise \u2014 so a missing named ref, a tag, or an empty\n * ref all read as \"does not resolve\". Never interprets the mutable HEAD as a base.\n */\nasync function refResolvesToCommit(\n runGit: RunGit,\n checkout: string,\n ref: string,\n): Promise<boolean> {\n try {\n const out = (\n await runGit(checkout, [\n \"rev-parse\",\n \"--verify\",\n \"--quiet\",\n `${ref}^{commit}`,\n ])\n ).trim();\n return out.length > 0;\n } catch {\n return false;\n }\n}\n\n/** The shared object store (`--git-common-dir`), realpath'd \u2014 identifies the repo. */\nasync function commonGitDir(runGit: RunGit, cwd: string): Promise<string> {\n const raw = (await runGit(cwd, [\"rev-parse\", \"--git-common-dir\"])).trim();\n return realpath(path.resolve(cwd, raw));\n}\n\n/**\n * Create a fresh worktree via `git worktree add`. When the stage branch already\n * exists (a retry/restart on the same branch) it is checked out at its current tip;\n * otherwise it is created from the provided `executionBaseRef`. Writes the sibling\n * ownership marker and re-verifies containment after creation.\n */\nexport async function createWorktree(opts: {\n config: WorktreeRepoConfig;\n identity: WorktreeIdentity;\n executionBaseRef: string;\n runGit?: RunGit;\n}): Promise<EnsureWorktreeResult> {\n const runGit = opts.runGit ?? defaultRunGit;\n const { root, dir, markerPath } = resolveWorktreePaths(\n opts.config,\n opts.identity,\n );\n await mkdir(path.dirname(dir), { recursive: true });\n await realpathContained(root, dir);\n // Refuse a pre-planted symlink at the sibling marker path BEFORE `git worktree\n // add`, so create can never write the marker through a symlink out of the root.\n await assertMarkerContained(root, markerPath);\n const marker: WorktreeMarker = { ...opts.identity, status: \"active\" };\n try {\n if (\n await branchExists(runGit, opts.config.checkout, opts.identity.branch)\n ) {\n await runGit(opts.config.checkout, [\n \"worktree\",\n \"add\",\n dir,\n opts.identity.branch,\n ]);\n } else {\n // Verify the resolved executionBaseRef resolves to a commit BEFORE creating\n // the worktree \u2014 a missing named ref yields an actionable MISSING_REF error\n // (a runner lacking the ref fetches ONLY it through the brokered repository\n // boundary) instead of an opaque `git worktree add` failure. This is also the\n // never-substitute-HEAD guard: an empty/unresolvable base ref is refused\n // here, so a fresh branch is never silently cut from the checkout's HEAD.\n if (\n !(await refResolvesToCommit(\n runGit,\n opts.config.checkout,\n opts.executionBaseRef,\n ))\n ) {\n throw new WorktreeError(\n \"MISSING_REF\",\n `executionBaseRef ${JSON.stringify(opts.executionBaseRef)} does not resolve to a commit in ${opts.config.checkout}; fetch only that ref through the brokered repository boundary (e.g. \\`git fetch <remote> ${opts.executionBaseRef}\\`) before creating the worktree for job ${opts.identity.jobId}.`,\n );\n }\n await runGit(opts.config.checkout, [\n \"worktree\",\n \"add\",\n \"-b\",\n opts.identity.branch,\n dir,\n opts.executionBaseRef,\n ]);\n }\n } catch (err) {\n // A typed WorktreeError (e.g. the MISSING_REF pre-check) is already\n // actionable \u2014 surface it verbatim instead of masking it as CREATE_FAILED.\n if (err instanceof WorktreeError) throw err;\n throw new WorktreeError(\n \"CREATE_FAILED\",\n `git worktree add for job ${opts.identity.jobId} (branch ${opts.identity.branch} from ${opts.executionBaseRef}) failed: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n await writeMarker(markerPath, marker);\n await realpathContained(root, dir);\n return { dir, markerPath, marker, created: true };\n}\n\n/**\n * Adopt an EXISTING worktree directory (restart recovery). Succeeds ONLY when the\n * sibling marker AND Git metadata agree on repo/job/stage/branch; any mismatch,\n * path escape, or symlink escape fails closed and the directory is never touched.\n */\nexport async function adoptWorktree(opts: {\n config: WorktreeRepoConfig;\n identity: WorktreeIdentity;\n runGit?: RunGit;\n}): Promise<EnsureWorktreeResult> {\n const runGit = opts.runGit ?? defaultRunGit;\n const { root, dir, markerPath } = resolveWorktreePaths(\n opts.config,\n opts.identity,\n );\n const realDir = await realpathContained(root, dir);\n\n await assertMarkerContained(root, markerPath);\n const marker = await readMarker(markerPath);\n if (!markerMatches(marker, opts.identity)) {\n throw new WorktreeError(\n \"MARKER_MISMATCH\",\n `worktree at ${dir} is owned by ${marker.repo}#${marker.jobId} stage ${marker.stageId} (branch ${marker.branch}), not ${opts.identity.repo}#${opts.identity.jobId} stage ${opts.identity.stageId} (branch ${opts.identity.branch}); refusing to overwrite.`,\n );\n }\n\n const insideWorkTree = (\n await runGit(dir, [\"rev-parse\", \"--is-inside-work-tree\"])\n ).trim();\n if (insideWorkTree !== \"true\") {\n throw new WorktreeError(\"NOT_A_WORKTREE\", `${dir} is not a Git work tree`);\n }\n const topLevel = await realpath(\n (await runGit(dir, [\"rev-parse\", \"--show-toplevel\"])).trim(),\n );\n if (topLevel !== realDir) {\n throw new WorktreeError(\n \"NOT_A_WORKTREE\",\n `${dir} is not the top of its work tree (git reports ${topLevel})`,\n );\n }\n const head = (\n await runGit(dir, [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"])\n ).trim();\n if (head !== opts.identity.branch) {\n throw new WorktreeError(\n \"BRANCH_MISMATCH\",\n `worktree at ${dir} has branch ${head} checked out but the attempt expects ${opts.identity.branch}; refusing to adopt.`,\n );\n }\n const [worktreeRepo, configuredRepo] = await Promise.all([\n commonGitDir(runGit, dir),\n commonGitDir(runGit, opts.config.checkout),\n ]);\n if (worktreeRepo !== configuredRepo) {\n throw new WorktreeError(\n \"REPO_MISMATCH\",\n `worktree at ${dir} belongs to a different repository (${worktreeRepo}) than the configured checkout (${configuredRepo}).`,\n );\n }\n return { dir: realDir, markerPath, marker, created: false };\n}\n\n/** Derive \u2192 adopt if the directory already exists, else create. */\nexport async function ensureWorktree(opts: {\n config: WorktreeRepoConfig;\n identity: WorktreeIdentity;\n executionBaseRef: string;\n runGit?: RunGit;\n}): Promise<EnsureWorktreeResult> {\n const { dir } = resolveWorktreePaths(opts.config, opts.identity);\n if (existsSync(dir)) {\n return adoptWorktree(opts);\n }\n return createWorktree(opts);\n}\n\n/**\n * Free a superseded attempt's stage branch WITHOUT discarding its work: run\n * `git checkout --detach` inside the OLD worktree (preserves all dirty files) and\n * stamp its retained marker `superseded-detached`. The caller must have already\n * proven, from fresh Jentrix state, that the old attempt is superseded \u2014 this helper\n * contains no such policy, only the mechanical, marker-validated detach.\n */\nexport async function detachSupersededWorktree(opts: {\n config: WorktreeRepoConfig;\n /** The OLD (superseded) attempt's identity. */\n identity: WorktreeIdentity;\n runGit?: RunGit;\n}): Promise<{ dir: string; markerPath: string; marker: WorktreeMarker }> {\n const runGit = opts.runGit ?? defaultRunGit;\n const { root, dir, markerPath } = resolveWorktreePaths(\n opts.config,\n opts.identity,\n );\n if (!existsSync(dir)) {\n throw new WorktreeError(\"NOT_FOUND\", `no worktree to detach at ${dir}`);\n }\n const realDir = await realpathContained(root, dir);\n await assertMarkerContained(root, markerPath);\n const marker = await readMarker(markerPath);\n if (!markerMatches(marker, opts.identity)) {\n throw new WorktreeError(\n \"MARKER_MISMATCH\",\n `worktree at ${dir} is not owned by ${opts.identity.repo}#${opts.identity.jobId}; refusing to detach.`,\n );\n }\n // Detach preserves the working tree (tracked + untracked stay on disk).\n await runGit(dir, [\"checkout\", \"--detach\"]);\n const stamped: WorktreeMarker = { ...marker, status: \"superseded-detached\" };\n await writeMarker(markerPath, stamped);\n return { dir: realDir, markerPath, marker: stamped };\n}\n\n/**\n * Commit a parked/abandoned attempt's dirty worktree ONTO its stage branch, so a\n * park never strands work (Harness Reliability W1).\n *\n * An attempt that parks \u2014 cap park, adjudication park, failed turn, killed\n * runner \u2014 never reaches its commit gate. The next attempt gets a FRESH worktree\n * keyed by its own job id and checks out the stage branch at a tip that has none\n * of the prior attempt's changes: the diff is still on disk, but invisible to\n * every reviewer, gate, and operator (M18 needed ten manual rescue commits; one\n * attempt alone left 2,881 uncommitted lines behind).\n *\n * The load-bearing guard is the BRANCH REF, not the commit: a commit made in a\n * DETACHED worktree succeeds and advances nothing, which is exactly how work\n * gets stranded invisibly. So this refuses to commit unless the worktree has the\n * expected branch checked out, and re-reads `refs/heads/<branch>` afterwards to\n * prove the ref actually moved. A clean tree commits nothing (no empty commits,\n * no noise); a missing worktree is `absent`, not an error.\n */\nexport async function checkpointWorktree(opts: {\n config: WorktreeRepoConfig;\n identity: WorktreeIdentity;\n /** Commit message \u2014 the caller names the park reason. */\n message: string;\n runGit?: RunGit;\n}): Promise<CheckpointResult> {\n const runGit = opts.runGit ?? defaultRunGit;\n const { root, dir, markerPath } = resolveWorktreePaths(\n opts.config,\n opts.identity,\n );\n if (!existsSync(dir)) return { committed: false, reason: \"absent\" };\n\n // Same fail-closed validation as every other mutating helper: containment,\n // then the ownership marker, before anything is written.\n await realpathContained(root, dir);\n await assertMarkerContained(root, markerPath);\n const marker = await readMarker(markerPath);\n if (!markerMatches(marker, opts.identity)) {\n throw new WorktreeError(\n \"MARKER_MISMATCH\",\n `worktree at ${dir} is owned by ${marker.repo}#${marker.jobId} (branch ${marker.branch}), not ${opts.identity.repo}#${opts.identity.jobId} (branch ${opts.identity.branch}); refusing to checkpoint it.`,\n );\n }\n\n const porcelain = (await runGit(dir, [\"status\", \"--porcelain\"])).trim();\n if (!porcelain) return { committed: false, reason: \"clean\" };\n\n // A commit only reaches the stage branch from a branch-ATTACHED worktree.\n const head = (\n await runGit(dir, [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"])\n ).trim();\n if (head !== opts.identity.branch) {\n throw new WorktreeError(\n \"CHECKPOINT_UNREACHABLE\",\n `worktree at ${dir} has ${head === \"HEAD\" ? \"a DETACHED HEAD\" : `branch ${head}`} checked out, not ${opts.identity.branch}: a commit here would never advance the stage branch, so ${porcelain.split(\"\\n\").length} uncommitted change(s) cannot be checkpointed. Reconcile that worktree by hand (\\`git -C ${dir} status\\`) before the stage continues.`,\n );\n }\n const branchRef = `refs/heads/${opts.identity.branch}`;\n const before = (await runGit(dir, [\"rev-parse\", branchRef])).trim();\n\n await runGit(dir, [\"add\", \"-A\"]);\n const staged = (await runGit(dir, [\"diff\", \"--cached\", \"--name-only\"]))\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter(Boolean);\n // Porcelain can be non-empty while `add -A` stages nothing (e.g. a path the\n // index already matches). Never create an empty commit.\n if (staged.length === 0) return { committed: false, reason: \"clean\" };\n await runGit(dir, [\"commit\", \"-m\", opts.message]);\n\n const after = (await runGit(dir, [\"rev-parse\", branchRef])).trim();\n if (!after || after === before) {\n throw new WorktreeError(\n \"CHECKPOINT_UNREACHABLE\",\n `checkpoint commit in ${dir} did not advance ${branchRef} (still ${before.slice(0, 12)}); ${staged.length} change(s) remain stranded there. Reconcile that worktree by hand before the stage continues.`,\n );\n }\n return { committed: true, reason: \"committed\", sha: after, files: staged };\n}\n\n/**\n * Safely remove a delivered worktree.\n *\n * Ordering matters:\n * 1. `git worktree prune` FIRST (PRD amendment b), so a worktree that was\n * manually `rm -rf`'d cannot wedge its branch.\n * 2. Validate containment (realpath/symlink) AND the ownership marker immediately\n * before any removal.\n * 3. Classify: `git status --porcelain` (no `--ignored`) surfaces exactly tracked\n * changes + non-ignored untracked files. Non-empty \u21D2 SOURCE-DIRTY \u21D2 retain.\n * 4. Otherwise clean/ignored-only \u21D2 `git clean -fdX` (removes ignored output\n * only), then `git worktree remove` WITHOUT force, then delete the marker.\n *\n * Never recursively deletes an arbitrary path: only git-managed removal + the single\n * derived marker file. The caller decides WHEN cleanup is allowed (terminal state,\n * no active run) \u2014 that policy is not in this helper.\n */\nexport async function cleanupWorktree(opts: {\n config: WorktreeRepoConfig;\n identity: WorktreeIdentity;\n runGit?: RunGit;\n}): Promise<CleanupResult> {\n const runGit = opts.runGit ?? defaultRunGit;\n const { root, dir, markerPath } = resolveWorktreePaths(\n opts.config,\n opts.identity,\n );\n\n // (1) Prune first \u2014 reconcile any manually-deleted worktree so its branch is free.\n await runGit(opts.config.checkout, [\"worktree\", \"prune\"]);\n\n if (!existsSync(dir)) {\n // Already gone (e.g. manually removed). Prune freed the branch; drop the stale\n // marker \u2014 but only after proving it's contained and not a symlink escape.\n if (existsSync(markerPath)) {\n await assertMarkerContained(root, markerPath);\n await rm(markerPath, { force: true });\n }\n return { removed: false, reason: \"absent\" };\n }\n\n // (2) Containment + marker validated immediately before any destructive op.\n const realDir = await realpathContained(root, dir);\n await assertMarkerContained(root, markerPath);\n const marker = await readMarker(markerPath);\n if (!markerMatches(marker, opts.identity)) {\n throw new WorktreeError(\n \"MARKER_MISMATCH\",\n `worktree at ${dir} is owned by ${marker.repo}#${marker.jobId}, not ${opts.identity.repo}#${opts.identity.jobId}; refusing to remove.`,\n );\n }\n\n // (3) Source-dirty classification: any porcelain line = tracked change or\n // non-ignored untracked file (ignored files never appear without --ignored).\n const porcelain = (await runGit(dir, [\"status\", \"--porcelain\"])).trim();\n if (porcelain.length > 0) {\n return {\n removed: false,\n reason: \"source-dirty\",\n dirty: porcelain.split(\"\\n\"),\n };\n }\n\n // (4) Clean or ignored-only: drop disposable ignored output, then remove via git.\n await runGit(dir, [\"clean\", \"-fdX\"]);\n await runGit(opts.config.checkout, [\"worktree\", \"remove\", realDir]);\n await rm(markerPath, { force: true });\n return { removed: true, reason: \"clean\" };\n}\n", "/**\n * DriverExecutionBackend \u2014 the run lifecycle the reference runner executes\n * through (M12.1). It owns LIMIT ENFORCEMENT (the wall-time kill) and turns a\n * driver's raw outcome into the single structured {@link ResultEnvelope}. A run\n * that breaches its CPU or wall-time budget is KILLED and reported as a typed\n * `resource_limit_exceeded` failure \u2014 never left to hang.\n */\nimport {\n parseManifest,\n ResultEnvelopeSchema,\n type CancelRequestInput,\n type Heartbeat,\n type LifecycleState,\n type ResourceUsage,\n type ResultEnvelope,\n type ResultFailure,\n type RunManifest,\n type RunManifestInput,\n} from \"./schemas.js\";\nimport type {\n ClaimRequest,\n ExecutionBackend,\n ExecutionTicket,\n RunOptions,\n Sandbox,\n SandboxDriver,\n} from \"./types.js\";\n\nconst DEFAULT_HEARTBEAT_MS = 5_000;\nconst CANCEL_GRACE_MS = 2_000;\n\ninterface InFlight {\n runId: string;\n manifest?: RunManifest;\n sandbox?: Sandbox;\n startedAt: number;\n state: LifecycleState;\n wallTimer?: ReturnType<typeof setTimeout>;\n heartbeatTimer?: ReturnType<typeof setInterval>;\n walltimeExceeded: boolean;\n canceled: boolean;\n cancelReason?: string;\n settled?: Promise<ResultEnvelope>;\n final?: ResultEnvelope;\n}\n\nexport class DriverExecutionBackend implements ExecutionBackend {\n readonly driver: string;\n private readonly sandboxDriver: SandboxDriver;\n private readonly now: () => number;\n private readonly runs = new Map<string, InFlight>();\n\n constructor(driver: SandboxDriver, opts: { now?: () => number } = {}) {\n this.sandboxDriver = driver;\n this.driver = driver.name;\n this.now = opts.now ?? Date.now;\n }\n\n async claim(req: ClaimRequest): Promise<ExecutionTicket> {\n let rec = this.runs.get(req.runId);\n if (!rec) {\n rec = {\n runId: req.runId,\n startedAt: this.now(),\n state: \"PENDING\",\n walltimeExceeded: false,\n canceled: false,\n };\n this.runs.set(req.runId, rec);\n }\n return {\n runId: req.runId,\n claimedAt: new Date(this.now()).toISOString(),\n state: rec.state,\n };\n }\n\n async run(input: RunManifest, opts: RunOptions = {}): Promise<ResultEnvelope> {\n const manifest = parseManifest(input);\n const log = opts.log ?? (() => {});\n const rec: InFlight = this.runs.get(manifest.runId) ?? {\n runId: manifest.runId,\n startedAt: this.now(),\n state: \"PENDING\",\n walltimeExceeded: false,\n canceled: false,\n };\n rec.manifest = manifest;\n rec.startedAt = this.now();\n rec.state = \"STARTING\";\n rec.walltimeExceeded = false;\n rec.canceled = false;\n rec.final = undefined;\n this.runs.set(manifest.runId, rec);\n\n let sandbox: Sandbox;\n try {\n sandbox = await this.sandboxDriver.create(manifest, {\n signal: opts.signal,\n inProcessRunner: opts.inProcessRunner,\n log,\n });\n } catch (err) {\n // The sandbox could not be provisioned \u2014 a structured startup failure.\n const envelope = this.finalize(rec, {\n status: \"failed\",\n state: \"FAILED\",\n exitCode: null,\n stdout: \"\",\n stderr: err instanceof Error ? err.message : String(err),\n summary: \"\",\n failure: {\n kind: \"startup_error\",\n limit: null,\n message: err instanceof Error ? err.message : String(err),\n signal: null,\n },\n });\n return envelope;\n }\n\n rec.sandbox = sandbox;\n rec.state = \"RUNNING\";\n\n // WALL-TIME ENFORCEMENT: the backend's own deadline. On breach it kills the\n // sandbox with a `wall_time` reason so the outcome resolves promptly.\n rec.wallTimer = setTimeout(() => {\n rec.walltimeExceeded = true;\n rec.state = \"TIMED_OUT\";\n log(\n `[execution ${manifest.runId}] wall-time budget ${manifest.limits.wallMs}ms exceeded \u2014 killing.`,\n );\n void sandbox.kill({\n reason: \"wall-time budget exceeded\",\n limit: \"wall_time\",\n graceMs: CANCEL_GRACE_MS,\n });\n }, manifest.limits.wallMs);\n // NOTE: the wall timer is intentionally NOT unref'd \u2014 it is the load-bearing\n // deadline enforcement. It is cleared the moment the run settles.\n\n // Optional heartbeat sampling.\n const hbMs = opts.heartbeatMs ?? DEFAULT_HEARTBEAT_MS;\n if (opts.onHeartbeat && hbMs > 0) {\n rec.heartbeatTimer = setInterval(() => {\n void this.heartbeat(manifest.runId)\n .then((hb) => opts.onHeartbeat?.(hb))\n .catch(() => {});\n }, hbMs);\n (rec.heartbeatTimer as { unref?: () => void }).unref?.();\n }\n\n const settled = (async (): Promise<ResultEnvelope> => {\n const outcome = await sandbox.wait();\n if (rec.wallTimer) clearTimeout(rec.wallTimer);\n if (rec.heartbeatTimer) clearInterval(rec.heartbeatTimer);\n // Best-effort cleanup (idempotent).\n await this.sandboxDriver.terminate(sandbox).catch(() => {});\n\n let status: ResultEnvelope[\"status\"];\n let state: LifecycleState;\n let failure: ResultFailure | null = null;\n\n if (rec.canceled && !rec.walltimeExceeded) {\n status = \"canceled\";\n state = \"CANCELED\";\n failure = {\n kind: \"canceled\",\n limit: null,\n message: rec.cancelReason ?? \"run canceled\",\n signal: outcome.signal,\n };\n } else if (rec.walltimeExceeded) {\n status = \"timed_out\";\n state = \"TIMED_OUT\";\n failure = {\n kind: \"resource_limit_exceeded\",\n limit: \"wall_time\",\n message: `wall-time budget of ${manifest.limits.wallMs}ms exceeded`,\n signal: outcome.signal,\n };\n } else if (outcome.resourceLimit) {\n // The driver observed a CPU/memory/disk kill (e.g. SIGXCPU).\n status = \"failed\";\n state = \"KILLED\";\n failure = {\n kind: \"resource_limit_exceeded\",\n limit: outcome.resourceLimit,\n message: `${outcome.resourceLimit} budget exceeded \u2014 run killed`,\n signal: outcome.signal,\n };\n } else if (outcome.exitCode === 0) {\n status = \"succeeded\";\n state = \"SUCCEEDED\";\n } else {\n status = \"failed\";\n state = \"FAILED\";\n failure = {\n kind: outcome.exitCode === null ? \"driver_error\" : \"nonzero_exit\",\n limit: null,\n message:\n outcome.exitCode === null\n ? outcome.stderr || \"run ended without an exit code\"\n : `run exited with code ${outcome.exitCode}`,\n signal: outcome.signal,\n };\n }\n\n return this.finalize(rec, {\n status,\n state,\n exitCode: outcome.exitCode,\n stdout: outcome.stdout,\n stderr: outcome.stderr,\n summary: outcome.summary ?? \"\",\n failure,\n });\n })();\n\n rec.settled = settled;\n return settled;\n }\n\n async heartbeat(runId: string): Promise<Heartbeat> {\n const rec = this.runs.get(runId);\n if (!rec) throw new Error(`heartbeat: unknown run ${runId}`);\n if (rec.final) {\n return {\n runId,\n state: rec.final.state,\n at: new Date(this.now()).toISOString(),\n usage: rec.final.usage,\n wallRemainingMs: 0,\n };\n }\n const usage: ResourceUsage = rec.sandbox\n ? await rec.sandbox.usage()\n : { wallMs: Math.max(0, this.now() - rec.startedAt) };\n const wallMs = rec.manifest?.limits.wallMs;\n return {\n runId,\n state: rec.state,\n at: new Date(this.now()).toISOString(),\n usage,\n ...(wallMs !== undefined\n ? { wallRemainingMs: wallMs - usage.wallMs }\n : {}),\n };\n }\n\n async cancel(req: CancelRequestInput | string): Promise<ResultEnvelope> {\n const runId = typeof req === \"string\" ? req : req.runId;\n const reason =\n typeof req === \"string\" ? \"canceled\" : (req.reason ?? \"canceled\");\n const graceMs =\n typeof req === \"string\" ? CANCEL_GRACE_MS : (req.graceMs ?? CANCEL_GRACE_MS);\n const rec = this.runs.get(runId);\n if (!rec) throw new Error(`cancel: unknown run ${runId}`);\n if (rec.final) return rec.final;\n rec.canceled = true;\n rec.cancelReason = reason;\n rec.state = \"CANCELED\";\n if (rec.sandbox) {\n await rec.sandbox.kill({ reason, graceMs }).catch(() => {});\n }\n if (rec.settled) return rec.settled;\n // Claimed but never run: synthesize a canceled terminal envelope.\n return this.finalize(rec, {\n status: \"canceled\",\n state: \"CANCELED\",\n exitCode: null,\n stdout: \"\",\n stderr: \"\",\n summary: \"\",\n failure: { kind: \"canceled\", limit: null, message: reason, signal: null },\n });\n }\n\n async report(runId: string): Promise<ResultEnvelope | null> {\n return this.runs.get(runId)?.final ?? null;\n }\n\n /** Build, validate, store, and return the terminal envelope for a run. */\n private finalize(\n rec: InFlight,\n parts: {\n status: ResultEnvelope[\"status\"];\n state: LifecycleState;\n exitCode: number | null;\n stdout: string;\n stderr: string;\n summary: string;\n failure: ResultFailure | null;\n },\n ): ResultEnvelope {\n const endedAt = this.now();\n const envelope = ResultEnvelopeSchema.parse({\n runId: rec.runId,\n driver: this.driver,\n status: parts.status,\n state: parts.state,\n exitCode: parts.exitCode,\n startedAt: new Date(rec.startedAt).toISOString(),\n endedAt: new Date(endedAt).toISOString(),\n usage: { wallMs: Math.max(0, endedAt - rec.startedAt) },\n stdout: parts.stdout,\n stderr: parts.stderr,\n summary: parts.summary || lastNonEmptyLine(parts.stdout),\n failure: parts.failure,\n } satisfies Record<string, unknown>);\n rec.final = envelope;\n rec.state = envelope.state;\n rec.sandbox = undefined;\n return envelope;\n }\n}\n\nfunction lastNonEmptyLine(text: string): string {\n const lines = text\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter(Boolean);\n return lines.length ? lines[lines.length - 1] : \"\";\n}\n\n/** Convenience factory. */\nexport function createExecutionBackend(\n driver: SandboxDriver,\n opts: { now?: () => number } = {},\n): ExecutionBackend {\n return new DriverExecutionBackend(driver, opts);\n}\n", "/**\n * Shared driver plumbing: env-allowlist resolution, a minimal spawn seam (so\n * tests can drive drivers without a real subprocess/daemon), and stream capture.\n */\nimport { spawn as nodeSpawn } from \"node:child_process\";\nimport type { Readable } from \"node:stream\";\n\nimport type { RunManifest } from \"../schemas.js\";\n\n/**\n * The env passed INTO a sandbox is deny-by-default: only names in the manifest's\n * `envAllowlist` are eligible, taking their value from the manifest's explicit\n * `env` first, else the provided base env (the host process env). Anything not on\n * the allowlist is dropped \u2014 a sandbox never silently inherits the host's secrets.\n */\nexport function resolveSandboxEnv(\n manifest: RunManifest,\n baseEnv: NodeJS.ProcessEnv = process.env,\n): Record<string, string> {\n const out: Record<string, string> = {};\n for (const name of manifest.envAllowlist) {\n if (Object.prototype.hasOwnProperty.call(manifest.env, name)) {\n out[name] = manifest.env[name];\n } else if (typeof baseEnv[name] === \"string\") {\n out[name] = baseEnv[name] as string;\n }\n }\n // Explicit manifest.env entries that are ALSO on the allowlist are already\n // covered above; entries off the allowlist are intentionally not passed.\n return out;\n}\n\n/** A child process, narrowed to what the drivers use (Node's ChildProcess fits). */\nexport interface ChildLike {\n readonly pid?: number;\n readonly stdout: Readable | null;\n readonly stderr: Readable | null;\n on(event: \"error\", cb: (err: Error) => void): unknown;\n /** Fires after the process exits AND its stdio has flushed/closed. */\n on(\n event: \"close\",\n cb: (code: number | null, signal: NodeJS.Signals | null) => void,\n ): unknown;\n kill(signal?: NodeJS.Signals | number): boolean;\n}\n\n/** Injectable spawn seam \u2014 defaults to node:child_process.spawn. */\nexport type SpawnFn = (\n command: string,\n args: string[],\n options: {\n cwd?: string;\n env?: NodeJS.ProcessEnv;\n detached?: boolean;\n },\n) => ChildLike;\n\nexport const defaultSpawn: SpawnFn = (command, args, options) =>\n nodeSpawn(command, args, {\n cwd: options.cwd,\n env: options.env,\n detached: options.detached,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n }) as unknown as ChildLike;\n\n/** Accumulate a readable stream into a bounded string (guards against a flood). */\nexport function captureStream(\n stream: Readable | null,\n onChunk: (text: string) => void,\n maxBytes = 1_000_000,\n): void {\n if (!stream) return;\n let total = 0;\n stream.setEncoding(\"utf8\");\n stream.on(\"data\", (chunk: string) => {\n if (total >= maxBytes) return;\n total += Buffer.byteLength(chunk);\n onChunk(chunk);\n });\n}\n\n/** The final non-empty line of text \u2014 the reference runner's turn summary. */\nexport function lastLine(text: string): string {\n const lines = text\n .split(\"\\n\")\n .map((l) => l.trimEnd())\n .filter((l) => l.trim().length > 0);\n return lines.length ? lines[lines.length - 1] : \"\";\n}\n", "/**\n * HostProcessDriver \u2014 the reference runner's former direct-exec path, preserved\n * behind the SandboxDriver contract (M12.1).\n *\n * Two modes, chosen by the manifest:\n * \u2022 `inProcess: true` \u2014 runs the caller-supplied {@link InProcessRunner} in THIS\n * process (the reference runner's agent turn). This is the byte-for-byte prior\n * behavior, so Jentrix-side records are identical to the pre-refactor runner.\n * Wall-time/cancel are enforced by aborting the turn's AbortSignal (JS can't be\n * preempted, so a runner that ignores the signal is force-settled after a grace).\n * \u2022 otherwise \u2014 spawns `command` as a real subprocess. CPU-time is enforced with\n * `ulimit -t` (a breach delivers SIGXCPU \u2192 the driver reports a `cpu` kill);\n * wall-time is enforced by the ExecutionBackend killing the process group.\n *\n * Host processes share the host network, so the egress profile is ADVISORY here \u2014\n * true deny-by-default network isolation is the LocalDockerDriver's job.\n */\nimport type {\n LifecycleState,\n RunManifest,\n ResourceLimitKind,\n ResourceUsage,\n} from \"../schemas.js\";\nimport type {\n DriverRunOptions,\n ExecOutcome,\n InProcessRunner,\n Sandbox,\n SandboxDriver,\n SandboxHandle,\n SnapshotRef,\n} from \"../types.js\";\nimport {\n captureStream,\n defaultSpawn,\n lastLine,\n resolveSandboxEnv,\n type ChildLike,\n type SpawnFn,\n} from \"./shared.js\";\n\nconst DRIVER = \"host-process\";\n\nexport interface HostProcessDriverOptions {\n /** Injectable spawn seam (tests). Defaults to node:child_process.spawn. */\n spawn?: SpawnFn;\n /** Base env the allowlist filters (defaults to process.env). */\n baseEnv?: NodeJS.ProcessEnv;\n /** Injectable clock (ms). Defaults to Date.now. */\n now?: () => number;\n}\n\ntype State = LifecycleState;\n\n/** Shell prelude that applies POSIX rlimits before exec-ing the run's argv. */\nfunction ulimitPrelude(manifest: RunManifest): string {\n const parts: string[] = [];\n const cpuMs = manifest.limits.cpuMs;\n if (cpuMs) {\n // RLIMIT_CPU is whole seconds; round UP so a sub-second budget still bounds.\n const cpuSec = Math.max(1, Math.ceil(cpuMs / 1000));\n parts.push(`ulimit -t ${cpuSec} 2>/dev/null || true`);\n }\n if (manifest.limits.memoryBytes) {\n // Virtual-memory ceiling in KB. Unsupported on some platforms (macOS) \u2014 the\n // `|| true` keeps it best-effort; Docker's --memory is the real enforcement.\n const kb = Math.max(1, Math.ceil(manifest.limits.memoryBytes / 1024));\n parts.push(`ulimit -v ${kb} 2>/dev/null || true`);\n }\n if (manifest.limits.diskBytes) {\n // Max file size in 1024-byte blocks (best-effort disk proxy).\n const blocks = Math.max(1, Math.ceil(manifest.limits.diskBytes / 1024));\n parts.push(`ulimit -f ${blocks} 2>/dev/null || true`);\n }\n return parts.length ? parts.join(\"; \") + \"; \" : \"\";\n}\n\n/** A run backed by a real host subprocess. */\nclass SubprocessSandbox implements Sandbox {\n readonly handle: SandboxHandle;\n private _state: State = \"STARTING\";\n private readonly child: ChildLike;\n private readonly startedAt: number;\n private readonly now: () => number;\n private stdout = \"\";\n private stderr = \"\";\n private killedByUs = false;\n private killLimit: ResourceLimitKind | null = null;\n private readonly outcome: Promise<ExecOutcome>;\n\n constructor(\n manifest: RunManifest,\n spawn: SpawnFn,\n baseEnv: NodeJS.ProcessEnv,\n now: () => number,\n ) {\n this.now = now;\n this.startedAt = now();\n if (manifest.command.length === 0) {\n throw new Error(\n \"HostProcessDriver: a subprocess manifest must declare a non-empty `command`.\",\n );\n }\n const cwd =\n manifest.workdir ??\n (manifest.codeSnapshot.kind === \"checkout\"\n ? manifest.codeSnapshot.path\n ? `${manifest.codeSnapshot.ref}/${manifest.codeSnapshot.path}`\n : manifest.codeSnapshot.ref\n : undefined);\n const script = `${ulimitPrelude(manifest)}exec \"$@\"`;\n // The sandbox env is deny-by-default (allowlist-gated). PATH is INFRASTRUCTURE,\n // not host state \u2014 inject a baseline so the shell and coreutils resolve; without\n // it a host run cannot even find `sh`. Everything else stays allowlist-gated.\n const sandboxEnv = resolveSandboxEnv(manifest, baseEnv);\n if (!sandboxEnv.PATH) {\n sandboxEnv.PATH = baseEnv.PATH ?? \"/usr/bin:/bin:/usr/sbin:/sbin\";\n }\n // detached \u2192 the child leads its own process group, so a wall-time/cancel\n // kill can signal the WHOLE group (the shell plus anything it spawned).\n this.child = spawn(\n \"/bin/sh\",\n [\"-c\", script, \"stacks-sandbox\", ...manifest.command],\n {\n cwd,\n env: sandboxEnv,\n detached: true,\n },\n );\n this._state = \"RUNNING\";\n this.handle = {\n driver: DRIVER,\n id: this.child.pid ? String(this.child.pid) : \"unknown\",\n runId: manifest.runId,\n createdAt: new Date(this.startedAt).toISOString(),\n meta: { pid: this.child.pid },\n };\n captureStream(this.child.stdout, (t) => (this.stdout += t));\n captureStream(this.child.stderr, (t) => (this.stderr += t));\n\n this.outcome = new Promise<ExecOutcome>((resolve) => {\n let settled = false;\n const settle = (o: ExecOutcome) => {\n if (settled) return;\n settled = true;\n resolve(o);\n };\n this.child.on(\"error\", (err) => {\n this._state = \"FAILED\";\n settle({\n exitCode: null,\n signal: null,\n stdout: this.stdout,\n stderr: this.stderr || String(err?.message ?? err),\n killed: this.killedByUs,\n summary: lastLine(this.stdout),\n });\n });\n this.child.on(\"close\", (code, signal) => {\n // SIGXCPU is the kernel's RLIMIT_CPU breach signal \u2014 a `cpu` kill the\n // driver itself observed (distinct from a backend-initiated wall-time kill).\n const resourceLimit: ResourceLimitKind | null =\n this.killLimit ?? (signal === \"SIGXCPU\" ? \"cpu\" : null);\n this._state = code === 0 ? \"SUCCEEDED\" : \"FAILED\";\n settle({\n exitCode: code,\n signal,\n stdout: this.stdout,\n stderr: this.stderr,\n killed: this.killedByUs,\n resourceLimit,\n summary: lastLine(this.stdout),\n });\n });\n });\n }\n\n get state(): State {\n return this._state;\n }\n\n wait(): Promise<ExecOutcome> {\n return this.outcome;\n }\n\n async kill(req?: {\n reason?: string;\n limit?: ResourceLimitKind;\n graceMs?: number;\n }): Promise<void> {\n this.killedByUs = true;\n this.killLimit = req?.limit ?? null;\n const grace = req?.graceMs ?? 2000;\n const signalGroup = (sig: NodeJS.Signals) => {\n const pid = this.child.pid;\n try {\n if (pid) process.kill(-pid, sig);\n else this.child.kill(sig);\n } catch {\n // Already gone / not permitted \u2014 fall back to a direct child kill.\n try {\n this.child.kill(sig);\n } catch {\n /* already dead */\n }\n }\n };\n signalGroup(\"SIGTERM\");\n const timer = setTimeout(() => signalGroup(\"SIGKILL\"), grace);\n (timer as { unref?: () => void }).unref?.();\n }\n\n async usage(): Promise<ResourceUsage> {\n return { wallMs: Math.max(0, this.now() - this.startedAt) };\n }\n}\n\n/** A run backed by an in-process turn (the reference runner's direct-exec path). */\nclass InProcessSandbox implements Sandbox {\n readonly handle: SandboxHandle;\n private _state: State = \"RUNNING\";\n private readonly controller = new AbortController();\n private readonly startedAt: number;\n private readonly now: () => number;\n private killed = false;\n private killLimit: ResourceLimitKind | null = null;\n private readonly outcome: Promise<ExecOutcome>;\n private settleFn!: (o: ExecOutcome) => void;\n private done = false;\n\n constructor(\n manifest: RunManifest,\n runner: InProcessRunner,\n opts: DriverRunOptions,\n now: () => number,\n ) {\n this.now = now;\n this.startedAt = now();\n this.handle = {\n driver: DRIVER,\n id: `inproc-${manifest.runId}`,\n runId: manifest.runId,\n createdAt: new Date(this.startedAt).toISOString(),\n };\n this.outcome = new Promise<ExecOutcome>((resolve) => {\n this.settleFn = (o) => {\n if (this.done) return;\n this.done = true;\n resolve(o);\n };\n });\n // A caller cancel (opts.signal) is a freeze/cancel \u2014 abort the turn.\n if (opts.signal) {\n if (opts.signal.aborted) void this.kill({ reason: \"canceled\" });\n else\n opts.signal.addEventListener(\n \"abort\",\n () => void this.kill({ reason: \"canceled\" }),\n { once: true },\n );\n }\n runner({ manifest, signal: this.controller.signal })\n .then((r) => {\n this._state = this.killed ? \"KILLED\" : \"SUCCEEDED\";\n this.settleFn({\n exitCode: r.exitCode ?? 0,\n signal: null,\n stdout: r.summary,\n stderr: \"\",\n summary: r.summary,\n killed: this.killed,\n resourceLimit: this.killLimit,\n });\n })\n .catch((err: unknown) => {\n this._state = \"FAILED\";\n this.settleFn({\n exitCode: 1,\n signal: null,\n stdout: \"\",\n stderr: err instanceof Error ? err.message : String(err),\n summary: \"\",\n killed: this.killed,\n resourceLimit: this.killLimit,\n });\n });\n }\n\n get state(): State {\n return this._state;\n }\n\n wait(): Promise<ExecOutcome> {\n return this.outcome;\n }\n\n async kill(req?: {\n reason?: string;\n limit?: ResourceLimitKind;\n graceMs?: number;\n }): Promise<void> {\n this.killed = true;\n this.killLimit = req?.limit ?? null;\n this._state = req?.limit === \"wall_time\" ? \"TIMED_OUT\" : \"KILLED\";\n this.controller.abort();\n // JS can't be preempted: if the turn ignores the abort, force-settle after a\n // grace so the backend never hangs waiting on a runaway in-process run.\n const grace = req?.graceMs ?? 2000;\n // Ref'd on purpose: this force-settle is the backstop for a runner that\n // ignores the abort \u2014 it must fire even if nothing else keeps the loop alive.\n setTimeout(() => {\n this.settleFn({\n exitCode: null,\n signal: \"SIGKILL\",\n stdout: \"\",\n stderr: \"in-process run did not stop on abort within the grace period\",\n summary: \"\",\n killed: true,\n resourceLimit: this.killLimit,\n });\n }, grace);\n }\n\n async usage(): Promise<ResourceUsage> {\n return { wallMs: Math.max(0, this.now() - this.startedAt) };\n }\n}\n\nexport class HostProcessDriver implements SandboxDriver {\n readonly name = DRIVER;\n private readonly spawn: SpawnFn;\n private readonly baseEnv: NodeJS.ProcessEnv;\n private readonly now: () => number;\n\n constructor(opts: HostProcessDriverOptions = {}) {\n this.spawn = opts.spawn ?? defaultSpawn;\n this.baseEnv = opts.baseEnv ?? process.env;\n this.now = opts.now ?? Date.now;\n }\n\n async create(\n manifest: RunManifest,\n opts: DriverRunOptions = {},\n ): Promise<Sandbox> {\n if (manifest.inProcess) {\n if (!opts.inProcessRunner) {\n throw new Error(\n \"HostProcessDriver: an in-process manifest requires an inProcessRunner.\",\n );\n }\n return new InProcessSandbox(\n manifest,\n opts.inProcessRunner,\n opts,\n this.now,\n );\n }\n return new SubprocessSandbox(manifest, this.spawn, this.baseEnv, this.now);\n }\n\n async resume(): Promise<Sandbox> {\n // Host subprocesses are ephemeral to this process \u2014 nothing to re-attach to.\n throw new Error(\n \"HostProcessDriver does not support resume(): host runs are ephemeral.\",\n );\n }\n\n async snapshot(): Promise<SnapshotRef> {\n throw new Error(\"HostProcessDriver does not support snapshot().\");\n }\n\n async terminate(sandbox: Sandbox): Promise<void> {\n // Best-effort: ensure nothing lingers.\n await sandbox.kill({ reason: \"terminate\", graceMs: 0 }).catch(() => {});\n }\n}\n", "/**\n * LocalDockerDriver \u2014 runs each run in an EPHEMERAL container over a preconfigured\n * checkout, with enforced resource limits and a DENY-BY-DEFAULT egress profile (M12.1).\n *\n * Resource enforcement is delegated to the kernel via docker flags: `--cpus`\n * (throttle) + `--ulimit cpu` (hard CPU-time budget; a breach kills the run \u2014 SIGXCPU\n * on some platforms, SIGKILL/exit-137 on Docker Desktop's Linux VM), `--memory` (OOM\n * kill), `--ulimit fsize` (disk/file-size), `--pids-limit`. Wall-time is enforced\n * by the ExecutionBackend (which `kill()`s the container). Egress is `--network none`\n * UNLESS the operator sets STACKS_SANDBOX_ALLOW_NET=1 \u2014 the single dev bypass, off by\n * default, mirroring the webhook SSRF allow-flag (STACKS_WEBHOOK_ALLOW_PRIVATE).\n */\nimport type {\n EgressProfile,\n LifecycleState,\n RunManifest,\n ResourceLimitKind,\n ResourceUsage,\n RuntimeClass,\n} from \"../schemas.js\";\nimport type {\n DriverRunOptions,\n ExecOutcome,\n Sandbox,\n SandboxDriver,\n SandboxHandle,\n SnapshotRef,\n} from \"../types.js\";\nimport {\n captureStream,\n defaultSpawn,\n lastLine,\n resolveSandboxEnv,\n type ChildLike,\n type SpawnFn,\n} from \"./shared.js\";\n\nconst DRIVER = \"local-docker\";\n/** Default mount point + workdir for a bind-mounted checkout. */\nconst DEFAULT_WORKDIR = \"/workspace\";\n/**\n * The Docker host-gateway alias. When a run has network, the container reaches\n * host-run services (the Jentrix MCP server, the provider API proxy) through this\n * name. Docker Desktop resolves it automatically, but a Linux engine needs the\n * explicit `--add-host \u2026:host-gateway` this driver adds.\n */\nexport const HOST_GATEWAY_ALIAS = \"host.docker.internal\";\n\nexport interface LocalDockerDriverOptions {\n /** The preconfigured runner image for `checkout`-kind snapshots. */\n image?: string;\n /** Injectable command runner (tests). Defaults to node:child_process.spawn. */\n spawn?: SpawnFn;\n /** The docker binary (default \"docker\"). */\n dockerPath?: string;\n /** Base env the allowlist filters (defaults to process.env). */\n baseEnv?: NodeJS.ProcessEnv;\n /** Injectable clock (ms). Defaults to Date.now. */\n now?: () => number;\n /**\n * Whether the operator has opted into sandbox network egress. Default reads\n * STACKS_SANDBOX_ALLOW_NET === \"1\". Even when true, a `deny` egress profile\n * still gets no network \u2014 the flag only lets a non-deny profile take effect.\n */\n allowNet?: () => boolean;\n /**\n * The URL of a running egress proxy that enforces + audits the run's allowlist.\n * When set, an `allowlist`-profile run is routed THROUGH the proxy (the accepted\n * allowlisted data path) instead of fail-closing to deny. Injectable as a\n * function so a per-run proxy can be started lazily.\n */\n egressProxyUrl?: () => string | undefined;\n /**\n * The per-run user-defined Docker network the sandbox joins to reach an\n * in-container (sidecar) egress gateway by DNS name. When set (alongside a\n * matching `egressProxyUrl`), an `allowlist` run is `--network`'d onto it \u2014 the\n * firewall-independent in-container allowlisted egress path. Injectable as a\n * function so a per-run network can be created lazily.\n */\n egressNetwork?: () => string | undefined;\n /**\n * Container-name prefix (default `stacks-run-`). The managed EVAL path sets\n * `stacks-eval-` so a container is deterministically `stacks-eval-<runId>`\n * (runId = the sandboxRun id) \u2014 the R10 orphan-reaping contract: a worker can\n * list + reap its own containers by name/label after a crash.\n */\n namePrefix?: string;\n /**\n * Driver-level labels stamped on EVERY run (e.g. `{ \"stacks.kind\": \"eval\" }`),\n * merged under the canonical `stacks.runId` and the per-run manifest labels. A\n * reconciler filters a class of containers with `docker ps --filter label=\u2026`.\n */\n labels?: Record<string, string>;\n log?: (msg: string) => void;\n}\n\n/** The default container-name prefix (harness/generic runs). */\nexport const DEFAULT_CONTAINER_NAME_PREFIX = \"stacks-run-\";\n\n/** Docker container/object names must match [a-zA-Z0-9][a-zA-Z0-9_.-]*. */\nfunction sanitizeName(\n runId: string,\n prefix: string = DEFAULT_CONTAINER_NAME_PREFIX,\n): string {\n const cleaned = runId.replace(/[^a-zA-Z0-9_.-]/g, \"-\");\n return `${prefix}${cleaned}`.slice(0, 200);\n}\n\n/**\n * The Docker `--runtime` value for a runtime class. `runc` is the daemon default\n * (no flag). `gvisor` maps to `runsc`; `microvm` to `kata-runtime`. The MANAGED\n * runtime installs these (M12 infra-a/infra-b) \u2014 the local driver simply passes the\n * flag through, so a host without the runtime installed surfaces a clear docker\n * error rather than silently dropping the isolation request.\n */\nconst RUNTIME_FLAG: Record<RuntimeClass, string | null> = {\n runc: null,\n gvisor: \"runsc\",\n microvm: \"kata-runtime\",\n};\n\n/** The `--runtime <name>` args for a manifest's runtime class ([] for stock runc). */\nexport function runtimeArgs(runtimeClass: RuntimeClass | undefined): string[] {\n if (!runtimeClass) return [];\n const flag = RUNTIME_FLAG[runtimeClass];\n return flag ? [\"--runtime\", flag] : [];\n}\n\n/** Whether the run gets network: the operator flag AND a non-deny egress profile. */\nexport function egressAllowsNetwork(\n manifest: RunManifest,\n allowNet: boolean,\n): boolean {\n return allowNet && manifest.egress.mode !== \"deny\";\n}\n\n/**\n * The egress posture the driver ACTUALLY enforces for a run (real enforcement, not\n * the declared intent). Deny-by-default is enforced at the kernel via `--network\n * none`; a non-deny profile only takes effect when the operator opted into\n * `STACKS_SANDBOX_ALLOW_NET` \u2014 otherwise the local driver has no per-host egress\n * proxy and DOWNGRADES the run to `deny` (fail-closed). The result is data the\n * sandbox controller records + audits, so the run record shows what network the\n * container really got rather than only what it asked for.\n */\nexport interface EgressEnforcement {\n /** What the manifest declared. */\n requestedMode: EgressProfile[\"mode\"];\n /** What the driver actually applied at the kernel (`--network none` \u21D2 \"deny\"). */\n enforcedMode: EgressProfile[\"mode\"];\n /** Whether the container got a network at all. */\n netEnabled: boolean;\n /** True when a non-deny request was fail-closed to deny (no local egress proxy). */\n downgraded: boolean;\n /**\n * The egress proxy URL the container is pointed at (via HTTP(S)_PROXY) when an\n * `allowlist` profile is enforced through a proxy \u2014 the REAL allowlisted egress\n * data path. Undefined for deny / direct-net runs.\n */\n proxyUrl?: string;\n /**\n * The user-defined Docker network the sandbox is attached to when the allowlist\n * gateway runs as an in-container sidecar (the sandbox reaches the gateway by\n * container DNS name on this network \u2014 the firewall-independent in-container\n * data path). Undefined when the proxy is host-bound / for deny/direct-net runs.\n */\n network?: string;\n /** Human-readable reason for the enforced posture. */\n reason: string;\n}\n\n/** Options controlling how egress is enforced (an allowlist egress proxy). */\nexport interface EgressEnforcementOptions {\n /**\n * A running egress proxy's URL. When set, an `allowlist` profile is HONORED by\n * routing the container's egress through the proxy (which enforces + audits the\n * allowlist) instead of fail-closing to deny \u2014 the accepted allowlisted data\n * path. Deny and open profiles ignore it.\n */\n proxyUrl?: string;\n /**\n * A user-defined Docker network the sandbox joins to reach an in-container\n * (sidecar) egress gateway by DNS name. When set alongside `proxyUrl` for an\n * `allowlist` run, the sandbox is `--network`'d onto it instead of getting the\n * host-gateway bridge \u2014 so the container\u2192gateway hop routes regardless of the\n * host firewall (the zero-skip in-container path).\n */\n network?: string;\n}\n\n/** Resolve the network posture the driver enforces for a manifest (pure, testable). */\nexport function resolveEgressEnforcement(\n manifest: RunManifest,\n allowNet: boolean,\n opts: EgressEnforcementOptions = {},\n): EgressEnforcement {\n const requestedMode = manifest.egress.mode;\n\n // The ACCEPTED allowlisted data path: an `allowlist` profile with a configured\n // egress proxy is honored by routing egress THROUGH the proxy (the proxy is the\n // enforcement + audit choke point), so the run gets a network locked to the\n // allowlist \u2014 no operator allow-net flag required.\n if (requestedMode === \"allowlist\" && opts.proxyUrl) {\n return {\n requestedMode,\n enforcedMode: \"allowlist\",\n netEnabled: true,\n downgraded: false,\n proxyUrl: opts.proxyUrl,\n ...(opts.network ? { network: opts.network } : {}),\n reason: opts.network\n ? `egress \"allowlist\" honored via in-container gateway on network ${opts.network} (${opts.proxyUrl})`\n : `egress \"allowlist\" honored via egress proxy (${opts.proxyUrl})`,\n };\n }\n\n const netEnabled = egressAllowsNetwork(manifest, allowNet);\n const enforcedMode: EgressProfile[\"mode\"] = netEnabled\n ? requestedMode\n : \"deny\";\n const downgraded = requestedMode !== \"deny\" && !netEnabled;\n const reason = netEnabled\n ? `egress \"${requestedMode}\" honored (STACKS_SANDBOX_ALLOW_NET set)`\n : requestedMode === \"deny\"\n ? \"deny-by-default: --network none (no egress declared)\"\n : `egress \"${requestedMode}\" requested but STACKS_SANDBOX_ALLOW_NET not set \u2014 ` +\n \"fail-closed to --network none (no local egress proxy)\";\n return { requestedMode, enforcedMode, netEnabled, downgraded, reason };\n}\n\n/**\n * Build the `docker run` argv for a manifest. Pure + exported so the argv (resource\n * flags, `--network none`, mounts, env) is unit-testable without a docker daemon.\n */\n/**\n * Rewrite a localhost egress-proxy URL so a container can reach it: the proxy\n * binds to the host's loopback, which inside a container is the container itself\n * \u2014 the Docker host gateway alias is how the container reaches the host.\n */\nexport function containerProxyUrl(proxyUrl: string): string {\n return proxyUrl.replace(\n /127\\.0\\.0\\.1|0\\.0\\.0\\.0|localhost|\\[::1\\]/,\n HOST_GATEWAY_ALIAS,\n );\n}\n\nexport function buildDockerArgs(\n manifest: RunManifest,\n opts: {\n image?: string;\n netEnabled: boolean;\n baseEnv?: NodeJS.ProcessEnv;\n /** When set, inject HTTP(S)_PROXY so all egress routes through the allowlist proxy. */\n proxyUrl?: string;\n /**\n * When set, attach the sandbox to this user-defined Docker network (so it can\n * reach an in-container sidecar egress gateway by DNS name) instead of the\n * host-gateway bridge \u2014 the firewall-independent in-container egress path.\n */\n network?: string;\n /** Container-name prefix (default `stacks-run-`). */\n namePrefix?: string;\n /** Driver-level labels merged onto the run (under the manifest's own labels). */\n labels?: Record<string, string>;\n },\n): string[] {\n // The pinned OCI base image declared on the manifest wins over a\n // codeSnapshot(image) ref, which wins over the driver's default image.\n const image =\n manifest.image ??\n (manifest.codeSnapshot.kind === \"image\"\n ? manifest.codeSnapshot.ref\n : opts.image);\n if (!image) {\n throw new Error(\n \"LocalDockerDriver: no image \u2014 declare `manifest.image`, pass `image` for \" +\n \"checkout-kind snapshots, or use a codeSnapshot of kind 'image'.\",\n );\n }\n const workdir = manifest.workdir ?? DEFAULT_WORKDIR;\n const args: string[] = [\"run\", \"--rm\", \"--init\"];\n args.push(\"--name\", sanitizeName(manifest.runId, opts.namePrefix));\n // Run-identity labels (R10 orphan reaping): stamp the canonical `stacks.runId`,\n // any driver-level class labels (e.g. `stacks.kind=eval`), and the manifest's\n // own labels as `--label`. This is what lets a worker LIST its containers\n // (`docker ps --filter label=stacks.kind=eval`) and reap orphans by name after\n // a crash \u2014 the mechanism, not just a test.\n const labels: Record<string, string> = {\n \"stacks.runId\": manifest.runId,\n ...(opts.labels ?? {}),\n ...manifest.labels,\n };\n for (const [key, value] of Object.entries(labels)) {\n args.push(\"--label\", `${key}=${value}`);\n }\n // Risk-class-driven runtime selection (gVisor / microVM) \u2014 expressed on the\n // manifest, honored by the driver.\n args.push(...runtimeArgs(manifest.runtimeClass));\n\n // Resource ceilings.\n const { limits } = manifest;\n if (limits.cpus) args.push(\"--cpus\", String(limits.cpus));\n if (limits.cpuMs) {\n // Hard CPU-time budget in whole seconds (RLIMIT_CPU) \u2192 SIGXCPU on breach.\n const cpuSec = Math.max(1, Math.ceil(limits.cpuMs / 1000));\n args.push(\"--ulimit\", `cpu=${cpuSec}:${cpuSec}`);\n }\n if (limits.memoryBytes) args.push(\"--memory\", String(limits.memoryBytes));\n if (limits.diskBytes) {\n args.push(\"--ulimit\", `fsize=${limits.diskBytes}:${limits.diskBytes}`);\n }\n if (limits.pids) args.push(\"--pids-limit\", String(limits.pids));\n\n // DENY-BY-DEFAULT egress: no network unless explicitly allowed for this run.\n if (opts.network) {\n // In-container egress gateway (sidecar): attach the sandbox to the per-run\n // user-defined network so it reaches the gateway by container DNS name \u2014 the\n // container\u2192gateway hop routes regardless of the host firewall. No host-gateway\n // bridge is needed (and NOT --network none \u2014 egress is honored via the gateway).\n args.push(\"--network\", opts.network);\n } else if (!opts.netEnabled) {\n args.push(\"--network\", \"none\");\n } else {\n // Network is enabled ONLY to reach host-run services. Map the Docker host\n // gateway so an in-container executor can resolve `host.docker.internal` and\n // actually connect to (and authenticate against) the host's Jentrix MCP server \u2014\n // without this a localhost-rewritten MCP URL resolves nowhere and every agent\n // tool call fails auth. Harmless when the run doesn't use it.\n args.push(\"--add-host\", `${HOST_GATEWAY_ALIAS}:host-gateway`);\n }\n\n // The preconfigured checkout is bind-mounted at the workdir; explicit mounts\n // ride alongside (read-only unless a mount opts into rw).\n if (manifest.codeSnapshot.kind === \"checkout\") {\n const src = manifest.codeSnapshot.path\n ? `${manifest.codeSnapshot.ref}/${manifest.codeSnapshot.path}`\n : manifest.codeSnapshot.ref;\n args.push(\"-v\", `${src}:${workdir}:rw`);\n }\n for (const m of manifest.mounts) {\n args.push(\"-v\", `${m.source}:${m.target}:${m.mode}`);\n }\n args.push(\"--workdir\", workdir);\n\n // Env is allowlist-gated (resolveSandboxEnv drops anything off the allowlist).\n const env = resolveSandboxEnv(manifest, opts.baseEnv ?? {});\n for (const [name, value] of Object.entries(env)) {\n args.push(\"-e\", `${name}=${value}`);\n }\n\n // The allowlisted egress data path: point ALL of the container's egress at the\n // enforcing proxy (which allows only allowlisted hosts and audits the rest).\n // Driver-injected control env \u2014 not host env, so it bypasses the allowlist gate.\n if (opts.proxyUrl) {\n // An in-container (sidecar) gateway is already a container-DNS URL reachable on\n // the shared network \u2014 inject it verbatim. A host-bound proxy binds loopback,\n // which inside a container is the container itself, so rewrite it to the host\n // gateway alias.\n const proxy = opts.network\n ? opts.proxyUrl\n : containerProxyUrl(opts.proxyUrl);\n for (const name of [\n \"HTTP_PROXY\",\n \"HTTPS_PROXY\",\n \"http_proxy\",\n \"https_proxy\",\n ]) {\n args.push(\"-e\", `${name}=${proxy}`);\n }\n // Nothing bypasses the proxy (empty NO_PROXY) \u2014 every host goes through the\n // allowlist choke point.\n args.push(\"-e\", \"NO_PROXY=\", \"-e\", \"no_proxy=\");\n }\n\n args.push(image, ...manifest.command);\n return args;\n}\n\n/** A run backed by a `docker run` foreground process. */\nclass DockerSandbox implements Sandbox {\n readonly handle: SandboxHandle;\n private _state: LifecycleState = \"RUNNING\";\n private readonly child: ChildLike;\n private readonly containerName: string;\n private readonly startedAt: number;\n private readonly now: () => number;\n private readonly dockerPath: string;\n private readonly spawn: SpawnFn;\n private readonly hasMemLimit: boolean;\n private readonly hasCpuLimit: boolean;\n private readonly hasDiskLimit: boolean;\n private stdout = \"\";\n private stderr = \"\";\n private killedByUs = false;\n private killLimit: ResourceLimitKind | null = null;\n private readonly outcome: Promise<ExecOutcome>;\n\n constructor(\n manifest: RunManifest,\n args: string[],\n spawn: SpawnFn,\n dockerPath: string,\n now: () => number,\n namePrefix?: string,\n ) {\n this.now = now;\n this.spawn = spawn;\n this.dockerPath = dockerPath;\n this.startedAt = now();\n this.containerName = sanitizeName(manifest.runId, namePrefix);\n this.hasMemLimit = Boolean(manifest.limits.memoryBytes);\n this.hasCpuLimit = Boolean(manifest.limits.cpuMs);\n this.hasDiskLimit = Boolean(manifest.limits.diskBytes);\n this.child = spawn(dockerPath, args, { env: process.env });\n this.handle = {\n driver: DRIVER,\n id: this.containerName,\n runId: manifest.runId,\n createdAt: new Date(this.startedAt).toISOString(),\n meta: { containerName: this.containerName, pid: this.child.pid },\n };\n captureStream(this.child.stdout, (t) => (this.stdout += t));\n captureStream(this.child.stderr, (t) => (this.stderr += t));\n\n this.outcome = new Promise<ExecOutcome>((resolve) => {\n let settled = false;\n const settle = (o: ExecOutcome) => {\n if (settled) return;\n settled = true;\n resolve(o);\n };\n this.child.on(\"error\", (err) => {\n this._state = \"FAILED\";\n settle({\n exitCode: null,\n signal: null,\n stdout: this.stdout,\n stderr: this.stderr || String(err?.message ?? err),\n killed: this.killedByUs,\n summary: lastLine(this.stdout),\n });\n });\n this.child.on(\"close\", (code, signal) => {\n // Attribute an UNREQUESTED fatal-signal container exit to the declared budget\n // most likely responsible. This must be inferable from the exit code + the\n // manifest's limits ALONE: an exited `--rm` container is gone before\n // `docker inspect .State.OOMKilled` can read it, so no post-mortem probe is\n // possible. Platform reality (verified against Docker Desktop's Linux VM,\n // arm64): a `--ulimit cpu` (RLIMIT_CPU) breach delivers SIGKILL \u2192 exit 137,\n // NOT the textbook SIGXCPU \u2192 152. So a CPU-budget kill must be recognized from\n // 137 as well, or the M12.1 observable exit would degrade to a generic\n // `nonzero_exit` on the Docker driver.\n let resourceLimit: ResourceLimitKind | null = this.killLimit;\n if (!resourceLimit && !this.killedByUs) {\n const signalKilled =\n signal === \"SIGKILL\" ||\n signal === \"SIGXCPU\" ||\n signal === \"SIGXFSZ\" ||\n code === 137 || // 128 + SIGKILL(9)\n code === 152 || // 128 + SIGXCPU(24)\n code === 153; // 128 + SIGXFSZ(25)\n if (signal === \"SIGXFSZ\" || code === 153) {\n // Unambiguous disk/file-size signal: an RLIMIT_FSIZE (`--ulimit fsize`)\n // breach delivers SIGXFSZ (signal 25) \u2192 exit 153 to a process that writes\n // past its file-size budget. Under Docker's `--init` the command is not\n // PID 1, so the signal actually terminates it (verified live, arm64).\n resourceLimit = \"disk\";\n } else if (signal === \"SIGXCPU\" || code === 152) {\n // Unambiguous CPU-time signal (platforms that deliver SIGXCPU).\n resourceLimit = \"cpu\";\n } else if (signalKilled && this.hasCpuLimit) {\n // RLIMIT_CPU hard-limit kill (SIGKILL/137 on this platform). CPU takes\n // precedence over memory here because it is the M12.1 uniquely-owned exit\n // that MUST surface as a structured resource-limit failure. (Both budgets\n // are ambiguous under a bare 137, but either verdict is still a structured\n // resource_limit_exceeded, and CPU is the criterion under test.)\n resourceLimit = \"cpu\";\n } else if (signalKilled && this.hasMemLimit) {\n resourceLimit = \"memory\"; // OOM kill (best-effort).\n } else if (signalKilled && this.hasDiskLimit) {\n resourceLimit = \"disk\"; // fsize kill on a platform that used SIGKILL.\n }\n }\n this._state = code === 0 ? \"SUCCEEDED\" : \"FAILED\";\n settle({\n exitCode: code,\n signal,\n stdout: this.stdout,\n stderr: this.stderr,\n killed: this.killedByUs,\n resourceLimit,\n summary: lastLine(this.stdout),\n });\n });\n });\n }\n\n get state(): LifecycleState {\n return this._state;\n }\n\n wait(): Promise<ExecOutcome> {\n return this.outcome;\n }\n\n async kill(req?: {\n reason?: string;\n limit?: ResourceLimitKind;\n graceMs?: number;\n }): Promise<void> {\n this.killedByUs = true;\n this.killLimit = req?.limit ?? null;\n // `docker kill` stops the container itself (the foreground `docker run` child\n // dying does not guarantee the container stops); best-effort + detached.\n try {\n const killer = this.spawn(this.dockerPath, [\"kill\", this.containerName], {\n env: process.env,\n });\n killer.on(\"error\", () => {});\n } catch {\n /* daemon unreachable \u2014 fall through to the child kill */\n }\n try {\n this.child.kill(\"SIGKILL\");\n } catch {\n /* already gone */\n }\n }\n\n async usage(): Promise<ResourceUsage> {\n return { wallMs: Math.max(0, this.now() - this.startedAt) };\n }\n}\n\nexport class LocalDockerDriver implements SandboxDriver {\n readonly name = DRIVER;\n private readonly image?: string;\n private readonly spawn: SpawnFn;\n private readonly dockerPath: string;\n private readonly baseEnv: NodeJS.ProcessEnv;\n private readonly now: () => number;\n private readonly allowNet: () => boolean;\n private readonly egressProxyUrl: () => string | undefined;\n private readonly egressNetwork: () => string | undefined;\n private readonly namePrefix?: string;\n private readonly labels: Record<string, string>;\n private readonly log: (msg: string) => void;\n\n constructor(opts: LocalDockerDriverOptions = {}) {\n this.image = opts.image;\n this.spawn = opts.spawn ?? defaultSpawn;\n this.dockerPath = opts.dockerPath ?? \"docker\";\n this.baseEnv = opts.baseEnv ?? process.env;\n this.now = opts.now ?? Date.now;\n this.allowNet =\n opts.allowNet ?? (() => process.env.STACKS_SANDBOX_ALLOW_NET === \"1\");\n this.egressProxyUrl = opts.egressProxyUrl ?? (() => undefined);\n this.egressNetwork = opts.egressNetwork ?? (() => undefined);\n this.namePrefix = opts.namePrefix;\n this.labels = opts.labels ?? {};\n this.log = opts.log ?? (() => {});\n }\n\n async create(\n manifest: RunManifest,\n _opts: DriverRunOptions = {},\n ): Promise<Sandbox> {\n if (manifest.command.length === 0) {\n throw new Error(\n \"LocalDockerDriver: a manifest must declare a non-empty `command`.\",\n );\n }\n const allowNet = this.allowNet();\n const proxyUrl = this.egressProxyUrl();\n const network = this.egressNetwork();\n const enforcement = resolveEgressEnforcement(manifest, allowNet, {\n proxyUrl,\n ...(network ? { network } : {}),\n });\n if (enforcement.downgraded) {\n this.log(`[local-docker ${manifest.runId}] ${enforcement.reason}`);\n }\n const args = buildDockerArgs(manifest, {\n image: this.image,\n netEnabled: enforcement.netEnabled,\n baseEnv: this.baseEnv,\n ...(enforcement.proxyUrl ? { proxyUrl: enforcement.proxyUrl } : {}),\n ...(enforcement.network ? { network: enforcement.network } : {}),\n ...(this.namePrefix ? { namePrefix: this.namePrefix } : {}),\n ...(Object.keys(this.labels).length ? { labels: this.labels } : {}),\n });\n return new DockerSandbox(\n manifest,\n args,\n this.spawn,\n this.dockerPath,\n this.now,\n this.namePrefix,\n );\n }\n\n async resume(handle: SandboxHandle): Promise<Sandbox> {\n // --rm containers are gone once exited; resume is only meaningful for a still\n // -running container. Not supported for the ephemeral run model.\n throw new Error(\n `LocalDockerDriver does not support resume() for ephemeral (--rm) runs (${handle.id}).`,\n );\n }\n\n async snapshot(sandbox: Sandbox): Promise<SnapshotRef> {\n // `docker commit` the live container into an image. Best-effort; requires the\n // container to still exist (not yet --rm'd).\n const name = sandbox.handle.id;\n const image = `stacks-snapshot-${name}`;\n try {\n const child = this.spawn(this.dockerPath, [\"commit\", name, image], {\n env: process.env,\n });\n child.on(\"error\", () => {});\n } catch {\n /* daemon unreachable */\n }\n return {\n driver: DRIVER,\n id: image,\n createdAt: new Date(this.now()).toISOString(),\n sourceSandboxId: name,\n };\n }\n\n async terminate(sandbox: Sandbox): Promise<void> {\n await sandbox.kill({ reason: \"terminate\", graceMs: 0 }).catch(() => {});\n }\n}\n", "/**\n * Turn-summary wire protocol between the docker container entrypoint (run-turn.ts)\n * and the execution bridge (execution.ts) \u2014 M12.1.\n *\n * The host driver runs the turn IN-PROCESS and gets the agent's summary as a return\n * value, so the FULL (usually multi-line) summary is preserved verbatim. The docker\n * driver instead reads the container's stdout, where a naive \"last non-empty line\"\n * capture would TRUNCATE a multi-line summary \u2014 and that summary is recorded as the\n * stage's TEST_EVIDENCE artifact, so a truncated capture would make the docker-driver\n * Jentrix-side records DIFFER from the pre-refactor/host records.\n *\n * To keep the records identical, run-turn.ts wraps the summary in these delimiters\n * and the bridge recovers the whole region from stdout. Kept in a tiny standalone\n * module so the container entrypoint doesn't pull in the driver/child-process graph.\n */\nexport const TURN_SUMMARY_BEGIN = \"<<<STACKS_TURN_SUMMARY_BEGIN>>>\";\nexport const TURN_SUMMARY_END = \"<<<STACKS_TURN_SUMMARY_END>>>\";\n\n/** Wrap a turn summary for stdout emission by the container entrypoint. */\nexport function frameTurnSummary(summary: string): string {\n return `${TURN_SUMMARY_BEGIN}\\n${summary}\\n${TURN_SUMMARY_END}\\n`;\n}\n\n/**\n * Recover the FULL turn summary the container emitted from its captured stdout.\n * Uses `lastIndexOf` so incidental stdout noise before the region is tolerated;\n * falls back to the driver-provided value when the delimiters are absent.\n */\nexport function extractTurnSummary(stdout: string, fallback: string): string {\n const begin = stdout.lastIndexOf(TURN_SUMMARY_BEGIN);\n const end = stdout.lastIndexOf(TURN_SUMMARY_END);\n if (begin >= 0 && end > begin) {\n return stdout.slice(begin + TURN_SUMMARY_BEGIN.length, end).trim();\n }\n return fallback;\n}\n", "/**\n * runner-pool.ts \u2014 bounded, job-id-deduplicating work pool for the reference\n * workflow runner (Concurrent Harness Execution PRD \u00A77, Stage 4 \"S4\").\n *\n * Replaces the runner's two single serialized promise chains with two of these:\n * \u2022 an AGENT-TURN pool (STACKS_RUNNER_MAX_CONCURRENT_JOBS, default 1) bounding\n * planner/reviewer/executor turns;\n * \u2022 a COMMIT pool (STACKS_RUNNER_MAX_CONCURRENT_COMMITS, default 1) bounding\n * post-validation commit/push continuations \u2014 a DEDICATED pool so a freshly\n * approved commit never sits behind a long model turn, even when the\n * agent-turn pool is full.\n *\n * Server-side `claim_agent_job` CAS is STILL the final ownership guard; this pool\n * only avoids WASTING a slot on a delivery that a peer already owns. Two local\n * invariants the runner leans on:\n *\n * \u2022 DEDUP \u2014 a jobId already queued/running/detached collapses a duplicate\n * delivery (webhook OR poll \u2014 both call submit() on the SAME pool object, so\n * the registry spans both inputs) BEFORE it consumes a slot. submit() returns\n * false for a collapsed duplicate.\n *\n * \u2022 WATCHDOG DETACH keeps the jobId in the dedup registry \u2014 the slot frees so a\n * hung provider session can't wedge throughput, but the jobId stays\n * \"inflight\" until the orphaned work TRULY settles, so a re-delivery of the\n * SAME jobId can never race the orphan on the SAME job-scoped worktree. (A\n * retry mints a NEW jobId \u2192 a different worktree dir, so it is not a\n * duplicate and proceeds in its own slot.)\n *\n * The pool is a plain in-memory local-queue optimization by design \u2014 the PRD is\n * explicit that \"the runner deduplicates the LOCAL queue by job id\" while the\n * server-side claim CAS remains the trust boundary. It shells out to nothing and\n * adds no dependency.\n */\n\n/** A point-in-time gauge for the telemetry line. */\nexport interface PoolSnapshot {\n kind: string;\n /** The raw STACKS_RUNNER_MAX_CONCURRENT_* value the operator configured. */\n configuredMax: number;\n /** configuredMax clamped to [1, hardMax] \u2014 the bound actually enforced. */\n effectiveMax: number;\n /** Slots consumed right now (bounded by effectiveMax). */\n active: number;\n /** Tasks waiting for a slot. */\n queueDepth: number;\n /** Dedup-registry size: queued + running + watchdog-detached job ids. */\n inflight: number;\n}\n\ninterface Pending {\n jobId: string;\n run: () => Promise<void>;\n enqueuedAt: number;\n}\n\nexport interface BoundedDedupPoolOpts {\n /** Hard upper bound on a single task; when exceeded the SLOT is released and\n * the orphan keeps running (attempt-guarded, worktree retained). */\n watchdogMs: number;\n /** Injectable clock for deterministic tests (defaults to Date.now). */\n now?: () => number;\n log?: (msg: string) => void;\n /** Fired when a task actually STARTS running \u2014 queueLatencyMs is submit\u2192start\n * (the pool's per-pool queue latency the PRD reports separately). */\n onStart?: (jobId: string, queueLatencyMs: number) => void;\n /** Fired after any slot free or true settle \u2014 a hook to re-emit telemetry. */\n onSettle?: () => void;\n}\n\n/**\n * Clamp an operator-configured concurrency to a finite documented maximum. A\n * missing / non-integer / < 1 value falls back to `fallback` (never unbounded);\n * anything above `hardMax` is clamped down to it. Both pools document their\n * finite maxima at the call site.\n */\nexport function parseBoundedMax(\n raw: string | undefined,\n fallback: number,\n hardMax: number,\n): number {\n const n = Number(raw);\n if (!Number.isInteger(n) || n < 1) return Math.min(fallback, hardMax);\n return Math.min(n, hardMax);\n}\n\n/**\n * F8 (AGE-505): parse a positive-integer env knob (a timeout in ms, a turn\n * budget, a port) with a NaN-safe fallback. `Number(undefined)`/typos silently\n * produced NaN timeouts and budgets before \u2014 a NaN setTimeout fires\n * immediately and a NaN maxTurns disables the budget entirely.\n */\nexport function parsePositiveInt(\n raw: string | undefined,\n fallback: number,\n): number {\n const n = Number(raw);\n if (!Number.isFinite(n) || !Number.isInteger(n) || n < 1) return fallback;\n return n;\n}\n\nexport class BoundedDedupPool {\n private active = 0;\n private readonly queue: Pending[] = [];\n private readonly inflight = new Set<string>();\n\n constructor(\n readonly kind: string,\n /** The bound actually enforced (already clamped by parseBoundedMax). */\n readonly effectiveMax: number,\n private readonly configuredMax: number,\n private readonly opts: BoundedDedupPoolOpts,\n ) {}\n\n private now(): number {\n return this.opts.now ? this.opts.now() : Date.now();\n }\n\n /**\n * Enqueue `run` for `jobId`. Returns false (a no-op) when `jobId` is already\n * queued/running/detached \u2014 the duplicate is COLLAPSED before it consumes a\n * slot. Returns true when the job was newly enqueued.\n */\n submit(jobId: string, run: () => Promise<void>): boolean {\n if (this.inflight.has(jobId)) {\n this.opts.log?.(\n `[pool:${this.kind}] duplicate delivery for job ${jobId} collapsed (already queued/running).`,\n );\n return false;\n }\n this.inflight.add(jobId);\n this.queue.push({ jobId, run, enqueuedAt: this.now() });\n this.pump();\n return true;\n }\n\n /**\n * True when `jobId` is already queued/running/watchdog-detached. Lets the poll\n * loop skip the expensive fresh get_agent_job re-read for a job already in the\n * shared registry; submit() is still the authoritative dedup guard (a webhook\n * delivery racing the poll read collapses on submit()).\n */\n has(jobId: string): boolean {\n return this.inflight.has(jobId);\n }\n\n snapshot(): PoolSnapshot {\n return {\n kind: this.kind,\n configuredMax: this.configuredMax,\n effectiveMax: this.effectiveMax,\n active: this.active,\n queueDepth: this.queue.length,\n inflight: this.inflight.size,\n };\n }\n\n private pump(): void {\n while (this.active < this.effectiveMax && this.queue.length > 0) {\n const item = this.queue.shift() as Pending;\n this.active += 1;\n this.opts.onStart?.(item.jobId, Math.max(0, this.now() - item.enqueuedAt));\n this.runOne(item);\n }\n }\n\n private runOne(item: Pending): void {\n let slotReleased = false;\n const releaseSlot = (reason: \"settled\" | \"watchdog\"): void => {\n if (slotReleased) return;\n slotReleased = true;\n this.active -= 1;\n if (reason === \"watchdog\") {\n this.opts.log?.(\n `[pool:${this.kind}] job ${item.jobId} exceeded ${this.opts.watchdogMs}ms \u2014 releasing the slot; the orphan stays attempt-guarded (worktree retained, a re-delivery of ${item.jobId} stays collapsed) and the server-side claim CAS rejects its late writes.`,\n );\n }\n this.pump();\n this.opts.onSettle?.();\n };\n const timer = setTimeout(\n () => releaseSlot(\"watchdog\"),\n this.opts.watchdogMs,\n );\n // Errors are consumed HERE \u2014 a failed/detached task must never surface as an\n // unhandled rejection.\n const work = item.run().catch((err) =>\n this.opts.log?.(\n `[pool:${this.kind}] job ${item.jobId} failed: ${\n err instanceof Error ? err.message : String(err)\n }`,\n ),\n );\n // The SLOT is freed on the watchdog OR the true settle, whichever first.\n // The DEDUP registry entry is dropped ONLY on the true settle \u2014 so a job the\n // watchdog detached keeps its registry slot until its orphan really finishes,\n // never sharing its worktree with a same-jobId re-delivery.\n void work.finally(() => {\n clearTimeout(timer);\n releaseSlot(\"settled\");\n this.inflight.delete(item.jobId);\n this.opts.onSettle?.();\n });\n }\n}\n", "/**\n * Reference-runner \u2194 ExecutionBackend bridge (M12.1).\n *\n * The reference runner used to run each agent turn by calling `runJentrixAgent`\n * directly (the \"direct-exec path\"). It now runs every turn THROUGH an\n * {@link ExecutionBackend} (@stacks/execution): the backend enforces the turn's\n * wall-time/CPU budget and returns a structured result envelope.\n *\n * Two drivers, selected by STACKS_EXECUTION_DRIVER:\n * \u2022 \"host\" (default) \u2014 HostProcessDriver in-process mode. It runs the SAME\n * `runJentrixAgent` call as before, so the Jentrix-side records\n * (AgentJob/AgentRun/Activity/artifacts) are IDENTICAL to the pre-refactor\n * runner. This is the former direct-exec path, preserved behind the contract.\n * \u2022 \"docker\" \u2014 LocalDockerDriver: the turn runs in an ephemeral container over\n * the mounted checkout (entrypoint: run-turn.ts) with enforced limits and a\n * deny-by-default egress profile. Because an agent turn must reach the MCP\n * server + provider API, the container needs egress: set\n * STACKS_SANDBOX_ALLOW_NET=1 (the single dev bypass, off by default) or run it\n * behind an egress proxy. Requires a preconfigured image (STACKS_SANDBOX_IMAGE).\n */\nimport {\n createExecutionBackend,\n HostProcessDriver,\n LocalDockerDriver,\n isResourceLimitExceeded,\n type ExecutionBackend,\n type ResultEnvelope,\n type RunManifestInput,\n} from \"../../packages/execution/src/index.js\";\n\nimport {\n runJentrixAgent,\n type AgentProvider,\n type JentrixConnection,\n} from \"./jentrix.js\";\nimport { extractTurnSummary } from \"./turn-protocol.js\";\nimport { parsePositiveInt } from \"./runner-pool.js\";\n\nexport type ExecutionDriverKind = \"host\" | \"docker\";\n\n/** The seam the reference runner writes its Jentrix-side records through. */\nexport type RunAgentFn = typeof runJentrixAgent;\n\n/**\n * Rewrite a host-facing MCP URL to one an IN-CONTAINER executor can reach.\n *\n * Inside a container `localhost`/`127.0.0.1` is the container itself \u2014 NOT the host\n * running Jentrix \u2014 so handing a loopback MCP URL to a docker-driver turn makes every\n * agent tool call fail to connect: an executor \"authentication failure\" that leaves\n * the turn unable to do (or verify) any work. Loopback hosts are mapped to the Docker\n * host-gateway alias, which the LocalDockerDriver wires up via\n * `--add-host host.docker.internal:host-gateway`. Non-loopback URLs pass through.\n */\nexport function containerMcpUrl(rawUrl: string): string {\n try {\n const u = new URL(rawUrl);\n if ([\"localhost\", \"127.0.0.1\", \"0.0.0.0\", \"::1\"].includes(u.hostname)) {\n u.hostname = \"host.docker.internal\";\n }\n return u.toString();\n } catch {\n return rawUrl;\n }\n}\n\n/** The execution driver the runner uses (default host \u2014 identical prior records). */\nexport function executionDriverKind(): ExecutionDriverKind {\n return process.env.STACKS_EXECUTION_DRIVER === \"docker\" ? \"docker\" : \"host\";\n}\n\n/** The sandbox egress bypass \u2014 off by default, mirroring the webhook allow-flag. */\nexport function sandboxNetAllowed(): boolean {\n return process.env.STACKS_SANDBOX_ALLOW_NET === \"1\";\n}\n\n/** Default wall-time budget for an agent turn (generous \u2014 real turns are long).\n * F8 (AGE-505): NaN-safe \u2014 a typo'd env value falls back to the default. */\nconst DEFAULT_WALL_MS = parsePositiveInt(\n process.env.STACKS_EXEC_WALL_MS,\n 45 * 60 * 1000,\n);\n\n/**\n * The in-container entrypoint argv for the docker driver (image-provided).\n *\n * Resolved PER CALL (not frozen at import) so an operator \u2014 or a live record-parity\n * test \u2014 can override it via STACKS_SANDBOX_TURN_CMD. A value that starts with \"[\"\n * is parsed as a JSON argv array (so an argument containing spaces survives intact);\n * otherwise it is whitespace-split. Defaults to the image-provided run-turn.ts.\n */\nexport function dockerTurnCommand(\n env: NodeJS.ProcessEnv = process.env,\n): string[] {\n const raw = env.STACKS_SANDBOX_TURN_CMD;\n if (!raw || !raw.trim()) {\n return [\"node\", \"--import\", \"tsx\", \"/app/agents/run-turn.ts\"];\n }\n const trimmed = raw.trim();\n if (trimmed.startsWith(\"[\")) {\n try {\n const parsed = JSON.parse(trimmed);\n if (\n Array.isArray(parsed) &&\n parsed.length > 0 &&\n parsed.every((s) => typeof s === \"string\")\n ) {\n return parsed as string[];\n }\n } catch {\n /* not valid JSON \u2014 fall through to whitespace split */\n }\n }\n return trimmed.split(/\\s+/);\n}\n\nlet turnCounter = 0;\nlet verificationCounter = 0;\nlet verificationBackend: ExecutionBackend | null = null;\n\nexport function makeExecutionBackend(\n kind: ExecutionDriverKind = executionDriverKind(),\n): { backend: ExecutionBackend; kind: ExecutionDriverKind } {\n const driver =\n kind === \"docker\"\n ? new LocalDockerDriver({\n image: process.env.STACKS_SANDBOX_IMAGE,\n log: (m) => console.log(m),\n })\n : new HostProcessDriver();\n return { backend: createExecutionBackend(driver), kind };\n}\n\nconst VERIFICATION_WRAPPER = `set -e\nif [ ! -d \"$STACKS_VERIFICATION_DEPENDENCIES\" ]; then\n echo \"managed verification dependencies are missing\" >&2\n exit 127\nfi\nworkspace=/tmp/stacks-verification-workspace\nmkdir \"$workspace\"\ntar -C /workspace --exclude=./node_modules -cf - . | tar -C \"$workspace\" -xf -\nln -s \"$STACKS_VERIFICATION_DEPENDENCIES\" \"$workspace/node_modules\"\nlink_pkg() {\n if [ -n \"$2\" ] && [ -d \"$2\" ] && [ -d \"$workspace/$1\" ]; then\n rm -rf \"$workspace/$1/node_modules\"\n ln -s \"$2\" \"$workspace/$1/node_modules\"\n fi\n}\nlink_pkg services/worker \"$STACKS_VERIFICATION_WORKER_DEPENDENCIES\"\nlink_pkg agents \"$STACKS_VERIFICATION_AGENTS_DEPENDENCIES\"\nlink_pkg cli \"$STACKS_VERIFICATION_CLI_DEPENDENCIES\"\ncd \"$workspace\"\nexport PATH=\"$workspace/node_modules/.bin:/app/node_modules/.bin:/app/agents/node_modules/.bin:/usr/local/bin:/usr/bin:/bin\"\nexec sh -lc \"$STACKS_VERIFICATION_COMMAND\"`;\n\n/** A verification command's complete managed-sandbox contract. Exported so the\n * deny-egress and scrubbed-environment boundary is pinned by a small test. */\nexport function managedVerificationManifest(\n cwd: string,\n command: string,\n timeoutMs: number,\n): RunManifestInput {\n const env = {\n CI: \"1\",\n // The verification image preloads the lockfile-pinned pnpm release here.\n // HOME is intentionally scrubbed to /tmp, so Corepack otherwise ignores\n // that cache and attempts a denied registry download before tests start.\n COREPACK_HOME: \"/root/.cache/node/corepack\",\n HOME: \"/tmp\",\n NODE_ENV: \"test\",\n NO_COLOR: \"1\",\n PATH: \"/workspace/node_modules/.bin:/app/node_modules/.bin:/app/agents/node_modules/.bin:/usr/local/bin:/usr/bin:/bin\",\n // pnpm 11 defaults verifyDepsBeforeRun to \"install\". The worktree consumes\n // dependencies from the digest-pinned verification image, so an implicit\n // install would both ignore that immutable input and retry the registry\n // forever under the intentional deny-egress policy.\n PNPM_CONFIG_VERIFY_DEPS_BEFORE_RUN: \"false\",\n STACKS_VERIFICATION_COMMAND: command,\n STACKS_VERIFICATION_DEPENDENCIES:\n process.env.STACKS_VERIFICATION_DEPENDENCIES ?? \"/app/node_modules\",\n // AGE-907: the repo has THREE dependency-firewalled standalone packages\n // (own lockfile + `.npmrc ignore-workspace`) whose node_modules are all\n // gitignored \u2014 so each is absent from the stage checkout AND not covered by\n // the root tree above. Without its tree, a command targeting one of them can\n // only run by installing, which deny-egress hangs on until the wall clock.\n // Every link is SOFT (the wrapper skips a missing dir) so an image built\n // before any of these existed keeps running every other command unchanged.\n STACKS_VERIFICATION_WORKER_DEPENDENCIES:\n process.env.STACKS_VERIFICATION_WORKER_DEPENDENCIES ??\n \"/app/services/worker/node_modules\",\n STACKS_VERIFICATION_AGENTS_DEPENDENCIES:\n process.env.STACKS_VERIFICATION_AGENTS_DEPENDENCIES ??\n \"/app/agents/node_modules\",\n STACKS_VERIFICATION_CLI_DEPENDENCIES:\n process.env.STACKS_VERIFICATION_CLI_DEPENDENCIES ??\n \"/app/cli/node_modules\",\n };\n return {\n runId: `harness-verify-${process.pid}-${verificationCounter++}`,\n command: [\"sh\", \"-lc\", VERIFICATION_WRAPPER],\n codeSnapshot: { kind: \"checkout\", ref: cwd },\n workdir: \"/workspace\",\n envAllowlist: Object.keys(env),\n env,\n capabilities: [],\n limits: {\n cpus: 2,\n memoryBytes: 4 * 1024 * 1024 * 1024,\n pids: 512,\n wallMs: timeoutMs,\n },\n egress: { mode: \"deny\", allow: [] },\n labels: { kind: \"harness-verification\" },\n };\n}\n\nfunction managedVerificationBackend(): ExecutionBackend {\n if (verificationBackend) return verificationBackend;\n const image =\n process.env.STACKS_VERIFICATION_IMAGE ?? process.env.STACKS_SANDBOX_IMAGE;\n if (!image) {\n throw new Error(\n \"managed verification requires STACKS_VERIFICATION_IMAGE (or STACKS_SANDBOX_IMAGE)\",\n );\n }\n verificationBackend = createExecutionBackend(\n new LocalDockerDriver({\n image,\n allowNet: () => false,\n baseEnv: {},\n log: (message) => console.log(message),\n }),\n );\n return verificationBackend;\n}\n\nexport interface ManagedVerificationResult {\n command: string;\n exitCode: number;\n timedOut: boolean;\n stdout: string;\n stderr: string;\n startedAt: string;\n finishedAt: string;\n}\n\n// ---------------------------------------------------------------------------\n// D2 (AGE-507): the HOST verification lane for E2E. `pnpm test:e2e` provisions\n// its own isolated Docker pgvector database and drives a real dev server \u2014\n// it needs the Docker socket and localhost networking, which the sealed\n// deny-egress container rightly lacks. Instead of a cluster to seal E2E (the\n// deleted D1 lane), E2E runs as a runner-attested HOST command under a small\n// explicit env allowlist (never the runner's tokens/keys); unit/lint/typecheck\n// keep the sealed container. The attested tier stays INTEGRATION_LOCAL.\n// ---------------------------------------------------------------------------\n\nconst HOST_VERIFICATION_COMMAND_RE = /\\btest:e2e\\b/;\n\nexport function isHostVerificationCommand(command: string): boolean {\n return HOST_VERIFICATION_COMMAND_RE.test(command);\n}\n\n/** Pass-through host vars the E2E toolchain needs (docker CLI, pnpm, node). */\nconst HOST_ENV_PASSTHROUGH = [\n \"PATH\",\n \"HOME\",\n \"TMPDIR\",\n \"SHELL\",\n \"USER\",\n \"LANG\",\n \"DOCKER_HOST\",\n \"DOCKER_CONFIG\",\n] as const;\n\n/** The scrubbed host-lane environment: the explicit passthrough list + CI\n * knobs, and NOTHING else \u2014 no STACKS_* tokens, no provider keys. The E2E\n * suite reads its DB URL from the worktree's own .env.local. */\nexport function hostVerificationEnv(\n base: NodeJS.ProcessEnv = process.env,\n): Record<string, string> {\n const env: Record<string, string> = {\n CI: \"1\",\n NODE_ENV: \"test\",\n NO_COLOR: \"1\",\n };\n for (const key of HOST_ENV_PASSTHROUGH) {\n const value = base[key];\n if (value) env[key] = value;\n }\n return env;\n}\n\nasync function runHostVerificationCommand(input: {\n cwd: string;\n command: string;\n timeoutMs: number;\n signal?: AbortSignal;\n}): Promise<ManagedVerificationResult> {\n const startedAt = new Date().toISOString();\n const { spawn } = await import(\"node:child_process\");\n return new Promise((resolve) => {\n let timedOut = false;\n const child = spawn(\"sh\", [\"-lc\", input.command], {\n cwd: input.cwd,\n env: hostVerificationEnv(),\n });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout.on(\"data\", (d) => (stdout += d));\n child.stderr.on(\"data\", (d) => (stderr += d));\n const finish = (exitCode: number) => {\n clearTimeout(timer);\n input.signal?.removeEventListener(\"abort\", onAbort);\n resolve({\n command: input.command,\n exitCode,\n timedOut,\n stdout,\n stderr,\n startedAt,\n finishedAt: new Date().toISOString(),\n });\n };\n const timer = setTimeout(() => {\n timedOut = true;\n child.kill(\"SIGKILL\");\n }, input.timeoutMs);\n const onAbort = () => child.kill(\"SIGKILL\");\n input.signal?.addEventListener(\"abort\", onAbort, { once: true });\n child.on(\"error\", () => finish(127));\n child.on(\"close\", (code) => finish(timedOut ? 124 : (code ?? 1)));\n });\n}\n\n/** Execute one planner-declared command in an ephemeral, env-scrubbed,\n * deny-egress container. The stage worktree is its only writable host mount.\n * E2E commands take the D2 host lane above. */\nexport async function runManagedVerificationCommand(input: {\n cwd: string;\n command: string;\n timeoutMs: number;\n signal?: AbortSignal;\n}): Promise<ManagedVerificationResult> {\n if (isHostVerificationCommand(input.command)) {\n return runHostVerificationCommand(input);\n }\n const startedAt = new Date().toISOString();\n const envelope = await managedVerificationBackend().run(\n managedVerificationManifest(input.cwd, input.command, input.timeoutMs),\n { signal: input.signal },\n );\n return {\n command: input.command,\n exitCode:\n envelope.exitCode ??\n (envelope.status === \"timed_out\"\n ? 124\n : envelope.status === \"canceled\"\n ? 130\n : 127),\n timedOut: envelope.status === \"timed_out\",\n stdout: envelope.stdout,\n stderr: envelope.stderr,\n startedAt,\n finishedAt: new Date().toISOString(),\n };\n}\n\n/** Prove Docker + the configured verification image can start before each Harness\n * turn is claimed. Re-run every time so a recovered daemon/image resumes at the\n * closest safe point without requiring a runner restart. */\nexport function preflightManagedVerification(): Promise<void> {\n return runManagedVerificationCommand({\n cwd: process.cwd(),\n command: \"command -v sh >/dev/null\",\n timeoutMs: 30_000,\n }).then((result) => {\n if (result.exitCode !== 0 || result.timedOut) {\n throw new Error(\n `managed verification preflight failed (${result.timedOut ? \"timed out\" : `exit ${result.exitCode}`}): ${result.stderr.trim()}`,\n );\n }\n });\n}\n\nexport interface TurnSpec {\n /** Execution-layer run id (distinct from the Jentrix AgentRun id). */\n runId?: string;\n jobId?: string;\n prompt: string;\n systemPrompt: string;\n /** Writable checkout for an executor turn; unset for a tools-only turn. */\n repoCwd?: string;\n /** W3: harness STAGE executor leg \u2014 the runtime registers the executor hooks\n * (runner-owned submissions, foreground-evidence stop nudge). */\n runnerOwnsSubmissions?: boolean;\n /**\n * M18.3 R7: run against `repoCwd` READ-ONLY. Set from the dispatch role's\n * entry in `role-repo-access.ts` (true for a validator or any unrecognized\n * role) and enforced by the providers \u2014 claude withholds the write/edit\n * tools, codex runs the shell under a read-only sandbox. Threaded through\n * BOTH drivers below so the docker path is not a hole in the guarantee.\n */\n repoReadOnly?: boolean;\n maxTurns: number;\n /** Claude-only model override for this turn (see JentrixAgentConfig.model). */\n model?: string;\n connection: JentrixConnection;\n provider: AgentProvider;\n /** Aborted on freeze/cancel \u2014 threaded into the turn so it stops. */\n signal?: AbortSignal;\n /** Wall-time budget (ms). Defaults to STACKS_EXEC_WALL_MS. */\n wallMs?: number;\n /** Optional hard CPU-time budget (ms). */\n cpuMs?: number;\n}\n\n/**\n * The allowlisted env the docker driver injects so `run-turn.ts` can reconstruct\n * and run the SAME agent turn IN-CONTAINER as the in-process host path. Exported so\n * record-parity tests can assert the container is handed identical turn inputs (and\n * a REACHABLE, loopback-rewritten MCP URL) without a live daemon.\n */\nexport function dockerTurnEnv(spec: TurnSpec): Record<string, string> {\n return {\n STACKS_TURN_PROMPT: spec.prompt,\n STACKS_TURN_SYSTEM_PROMPT: spec.systemPrompt,\n STACKS_TURN_MAX_TURNS: String(spec.maxTurns),\n STACKS_TURN_MODEL: spec.model ?? \"\",\n STACKS_TURN_PROVIDER: spec.provider,\n STACKS_TURN_REPO_CWD: spec.repoCwd ? \"/workspace\" : \"\",\n // W3: the container path reconstructs the SAME runJentrixAgent call, so the\n // executor hooks must ride across too \u2014 otherwise the docker driver would\n // silently run without them.\n STACKS_TURN_RUNNER_OWNS_SUBMISSIONS: spec.runnerOwnsSubmissions ? \"1\" : \"\",\n // M18.3 R7: the read-only verdict crosses into the container too, so a\n // docker-driven validator turn is sandboxed exactly like the host one.\n STACKS_TURN_REPO_READ_ONLY: spec.repoReadOnly ? \"1\" : \"\",\n // Loopback \u2192 host-gateway so the containerized executor can actually reach and\n // AUTHENTICATE against the host's Jentrix MCP server (see containerMcpUrl).\n STACKS_MCP_URL: containerMcpUrl(spec.connection.url),\n STACKS_MCP_BEARER: spec.connection.token,\n };\n}\n\n/**\n * Run ONE agent turn through the ExecutionBackend and return its summary text.\n * On the host driver this is byte-for-byte the prior in-process `runJentrixAgent`\n * call (identical records) plus wall-time enforcement; a budget kill surfaces as a\n * thrown error so the runner fails the job (blocks for a human) \u2014 never a silent hang.\n *\n * `deps.runAgent` overrides the Jentrix-writing call on the HOST path (default: the\n * real `runJentrixAgent`); tests inject a recorder to evidence record parity offline.\n */\nexport async function runTurnThroughBackend(\n backend: ExecutionBackend,\n kind: ExecutionDriverKind,\n spec: TurnSpec,\n deps: { runAgent?: RunAgentFn } = {},\n): Promise<string> {\n const runAgent = deps.runAgent ?? runJentrixAgent;\n const runId = spec.runId ?? `exec-${Date.now()}-${turnCounter++}`;\n const wallMs = spec.wallMs ?? DEFAULT_WALL_MS;\n const egress: RunManifestInput[\"egress\"] = sandboxNetAllowed()\n ? { mode: \"open\" }\n : { mode: \"deny\" };\n\n if (kind === \"host\") {\n const manifest: RunManifestInput = {\n runId,\n jobId: spec.jobId,\n inProcess: true,\n command: [],\n codeSnapshot: { kind: \"checkout\", ref: spec.repoCwd ?? process.cwd() },\n ...(spec.repoCwd ? { workdir: spec.repoCwd } : {}),\n capabilities: [{ id: \"mcp:stacks\", kind: \"mcp\" }],\n limits: { wallMs, ...(spec.cpuMs ? { cpuMs: spec.cpuMs } : {}) },\n egress,\n };\n const envelope = await backend.run(manifest, {\n signal: spec.signal,\n inProcessRunner: async ({ signal }) => ({\n // The SAME call the direct-exec path made \u2014 identical Jentrix-side records.\n summary: await runAgent(\n spec.prompt,\n {\n systemPrompt: spec.systemPrompt,\n maxTurns: spec.maxTurns,\n ...(spec.model ? { model: spec.model } : {}),\n ...(spec.repoCwd ? { repoCwd: spec.repoCwd } : {}),\n ...(spec.runnerOwnsSubmissions\n ? { runnerOwnsSubmissions: true }\n : {}),\n ...(spec.repoReadOnly ? { repoReadOnly: spec.repoReadOnly } : {}),\n },\n {\n connection: spec.connection,\n provider: spec.provider,\n signal,\n },\n ),\n }),\n });\n return summaryOrThrow(envelope);\n }\n\n // Docker: the turn runs in an ephemeral container over the mounted checkout.\n // The turn spec rides in via allowlisted env (never on the command line) and is\n // reconstructed by run-turn.ts into the identical `runJentrixAgent` call.\n const turnEnv = dockerTurnEnv(spec);\n const manifest: RunManifestInput = {\n runId,\n jobId: spec.jobId,\n command: dockerTurnCommand(),\n codeSnapshot: {\n kind: \"checkout\",\n ref: spec.repoCwd ?? process.cwd(),\n },\n workdir: \"/workspace\",\n envAllowlist: [\n ...Object.keys(turnEnv),\n // Provider credentials + infra inherited from the host env.\n \"ANTHROPIC_API_KEY\",\n \"STACKS_AGENT_MODEL\",\n \"STACKS_CLAUDE_EFFORT\",\n \"HOME\",\n \"PATH\",\n ],\n env: turnEnv,\n capabilities: [{ id: \"mcp:stacks\", kind: \"mcp\" }],\n limits: { wallMs, ...(spec.cpuMs ? { cpuMs: spec.cpuMs } : {}) },\n // A containerized agent turn needs egress to the MCP server + provider API;\n // it only runs when the operator has enabled it (deny-by-default otherwise).\n // The allowlisted host is the REACHABLE (host-gateway-rewritten) MCP host.\n egress: sandboxNetAllowed()\n ? { mode: \"allowlist\", allow: [new URL(turnEnv.STACKS_MCP_URL).host] }\n : { mode: \"deny\" },\n };\n const envelope = await backend.run(manifest, { signal: spec.signal });\n // Recover the FULL container summary from stdout (the framed region), so the\n // captured evidence is byte-for-byte the host driver's in-process summary rather\n // than a truncated last line \u2014 this is what keeps the Jentrix-side records identical.\n return summaryOrThrow(envelope, (e) =>\n extractTurnSummary(e.stdout, e.summary),\n );\n}\n\n/** The turn summary on success; a descriptive throw on any structured failure. */\nfunction summaryOrThrow(\n envelope: ResultEnvelope,\n extractSummary: (e: ResultEnvelope) => string = (e) => e.summary,\n): string {\n if (envelope.status === \"succeeded\") return extractSummary(envelope);\n const f = envelope.failure;\n if (isResourceLimitExceeded(envelope)) {\n throw new Error(\n `agent turn killed: ${f?.limit} budget exceeded (${envelope.state}) \u2014 ${f?.message}`,\n );\n }\n throw new Error(\n `agent turn ${envelope.status} (${envelope.state}): ${\n f?.message ?? envelope.stderr ?? \"no detail\"\n }`,\n );\n}\n", "/**\n * Reference-runner authentication selector (M12.4b, AGE-174; legacy PATs\n * removed 2026-07, D4/AGE-509).\n *\n * The reference `workflow-runner` supports two provisioning modes, selected by\n * `STACKS_RUNNER_MODE`:\n *\n * \u2022 `managed` \u2014 the Jentrix-operated plane. Zero standing PATs; every role token\n * is minted per-run from workload identity (see `managed-auth.ts`).\n * \u2022 `self-hosted` \u2014 a runner on your own box. Authenticates via the M11.1\n * bootstrap + claim-URL flow: a ONE-TIME bootstrap token is redeemed at a\n * single-use, short-TTL claim URL for short-lived role tokens (refreshed\n * thereafter). No standing PAT required.\n *\n * The pre-M12.4 standing-PAT path (STACKS_RUNNER_TOKEN / STACKS_PLANNER_TOKEN /\n * STACKS_REVIEWER_TOKEN) was DELETED: nothing reads those env vars anymore, and\n * an unset mode is a configuration error naming the two real modes.\n *\n * `resolveRunnerAuth` returns a `RunnerTokenProvider`; the runner resolves each\n * role's bearer token through it at use-time, so short-lived tokens refresh\n * transparently.\n */\nimport {\n mkdirSync,\n readFileSync,\n renameSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { dirname } from \"node:path\";\n\nimport {\n createCachingTokenProvider,\n createHttpCapabilityMinter,\n createManagedTokenProvider,\n type CachingProviderOptions,\n type CapabilityMinter,\n type ManagedRunContext,\n type MintedToken,\n type RunnerRole,\n type RunnerTokenProvider,\n} from \"./managed-auth.js\";\n\nexport type {\n MintedToken,\n RunnerRole,\n RunnerTokenProvider,\n} from \"./managed-auth.js\";\n\n/**\n * Refuse to authenticate a call with an empty bearer (AGE-687).\n *\n * The runner's module-level role tokens start as `\"\"` and are (re)written only\n * by `refreshRoleTokens()`, which runs on the drive/commit/poll ticks and at leg\n * starts. A caller firing on its OWN timer \u2014 the heartbeat pump \u2014 can therefore\n * read one before the first refresh lands or while a re-mint is in flight.\n * Interpolating that into `Bearer ${token}` emits the literal header `Bearer `,\n * which the endpoint reports as `invalid_token / \"No authorization provided\"` \u2014\n * indistinguishable from a revoked token, and it burns both transient retries on\n * a condition no retry can fix at that call site.\n *\n * Failing fast and legibly is the correct direction: the token is missing\n * locally, not rejected remotely, and the caller's next tick has a real one.\n */\nexport function assertBearerPresent(token: string, context: string): void {\n if (token) return;\n throw new Error(\n `${context} refused: no bearer token available (role token not yet minted, or a re-mint is in flight). This is a local credential gap, not a server rejection.`,\n );\n}\n\n/**\n * A source of short-lived role tokens for the self-hosted path \u2014 the M11.1\n * bootstrap + claim-URL flow. Injectable so tests can drive it without HTTP.\n */\nexport interface RoleTokenSource {\n obtain(role: RunnerRole): Promise<MintedToken>;\n}\n\nexport interface SelfHostedTokenProviderDeps {\n source: RoleTokenSource;\n cache?: CachingProviderOptions;\n}\n\n/** Self-hosted provider: short-lived tokens from the bootstrap + claim-URL flow. */\nexport function createSelfHostedTokenProvider(\n deps: SelfHostedTokenProviderDeps,\n): RunnerTokenProvider {\n return createCachingTokenProvider(\n \"self-hosted\",\n (role) => deps.source.obtain(role),\n deps.cache,\n );\n}\n\nexport interface BootstrapClaimConfig {\n /** One-time bootstrap token (NOT a standing PAT) redeemed at the claim URL. */\n bootstrapToken: string;\n /** Single-use, short-TTL claim URL where the runner claims its credentials. */\n claimUrl: string;\n /** Injectable for tests; defaults to the global `fetch`. */\n fetchImpl?: typeof fetch;\n /** AGE-837: persist the ROTATED refresh credential here so a respawned\n * process (launchd once-mode) resumes the chain instead of re-presenting\n * the spent bootstrap. Secret material \u2014 written 0600, must be gitignored.\n * Unset = the pre-AGE-837 in-memory-only behavior. */\n statePath?: string;\n}\n\n/** Best-effort read of a persisted refresh credential; absent/corrupt = null. */\nfunction readPersistedRefresh(path: string | undefined): string | null {\n if (!path) return null;\n try {\n const parsed = JSON.parse(readFileSync(path, \"utf8\")) as {\n refreshToken?: unknown;\n };\n return typeof parsed.refreshToken === \"string\" && parsed.refreshToken\n ? parsed.refreshToken\n : null;\n } catch {\n return null;\n }\n}\n\n/** Atomically persist the newest refresh credential (tmp + rename, 0600). A\n * write failure only WARNS: auth still works in-process; the cost is one\n * fresh-grant ritual after the next restart, not a failed claim now. */\nfunction persistRefresh(path: string | undefined, refreshToken: string): void {\n if (!path) return;\n try {\n mkdirSync(dirname(path), { recursive: true });\n const tmp = `${path}.tmp`;\n writeFileSync(\n tmp,\n `${JSON.stringify({ refreshToken, rotatedAt: new Date().toISOString() })}\\n`,\n { mode: 0o600 },\n );\n renameSync(tmp, path);\n } catch (err) {\n console.error(\n `[auth] failed to persist refresh state to ${path}: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n}\n\nfunction dropPersistedRefresh(path: string | undefined): void {\n if (!path) return;\n try {\n unlinkSync(path);\n } catch {\n // Already gone (or never written) \u2014 the goal state.\n }\n}\n\n/**\n * Default self-hosted token source: the M11.1 bootstrap + claim-URL flow. The\n * FIRST claim redeems the one-time bootstrap token; the claim endpoint returns a\n * short-lived role token plus a refresh credential, and subsequent obtains\n * refresh with that credential \u2014 the bootstrap token is never a standing PAT and\n * is spent exactly once. Fails closed (throws) on any non-2xx or a response\n * missing the short-lived token.\n */\nexport function createBootstrapClaimSource(\n cfg: BootstrapClaimConfig,\n): RoleTokenSource {\n const doFetch = cfg.fetchImpl ?? fetch;\n // AGE-837: a persisted chain outranks the configured bootstrap \u2014 the\n // bootstrap in env is SPENT the moment any process redeems it, so on a\n // respawn the disk state is the only credential that can still work.\n let refreshToken: string | null = readPersistedRefresh(cfg.statePath);\n // Serialize claims: concurrent first-obtains must NOT each spend the one-time\n // bootstrap token \u2014 the first claim rotates to the refresh credential before\n // the next runs. A rejection never poisons the queue.\n let queue: Promise<unknown> = Promise.resolve();\n\n const post = (\n grant: \"bootstrap\" | \"refresh\",\n token: string,\n role: RunnerRole,\n ) =>\n doFetch(cfg.claimUrl, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ role, grant, token }),\n // AGE-835: a claim fetch that stalls (no server response, dead socket)\n // hangs this queue FOREVER \u2014 rejections don't poison it, but an unsettled\n // promise does, and every later obtain chains behind it. Fail loudly\n // instead; the next tick re-obtains.\n signal: AbortSignal.timeout(30_000),\n });\n\n const claimOne = async (role: RunnerRole): Promise<MintedToken> => {\n let res = refreshToken\n ? await post(\"refresh\", refreshToken, role)\n : await post(\"bootstrap\", cfg.bootstrapToken, role);\n // AGE-922: a 401 on the REFRESH grant means the PERSISTED chain is dead \u2014\n // it says nothing about the bootstrap in env, which the operator may have\n // just re-minted precisely because of this 401. Dropping the file alone was\n // not enough on either axis: the in-memory `refreshToken` survived, so every\n // later obtain in this process re-presented the dead credential, and the\n // thrown message told the operator to mint a grant they had already minted.\n // Clear BOTH and retry once on the bootstrap, so a stale state file\n // self-heals instead of costing a hand-deleted file plus a restart.\n if (res.status === 401 && refreshToken) {\n refreshToken = null;\n dropPersistedRefresh(cfg.statePath);\n console.error(\n `[auth] persisted refresh chain rejected (401) \u2014 falling back to the configured bootstrap grant (AGE-922).`,\n );\n res = await post(\"bootstrap\", cfg.bootstrapToken, role);\n }\n if (!res.ok) {\n // Reaching here on a 401 means the BOOTSTRAP itself was rejected (the\n // refresh fallback above already ran), so the ritual really is owed.\n if (res.status === 401) dropPersistedRefresh(cfg.statePath);\n throw new Error(\n `claim-URL redemption failed (${res.status}) for the ${role} role${\n res.status === 401\n ? \" \u2014 the configured bootstrap grant is spent, expired, or revoked (a persisted refresh chain, if any, was already retried and dropped); mint a fresh bootstrap grant (POST /api/agents/bootstrap) and update STACKS_BOOTSTRAP_TOKEN + STACKS_CLAIM_URL in agents/.env\"\n : \"\"\n }`,\n );\n }\n const body = (await res.json()) as {\n token?: string;\n expiresAt?: string;\n refreshToken?: string;\n };\n if (!body.token || !body.expiresAt) {\n throw new Error(\n `claim-URL returned no short-lived token for the ${role} role`,\n );\n }\n // Rotate to the refresh credential so the one-time bootstrap is spent once;\n // persist it so a respawned process resumes the chain (AGE-837).\n if (body.refreshToken) {\n refreshToken = body.refreshToken;\n persistRefresh(cfg.statePath, body.refreshToken);\n }\n return { token: body.token, expiresAt: body.expiresAt };\n };\n\n return {\n obtain(role) {\n const run = queue.then(() => claimOne(role));\n queue = run.catch(() => {});\n return run;\n },\n };\n}\n\nexport interface ResolveRunnerAuthDeps {\n env?: NodeJS.ProcessEnv;\n cache?: CachingProviderOptions;\n /** Managed mode: the capability minter + run context. Defaults to the HTTP\n * minter built from workload-identity env when omitted. */\n managed?: {\n minter?: CapabilityMinter;\n runContext?: ManagedRunContext;\n onMint?: (role: RunnerRole, minted: MintedToken) => void;\n };\n /** Self-hosted mode: the role-token source. Defaults to the bootstrap +\n * claim-URL source built from env when omitted. */\n selfHosted?: { source?: RoleTokenSource };\n}\n\nfunction required(env: NodeJS.ProcessEnv, name: string): string {\n const value = env[name];\n if (!value || !value.trim()) {\n throw new Error(\n `STACKS_RUNNER_MODE requires ${name} \u2014 see agents/README.md.`,\n );\n }\n return value;\n}\n\nfunction defaultManagedProvider(\n env: NodeJS.ProcessEnv,\n deps: ResolveRunnerAuthDeps,\n): RunnerTokenProvider {\n const minter =\n deps.managed?.minter ??\n createHttpCapabilityMinter({\n exchangeUrl: required(env, \"STACKS_TOKEN_EXCHANGE_URL\"),\n // The worker's short-lived workload-identity SVID (M12.4a) \u2014 not a PAT.\n svid: required(env, \"STACKS_WORKLOAD_SVID\"),\n });\n const runContext = deps.managed?.runContext ?? {\n runId: required(env, \"STACKS_RUN_ID\"),\n workspaceId: required(env, \"STACKS_WORKSPACE_ID\"),\n };\n return createManagedTokenProvider({\n minter,\n runContext,\n env,\n onMint: deps.managed?.onMint,\n cache: deps.cache,\n });\n}\n\nfunction defaultSelfHostedProvider(\n env: NodeJS.ProcessEnv,\n deps: ResolveRunnerAuthDeps,\n): RunnerTokenProvider {\n const source =\n deps.selfHosted?.source ??\n createBootstrapClaimSource({\n bootstrapToken: required(env, \"STACKS_BOOTSTRAP_TOKEN\"),\n claimUrl: required(env, \"STACKS_CLAIM_URL\"),\n // AGE-837: default ON \u2014 resuming the persisted chain across restarts is\n // what kills the fresh-grant-per-restart ritual (launchd once-mode\n // respawns above all). Relative to the runner's cwd (agents/).\n statePath:\n env.STACKS_AUTH_STATE_PATH?.trim() || \".runner-auth-state.json\",\n });\n return createSelfHostedTokenProvider({ source, cache: deps.cache });\n}\n\n/**\n * Select and construct the runner's token provider from the environment.\n *\n * STACKS_RUNNER_MODE=managed \u2192 workload identity (zero PATs)\n * STACKS_RUNNER_MODE=self-hosted \u2192 M11.1 bootstrap + claim-URL (short-lived)\n * anything else \u2192 configuration error (the legacy\n * standing-PAT path was deleted, D4)\n */\nexport function resolveRunnerAuth(\n deps: ResolveRunnerAuthDeps = {},\n): RunnerTokenProvider {\n const env = deps.env ?? process.env;\n const mode = (env.STACKS_RUNNER_MODE ?? \"\").trim().toLowerCase();\n\n if (mode === \"managed\") return defaultManagedProvider(env, deps);\n if (mode === \"self-hosted\" || mode === \"selfhosted\") {\n return defaultSelfHostedProvider(env, deps);\n }\n if (mode) {\n throw new Error(\n `Unknown STACKS_RUNNER_MODE=\"${mode}\". Use \"managed\" or \"self-hosted\".`,\n );\n }\n throw new Error(\n \"No runner auth configured. Set STACKS_RUNNER_MODE=self-hosted (M11.1 \" +\n \"bootstrap + claim-URL \u2014 mint a grant via POST /api/agents/bootstrap, \" +\n \"then set STACKS_BOOTSTRAP_TOKEN + STACKS_CLAIM_URL) or =managed \" +\n \"(workload identity). The standing-PAT path was removed (D4, 2026-07).\",\n );\n}\n", "/**\n * Standing-PAT retirement policy (M12.4b, AGE-174).\n *\n * This module is THE single place that NAMES the standing personal-access-token\n * env vars the managed execution path must never carry. It only ever *forbids*\n * them \u2014 it never reads one for consumption. Keeping the names here (and NOT in\n * the managed-path modules) is deliberate: the managed-path grep test\n * (`runner-auth.smoke.test.ts`) can then assert that no managed-path file so much\n * as mentions a standing-PAT env var, with this policy file as the one allowed\n * declaration site.\n *\n * Background: before M12.4 the reference runner authenticated every role with a\n * long-lived PAT (`STACKS_RUNNER_TOKEN` / `STACKS_PLANNER_TOKEN` /\n * `STACKS_REVIEWER_TOKEN`). M12.4a introduced the workload-identity plane +\n * per-run capability tokens; M12.4b (this) retires the standing PATs from the\n * managed plane entirely and deprecates them in the reference runner. The only\n * code allowed to read one is the explicitly-deprecated legacy provider in\n * `runner-auth.ts`, and only for backward-compatible self-hosted runners.\n */\n\n/**\n * The standing PAT env vars retired from the managed execution path. The managed\n * plane authenticates via workload identity + short-lived per-run capability\n * tokens (M12.4a) and carries NONE of these.\n */\nexport const STANDING_PAT_ENV_VARS = [\n \"STACKS_RUNNER_TOKEN\",\n \"STACKS_PLANNER_TOKEN\",\n \"STACKS_REVIEWER_TOKEN\",\n] as const;\n\nexport type StandingPatEnvVar = (typeof STANDING_PAT_ENV_VARS)[number];\n\n/**\n * Thrown when a standing PAT is present in an environment that must be\n * PAT-free \u2014 the managed execution path. Fail-closed: the managed plane refuses\n * to start rather than silently authenticate with a long-lived credential.\n */\nexport class StandingPatOnManagedPathError extends Error {\n readonly present: string[];\n constructor(present: string[]) {\n super(\n `Managed execution path refuses to start: standing PAT env var(s) present ` +\n `(${present.join(\", \")}). The managed plane authenticates via workload ` +\n `identity + per-run capability tokens (M12.4a) and must carry ZERO ` +\n `standing PATs in any env or config. Unset them on the managed plane, or ` +\n `run the deprecated self-hosted legacy path deliberately.`,\n );\n this.name = \"StandingPatOnManagedPathError\";\n this.present = present;\n }\n}\n\n/**\n * Fail closed if any standing PAT leaked into a managed-path environment.\n * Iterates the forbidden NAMES (a variable lookup \u2014 never a literal\n * `process.env.STACKS_*_TOKEN` read) so this presence check can never be mistaken\n * for consumption by the managed-path grep.\n */\nexport function assertNoStandingPatsOnManagedPath(\n env: NodeJS.ProcessEnv = process.env,\n): void {\n const present = STANDING_PAT_ENV_VARS.filter((name) => {\n const value = env[name];\n return typeof value === \"string\" && value.trim().length > 0;\n });\n if (present.length > 0) throw new StandingPatOnManagedPathError(present);\n}\n", "/**\n * Managed execution-path authentication (M12.4b, AGE-174).\n *\n * The managed plane (Jentrix-operated workers) authenticates with ZERO standing\n * PATs. Instead it holds a short-lived, auto-rotated workload-identity SVID\n * (M12.4a) and trades it \u2014 per run \u2014 for narrow, short-TTL capability tokens via\n * the control-plane token exchange. This module is the runner-side seam for that\n * flow:\n *\n * \u2022 `createManagedTokenProvider` fails CLOSED the instant a standing PAT is\n * present in its environment (`assertNoStandingPatsOnManagedPath`), then\n * resolves each role's bearer token by MINTING a capability token from\n * workload identity \u2014 never from a PAT env var.\n * \u2022 `createHttpCapabilityMinter` is the production wiring: it presents the\n * worker's SVID to the control-plane exchange endpoint and receives a\n * run/workspace/role-scoped capability token (a NARROWING of the run's P2.1\n * authorization \u2014 see `@stacks/identity`).\n *\n * INVARIANT (asserted by the managed-path grep in `runner-auth.smoke.test.ts`):\n * this file \u2014 and every other managed-path module \u2014 never READS a standing-PAT\n * env var. The forbidden names live only in `standing-pat-policy.ts`.\n */\nimport { assertNoStandingPatsOnManagedPath } from \"./standing-pat-policy.js\";\n\n/** The three principals the runner authenticates (claim \u2260 submit principal). */\nexport type RunnerRole = \"runner\" | \"planner\" | \"reviewer\";\n\n/** How a role token was provisioned. `legacy-pat` is the deprecated path. */\nexport type RunnerAuthMode = \"managed\" | \"self-hosted\" | \"legacy-pat\";\n\n/** A minted bearer token + its expiry. Short-lived by construction (minutes). */\nexport interface MintedToken {\n token: string;\n /** ISO-8601 expiry. */\n expiresAt: string;\n}\n\n/**\n * Resolves a currently-valid bearer token for a runner role, minting/refreshing\n * as needed. The workflow-runner calls `tokenFor` at each use so a long-running\n * server never presents an expired short-lived token.\n */\nexport interface RunnerTokenProvider {\n readonly mode: RunnerAuthMode;\n tokenFor(role: RunnerRole): Promise<string>;\n /** Drop the cached token for a role so the next `tokenFor` mints fresh.\n * Used at LEG boundaries: every mint ROTATES the server-side bearer, so a\n * mid-leg refresh kills the in-flight session's embedded token \u2014 but a leg\n * must also START with a full-TTL token or it dies at submit. Invalidate +\n * obtain at leg start; leave the small expiry skew everywhere else. */\n invalidate?(role: RunnerRole): void;\n}\n\n/** The run this managed worker was dispatched for (per-run capability scope). */\nexport interface ManagedRunContext {\n runId: string;\n workspaceId: string;\n}\n\n/** Trades workload identity for a short-lived, role-scoped capability token. */\nexport interface CapabilityMinter {\n mint(role: RunnerRole, ctx: ManagedRunContext): Promise<MintedToken>;\n}\n\nexport interface CachingProviderOptions {\n /** Re-mint a role token this many ms before it expires (default 30s). */\n refreshSkewMs?: number;\n now?: () => number;\n}\n\n/**\n * Wrap a per-role `fetchToken` in an expiry-aware cache: a cached token is\n * reused while comfortably before expiry, otherwise re-minted. Both the managed\n * and self-hosted providers build on this so their short-lived tokens refresh\n * transparently across a long-running server's lifetime.\n */\nexport function createCachingTokenProvider(\n mode: RunnerAuthMode,\n fetchToken: (role: RunnerRole) => Promise<MintedToken>,\n opts: CachingProviderOptions = {},\n): RunnerTokenProvider {\n const skew = opts.refreshSkewMs ?? 30_000;\n const now = opts.now ?? (() => Date.now());\n const cache = new Map<RunnerRole, MintedToken>();\n return {\n mode,\n async tokenFor(role) {\n const cached = cache.get(role);\n if (cached) {\n const expMs = Date.parse(cached.expiresAt);\n if (Number.isFinite(expMs) && expMs - now() > skew) return cached.token;\n }\n const minted = await fetchToken(role);\n cache.set(role, minted);\n return minted.token;\n },\n invalidate(role) {\n cache.delete(role);\n },\n };\n}\n\nexport interface ManagedTokenProviderDeps {\n /** Trades the worker's SVID for per-run, role-scoped capability tokens. */\n minter: CapabilityMinter;\n /** The run this managed worker executes (per-run token scope). */\n runContext: ManagedRunContext;\n /** Environment checked for standing PATs at construction (default process.env). */\n env?: NodeJS.ProcessEnv;\n /** Non-secret audit hook fired after each mint (never the token itself). */\n onMint?: (role: RunnerRole, minted: MintedToken) => void;\n cache?: CachingProviderOptions;\n}\n\n/**\n * The managed provider. Fails CLOSED if any standing PAT is present in its\n * environment, then resolves every role token by minting a capability token from\n * workload identity \u2014 the managed plane carries ZERO standing PATs.\n */\nexport function createManagedTokenProvider(\n deps: ManagedTokenProviderDeps,\n): RunnerTokenProvider {\n // The managed plane must carry no standing PAT \u2014 refuse to start otherwise.\n assertNoStandingPatsOnManagedPath(deps.env ?? process.env);\n return createCachingTokenProvider(\n \"managed\",\n async (role) => {\n const minted = await deps.minter.mint(role, deps.runContext);\n deps.onMint?.(role, minted);\n return minted;\n },\n deps.cache,\n );\n}\n\n/**\n * The scopes/actions each role requests from the token exchange. The exchange\n * still NARROWS to the run's authorization \u2229 the SVID's upper bound, so this is\n * an upper request, never a grant (see `@stacks/identity` `exchangeCapabilityToken`).\n */\nexport const ROLE_CAPABILITY_REQUEST: Record<\n RunnerRole,\n { scopes: string[]; actions: string[] }\n> = {\n // The admin principal: claim / heartbeat / fail / authorize the local commit.\n runner: {\n scopes: [\"read\", \"write\", \"admin\"],\n actions: [\"job:claim\", \"job:heartbeat\", \"job:fail\", \"repo:commit\"],\n },\n // The executor principal: submit plan/execution results (turn-guard).\n planner: { scopes: [\"read\", \"write\"], actions: [\"job:submit\"] },\n // The reviewer principal: submit reviews (turn-guard).\n reviewer: { scopes: [\"read\", \"write\"], actions: [\"job:submit\"] },\n};\n\nexport interface HttpCapabilityMinterConfig {\n /** Control-plane token-exchange endpoint (mTLS in production). */\n exchangeUrl: string;\n /** The worker's presented workload-identity SVID (short-lived, auto-rotated). */\n svid: string;\n /** Injectable for tests; defaults to the global `fetch`. */\n fetchImpl?: typeof fetch;\n}\n\n/**\n * Production capability minter: presents the worker's SVID to the control-plane\n * token-exchange endpoint and receives a run/workspace/role-scoped capability\n * token. Fails closed (throws) on any non-2xx or a response missing the token \u2014\n * it never falls back to a PAT.\n */\nexport function createHttpCapabilityMinter(\n cfg: HttpCapabilityMinterConfig,\n): CapabilityMinter {\n const doFetch = cfg.fetchImpl ?? fetch;\n return {\n async mint(role, ctx) {\n const spec = ROLE_CAPABILITY_REQUEST[role];\n const res = await doFetch(cfg.exchangeUrl, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n // The SVID is the mTLS-channel-delivered identity, NOT a bearer PAT.\n authorization: `SVID ${cfg.svid}`,\n },\n body: JSON.stringify({\n role,\n runId: ctx.runId,\n workspaceId: ctx.workspaceId,\n scopes: spec.scopes,\n actions: spec.actions,\n }),\n // AGE-835: a stalled exchange must reject, never hang the caller.\n signal: AbortSignal.timeout(30_000),\n });\n if (!res.ok) {\n throw new Error(\n `token-exchange failed (${res.status}) minting the ${role} capability`,\n );\n }\n const body = (await res.json()) as {\n token?: string;\n expiresAt?: string;\n };\n if (!body.token || !body.expiresAt) {\n throw new Error(\n `token-exchange returned no capability token for the ${role} role`,\n );\n }\n return { token: body.token, expiresAt: body.expiresAt };\n },\n };\n}\n", "/**\n * AGE-899: which role minted a given bearer, including bearers that have since\n * been rotated out.\n *\n * The AGE-840 re-mint asks \"which role does this 401'ing token belong to?\" so it\n * can invalidate that role and mint a fresh one. Answering by identity against\n * the CURRENT role tokens is not enough, and that gap is what made the fix miss\n * in production: a long call \u2014 a heartbeat, an executor turn \u2014 captures its\n * bearer, `refreshRoleTokens` swaps the module-level tokens underneath it, and\n * the 401 that follows then resolves to no role at all. The re-mint declines and\n * the caller wedges for the rest of the token's TTL. Observed live on 2026-08-02:\n * the re-mint fired correctly at 02:29 and failed to fire at 05:28, costing a\n * stage attempt against the immutable retry cap.\n *\n * A superseded bearer only has to stay recognizable long enough for its\n * in-flight call to fail, so the history is capped rather than unbounded \u2014 it\n * can never grow with process uptime.\n */\nimport type { RunnerRole } from \"./runner-auth.js\";\n\n/** Several generations across three roles; far more than any in-flight call needs. */\nexport const TOKEN_ROLE_HISTORY_MAX = 12;\n\nconst history = new Map<string, RunnerRole>();\n\n/** Record a freshly minted token. Call BEFORE anything can rotate it again. */\nexport function rememberTokenRole(token: string, role: RunnerRole): void {\n if (!token) return;\n // Re-insert so the most recently minted tokens are the last to be pruned:\n // Map iterates in insertion order, so delete-then-set moves this key to the\n // end and the eviction below always takes the genuinely oldest entry.\n history.delete(token);\n history.set(token, role);\n while (history.size > TOKEN_ROLE_HISTORY_MAX) {\n const oldest = history.keys().next().value;\n if (oldest === undefined) break;\n history.delete(oldest);\n }\n}\n\n/** The role that minted this bearer, or null if it is not one of ours. */\nexport function roleForKnownToken(token: string): RunnerRole | null {\n if (!token) return null;\n return history.get(token) ?? null;\n}\n\n/** Test seam \u2014 the history is process-global by design. */\nexport function resetTokenRoleHistoryForTests(): void {\n history.clear();\n}\n", "/**\n * Harness-aware runner protocol (H10.6).\n *\n * The generic M7 `workflow-runner` reacts to `agent.handoff` and runs the\n * plan \u2192 review \u2192 execute \u2192 review loop. A Harness Automation STAGE rides the\n * SAME loop (`templateKey === \"stage_execution\"`), but its execution turn has\n * extra obligations that this module implements:\n *\n * 1. DETECT a harness stage job. The `agent.handoff` webhook carries only the\n * jobId \u2014 `get_agent_job(jobId)` returns a `harness` block (run/stage ids,\n * branch/repo/base + strategy/template, commit policy, acceptance criteria)\n * when, and only when, the job executes a HarnessStage.\n * 2. EXECUTION TURN (driveHarnessStage, on the EXECUTING handoff \u2014 it does NOT\n * commit; the local commit is only authorizable once the stage is validated):\n * execute in the mapped checkout (the run's repo \u2192 STACKS_RUNNER_REPOS), then\n * \u2022 `submit_harness_artifact` \u00D72 \u2014 capture the diff (DIFF_OR_PATCH) + test\n * evidence (TEST_EVIDENCE), the two gate-required kinds beyond the\n * EXECUTION_SUMMARY,\n * \u2022 `submit_harness_stage_result` \u2014 the structured evidence + the linked\n * artifacts (NO commit yet), what the validation gate reads, and\n * \u2022 `submit_execution_result` \u2014 the generic M7 submission that advances\n * EXECUTING \u2192 EXECUTION_REVIEW so the reviewer turn opens.\n * 3. COMMIT BOUNDARY (driveHarnessCommit, once the stage is VALIDATED/COMMIT_GATE\n * \u2014 opportunistically after submit when an ALLOW policy auto-approved, else on\n * a later invocation after a human approves the acceptance gate): AUTHORIZE the\n * local commit with `authorize_harness_local_commit` BEFORE running\n * `git commit` (a `repo:commit` permission check that honors freeze/leases/\n * policy \u2014 it mints NO credential and approves NO gate), then report the SHA\n * via `submit_harness_stage_result` (the local-commit evidence the boundary\n * needs to advance to COMMITTED).\n * 4. PUSH/PR only AFTER the commit boundary authorizes it: poll the stage until\n * it is COMMITTED (push/PR authorized), then broker a SINGLE-USE\n * `repo:push` / `repo:pr_create` credential (the injected\n * `brokerPushCredential` seam \u2014 a real deployment wires it to the M8 governed\n * broker) and perform the external git write. There is NO standing raw repo\n * token, and the broker fails closed (no push) while frozen or on a deny.\n * 5. FREEZE. `heartbeat_agent_job` returns `{ frozen: true }` when the run is\n * frozen \u2014 this module ABORTS the in-flight subprocess and performs no\n * further submit / commit-evidence / credential / push / PR until resume.\n * Freeze is honored by THIS external process, not only by Jentrix guards.\n *\n * Everything that touches the outside world (MCP, the agent runtime, git, the\n * clock) is INJECTED, so the smoke test (`harness-runner.smoke.test.ts`) drives a\n * fake repo with mocked provider turns and no real Claude/Codex/GitHub.\n *\n * Security invariants Codex validates (H10.6 focus):\n * \u2022 No agent self-approves a human gate \u2014 the runner only AUTHORIZES the local\n * commit (never the commit/merge gate) and waits for the gate to advance.\n * \u2022 No standing repo credential \u2014 push/PR creds are brokered single-use.\n * \u2022 Freeze is honored by the external process.\n * \u2022 The shell-capable checkout path is BOUNDED to configured repos \u2014 an\n * unmapped repo aborts before any agent/git/credential action.\n */\n\nimport { createHash } from \"node:crypto\";\n\nimport { claudeLegModel, claudeModel } from \"./providers/claude.js\";\nimport { codexModel } from \"./providers/codex.js\";\nimport {\n workerCapabilities,\n type WorkerCapabilitiesDecl,\n} from \"./providers/capabilities.js\";\nimport {\n resolveClaimExecution,\n type ExpectedRoleBinding,\n type ResolvedClaimExecution,\n} from \"./runtime-routing.js\";\nimport { buildProjectContext, measureBaseDrift } from \"./project-context.js\";\nimport { loadRubric } from \"./rubrics.js\";\nimport {\n missingReadOnlyCheckoutReason,\n repoAccessForRole,\n} from \"./role-repo-access.js\";\nimport { agentProvider } from \"./jentrix.js\";\nimport {\n resolveRevisionStamp,\n type RevisionStamp,\n} from \"../../packages/execution/src/revision.js\";\nimport type {\n StageWorktreeIdentity,\n WorktreeManager,\n} from \"./harness-worktree.js\";\n\nexport interface HarnessStageJobContext {\n harnessRunId: string;\n stageId: string;\n stageNumber: number;\n stageTitle: string;\n branch: string | null;\n branchTemplate: string | null;\n /** AGE-690: the run's anchor task key \u2014 what `{taskKey}` in `branchTemplate`\n * resolves to. Carried on THIS context (not a webhook payload) so the poll\n * leg resolves the same branch the webhook leg does. Optional: a server\n * predating AGE-690 omits it. */\n taskKey?: string | null;\n repo: string | null;\n baseBranch: string | null;\n branchStrategy: string;\n commitPolicy: string | null;\n acceptanceCriteria: string[];\n /** AGE-781: the decomposition-reviewed implementation approach \u2014 rendered\n * into the executor prompt (stages run with no per-stage plan turn).\n * Absent/null on legacy plans and servers predating the field. */\n approach?: string | null;\n /** HAI S3: commands the RUNNER executes itself (foreground, per-command\n * timeout, in the stage worktree) to mint attested TEST_EVIDENCE. Executor\n * prose never satisfies the evidence gate. Absent/empty on legacy plans. */\n verificationCommands?: string[];\n /** HAI S3: the AUTOMATED policy criteria the attested evidence covers \u2014\n * passed through as criterionRefs on the TEST_EVIDENCE capture. */\n automatedCriteria?: string[];\n /** Stage 2: the NAMED ref the stage's execution worktree branches FROM (own\n * branch tip on a retry, the run base on the first stage / after a predecessor\n * merged, else the preceding stage's branch tip). NEVER the checkout HEAD \u2014\n * createWorktree verifies it resolves to a commit before cutting the branch. */\n executionBaseRef: string;\n}\n\n/** The slice of `get_agent_job` this protocol reads. */\nexport interface AgentJobView {\n id: string;\n phase: string;\n turn: string;\n repoOwnerName: string | null;\n /** F6 (AGE-503): non-null while an attempt owns the turn \u2014 a claim on such a\n * job can only CONFLICT (\"it has an active run\"), so pollers skip it and let\n * the sweep expire a zombie run instead of storming identical claims. */\n activeRunId?: string | null;\n harness: HarnessStageJobContext | null;\n harnessRun: {\n id: string;\n repo: string | null;\n baseBranch: string | null;\n } | null;\n}\n\n/** A single MCP tool call with a specific token (admin or role). */\nexport type CallTool = (\n token: string,\n name: string,\n args: Record<string, unknown>,\n) => Promise<Record<string, unknown>>;\n\n/** Run one agent turn in a checkout and return its final summary text. */\nexport type RunAgentTurn = (args: {\n prompt: string;\n systemPrompt: string;\n repoCwd: string;\n /**\n * M18.3 R7: run the turn against `repoCwd` READ-ONLY \u2014 the providers already\n * enforce it (claude.ts withholds the write/edit tools; codex.ts runs the\n * shell under a read-only sandbox). Set from the dispatch role's entry in\n * `role-repo-access.ts`, never by hand.\n */\n repoReadOnly?: boolean;\n /** Aborted when the run is frozen \u2014 the runtime must stop the subprocess. */\n signal: AbortSignal;\n /** W3: this is a harness STAGE executor leg \u2014 the runner submits the result\n * and attests the evidence, so the runtime registers the executor hooks. */\n runnerOwnsSubmissions?: boolean;\n execution?: ResolvedClaimExecution;\n}) => Promise<string>;\n\n/** Run a git command in a checkout; returns trimmed stdout. `env` (when given) is\n * merged into the child's environment \u2014 used to hand a single-use push token to a\n * credential helper WITHOUT placing it in the command line (argv). */\nexport type RunGit = (\n cwd: string,\n args: string[],\n env?: Record<string, string>,\n) => Promise<string>;\n\n/** HAI S3: one runner-executed verification command's observed outcome. */\nexport interface VerificationRunResult {\n command: string;\n exitCode: number;\n timedOut: boolean;\n stdout: string;\n stderr: string;\n startedAt: string;\n finishedAt: string;\n}\n\n/** HAI S3: execute ONE declared verification command in the stage worktree,\n * FOREGROUND, with a hard timeout \u2014 the runner itself, never the agent turn.\n * The command text is gate-approved stage-plan content (the same trust level\n * as bootstrap argv), so the production wiring may run it through a shell.\n * MUST resolve (never reject) with the observed exit/timeout \u2014 a spawn\n * failure is reported as exitCode 127. */\nexport type RunVerificationCommand = (args: {\n cwd: string;\n command: string;\n timeoutMs: number;\n signal: AbortSignal;\n}) => Promise<VerificationRunResult>;\n\nexport interface HarnessRunnerTokens {\n /** read,write,admin \u2014 claim/heartbeat/fail/authorize/broker. */\n runner: string;\n /** read,write \u2014 the executor session principal (turn-guard). */\n planner: string;\n}\n\n/** The only tier a local runner attests (D1 deleted the stronger local lane). */\nexport const DEFAULT_RUNNER_EVIDENCE_TIER = \"INTEGRATION_LOCAL\";\n\n/**\n * D5 dedup: what a worker PRESENTS on `claim_agent_job` \u2014 the pinned model\n * (silent-model-change forensics, M12.3b's fail-closed revision guard, and the\n * M13.4b capability preflight). Shared by the generic M7 drive and the harness\n * stage claim, which used to duplicate this block.\n */\nexport function claimPresentation(\n provider: \"claude\" | \"codex\",\n opts: {\n revision?: RevisionStamp;\n capabilities?: unknown;\n /** The model THIS claim's leg will actually launch (per-leg Claude pins \u2014\n * see claudeLegModel); unset \u21D2 the provider's process-wide pin. */\n model?: string;\n } = {},\n): {\n provider: string;\n model: string;\n schemaRevision: string;\n appRevision: string;\n capabilities: unknown;\n} {\n const revision = opts.revision ?? resolveRevisionStamp();\n const model =\n opts.model ?? (provider === \"codex\" ? codexModel() : claudeModel());\n // M18 bring-up: the release registry + eval-plane egress allowlist key Claude\n // releases by the BILLING provider (\"anthropic\"), while the runner's leg union\n // stays \"claude\" | \"codex\". STACKS_CLAUDE_PROVIDER_LABEL relabels what claude\n // legs PRESENT so claims match an anthropic-pinned release; unset \u21D2 \"claude\".\n const presentedProvider =\n provider === \"claude\"\n ? (process.env.STACKS_CLAUDE_PROVIDER_LABEL?.trim() ?? provider)\n : provider;\n return {\n provider: presentedProvider,\n model,\n schemaRevision: revision.schemaRevision,\n appRevision: revision.appRevision,\n capabilities:\n opts.capabilities ??\n workerCapabilities({\n model,\n // Claude claims always vouch for BOTH per-leg pins: the agent release\n // may pin the planner leg's model while this claim launches the\n // executor leg's (or vice versa) \u2014 either must pass the M13.4b\n // capability preflight.\n extraAcceptedModels:\n provider === \"codex\"\n ? process.env.STACKS_CODEX_ACCEPTED_MODELS\n : [\n process.env.STACKS_CLAUDE_ACCEPTED_MODELS,\n claudeLegModel(\"planner\"),\n claudeLegModel(\"executor\"),\n ]\n .filter(Boolean)\n .join(\",\"),\n }),\n };\n}\n\nexport interface HarnessRunnerConfig {\n tokens: HarnessRunnerTokens;\n /** \"owner/name\" \u2192 local checkout path. The executor path is BOUNDED to this. */\n repos: Record<string, string>;\n /** Heartbeat cadence (ms). */\n heartbeatMs: number;\n /** Poll cadence while waiting for the commit boundary to authorize push (ms). */\n commitPollMs: number;\n /** Max polls before giving up on the commit boundary (then the human drives). */\n commitPollMax: number;\n /** HAI S3: per-command timeout for runner-executed verification commands\n * (default 15 min). A timed-out command is attested timedOut \u2014 the gate\n * blocks on it. */\n verificationTimeoutMs?: number;\n /** HAI S3: the evidence tier this runner attests at (default\n * INTEGRATION_LOCAL \u2014 a local runner). The SERVER caps the claim at the\n * token's maxEvidenceTier ceiling regardless of what is declared here. */\n evidenceTier?: string;\n /**\n * M12.3b (AGE-173): this runner's build-stamped deployment revision, PRESENTED on\n * every `claim_agent_job` so the control plane refuses a schema-incompatible claim\n * FAIL-CLOSED and can require strict schema+app attestation for validator dispatch \u2014\n * the harness execution runner must never execute against an incompatible schema.\n * Defaults to the\n * shared, env-resolved stamp (`resolveRevisionStamp()`) \u2014 the SAME single source of\n * truth the generic M7 runner and the worker/sandbox images stamp from; an\n * un-stamped dev runner presents `unknown` (the control plane's guard is inert).\n */\n revision?: RevisionStamp;\n /**\n * M13.4b (Quality & Release Plane): what this worker can actually run, PRESENTED\n * on every `claim_agent_job` so the control plane refuses a release pinning a\n * model the installed SDK cannot run BEFORE opening a run (zero claims burned).\n * Defaults to `workerCapabilities({ model: claudeLegModel(\"executor\") })` \u2014 the harness\n * executor is always the Claude runtime; it always vouches for the model it\n * launches (never omitted, so the model dimension actually fires in production).\n */\n capabilities?: WorkerCapabilitiesDecl;\n /** Setup-resolved executor binding. Omitted only by the deprecated env path. */\n executorBinding?: ExpectedRoleBinding;\n mintClaimCredential?: (\n binding: ExpectedRoleBinding,\n ) => Promise<string | undefined>;\n stopping?: () => boolean;\n log?: (msg: string) => void;\n}\n\n/**\n * M12.5 (AGE-175) \u2014 the SANDBOX-SIDE egress broker. When wired, the push and PR are\n * performed by a broker that OWNS the credential injection (git credential helper for\n * push, App-token `Authorization` header for PR), so this runner never holds the raw\n * token at all: it hands the broker a non-secret request and gets back only the\n * result. This is the production replacement for the token-returning\n * `brokerPushCredential` + `createPullRequest` seams \u2014 injection moves sandbox-side.\n *\n * Both methods fail CLOSED (return null) when the broker refuses (frozen / policy /\n * grant unresolved); the runner then defers to the governed path, exactly as the\n * no-op seams did. `openPr` returning null defers PR creation to inbound correlation.\n */\nexport interface SandboxEgressBroker {\n push(req: {\n harnessRunId: string;\n stageId: string;\n repo: string;\n branch: string;\n cwd: string;\n }): Promise<{ pushed: boolean } | null>;\n openPr(req: {\n harnessRunId: string;\n stageId: string;\n repo: string;\n branch: string;\n baseBranch: string | null;\n title: string;\n }): Promise<{ url: string; number: number } | null>;\n}\n\n/**\n * S1 documentation commit guard. The managed harness runs `docs:sync` before the\n * final review turn (so a public-contract change lands its generated doc entry in\n * the diff the reviewer sees) and `docs:check` immediately before authorizing the\n * local commit (a stale public contract BLOCKS via a server-recorded, checksum-bound\n * DOCUMENTATION_REVIEW finding). Injected so the smoke tests stub it and a real\n * deployment wires it to spawn `pnpm docs:sync` / `pnpm docs:check` in the worktree.\n */\nexport interface DocsGuard {\n /** Regenerate the checked-in generated docs in the worktree (`pnpm docs:sync`). */\n sync(cwd: string, changedFiles: string[]): Promise<void>;\n /** Run the public-contract docs check (`pnpm docs:check`) over the worktree change. */\n check(\n cwd: string,\n changedFiles: string[],\n ): Promise<{ ok: boolean; staleDocs: string[]; output: string }>;\n}\n\nexport interface HarnessRunnerDeps {\n callTool: CallTool;\n runAgentTurn: RunAgentTurn;\n git: RunGit;\n /**\n * HAI S3: execute a declared verification command (foreground, timed) so the\n * runner \u2014 never the executor \u2014 authors TEST_EVIDENCE. Optional for older\n * test harnesses: when absent and a stage declares commands, NO test\n * evidence is captured (the stage honestly fails its gate) and the\n * structured report lists the commands under testsNotRun.\n */\n runCommand?: RunVerificationCommand;\n /** Fail-fast managed verification preflight. Production wires this before the\n * claim so a missing daemon/image consumes zero model turns. */\n preflightVerification?: () => Promise<void>;\n /**\n * S1: the documentation commit guard. Absent \u21D2 the guard is skipped (the\n * reference/smoke path); the managed workflow-runner wires the real one, so the\n * managed harness always runs docs:sync before review and docs:check before commit.\n */\n docsGuard?: DocsGuard;\n /**\n * M12.5: the sandbox-side broker that OWNS credential injection \u2014 the ONLY\n * push/PR egress (D5, 2026-07: the raw-token seams were deleted). When\n * absent (the default), push/PR defer fail-closed: the stage stays COMMITTED\n * on Jentrix and the governed delivery path (or an operator) performs the\n * externally-visible write.\n */\n sandboxEgress?: SandboxEgressBroker;\n /**\n * Stage 3: the per-job WORKTREE the executor/commit turn works in. The executor's\n * workingDirectory is this worktree (never the shared checkout), so diff/test\n * evidence is captured from it alone, a same-job revision turn reuses it, and the\n * reviewer receives it read-only. Injected so the smoke tests drive a fake and the\n * production runner wires the real RunnerWorktreeManager.\n */\n worktree: WorktreeManager;\n /** Injectable for deterministic timing in tests. */\n sleep: (ms: number) => Promise<void>;\n}\n\n/**\n * W7: the executor's evidence contract is a VERSIONED rubric file\n * (`agents/rubrics/executor-evidence.md`), not an inline literal \u2014 one source,\n * diffable when the contract changes, and loaded fail-closed (a turn without its\n * contract is the silent degradation this program removes).\n */\nexport function harnessExecutorSystemPrompt(): string {\n return loadRubric(\"executor-evidence\");\n}\n\n/**\n * The harness-flow gate: the verification command EVERY executor job runs last,\n * on top of whatever the stage declares.\n *\n * The harness drives itself with the same repo it is changing, so a stage can\n * quietly break the machinery carrying it \u2014 and the symptom shows up rounds\n * later as a wedged stage nobody can attribute (M18 stage 6 burned five review\n * rounds on a cap counter that never reset). This gate runs the suites that\n * prove the flow still converges and never parks silently: sweep-only liveness,\n * decision-table totality, and the review-round/park accounting. Seconds, not\n * minutes \u2014 the full Playwright e2e provisions a database container per run and\n * cannot be a per-turn gate; it stays on the stage's own command list where a\n * stage needs it.\n */\nexport const HARNESS_FLOW_GATE_COMMAND = \"pnpm test:harness-flow\";\n\n/** Thrown when the run is frozen mid-turn \u2014 STOP all further work until resume. */\nexport class HarnessFrozenError extends Error {\n constructor(stageId: string) {\n super(\n `Harness run frozen \u2014 paused stage ${stageId} before any submit/commit/push.`,\n );\n this.name = \"HarnessFrozenError\";\n }\n}\n\n/** Thrown when the job's repo is not in STACKS_RUNNER_REPOS \u2014 the executor path\n * is bounded to configured checkouts, never a tools-only assumption. */\nexport class UnmappedRepoError extends Error {\n constructor(repo: string | null) {\n super(\n repo\n ? `No STACKS_RUNNER_REPOS entry for ${repo} \u2014 cannot execute a harness stage there.`\n : \"Harness stage has no repo configured on its run \u2014 cannot execute.\",\n );\n this.name = \"UnmappedRepoError\";\n }\n}\n\n/**\n * Detect whether an agent job is a harness stage execution job. Returns its\n * harness context (truthy) or null. The single source of truth is the `harness`\n * block on `get_agent_job` \u2014 never the handoff payload (which omits it).\n */\nexport async function getHarnessStageJob(\n deps: Pick<HarnessRunnerDeps, \"callTool\">,\n cfg: Pick<HarnessRunnerConfig, \"tokens\">,\n jobId: string,\n): Promise<AgentJobView> {\n const job = (await deps.callTool(cfg.tokens.runner, \"get_agent_job\", {\n jobId,\n })) as unknown as AgentJobView;\n return job;\n}\n\n/**\n * Parse the executor's trailing `ADDRESSED_FINDINGS:` line into the finding ids\n * it explicitly claims (the last such line wins \u2014 an executor may quote the\n * instruction earlier in its summary). Conservative by design: no line, or\n * \"none\", means NO claims \u2014 an unlisted row stays OPEN for the next round\n * rather than being falsely marked FIXED. (The blanket mark-everything-FIXED\n * this replaces claimed rows even on no-edit rounds, which taught the reviewer\n * to distrust the ledger and reject every round.)\n */\nexport function parseAddressedFindingIds(summary: string): string[] {\n const matches = [...summary.matchAll(/ADDRESSED_FINDINGS:\\s*([^\\n]*)/gi)];\n const line = matches.at(-1)?.[1]?.trim();\n if (!line || /^none\\b/i.test(line)) return [];\n return [\n ...new Set(\n line\n .split(/[,\\s]+/)\n // Strip wrapping punctuation an agent might add (`id`, \"id\", [id], id.)\n .map((s) => s.replace(/^[^A-Za-z0-9_-]+|[^A-Za-z0-9_-]+$/g, \"\"))\n .filter(Boolean),\n ),\n ];\n}\n\n/** Resolve the branch the stage should land on: the stage's pinned branch, else\n * the run branchTemplate with {taskKey}/{slug}/{number} filled.\n *\n * AGE-690: `{taskKey}` comes from `ctx` \u2014 the SAME `get_agent_job` read that\n * carries `branchTemplate` \u2014 and from nowhere else. It used to be a separate\n * parameter threaded from the `agent.handoff` webhook payload, which the POLL\n * leg never supplies; the absent key then became the literal \"task\", so every\n * poll-driven branch silently dropped the anchor key the M8 head-branch matcher\n * resolves the task by, and every PR off one would land ORPHAN. A run with no\n * anchor task has no key at all: it gets an obviously-synthetic, stage-scoped\n * token instead \u2014 unique (never colliding across runs the way \"task\" did) and\n * visibly not a task key, rather than a valid-looking name that fails silently. */\nexport function resolveStageBranch(ctx: HarnessStageJobContext): string {\n if (ctx.branch) return ctx.branch;\n const template = ctx.branchTemplate ?? \"harness/{taskKey}-stage-{number}\";\n return (\n template\n .replaceAll(\n \"{taskKey}\",\n (ctx.taskKey ?? `unanchored-${ctx.stageId}`).toLowerCase(),\n )\n .replaceAll(\"{slug}\", String(ctx.stageId))\n .replaceAll(\"{number}\", String(ctx.stageNumber))\n // A leftover placeholder would make an invalid ref \u2014 strip the braces.\n .replaceAll(/[{}]/g, \"\")\n );\n}\n\n/**\n * A FRESH freeze read, awaited at every external boundary. Both the heartbeat pump\n * (execution turn) and the one-shot probe (commit phase) implement it; the\n * boundaries `await source.check()` right before crossing, so a freeze that lands\n * between a prior poll and the boundary is caught (not a stale latched boolean).\n * `frozen` exposes the last known value for cheap inline guards.\n */\nexport interface FreezeSource {\n /** Last known frozen state (cheap inline guard). */\n readonly frozen: boolean;\n /** Re-read the run's frozen state NOW and return it. */\n check(): Promise<boolean>;\n}\n\n/**\n * A heartbeat pump that ALSO enforces freeze. It heartbeats on `cfg.heartbeatMs`;\n * the instant a heartbeat returns `{ frozen: true }` it ABORTS the controller (so\n * the running subprocess stops) and latches `frozen = true`. Boundaries call\n * `check()` for a FRESH read right before crossing \u2014 Jentrix cannot kill a local\n * process, so the runner is contractually the enforcer.\n */\nexport class HeartbeatPump implements FreezeSource {\n frozen = false;\n private timer: ReturnType<typeof setInterval> | null = null;\n private subprocessDone = false;\n readonly controller = new AbortController();\n\n constructor(\n private readonly deps: Pick<HarnessRunnerDeps, \"callTool\">,\n private readonly cfg: Pick<\n HarnessRunnerConfig,\n \"tokens\" | \"heartbeatMs\" | \"log\"\n >,\n private readonly jobId: string,\n private readonly runId: string,\n ) {}\n\n /** Perform one heartbeat now and react to a frozen response. Exposed so the\n * caller can also check freeze synchronously at a boundary (a \"freeze tick\"). */\n async beat(): Promise<void> {\n let res: Record<string, unknown>;\n try {\n res = await this.deps.callTool(\n this.cfg.tokens.runner,\n \"heartbeat_agent_job\",\n {\n jobId: this.jobId,\n runId: this.runId,\n },\n );\n } catch (e) {\n const msg = String(e);\n if (msg.includes(\"not the job's active run\")) {\n // Superseded turn (the job was failed + relaunched externally): stop the\n // pump and abort the subprocess \u2014 every submit from this turn would be\n // rejected by the server-side turn CAS anyway, so working on is waste.\n // EXCEPT once the subprocess has finished: submit_execution_result\n // completes this run, so the post-submit boundary beats ALWAYS conflict\n // on a successful turn \u2014 that is turn completion, not supersession, and\n // logging/aborting would misread every good turn as a failure.\n if (!this.subprocessDone) {\n this.cfg.log?.(`[heartbeat ${this.jobId}] ${msg}`);\n this.cfg.log?.(\n `[harness ${this.jobId}] turn superseded \u2014 aborting the stage subprocess`,\n );\n this.controller.abort();\n }\n this.stop();\n return;\n }\n // A heartbeat error (e.g. expired run) is logged; the run lifecycle is\n // handled by the caller's claim/fail. Do not crash the pump.\n this.cfg.log?.(`[heartbeat ${this.jobId}] ${msg}`);\n return;\n }\n if (res.frozen === true) {\n if (!this.frozen) {\n this.frozen = true;\n this.cfg.log?.(\n `[harness ${this.jobId}] FROZEN \u2014 aborting the stage subprocess`,\n );\n this.controller.abort();\n }\n }\n }\n\n /** A FRESH freeze read (one heartbeat) for a boundary check. */\n async check(): Promise<boolean> {\n await this.beat();\n return this.frozen;\n }\n\n /** The stage subprocess exited. From here on a heartbeat CONFLICT is the\n * normal end of a submitted turn (see beat()), never a supersession \u2014 there\n * is no subprocess left to abort, and the submits enforce their own turn CAS. */\n markSubprocessDone(): void {\n this.subprocessDone = true;\n }\n\n start(): void {\n if (this.timer) return;\n this.timer = setInterval(() => void this.beat(), this.cfg.heartbeatMs);\n // Don't keep the event loop alive for the heartbeat alone.\n (this.timer as { unref?: () => void }).unref?.();\n }\n\n stop(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n }\n}\n\n/** Capture the working-tree diff + a stat summary as evidence text. Best-effort:\n * a git failure yields an empty summary rather than aborting the report. */\ninterface CapturedChange {\n changedFiles: string[];\n diffLines: number;\n diffSummary: string;\n patch: string;\n /** AGE-901: did the patch read actually SUCCEED? An empty `patch` has two\n * causes that must not be conflated \u2014 a genuinely clean tree (a recordable\n * subject: the diff of \"no change\") and a failed capture (git error, no repo).\n * Only the latter may suppress attestation; treating both as \"no subject\"\n * makes a verification-only stage structurally unable to validate. */\n patchRead: boolean;\n}\n\n/** The shared diff-reading core (D5 dedup): name-only / stat / numstat / patch\n * over one git range. Best-effort per stream \u2014 a git failure yields the empty\n * value for that stream, never a throw. */\nasync function readDiff(\n deps: Pick<HarnessRunnerDeps, \"git\">,\n cwd: string,\n range: string[],\n): Promise<CapturedChange> {\n const capture: CapturedChange = {\n changedFiles: [],\n diffLines: 0,\n diffSummary: \"\",\n patch: \"\",\n patchRead: false,\n };\n try {\n const names = await deps.git(cwd, [\"diff\", \"--name-only\", ...range]);\n capture.changedFiles = names\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter(Boolean);\n } catch {\n /* no diff available */\n }\n try {\n capture.diffSummary = await deps.git(cwd, [\"diff\", \"--stat\", ...range]);\n } catch {\n /* no stat available */\n }\n try {\n // ACTUAL changed-line count = \u03A3(added + deleted) across files, from numstat\n // (NOT the count of --stat lines, which is ~file count) \u2014 so the\n // high_risk_change diff-size policy keys off the real change magnitude.\n const numstat = await deps.git(cwd, [\"diff\", \"--numstat\", ...range]);\n capture.diffLines = numstat\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean)\n .reduce((sum, line) => {\n const [added, deleted] = line.split(/\\s+/);\n // Binary files report \"-\" for both; count those as 0 lines.\n const a = Number(added);\n const d = Number(deleted);\n return (\n sum + (Number.isFinite(a) ? a : 0) + (Number.isFinite(d) ? d : 0)\n );\n }, 0);\n } catch {\n /* no numstat available */\n }\n try {\n capture.patch = await deps.git(cwd, [\"diff\", ...range]);\n capture.patchRead = true;\n } catch {\n /* no patch available \u2014 leaves patchRead false, the honestly-absent case */\n }\n return capture;\n}\n\nexport async function captureDiffEvidence(\n deps: Pick<HarnessRunnerDeps, \"git\">,\n cwd: string,\n): Promise<CapturedChange> {\n let intentToAdd: string[] = [];\n // Plain `git diff HEAD` omits untracked files. Temporarily add only an\n // intent-to-add index entry so Git can render their complete patch and bind\n // test evidence to the real subject. The content is never staged, and the\n // index entries are removed before returning.\n try {\n const untracked = await deps.git(cwd, [\n \"ls-files\",\n \"--others\",\n \"--exclude-standard\",\n \"-z\",\n ]);\n intentToAdd = untracked.split(\"\\0\").filter(Boolean);\n if (intentToAdd.length) {\n await deps.git(cwd, [\"add\", \"--intent-to-add\", \"--\", ...intentToAdd]);\n }\n } catch {\n intentToAdd = [];\n }\n const capture = await readDiff(deps, cwd, [\"HEAD\"]);\n if (intentToAdd.length) {\n try {\n await deps.git(cwd, [\"reset\", \"--quiet\", \"--\", ...intentToAdd]);\n } catch {\n /* evidence remains valid; commit-time git add still owns final staging */\n }\n }\n return capture;\n}\n\n/** W2: what a verification command's own output says actually ran. Mirrored (never\n * imported) across the agents/ dependency firewall \u2014 the server's\n * RunnerAttestationSchema is the other half of this contract. */\nexport interface AttestedTestCounts {\n testsRun: number;\n testsPassed: number;\n testsSkipped: number;\n suites: number;\n}\n\n/** Strip ANSI SGR sequences so a colorized runner (FORCE_COLOR, a TTY) parses the\n * same as a piped one. */\nconst stripAnsi = (s: string): string =>\n // eslint-disable-next-line no-control-regex\n s.replace(new RegExp(`${String.fromCharCode(27)}\\\\[[0-9;]*m`, \"g\"), \"\");\n\n/**\n * W2: parse test counts out of a verification command's captured output.\n *\n * Exit code 0 is not proof that anything RAN \u2014 a suite whose cases were all\n * skipped exits 0 and used to attest as clean evidence (observed: a live-DB\n * file, 14/14 skipped, recorded as the stage's test evidence). The counts\n * existed only in the executor's prose, which the gate rightly ignores.\n *\n * Detection is OUTPUT-driven, not command-driven: the declared commands are\n * gate-approved script names (`pnpm test:harness-flow`) that never say \"vitest\",\n * so recognizing vitest's own summary is both simpler and more general than\n * pattern-matching the command text. Anything unrecognized returns null \u2014 the\n * attestation then says `counts: null` explicitly rather than fabricating zeros.\n *\n * Vitest's summary, whose shape this pins:\n * Test Files 4 passed (4)\n * Tests 1 passed | 2 skipped | 1 todo (4)\n * and, when nothing matched the filter, `No test files found`.\n */\nexport function parseTestCounts(output: string): AttestedTestCounts | null {\n const text = stripAnsi(output);\n // The LAST summary wins (a script may run several suites in sequence).\n const testsLine = [...text.matchAll(/^\\s*Tests\\s{2,}(.+)$/gm)].at(-1)?.[1];\n const filesLine = [...text.matchAll(/^\\s*Test Files\\s{2,}(.+)$/gm)].at(\n -1,\n )?.[1];\n if (!testsLine) {\n // A filter that matched no file is REAL vacuity, not an unparseable command.\n return /^\\s*No test files found/m.test(text)\n ? { testsRun: 0, testsPassed: 0, testsSkipped: 0, suites: 0 }\n : null;\n }\n const total = /\\((\\d+)\\)\\s*$/.exec(testsLine);\n if (!total) return null;\n const count = (line: string, label: string): number => {\n const m = new RegExp(`(\\\\d+)\\\\s+${label}`).exec(line);\n return m ? Number(m[1]) : 0;\n };\n return {\n testsRun: Number(total[1]),\n testsPassed: count(testsLine, \"passed\"),\n // `todo` cases never executed either \u2014 counting them as skipped keeps\n // \"nothing actually ran\" honest.\n testsSkipped: count(testsLine, \"skipped\") + count(testsLine, \"todo\"),\n suites: filesLine ? Number(/\\((\\d+)\\)\\s*$/.exec(filesLine)?.[1] ?? 0) : 0,\n };\n}\n\n/** Bound one captured stream for artifact storage (redaction is server-side on\n * ingest; this only caps the size \u2014 keep the TAIL, where failures print). */\nfunction boundOutput(s: string, max = 60_000): string {\n return s.length <= max\n ? s\n : `\u2026[${s.length - max} chars truncated]\\n${s.slice(-max)}`;\n}\n\nconst sha256 = (s: string): string =>\n createHash(\"sha256\").update(s).digest(\"hex\");\n\n/**\n * Capture the stage's DIFF_OR_PATCH + TEST_EVIDENCE artifacts (the two evidence\n * kinds, beyond the EXECUTION_SUMMARY `submit_harness_stage_result` writes itself)\n * and return their artifactIds so the stage result can LINK them.\n *\n * HAI S3: TEST_EVIDENCE is no longer the executor's prose \u2014 each entry is a\n * RUNNER-executed verification command's captured output, submitted with a\n * runner attestation via the RUNNER token (the token that claimed the attempt;\n * the server verifies that identity and the tier ceiling). The DIFF is captured\n * FIRST via the role token; its returned checksum is the attestation's\n * subjectDigest, binding every piece of test evidence to the exact reviewed\n * diff. `submit_harness_artifact` redacts on ingest and returns null when R2 is\n * unconfigured \u2014 evidence is then simply not linked (the stage stays\n * un-validatable \u2014 honest, not silently validated).\n */\nexport async function captureStageEvidence(\n deps: Pick<HarnessRunnerDeps, \"callTool\">,\n cfg: Pick<HarnessRunnerConfig, \"tokens\" | \"evidenceTier\">,\n ctx: HarnessStageJobContext,\n args: {\n patch: string;\n /** AGE-901: whether the diff READ succeeded (see `CapturedChange.patchRead`).\n * An empty `patch` with `patchRead: true` is a clean tree \u2014 a real subject\n * that must still be recorded, so a verification-only stage can attest its\n * declared commands. Defaults false, which preserves the old fail-closed\n * behavior for any caller that cannot say. */\n patchRead?: boolean;\n verification: VerificationRunResult[];\n /** Identity of the claimed attempt every capture binds to. REQUIRED, not\n * optional: the sole call site runs strictly after `claim_agent_job`\n * returns a runId, so an unattested capture is unreachable \u2014 and making it\n * unrepresentable is the honest shape. The server enforces the same thing\n * from its side (an attested capture whose jobId/runId is not the stage's\n * live attempt is refused, harness-specs/05 \u00A72.4), and AGE-689's dedup keys\n * are DERIVED from this identity, so a nullable attempt would silently take\n * the diff capture back to \"no key \u21D2 no dedup\". */\n attest: {\n jobId: string;\n runId: string;\n baseHead: string;\n cwd: string;\n };\n /** W5: how far this attempt's checkout trails the run's base branch,\n * measured at claim time. Stacking on an unmerged predecessor is correct \u2014\n * this makes the resulting drift a recorded fact instead of a silent one. */\n drift?: { behindBase: number; baseSha: string } | null;\n },\n): Promise<\n Array<{ artifactId: string; kind: \"DIFF_OR_PATCH\" | \"TEST_EVIDENCE\" }>\n> {\n const linked: Array<{\n artifactId: string;\n kind: \"DIFF_OR_PATCH\" | \"TEST_EVIDENCE\";\n }> = [];\n // 1. The diff (role token \u2014 the executor's work product). Its checksum is\n // the subject digest every attestation binds to.\n let subjectDigest: string | null = null;\n // AGE-901: a CLEAN TREE is a subject, not a missing one. A verification-only\n // stage (an exit floor) correctly changes nothing, and gating the artifact on\n // a non-empty patch made every such stage structurally unable to validate \u2014\n // no DIFF_OR_PATCH meant no subjectDigest, which meant not one of its declared\n // commands could attest. Recording \"no change\" explicitly keeps the subject\n // real while leaving the genuinely-unrecorded case (`patchRead` false: git\n // failed, no repo) suppressed exactly as before.\n const noChange = !args.patch.trim() && args.patchRead === true;\n if (args.patch.trim() || noChange) {\n const res = (await deps.callTool(\n cfg.tokens.planner,\n \"submit_harness_artifact\",\n {\n harnessRunId: ctx.harnessRunId,\n harnessStageId: ctx.stageId,\n kind: \"DIFF_OR_PATCH\",\n title: `Stage ${ctx.stageNumber} diff${noChange ? \" (no change)\" : \"\"}`,\n body: noChange\n ? `# No change\\n\\nThe working tree is clean at this attempt's HEAD: the stage's declared work product is zero source changes (a verification-only stage). The diff was read successfully and is empty \u2014 this is the recorded subject, not an absent one.\\n`\n : args.patch,\n // AGE-689: callTool retries transient transport faults, and a retry of\n // a submit that ACTUALLY LANDED creates a second link when no key is\n // given (\"No key \u21D2 no dedup\" \u2014 harness-specs/05 \u00A72). Keyed on attempt\n // identity + kind, so a replay returns the stored response instead.\n idempotencyKey: `${args.attest.jobId}:${args.attest.runId}:DIFF_OR_PATCH`,\n },\n )) as {\n artifact?: { artifactId?: string; checksum?: string } | null;\n };\n if (res.artifact?.artifactId) {\n linked.push({\n artifactId: res.artifact.artifactId,\n kind: \"DIFF_OR_PATCH\",\n });\n subjectDigest = res.artifact.checksum ?? null;\n }\n }\n // 2. One attested TEST_EVIDENCE capture per runner-executed command (RUNNER\n // token \u2014 the claiming identity; the server rejects any other issuer).\n // `subjectDigest` alone gates this: no diff artifact (an UNREAD diff, or R2\n // unconfigured so the capture returned null) means there is nothing to bind\n // an attestation TO, so the evidence is honestly absent and the stage stays\n // un-validatable \u2014 never attested against an unrecorded subject. AGE-901: a\n // read-and-empty diff is recorded above, so it reaches here with a digest.\n if (subjectDigest) {\n for (const v of args.verification) {\n const body =\n `# Verification command (runner-executed)\\n\\n` +\n `$ ${v.command}\\n` +\n `exit ${v.exitCode}${v.timedOut ? \" (TIMED OUT)\" : \"\"} \u2014 started ${v.startedAt}, finished ${v.finishedAt}\\n\\n` +\n `## stdout\\n\\n${boundOutput(v.stdout) || \"(empty)\"}\\n\\n` +\n `## stderr\\n\\n${boundOutput(v.stderr) || \"(empty)\"}\\n`;\n const res = (await deps.callTool(\n cfg.tokens.runner,\n \"submit_harness_artifact\",\n {\n harnessRunId: ctx.harnessRunId,\n harnessStageId: ctx.stageId,\n kind: \"TEST_EVIDENCE\",\n title: `Stage ${ctx.stageNumber} verification: ${v.command.slice(0, 120)}`,\n body,\n criterionRefs: ctx.automatedCriteria ?? [],\n // AGE-689: one evidence link per command per attempt, even when\n // callTool retries a submit that already landed. The command is what\n // makes it unique within an attempt \u2014 the gate matches evidence to\n // each DECLARED command, so that is the right granularity. Hashed\n // (AGE-835): the raw command blew the server's 200-char key limit on\n // long multi-file vitest lines, failing the whole evidence leg.\n idempotencyKey: `${args.attest.jobId}:${args.attest.runId}:TEST_EVIDENCE:${createHash(\"sha256\").update(v.command).digest(\"hex\").slice(0, 32)}`,\n attestation: {\n version: 1,\n issuer: \"runner\",\n jobId: args.attest.jobId,\n runId: args.attest.runId,\n repo: ctx.repo ?? \"(unmapped)\",\n branch: ctx.branch ?? \"(unresolved)\",\n baseHead: args.attest.baseHead,\n subjectDigest,\n command: v.command,\n cwd: args.attest.cwd,\n startedAt: v.startedAt,\n finishedAt: v.finishedAt,\n exitCode: v.exitCode,\n timedOut: v.timedOut,\n stdoutHash: sha256(v.stdout),\n stderrHash: sha256(v.stderr),\n evidenceTier: cfg.evidenceTier ?? DEFAULT_RUNNER_EVIDENCE_TIER,\n // W2: `version` stays 1 (an older control plane must still parse\n // this); the payload revision + counts ride their own keys. Counts\n // come from the SAME bytes stdoutHash covers, so they are bound to\n // attested output rather than to a side file nothing verifies.\n attestationVersion: 2,\n counts: parseTestCounts(`${v.stdout}\\n${v.stderr}`),\n // W5: the attempt's drift from the run's base branch. Recorded on\n // the attestation because it is the only durable, attempt-bound\n // payload the runner authors \u2014 a stage that trails its base by 5\n // commits was reviewed against a tree the deployed server has\n // already moved past, and that used to be invisible.\n ...(args.drift\n ? {\n behindBase: args.drift.behindBase,\n ...(args.drift.baseSha\n ? { baseSha: args.drift.baseSha }\n : {}),\n }\n : {}),\n },\n },\n )) as { artifact?: { artifactId?: string } | null };\n if (res.artifact?.artifactId) {\n linked.push({\n artifactId: res.artifact.artifactId,\n kind: \"TEST_EVIDENCE\",\n });\n }\n }\n }\n return linked;\n}\n\n/**\n * The local commit leg (boundary 1): AUTHORIZE \u2192 `git commit` \u2192 return the SHA.\n * `authorize_harness_local_commit` is a permission check ONLY; it mints no\n * credential. A non-ALLOW decision throws (CONFLICT/FORBIDDEN) and we do NOT\n * commit. The authorization carries the RESOLVED branch + the pre-commit change\n * (paths + line count) so branch-scoped leases and the high_risk_change / diff-size\n * policy evaluate the ACTUAL target BEFORE the local commit (not an empty payload).\n * Freeze is re-checked right before the commit.\n */\nexport async function authorizeAndCommit(\n deps: Pick<HarnessRunnerDeps, \"callTool\" | \"git\" | \"docsGuard\">,\n cfg: Pick<HarnessRunnerConfig, \"tokens\">,\n freeze: FreezeSource,\n ctx: HarnessStageJobContext,\n args: { cwd: string; branch: string; message: string },\n): Promise<{ sha: string | null; changedFiles: string[]; diffLines: number }> {\n if (await freeze.check()) throw new HarnessFrozenError(ctx.stageId);\n // Capture the PENDING change BEFORE committing so the authorization checks the\n // real branch/paths/size (the commit boundary's policy keys off these) AND so the\n // caller can report the committed files (a post-commit diff is empty).\n const pending = await captureDiffEvidence(deps, args.cwd);\n // S1 documentation commit guard: run `docs:check` over the pending change\n // IMMEDIATELY before authorizing. The outcome (+ a stable checksum of the change)\n // is handed to the server, which records a checksum-bound DOCUMENTATION_REVIEW\n // finding and BLOCKS this authorization when a public contract is missing its\n // generated doc entry. The guard only CHECKS here \u2014 it never re-syncs-and-stages\n // behind the reviewer (docs:sync ran before the review turn, in the diff they saw).\n let docsArgs: Record<string, unknown> = {};\n if (deps.docsGuard) {\n const result = await deps.docsGuard.check(args.cwd, pending.changedFiles);\n docsArgs = {\n docsCheckOk: result.ok,\n docsChecksum: createHash(\"sha256\").update(pending.patch).digest(\"hex\"),\n docsStaleSummary: result.staleDocs.length\n ? result.staleDocs.join(\", \")\n : result.ok\n ? undefined\n : result.output.slice(0, 1000) || undefined,\n };\n }\n // Authorization-only: throws if the stage is not VALIDATED/COMMIT_GATE, the run\n // is frozen, a lease blocks, repo:commit policy is not ALLOW, OR the docs guard\n // blocks (stale public contract). Passes the resolved branch + change so the\n // policy/lease check sees the actual target.\n await deps.callTool(cfg.tokens.runner, \"authorize_harness_local_commit\", {\n harnessStageId: ctx.stageId,\n branch: args.branch,\n changedPaths: pending.changedFiles,\n diffLines: pending.diffLines,\n ...docsArgs,\n });\n // FRESH freeze read right before touching git \u2014 a freeze that landed during\n // authorization must stop the commit (the local commit IS a boundary).\n if (await freeze.check()) throw new HarnessFrozenError(ctx.stageId);\n // Stage the work onto the stage branch and commit locally.\n await deps.git(args.cwd, [\"checkout\", \"-B\", args.branch]);\n await deps.git(args.cwd, [\"add\", \"-A\"]);\n if (await freeze.check()) throw new HarnessFrozenError(ctx.stageId);\n // IDEMPOTENT on resume: if a prior attempt already committed (then got frozen\n // before reporting), there is nothing staged now \u2014 DON'T create an empty commit;\n // re-use the existing HEAD so the resume re-reports the SAME commit. The change\n // we report is then taken from HEAD~1..HEAD (the already-committed change).\n const staged = (await deps.git(args.cwd, [\"diff\", \"--cached\", \"--name-only\"]))\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter(Boolean);\n if (staged.length > 0) {\n await deps.git(args.cwd, [\"commit\", \"-m\", args.message]);\n }\n const sha = (await deps.git(args.cwd, [\"rev-parse\", \"HEAD\"])).trim();\n // When we just committed, the pending capture above is the committed change; on a\n // resume (nothing staged) report the last commit's change instead.\n const reported =\n staged.length > 0 ? pending : await captureCommittedChange(deps, args.cwd);\n return {\n sha: sha || null,\n changedFiles: reported.changedFiles,\n diffLines: reported.diffLines,\n };\n}\n\n/** The change in an already-committed range (`baseRef..HEAD`; default the last\n * commit) \u2014 used when the work was committed BEFORE evidence capture: a resume\n * whose prior attempt committed then froze (authorizeAndCommit), or an executor\n * turn that committed locally so the post-turn working tree is clean (AGE-306).\n * Same shape as `captureDiffEvidence`. Best-effort: a git failure yields an\n * empty change. */\nasync function captureCommittedChange(\n deps: Pick<HarnessRunnerDeps, \"git\">,\n cwd: string,\n baseRef = \"HEAD~1\",\n): Promise<CapturedChange> {\n return readDiff(deps, cwd, [baseRef, \"HEAD\"]);\n}\n\n/**\n * The push/PR egress leg (boundaries 2+3) \u2014 performed ONLY after the commit\n * boundary authorizes it. Polls the stage until it is COMMITTED (Jentrix records\n * `pushPrAuthorized` on that transition), then requests SINGLE-USE brokered\n * `repo:push` / `repo:pr_create` credentials and performs the external git write.\n * No standing token: each credential is minted per call and expires. Returns\n * whether the push happened (false = still gated/awaiting a human \u2192 the human\n * drives the gate; the runner does not loop forever).\n */\nexport async function pushAfterAuthorized(\n deps: Pick<HarnessRunnerDeps, \"git\" | \"sleep\" | \"sandboxEgress\">,\n cfg: Pick<HarnessRunnerConfig, \"commitPollMs\" | \"commitPollMax\" | \"log\">,\n freeze: FreezeSource,\n ctx: HarnessStageJobContext,\n args: { cwd: string; branch: string; commitSha: string; repo: string },\n waitForAuthorized: () => Promise<\"authorized\" | \"gated\" | \"blocked\">,\n): Promise<{ pushed: boolean; reason?: string }> {\n // Wait for the commit boundary to authorize push/PR (the stage reaches\n // COMMITTED, recording pushPrAuthorized). A pending COMMIT gate means a human\n // must approve first, and a BLOCKED stage means a human must resolve it \u2014 in\n // both cases we stop rather than spin (the runner never forces a gate).\n const state = await waitForAuthorized();\n if (await freeze.check()) return { pushed: false, reason: \"frozen\" };\n if (state === \"blocked\") {\n return { pushed: false, reason: \"stage blocked \u2014 a human must resolve it\" };\n }\n if (state === \"gated\") {\n return {\n pushed: false,\n reason: \"commit gate pending \u2014 awaiting a human approval before push/PR\",\n };\n }\n\n // M12.5: push + PR go THROUGH the sandbox-side broker, which owns credential\n // injection \u2014 this runner never holds the raw token. D5 (2026-07): the old\n // raw-token leg (brokerPushCredential + createPullRequest seams, always\n // null-wired in production) was DELETED \u2014 without a broker the push defers\n // fail-closed and the governed delivery path (or an operator) performs the\n // externally-visible write.\n if (deps.sandboxEgress) {\n return pushViaSandboxBroker(deps, cfg, freeze, ctx, args);\n }\n return {\n pushed: false,\n reason:\n \"no push egress configured \u2014 the stage stays COMMITTED; the governed delivery path (or an operator) pushes\",\n };\n}\n\n/**\n * M12.5 egress leg via the SANDBOX-SIDE broker (broker-owns-injection path). The\n * runner hands the broker non-secret requests and gets back only results; the raw\n * push/PR credential is confined to the broker's injection helper and destroyed\n * there \u2014 it never enters this process's git argv/env or the returned values.\n * Freeze is re-checked before each broker call; a broker refusal (null) fails closed\n * exactly like the legacy path (defer to the governed path, never push un-brokered).\n */\nasync function pushViaSandboxBroker(\n deps: Pick<HarnessRunnerDeps, \"sandboxEgress\">,\n cfg: Pick<HarnessRunnerConfig, \"log\">,\n freeze: FreezeSource,\n ctx: HarnessStageJobContext,\n args: { cwd: string; branch: string; commitSha: string; repo: string },\n): Promise<{ pushed: boolean; reason?: string }> {\n const log = cfg.log ?? (() => {});\n const broker = deps.sandboxEgress!;\n if (await freeze.check())\n return { pushed: false, reason: \"frozen before push\" };\n const pushed = await broker.push({\n harnessRunId: ctx.harnessRunId,\n stageId: ctx.stageId,\n repo: args.repo,\n branch: args.branch,\n cwd: args.cwd,\n });\n if (!pushed?.pushed) {\n return {\n pushed: false,\n reason: \"sandbox broker push failed closed (frozen/policy)\",\n };\n }\n log(\n `[harness ${ctx.stageId}] pushed ${args.branch} via sandbox broker (${args.commitSha.slice(0, 8)})`,\n );\n // PR uses a SEPARATE brokered credential \u2014 re-check freeze before opening it.\n if (await freeze.check()) {\n return { pushed: true, reason: \"frozen after push, before PR\" };\n }\n const pr = await broker.openPr({\n harnessRunId: ctx.harnessRunId,\n stageId: ctx.stageId,\n repo: args.repo,\n branch: args.branch,\n baseBranch: ctx.baseBranch,\n title: `Harness stage ${ctx.stageNumber}: ${ctx.stageTitle}`,\n });\n log(\n pr\n ? `[harness ${ctx.stageId}] opened PR ${pr.url} via sandbox broker`\n : `[harness ${ctx.stageId}] PR deferred to governed path + inbound correlation`,\n );\n return { pushed: true };\n}\n\n/**\n * AGE-298 (H6b): per-process deadman dedupe \u2014 SPLIT (review P2): the ERROR\n * marker and the anchor-task comment are tracked separately, and a stage only\n * enters the commented set AFTER create_comment succeeds. A transient comment\n * failure (or a temporarily missing taskId) therefore RETRIES on the next\n * budget exhaustion instead of being permanently consumed. A runner restart\n * legitimately re-escalates both.\n */\nconst deadmanMarkedStages = new Set<string>();\nconst deadmanCommentedStages = new Set<string>();\n\n/**\n * Review r3 (P2) \u2014 MIRROR of `src/server/harness/gate-visibility.ts` (the\n * agents package cannot import the app tree; keep the two in sync): a PENDING\n * approval is a VISIBLE human park only when a human can actually act on it \u2014\n * a COMMIT gate by kind (it rides a DONE job), or any other kind only while\n * its job is genuinely parked in a gate phase. A stale PENDING\n * FINAL_ACCEPTANCE row on a DONE job is the exact AGE-293 impossible-state\n * regression: the Control Tower escalates it, so the deadman must too \u2014\n * treating it as \"visibly parked\" would suppress the one alert that exists.\n */\nconst HARNESS_GATE_PHASES = [\n \"PLAN_APPROVAL_GATE\",\n \"FINAL_ACCEPTANCE_GATE\",\n \"MERGE_GATE\",\n \"DEPLOY_GATE\",\n];\n\nfunction isActionablePendingGate(\n kind: string | undefined,\n jobPhase: string | undefined,\n): boolean {\n if (kind === \"COMMIT\") return true;\n return HARNESS_GATE_PHASES.includes(jobPhase ?? \"\");\n}\n\n/** Test seam: forget prior escalations (each smoke case is its own world). */\nexport function resetCommitDeadmanForTests(): void {\n deadmanMarkedStages.clear();\n deadmanCommentedStages.clear();\n}\n\n/**\n * AGE-298 (H6b): the commit poller's deadman. `waitForCommitAuthorized` used\n * to exhaust its budget and report the catch-all \"gated\" forever \u2014 during\n * AGE-291 the runner spun on \"not committable (stage EXECUTING)\" for 18 hours\n * while nothing was actually gated. On budget exhaustion this probes DURABLE\n * state: if the pairing is impossible \u2014 the job is DONE, the stage never\n * reached COMMITTED/SKIPPED/BLOCKED, and no ACTIONABLE approval is pending\n * (per the mirrored gate-visibility predicate above) \u2014 it emits a\n * distinct ERROR-level marker line (monitor-alertable) and, holding a\n * write-scoped PAT, posts a comment on the run's anchor task so a human sees\n * the stuck stage where they already look. Once per stage per process;\n * best-effort by contract (a probe/comment failure never breaks the poller).\n */\nasync function commitDeadmanProbe(\n deps: Pick<HarnessRunnerDeps, \"callTool\">,\n cfg: Pick<HarnessRunnerConfig, \"tokens\" | \"log\">,\n ctx: HarnessStageJobContext,\n jobId: string,\n stageStatusNow: string | null,\n): Promise<void> {\n const log = cfg.log ?? (() => {});\n if (\n deadmanMarkedStages.has(ctx.stageId) &&\n deadmanCommentedStages.has(ctx.stageId)\n ) {\n return; // fully escalated this process \u2014 nothing left to do\n }\n try {\n if (\n !stageStatusNow ||\n [\"COMMITTED\", \"SKIPPED\", \"BLOCKED\"].includes(stageStatusNow)\n ) {\n return; // terminal or human-parked \u2014 the plain \"gated\"/\"blocked\" story\n }\n const job = (await deps.callTool(cfg.tokens.runner, \"get_agent_job\", {\n jobId,\n })) as {\n phase?: string;\n taskId?: string;\n approvals?: Array<{ status?: string; kind?: string }>;\n };\n // Only an ACTIONABLE pending gate counts as visibly parked (the shared\n // gate-visibility predicate) \u2014 a stale FINAL_ACCEPTANCE approval left\n // PENDING on a DONE job suppresses nothing.\n const pendingGate = (job.approvals ?? []).some(\n (a) =>\n a.status === \"PENDING\" && isActionablePendingGate(a.kind, job.phase),\n );\n if (job.phase !== \"DONE\" || pendingGate) return; // visibly parked \u2014 fine\n if (!deadmanMarkedStages.has(ctx.stageId)) {\n deadmanMarkedStages.add(ctx.stageId);\n // The distinct, greppable, monitor-alertable marker (ERROR level).\n log(\n `[harness-deadman] ERROR: impossible state \u2014 stage ${ctx.stageId} ` +\n `(run ${ctx.harnessRunId}, stage ${ctx.stageNumber}) is ${stageStatusNow} ` +\n `while job ${jobId} is DONE with no actionable pending gate; the commit ` +\n `poller budget is exhausted and nothing external will fire (AGE-291 class). ` +\n `The server sweep should converge it \u2014 escalating on the anchor task.`,\n );\n }\n // The comment dedupes SEPARATELY and only after SUCCESS (review P2): a\n // transient failure or missing taskId retries on the next exhaustion.\n if (!deadmanCommentedStages.has(ctx.stageId) && job.taskId) {\n await deps.callTool(cfg.tokens.planner, \"create_comment\", {\n taskId: job.taskId,\n body:\n `\uD83D\uDEA8 Harness commit-poller deadman: stage ${ctx.stageNumber} ` +\n `(\\`${ctx.stageId}\\`, run \\`${ctx.harnessRunId}\\`) is stuck ` +\n `${stageStatusNow} while its execution job \\`${jobId}\\` is DONE ` +\n `with no actionable pending gate \u2014 the AGE-291 impossible-state ` +\n `class. The runner's poll budget is exhausted; the cron sweep should ` +\n `converge it (STUCK_HARNESSES has the item), else retry the stage.`,\n });\n deadmanCommentedStages.add(ctx.stageId);\n }\n } catch (e) {\n // Best-effort: never break the poller over its own escalation.\n log(`[harness-deadman] escalation failed for stage ${ctx.stageId}: ${e}`);\n }\n}\n\n/**\n * Poll `list_harness_stages` until the stage is COMMITTED (push/PR authorized),\n * BLOCKED/SKIPPED (human must resolve), or the poll budget is exhausted (treated\n * as still-gated \u2014 a human drives the gate; the AGE-298 deadman first probes for\n * the impossible pairing and escalates it once per stage per process). Separated\n * from the push so the smoke test can drive the wait deterministically.\n */\nexport async function waitForCommitAuthorized(\n deps: Pick<HarnessRunnerDeps, \"callTool\" | \"sleep\">,\n cfg: Pick<\n HarnessRunnerConfig,\n \"tokens\" | \"commitPollMs\" | \"commitPollMax\" | \"log\"\n >,\n freeze: FreezeSource,\n ctx: HarnessStageJobContext,\n opts: { jobId?: string } = {},\n): Promise<\"authorized\" | \"gated\" | \"blocked\"> {\n for (let i = 0; i < cfg.commitPollMax; i++) {\n // A FRESH freeze read each poll \u2014 a freeze mid-wait stops us before push.\n if (await freeze.check()) return \"gated\";\n // Paginated lookup (handles a 50+-stage harness).\n const status = await stageStatus(deps, cfg, ctx);\n if (status === \"COMMITTED\") return \"authorized\";\n if (status === \"BLOCKED\" || status === \"SKIPPED\") return \"blocked\";\n await deps.sleep(cfg.commitPollMs);\n }\n // Budget exhausted. Re-read freeze AND stage status FRESH (review P2): the\n // stage may have committed/blocked \u2014 or the run frozen \u2014 during the final\n // sleep, and a stale snapshot must neither false-alarm the deadman nor\n // mis-report the disposition.\n if (await freeze.check()) return \"gated\";\n const finalStatus = await stageStatus(deps, cfg, ctx);\n if (finalStatus === \"COMMITTED\") return \"authorized\";\n if (finalStatus === \"BLOCKED\" || finalStatus === \"SKIPPED\") return \"blocked\";\n if (opts.jobId) {\n await commitDeadmanProbe(deps, cfg, ctx, opts.jobId, finalStatus);\n }\n return \"gated\";\n}\n\n/**\n * Drive ONE harness stage EXECUTION turn end to end. This is the EXECUTING-phase\n * handoff: it does NOT commit. A harness stage rides the M7 loop, so the commit is\n * a SEPARATE, post-validation boundary (`authorize_harness_local_commit` rejects\n * anything not already VALIDATED/COMMIT_GATE) \u2014 `driveHarnessCommit` handles that\n * once the stage is validated. The execution turn:\n * 1. executes in the checkout (freeze aborts the subprocess),\n * 2. captures the diff + test evidence and links them via submit_harness_artifact,\n * 3. records submit_harness_stage_result (evidence linked; NO commit yet \u2014 the\n * stage isn't validated), and\n * 4. satisfies the generic M7 submit_execution_result so the loop advances to\n * the reviewer turn.\n * It then OPPORTUNISTICALLY runs the commit boundary if the stage is ALREADY\n * VALIDATED/COMMIT_GATE (e.g. an auto-approved gate under an ALLOW policy); when a\n * human gate is still pending it returns \"awaiting validation\" and the commit runs\n * on a later invocation.\n *\n * Returns a terminal disposition for the runner's log. Throws nothing for the\n * common gated/frozen cases \u2014 those are reported, not failed (a real provider\n * error still propagates so the caller can `fail_agent_job`).\n */\nexport async function driveHarnessStage(\n deps: HarnessRunnerDeps,\n cfg: HarnessRunnerConfig,\n input: { jobId: string },\n): Promise<{ disposition: string }> {\n const log = cfg.log ?? (() => {});\n const job = await getHarnessStageJob(deps, cfg, input.jobId);\n const ctx = job.harness;\n if (!ctx) {\n // Not a harness stage job \u2014 the caller should have routed this to the generic\n // path. Defensive: report rather than act.\n return { disposition: \"not_a_harness_stage_job\" };\n }\n\n // BOUND the executor path to a configured checkout BEFORE claiming/working \u2014 a\n // tools-only reference-agent assumption must never leak into the executor path.\n // The actual working directory is a per-job WORKTREE resolved AFTER the claim\n // (inside the try below), so the ownership check runs as the newest attempt.\n const repo = ctx.repo;\n if (!repo || !cfg.repos[repo]) {\n throw new UnmappedRepoError(repo);\n }\n\n await deps.preflightVerification?.();\n\n // Claim the turn with the ADMIN token \u2192 runId. The presentation (pinned\n // model + build-stamped revision + capabilities) rides claimPresentation \u2014\n // the control plane refuses a schema-incompatible worker (and an unattested\n // validator lane) BEFORE any model turn burns (M12.3b/M13.4b; un-stamped dev\n // leaves the compatibility guard inert).\n const configured = cfg.executorBinding;\n if (cfg.stopping?.()) return { disposition: \"shutdown_requested\" };\n const provider = configured?.runtimeAdapterKey ?? agentProvider();\n const model =\n configured?.model ??\n (provider === \"claude\" ? claudeLegModel(\"executor\") : codexModel());\n const workerClaimToken = configured\n ? await cfg.mintClaimCredential?.(configured)\n : undefined;\n if (cfg.stopping?.()) return { disposition: \"shutdown_requested\" };\n const claim = await deps.callTool(cfg.tokens.runner, \"claim_agent_job\", {\n jobId: input.jobId,\n ...claimPresentation(provider, {\n revision: cfg.revision,\n capabilities: cfg.capabilities,\n model,\n }),\n ...(configured ? { provider: configured.provider } : {}),\n ...(workerClaimToken ? { workerClaimToken } : {}),\n });\n const runId = String(claim.runId);\n let execution: ResolvedClaimExecution | undefined;\n try {\n execution = configured\n ? resolveClaimExecution(claim, configured)\n : undefined;\n } catch (error) {\n await deps\n .callTool(cfg.tokens.runner, \"fail_agent_job\", {\n jobId: input.jobId,\n runId,\n error: error instanceof Error ? error.message : \"role route refused\",\n })\n .catch(() => {});\n throw error;\n }\n // M18.3 R7 \u2014 THE CHECKOUT DECISION, made from the DURABLE run role the control\n // plane just returned, not from the leg's shape. `claim_agent_job` answers with\n // the role it opened the run as; `repoAccessForRole` is total and fail-closed,\n // so EXECUTOR gets the writable worktree it always got and every other role \u2014\n // VALIDATOR, or anything this runner does not recognize \u2014 gets an adopt-only,\n // read-only tree. Resolved ONCE here and consumed at both sites below (the\n // worktree call and the model session), so there is no second place where a\n // writable checkout could be conjured up.\n const repoAccess = repoAccessForRole(\n typeof claim.role === \"string\" ? claim.role : null,\n );\n\n const pump = new HeartbeatPump(deps, cfg, input.jobId, runId);\n pump.start();\n try {\n // 0. The stage's OPEN review-findings ledger is required executor scope:\n // without feeding it into the turn (and claiming FIXED on submit, below)\n // the rows stay OPEN forever and a findings-aware reviewer rejects every\n // round regardless of evidence quality. Fixer claims, reviewer verifies.\n const openFindings: Array<{\n id?: unknown;\n title?: unknown;\n body?: unknown;\n suggestedFix?: unknown;\n resolutionNote?: unknown;\n reopenCount?: unknown;\n }> = await deps\n .callTool(cfg.tokens.planner, \"list_harness_findings\", {\n harnessRunId: ctx.harnessRunId,\n harnessStageId: ctx.stageId,\n status: \"OPEN\",\n // Concise omits body/resolution fields \u2014 exactly the information an\n // executor needs to avoid repeating a rejected evidence substitution.\n response_format: \"detailed\",\n })\n .then((r) => (Array.isArray(r.findings) ? r.findings : []))\n .catch(() => []);\n const findingsBlock = openFindings.length\n ? `\\nOpen review findings on this stage \u2014 these are the reviewer's FULL objections, not optional hints. Address EVERY requirement in the body and suggested fix with production-path code plus completed evidence. Do not substitute an in-memory model, a comment, or a future adapter seam for the requested trust/effect boundary:\\n\\n${openFindings\n .map((f, index) => {\n // W3: a REOPENED row is the loop oscillating on one finding \u2014 the\n // second reopen parks the stage for human adjudication, so the\n // executor must know it is on its last pass at this objection\n // rather than treating the row as freshly raised.\n const reopens =\n typeof f.reopenCount === \"number\" && f.reopenCount > 0\n ? ` \u2014 REOPENED ${f.reopenCount}\u00D7 (a prior fix for this exact finding was rejected; two reopens park the stage for human adjudication, so do not repeat a rejected approach)`\n : \"\";\n const sections = [\n `Finding ${index + 1} [${String(f.id)}]${reopens}: ${String(f.title)}`,\n typeof f.body === \"string\" && f.body.trim()\n ? `Reviewer rationale:\\n${f.body.trim()}`\n : null,\n typeof f.suggestedFix === \"string\" && f.suggestedFix.trim()\n ? `Required fix/evidence:\\n${f.suggestedFix.trim()}`\n : null,\n typeof f.resolutionNote === \"string\" && f.resolutionNote.trim()\n ? `Prior attempted resolution (verify it; do not repeat it if rejected):\\n${f.resolutionNote.trim()}`\n : null,\n ].filter((part): part is string => part !== null);\n return sections.join(\"\\n\");\n })\n .join(\n \"\\n\\n---\\n\\n\",\n )}\\n\\nEnd your summary with the line \"ADDRESSED_FINDINGS: <comma-separated ids>\" naming ONLY the findings you actually completed (or \"ADDRESSED_FINDINGS: none\") \u2014 only those are claimed FIXED for the reviewer to verify; the rest stay OPEN.\\n`\n : \"\";\n\n // 1. EXECUTE in the per-job WORKTREE (role token; turn-guard passes). The\n // signal is aborted if a heartbeat reports the run frozen mid-turn.\n const branch = resolveStageBranch(ctx);\n // Resolve the executor's workingDirectory: the job's own native-Git worktree\n // (created from executionBaseRef or the reused stage-branch tip; adopted on a\n // restart; ownership-checked before reusing a shared stage branch). Diff/test\n // evidence below is captured from THIS worktree only. A resolution failure\n // (ownership conflict / unprovable / missing ref) throws \u2192 fail_agent_job parks\n // the stage for a human with the actionable diagnostic.\n //\n // M18.3 R7: which of the two worktree primitives runs is decided by\n // `repoAccess.provisionWorktree`, i.e. by the durable run role. The\n // read-only lane calls `adoptExecutionCwd` \u2014 which creates nothing,\n // bootstraps nothing and copies nothing \u2014 and PARKS when there is no tree to\n // adopt. It must never degrade to `ensureExecutionCwd` (that IS the writable\n // lane) nor to the shared grounding checkout (which lacks the stage's\n // uncommitted change, so any verdict would describe the wrong tree) \u2014 the\n // same fail-closed rule the harness reviewer leg already follows.\n const identity = {\n repo,\n jobId: input.jobId,\n stageId: ctx.stageId,\n branch,\n };\n let cwd: string;\n if (repoAccess.provisionWorktree) {\n cwd = await deps.worktree.ensureExecutionCwd(\n identity,\n ctx.executionBaseRef,\n );\n } else {\n const adopted = await deps.worktree.adoptExecutionCwd(identity);\n if (!adopted) {\n const reason = missingReadOnlyCheckoutReason({\n role: typeof claim.role === \"string\" ? claim.role : null,\n stageId: ctx.stageId,\n });\n log(`[harness ${ctx.stageId}] ${reason}`);\n await deps\n .callTool(cfg.tokens.runner, \"fail_agent_job\", {\n jobId: input.jobId,\n runId,\n error: reason,\n })\n .catch(() => {});\n return { disposition: \"read_only_checkout_unavailable\" };\n }\n cwd = adopted;\n }\n // Snapshot HEAD before the turn: a local-commit stage's executor commits its\n // own work, leaving a clean tree \u2014 evidence then comes from the\n // preTurnHead..HEAD range (step 2), not the (empty) working-tree diff.\n const preTurnHead = await deps\n .git(cwd, [\"rev-parse\", \"HEAD\"])\n .then((s) => s.trim())\n .catch(() => null);\n // The repo's own conventions + the base-branch commits this worktree does\n // NOT have (parallel work on the same repo \u2014 the M18 shape). Fail-soft.\n const projectContext = await buildProjectContext(\n { git: (dir, args) => deps.git(dir, args) },\n { cwd, baseBranch: ctx.baseBranch, role: \"executor\" },\n ).catch(() => \"\");\n // W5: measure the drift ONCE, before the turn, so the number the executor is\n // told and the number the attestation records are the same fact.\n const drift = await measureBaseDrift(\n { git: (dir, args) => deps.git(dir, args) },\n { cwd, baseBranch: ctx.baseBranch },\n ).catch(() => null);\n if (drift && drift.behindBase > 0) {\n log(\n `[harness ${ctx.stageId}] behind base by ${drift.behindBase} commit(s) (${ctx.baseBranch ?? \"main\"} @ ${drift.baseSha.slice(0, 12)}) \u2014 stacked work reviewed against an older tree`,\n );\n }\n // A read-only attempt is told the truth about its tree. The RUNNER executes\n // the declared verification commands either way (step 2b below) and attests\n // the result \u2014 that is the only channel a validator's TEST_EVIDENCE can\n // arrive through, so the turn's job is to read and report, not to implement.\n // AGE-781: the decomposition-reviewed implementation approach \u2014 the\n // executor's brief. Stages open at EXECUTING with no per-stage plan turn,\n // so this reviewed sketch is the only \"how\" beyond the criteria. Advisory\n // by design: the criteria stay the literal contract, and an executor that\n // finds the approach wrong in the checkout follows the code, not the sketch.\n const approachBlock = ctx.approach\n ? `Reviewed implementation approach (the decomposition's brief \u2014 follow it unless the checkout proves it wrong, and say so in the summary if it is):\\n${ctx.approach}\\n`\n : \"\";\n const taskPrompt = repoAccess.repoReadOnly\n ? `Verify Harness stage ${ctx.stageNumber} (\"${ctx.stageTitle}\") against the READ-ONLY checkout at ${cwd} on branch ${branch}. ` +\n `You may read the tree and report findings; you cannot modify it, and you must not try. ` +\n `The RUNNER \u2014 not you \u2014 executes this stage's declared verification commands and attests the result as TEST_EVIDENCE. ` +\n `Acceptance criteria (literal contract; judge each clause against production-path evidence):\\n- ${ctx.acceptanceCriteria.join(\"\\n- \")}\\n` +\n approachBlock +\n findingsBlock +\n `Report what verification found.`\n : `Implement Harness stage ${ctx.stageNumber} (\"${ctx.stageTitle}\") in ${cwd} on branch ${branch}. ` +\n `Acceptance criteria (literal contract; satisfy each clause with production-path evidence):\\n- ${ctx.acceptanceCriteria.join(\"\\n- \")}\\n` +\n approachBlock +\n findingsBlock +\n `Run the relevant tests and report what you changed.`;\n const summary = await deps.runAgentTurn({\n prompt: taskPrompt + projectContext,\n // W7: the executor rubric is a versioned file injected once, so the system\n // prompt is a function call here rather than the old module constant.\n systemPrompt: harnessExecutorSystemPrompt(),\n repoCwd: cwd,\n // M18.3 R7: map-derived, never a hand-written literal. False for EXECUTOR\n // (today's behavior, unchanged); true for a validator or any unrecognized\n // role, which the providers enforce by withholding the write/edit tools\n // (claude) and running the shell read-only (codex).\n repoReadOnly: repoAccess.repoReadOnly,\n signal: pump.controller.signal,\n // W3: the runner \u2014 not this turn \u2014 submits the stage result and attests\n // the evidence, so the runtime denies a submission attempted over an\n // uncommitted tree and nudges a turn ending with verification still\n // running in the background.\n runnerOwnsSubmissions: true,\n execution,\n });\n pump.markSubprocessDone();\n log(`[harness ${ctx.stageId}] executor: ${summary}`);\n\n // 1b. S1 documentation commit guard \u2014 regenerate the checked-in generated docs\n // BEFORE the reviewer turn, so a public-contract change (e.g. a new MCP tool)\n // lands its generated doc entry in the SAME diff the reviewer and the evidence\n // capture below see. This never silently stages behind the reviewer: the\n // regenerated files show up in the diff evidence, and the authoritative gate\n // is docs:check at the commit boundary, which blocks if the tree is still stale.\n if (deps.docsGuard) {\n try {\n const preDocs = await captureDiffEvidence(deps, cwd);\n await deps.docsGuard.sync(cwd, preDocs.changedFiles);\n } catch (err) {\n log(\n `[harness ${ctx.stageId}] docs:sync failed (non-blocking; commit-time docs:check still gates): ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n }\n\n // 2. Capture the diff + test evidence and link them (the validation gate needs\n // DIFF_OR_PATCH + TEST_EVIDENCE; submit_harness_stage_result writes the\n // EXECUTION_SUMMARY itself). The executor's summary carries its test results.\n // A FRESH freeze read BEFORE the evidence submits \u2014 \"no submit while frozen\"\n // covers the artifact captures too (the capture is an MCP mutation).\n if (await pump.check()) throw new HarnessFrozenError(ctx.stageId);\n let evidence = await captureDiffEvidence(deps, cwd);\n // AGE-306: an executor that committed during its turn (local-commit stages)\n // leaves a clean tree \u2014 the working-tree diff is empty, and skipping the\n // DIFF_OR_PATCH artifact wedges FINAL_ACCEPTANCE on \"missing evidence\".\n // When HEAD moved across the turn, the committed range IS the turn's change;\n // an unmoved HEAD stays empty (never fabricate evidence from prior commits).\n if (!evidence.patch.trim() && preTurnHead) {\n const postTurnHead = await deps\n .git(cwd, [\"rev-parse\", \"HEAD\"])\n .then((s) => s.trim())\n .catch(() => null);\n if (postTurnHead && postTurnHead !== preTurnHead) {\n const committed = await captureCommittedChange(deps, cwd, preTurnHead);\n if (committed.patch.trim()) evidence = committed;\n }\n }\n // 2b. HAI S3: the RUNNER executes the stage's declared verification\n // commands itself \u2014 foreground, per-command timeout, in the worktree.\n // The executor's prose NEVER becomes TEST_EVIDENCE; only these observed\n // results do, each submitted with a runner attestation bound to the\n // diff checksum. Missing runCommand dep or declared-but-unrun commands\n // leave the evidence honestly absent (the gate blocks, never fakes).\n // The stage's own commands PLUS the mandatory harness-flow gate, always\n // last. It rides the existing verification path deliberately: the runner\n // executes it in the foreground, its real exit code becomes attested\n // TEST_EVIDENCE, and a red gate lands in `risks` + `testsNotRun` where the\n // validation gate and the reviewer both see it. A stage that already\n // declares it is not run twice.\n const declaredCommands = [\n ...(ctx.verificationCommands ?? []).filter(\n (c) => c.trim() !== HARNESS_FLOW_GATE_COMMAND,\n ),\n HARNESS_FLOW_GATE_COMMAND,\n ];\n const verification: VerificationRunResult[] = [];\n for (const command of declaredCommands) {\n if (!deps.runCommand) break;\n if (await pump.check()) throw new HarnessFrozenError(ctx.stageId);\n log(`[harness ${ctx.stageId}] verify: ${command}`);\n verification.push(\n await deps.runCommand({\n cwd,\n command,\n timeoutMs: cfg.verificationTimeoutMs ?? 900_000,\n signal: pump.controller.signal,\n }),\n );\n }\n const evidenceArtifacts = await captureStageEvidence(deps, cfg, ctx, {\n patch: evidence.patch,\n patchRead: evidence.patchRead,\n verification,\n attest: {\n jobId: input.jobId,\n runId,\n baseHead: preTurnHead ?? \"(unknown)\",\n cwd,\n },\n drift,\n });\n\n // 3. Record the structured stage result \u2014 evidence linked, NO commit (the stage\n // is not validated yet; reporting a commit now would be rejected by the\n // boundary anyway). The commit + its SHA report happen in driveHarnessCommit\n // AFTER validation. FRESH freeze read right before the submit. HAI S3:\n // the structured report is populated HONESTLY from the observed runs \u2014\n // commandsRun = executed, testsRun = passed, testsNotRun = declared but\n // not executed or failed, risks = the failures.\n if (await pump.check()) throw new HarnessFrozenError(ctx.stageId);\n const executed = new Set(verification.map((v) => v.command));\n const passed = verification.filter((v) => v.exitCode === 0 && !v.timedOut);\n const failed = verification.filter((v) => v.exitCode !== 0 || v.timedOut);\n await submitStageResultResilient(\n deps,\n cfg,\n {\n harnessRunId: ctx.harnessRunId,\n stageId: ctx.stageId,\n changedFiles: evidence.changedFiles,\n commandsRun: verification.map((v) => v.command),\n testsRun: passed.map((v) => v.command),\n testsNotRun: [\n ...declaredCommands.filter((c) => !executed.has(c)),\n ...failed.map((v) => v.command),\n ],\n risks: failed.map(\n (v) =>\n `verification failed: ${v.command} (${v.timedOut ? \"timed out\" : `exit ${v.exitCode}`})`,\n ),\n diffLines: evidence.diffLines,\n branch,\n evidenceArtifacts,\n // AGE-297: every stage-result submission is attempt-bound (required) \u2014\n // a superseded attempt's late submit is refused server-side.\n jobId: input.jobId,\n },\n // Stable per-attempt key: a post-504 retry replays the landed write.\n `stage-result:${runId}`,\n );\n\n // 3b. Claim FIXED ONLY on the ledger rows the executor explicitly reported\n // completing (its ADDRESSED_FINDINGS line) \u2014 BEFORE the reviewer turn\n // opens, so it reads a consistent ledger. NEVER a blanket claim: a\n // round that fixed 2 of 6 rows (or made no edits at all) used to mark\n // all 6 FIXED, which taught the reviewer to distrust every claim and\n // reject every round. Unlisted rows stay OPEN \u2014 honest, and the\n // reviewer's own OPEN\u2192FIXED\u2192VERIFIED path still covers a row the\n // executor fixed but forgot to list. The reviewer VERIFIES or REOPENS\n // each claim (update_harness_finding enforces legal transitions; an\n // already-resolved row is a tolerated failure, not a stop).\n const openIds = new Set(openFindings.map((f) => String(f.id)));\n const addressedIds = parseAddressedFindingIds(summary).filter((id) =>\n openIds.has(id),\n );\n for (const findingId of addressedIds) {\n await deps\n .callTool(cfg.tokens.planner, \"update_harness_finding\", {\n findingId,\n status: \"FIXED\",\n resolutionNote: `Addressed in stage ${ctx.stageNumber} execution (run ${runId}) \u2014 see the execution summary and evidence artifacts.`,\n })\n .catch(() => {});\n }\n\n // 4. Satisfy the generic M7 execution submission so the state machine advances\n // EXECUTING \u2192 EXECUTION_REVIEW and the reviewer turn opens. FRESH freeze read.\n if (await pump.check()) throw new HarnessFrozenError(ctx.stageId);\n try {\n await deps.callTool(cfg.tokens.planner, \"submit_execution_result\", {\n jobId: input.jobId,\n runId,\n executionSummary: summary,\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (!message.includes(\"It is not this agent's turn\")) throw error;\n\n // The tools-capable executor can occasionally submit the generic result\n // despite the runner-only instruction. Converge only when a fresh read of\n // this exact job proves that transition already landed; any other conflict\n // remains a real failure.\n const fresh = (await deps.callTool(cfg.tokens.runner, \"get_agent_job\", {\n jobId: input.jobId,\n })) as unknown as AgentJobView;\n if (\n fresh.id !== input.jobId ||\n fresh.phase !== \"EXECUTION_REVIEW\" ||\n fresh.harness?.stageId !== ctx.stageId\n ) {\n throw error;\n }\n log(\n `[harness ${ctx.stageId}] execution result already submitted; continuing from EXECUTION_REVIEW`,\n );\n }\n\n // 5. OPPORTUNISTIC commit: if the stage is ALREADY VALIDATED/COMMIT_GATE (an\n // auto-approved gate under an ALLOW policy), run the commit boundary now.\n // Otherwise the human gate is still pending \u2014 defer; the commit runs on a\n // later invocation of driveHarnessCommit.\n if (await pump.check()) throw new HarnessFrozenError(ctx.stageId);\n const status = await stageStatus(deps, cfg, ctx);\n if (status === \"VALIDATED\" || status === \"COMMIT_GATE\") {\n const commit = await driveHarnessCommit(deps, cfg, pump, ctx, {\n cwd,\n branch,\n jobId: input.jobId,\n });\n return { disposition: `executed; ${commit.disposition}` };\n }\n return {\n disposition: `executed; awaiting validation (stage ${status ?? \"?\"})`,\n };\n } catch (err) {\n if (err instanceof HarnessFrozenError) {\n // Deliberately NOT checkpointed: a local commit is a freeze boundary, and\n // the worktree is retained + re-adopted by this same job on resume, so a\n // freeze never strands work.\n log(err.message);\n return { disposition: \"frozen\" };\n }\n // W1: this turn is about to PARK the job for a human. Commit whatever it left\n // in the worktree onto the stage branch FIRST \u2014 the retry gets a fresh\n // worktree from the branch tip, so anything uncommitted here dies invisibly.\n await checkpointParkedWorktree(deps, cfg, ctx, {\n jobId: input.jobId,\n branch: resolveStageBranch(ctx),\n reason: `failed turn: ${err instanceof Error ? err.message : \"harness runner error\"}`,\n });\n // A real provider/git/MCP error AFTER the claim must FAIL the run (admin token)\n // so the job BLOCKS for a human promptly, rather than sitting active until the\n // heartbeat lapses \u2014 same contract as the generic M7 drive() path.\n await deps\n .callTool(cfg.tokens.runner, \"fail_agent_job\", {\n jobId: input.jobId,\n runId,\n error: err instanceof Error ? err.message : \"harness runner error\",\n })\n .catch((e) =>\n log(`[harness ${input.jobId}] fail_agent_job failed: ${e}`),\n );\n throw err;\n } finally {\n pump.stop();\n }\n}\n\n/**\n * W1: make a park LOSSLESS. A parking attempt never reaches its commit gate, and\n * the next attempt gets a fresh worktree checked out at the stage branch's tip \u2014\n * so any uncommitted work left here is invisible to the reviewer, the gates, and\n * the operator (the M18 run needed ten manual \"operator checkpoint\" commits;\n * attempt #7 alone left 2,881 lines behind). Committing it onto the branch makes\n * it part of the diff the next round reviews.\n *\n * Best-effort by contract: a checkpoint failure is LOGGED with the worktree path\n * (the work is still on disk, and `pnpm harness-worktrees` reports it) and never\n * masks the park itself \u2014 the human needs the original reason.\n */\nasync function checkpointParkedWorktree(\n deps: Pick<HarnessRunnerDeps, \"worktree\">,\n cfg: Pick<HarnessRunnerConfig, \"log\">,\n ctx: HarnessStageJobContext,\n args: { jobId: string; branch: string; reason: string },\n): Promise<void> {\n const log = cfg.log ?? (() => {});\n if (!ctx.repo) return;\n try {\n const res = await deps.worktree.checkpointExecutionCwd(\n {\n repo: ctx.repo,\n jobId: args.jobId,\n stageId: ctx.stageId,\n branch: args.branch,\n },\n `harness checkpoint: stage ${ctx.stageNumber} job ${args.jobId} (${args.reason})`,\n );\n if (res.committed) {\n log(\n `[harness ${ctx.stageId}] park checkpoint: committed ${res.files?.length ?? 0} path(s) to ${args.branch} (${res.sha?.slice(0, 12)}) \u2014 the next attempt inherits this work`,\n );\n }\n } catch (e) {\n log(\n `[harness ${ctx.stageId}] park checkpoint FAILED \u2014 uncommitted work may be stranded in this attempt's worktree: ${\n e instanceof Error ? e.message : String(e)\n }`,\n );\n }\n}\n\n/** The stage's current status via list_harness_stages, PAGINATING until the stage\n * is found (the server caps each page at 50; a harness with 50+ stages would\n * otherwise read a late stage as \"not found\"). Returns null only when the stage is\n * absent from every page. */\n/**\n * F3 (AGE-500): submit the stage result with a STABLE idempotency key and one\n * delayed final replay. A gateway 504 whose write actually landed stores the\n * response under the key server-side, so the replay returns it instead of\n * failing a green turn \u2014 the old path called fail_agent_job after a landed\n * submit, and the re-claim then stormed \"not the job's active run\" CONFLICTs.\n * App-level tool errors (the isError envelope) stay deterministic failures.\n */\nasync function submitStageResultResilient(\n deps: Pick<HarnessRunnerDeps, \"callTool\" | \"sleep\">,\n cfg: Pick<HarnessRunnerConfig, \"tokens\">,\n args: Record<string, unknown>,\n idempotencyKey: string,\n): Promise<void> {\n const payload = { ...args, idempotencyKey };\n try {\n await deps.callTool(\n cfg.tokens.planner,\n \"submit_harness_stage_result\",\n payload,\n );\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n // A structured tool error is deterministic \u2014 replaying cannot change it.\n if (msg.startsWith(\"submit_harness_stage_result failed:\")) throw err;\n // Transport-level failure that survived callTool's own retries: ONE more\n // replay after a longer wait. With the key it is a read when the first\n // write landed, and an execute when it truly did not.\n await deps.sleep(30_000);\n await deps.callTool(\n cfg.tokens.planner,\n \"submit_harness_stage_result\",\n payload,\n );\n }\n}\n\n/** All stage statuses for a run in ONE paginated list_harness_stages walk \u2014\n * the F5/F4 commit-watch reads every watched stage of a run from a single\n * call per tick instead of a multi-call drive per watched job. */\nexport async function listStageStatuses(\n deps: Pick<HarnessRunnerDeps, \"callTool\">,\n cfg: Pick<HarnessRunnerConfig, \"tokens\">,\n harnessRunId: string,\n): Promise<Map<string, string>> {\n const statuses = new Map<string, string>();\n let cursor: string | undefined;\n // Bounded page walk (defensive against an unbounded cursor loop).\n for (let page = 0; page < 100; page++) {\n const res = (await deps.callTool(cfg.tokens.runner, \"list_harness_stages\", {\n harnessRunId,\n ...(cursor ? { cursor } : {}),\n })) as {\n stages?: Array<{ id: string; status: string }>;\n nextCursor?: string | null;\n };\n for (const s of res.stages ?? []) statuses.set(s.id, s.status);\n if (!res.nextCursor) break;\n cursor = res.nextCursor;\n }\n return statuses;\n}\n\nasync function stageStatus(\n deps: Pick<HarnessRunnerDeps, \"callTool\">,\n cfg: Pick<HarnessRunnerConfig, \"tokens\">,\n ctx: HarnessStageJobContext,\n): Promise<string | null> {\n const statuses = await listStageStatuses(deps, cfg, ctx.harnessRunId);\n return statuses.get(ctx.stageId) ?? null;\n}\n\n/**\n * Drive the post-validation COMMIT boundary for a stage that has reached\n * VALIDATED/COMMIT_GATE: AUTHORIZE the local commit (a permission check that mints\n * no credential and approves no gate), `git commit`, report the SHA via\n * submit_harness_stage_result (which records the commit evidence bound to this\n * attempt and lets the boundary advance the stage to COMMITTED), then PUSH/PR via\n * a single-use brokered credential once the boundary authorizes it. The runner\n * NEVER approves the commit gate itself \u2014 when policy parks the stage at a pending\n * COMMIT gate it stops and the human approves in the Control Tower. Freeze is\n * re-checked at every boundary. Exported so the runner can invoke it on its own\n * (after a later VALIDATED signal) and the smoke test can drive it deterministically.\n */\nexport async function driveHarnessCommit(\n deps: HarnessRunnerDeps,\n cfg: HarnessRunnerConfig,\n freeze: FreezeSource,\n ctx: HarnessStageJobContext,\n args: { cwd: string; branch: string; jobId: string },\n): Promise<{ disposition: string }> {\n const log = cfg.log ?? (() => {});\n if (await freeze.check()) return { disposition: \"frozen\" };\n\n // AUTHORIZE \u2192 commit locally. authorize_harness_local_commit throws on a\n // non-validated/frozen/lease-blocked/policy-deny stage, so a red stage can never\n // commit. It mints NO credential and approves NO gate. It returns the committed\n // change (captured pre-commit, since a post-commit diff is empty). It re-checks\n // freeze FRESH at each of its own boundaries.\n const commit = await authorizeAndCommit(deps, cfg, freeze, ctx, {\n cwd: args.cwd,\n branch: args.branch,\n message: `Harness stage ${ctx.stageNumber}: ${ctx.stageTitle}`,\n });\n if (!commit.sha) return { disposition: \"commit produced no SHA\" };\n\n // FRESH freeze read before the commit-evidence submit. If a freeze landed after\n // the local commit, don't report (the server would park it on a frozen run\n // anyway) \u2014 on resume the runner re-drives and re-reports the same commit.\n if (await freeze.check()) return { disposition: \"frozen\" };\n // Report the SHA + the committed files \u2014 this records the commit evidence (bound\n // to this attempt's jobId) the boundary needs to advance VALIDATED/COMMIT_GATE \u2192\n // COMMITTED. No new evidence artifacts here (they were linked on the execution\n // turn); this report is the local-commit report (boundary 1's second half).\n await submitStageResultResilient(\n deps,\n cfg,\n {\n harnessRunId: ctx.harnessRunId,\n stageId: ctx.stageId,\n changedFiles: commit.changedFiles,\n diffLines: commit.diffLines,\n branch: args.branch,\n commit: commit.sha,\n jobId: args.jobId,\n },\n // Keyed on the attempt + the exact SHA: a retry of the same commit report\n // replays; a NEW SHA (re-commit) is a different key, never a replay.\n `commit-evidence:${args.jobId}:${commit.sha}`,\n );\n\n // PUSH/PR egress \u2014 only after the boundary authorizes it (the stage reaches\n // COMMITTED). Brokered single-use credentials; never a standing token. A pending\n // commit gate or a blocked stage stops the runner (no self-approve).\n const result = await pushAfterAuthorized(\n deps,\n cfg,\n freeze,\n ctx,\n {\n cwd: args.cwd,\n branch: args.branch,\n commitSha: commit.sha,\n repo: ctx.repo ?? \"\",\n },\n () =>\n waitForCommitAuthorized(deps, cfg, freeze, ctx, { jobId: args.jobId }),\n );\n if (!result.pushed) {\n log(`[harness ${ctx.stageId}] push deferred: ${result.reason}`);\n return { disposition: `committed; push ${result.reason}` };\n }\n // A frozen-before-PR push still pushed, but the PR is deferred \u2014 surface it so a\n // resume (the COMMITTED-stage path) retries the PR rather than masking it. The\n // worktree is RETAINED (a resume needs it) \u2014 no cleanup on a deferred/frozen leg.\n if (result.reason) {\n return { disposition: `committed_and_pushed; ${result.reason}` };\n }\n // Fully delivered (COMMITTED + pushed + PR done): a safe terminal Jentrix state\n // with no active run \u2014 clean up the worktree (source-dirty/orphaned retained).\n await maybeCleanupWorktree(deps, cfg, ctx, {\n branch: args.branch,\n jobId: args.jobId,\n });\n return { disposition: \"committed_and_pushed\" };\n}\n\n/**\n * Stage 3 cleanup: once the stage is a safe TERMINAL Jentrix state (COMMITTED and\n * fully delivered \u2014 pushed, not frozen/gated), remove the delivered worktree via\n * the S1 safe path (git clean -fdX ignored \u2192 `git worktree remove` \u2192 prune). A\n * source-dirty or orphaned worktree is RETAINED and reported (a human decides). The\n * worktree deliberately survives freeze, PRE_EXECUTION/FINAL_ACCEPTANCE/COMMIT\n * gates, same-job revisions, and a process restart \u2014 those never reach this leg.\n * Best-effort: a cleanup failure never changes the commit disposition.\n */\nasync function maybeCleanupWorktree(\n deps: Pick<HarnessRunnerDeps, \"worktree\">,\n cfg: Pick<HarnessRunnerConfig, \"log\">,\n ctx: HarnessStageJobContext,\n args: { branch: string; jobId: string },\n): Promise<void> {\n const log = cfg.log ?? (() => {});\n if (!ctx.repo) return;\n try {\n const res = await deps.worktree.cleanupExecutionWorktree({\n repo: ctx.repo,\n jobId: args.jobId,\n stageId: ctx.stageId,\n branch: args.branch,\n });\n if (res.removed) {\n log(`[harness ${ctx.stageId}] worktree removed (delivered)`);\n } else if (res.reason === \"source-dirty\") {\n log(\n `[harness ${ctx.stageId}] worktree RETAINED (source-dirty, ${res.dirty?.length ?? 0} change(s)) \u2014 inspect + remove manually via the harness-worktrees command.`,\n );\n }\n } catch (e) {\n log(`[harness ${ctx.stageId}] worktree cleanup skipped: ${e}`);\n }\n}\n\n/**\n * A freeze probe for the post-validation commit phase, which (unlike the execution\n * turn) has no active M7 run to heartbeat. `check()` reads the run's frozen state\n * FRESH via `get_harness` at every boundary, so a freeze landing between boundaries\n * is caught; the server guards (authorize throws, submit/broker park/fail-closed on\n * a frozen run) are the backstop. A read failure leaves the last known state (never\n * force-unfreezes).\n */\nexport class FreezeProbe implements FreezeSource {\n frozen = false;\n constructor(\n private readonly deps: Pick<HarnessRunnerDeps, \"callTool\">,\n private readonly cfg: Pick<HarnessRunnerConfig, \"tokens\">,\n private readonly harnessRunId: string,\n ) {}\n async check(): Promise<boolean> {\n try {\n const res = (await this.deps.callTool(\n this.cfg.tokens.runner,\n \"get_harness\",\n {\n // The op's schema keys on harnessRunId (NOT harnessId).\n harnessRunId: this.harnessRunId,\n },\n )) as { harness?: { frozen?: boolean; status?: string } };\n this.frozen =\n res.harness?.frozen === true || res.harness?.status === \"FROZEN\";\n } catch {\n // A read failure shouldn't force-unfreeze; leave the last known state.\n }\n return this.frozen;\n }\n}\n\n/**\n * The LIVE post-validation commit entry point. A harness stage is validated LATER\n * than its execution turn (after the reviewer + the human FINAL_ACCEPTANCE gate),\n * at which point Jentrix emits `harness.stage_validated` (and the server commit\n * boundary parks awaiting the runner's commit evidence). The runner reacts to that\n * webhook by calling this: it re-reads the job's harness context, confirms the\n * stage is VALIDATED/COMMIT_GATE, and drives the commit boundary. Returns a\n * disposition; a non-validated stage (e.g. a stale/duplicate signal) is a no-op.\n */\nexport async function driveHarnessStageCommit(\n deps: HarnessRunnerDeps,\n cfg: HarnessRunnerConfig,\n input: { jobId: string },\n): Promise<{ disposition: string }> {\n const log = cfg.log ?? (() => {});\n const job = await getHarnessStageJob(deps, cfg, input.jobId);\n const ctx = job.harness;\n if (!ctx) return { disposition: \"not_a_harness_stage_job\" };\n\n // Bound the checkout, same as the execution turn.\n const repo = ctx.repo;\n if (!repo || !cfg.repos[repo]) throw new UnmappedRepoError(repo);\n\n const status = await stageStatus(deps, cfg, ctx);\n // AGE-410: bail BEFORE touching a worktree. This poller used to resolve the\n // worktree first, so every tick paid a bootstrap (pnpm install) for a stage\n // that was not committable \u2014 a gate-parked job on a cancelled run churned one\n // per poll, forever. Order: cheap status reads, then the worktree.\n if (\n status !== \"COMMITTED\" &&\n status !== \"VALIDATED\" &&\n status !== \"COMMIT_GATE\"\n ) {\n // A terminal run can never authorize this commit \u2014 tell the pump to drop\n // the watch instead of re-probing every tick (server-side cancel semantics\n // are AGE-410; this keeps the poller honest meanwhile).\n const run = (await deps.callTool(cfg.tokens.runner, \"get_harness\", {\n harnessRunId: ctx.harnessRunId,\n response_format: \"concise\",\n })) as { harness?: { status?: string } };\n const runStatus = run.harness?.status;\n if (runStatus === \"CANCELLED\" || runStatus === \"ARCHIVED\") {\n return { disposition: `run terminal (${runStatus}) \u2014 dropping watch` };\n }\n return { disposition: `not committable (stage ${status ?? \"?\"})` };\n }\n // The branch is read from the stage (the execution turn pinned it), so a resume\n // never re-resolves a different default-template branch. AGE-690: and if it did,\n // `ctx.taskKey` comes from this same job read, so the resolution no longer\n // depends on which channel woke the runner.\n const branch = resolveStageBranch(ctx);\n // Resolve the SAME per-job worktree the execution turn used: adopted when it\n // survived (the common case \u2014 a worktree survives validation/COMMIT gates), or\n // recreated from the stage-branch tip after a process restart that lost the dir.\n const cwd = await deps.worktree.ensureExecutionCwd(\n { repo, jobId: input.jobId, stageId: ctx.stageId, branch },\n ctx.executionBaseRef,\n );\n // The post-validation phase has no active M7 run to heartbeat, so freeze is read\n // FRESH via get_harness at every boundary (FreezeProbe.check()).\n const probe = new FreezeProbe(deps, cfg, ctx.harnessRunId);\n\n // RESUME after a freeze that landed AFTER the push but before the PR: the stage is\n // already COMMITTED (committed + pushed), so re-run ONLY the idempotent push/PR\n // leg (a re-push of the same branch is a no-op; PR-create defers to inbound\n // correlation when one already exists). Never re-commit a COMMITTED stage.\n if (status === \"COMMITTED\") {\n if (await probe.check()) return { disposition: \"frozen\" };\n const headSha = await currentHeadSha(deps, cwd);\n const result = await pushAfterAuthorized(\n deps,\n cfg,\n probe,\n ctx,\n { cwd, branch, commitSha: headSha, repo },\n // Already COMMITTED \u2014 push/PR is authorized; no need to wait.\n async () => \"authorized\",\n );\n // Fully delivered on resume (pushed, no freeze/deferral) \u2192 clean up; a deferred\n // resume RETAINS the worktree for the next attempt.\n if (result.pushed && !result.reason) {\n await maybeCleanupWorktree(deps, cfg, ctx, {\n branch,\n jobId: input.jobId,\n });\n }\n return {\n disposition: result.pushed\n ? \"committed_and_pushed (resume)\"\n : `committed; push ${result.reason} (resume)`,\n };\n }\n\n if (await probe.check()) {\n log(`[harness ${ctx.stageId}] frozen \u2014 deferring commit`);\n return { disposition: \"frozen\" };\n }\n try {\n return await driveHarnessCommit(deps, cfg, probe, ctx, {\n cwd,\n branch,\n jobId: input.jobId,\n });\n } catch (err) {\n if (err instanceof HarnessFrozenError) {\n log(err.message);\n return { disposition: \"frozen\" };\n }\n throw err;\n }\n}\n\n/** The current HEAD SHA (best-effort; empty string on failure). */\nasync function currentHeadSha(\n deps: Pick<HarnessRunnerDeps, \"git\">,\n cwd: string,\n): Promise<string> {\n try {\n return (await deps.git(cwd, [\"rev-parse\", \"HEAD\"])).trim();\n } catch {\n return \"\";\n }\n}\n", "/**\n * Worker capability declaration for the M13.4b claim/launch PREFLIGHT.\n *\n * Every governed claim (`claim_agent_job`) must PRESENT what this worker can\n * actually run so the control plane can refuse \u2014 with zero claims burned, before\n * any `AgentRun` is opened \u2014 a release that pins a model the installed SDK/binary\n * cannot execute. That is the exact `gpt-5.6-sol` incident: the account's selected\n * model needed a newer Codex runtime than the worker had installed, and the job\n * only failed at RUN TIME as an unhandled provider exception.\n *\n * The declaration is honest BY CONSTRUCTION: the worker always vouches for the\n * exact model it is about to launch (`claudeModel()` / `codexModel()`), so a\n * release pinning ANY other model is refused at preflight rather than blowing up\n * mid-turn. An operator whose installed runtime genuinely runs a broader set\n * BROADENS the list via env (per-provider, since Claude and Codex model names do\n * not overlap). The optional image/sandbox digests + code-snapshot inventory pass\n * through from env only when the operator stamps them; unset \u21D2 that dimension\n * reads as unverified server-side (never a false refusal).\n *\n * This closes the P0 for the CHECKED-IN runners: the gate no longer fires only for\n * hypothetical callers that opt into the optional field \u2014 the real runners opt in.\n */\n\n/** The `capabilities` object sent on `claim_agent_job` (matches ClaimAgentJobSchema.capabilities). */\nexport interface WorkerCapabilitiesDecl {\n /** Models this worker's installed SDK/binary can actually run \u2014 ALWAYS non-empty. */\n acceptedModels: string[];\n /** Installed SDK/binary revision (only when the operator stamps it). */\n sdkRevision?: string;\n /** Worker image digest (only when stamped). */\n workerImageDigest?: string;\n /** Sandbox base image digest (only when stamped). */\n sandboxBaseImageDigest?: string;\n /** Code-snapshot refs the worker can check out (only when stamped). */\n availableCodeSnapshots?: string[];\n}\n\n/** Parse a comma/whitespace-separated env list into a trimmed, non-empty array (or undefined). */\nfunction parseList(raw: string | undefined): string[] | undefined {\n if (!raw) return undefined;\n const items = raw\n .split(/[,\\s]+/)\n .map((s) => s.trim())\n .filter(Boolean);\n return items.length ? items : undefined;\n}\n\n/** A trimmed non-empty env string, or undefined. */\nfunction envString(raw: string | undefined): string | undefined {\n const v = raw?.trim();\n return v ? v : undefined;\n}\n\n/**\n * Build this worker's capability declaration for a claim.\n *\n * @param model The model the worker will actually launch for THIS role/turn \u2014 it\n * is always included in `acceptedModels`, because the worker can, by definition,\n * run the model it is about to invoke.\n * @param extraAcceptedModels Raw env value (e.g. `process.env.STACKS_CLAUDE_ACCEPTED_MODELS`)\n * listing additional models the operator's installed runtime can run. Per-provider\n * because Claude and Codex model names are disjoint \u2014 the caller picks the env.\n * @param env The environment to read the optional worker/image/sandbox stamps from\n * (defaults to `process.env`; injectable for tests).\n */\nexport function workerCapabilities(opts: {\n model: string;\n extraAcceptedModels?: string;\n env?: NodeJS.ProcessEnv;\n}): WorkerCapabilitiesDecl {\n const env = opts.env ?? process.env;\n // The worker ALWAYS vouches for the model it is launching (guarantees non-empty),\n // plus any operator-declared extras its installed runtime can also run.\n const extras = parseList(opts.extraAcceptedModels) ?? [];\n const acceptedModels = Array.from(new Set([opts.model, ...extras]));\n\n const decl: WorkerCapabilitiesDecl = { acceptedModels };\n\n const sdkRevision = envString(env.STACKS_SDK_REVISION);\n if (sdkRevision) decl.sdkRevision = sdkRevision;\n const workerImageDigest = envString(env.STACKS_WORKER_IMAGE_DIGEST);\n if (workerImageDigest) decl.workerImageDigest = workerImageDigest;\n const sandboxBaseImageDigest = envString(env.STACKS_SANDBOX_BASE_IMAGE_DIGEST);\n if (sandboxBaseImageDigest) decl.sandboxBaseImageDigest = sandboxBaseImageDigest;\n const availableCodeSnapshots = parseList(env.STACKS_AVAILABLE_CODE_SNAPSHOTS);\n if (availableCodeSnapshots) decl.availableCodeSnapshots = availableCodeSnapshots;\n\n return decl;\n}\n", "import type { AgentProvider } from \"./jentrix.js\";\n\nexport type WorkflowRole = \"planner\" | \"executor\" | \"reviewer\";\n\nexport interface ExpectedRoleBinding {\n agentId: string;\n runtimeAdapterKey: AgentProvider;\n provider: string;\n providerConnectionId: string;\n model: string;\n source: \"active_release\" | \"worker_draft\";\n requiresClaimCredential: boolean;\n}\n\nexport type RunnerRoleBindings = Record<WorkflowRole, ExpectedRoleBinding>;\n\nexport interface ResolvedClaimExecution {\n runtimeAdapterKey: AgentProvider;\n providerConnectionId: string;\n model: string;\n generationControls: Record<string, unknown> | null;\n permissions: Record<string, unknown> | null;\n}\n\nfunction record(value: unknown): Record<string, unknown> | null {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction parseBinding(value: unknown, role: WorkflowRole): ExpectedRoleBinding {\n const row = record(value);\n if (!row)\n throw new Error(`RUNNER_CONFIG_INVALID: ${role} role binding is missing.`);\n for (const key of [\n \"agentId\",\n \"provider\",\n \"providerConnectionId\",\n \"model\",\n \"source\",\n ] as const) {\n if (typeof row[key] !== \"string\" || row[key].length === 0) {\n throw new Error(`RUNNER_CONFIG_INVALID: ${role}.${key} is missing.`);\n }\n }\n if (row.runtimeAdapterKey !== \"claude\" && row.runtimeAdapterKey !== \"codex\") {\n throw new Error(\n `RUNNER_CONFIG_INVALID: ${role} names an unknown runtime adapter.`,\n );\n }\n if (row.source !== \"active_release\" && row.source !== \"worker_draft\") {\n throw new Error(\n `RUNNER_CONFIG_INVALID: ${role} binding source is invalid.`,\n );\n }\n if (typeof row.requiresClaimCredential !== \"boolean\") {\n throw new Error(\n `RUNNER_CONFIG_INVALID: ${role}.requiresClaimCredential is missing.`,\n );\n }\n return row as unknown as ExpectedRoleBinding;\n}\n\nexport function parseRoleBindings(raw: string): RunnerRoleBindings {\n let value: unknown;\n try {\n value = JSON.parse(raw);\n } catch {\n throw new Error(\n \"RUNNER_CONFIG_INVALID: STACKS_RUNNER_ROLE_BINDINGS is not valid JSON.\",\n );\n }\n const row = record(value);\n if (!row)\n throw new Error(\"RUNNER_CONFIG_INVALID: role bindings must be an object.\");\n return {\n planner: parseBinding(row.planner, \"planner\"),\n executor: parseBinding(row.executor, \"executor\"),\n reviewer: parseBinding(row.reviewer, \"reviewer\"),\n };\n}\n\nexport function resolveClaimExecution(\n claim: Record<string, unknown>,\n expected: ExpectedRoleBinding,\n): ResolvedClaimExecution {\n const execution = record(claim.workerExecution);\n if (!execution) {\n throw new Error(\n \"ROLE_PLAN_UNSATISFIED: the claimed job has no durable worker execution binding; publish and activate a configured release.\",\n );\n }\n const adapter = execution.runtimeAdapterKey;\n const connectionId = execution.providerConnectionId;\n const model = execution.model;\n if (\n (adapter !== \"claude\" && adapter !== \"codex\") ||\n typeof connectionId !== \"string\" ||\n typeof model !== \"string\"\n ) {\n throw new Error(\n \"ROLE_PLAN_UNSATISFIED: the claim returned a malformed worker execution binding.\",\n );\n }\n if (\n adapter !== expected.runtimeAdapterKey ||\n connectionId !== expected.providerConnectionId ||\n model !== expected.model\n ) {\n throw new Error(\n `ROLE_PLAN_UNSATISFIED: claimed ${adapter}/${connectionId}/${model} does not match the configured durable ${expected.runtimeAdapterKey}/${expected.providerConnectionId}/${expected.model} binding.`,\n );\n }\n return {\n runtimeAdapterKey: adapter,\n providerConnectionId: connectionId,\n model,\n generationControls: record(execution.generationControls),\n permissions: record(execution.permissions),\n };\n}\n", "/**\n * Project-context injection for the three harness roles (planner, executor,\n * reviewer).\n *\n * Two gaps this closes, both observed on the M18 run:\n *\n * 1. CONVENTIONS. The Claude legs run with `settingSources: ['project']` so the\n * SDK loads the checkout's CLAUDE.md natively (see providers/claude.ts); the\n * Codex legs read AGENTS.md, which is a symlink to the same file. Neither is\n * guaranteed to be *noticed* \u2014 an explicit instruction naming the file as the\n * contract the reviewer enforces costs ~60 tokens and is the difference\n * between a turn that follows the repo's ops-core/MCP/enum rules and one that\n * re-invents them and gets rejected.\n *\n * 2. PARALLEL WORK. A stage worktree is cut from its base ref once and never\n * rebased, so commits landing on the base branch mid-run (harness fixes while\n * the same repo's PRD is being implemented \u2014 the M18 shape exactly) are\n * invisible to every role. Naming them keeps a role from re-fixing what was\n * already fixed, or from reasoning about a file the deployed server no longer\n * matches.\n *\n * Fail-soft by construction: every git read is best-effort, and a failure\n * degrades to the conventions block alone. A context builder must never be the\n * reason a turn dies.\n */\n\nexport interface ProjectContextDeps {\n /** Run a git command in `cwd` and return stdout (the runner's bounded RunGit). */\n git: (cwd: string, args: string[]) => Promise<string>;\n}\n\nexport type ProjectRole = \"planner\" | \"executor\" | \"reviewer\";\n\nexport interface ProjectContextInput {\n /** The role's checkout (worktree for the executor, read-only for the others). */\n cwd: string;\n /** The run's base branch. Defaults to `main` when the caller has none. */\n baseBranch?: string | null;\n role: ProjectRole;\n}\n\n/** W5: how far this checkout's lineage trails the run's base branch. */\nexport interface BaseDrift {\n /** Commits on the base branch that are not in this checkout's history. */\n behindBase: number;\n /** The base branch's tip sha (empty when the ref could not be read). */\n baseSha: string;\n /** This checkout's HEAD sha (empty when unreadable). */\n headSha: string;\n}\n\n/**\n * W5: measure drift between this checkout and the run's base branch. Stacking a\n * stage on an unmerged predecessor is CORRECT, so drift is not an error \u2014 it is\n * a fact that was previously invisible: while M18 stage 6 sat unmerged for two\n * days, `main` advanced five harness fixes and stage 7 planned against a stale\n * CLAUDE.md. Measured and surfaced; never auto-rebased (that stays an operator\n * act). Best-effort: an unreadable ref reports zero rather than failing a turn.\n */\nexport async function measureBaseDrift(\n deps: ProjectContextDeps,\n input: { cwd: string; baseBranch?: string | null },\n): Promise<BaseDrift> {\n const base = (input.baseBranch || \"main\").trim() || \"main\";\n const ref = `refs/remotes/origin/${base}`;\n const read = async (args: string[]): Promise<string> =>\n (await deps.git(input.cwd, args).catch(() => \"\")).trim();\n // `rev-list --count HEAD..<base>` is exactly \"commits on the base branch this\n // checkout does not have\" \u2014 it already accounts for the merge base, so a\n // stacked stage counts only what actually landed after its lineage diverged.\n const count = await read([\"rev-list\", \"--count\", `HEAD..${ref}`]);\n return {\n behindBase: Number.isFinite(Number(count)) ? Number(count) : 0,\n baseSha: await read([\"rev-parse\", ref]),\n headSha: await read([\"rev-parse\", \"HEAD\"]),\n };\n}\n\n/** How many parallel commits to name before summarizing the rest. */\nconst MAX_LISTED_COMMITS = 20;\n\nconst ROLE_LINE: Record<ProjectRole, string> = {\n planner:\n \"Plan WITHIN these conventions \u2014 a plan that proposes a second engine, a parallel store, or a new enum where the repo says otherwise is rejected before it is executed.\",\n executor:\n \"Implement WITHIN these conventions and do not re-fix what a parallel commit already fixed; read the current file before changing code a listed commit touched.\",\n reviewer:\n \"Judge the diff against these conventions as well as the plan \u2014 and do not raise as a defect something a listed parallel commit already resolved on the base branch.\",\n};\n\n/**\n * Build the injected context block for one role's turn. Returns \"\" only if\n * every section is empty (never throws).\n */\nexport async function buildProjectContext(\n deps: ProjectContextDeps,\n input: ProjectContextInput,\n): Promise<string> {\n const sections = [\n `CONVENTIONS \u2014 read \\`AGENT_GUIDELINES.md\\` at the checkout root FIRST: it is the operating contract for every agent in this repo (the non-negotiable invariants, the map of \\`src/server\\` subsystems, your role's authority limits, and the evidence rules), and it names where each rule is enforced. Then read \\`CLAUDE.md\\` (\\`AGENTS.md\\` is the same file) for the product-surface architecture it points to. For anything under \\`src/server/harness\\`, \\`src/server/workflows\\`, or \\`agents/\\`, \\`harness-specs/\\` is the SOURCE OF TRUTH for how the engine behaves \u2014 open \\`harness-specs/README.md\\` and read the file its index points you to BEFORE claiming a state, gate, refusal, or env var works a particular way, and update that spec in the same change when you alter engine behavior. A change that ignores any of these is rejected at review regardless of test results. ${ROLE_LINE[input.role]}`,\n ];\n\n const truth = await gitTruth(deps, input);\n if (truth) sections.push(truth);\n\n const parallel = await baseBranchDelta(deps, input);\n if (parallel) sections.push(parallel);\n\n return `\\n\\n## Project context (injected by the runner)\\n\\n${sections.join(\"\\n\\n\")}\\n`;\n}\n\n/**\n * W3: runner-computed GIT TRUTH for this turn \u2014 HEAD, how dirty the tree is, and\n * how far the checkout trails the base branch.\n *\n * A role that reasons about the tree from memory (or from a prior round's\n * summary) writes claims the attested ledger then contradicts; M18 stage 7's\n * executor \"audited instead of fixing\" partly because the state it reasoned\n * about lived in prose it could rationalize past. Naming the facts every turn is\n * the cheap half of the fix \u2014 the enforcing half is the hooks + the evidence\n * gate. Best-effort: unreadable git degrades to no section.\n */\nasync function gitTruth(\n deps: ProjectContextDeps,\n input: ProjectContextInput,\n): Promise<string | null> {\n const drift = await measureBaseDrift(deps, input);\n if (!drift.headSha) return null;\n const dirty = (await deps.git(input.cwd, [\"status\", \"--porcelain\"]).catch(() => \"\"))\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter(Boolean);\n const base = (input.baseBranch || \"main\").trim() || \"main\";\n const drifted =\n drift.behindBase > 0\n ? `${drift.behindBase} commit(s) BEHIND \\`${base}\\`${drift.baseSha ? ` (${drift.baseSha.slice(0, 12)})` : \"\"}`\n : `up to date with \\`${base}\\``;\n return `GIT TRUTH (measured by the runner in this checkout, not remembered): HEAD is \\`${drift.headSha.slice(0, 12)}\\`, the tree has ${dirty.length} uncommitted change(s), and this checkout is ${drifted}. These are the facts your claims are checked against \u2014 the runner captures the diff from THIS tree and attests the verification commands itself.`;\n}\n\n/**\n * Commits on the base branch that this checkout does NOT have. Uses the local\n * remote-tracking ref \u2014 the worktree manager already fast-forwards it to the run\n * base, so this costs no network round-trip and a missing ref simply yields \"\".\n */\nasync function baseBranchDelta(\n deps: ProjectContextDeps,\n input: ProjectContextInput,\n): Promise<string | null> {\n const base = (input.baseBranch || \"main\").trim() || \"main\";\n const ref = `refs/remotes/origin/${base}`;\n const out = await deps\n .git(input.cwd, [\n \"log\",\n \"--oneline\",\n \"--no-decorate\",\n `-${MAX_LISTED_COMMITS + 1}`,\n `HEAD..${ref}`,\n ])\n .catch(() => \"\");\n const commits = out\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean);\n if (commits.length === 0) return null;\n const listed = commits.slice(0, MAX_LISTED_COMMITS);\n const overflow =\n commits.length > MAX_LISTED_COMMITS\n ? `\\n \u2026and more \u2014 run \\`git log --oneline HEAD..${ref}\\` for the full list.`\n : \"\";\n return `PARALLEL WORK \u2014 \\`${base}\\` has moved since this branch was cut. ${listed.length}${overflow ? \"+\" : \"\"} commit(s) are on the base branch but NOT in your checkout, and the DEPLOYED server already has them:\\n ${listed.join(\"\\n \")}${overflow}`;\n}\n", "/**\n * Versioned role rubrics (Harness Reliability W7).\n *\n * The executor's evidence contract and the reviewer's disposition rubric used to\n * live as inline template literals in two different files \u2014 unversioned,\n * partially duplicated, and impossible to diff when a role's behavior changed.\n * They are runtime content injected into every role turn, so they live in THIS\n * repo (the one the runner clones), next to the runner that injects them.\n *\n * Injection stays explicit: the Agent SDK does not auto-discover skills, and the\n * Codex legs get their prompt assembled the same way.\n *\n * FAIL CLOSED on a missing rubric. A role turn that runs without its contract is\n * exactly the silent degradation this program exists to remove \u2014 a loud startup\n * error naming the path is strictly better than a turn that quietly reverts to\n * \"whatever the model assumes\".\n */\nimport { readFileSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport type RubricName = \"executor-evidence\" | \"reviewer-disposition\";\n\nconst RUBRIC_DIR = path.join(\n path.dirname(fileURLToPath(import.meta.url)),\n \"..\",\n \"rubrics\",\n);\n\nconst cache = new Map<RubricName, string>();\n\n/** The rubric's text, cached. Throws (naming the path) when it is missing. */\nexport function loadRubric(name: RubricName): string {\n const cached = cache.get(name);\n if (cached) return cached;\n const file = path.join(RUBRIC_DIR, `${name}.md`);\n let text: string;\n try {\n text = readFileSync(file, \"utf8\").trim();\n } catch {\n throw new Error(\n `Missing role rubric ${name} at ${file} \u2014 a role turn must never run without its contract. Restore agents/rubrics/ (it ships with the runner) and retry.`,\n );\n }\n if (!rubricVersion(text)) {\n throw new Error(\n `Role rubric ${name} at ${file} carries no version marker (<!-- rubric-version: ${name}/N -->); refusing to inject an unversioned contract.`,\n );\n }\n cache.set(name, text);\n return text;\n}\n\n/** The `<!-- rubric-version: name/N -->` marker, or null when absent. PURE. */\nexport function rubricVersion(text: string): string | null {\n return /<!--\\s*rubric-version:\\s*([^\\s]+)\\s*-->/.exec(text)?.[1] ?? null;\n}\n", "/**\n * The runner's checkout-access lane, keyed off the DURABLE run role (M18.3 R7).\n *\n * ZERO IMPORTS, ON PURPOSE \u2014 three things depend on it and each one breaks if a\n * single import lands here:\n *\n * 1. **The dependency firewall stays intact.** `agents/` is its own pnpm package\n * with its own lockfile, excluded from the app's tsconfig and eslint. A module\n * with no imports can be read by the app's test suite across that firewall\n * WITHOUT dragging the Claude/Codex SDKs into the app's dependency graph.\n * 2. **The frozen root suite can EXECUTE it.** `src/server/harness/validator-semantics.test.ts`\n * imports this file directly and runs every case in-process. That suite rides\n * the stage's frozen verification commands, so the decision below is\n * runner-attested rather than asserted in executor prose. (`pnpm typecheck`\n * type-checks this file as an imported file \u2014 tsconfig `exclude` filters the\n * default include glob, never files reached through an import.)\n * 3. **There is exactly one copy of the rule per side.** The table below must\n * equal `REPO_ACCESS_BY_DISPATCH_ROLE` in `src/server/harness/validator-semantics.ts`\n * entry-for-entry, including the fail-closed default. That equality is\n * asserted by the attested suite, so drift is a red test, not a silent\n * divergence between what the control plane promises and what the runner does.\n *\n * WHY THIS EXISTS. A claim is the one doorway where an attempt is handed both its\n * Jentrix authority and \u2014 on the runner's side of that answer \u2014 its checkout.\n * Nothing downstream can take a writable worktree back once it has been handed\n * over, so \"this attempt may not mutate the repository\" is not something a later\n * boundary can retrofit; it is a property of how the attempt was DISPATCHED. The\n * runner used to decide that from the leg's SHAPE (`isExecution` / `isReviewer`,\n * derived from the job phase). This module moves the decision onto the durable\n * identity the control plane returns from `claim_agent_job` \u2014 `AgentRun.role` \u2014\n * so every leg the deployed runner drives resolves its checkout the same way,\n * through one total, fail-closed function.\n *\n * FAIL-CLOSED IS THE LOAD-BEARING PART. The map is TOTAL: a role it does not\n * recognize \u2014 VALIDATOR, a role a later milestone adds, a typo, an empty string\n * from a control plane that stopped returning the field \u2014 resolves to READ-ONLY,\n * ADOPT-ONLY. A writable worktree is only ever handed out by an entry that says\n * so in so many words. That is what makes the guarantee survive a change nobody\n * remembered to update this file for: the new thing is read-only until someone\n * deliberately writes it down here, and writing it down means the attested\n * mirror-conformance test forces the same entry into the server's table.\n */\n\n/** How a dispatched attempt may touch the repository checkout. */\nexport interface RepoAccess {\n /** `read-write` is the ONLY mode that may provision or mutate a worktree. */\n readonly mode: \"read-write\" | \"read-only\";\n /**\n * May the dispatcher CREATE the attempt's worktree (`ensureExecutionCwd` /\n * `git worktree add`)? False means adopt-an-existing-tree or nothing \u2014 the\n * runner never brings a writable checkout into being for this role.\n */\n readonly provisionWorktree: boolean;\n /**\n * The flag the provider sandboxes already enforce (`lib/providers/claude.ts`\n * withholds the write/edit tools; `lib/providers/codex.ts` runs the shell under\n * a read-only sandbox). Passed straight through to the model session.\n */\n readonly repoReadOnly: boolean;\n /** May this attempt author a repository mutation (local commit, push, PR)? */\n readonly canCommit: boolean;\n}\n\n/** A writable worktree \u2014 the executor lane, and the only one there is. */\nconst READ_WRITE: RepoAccess = {\n mode: \"read-write\",\n provisionWorktree: true,\n repoReadOnly: false,\n canCommit: true,\n};\n\n/**\n * Read-only, adopt-only. The planner and reviewer legs already ran this way\n * (they read a checkout they never provision); a VALIDATOR attempt runs here\n * too, and so does anything unrecognized.\n */\nconst READ_ONLY: RepoAccess = {\n mode: \"read-only\",\n provisionWorktree: false,\n repoReadOnly: true,\n canCommit: false,\n};\n\n/**\n * The authority table. MIRROR of `REPO_ACCESS_BY_DISPATCH_ROLE` in\n * `src/server/harness/validator-semantics.ts` \u2014 keep them identical.\n *\n * EXECUTOR is the single read-write entry: an execution turn implements the\n * change, so it gets the writable worktree it always got (byte-for-byte today's\n * behavior). PLANNER and REVIEWER are read-only, which is also exactly what they\n * do today \u2014 they are listed explicitly rather than left to the default so that\n * the table states the whole shipped world and a future edit to the default\n * cannot silently change them.\n */\nexport const REPO_ACCESS_BY_ROLE: Readonly<Record<string, RepoAccess>> = {\n EXECUTOR: READ_WRITE,\n PLANNER: READ_ONLY,\n REVIEWER: READ_ONLY,\n VALIDATOR: READ_ONLY,\n};\n\n/**\n * What an UNRECOGNIZED role gets. Read-only, adopt-only \u2014 never a writable\n * worktree. See the header: this is the entry that makes the guarantee hold for\n * roles this file has never heard of.\n */\nexport const FAIL_CLOSED_REPO_ACCESS: RepoAccess = READ_ONLY;\n\n/**\n * The total function every dispatch path calls. Null, undefined, an empty\n * string, an unknown role \u2014 all read-only. Case-sensitive on purpose: the\n * control plane returns the enum name verbatim, and quietly normalizing a\n * near-miss like \"executor\" into the writable lane is exactly the kind of\n * helpfulness that hands out a checkout nobody authorized.\n */\nexport function repoAccessForRole(role: string | null | undefined): RepoAccess {\n if (typeof role !== \"string\") return FAIL_CLOSED_REPO_ACCESS;\n const entry = Object.prototype.hasOwnProperty.call(REPO_ACCESS_BY_ROLE, role)\n ? REPO_ACCESS_BY_ROLE[role]\n : undefined;\n return entry ?? FAIL_CLOSED_REPO_ACCESS;\n}\n\n/**\n * The operator-facing diagnostic when a read-only attempt has no tree to adopt.\n *\n * The read-only lane must NEVER degrade to \"create one instead\" (that is the\n * writable lane it was just refused) or to \"read the shared checkout\" (which\n * lacks the stage's uncommitted change, so any verdict it produces is about the\n * wrong tree \u2014 the same fail-closed rule the harness reviewer leg already\n * follows). Parking the attempt with this sentence is the honest third option.\n */\nexport function missingReadOnlyCheckoutReason(ctx: {\n role: string | null | undefined;\n stageId: string;\n}): string {\n return (\n `A ${String(ctx.role ?? \"(unset)\")} attempt on stage ${ctx.stageId} runs read-only (M18.3 R7), so it may ` +\n \"adopt an existing worktree but never create one \u2014 and no worktree for this stage exists to adopt. \" +\n \"Refusing to fall back to a writable checkout (that is the lane this role was denied) or to the shared \" +\n \"grounding checkout (which lacks the stage's uncommitted changes, so any verdict would describe the \" +\n \"wrong tree). Run the stage's executor assignment first so the tree exists, then re-run this attempt.\"\n );\n}\n", "/**\n * Reference-runner worktree manager (Concurrent Harness Execution PRD, Stage 3).\n *\n * S1 (`packages/execution/src/worktree.ts`) is the dependency-free MECHANICS\n * (path derivation, create/adopt/detach/cleanup, marker validation, containment).\n * THIS module is the reference runner's POLICY layer on top of it \u2014 the part that\n * needs the runner's git seam AND fresh Jentrix state:\n *\n * \u2022 per-repo config: STACKS_RUNNER_REPOS stays back-compatible with string\n * values (\"owner/name\" -> checkout) and also accepts an operator object\n * { cwd, bootstrap:[[argv]], copyIgnoredFiles, worktreeRoot } (parseRunnerRepos);\n * \u2022 ensureExecutionCwd \u2014 the per-job worktree the executor/commit turn works in:\n * prune FIRST (amendment b), adopt this job's own worktree on restart, else run\n * the branch-OWNERSHIP check before creating on a shared stage branch, then\n * create/adopt, run idempotent bootstrap argv, and copy allowlisted ignored\n * config (owner-only, git-check-ignore confirmed);\n * \u2022 adoptExecutionCwd \u2014 read-only adoption for the reviewer + a commit resume;\n * \u2022 cleanupExecutionWorktree \u2014 the S1 safe cleanup, caller-gated to a terminal\n * Jentrix state (git clean -fdX ignored + `git worktree remove` + prune, source-\n * dirty retained);\n * \u2022 list \u2014 the operator listing (repo/job/stage/age/source-cleanliness).\n *\n * The runner NEVER assumes a branch template is globally unique: because the\n * null/legacy fallback `harness/{taskKey}-stage-{number}` and the current stage-id\n * `{slug}` substitution let legacy, null, custom, and same-anchor runs resolve to\n * the SAME branch, ensureExecutionCwd applies the ownership check on THAT headline\n * multi-harness path \u2014 a collision with a live or unprovable attempt is rejected\n * with the owning branch/job named, and no checkout is reset, renamed, or stolen.\n */\nimport { execFile } from \"node:child_process\";\nimport { constants as fsConstants, existsSync, realpathSync } from \"node:fs\";\nimport { chmod, copyFile, mkdir, readdir, stat } from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { promisify } from \"node:util\";\n\nimport {\n adoptWorktree,\n checkpointWorktree,\n cleanupWorktree,\n createWorktree,\n detachSupersededWorktree,\n readMarker,\n resolveWorktreePaths,\n WorktreeError,\n type CheckpointResult,\n type CleanupResult,\n type RunGit,\n type WorktreeIdentity,\n type WorktreeMarker,\n type WorktreeRepoConfig,\n} from \"../../packages/execution/src/worktree.js\";\n\nconst execFileP = promisify(execFile);\n\n/** One configured repository: the S1 path config plus the runner's per-repo\n * operator options (bootstrap argv + ignored-config allowlist). */\nexport interface RunnerRepoEntry {\n config: WorktreeRepoConfig;\n /** argv arrays run in the worktree AFTER containment/ownership validation.\n * Idempotent by contract (may re-run on adoption). Empty by default. */\n bootstrap: string[][];\n /** Repo-relative paths of IGNORED config to copy into a fresh worktree, each\n * re-confirmed ignored by `git check-ignore` at copy time. Empty by default \u2014\n * no ignored file is copied unless explicitly allowlisted. */\n copyIgnoredFiles: string[];\n}\n\n/** The four identifiers that key + validate an attempt's worktree at the runner\n * boundary (a superset-free view of the S1 WorktreeIdentity). */\nexport interface StageWorktreeIdentity {\n repo: string;\n jobId: string;\n stageId: string;\n branch: string;\n}\n\n/** A runner-owned worktree row for the operator listing (LOCAL paths \u2014 printed to\n * stdout for a human, NEVER persisted into Jentrix activity or artifacts). */\nexport interface RunnerWorktreeInfo {\n repo: string;\n jobId: string;\n stageId: string;\n branch: string;\n status: WorktreeMarker[\"status\"];\n /** Absolute local path (operator-facing only). */\n dir: string;\n /** Age of the worktree (ms) from its marker mtime. */\n ageMs: number;\n /** True when `git status --porcelain` is non-empty (tracked changes or non-\n * ignored untracked files) \u2014 retained by cleanup, needs a manual decision. */\n sourceDirty: boolean;\n /** Present when git no longer has a live worktree at `dir` (orphaned/prunable). */\n orphaned: boolean;\n}\n\n/** The verdict of reading FRESH Jentrix state for a branch's current owner. */\nexport type OwnerVerdict =\n | { status: \"live\"; detail: string }\n | { status: \"superseded\"; detail: string }\n | { status: \"unprovable\"; detail: string };\n\n/**\n * Read FRESH Jentrix state to decide whether the OLD attempt that owns a colliding\n * stage branch is still the live/current owner, is confirmed superseded, or is\n * unprovable. Injected so the manager stays testable and the \"read fresh Jentrix\n * state\" concern lives in ONE wired place (the runner's callTool). `current` is the\n * attempt asking to reuse the branch (this runner's claimed job).\n */\nexport type OwnerStateReader = (\n owner: { jobId: string; stageId: string; branch: string },\n current: { jobId: string; stageId: string },\n) => Promise<OwnerVerdict>;\n\n/** Run an arbitrary bootstrap argv in a cwd (spawn seam; git is separate). */\nexport type RunCommand = (cwd: string, argv: string[]) => Promise<void>;\n\nconst defaultRunCommand: RunCommand = async (cwd, argv) => {\n await execFileP(argv[0], argv.slice(1), {\n cwd,\n maxBuffer: 64 * 1024 * 1024,\n });\n};\n\n/** A fail-closed ownership error \u2014 the branch's owner is live or unprovable, so the\n * worktree/branch is left untouched (never reset, renamed, or stolen).\n * `CHECKPOINT_FAILED` (W1) is the same posture applied to work rather than to the\n * branch: the superseded attempt's uncommitted diff could not be rescued onto the\n * branch, so the claim is refused loudly instead of silently overwriting it. */\nexport class WorktreeOwnershipError extends Error {\n constructor(\n readonly code: \"LIVE_CONFLICT\" | \"UNPROVABLE\" | \"CHECKPOINT_FAILED\",\n message: string,\n ) {\n super(message);\n this.name = \"WorktreeOwnershipError\";\n }\n}\n\n/** What the reference runner depends on for per-job worktree lifecycle. */\nexport interface WorktreeManager {\n /** Fast-forward the shared read-only grounding checkout to the run base. */\n refreshGroundingCheckout(repo: string, baseBranch: string): Promise<string>;\n /** Create/adopt this job's worktree and return its absolute dir: prune first,\n * adopt on restart, else ownership-check + create on the stage branch, then run\n * idempotent bootstrap + copy allowlisted ignored config. */\n ensureExecutionCwd(\n identity: StageWorktreeIdentity,\n executionBaseRef: string,\n ): Promise<string>;\n /** Adopt an EXISTING worktree (reviewer read-only / commit resume). Returns its\n * dir, or null when absent. No create / bootstrap / copy. */\n adoptExecutionCwd(identity: StageWorktreeIdentity): Promise<string | null>;\n /** W1: commit a parked attempt's dirty tree onto its stage branch so the park is\n * LOSSLESS. Clean tree \u21D2 no commit; a worktree that cannot reach the branch\n * (detached/other branch) throws rather than stranding the work silently. */\n checkpointExecutionCwd(\n identity: StageWorktreeIdentity,\n message: string,\n ): Promise<CheckpointResult>;\n /** Safe cleanup (caller-gated to a terminal Jentrix state with no active run). */\n cleanupExecutionWorktree(\n identity: StageWorktreeIdentity,\n ): Promise<CleanupResult>;\n /** Operator listing of runner-owned worktrees (absolute paths \u2014 stdout only). */\n list(): Promise<RunnerWorktreeInfo[]>;\n}\n\n/** One entry parsed from `git worktree list --porcelain`. */\ninterface GitWorktreeRow {\n path: string;\n branch: string | null;\n detached: boolean;\n}\n\n/**\n * Parse STACKS_RUNNER_REPOS. Back-compatible with string values (\"owner/name\" ->\n * checkout path) and also accepts the operator object form. Throws a legible error\n * on a malformed entry rather than silently dropping config.\n */\nexport function parseRunnerRepos(\n raw: unknown,\n): Record<string, RunnerRepoEntry> {\n const out: Record<string, RunnerRepoEntry> = {};\n if (raw == null) return out;\n if (typeof raw !== \"object\" || Array.isArray(raw)) {\n throw new Error(\n \"STACKS_RUNNER_REPOS must be a JSON object mapping 'owner/name' -> checkout | { cwd, bootstrap, copyIgnoredFiles }.\",\n );\n }\n for (const [repo, value] of Object.entries(raw as Record<string, unknown>)) {\n if (typeof value === \"string\") {\n out[repo] = {\n config: { repo, checkout: value },\n bootstrap: [],\n copyIgnoredFiles: [],\n };\n continue;\n }\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new Error(\n `STACKS_RUNNER_REPOS['${repo}'] must be a checkout path string or an object { cwd, ... }.`,\n );\n }\n const obj = value as Record<string, unknown>;\n const cwd = obj.cwd;\n if (typeof cwd !== \"string\" || !cwd.trim()) {\n throw new Error(\n `STACKS_RUNNER_REPOS['${repo}'].cwd must be a non-empty checkout path.`,\n );\n }\n const bootstrap = parseBootstrap(repo, obj.bootstrap);\n const copyIgnoredFiles = parseCopyIgnored(repo, obj.copyIgnoredFiles);\n const worktreeRoot =\n typeof obj.worktreeRoot === \"string\" && obj.worktreeRoot.trim()\n ? obj.worktreeRoot\n : undefined;\n out[repo] = {\n config: {\n repo,\n checkout: cwd,\n ...(worktreeRoot ? { worktreeRoot } : {}),\n },\n bootstrap,\n copyIgnoredFiles,\n };\n }\n return out;\n}\n\nfunction parseBootstrap(repo: string, value: unknown): string[][] {\n if (value == null) return [];\n if (!Array.isArray(value)) {\n throw new Error(\n `STACKS_RUNNER_REPOS['${repo}'].bootstrap must be an array of argv arrays.`,\n );\n }\n return value.map((argv, i) => {\n if (\n !Array.isArray(argv) ||\n argv.length === 0 ||\n !argv.every((a) => typeof a === \"string\")\n ) {\n throw new Error(\n `STACKS_RUNNER_REPOS['${repo}'].bootstrap[${i}] must be a non-empty array of string args.`,\n );\n }\n return argv as string[];\n });\n}\n\nfunction parseCopyIgnored(repo: string, value: unknown): string[] {\n if (value == null) return [];\n if (!Array.isArray(value) || !value.every((v) => typeof v === \"string\")) {\n throw new Error(\n `STACKS_RUNNER_REPOS['${repo}'].copyIgnoredFiles must be an array of repo-relative path strings.`,\n );\n }\n return value as string[];\n}\n\n/** Derive the owner\u2192checkout map the generic (non-worktree) drive path still uses. */\nexport function checkoutMap(\n entries: Record<string, RunnerRepoEntry>,\n): Record<string, string> {\n return Object.fromEntries(\n Object.entries(entries).map(([repo, e]) => [repo, e.config.checkout]),\n );\n}\n\n/** Reference-runner worktree manager over the S1 mechanics + a git seam + a fresh\n * Jentrix-state reader. */\nexport class RunnerWorktreeManager implements WorktreeManager {\n constructor(\n private readonly entries: Record<string, RunnerRepoEntry>,\n private readonly runGit: RunGit,\n private readonly readOwnerState: OwnerStateReader,\n private readonly opts: {\n runCommand?: RunCommand;\n log?: (msg: string) => void;\n } = {},\n ) {}\n\n private entryFor(repo: string): RunnerRepoEntry {\n const entry = this.entries[repo];\n if (!entry) {\n throw new Error(\n `No STACKS_RUNNER_REPOS entry for ${repo} \u2014 cannot resolve a worktree.`,\n );\n }\n return entry;\n }\n\n private wtId(identity: StageWorktreeIdentity): WorktreeIdentity {\n return {\n repo: identity.repo,\n jobId: identity.jobId,\n stageId: identity.stageId,\n branch: identity.branch,\n };\n }\n\n async refreshGroundingCheckout(\n repo: string,\n baseBranch: string,\n ): Promise<string> {\n const entry = this.entryFor(repo);\n const branch = baseBranch.trim() || \"main\";\n const remoteRef = `refs/remotes/origin/${branch}`;\n await this.runGit(entry.config.checkout, [\n \"fetch\",\n \"origin\",\n `+refs/heads/${branch}:${remoteRef}`,\n ]);\n await this.runGit(entry.config.checkout, [\"merge\", \"--ff-only\", remoteRef]);\n const [head, baseHead] = await Promise.all([\n this.runGit(entry.config.checkout, [\"rev-parse\", \"HEAD\"]),\n this.runGit(entry.config.checkout, [\"rev-parse\", remoteRef]),\n ]);\n if (head !== baseHead) {\n throw new Error(\n `grounding checkout HEAD ${head.slice(0, 12)} did not reach ${branch} ${baseHead.slice(0, 12)}`,\n );\n }\n return entry.config.checkout;\n }\n\n async ensureExecutionCwd(\n identity: StageWorktreeIdentity,\n executionBaseRef: string,\n ): Promise<string> {\n const entry = this.entryFor(identity.repo);\n const wtId = this.wtId(identity);\n const { dir } = resolveWorktreePaths(entry.config, wtId);\n\n // (1) Prune FIRST (amendment b) \u2014 reconcile any manually-removed worktree so a\n // stale registration can't wedge the stage branch before the ownership check.\n await this.runGit(entry.config.checkout, [\"worktree\", \"prune\"]);\n\n if (existsSync(dir)) {\n // This job's OWN worktree already exists (restart / same-job revision turn):\n // adopt it (marker + git must agree, else S1 fails closed) and re-run the\n // idempotent bootstrap/copy.\n const res = await adoptWorktree({\n config: entry.config,\n identity: wtId,\n runGit: this.runGit,\n });\n await this.bootstrapAndCopy(entry, res.dir);\n return res.dir;\n }\n\n // Fresh worktree for this job. The stage branch may be owned by ANOTHER\n // attempt's worktree (retry, or a same-anchor/legacy/null-template collision):\n // resolve ownership from durable Git metadata + fresh Jentrix state BEFORE\n // touching the branch. detach-on-superseded is the only mutation it performs.\n await this.ownershipCheckBeforeRetry(entry, wtId);\n\n const res = await createWorktree({\n config: entry.config,\n identity: wtId,\n executionBaseRef,\n runGit: this.runGit,\n });\n await this.bootstrapAndCopy(entry, res.dir);\n return res.dir;\n }\n\n async adoptExecutionCwd(\n identity: StageWorktreeIdentity,\n ): Promise<string | null> {\n const entry = this.entryFor(identity.repo);\n const wtId = this.wtId(identity);\n // Prune first so a manually-removed worktree reads as absent (null), not as a\n // spurious adoption failure.\n await this.runGit(entry.config.checkout, [\"worktree\", \"prune\"]);\n const { dir } = resolveWorktreePaths(entry.config, wtId);\n if (!existsSync(dir)) return null;\n const res = await adoptWorktree({\n config: entry.config,\n identity: wtId,\n runGit: this.runGit,\n });\n return res.dir;\n }\n\n async checkpointExecutionCwd(\n identity: StageWorktreeIdentity,\n message: string,\n ): Promise<CheckpointResult> {\n const entry = this.entryFor(identity.repo);\n return checkpointWorktree({\n config: entry.config,\n identity: this.wtId(identity),\n message,\n runGit: this.runGit,\n });\n }\n\n async cleanupExecutionWorktree(\n identity: StageWorktreeIdentity,\n ): Promise<CleanupResult> {\n const entry = this.entryFor(identity.repo);\n return cleanupWorktree({\n config: entry.config,\n identity: this.wtId(identity),\n runGit: this.runGit,\n });\n }\n\n async list(): Promise<RunnerWorktreeInfo[]> {\n const rows: RunnerWorktreeInfo[] = [];\n for (const entry of Object.values(this.entries)) {\n // `git worktree list` reflects LIVE registrations\u2026\n const live = await this.listGitWorktrees(entry.config.checkout).catch(\n () => [] as GitWorktreeRow[],\n );\n const liveByRealDir = new Map<string, GitWorktreeRow>();\n for (const w of live) {\n liveByRealDir.set(realDirKey(w.path), w);\n }\n // \u2026but the ownership MARKERS on disk are the source of truth for what the\n // runner owns. Enumerate every sibling marker (not just the ones a live\n // worktree registration still points at), so a STALE marker whose worktree\n // registration/path is gone \u2014 a manual `rm -rf`, or a `git worktree remove`\n // that lost the marker \u2014 is reported ORPHANED for manual cleanup instead of\n // silently vanishing because `git worktree list` no longer shows it.\n const base = path.dirname(\n resolveWorktreePaths(entry.config, MARKER_SCAN_IDENTITY).dir,\n );\n for (const markerPath of await listMarkerFiles(base)) {\n const marker = await readMarker(markerPath).catch(() => null);\n if (!marker || marker.repo !== entry.config.repo) continue;\n // S1 derives dir + marker as `<base>/<jobId>` and\n // `<base>/<jobId>.marker.json`, so the worktree dir is the marker path\n // minus the `.marker.json` sibling suffix.\n const dir = markerPath.slice(0, -MARKER_SUFFIX.length);\n const present = existsSync(dir);\n // Orphaned when git no longer has a live worktree at the dir OR the dir\n // itself is gone \u2014 either way the marker outlived its worktree.\n const orphaned = !liveByRealDir.has(realDirKey(dir)) || !present;\n const sourceDirty = present ? await this.isSourceDirty(dir) : false;\n rows.push({\n repo: marker.repo,\n jobId: marker.jobId,\n stageId: marker.stageId,\n branch: marker.branch,\n status: marker.status,\n dir,\n ageMs: await markerAgeMs(markerPath),\n sourceDirty,\n orphaned,\n });\n }\n }\n return rows;\n }\n\n // -------------------------------------------------------------------------\n // Ownership check (retry / same-anchor branch collision).\n // -------------------------------------------------------------------------\n\n private async ownershipCheckBeforeRetry(\n entry: RunnerRepoEntry,\n wtId: WorktreeIdentity,\n ): Promise<void> {\n const ourDir = safeRealpath(resolveWorktreePaths(entry.config, wtId).dir);\n const live = await this.listGitWorktrees(entry.config.checkout);\n // Any OTHER worktree with our target branch checked out is a collision \u2014 the\n // runner NEVER assumes the branch template is globally unique.\n const conflict = live.find(\n (w) => w.branch === wtId.branch && safeRealpath(w.path) !== ourDir,\n );\n if (!conflict) return; // no live checkout holds the branch \u2014 safe to create\n\n // Resolve the owner marker (a SIBLING of the conflicting worktree dir). A\n // worktree that holds the branch but has no runner marker (e.g. the main\n // checkout, or a foreign worktree) is UNPROVABLE \u2014 fail closed, steal nothing.\n const markerPath = markerPathFor(conflict.path);\n const marker = existsSync(markerPath)\n ? await readMarker(markerPath).catch(() => null)\n : null;\n if (!marker || marker.branch !== wtId.branch) {\n throw new WorktreeOwnershipError(\n \"UNPROVABLE\",\n `Stage branch ${wtId.branch} is checked out at ${conflict.path}, which carries no resolvable runner ownership marker; refusing to reset/rename/steal it. Free that checkout manually, then retry job ${wtId.jobId}.`,\n );\n }\n if (marker.jobId === wtId.jobId) return; // somehow ours (dir differed) \u2014 no-op\n\n // Read FRESH Jentrix state for the owning attempt.\n let verdict: OwnerVerdict;\n try {\n verdict = await this.readOwnerState(\n {\n jobId: marker.jobId,\n stageId: marker.stageId,\n branch: wtId.branch,\n },\n { jobId: wtId.jobId, stageId: wtId.stageId },\n );\n } catch (err) {\n throw new WorktreeOwnershipError(\n \"UNPROVABLE\",\n `Could not read Jentrix state for the attempt (job ${marker.jobId}, stage ${marker.stageId}) owning branch ${wtId.branch}: ${\n err instanceof Error ? err.message : String(err)\n }. Failing closed \u2014 the worktree at ${conflict.path} is unchanged.`,\n );\n }\n\n if (verdict.status === \"live\") {\n throw new WorktreeOwnershipError(\n \"LIVE_CONFLICT\",\n `Stage branch ${wtId.branch} is owned by a live attempt (job ${marker.jobId}, stage ${marker.stageId}) at ${conflict.path} \u2014 ${verdict.detail}. Refusing to reset/rename/steal it; resolve or supersede that attempt before retrying job ${wtId.jobId}.`,\n );\n }\n if (verdict.status === \"unprovable\") {\n throw new WorktreeOwnershipError(\n \"UNPROVABLE\",\n `Ownership of stage branch ${wtId.branch} (job ${marker.jobId}, stage ${marker.stageId}) is unprovable \u2014 ${verdict.detail}. Failing closed; the worktree at ${conflict.path} is unchanged.`,\n );\n }\n\n // W1 claim-time rescue: the superseded attempt parked (or its runner died)\n // without reaching a commit gate, so its worktree may still hold uncommitted\n // work. Detaching preserves those files ON DISK but leaves them off the\n // branch \u2014 the fresh worktree below checks the branch out at a tip that has\n // none of them, and the diff becomes invisible to every reviewer and gate.\n // Checkpoint it onto the branch FIRST, while the old worktree still has that\n // branch attached. If the checkpoint cannot reach the branch, refuse the\n // claim with the path named: parking loudly beats losing work silently.\n const rescued = await this.rescueSupersededWork(entry, marker, wtId);\n\n // Confirmed superseded \u2192 detach the OLD worktree (files preserved, marker\n // stamped superseded-detached), which frees the branch for our fresh worktree\n // to reuse. detachSupersededWorktree re-validates the marker before touching it.\n this.opts.log?.(\n `[harness-worktree] branch ${wtId.branch} superseded (${verdict.detail}) \u2014 ${rescued}detaching old worktree (job ${marker.jobId}) to reuse the branch for job ${wtId.jobId}`,\n );\n await detachSupersededWorktree({\n config: entry.config,\n identity: {\n repo: marker.repo,\n jobId: marker.jobId,\n stageId: marker.stageId,\n branch: marker.branch,\n },\n runGit: this.runGit,\n });\n }\n\n /**\n * W1: checkpoint a confirmed-superseded attempt's dirty tree onto the stage\n * branch before the detach that would strand it. Returns a log fragment naming\n * what was rescued (empty when there was nothing to rescue). A checkpoint that\n * cannot reach the branch REFUSES the claim \u2014 the work stays on disk, named in\n * the error, and a human reconciles it; overwriting it silently is the defect\n * this exists to kill.\n */\n private async rescueSupersededWork(\n entry: RunnerRepoEntry,\n marker: WorktreeMarker,\n wtId: WorktreeIdentity,\n ): Promise<string> {\n const oldIdentity: WorktreeIdentity = {\n repo: marker.repo,\n jobId: marker.jobId,\n stageId: marker.stageId,\n branch: marker.branch,\n };\n let res: CheckpointResult;\n try {\n res = await checkpointWorktree({\n config: entry.config,\n identity: oldIdentity,\n message: `harness checkpoint: stage ${marker.stageId} job ${marker.jobId} (claim-time rescue by job ${wtId.jobId})`,\n runGit: this.runGit,\n });\n } catch (err) {\n const oldDir = resolveWorktreePaths(entry.config, oldIdentity).dir;\n throw new WorktreeOwnershipError(\n \"CHECKPOINT_FAILED\",\n `Stage branch ${wtId.branch} is held by a superseded attempt (job ${marker.jobId}) whose uncommitted work at ${oldDir} could NOT be checkpointed onto the branch: ${\n err instanceof Error ? err.message : String(err)\n } Refusing the claim for job ${wtId.jobId} rather than reusing the branch and losing that work \u2014 reconcile ${oldDir} by hand, then retry.`,\n );\n }\n if (!res.committed) return \"\";\n this.opts.log?.(\n `[harness-worktree] rescued ${res.files?.length ?? 0} uncommitted path(s) from superseded job ${marker.jobId} onto ${marker.branch} (${res.sha?.slice(0, 12)})`,\n );\n return `rescued ${res.files?.length ?? 0} uncommitted path(s) onto the branch, `;\n }\n\n // -------------------------------------------------------------------------\n // Bootstrap + ignored-config copy (fresh + idempotent-on-adoption).\n // -------------------------------------------------------------------------\n\n private async bootstrapAndCopy(\n entry: RunnerRepoEntry,\n dir: string,\n ): Promise<void> {\n // Copy the allowlisted ignored config FIRST (a bootstrap step may consume it,\n // e.g. a .env the install/build reads), THEN run bootstrap. Both only after\n // the worktree passed containment/ownership validation above.\n await this.copyIgnoredConfig(entry, dir);\n await this.runBootstrap(entry, dir);\n }\n\n private async runBootstrap(\n entry: RunnerRepoEntry,\n dir: string,\n ): Promise<void> {\n const run = this.opts.runCommand ?? defaultRunCommand;\n for (const argv of entry.bootstrap) {\n if (argv.length === 0) continue;\n // Idempotent by contract (may re-run on adoption). Never logged with args\n // beyond the command name (an argv could carry a secret).\n this.opts.log?.(`[harness-worktree] bootstrap: ${argv[0]} \u2026`);\n await run(dir, argv);\n }\n }\n\n private async copyIgnoredConfig(\n entry: RunnerRepoEntry,\n dir: string,\n ): Promise<void> {\n if (entry.copyIgnoredFiles.length === 0) return; // nothing copied by default\n let copied = 0;\n for (const rel of entry.copyIgnoredFiles) {\n // Repo-relative only \u2014 reject absolute paths + `..` traversal outright.\n if (path.isAbsolute(rel) || rel.split(/[\\\\/]+/).includes(\"..\")) {\n throw new Error(\n `copyIgnoredFiles entry ${JSON.stringify(rel)} must be a repo-relative path with no '..'.`,\n );\n }\n const src = path.join(entry.config.checkout, rel);\n if (!existsSync(src)) continue; // absent source \u2014 nothing to copy\n // `git check-ignore` MUST confirm the path is ignored \u2014 never copy a tracked\n // file (that would shadow real source in the worktree).\n if (!(await this.isIgnored(entry.config.checkout, rel))) continue;\n const dest = path.join(dir, rel);\n assertUnder(dir, dest); // dest can never escape the worktree\n await mkdir(path.dirname(dest), { recursive: true, mode: 0o700 });\n // Copy, then clamp to owner-only. copyFile without an existing dest inherits\n // umask; chmod pins 0o600 so the (possibly secret) config is owner-only.\n await copyFile(src, dest, fsConstants.COPYFILE_FICLONE);\n await chmod(dest, 0o600);\n copied += 1;\n }\n // NEVER log file names/contents (an ignored config can be a secret) \u2014 count only.\n if (copied > 0) {\n this.opts.log?.(\n `[harness-worktree] copied ${copied} ignored config file(s)`,\n );\n }\n }\n\n private async isIgnored(checkout: string, rel: string): Promise<boolean> {\n try {\n // `git check-ignore <path>` prints the path + exits 0 when ignored; exits 1\n // (which runGit surfaces as a rejection) when NOT ignored. `--` guards a\n // path that looks like a flag.\n const out = await this.runGit(checkout, [\"check-ignore\", \"--\", rel]);\n return out.trim().length > 0;\n } catch {\n return false;\n }\n }\n\n // -------------------------------------------------------------------------\n // Git helpers.\n // -------------------------------------------------------------------------\n\n private async listGitWorktrees(checkout: string): Promise<GitWorktreeRow[]> {\n const out = await this.runGit(checkout, [\n \"worktree\",\n \"list\",\n \"--porcelain\",\n ]);\n const rows: GitWorktreeRow[] = [];\n let cur: Partial<GitWorktreeRow> | null = null;\n for (const line of out.split(\"\\n\")) {\n if (line.startsWith(\"worktree \")) {\n if (cur?.path) rows.push(finishRow(cur));\n cur = { path: line.slice(\"worktree \".length).trim() };\n } else if (line.startsWith(\"branch \")) {\n const ref = line.slice(\"branch \".length).trim();\n if (cur) cur.branch = ref.replace(/^refs\\/heads\\//, \"\");\n } else if (line.trim() === \"detached\") {\n if (cur) cur.detached = true;\n }\n }\n if (cur?.path) rows.push(finishRow(cur));\n return rows;\n }\n\n private async isSourceDirty(dir: string): Promise<boolean> {\n try {\n const porcelain = await this.runGit(dir, [\"status\", \"--porcelain\"]);\n return porcelain.trim().length > 0;\n } catch {\n return false;\n }\n }\n}\n\nfunction finishRow(cur: Partial<GitWorktreeRow>): GitWorktreeRow {\n return {\n path: cur.path as string,\n branch: cur.branch ?? null,\n detached: cur.detached ?? false,\n };\n}\n\n/** The sibling ownership-marker path for a listed worktree dir. */\nfunction markerPathFor(worktreeDir: string): string {\n return path.join(\n path.dirname(worktreeDir),\n `${path.basename(worktreeDir)}.marker.json`,\n );\n}\n\nfunction assertUnder(base: string, target: string): void {\n const b = path.resolve(base);\n const t = path.resolve(target);\n if (t !== b && !t.startsWith(b + path.sep)) {\n throw new WorktreeError(\"PATH_ESCAPE\", `path ${t} escapes ${b}`);\n }\n}\n\nfunction safeRealpath(p: string): string {\n // realpathSync would throw on a not-yet-existing path; for comparison we only\n // need a normalized absolute form, and existing dirs are compared by realpath at\n // the S1 layer. path.resolve is enough here (git already emits absolute paths).\n return path.resolve(p);\n}\n\n/** Realpath-normalized key for a worktree dir so a live `git worktree list` path\n * and a marker-derived dir compare equal across symlinked roots (e.g. macOS\n * /var \u2192 /private/var). Falls back to path.resolve when the dir is gone. */\nfunction realDirKey(p: string): string {\n try {\n return realpathSync(p);\n } catch {\n return path.resolve(p);\n }\n}\n\nconst MARKER_SUFFIX = \".marker.json\";\n\n/** A dummy identity used ONLY to derive a repo's worktree base dir\n * (`<root>/<repoKey>`) via resolveWorktreePaths \u2014 the jobId leaf is discarded\n * (we take its parent). \"scan\" satisfies the S1 opaque-jobId shape check. */\nconst MARKER_SCAN_IDENTITY: WorktreeIdentity = {\n repo: \"_\",\n jobId: \"scan\",\n stageId: \"_\",\n branch: \"_\",\n};\n\n/** Enumerate the sibling ownership markers directly under a repo's worktree base.\n * Tolerates a not-yet-created base (no worktrees \u21D2 empty list). */\nasync function listMarkerFiles(base: string): Promise<string[]> {\n let names: string[];\n try {\n names = await readdir(base);\n } catch {\n return [];\n }\n return names\n .filter((n) => n.endsWith(MARKER_SUFFIX))\n .map((n) => path.join(base, n));\n}\n\nasync function markerAgeMs(markerPath: string): Promise<number> {\n try {\n const s = await stat(markerPath);\n return Math.max(0, Date.now() - s.mtimeMs);\n } catch {\n return 0;\n }\n}\n", "/**\n * Sandbox-side broker adapters \u2014 production credential injection (M12.5, AGE-175).\n *\n * M12.3a shipped the {@link CredentialBroker} that turns a capability handle into a\n * short-lived credential; M12.4a gave it a workload-identity resolver. Both stop at\n * \"here is a token string\". This module is the M12.5 half: the ADAPTERS that take a\n * resolved M4 grant and INJECT the secret into exactly ONE authorized process/action,\n * then DESTROY it \u2014 so the agent process can *request* an action but can never *read*\n * the secret.\n *\n * The trust split is the whole point:\n * \u2022 The AGENT (the untrusted workload inside the sandbox) only ever holds an OPAQUE,\n * single-use {@link ActionHandle} \u2014 a nonce + the authorized action + non-secret\n * target. It requests \"perform handle H with params P\"; it never sees material.\n * \u2022 The BROKER (this module, owned by the sandbox host/controller, a separate trust\n * domain) resolves the grant behind the handle, injects the credential into the\n * ONE authorized effect, runs it, destroys the material, and returns only the\n * non-secret result.\n *\n * Three production adapters, one authorized effect each:\n * \u2022 repo:push \u2192 git credential helper (secret in the git child's ENV, never\n * argv, never the parent/agent env).\n * \u2022 repo:pr_create \u2192 GitHub App-token `Authorization` header on the PR-create call.\n * \u2022 deploy:production \u2192 Vercel `Authorization: Bearer` header on the deploy call\n * (and release:rollback over the same Vercel adapter).\n *\n * Every adapter enforces, in code (proven by the conformance suite):\n * \u2022 single-use \u2014 a handle performs at most once; the grant resolve is single-use\n * server-side too.\n * \u2022 TTL expiry \u2014 an expired handle (or grant) fails closed before any injection.\n * \u2022 scope-narrow \u2014 the requested target must lie within the resolved grant's scope\n * (repo \u2208 repositories, contents:write present; environment match);\n * a violation fails closed WITHOUT injecting and revokes the grant.\n * \u2022 audit \u2014 granted \u2192 resolved \u2192 injected \u2192 destroyed (or \u2192 revoked/denied)\n * rows, carrying NO material.\n * \u2022 revoke-on-fail \u2014 an injected action that throws revokes the grant before it\n * surfaces the error.\n *\n * Dependency-free apart from node builtins + the execution package (matches the rest\n * of this standalone package). Everything with a side effect (grant resolve/revoke,\n * git, http, clock, nonce) is INJECTED so the conformance/adversarial/observable-exit\n * suites drive it hermetically and a real deployment wires the live effects.\n */\nimport { randomUUID } from \"node:crypto\";\nimport { spawn } from \"node:child_process\";\n\n/** The externally-visible actions a sandbox-side adapter can inject a credential for. */\nexport type BrokerAction =\n | \"repo:push\"\n | \"repo:pr_create\"\n | \"deploy:production\"\n | \"release:rollback\";\n\n/** Non-secret binding of an action to its target (what the agent is allowed to ask). */\nexport interface ActionTarget {\n /** \"owner/name\" \u2014 the repo a push/PR is bound to. */\n repo?: string;\n /** The git branch a push/PR targets. */\n branch?: string;\n /** The deploy environment (\"production\"). */\n environment?: string;\n}\n\n/**\n * The OPAQUE, single-use action handle handed to the agent. It carries NO secret \u2014\n * only a nonce, the one authorized action, the non-secret target, and the id of the\n * M4 grant it will consume (an opaque reference, not material). A leaked handle is\n * useless without the broker (which alone can resolve the grant) and is single-use.\n */\nexport interface ActionHandle {\n handleId: string;\n action: BrokerAction;\n capabilityId: string;\n /** The M4 grant id this handle consumes \u2014 an opaque ref, NOT a secret. */\n grantId: string;\n target: ActionTarget;\n /** ISO timestamp after which the handle is dead (fail closed). */\n expiresAt: string;\n}\n\n/** The scope a resolved M4 grant is narrowed to (mirrors the CredentialGrant.scope). */\nexport interface GrantScope {\n /**\n * The GitHub repositories the grant's token is scoped to. Each entry is EITHER a\n * fully-qualified `owner/name` (compared whole) OR a bare short name (the GitHub\n * installation-token form) \u2014 a bare short name is honored ONLY when {@link owner}\n * pins the account it belongs to. Never compare short names alone: a grant for\n * `acme/api` must never authorize `evil/api` (see {@link repoWithinScope}).\n */\n repositories?: string[];\n /**\n * The GitHub account/owner login the grant's installation is bound to. A GitHub App\n * installation lives under exactly one account, so bare `repositories` short names\n * are attributable to THIS owner and no other. Required to authorize a bare short\n * name; when absent, only fully-qualified `owner/name` entries can match (fail\n * closed otherwise), so the owner can never be spoofed.\n */\n owner?: string;\n /** GitHub installation-token permissions, e.g. { contents: \"write\" }. */\n permissions?: Record<string, string>;\n /** The single environment a cloud grant authorizes. */\n environment?: string;\n}\n\n/**\n * True iff the FULL `owner/name` `repo` is authorized by `scope`. The check is\n * OWNER-AWARE (the M12.5 finding this closes): a bare short-name entry in\n * `scope.repositories` is honored ONLY when `scope.owner` pins the same account, and\n * a fully-qualified entry must match `owner/name` whole (case-insensitive, per\n * GitHub). A `repo` that is not fully-qualified, or whose owner we cannot attribute to\n * the grant, fails closed \u2014 so a grant scoped to `acme/api` never authorizes the\n * same-short-name `evil/api`.\n */\nexport function repoWithinScope(scope: GrantScope, repo: string): boolean {\n if (!repo.includes(\"/\")) return false; // require a fully-qualified owner/name\n const [owner, name] = repo.split(\"/\");\n if (!owner || !name) return false;\n const target = repo.toLowerCase();\n const ownerLc = owner.toLowerCase();\n const nameLc = name.toLowerCase();\n const scopeOwner = scope.owner?.toLowerCase();\n for (const entry of scope.repositories ?? []) {\n if (entry.includes(\"/\")) {\n // Fully-qualified entry \u2014 must match the whole owner/name.\n if (entry.toLowerCase() === target) return true;\n } else if (\n scopeOwner &&\n scopeOwner === ownerLc &&\n entry.toLowerCase() === nameLc\n ) {\n // Bare short name \u2014 honored ONLY under the grant's pinned owner.\n return true;\n }\n }\n return false;\n}\n\n/**\n * A resolved M4 grant: the SECRET plus its narrowed scope + expiry. This value NEVER\n * leaves the broker \u2014 it lives only inside a `perform*` call and is destroyed after\n * the single injection.\n */\nexport interface ResolvedGrant {\n /** The raw credential material (installation token / Vercel token). */\n material: string;\n expiresAt: string;\n scope: GrantScope;\n}\n\n/**\n * The M4 grant plane, injected. In production `resolve` is wired to the control\n * plane's `resolveGrantForExecution` (single-use: ISSUED\u2192USED atomically, fails\n * closed on expired/revoked/action-mismatch) and `revoke` to `revokeCredentialGrant`.\n * The broker treats BOTH as authoritative \u2014 it never fabricates or caches material.\n */\nexport interface GrantPlane {\n /** Resolve a grant to material. MUST be single-use + fail-closed server-side. */\n resolve(grantId: string, action: BrokerAction): Promise<ResolvedGrant>;\n /** Revoke a grant (revocation-on-failure). Best-effort; never throws material. */\n revoke(grantId: string, reason: string): Promise<void>;\n}\n\n/** A single non-secret audit row. `detail` MUST never contain material. */\nexport interface BrokerAuditRow {\n ts: string;\n phase:\n | \"granted\"\n | \"resolved\"\n | \"injected\"\n | \"destroyed\"\n | \"revoked\"\n | \"denied\";\n handleId: string;\n grantId: string;\n action: BrokerAction;\n capabilityId: string;\n outcome: \"ok\" | \"failed\";\n detail?: string;\n}\n\n/**\n * Run a git command in a checkout. `secretEnv` is merged into the CHILD process\n * environment ONLY \u2014 never the parent/agent env, never argv (a token-in-URL would\n * leak into `ps`/git error output). Returns the child's stdout + exit code.\n */\nexport type GitInjector = (args: {\n cwd: string;\n argv: string[];\n secretEnv: Record<string, string>;\n}) => Promise<{ stdout: string; stderr: string; exitCode: number }>;\n\n/**\n * Perform an authenticated HTTP request. `authHeader` carries the secret and is sent\n * ONLY as the `Authorization` request header to the destination \u2014 never in the URL,\n * body, or any surface the agent or MCP transport can read.\n */\nexport type HttpInjector = (args: {\n method: string;\n url: string;\n authHeader: string;\n headers?: Record<string, string>;\n body?: string;\n}) => Promise<{ status: number; body: string }>;\n\nexport interface SandboxBrokerDeps {\n grants: GrantPlane;\n git: GitInjector;\n http: HttpInjector;\n /** Non-secret audit sink (grant/injection/destruction feed). */\n audit?: (row: BrokerAuditRow) => void;\n now?: () => number;\n /** Opaque handle-id minter (default randomUUID) \u2014 injectable for determinism. */\n mintHandleId?: () => string;\n /** GitHub REST base (PR create). Default https://api.github.com. */\n githubApiBase?: string;\n /** Vercel REST base (deploy/rollback). Default https://api.vercel.com. */\n vercelApiBase?: string;\n}\n\n/** A structured, fail-closed broker error. `message`/`code` carry NO material. */\nexport class BrokerAdapterError extends Error {\n constructor(\n readonly code:\n | \"HANDLE_EXPIRED\"\n | \"HANDLE_CONSUMED\"\n | \"ACTION_MISMATCH\"\n | \"SCOPE_VIOLATION\"\n | \"GRANT_UNRESOLVED\"\n | \"INJECTION_FAILED\",\n message: string,\n ) {\n super(message);\n this.name = \"BrokerAdapterError\";\n }\n}\n\nexport interface PushResult {\n pushed: boolean;\n branch: string;\n remote: string;\n}\nexport interface PrResult {\n url: string;\n number: number;\n}\nexport interface DeployResult {\n deploymentId: string | null;\n status: string;\n url: string | null;\n}\n\n/**\n * The default git injector: spawns real `git`, merging `secretEnv` into the CHILD\n * env only. The secret never touches argv or the parent process env.\n */\nexport const spawnGitInjector: GitInjector = ({ cwd, argv, secretEnv }) =>\n new Promise((resolve, reject) => {\n const child = spawn(\"git\", argv, {\n cwd,\n // The ONLY place the secret exists: this child's environment. It is gone the\n // moment the process exits \u2014 never inherited by the agent workload.\n env: { ...process.env, ...secretEnv },\n });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout.on(\"data\", (d) => (stdout += d));\n child.stderr.on(\"data\", (d) => (stderr += d));\n child.on(\"error\", reject);\n child.on(\"close\", (code) =>\n resolve({\n stdout: stdout.trim(),\n stderr: stderr.trim(),\n exitCode: code ?? 0,\n }),\n );\n });\n\n/**\n * The default http injector: `fetch` with the secret only in the Authorization\n * header. Requires a global `fetch` (Node \u2265 18). The body is read back as text.\n */\nexport const fetchHttpInjector: HttpInjector = async ({\n method,\n url,\n authHeader,\n headers,\n body,\n}) => {\n const res = await fetch(url, {\n method,\n headers: { ...(headers ?? {}), Authorization: authHeader },\n body,\n redirect: \"manual\",\n });\n return { status: res.status, body: await res.text() };\n};\n\n/**\n * The sandbox-side credential broker. It mints opaque handles for the agent and\n * OWNS the injection of every credential \u2014 the agent never touches material.\n */\nexport class SandboxBroker {\n private readonly now: () => number;\n private readonly mintHandleId: () => string;\n private readonly audit: (row: BrokerAuditRow) => void;\n private readonly githubApiBase: string;\n private readonly vercelApiBase: string;\n /** Handles consumed exactly once \u2014 the in-broker half of single-use. */\n private readonly consumed = new Set<string>();\n\n constructor(private readonly deps: SandboxBrokerDeps) {\n this.now = deps.now ?? Date.now;\n this.mintHandleId = deps.mintHandleId ?? (() => `ah_${randomUUID()}`);\n this.audit = deps.audit ?? (() => {});\n this.githubApiBase = deps.githubApiBase ?? \"https://api.github.com\";\n this.vercelApiBase = deps.vercelApiBase ?? \"https://api.vercel.com\";\n }\n\n /**\n * Mint an OPAQUE, single-use action handle for the agent. No secret is touched\n * here \u2014 the handle only names an already-issued M4 grant + the one authorized\n * action + target. `ttlSeconds` bounds the handle independently of the grant.\n */\n grantHandle(req: {\n action: BrokerAction;\n capabilityId: string;\n grantId: string;\n target: ActionTarget;\n ttlSeconds?: number;\n }): ActionHandle {\n const ttl = req.ttlSeconds ?? 600;\n const handle: ActionHandle = {\n handleId: this.mintHandleId(),\n action: req.action,\n capabilityId: req.capabilityId,\n grantId: req.grantId,\n target: req.target,\n expiresAt: new Date(this.now() + ttl * 1000).toISOString(),\n };\n this.emit(handle, \"granted\", \"ok\");\n return handle;\n }\n\n // ---- The three production adapters (one authorized effect each) ----------\n\n /**\n * repo:push \u2014 inject a single-use GitHub token into a git push via a credential\n * helper that reads it from the git child's ENV. The secret never appears in argv\n * (no token-in-URL), the parent/agent env, or any returned value.\n */\n async performPush(\n handle: ActionHandle,\n params: {\n cwd: string;\n branch: string;\n refspec?: string;\n /** Override the remote (GitHub Enterprise host or a test remote); default\n * https://github.com/<owner>/<name>.git. The credential-helper injection is\n * identical regardless. */\n remoteUrl?: string;\n },\n ): Promise<PushResult> {\n return this.withGrant(handle, \"repo:push\", async (grant) => {\n const repo = handle.target.repo ?? \"\";\n this.assertRepoInScope(handle, grant, repo, \"contents\");\n const [owner, name] = repo.split(\"/\");\n const remoteUrl =\n params.remoteUrl ?? `https://github.com/${owner}/${name}.git`;\n const refspec = params.refspec ?? `${params.branch}:${params.branch}`;\n // The credential helper reads the token from $STACKS_GIT_TOKEN \u2014 passed ONLY\n // in the child env below, never on the command line.\n const helper =\n '!f() { echo \"username=x-access-token\"; echo \"password=$STACKS_GIT_TOKEN\"; }; f';\n const res = await this.deps.git({\n cwd: params.cwd,\n argv: [\"-c\", `credential.helper=${helper}`, \"push\", remoteUrl, refspec],\n secretEnv: { STACKS_GIT_TOKEN: grant.material },\n });\n if (res.exitCode !== 0) {\n throw new BrokerAdapterError(\n \"INJECTION_FAILED\",\n `git push failed (exit ${res.exitCode})`,\n );\n }\n return {\n pushed: true,\n branch: params.branch,\n remote: `${owner}/${name}`,\n };\n });\n }\n\n /**\n * repo:pr_create \u2014 inject the App-installation token as the `Authorization` header\n * on the GitHub PR-create REST call. The token is only ever a request header to\n * api.github.com; the returned {url, number} carries no material.\n */\n async performPrCreate(\n handle: ActionHandle,\n params: {\n repo: string;\n head: string;\n base: string;\n title: string;\n body?: string;\n },\n ): Promise<PrResult> {\n return this.withGrant(handle, \"repo:pr_create\", async (grant) => {\n this.assertRepoInScope(handle, grant, params.repo, \"pull_requests\");\n const res = await this.deps.http({\n method: \"POST\",\n url: `${this.githubApiBase}/repos/${params.repo}/pulls`,\n // The secret lives ONLY here \u2014 a request header to GitHub.\n authHeader: `Bearer ${grant.material}`,\n headers: {\n Accept: \"application/vnd.github+json\",\n \"X-GitHub-Api-Version\": \"2022-11-28\",\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n title: params.title,\n head: params.head,\n base: params.base,\n body: params.body ?? \"\",\n }),\n });\n if (res.status < 200 || res.status >= 300) {\n throw new BrokerAdapterError(\n \"INJECTION_FAILED\",\n `PR create failed (HTTP ${res.status})`,\n );\n }\n const parsed = JSON.parse(res.body) as {\n html_url?: string;\n number?: number;\n };\n return {\n url: parsed.html_url ?? \"\",\n number: parsed.number ?? 0,\n };\n });\n }\n\n /**\n * deploy:production / release:rollback \u2014 inject the Vercel token as an\n * `Authorization: Bearer` header on the deploy REST call. The environment target\n * must match the grant scope. Returns the deployment id/url \u2014 never the token.\n */\n async performDeploy(\n handle: ActionHandle,\n params: {\n projectId: string;\n environment: string;\n commitSha?: string;\n teamId?: string;\n },\n ): Promise<DeployResult> {\n const action = handle.action;\n if (action !== \"deploy:production\" && action !== \"release:rollback\") {\n throw new BrokerAdapterError(\n \"ACTION_MISMATCH\",\n `handle authorizes ${action}, not a deploy`,\n );\n }\n return this.withGrant(handle, action, async (grant) => {\n this.assertEnvInScope(handle, grant, params.environment);\n const q = params.teamId\n ? `?teamId=${encodeURIComponent(params.teamId)}`\n : \"\";\n const res = await this.deps.http({\n method: \"POST\",\n url: `${this.vercelApiBase}/v13/deployments${q}`,\n // The secret lives ONLY here \u2014 a request header to Vercel.\n authHeader: `Bearer ${grant.material}`,\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n name: params.projectId,\n project: params.projectId,\n target: params.environment,\n gitSource: params.commitSha\n ? { type: \"github\", sha: params.commitSha }\n : undefined,\n }),\n });\n if (res.status < 200 || res.status >= 300) {\n throw new BrokerAdapterError(\n \"INJECTION_FAILED\",\n `deploy failed (HTTP ${res.status})`,\n );\n }\n const parsed = JSON.parse(res.body) as {\n id?: string;\n url?: string;\n readyState?: string;\n status?: string;\n };\n return {\n deploymentId: parsed.id ?? null,\n status: parsed.readyState ?? parsed.status ?? \"PENDING\",\n url: parsed.url ?? null,\n };\n });\n }\n\n // ---- Shared injection lifecycle -----------------------------------------\n\n /**\n * The single-use / TTL / resolve / scope / inject / destroy / revoke-on-fail\n * lifecycle shared by every adapter. `run` is the ONE authorized effect; the\n * resolved grant (material) is visible only inside it and destroyed after.\n */\n private async withGrant<T>(\n handle: ActionHandle,\n expected: BrokerAction,\n run: (grant: ResolvedGrant) => Promise<T>,\n ): Promise<T> {\n // 1. Action must match the handle (defense against a coerced handle reuse).\n if (handle.action !== expected) {\n this.emit(handle, \"denied\", \"failed\", \"action mismatch\");\n throw new BrokerAdapterError(\n \"ACTION_MISMATCH\",\n `handle authorizes ${handle.action}, not ${expected}`,\n );\n }\n // 2. TTL \u2014 an expired handle fails closed before ANY grant resolve/injection.\n if (this.now() >= Date.parse(handle.expiresAt)) {\n this.emit(handle, \"denied\", \"failed\", \"handle expired\");\n throw new BrokerAdapterError(\"HANDLE_EXPIRED\", \"action handle expired\");\n }\n // 3. Single-use \u2014 claim the handle BEFORE resolving material so a concurrent or\n // replayed call cannot double-inject. (The server resolve is single-use too.)\n if (this.consumed.has(handle.handleId)) {\n this.emit(handle, \"denied\", \"failed\", \"handle already consumed\");\n throw new BrokerAdapterError(\n \"HANDLE_CONSUMED\",\n \"action handle already consumed\",\n );\n }\n this.consumed.add(handle.handleId);\n\n // 4. Resolve the grant to material (single-use + fail-closed server-side).\n let grant: ResolvedGrant;\n try {\n grant = await this.deps.grants.resolve(handle.grantId, expected);\n } catch (err) {\n this.emit(handle, \"denied\", \"failed\", \"grant unresolved\");\n throw new BrokerAdapterError(\n \"GRANT_UNRESOLVED\",\n `grant did not resolve: ${errText(err)}`,\n );\n }\n // The grant's own expiry is authoritative too \u2014 fail closed if already past it.\n if (this.now() >= Date.parse(grant.expiresAt)) {\n await this.revoke(handle, \"grant expired at injection\");\n throw new BrokerAdapterError(\"HANDLE_EXPIRED\", \"grant expired\");\n }\n this.emit(handle, \"resolved\", \"ok\");\n\n // 5. Inject into the ONE authorized effect. A scope violation raised inside `run`\n // (via assert*) or an effect failure revokes the grant (revoke-on-failure).\n let material: string | null = grant.material;\n try {\n const result = await run(grant);\n this.emit(handle, \"injected\", \"ok\");\n return result;\n } catch (err) {\n // Revoke-on-failure: a scope violation or a failed injection kills the grant\n // so a partially-used credential can never be retried.\n await this.revoke(handle, `injection failed: ${errText(err)}`);\n if (err instanceof BrokerAdapterError) throw err;\n throw new BrokerAdapterError(\"INJECTION_FAILED\", errText(err));\n } finally {\n // 6. Destroy the material \u2014 drop every in-broker reference. The git child env\n // is already gone; the http header was request-scoped. Nothing persists it.\n material = null;\n void material;\n (grant as { material: string }).material = \"\";\n this.emit(handle, \"destroyed\", \"ok\");\n }\n }\n\n /** Scope-narrowing for repo actions: the FULL `owner/name` target must be\n * authorized by the grant's `repositories` (owner-aware \u2014 see\n * {@link repoWithinScope}), and the required permission must be present at write\n * level. A violation throws inside `withGrant` \u2192 revoke-on-failure fires. */\n private assertRepoInScope(\n handle: ActionHandle,\n grant: ResolvedGrant,\n repo: string,\n requiredPermission: \"contents\" | \"pull_requests\",\n ): void {\n const permOk =\n (grant.scope.permissions?.[requiredPermission] ?? \"\") === \"write\";\n if (!permOk || !repoWithinScope(grant.scope, repo)) {\n this.emit(handle, \"denied\", \"failed\", \"scope violation (repo)\");\n throw new BrokerAdapterError(\n \"SCOPE_VIOLATION\",\n `grant does not authorize ${requiredPermission}:write on ${repo}`,\n );\n }\n }\n\n /** Scope-narrowing for cloud actions: the deploy environment must equal the\n * grant's single authorized environment. */\n private assertEnvInScope(\n handle: ActionHandle,\n grant: ResolvedGrant,\n environment: string,\n ): void {\n if ((grant.scope.environment ?? \"\") !== environment) {\n this.emit(handle, \"denied\", \"failed\", \"scope violation (environment)\");\n throw new BrokerAdapterError(\n \"SCOPE_VIOLATION\",\n `grant authorizes environment ${grant.scope.environment ?? \"<none>\"}, not ${environment}`,\n );\n }\n }\n\n private async revoke(handle: ActionHandle, reason: string): Promise<void> {\n try {\n await this.deps.grants.revoke(handle.grantId, reason);\n } catch {\n /* revoke is best-effort \u2014 the grant's short TTL bounds the window anyway */\n }\n this.emit(handle, \"revoked\", \"failed\", reason);\n }\n\n private emit(\n handle: ActionHandle,\n phase: BrokerAuditRow[\"phase\"],\n outcome: BrokerAuditRow[\"outcome\"],\n detail?: string,\n ): void {\n this.audit({\n ts: new Date(this.now()).toISOString(),\n phase,\n handleId: handle.handleId,\n grantId: handle.grantId,\n action: handle.action,\n capabilityId: handle.capabilityId,\n outcome,\n detail,\n });\n }\n}\n\nfunction errText(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n// ---------------------------------------------------------------------------\n// Scraping-resistance: prove a secret NEVER transits an agent-visible surface.\n// ---------------------------------------------------------------------------\n\n/** A named surface the agent (or the MCP transport) can read, for absence scanning. */\nexport interface AgentVisibleSurface {\n name: string;\n /** The surface content as a string (env dump, argv join, MCP transcript, log). */\n content: string;\n}\n\n/**\n * Scan agent-visible surfaces for a literal secret. Returns the names of any surface\n * that LEAKED it (empty = clean). Used by the adversarial + observable-exit proofs:\n * the broker's injection helpers keep the secret out of the agent env, process args,\n * and MCP transport, and this is the grep that proves it.\n */\nexport function scanForSecret(\n secret: string,\n surfaces: AgentVisibleSurface[],\n): string[] {\n if (!secret) return [];\n return surfaces.filter((s) => s.content.includes(secret)).map((s) => s.name);\n}\n\n/**\n * Assert a secret is absent from every agent-visible surface \u2014 throws (fail closed)\n * naming the leaking surface if not. The one-line \"grep proves no secret value ever\n * transits the agent-visible env or MCP transport\" from the M12.5 observable exit.\n */\nexport function assertSecretAbsent(\n secret: string,\n surfaces: AgentVisibleSurface[],\n): void {\n const leaked = scanForSecret(secret, surfaces);\n if (leaked.length > 0) {\n throw new Error(\n `secret leaked into agent-visible surface(s): ${leaked.join(\", \")}`,\n );\n }\n}\n", "/**\n * Production wiring for the M12.5 sandbox-side broker adapters (AGE-175).\n *\n * This is the factory that REPLACES the reference runner's fail-closed no-op seams\n * (`brokerPushCredential` / `createPullRequest`, and the M8 `brokerCloudToken` deploy\n * path) with a broker that OWNS credential injection sandbox-side. It composes the\n * dependency-free {@link SandboxBroker} (from @stacks/sandbox-controller) with a\n * deployment-supplied M4 grant plane:\n *\n * \u2022 {@link DeliveryGrantSource.issueGrant} \u2014 issues an M4 grant for one action +\n * target (server-side `brokerRepoToken` / `brokerCloudToken`); returns only an\n * OPAQUE grant id, never material.\n * \u2022 {@link SandboxBroker}'s `GrantPlane.resolve` \u2014 resolves that grant to material\n * server-side (`resolveGrantForExecution`, single-use ISSUED\u2192USED) and injects it\n * into the ONE authorized process/action, then destroys it.\n *\n * The whole thing is FEATURE-GATED: `createSandboxEgress` / `createDeliveryDeploy`\n * return `undefined` unless `STACKS_SANDBOX_BROKER_ENABLED=1` AND a grant source is\n * supplied \u2014 so a runner with no configured grant plane keeps the exact fail-closed\n * no-op behaviour (the harness runner treats `undefined` as \"use the legacy path\" and\n * a null result as \"defer to the governed path\"). The adapters import ONLY the\n * dependency-free `adapters.js` module (no zod / no @stacks/execution) so the agents\n * package typechecks without pulling the controller's full dependency tree.\n */\nimport {\n SandboxBroker,\n type BrokerAction,\n type DeployResult,\n} from \"../../services/sandbox-controller/src/adapters.js\";\n\nimport type { SandboxEgressBroker } from \"./harness-runner.js\";\n\n/** Whether the sandbox broker is enabled (mirrors the controller's own flag). */\nexport function isSandboxBrokerEnabled(\n env: NodeJS.ProcessEnv = process.env,\n): boolean {\n return env.STACKS_SANDBOX_BROKER_ENABLED === \"1\";\n}\n\n/**\n * Issues M4 grants for the delivery egress actions. A real deployment implements\n * this over the control plane (`brokerRepoToken` for repo:*, `brokerCloudToken` for\n * deploy:*), returning ONLY an opaque grant id \u2014 the material is resolved later, at\n * the broker's injection boundary, by the {@link SandboxBroker}'s grant plane.\n * Returns null to fail closed (frozen / policy deny / provider unconfigured).\n */\nexport interface DeliveryGrantSource {\n issueGrant(req: {\n action: BrokerAction;\n repo?: string;\n environment?: string;\n harnessRunId?: string;\n stageId?: string;\n jobId?: string;\n runId?: string;\n }): Promise<string | null>;\n}\n\n/**\n * Build the harness runner's {@link SandboxEgressBroker} from a {@link SandboxBroker}\n * + an M4 grant source. Returns `undefined` (\u21D2 the runner uses the legacy no-op path)\n * unless the flag is on and a grant source is present. Each call issues a fresh\n * single-use grant, mints an OPAQUE handle for it, and asks the broker to perform the\n * action \u2014 the raw credential never returns to the runner. Any failure fails closed\n * (null) so the runner defers to the governed path, never pushing un-brokered.\n */\nexport function createSandboxEgress(opts: {\n broker: SandboxBroker;\n grants: DeliveryGrantSource;\n env?: NodeJS.ProcessEnv;\n}): SandboxEgressBroker | undefined {\n if (!isSandboxBrokerEnabled(opts.env)) return undefined;\n const { broker, grants } = opts;\n return {\n async push(req) {\n const grantId = await grants\n .issueGrant({\n action: \"repo:push\",\n repo: req.repo,\n harnessRunId: req.harnessRunId,\n stageId: req.stageId,\n })\n .catch(() => null);\n if (!grantId) return null; // fail closed \u2014 defer to the governed path\n const handle = broker.grantHandle({\n action: \"repo:push\",\n capabilityId: `stage:${req.stageId}`,\n grantId,\n target: { repo: req.repo, branch: req.branch },\n });\n try {\n const res = await broker.performPush(handle, {\n cwd: req.cwd,\n branch: req.branch,\n });\n return { pushed: res.pushed };\n } catch {\n return null; // broker failed closed (frozen / scope / injection)\n }\n },\n async openPr(req) {\n const grantId = await grants\n .issueGrant({\n action: \"repo:pr_create\",\n repo: req.repo,\n harnessRunId: req.harnessRunId,\n stageId: req.stageId,\n })\n .catch(() => null);\n if (!grantId) return null;\n const handle = broker.grantHandle({\n action: \"repo:pr_create\",\n capabilityId: `stage:${req.stageId}`,\n grantId,\n target: { repo: req.repo, branch: req.branch },\n });\n try {\n const pr = await broker.performPrCreate(handle, {\n repo: req.repo,\n head: req.branch,\n base: req.baseBranch ?? \"main\",\n title: req.title,\n });\n // A broker that returns an empty PR (e.g. a 2xx with no body) still defers.\n return pr.number > 0 ? { url: pr.url, number: pr.number } : null;\n } catch {\n return null;\n }\n },\n };\n}\n\n/**\n * The M8 cloud-deploy seam, now sandbox-side. `brokerCloudToken` (server) issues the\n * `deploy:production` / `release:rollback` M4 grant; this broker resolves it and\n * injects the Vercel token as a bearer header on the deploy call \u2014 the token never\n * leaves the broker. Returns null (fail closed) when disabled / unconfigured.\n */\nexport function createDeliveryDeploy(opts: {\n broker: SandboxBroker;\n grants: DeliveryGrantSource;\n env?: NodeJS.ProcessEnv;\n}):\n | ((req: {\n projectId: string;\n environment: string;\n commitSha?: string;\n teamId?: string;\n harnessRunId?: string;\n stageId?: string;\n rollback?: boolean;\n }) => Promise<DeployResult | null>)\n | undefined {\n if (!isSandboxBrokerEnabled(opts.env)) return undefined;\n const { broker, grants } = opts;\n return async (req) => {\n const action: BrokerAction = req.rollback\n ? \"release:rollback\"\n : \"deploy:production\";\n const grantId = await grants\n .issueGrant({\n action,\n environment: req.environment,\n harnessRunId: req.harnessRunId,\n stageId: req.stageId,\n })\n .catch(() => null);\n if (!grantId) return null;\n const handle = broker.grantHandle({\n action,\n capabilityId: `deploy:${req.environment}`,\n grantId,\n target: { environment: req.environment },\n });\n try {\n return await broker.performDeploy(handle, {\n projectId: req.projectId,\n environment: req.environment,\n commitSha: req.commitSha,\n teamId: req.teamId,\n });\n } catch {\n return null;\n }\n };\n}\n", "/**\n * Runtime construction of the M12.5 sandbox-side egress broker for the reference\n * runner (AGE-175). Keeps `workflow-runner.ts` thin: it just calls\n * {@link makeSandboxEgress}, which returns `undefined` (\u21D2 the harness runner uses the\n * legacy fail-closed no-op path, unchanged) UNLESS both are true:\n *\n * \u2022 `STACKS_SANDBOX_BROKER_ENABLED=1`, and\n * \u2022 `STACKS_BROKER_GRANT_URL` names the control-plane grant transport.\n *\n * When configured, it wires a real {@link SandboxBroker} (real git + fetch injectors)\n * to an HTTP grant plane. The grant plane issues M4 grants and resolves them to\n * material SERVER-SIDE \u2014 the runner only ever sees opaque grant ids + results, and\n * the broker confines the material to its one injection. The transport is\n * deliberately small and header-authenticated (`STACKS_BROKER_GRANT_TOKEN`).\n */\nimport {\n SandboxBroker,\n fetchHttpInjector,\n spawnGitInjector,\n type BrokerAction,\n type GrantPlane,\n type ResolvedGrant,\n} from \"../../services/sandbox-controller/src/adapters.js\";\n\nimport {\n createSandboxEgress,\n isSandboxBrokerEnabled,\n type DeliveryGrantSource,\n} from \"./sandbox-broker-adapters.js\";\nimport type { SandboxEgressBroker } from \"./harness-runner.js\";\n\n/** The control-plane grant transport: issues + resolves + revokes M4 grants over\n * HTTP. It NEVER returns material to the runner \u2014 only `resolve` (called by the\n * broker at its injection boundary) yields material, server-authenticated. */\nclass HttpGrantPlane implements GrantPlane, DeliveryGrantSource {\n constructor(\n private readonly baseUrl: string,\n private readonly token: string | undefined,\n private readonly fetchFn: typeof fetch = fetch,\n ) {}\n\n private headers(): Record<string, string> {\n return {\n \"content-type\": \"application/json\",\n ...(this.token ? { authorization: `Bearer ${this.token}` } : {}),\n };\n }\n\n async issueGrant(req: {\n action: BrokerAction;\n repo?: string;\n environment?: string;\n harnessRunId?: string;\n stageId?: string;\n jobId?: string;\n runId?: string;\n }): Promise<string | null> {\n const res = await this.fetchFn(`${this.baseUrl}/grants/issue`, {\n method: \"POST\",\n headers: this.headers(),\n body: JSON.stringify(req),\n });\n if (!res.ok) return null; // fail closed (frozen / policy deny / unconfigured)\n const body = (await res.json()) as { grantId?: string };\n return body.grantId ?? null;\n }\n\n async resolve(grantId: string, action: BrokerAction): Promise<ResolvedGrant> {\n const res = await this.fetchFn(`${this.baseUrl}/grants/resolve`, {\n method: \"POST\",\n headers: this.headers(),\n body: JSON.stringify({ grantId, action }),\n });\n if (!res.ok) {\n throw new Error(`grant resolve failed (HTTP ${res.status})`);\n }\n return (await res.json()) as ResolvedGrant;\n }\n\n async revoke(grantId: string, reason: string): Promise<void> {\n await this.fetchFn(`${this.baseUrl}/grants/revoke`, {\n method: \"POST\",\n headers: this.headers(),\n body: JSON.stringify({ grantId, reason }),\n }).catch(() => {});\n }\n}\n\n/**\n * Build the sandbox egress broker for the reference runner, or `undefined` when the\n * flag/transport are not configured (the default \u2014 the runner keeps the legacy\n * fail-closed no-op path). `env`/`fetchFn` are injectable for tests.\n */\nexport function makeSandboxEgress(\n env: NodeJS.ProcessEnv = process.env,\n fetchFn: typeof fetch = fetch,\n): SandboxEgressBroker | undefined {\n if (!isSandboxBrokerEnabled(env)) return undefined;\n const grantUrl = env.STACKS_BROKER_GRANT_URL;\n if (!grantUrl) return undefined; // no grant transport \u2192 fail-closed no-op\n const grants = new HttpGrantPlane(\n grantUrl,\n env.STACKS_BROKER_GRANT_TOKEN,\n fetchFn,\n );\n const broker = new SandboxBroker({\n grants,\n git: spawnGitInjector,\n http: fetchHttpInjector,\n });\n return createSandboxEgress({ broker, grants, env });\n}\n", "/**\n * Optional webhook-less runner scope. An unset scope preserves the historical\n * workspace-wide poller; a configured harness id admits only jobs that prove\n * they belong to that exact run. Generic jobs and other harnesses fail closed.\n */\nexport function pollScopeAllows(\n configuredHarnessRunId: string | undefined,\n jobHarnessRunId: string | null | undefined,\n): boolean {\n const scope = configuredHarnessRunId?.trim();\n if (!scope) return true;\n return jobHarnessRunId === scope;\n}\n\n/** Resolve the run id from either job shape: authoring/decomposition jobs have\n * no stage-level `harness` block yet, while stage jobs carry both forms. */\nexport function jobHarnessRunId(job: {\n harness?: { harnessRunId?: string | null } | null;\n harnessRun?: { id?: string | null } | null;\n}): string | null | undefined {\n return job.harness?.harnessRunId ?? job.harnessRun?.id;\n}\n", "/**\n * run-once.ts \u2014 the exit decision for the runner's once mode (AGE-836).\n *\n * Once mode (STACKS_RUNNER_ONCE=1) lives for the duration of the work it\n * found, then exits; launchd re-spawns it on an interval, so a wedged process\n * can never outlive one respawn cycle the way the immortal poll loop could.\n * The ONLY exit gate is this decision, and both halves are load-bearing:\n *\n * \u2022 `inflight`, never `active` \u2014 the pool gauge that still counts a\n * watchdog-DETACHED orphan turn. Exiting while one runs would kill its\n * SDK session mid-turn; `active` drops to 0 the moment the watchdog frees\n * the slot, `inflight` only on the true settle.\n *\n * \u2022 TWO consecutive idle ticks \u2014 a transition that lands between ticks (a\n * gate side effect draining post-response, a follow-on job minted by the\n * turn that just settled) gets one more look before the process yields\n * the burst to the next spawn. One idle tick would exit into a 2-minute\n * respawn latency for work that was seconds away from discoverable.\n */\n\n/** Structural subset of runner-pool's PoolSnapshot \u2014 all this decision needs. */\nexport interface PoolInflightSnapshot {\n inflight: number;\n}\n\n/** Consecutive idle ticks required before a once-mode process exits. */\nexport const IDLE_TICKS_TO_EXIT = 2;\n\n/**\n * Fold one tick's pool observation into the idle streak: any queued, running,\n * or watchdog-detached work in ANY pool resets the streak to zero; a fully\n * quiet tick extends it. The caller exits at IDLE_TICKS_TO_EXIT.\n */\nexport function nextIdleTicks(\n pools: PoolInflightSnapshot[],\n idleTicks: number,\n): number {\n const busy = pools.some((p) => p.inflight > 0);\n return busy ? 0 : idleTicks + 1;\n}\n", "/**\n * tick-watchdog.ts \u2014 the poll loop's hang detector (AGE-835, corrected AGE-923).\n *\n * AGE-835 raced each tick against a flat 180s timer, so the watchdog measured\n * TOTAL ELAPSED and read every slow tick as a wedge. It is not a hang detector\n * at that budget: one `callTool` can legitimately outlast it, because a\n * RATE_LIMITED reply carries `retryAfterSeconds` up to 60 (the server's bucket\n * is per-minute) and the caller honors it up to four times \u2014 ~244s of\n * DELIBERATE, bounded waiting inside a single supervised call, before the tick's\n * other serial reads are counted at all. That is the \"no completion in 180s on\n * a tick that then succeeds\" observation: the tick was never stuck.\n *\n * A wedge is the absence of PROGRESS, not the presence of duration. So the tick\n * reports each step it finishes and the watchdog fires only when nothing has\n * been reported for `stallMs` \u2014 a genuinely stalled await still trips it (it\n * reports nothing, ever), while a slow-but-live tick no longer does. The last\n * reported step rides in the message, so the next occurrence names the step\n * that overran instead of leaving it to be isolated by hand.\n */\n\nexport interface StallWatchdog {\n /** Report that a step of the supervised work finished. Resets the deadline. */\n progress(step: string): void;\n /** Race `work` against a stall \u2014 NOT against total elapsed time. */\n guard<T>(work: Promise<T>): Promise<T>;\n}\n\nexport function createStallWatchdog(opts: {\n stallMs: number;\n /** How often staleness is sampled. Small values only for tests. */\n checkMs?: number;\n now?: () => number;\n}): StallWatchdog {\n const now = opts.now ?? Date.now;\n const checkMs = opts.checkMs ?? Math.max(1_000, Math.floor(opts.stallMs / 6));\n let lastAt = now();\n let lastStep = \"start\";\n\n return {\n progress(step) {\n lastAt = now();\n lastStep = step;\n },\n guard(work) {\n lastAt = now();\n return Promise.race([\n work,\n new Promise<never>((_, reject) => {\n const timer = setInterval(() => {\n const idleMs = now() - lastAt;\n if (idleMs < opts.stallMs) return;\n clearInterval(timer);\n reject(\n new Error(\n `tick watchdog: no progress for ${Math.round(idleMs / 1000)}s ` +\n `(last completed step: ${lastStep})`,\n ),\n );\n }, checkMs);\n // Deliberately NOT unref'd: a wedged await holds nothing open, so an\n // unref'd sampler would let the loop drain and never fire \u2014 silently\n // absent in exactly the case it exists for. It cannot outlive the\n // tick either, since settling clears it below.\n // Stop sampling when the work settles \u2014 otherwise every tick leaks an\n // interval. The trailing catch keeps a rejected `work` from surfacing\n // twice (the race already delivers it to the caller).\n void work.finally(() => clearInterval(timer)).catch(() => {});\n }),\n ]);\n },\n };\n}\n", "/**\n * Runner revision stamp derivation + the live drift probe (AGE-497).\n *\n * Two halves of one operator complaint: the schema stamp is a hand-maintained\n * value that must equal the control plane's, and a mismatch is SILENT until a\n * claim fails closed with a 409.\n *\n * \u2022 {@link resolveSchemaRevision} \u2014 the stamp is DERIVED from the checkout's\n * newest migration directory when `STACKS_SCHEMA_REVISION` is unset. That is\n * the same value `revisionVerdict` (lib/preflight.ts) already compares\n * against and calls \"the expected value\" \u2014 this uses it instead of asking an\n * operator to hand-copy it. An explicit env value still WINS, because a\n * deliberate pin is what a rollback needs (deploy/RUNBOOK.md).\n * \u2022 {@link probeRevisionHealth} \u2014 asks the control plane's own `/api/health`\n * what it thinks of this runner's stamp, so drift is reported at startup and\n * on a slow timer instead of at the first burnt claim. The endpoint already\n * accepts a worker stamp and answers with the verdict; nothing new server-side.\n *\n * Derivation NEVER hard-fails the runner: an unstamped dev runner against an\n * unstamped dev control plane is legitimate (the compatibility guard is inert),\n * and the probe is the honest oracle for whether `unknown` actually matters here.\n */\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport type { RevisionStamp } from \"../../packages/execution/src/revision.js\";\n\n/**\n * Newest migration id in a `prisma/migrations` listing (they sort lexically).\n *\n * Lives HERE rather than in `preflight.ts` (its original home, which still\n * re-exports it) so the dependency runs one way: preflight consumes the stamp\n * resolution, and the resolution never reaches back into preflight.\n */\nexport function newestMigration(entries: readonly string[]): string | null {\n const dirs = entries.filter((e) => /^\\d{8,}_/.test(e)).sort();\n return dirs.length ? dirs[dirs.length - 1] : null;\n}\n\n/** Where a resolved schema revision came from \u2014 reported in the startup log. */\nexport type SchemaRevisionSource = \"env\" | \"migrations\" | \"none\";\n\nexport interface SchemaRevisionResolution {\n /** The resolved stamp, or null when nothing could be derived. */\n revision: string | null;\n source: SchemaRevisionSource;\n /** A legible one-liner for the startup log. */\n detail: string;\n}\n\n/**\n * The migrations directory of the RUNNER'S OWN tree, resolved from this module's\n * location (`agents/lib/` \u2192 repo root) rather than from cwd or configuration.\n *\n * Deliberately NOT the configured `STACKS_RUNNER_REPOS` checkout, which is the\n * repo the runner drives STAGES in \u2014 a different working copy that legitimately\n * sits at a different commit, and that need not be a Jentrix repo at all (a target\n * project with no `prisma/migrations` would derive nothing and silently present\n * `unknown`, failing every claim closed). The schema stamp describes the contract\n * THIS runner's code was built against, which is the same tree the app stamp's\n * `git rev-parse HEAD` reads.\n */\nexport function runnerMigrationsDir(\n moduleUrl: string = import.meta.url,\n): string {\n return path.resolve(\n path.dirname(fileURLToPath(moduleUrl)),\n \"../../prisma/migrations\",\n );\n}\n\n/**\n * Resolve the schema revision this runner should present. PURE apart from the\n * injected `listDir` seam.\n *\n * An explicit `STACKS_SCHEMA_REVISION` wins \u2014 a deliberate pin is what a rollback\n * needs; otherwise the newest migration directory IS the value, which is exactly\n * what `revisionVerdict` already compares a hand-set stamp against.\n */\nexport function resolveSchemaRevision(\n env: Record<string, string | undefined>,\n listDir: (path: string) => string[],\n migrationsDir: string = runnerMigrationsDir(),\n): SchemaRevisionResolution {\n const explicit = (env.STACKS_SCHEMA_REVISION ?? \"\").trim();\n if (explicit) {\n return {\n revision: explicit,\n source: \"env\",\n detail: `STACKS_SCHEMA_REVISION=${explicit} (explicit \u2014 derivation skipped)`,\n };\n }\n\n let entries: string[];\n try {\n entries = listDir(migrationsDir);\n } catch {\n entries = [];\n }\n const newest = newestMigration(entries);\n return newest\n ? {\n revision: newest,\n source: \"migrations\",\n detail: `derived ${newest} from ${migrationsDir}`,\n }\n : {\n revision: null,\n source: \"none\",\n detail: `no migration directories under ${migrationsDir} \u2014 presenting 'unknown', which a stamped control plane refuses fail-closed`,\n };\n}\n\n/** The control plane's revision probe URL for a given MCP endpoint + stamp. PURE. */\nexport function healthUrlFor(mcpUrl: string, stamp: RevisionStamp): string {\n const url = new URL(\"/api/health\", mcpUrl);\n url.searchParams.set(\"schemaRevision\", stamp.schemaRevision);\n url.searchParams.set(\"appRevision\", stamp.appRevision);\n return url.toString();\n}\n\nexport type RevisionProbeStatus =\n | \"ok\"\n | \"incompatible\"\n | \"unstamped\"\n | \"unreachable\";\n\nexport interface RevisionProbeResult {\n status: RevisionProbeStatus;\n message: string;\n}\n\n/** Interpret an `/api/health` body. PURE \u2014 the fetch seam lives in the caller. */\nexport function readProbeBody(body: unknown): RevisionProbeResult {\n const revision =\n body && typeof body === \"object\"\n ? ((body as Record<string, unknown>).revision as\n | Record<string, unknown>\n | undefined)\n : undefined;\n const status = revision?.status;\n const message = revision?.message;\n if (status === \"ok\" || status === \"incompatible\" || status === \"unstamped\") {\n return {\n status,\n message:\n typeof message === \"string\" && message.trim()\n ? message\n : `control plane reported ${status}`,\n };\n }\n return {\n status: \"unreachable\",\n message: \"control plane /api/health returned an unrecognized body\",\n };\n}\n\n/**\n * Ask the control plane whether THIS runner's stamp is compatible. Never throws\n * and never blocks a start: an unreachable probe reports `unreachable` \u2014 the\n * claim guard remains the authority, this only makes its verdict early and loud.\n */\nexport async function probeRevisionHealth(opts: {\n mcpUrl: string;\n stamp: RevisionStamp;\n fetchImpl?: typeof fetch;\n timeoutMs?: number;\n}): Promise<RevisionProbeResult> {\n const doFetch = opts.fetchImpl ?? fetch;\n try {\n const res = await doFetch(healthUrlFor(opts.mcpUrl, opts.stamp), {\n signal: AbortSignal.timeout(opts.timeoutMs ?? 5_000),\n });\n return readProbeBody(await res.json());\n } catch (err) {\n return {\n status: \"unreachable\",\n message: `could not reach the control plane revision probe: ${\n err instanceof Error ? err.message : String(err)\n }`,\n };\n }\n}\n", "/**\n * `pnpm harness:preflight` \u2014 prove the runner can actually run a stage BEFORE a\n * claim burns (Harness Reliability W6).\n *\n * Bring-up cost about two hours of live debugging on the M18 run, and not one\n * failure was novel: an expired grant, a repo path that moved, a schema stamp\n * nobody re-bumped after a migration, a stopped verification container, a model\n * pin the release would refuse. Each one surfaced as a claim failing mid-flight,\n * minutes apart, with the diagnosis buried in runner logs.\n *\n * Every check here shells out to the same thing the runbook already names \u2014 no\n * new infrastructure, no new state. Decisions are PURE (`renderTable`,\n * `exitCodeFor`, the individual predicates); everything that touches the world is\n * injected, so the smoke test drives the whole table with stubs.\n *\n * Honesty rules, same as the evidence contract: a check that cannot run reports\n * SKIP with the reason, never PASS. A check that FAILS exits non-zero. WARN is\n * for a real observation that is not a blocker (a checkout trailing origin).\n */\nimport { parseRunnerRepos } from \"./harness-worktree.js\";\nimport {\n newestMigration,\n resolveSchemaRevision,\n runnerMigrationsDir,\n type SchemaRevisionResolution,\n} from \"./revision-stamp.js\";\n\n// Re-exported from its new home so existing importers (and the smoke test) are\n// unaffected by the move that broke the preflight \u2194 revision-stamp cycle.\nexport { newestMigration };\n\nexport type CheckStatus = \"PASS\" | \"FAIL\" | \"WARN\" | \"SKIP\";\n\nexport interface CheckResult {\n name: string;\n status: CheckStatus;\n detail: string;\n}\n\nexport interface PreflightDeps {\n env: Record<string, string | undefined>;\n /** Resolve a role's bearer (exercises the D4 bootstrap grant on self-hosted). */\n resolveToken: (role: \"runner\" | \"planner\" | \"reviewer\") => Promise<string>;\n /** List the MCP tool names the endpoint exposes to this bearer. */\n listTools: (token: string) => Promise<string[]>;\n /** Call one MCP tool (used for the identity probe). */\n callTool: (\n token: string,\n name: string,\n args: Record<string, unknown>,\n ) => Promise<Record<string, unknown>>;\n git: (cwd: string, args: string[]) => Promise<string>;\n exists: (path: string) => boolean;\n /** Directory listing (used to read the repo's migration ids). */\n listDir: (path: string) => string[];\n /** Prove the managed verification substrate can start a container. */\n verificationPreflight: () => Promise<void>;\n /** TCP reachability probe for the codex bridge. */\n probeTcp: (host: string, port: number) => Promise<boolean>;\n /** Is the claim URL answering? MUST NOT redeem anything \u2014 the self-hosted\n * bootstrap grant is one-time, and spending it here would break the very\n * runner start this command exists to protect. */\n probeClaimUrl: (url: string) => Promise<boolean>;\n}\n\n// --- Pure predicates --------------------------------------------------------\n\n/** Env keys without which the runner cannot start at all. */\nexport const REQUIRED_ENV = [\n \"STACKS_MCP_URL\",\n \"STACKS_RUNNER_REPOS\",\n \"STACKS_RUNNER_MODE\",\n] as const;\n\nexport function missingEnv(env: PreflightDeps[\"env\"]): string[] {\n return REQUIRED_ENV.filter((k) => !(env[k] ?? \"\").trim());\n}\n\n/**\n * The schema revision the runner PRESENTS on every claim must match the schema\n * the control plane was built against, or the fail-closed claim guard refuses\n * every claim.\n *\n * Since AGE-497 the stamp DERIVES from this runner tree's newest migration\n * directory, so the healthy state carries no explicit value at all and there is\n * nothing to re-stamp \u2014 this check exists for the two states that are still\n * wrong: nothing derivable (presenting 'unknown', which a stamped control plane\n * refuses), and an explicit PIN that has fallen behind the repo. A pin is\n * legitimate for a rollback, so a stale one is reported as a pin to release,\n * never as a value to hand-bump.\n */\nexport function revisionVerdict(\n resolution: SchemaRevisionResolution,\n latestMigration: string | null,\n): CheckResult {\n const name = \"schema revision\";\n if (resolution.source === \"none\") {\n return {\n name,\n status: \"FAIL\",\n detail: `${resolution.detail} \u2014 a stamped control plane refuses every claim fail-closed.`,\n };\n }\n if (resolution.source === \"migrations\") {\n return {\n name,\n status: \"PASS\",\n detail: `derived ${resolution.revision} (no explicit stamp; nothing to re-stamp)`,\n };\n }\n const stamped = resolution.revision as string;\n if (!latestMigration) {\n return {\n name,\n status: \"SKIP\",\n detail: `pinned to ${stamped}; could not read prisma/migrations to compare`,\n };\n }\n return stamped === latestMigration\n ? {\n name,\n status: \"PASS\",\n detail: `${stamped} (explicit pin, matches the newest migration)`,\n }\n : {\n name,\n status: \"FAIL\",\n detail: `STACKS_SCHEMA_REVISION is explicitly pinned to ${stamped} but this tree's newest migration is ${latestMigration}. Unset it to derive the stamp (the default), or move the pin if you are deliberately holding a rollback. Every claim fails closed until it matches the control plane.`,\n };\n}\n\n/**\n * What a claim will PRESENT: the per-leg model pins plus the accepted-models set\n * built exactly the way `claimPresentation`/`workerCapabilities` build it \u2014 the\n * launched model is always vouched for, and a Claude claim additionally vouches\n * for BOTH leg pins.\n *\n * INFORMATIONAL by design. It reports rather than fails, because a pin missing\n * from `STACKS_*_ACCEPTED_MODELS` is *not* a refusal cause (the worker vouches\n * for what it launches), and the check that does have teeth \u2014 pin vs. the ACTIVE\n * RELEASE's pinned model \u2014 is run-scoped and already enforced server-side at\n * launch. Reporting the resolved pins is still worth a row: a silent model change\n * must be diagnosable from the ledger, and this is where an operator sees which\n * models the next claim will actually present.\n */\nexport function modelPinVerdict(env: PreflightDeps[\"env\"]): CheckResult {\n const list = (raw: string | undefined): string[] =>\n (raw ?? \"\")\n .split(/[,\\s]+/)\n .map((s) => s.trim())\n .filter(Boolean);\n const planner = (\n env.STACKS_PLANNER_MODEL ??\n env.STACKS_AGENT_MODEL ??\n \"\"\n ).trim();\n const executor = (\n env.STACKS_EXECUTOR_MODEL ??\n env.STACKS_AGENT_MODEL ??\n \"\"\n ).trim();\n const codex = (env.STACKS_CODEX_MODEL ?? \"\").trim();\n const pins = [\n planner && `planner=${planner}`,\n executor && `executor=${executor}`,\n codex && `codex=${codex}`,\n ].filter(Boolean);\n if (pins.length === 0) {\n return {\n name: \"model pins\",\n status: \"SKIP\",\n detail: \"no model pins configured \u2014 the provider default applies\",\n };\n }\n // Mirror the claim's vouching rule so the row shows the ACTUAL presented set.\n const vouched = new Set([\n ...list(env.STACKS_CLAUDE_ACCEPTED_MODELS),\n ...list(env.STACKS_CODEX_ACCEPTED_MODELS),\n ...[planner, executor, codex].filter(Boolean),\n ]);\n return {\n name: \"model pins\",\n status: \"PASS\",\n detail: `${pins.join(\", \")} \u00B7 vouched: ${[...vouched].join(\", \")}`,\n };\n}\n\n/**\n * Normalize a git remote URL to a lowercase `owner/name`, or null when it is not\n * a recognizable GitHub-style remote. PURE.\n *\n * The HOST is deliberately not compared. The push path builds its own URL from\n * the trusted `owner`/`name` (services/sandbox-controller/src/adapters.ts), so\n * the local remote's host is not what gets pushed to, and comparing it would\n * false-positive an SSH-vs-HTTPS or GHE-vs-github.com checkout.\n */\nexport function normalizeRemoteRepo(url: string): string | null {\n const raw = url.trim();\n if (!raw) return null;\n // scp-like: git@github.com:owner/name.git (no scheme, colon-separated path).\n const scp = /^[^/]+@([^:/]+):(.+)$/.exec(raw);\n let pathPart: string;\n if (scp) {\n pathPart = scp[2];\n } else {\n try {\n pathPart = new URL(raw).pathname;\n } catch {\n return null;\n }\n }\n const trimmed = pathPart\n .replace(/\\/+$/, \"\")\n .replace(/\\.git$/, \"\")\n .split(\"/\")\n .filter(Boolean);\n if (trimmed.length < 2) return null;\n return `${trimmed[0]}/${trimmed[1]}`.toLowerCase();\n}\n\n/**\n * Does the checkout's `origin` actually point at the repo it is mapped to?\n *\n * Weak by construction and that is worth stating: a SECOND clone of the SAME\n * repository passes this. It guards against a genuinely wrong repository, not\n * against the wrong copy of the right one \u2014 {@link checkoutBranchVerdict} and\n * {@link freshnessVerdict} are what catch that.\n *\n * `remote` is raw `git remote get-url origin` output, or null when there is no\n * origin at all \u21D2 SKIP: a check that cannot run never reports PASS, and a\n * local-only checkout cannot break execution (worktrees branch from local refs\n * and push builds its own URL). PURE.\n */\nexport function remoteIdentityVerdict(\n name: string,\n repo: string,\n remote: string | null,\n): CheckResult {\n if (remote === null || !remote.trim()) {\n return {\n name,\n status: \"SKIP\",\n detail: \"no origin remote \u2014 cannot verify the checkout's repository\",\n };\n }\n const actual = normalizeRemoteRepo(remote);\n if (!actual) {\n return {\n name,\n status: \"SKIP\",\n detail: `origin ${remote.trim()} is not a recognizable GitHub-style remote \u2014 cannot verify`,\n };\n }\n return actual === repo.toLowerCase()\n ? { name, status: \"PASS\", detail: `origin is ${actual}` }\n : {\n name,\n status: \"FAIL\",\n detail: `mapped to ${repo} but origin is ${actual} \u2014 STACKS_RUNNER_REPOS points at the wrong repository`,\n };\n}\n\n/** Stage branches are `harness/\u2026`; a SOURCE checkout must never be parked on one. */\nconst STAGE_BRANCH_PREFIX = \"harness/\";\n\n/**\n * Is the checkout on a branch a runner may ground stages from? PURE.\n *\n * `head` is `git symbolic-ref --short -q HEAD` output (\"\" \u21D2 detached).\n *\n * This is the row that catches the AGE-497 incident. A source checkout parked on\n * a stage branch is never legitimate: `refreshGroundingCheckout` fast-forwards it\n * to the base and every stage worktree is cut from it, so a `harness/` HEAD means\n * the checkout is a spent execution tree, not a base.\n */\nexport function checkoutBranchVerdict(\n name: string,\n head: string,\n base: string,\n): CheckResult {\n const branch = head.trim();\n if (!branch) {\n return {\n name,\n status: \"FAIL\",\n detail:\n \"checkout is in detached HEAD \u2014 a runner cannot ground stages from it\",\n };\n }\n if (branch.startsWith(STAGE_BRANCH_PREFIX)) {\n return {\n name,\n status: \"FAIL\",\n detail: `checkout is parked on stage branch ${branch} \u2014 this is a spent execution tree, not a base. Point STACKS_RUNNER_REPOS at a checkout tracking ${base}.`,\n };\n }\n return branch === base\n ? { name, status: \"PASS\", detail: `on ${branch}` }\n : {\n name,\n status: \"WARN\",\n detail: `on ${branch}, not the base branch ${base} \u2014 stages will branch from it`,\n };\n}\n\n/**\n * Is the checkout current with its upstream? PURE.\n *\n * FAILS when the fetch SUCCEEDED (a real, current lag \u2014 the runtime path already\n * throws on exactly this in `refreshGroundingCheckout`, so a WARN here while the\n * live path throws is an inconsistency, not a policy). Stays a WARN when the\n * fetch failed, because the number then came off a stale cached ref and an\n * offline machine must not be blocked on evidence it could not gather.\n */\nexport function freshnessVerdict(\n name: string,\n cwd: string,\n behind: number,\n fetched: boolean,\n upstream: string,\n): CheckResult {\n if (behind <= 0) {\n return {\n name,\n status: \"PASS\",\n detail: `${cwd}: current with ${upstream}${fetched ? \"\" : \" (fetch failed \u2014 number may be stale)\"}`,\n };\n }\n return fetched\n ? {\n name,\n status: \"FAIL\",\n detail: `${cwd}: ${behind} commit(s) behind ${upstream} \u2014 stages would branch from an older base. Pull it, then restart the runner.`,\n }\n : {\n name,\n status: \"WARN\",\n detail: `${cwd}: ${behind} commit(s) behind ${upstream} (fetch failed \u2014 number may be stale)`,\n };\n}\n\n/** Fixed-width PASS/FAIL table. PURE. */\nexport function renderTable(rows: readonly CheckResult[]): string {\n const width = Math.max(4, ...rows.map((r) => r.name.length));\n const lines = rows.map(\n (r) => `${r.status.padEnd(4)} ${r.name.padEnd(width)} ${r.detail}`,\n );\n const failed = rows.filter((r) => r.status === \"FAIL\").length;\n const warned = rows.filter((r) => r.status === \"WARN\").length;\n const skipped = rows.filter((r) => r.status === \"SKIP\").length;\n return [\n ...lines,\n \"\",\n failed\n ? `${failed} check(s) FAILED \u2014 fix the rows above before starting the runner.`\n : `All checks passed${warned ? ` (${warned} warning(s))` : \"\"}${\n skipped ? `, ${skipped} skipped` : \"\"\n }.`,\n ].join(\"\\n\");\n}\n\n/** Non-zero when ANY check failed. PURE. */\nexport function exitCodeFor(rows: readonly CheckResult[]): number {\n return rows.some((r) => r.status === \"FAIL\") ? 1 : 0;\n}\n\n// --- The checks -------------------------------------------------------------\n\nasync function attempt(\n name: string,\n fn: () => Promise<CheckResult>,\n): Promise<CheckResult> {\n try {\n return await fn();\n } catch (e) {\n return {\n name,\n status: \"FAIL\",\n detail: e instanceof Error ? e.message : String(e),\n };\n }\n}\n\n/** Every check, in the order an operator debugs them. */\nexport async function runPreflight(\n deps: PreflightDeps,\n): Promise<CheckResult[]> {\n const rows: CheckResult[] = [];\n const env = deps.env;\n\n const missing = missingEnv(env);\n rows.push(\n missing.length\n ? {\n name: \"environment\",\n status: \"FAIL\",\n detail: `missing ${missing.join(\", \")}`,\n }\n : {\n name: \"environment\",\n status: \"PASS\",\n detail: `mode=${env.STACKS_RUNNER_MODE}, mcp=${env.STACKS_MCP_URL}`,\n },\n );\n\n // The runner credential.\n //\n // On a SELF-HOSTED runner the bootstrap grant is ONE-TIME: the first claim\n // spends it and rotates to an in-process refresh credential. So resolving a\n // bearer here would consume the very grant the runner is about to need, and\n // the runner would then fail to start \u2014 a preflight that breaks the thing it\n // is checking. (Observed on the first live run of this command, 2026-07-27.)\n // The endpoint is probed for reachability instead, and the row says plainly\n // that grant validity was NOT proven. On the MANAGED path the exchange is\n // repeatable, so the bearer is really resolved.\n let runnerToken: string | null = null;\n const selfHosted = /^self-?hosted$/i.test(env.STACKS_RUNNER_MODE ?? \"\");\n rows.push(\n await attempt(\"runner credential\", async () => {\n if (selfHosted) {\n const claimUrl = (env.STACKS_CLAIM_URL ?? \"\").trim();\n if (!claimUrl || !(env.STACKS_BOOTSTRAP_TOKEN ?? \"\").trim()) {\n return {\n name: \"runner credential\",\n status: \"FAIL\",\n detail:\n \"self-hosted mode needs STACKS_BOOTSTRAP_TOKEN + STACKS_CLAIM_URL \u2014 mint a grant with POST /api/agents/bootstrap\",\n };\n }\n const reachable = await deps.probeClaimUrl(claimUrl);\n return reachable\n ? {\n name: \"runner credential\",\n status: \"SKIP\",\n detail:\n \"claim URL is reachable; the bootstrap grant is ONE-TIME so it is deliberately NOT redeemed here (redeeming would spend the grant the runner needs). Mint a fresh grant immediately before starting the runner.\",\n }\n : {\n name: \"runner credential\",\n status: \"FAIL\",\n detail: `claim URL ${claimUrl} is unreachable \u2014 the runner cannot obtain any role token`,\n };\n }\n runnerToken = await deps.resolveToken(\"runner\");\n return {\n name: \"runner credential\",\n status: \"PASS\",\n detail: `resolved a ${env.STACKS_RUNNER_MODE ?? \"?\"} runner bearer (${runnerToken.slice(0, 4)}\u2026)`,\n };\n }),\n );\n\n // The endpoint probe uses a read token when one is configured, so the MCP and\n // workspace rows stay meaningful on the self-hosted path without spending the\n // one-time grant above.\n const probeToken = runnerToken ?? (env.STACKS_TOKEN ?? \"\").trim() ?? null;\n rows.push(\n await attempt(\"MCP surface\", async () => {\n if (!probeToken) {\n return {\n name: \"MCP surface\",\n status: \"SKIP\",\n detail:\n \"no bearer available to probe with (the one-time grant is not spent here; set STACKS_TOKEN for a read-only probe)\",\n };\n }\n const tools = await deps.listTools(probeToken);\n return tools.length > 0\n ? {\n name: \"MCP surface\",\n status: \"PASS\",\n detail: `${tools.length} tools at ${env.STACKS_MCP_URL}`,\n }\n : {\n name: \"MCP surface\",\n status: \"FAIL\",\n detail: \"the endpoint exposed ZERO tools to this bearer\",\n };\n }),\n );\n\n rows.push(\n await attempt(\"workspace access\", async () => {\n if (!probeToken) {\n return {\n name: \"workspace access\",\n status: \"SKIP\",\n detail: \"no bearer available to probe with\",\n };\n }\n const res = (await deps.callTool(probeToken, \"list_workspaces\", {})) as {\n workspaces?: Array<{ slug?: string }>;\n };\n const slugs = (res.workspaces ?? []).map((w) => w.slug).filter(Boolean);\n return slugs.length\n ? {\n name: \"workspace access\",\n status: \"PASS\",\n detail: slugs.join(\", \"),\n }\n : {\n name: \"workspace access\",\n status: \"FAIL\",\n detail: \"the bearer authenticated but sees no workspace\",\n };\n }),\n );\n\n rows.push(...(await checkRepos(deps)));\n\n rows.push(\n await attempt(\"schema revision\", async () => {\n // The runner's OWN tree, never the configured work checkout \u2014 that one\n // legitimately sits at another commit and need not be a Jentrix repo at\n // all. Same resolution the runner presents on every claim.\n const dir = runnerMigrationsDir();\n const resolution = resolveSchemaRevision(\n env,\n (p) => safeList(deps, p),\n dir,\n );\n return revisionVerdict(resolution, newestMigration(safeList(deps, dir)));\n }),\n );\n\n rows.push(modelPinVerdict(env));\n\n rows.push(\n await attempt(\"verification substrate\", async () => {\n await deps.verificationPreflight();\n return {\n name: \"verification substrate\",\n status: \"PASS\",\n detail: `${env.STACKS_VERIFICATION_IMAGE ?? \"default image\"} started a container`,\n };\n }),\n );\n\n rows.push(await checkCodexBridge(deps));\n\n return rows;\n}\n\n/**\n * The narrow slice of {@link PreflightDeps} the repo checks actually touch, so\n * the RUNNER can call {@link checkRepos} at start-up without assembling the whole\n * preflight surface (tokens, docker, TCP probes).\n */\nexport type RepoCheckDeps = Pick<PreflightDeps, \"env\" | \"exists\" | \"git\">;\n\n/**\n * Downgrade the checkout-state FAILs to WARN. Exists because a developer\n * debugging a stage in place has a legitimately `harness/`-parked checkout, and\n * a guard with no hatch gets worked around by reverting the guard.\n */\nexport const STALE_CHECKOUT_OVERRIDE = \"STACKS_RUNNER_ALLOW_STALE_CHECKOUT\";\n\n/**\n * The two row kinds {@link STALE_CHECKOUT_OVERRIDE} may soften. Everything else\n * stays FAIL under the override: a wrong repository, a missing checkout, or an\n * unparseable `STACKS_RUNNER_REPOS` is never made correct by local debugging.\n */\nconst DOWNGRADABLE_ROW_SUFFIXES = [\" branch\", \" freshness\"] as const;\n\n/** Apply {@link STALE_CHECKOUT_OVERRIDE} to a row set. PURE. */\nexport function applyStaleCheckoutOverride(\n rows: readonly CheckResult[],\n enabled: boolean,\n): CheckResult[] {\n if (!enabled) return [...rows];\n return rows.map((r) =>\n r.status === \"FAIL\" &&\n DOWNGRADABLE_ROW_SUFFIXES.some((suffix) => r.name.endsWith(suffix))\n ? {\n ...r,\n status: \"WARN\" as const,\n detail: `${r.detail} [${STALE_CHECKOUT_OVERRIDE}=1 \u2014 downgraded]`,\n }\n : r,\n );\n}\n\n/**\n * Validate every configured checkout. Exported because the runner runs this at\n * start-up and REFUSES to start on a FAIL \u2014 the AGE-497 lesson is that a check\n * living only in a manually-invoked command is a check nobody runs.\n */\nexport async function checkRepos(deps: RepoCheckDeps): Promise<CheckResult[]> {\n const raw = safeJson(deps.env.STACKS_RUNNER_REPOS);\n let repos: ReturnType<typeof parseRunnerRepos>;\n try {\n repos = parseRunnerRepos(raw);\n } catch (e) {\n return [\n {\n name: \"repos\",\n status: \"FAIL\",\n detail: e instanceof Error ? e.message : String(e),\n },\n ];\n }\n const entries = Object.entries(repos);\n if (entries.length === 0) {\n return [\n { name: \"repos\", status: \"FAIL\", detail: \"STACKS_RUNNER_REPOS is empty\" },\n ];\n }\n const rows: CheckResult[] = [];\n for (const [repo, entry] of entries) {\n const name = `repo ${repo}`;\n const cwd = entry.config.checkout;\n if (!deps.exists(cwd)) {\n rows.push({\n name,\n status: \"FAIL\",\n detail: `checkout ${cwd} does not exist`,\n });\n continue;\n }\n const gitOut = async (args: string[]): Promise<string> =>\n (await deps.git(cwd, args).catch(() => \"\")).trim();\n\n rows.push(\n await attempt(`${name} branch`, async () => {\n const inside = await gitOut([\"rev-parse\", \"--is-inside-work-tree\"]);\n if (inside !== \"true\") {\n return {\n name,\n status: \"FAIL\",\n detail: `${cwd} is not a git checkout`,\n };\n }\n // The REPO's default branch, from origin/HEAD \u2014 never the current\n // branch's upstream. A checkout parked on a stage branch tracks that\n // stage branch, so deriving the base from the upstream would advise the\n // operator to \"track harness/\u2026-stage-9\", which is the broken state\n // itself. Not every clone has origin/HEAD set, hence the fallback.\n const base =\n (\n await gitOut([\n \"symbolic-ref\",\n \"--short\",\n \"refs/remotes/origin/HEAD\",\n ])\n ).replace(/^origin\\//, \"\") || \"main\";\n const head = await gitOut([\"symbolic-ref\", \"--short\", \"-q\", \"HEAD\"]);\n return checkoutBranchVerdict(`${name} branch`, head, base);\n }),\n );\n\n rows.push(\n await attempt(`${name} origin`, async () =>\n remoteIdentityVerdict(\n `${name} origin`,\n repo,\n (await gitOut([\"remote\", \"get-url\", \"origin\"])) || null,\n ),\n ),\n );\n\n rows.push(\n await attempt(`${name} freshness`, async () => {\n const upstream =\n (await gitOut([\"rev-parse\", \"--abbrev-ref\", \"@{upstream}\"])) ||\n \"origin/main\";\n // Fetching is what makes the freshness number mean anything; an offline\n // machine still gets a comparison against whatever ref it has.\n let fetched = true;\n try {\n await deps.git(cwd, [\"fetch\", \"--quiet\", \"origin\"]);\n } catch {\n fetched = false;\n }\n const behind = await gitOut([\n \"rev-list\",\n \"--count\",\n `HEAD..${upstream}`,\n ]);\n return freshnessVerdict(\n `${name} freshness`,\n cwd,\n Number(behind) || 0,\n fetched,\n upstream,\n );\n }),\n );\n }\n return rows;\n}\n\nasync function checkCodexBridge(deps: PreflightDeps): Promise<CheckResult> {\n const name = \"codex bridge\";\n const provider = (deps.env.STACKS_AGENT_PROVIDER ?? \"\").trim();\n const port = Number(deps.env.STACKS_CODEX_BRIDGE_PORT ?? 8791);\n const usesCodex =\n provider === \"codex\" || Boolean((deps.env.STACKS_CODEX_MODEL ?? \"\").trim());\n if (!usesCodex) {\n return { name, status: \"SKIP\", detail: \"no codex leg configured\" };\n }\n const up = await deps.probeTcp(\"127.0.0.1\", port).catch(() => false);\n return up\n ? { name, status: \"PASS\", detail: `answering on 127.0.0.1:${port}` }\n : {\n name,\n status: \"FAIL\",\n detail: `nothing answering on 127.0.0.1:${port} \u2014 start it with \\`pnpm --dir agents codex-provider-bridge\\``,\n };\n}\n\nfunction safeJson(raw: string | undefined): unknown {\n if (!raw?.trim()) return null;\n try {\n return JSON.parse(raw);\n } catch {\n throw new Error(\"STACKS_RUNNER_REPOS is not valid JSON\");\n }\n}\n\nfunction safeList(deps: PreflightDeps, path: string): string[] {\n try {\n return deps.listDir(path);\n } catch {\n return [];\n }\n}\n"],
|
|
5
|
-
"mappings": "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",
|
|
4
|
+
"sourcesContent": ["/**\n * Workflow runner (M7) \u2014 drives the plan \u2192 review \u2192 execute \u2192 review loop.\n *\n * Jentrix fires `agent.handoff` (HMAC-signed) on every turn\n * \u2192 this receiver verifies the signature\n * \u2192 claims the turn with the RUNNER admin token (claim_agent_job \u2192 runId)\n * \u2192 spawns the role runtime (Claude planner/executor, Codex reviewer) with\n * the ROLE token and the stacks-review-loop skill, passing the runId\n * \u2192 heartbeats the run while the session works; fails it on a provider error\n *\n * Two principals, by design: the runner's ADMIN token does claim/heartbeat/fail;\n * each session uses its ROLE token so the server-side turn-guard (planner submits\n * plans, reviewer submits reviews) passes. Configure both below.\n *\n * Setup: create a webhook for the `agent.handoff` event pointing at this server\n * and put its secret in STACKS_WEBHOOK_SECRET.\n *\n * AUTH (M12.4b, AGE-174; standing PATs deleted 2026-07, D4/AGE-509) \u2014 role\n * tokens (runner/planner/reviewer) are provisioned by a mode-selected provider\n * (`lib/runner-auth.ts`), refreshed at each drive so short-lived tokens never\n * expire mid-server. Select with STACKS_RUNNER_MODE (required):\n * managed \u2014 workload identity + per-run capability tokens (M12.4a); ZERO\n * standing PATs (STACKS_TOKEN_EXCHANGE_URL + STACKS_WORKLOAD_SVID\n * + STACKS_RUN_ID + STACKS_WORKSPACE_ID).\n * self-hosted \u2014 the M11.1 bootstrap + claim-URL flow: a one-time bootstrap\n * token redeemed at a claim URL for short-lived role tokens\n * (STACKS_BOOTSTRAP_TOKEN + STACKS_CLAIM_URL). No standing PAT.\n * Other env:\n * STACKS_MCP_URL \u2014 defaults to http://localhost:3000/api/mcp\n * STACKS_CODEX_MODEL \u2014 reviewer (Codex) model pin; default gpt-5.5. The\n * codex binary reads ~/.codex/config.toml as base\n * config, so the runner always pins model + effort\n * (STACKS_CODEX_EFFORT, default medium) explicitly.\n * STACKS_RUNNER_REPOS \u2014 optional JSON map \"owner/name\" -> local checkout\n * STACKS_POLL_MS \u2014 > 0 enables webhook-less POLL mode (drives the\n * same loop by polling; use when the Jentrix\n * deployment cannot reach this machine \u2014 its SSRF\n * guard rightly refuses localhost webhook targets)\n * Run: pnpm workflow-runner (listens on PORT, default 8788)\n */\nimport { createHmac, timingSafeEqual } from \"node:crypto\";\nimport { spawn } from \"node:child_process\";\nimport { existsSync, readdirSync } from \"node:fs\";\nimport { createServer } from \"node:http\";\nimport { setTimeout as delay } from \"node:timers/promises\";\n\nimport { Client } from \"@modelcontextprotocol/sdk/client/index.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\n\nimport { agentProvider, runJentrixAgent } from \"./lib/jentrix.js\";\nimport type { AgentTurnUsage } from \"./lib/jentrix.js\";\nimport { claudeLegModel } from \"./lib/providers/claude.js\";\nimport { codexModel } from \"./lib/providers/codex.js\";\nimport { workerCapabilities } from \"./lib/providers/capabilities.js\";\nimport { RUNNER_VERSION } from \"./lib/version.js\";\nimport {\n makeExecutionBackend,\n preflightManagedVerification,\n runManagedVerificationCommand,\n runTurnThroughBackend,\n} from \"./lib/execution.js\";\nimport { resolveRevisionStamp } from \"../packages/execution/src/revision.js\";\nimport {\n assertBearerPresent,\n resolveRunnerAuth,\n type RunnerRole,\n type RunnerTokenProvider,\n} from \"./lib/runner-auth.js\";\nimport { rememberTokenRole, roleForKnownToken } from \"./lib/token-roles.js\";\nimport {\n claimPresentation,\n DEFAULT_RUNNER_EVIDENCE_TIER,\n driveHarnessStage,\n driveHarnessStageCommit,\n getHarnessStageJob,\n listStageStatuses,\n resolveStageBranch,\n type HarnessRunnerConfig,\n type HarnessRunnerDeps,\n type RunGit,\n} from \"./lib/harness-runner.js\";\nimport {\n checkoutMap,\n parseRunnerRepos,\n RunnerWorktreeManager,\n type OwnerVerdict,\n type OwnerStateReader,\n} from \"./lib/harness-worktree.js\";\nimport { buildProjectContext } from \"./lib/project-context.js\";\nimport { loadRubric } from \"./lib/rubrics.js\";\nimport { repoAccessForRole } from \"./lib/role-repo-access.js\";\nimport { makeSandboxEgress } from \"./lib/sandbox-broker-runtime.js\";\nimport {\n BoundedDedupPool,\n parseBoundedMax,\n parsePositiveInt,\n} from \"./lib/runner-pool.js\";\nimport { jobHarnessRunId, pollScopeAllows } from \"./lib/poll-scope.js\";\nimport { IDLE_TICKS_TO_EXIT, nextIdleTicks } from \"./lib/run-once.js\";\nimport { createStallWatchdog } from \"./lib/tick-watchdog.js\";\nimport {\n probeRevisionHealth,\n resolveSchemaRevision,\n} from \"./lib/revision-stamp.js\";\nimport {\n applyStaleCheckoutOverride,\n checkRepos,\n renderTable,\n STALE_CHECKOUT_OVERRIDE,\n} from \"./lib/preflight.js\";\nimport {\n parseRoleBindings,\n resolveClaimExecution,\n type ExpectedRoleBinding,\n type RunnerRoleBindings,\n} from \"./lib/runtime-routing.js\";\n\ndeclare const __STACKS_BUNDLED_SCHEMA_REVISION__: string | undefined;\ndeclare const __STACKS_BUNDLED_APP_REVISION__: string | undefined;\n\n// F8 (AGE-505): every numeric env knob parses NaN-safe with its documented\n// default \u2014 a typo'd value can no longer produce a NaN timeout (fires\n// immediately) or a NaN turn budget (disables the budget).\nconst PORT = parsePositiveInt(process.env.PORT, 8788);\nconst HOST = process.env.STACKS_RUNNER_HOST ?? \"0.0.0.0\";\nconst SECRET = process.env.STACKS_WEBHOOK_SECRET ?? \"\";\nconst MCP_URL = process.env.STACKS_MCP_URL ?? \"http://localhost:3000/api/mcp\";\nconst STACKS_BASE_URL = process.env.STACKS_BASE_URL ?? new URL(MCP_URL).origin;\nconst ROLE_BINDINGS: RunnerRoleBindings | null = process.env\n .STACKS_RUNNER_ROLE_BINDINGS\n ? parseRoleBindings(process.env.STACKS_RUNNER_ROLE_BINDINGS)\n : null;\nlet shutdownRequested = false;\nif (!ROLE_BINDINGS) {\n console.error(\n \"DEPRECATED: no durable STACKS_RUNNER_ROLE_BINDINGS configured; using legacy STACKS_AGENT_PROVIDER routing for this compatibility window.\",\n );\n}\n\nasync function mintClaimCredential(\n binding: ExpectedRoleBinding,\n): Promise<string | undefined> {\n if (!binding.requiresClaimCredential) return undefined;\n const runnerToken = process.env.STACKS_WORKER_HEARTBEAT_TOKEN;\n if (!runnerToken) {\n throw new Error(\n \"ATTESTATION_FAILED: subscription routing requires the enrolled worker heartbeat token.\",\n );\n }\n const response = await fetch(\n new URL(\"/api/providers/claim-credential\", STACKS_BASE_URL),\n {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({\n runnerToken,\n connectionId: binding.providerConnectionId,\n }),\n signal: AbortSignal.timeout(30_000),\n },\n );\n const value = (await response.json().catch(() => null)) as {\n claimToken?: unknown;\n } | null;\n if (!response.ok || typeof value?.claimToken !== \"string\") {\n throw new Error(\n `ATTESTATION_FAILED: node-bound claim credential was refused (HTTP ${response.status}).`,\n );\n }\n return value.claimToken;\n}\n// M12.4b (AGE-174): the runner NEVER reads standing PATs directly. Role tokens\n// are provisioned by the mode-selected provider (managed / self-hosted / legacy)\n// and refreshed at each drive via refreshRoleTokens(), so a long-running server\n// with short-lived tokens never presents an expired one. Populated before listen.\nlet RUNNER_TOKEN = \"\";\nlet PLANNER_TOKEN = \"\";\nlet REVIEWER_TOKEN = \"\";\nconst HEARTBEAT_MS = 60_000;\nconst MAX_SKEW_MS = 5 * 60 * 1000;\n// A provider session that never returns (a network stall mid-turn) must not\n// wedge the runner: after this long the turn is failed (job parks BLOCKED,\n// recoverable via retry_harness_stage) and the pool frees the slot.\nconst TURN_TIMEOUT_MS = parsePositiveInt(\n process.env.STACKS_TURN_TIMEOUT_MS,\n 30 * 60 * 1000,\n);\n// AGE-414: in-run session retries when the stacks MCP server fails to connect\n// at SDK init (thrown before any model turn burns \u2014 see providers/claude.ts).\n// F7 (AGE-504): the SDK reports http MCP servers as \"pending\" at init (the M17\n// lesson \u2014 never abort on pending); the provider only fails on a terminal\n// status or the session's own tool-less sentinel. The [5s,15s] window still\n// lost to real Vercel cold-start/limit windows and failed planner jobs \u2014 the\n// bounded wait is now ~2.5 minutes across 5 attempts.\nconst MCP_CONNECT_RETRY_DELAYS_MS = [5_000, 15_000, 45_000, 90_000];\n// Turn budgets by turn type. Plan/review turns are a handful of MCP calls;\n// EXECUTION turns implement a real change in a checkout (S1 of the i18n run\n// burned 40 turns mid-migration) and need a far larger budget. A retried\n// execution turn continues from the surviving working tree, so even a\n// budget-death makes monotone progress \u2014 but hitting it should be rare.\nconst PLAN_MAX_TURNS = parsePositiveInt(process.env.STACKS_PLAN_MAX_TURNS, 40);\nconst EXEC_MAX_TURNS = parsePositiveInt(process.env.STACKS_EXEC_MAX_TURNS, 150);\n// Pool watchdog: a hard upper bound on ANY pooled task (turn or commit\n// boundary). Slightly above the turn timeout so the clean fail path wins;\n// when it fires, the pool releases the slot while the orphaned work keeps\n// running detached (attempt-guarded, worktree retained) \u2014 the server-side\n// claim CAS makes a superseding claim safe.\n// A pooled Harness drive also performs runner-attested verification after the\n// model turn, so the watchdog leaves headroom past the turn timeout for the\n// bounded verification commands instead of orphaning valid evidence.\nconst WATCHDOG_MS = parsePositiveInt(\n process.env.STACKS_JOB_WATCHDOG_MS,\n TURN_TIMEOUT_MS + 30 * 60 * 1000,\n);\n\n// ---------------------------------------------------------------------------\n// Stage 4 (S4): two bounded, job-id-deduplicating work pools replace the single\n// serialized promise chains. STACKS_RUNNER_MAX_CONCURRENT_JOBS bounds the\n// planner/reviewer/executor AGENT turns (default 1); STACKS_RUNNER_MAX_CONCURRENT_COMMITS\n// bounds the post-validation commit/push CONTINUATIONS on a DEDICATED pool\n// (default 1), so a freshly-approved commit never queues behind a long model\n// turn even when the agent-turn pool is full. Both parse to a FINITE documented\n// maximum (clamped by parseBoundedMax \u2014 never unbounded).\n// ponytail: fixed hard caps; bump the constant if a real deployment needs more.\nconst MAX_AGENT_JOBS_HARD = 16; // documented finite max for the agent-turn pool\nconst MAX_COMMIT_JOBS_HARD = 8; // documented finite max for the commit pool\nconst MAX_CONCURRENT_JOBS = parseBoundedMax(\n process.env.STACKS_RUNNER_MAX_CONCURRENT_JOBS,\n 1,\n MAX_AGENT_JOBS_HARD,\n);\nconst MAX_CONCURRENT_COMMITS = parseBoundedMax(\n process.env.STACKS_RUNNER_MAX_CONCURRENT_COMMITS,\n 1,\n MAX_COMMIT_JOBS_HARD,\n);\nconst AGENT_JOBS_CONFIGURED = process.env.STACKS_RUNNER_MAX_CONCURRENT_JOBS\n ? Number(process.env.STACKS_RUNNER_MAX_CONCURRENT_JOBS)\n : MAX_CONCURRENT_JOBS;\nconst COMMIT_JOBS_CONFIGURED = process.env.STACKS_RUNNER_MAX_CONCURRENT_COMMITS\n ? Number(process.env.STACKS_RUNNER_MAX_CONCURRENT_COMMITS)\n : MAX_CONCURRENT_COMMITS;\n\n// S4 telemetry state. jobEnqueuedAt mirrors the pools' inflight registries (set\n// on accept, cleared on TRUE settle) so we report the oldest in-flight job age;\n// lastClaimToExecMs is the most recent submit\u2192start (queue) latency; and\n// branchOwnershipConflicts counts stage-branch collisions the ownership reader\n// evaluated (a peer attempt already holds the resolved branch).\nconst jobEnqueuedAt = new Map<string, number>();\nlet lastClaimToExecMs = 0;\nlet branchOwnershipConflicts = 0;\n\n// STACKS_RUNNER_REPOS: \"owner/name\" -> a checkout path (string) OR an operator\n// object { cwd, bootstrap:[[argv]], copyIgnoredFiles, worktreeRoot } (Stage 3).\n// Parsed into per-repo entries the worktree manager drives; REPOS is the derived\n// owner->checkout map the generic (non-worktree) drive() path still uses.\nconst REPO_ENTRIES = (() => {\n let raw: unknown;\n try {\n raw = JSON.parse(process.env.STACKS_RUNNER_REPOS ?? \"{}\");\n } catch {\n console.error(\"STACKS_RUNNER_REPOS is not valid JSON \u2014 ignoring.\");\n return {};\n }\n try {\n return parseRunnerRepos(raw);\n } catch (err) {\n console.error(err instanceof Error ? err.message : String(err));\n return {};\n }\n})();\nconst REPOS: Record<string, string> = checkoutMap(REPO_ENTRIES);\nconst EXECUTION_PHASES = new Set([\"EXECUTING\", \"EXECUTION_REVISION\"]);\n\n// Webhook-less poll mode: > 0 turns on polling every N ms. A deployed Jentrix\n// cannot deliver webhooks to a localhost runner (the outbound SSRF guard\n// rejects private destinations, correctly), so without a public tunnel the\n// webhook path simply cannot fire \u2014 this fallback drives the SAME loop by\n// polling list_agent_jobs / the harness commit boundary instead. The webhook\n// server still runs (both can coexist; claims are CAS-guarded server-side, so\n// a webhook and a poll racing the same turn can never double-claim).\n// 0 = poll mode off (webhook only); an invalid value falls back to off.\nconst POLL_MS = process.env.STACKS_POLL_MS\n ? parsePositiveInt(process.env.STACKS_POLL_MS, 0)\n : 0;\nconst POLL_HARNESS_RUN_ID =\n process.env.STACKS_POLL_HARNESS_RUN_ID?.trim() || undefined;\n// AGE-836: once mode \u2014 a launchd-respawned dispatcher that lives for the\n// duration of the work it finds, then exits (lib/run-once.ts holds the exit\n// decision). Drives the SAME tick as poll mode; skips the webhook listener so\n// a canary can run beside a long-lived runner without fighting over PORT.\nconst RUN_ONCE = process.env.STACKS_RUNNER_ONCE === \"1\";\n// Once mode must not require the poll-mode env to be useful: tick at\n// STACKS_POLL_MS when set, else a sane default.\nconst ONCE_TICK_MS = POLL_MS > 0 ? POLL_MS : 15_000;\n// AGE-497: how often a LONG-LIVED runner re-asks the control plane whether its\n// stamp still matches. Prod redeploys while this process stays up, so a start-up\n// check alone goes stale; once mode re-checks by respawning instead.\nconst REVISION_PROBE_MS = 5 * 60_000;\n\n// In poll/once mode the webhook secret is optional (no deliveries expected);\n// unsigned posts are still rejected by verifySignature's empty-secret check.\nif (POLL_MS <= 0 && !RUN_ONCE && !SECRET) {\n console.error(\n \"Missing STACKS_WEBHOOK_SECRET \u2014 see the header of workflow-runner.ts.\",\n );\n process.exit(1);\n}\n\n// Select the auth provider from STACKS_RUNNER_MODE (managed / self-hosted /\n// legacy-PAT). A misconfiguration (no mode + no standing PATs) fails closed here\n// with a legible error, same as the old missing-token check \u2014 but the managed\n// path never reads a standing PAT.\nlet authProvider: RunnerTokenProvider;\ntry {\n // Default 30s expiry skew. Do NOT widen it: every mint ROTATES the\n // server-side bearer, and the poll loop refreshes each tick \u2014 a wide skew\n // rotates the token out from under an in-flight agent session (found live\n // 2026-07-24, twice). Fresh-per-leg tokens come from the leg-start\n // invalidation in refreshRoleTokens({ legStart: true }) instead.\n authProvider = resolveRunnerAuth();\n} catch (err) {\n console.error(err instanceof Error ? err.message : String(err));\n process.exit(1);\n}\n\n/** The P2.6 signature scheme (timestamp.body), same as bug-triage.ts. */\nfunction verifySignature(\n headers: Record<string, string | string[] | undefined>,\n rawBody: string,\n): boolean {\n const signature = headers[\"x-stacks-signature\"];\n const timestamp = headers[\"x-stacks-timestamp\"];\n if (typeof signature !== \"string\" || typeof timestamp !== \"string\") {\n return false;\n }\n const age = Math.abs(Date.now() - new Date(timestamp).getTime());\n if (!Number.isFinite(age) || age > MAX_SKEW_MS) return false;\n const expected =\n \"sha256=\" +\n createHmac(\"sha256\", SECRET)\n .update(`${timestamp}.${rawBody}`)\n .digest(\"hex\");\n const a = Buffer.from(expected);\n const b = Buffer.from(signature);\n return a.length === b.length && timingSafeEqual(a, b);\n}\n\n// Transport-level failures (Vercel 5xx blips, dropped sockets) are retried \u2014\n// a 504 on the runner's OWN recording call after a 25-minute green executor\n// turn parked stage 1 of the M17 run. App-level tool errors (the `isError`\n// envelope) are NEVER retried here. A retry of a call whose first attempt\n// actually landed can surface as CONFLICT \u2014 the state machine already\n// advanced, which the caller/sweep resolves from durable state.\nconst TRANSIENT_CALL_DELAYS_MS = [2_000, 8_000];\nconst TRANSIENT_CALL_RE =\n /Streamable HTTP error|fetch failed|ECONNRESET|socket hang up|Request timed out|\"code\":\\s*\"50[234]\"/;\n// AGE-835: fail fast so retries fit inside the 60s heartbeat cadence \u2014 the\n// SDK's 60s default meant ONE stalled connection consumed the whole beat, and\n// consecutive stalls outlived the server's run TTL (observed: a 12-min executor\n// turn expired mid-flight). 15s \u00D7 3 attempts + backoff \u2248 55s worst case.\nconst CALL_TIMEOUT_MS = 15_000;\n\n/** One MCP tool call with a specific token (the runner's admin token). */\n/**\n * AGE-840/899: which role a bearer belongs to, so a 401 can invalidate THAT\n * role. Current tokens match by identity; a bearer that has since been rotated\n * out resolves through the minted-token history in `lib/token-roles.ts` \u2014\n * identity ALONE left a long call's captured bearer unattributable, so the\n * re-mint declined and the caller wedged for the token's remaining TTL. An\n * unrecognized string still yields null, correctly declining to re-mint.\n */\nfunction roleForToken(token: string): RunnerRole | null {\n if (!token) return null;\n if (token === RUNNER_TOKEN) return \"runner\";\n if (token === PLANNER_TOKEN) return \"planner\";\n if (token === REVIEWER_TOKEN) return \"reviewer\";\n // A bearer captured before the last rotation is still ours \u2014 see token-roles.\n return roleForKnownToken(token);\n}\n\nfunction tokenForRole(role: RunnerRole): string {\n return role === \"runner\"\n ? RUNNER_TOKEN\n : role === \"planner\"\n ? PLANNER_TOKEN\n : REVIEWER_TOKEN;\n}\n\nasync function callTool(\n token: string,\n name: string,\n args: Record<string, unknown>,\n): Promise<Record<string, unknown>> {\n // AGE-687: never POST `Bearer ` \u2014 see assertBearerPresent. Checked OUTSIDE the\n // retry loop: an absent local token is not transient at this call site.\n assertBearerPresent(token, name);\n // AGE-840: a role token can be revoked SERVER-side BEFORE its own expiry \u2014\n // every claim rotates the bearer \u2014 while `createCachingTokenProvider` re-mints\n // only on timestamp expiry. The cache then serves a dead token for up to its\n // full 1h TTL and EVERY call 401s with no self-heal (observed twice: a wedged\n // poll loop, then a lost executor turn). Retrying the same string is futile,\n // so the first 401 invalidates that role and re-mints ONCE. Bounded to one\n // attempt: a second 401 on a freshly minted token is a real authorization\n // failure, not staleness, and must surface rather than loop.\n let bearer = token;\n let reMinted = false;\n // AGE-923: `retryAfterSeconds` is `60 - now.getUTCSeconds()` server-side, so\n // four honored waits are ~244s inside ONE call \u2014 longer than the tick\n // watchdog supervising it, which is how a live tick read as a wedge. Waiting\n // out the bucket needs one wait (two if the next minute re-trips), which is\n // what the evidence-submission burst this retry was built for actually took;\n // beyond that the cap is being re-tripped immediately and failing the call to\n // the caller's own retry beats sleeping through four minutes of it.\n const RATE_LIMIT_BUDGET_MS = 120_000;\n let rateLimitWaitedMs = 0;\n for (let attempt = 0; ; attempt++) {\n try {\n const transport = new StreamableHTTPClientTransport(new URL(MCP_URL), {\n requestInit: { headers: { Authorization: `Bearer ${bearer}` } },\n });\n const client = new Client({\n name: \"stacks-workflow-runner\",\n version: RUNNER_VERSION,\n });\n await client.connect(transport, { timeout: CALL_TIMEOUT_MS });\n try {\n const res = await client.callTool(\n { name, arguments: args },\n undefined,\n {\n timeout: CALL_TIMEOUT_MS,\n },\n );\n if (res.isError) {\n const text =\n Array.isArray(res.content) &&\n res.content[0] &&\n \"text\" in res.content[0]\n ? (res.content[0] as { text: string }).text\n : JSON.stringify(res.content);\n throw new Error(`${name} failed: ${text}`);\n }\n return (res.structuredContent ?? {}) as Record<string, unknown>;\n } finally {\n await client.close();\n }\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n // RATE_LIMITED is app-level but explicitly retriable: the server did not\n // process the call and tells us how long to wait. An evidence-submission\n // burst after a green executor turn tripped the 60/min cap and parked\n // stage 1 \u2014 honor retryAfterSeconds instead of failing the turn.\n if (msg.includes('\"RATE_LIMITED\"') && attempt < 4) {\n const m = msg.match(/\"retryAfterSeconds\":\\s*(\\d+)/);\n const waitMs = ((m ? Number(m[1]) : 5) + 1) * 1000;\n if (rateLimitWaitedMs + waitMs <= RATE_LIMIT_BUDGET_MS) {\n rateLimitWaitedMs += waitMs;\n console.error(\n `[callTool ${name}] rate-limited (attempt ${attempt + 1}) \u2014 waiting ${waitMs}ms`,\n );\n await new Promise((r) => setTimeout(r, waitMs));\n continue;\n }\n console.error(\n `[callTool ${name}] rate-limited past the ${RATE_LIMIT_BUDGET_MS}ms backoff budget \u2014 failing to the caller (AGE-923)`,\n );\n }\n // AGE-840: a revoked-but-unexpired cached token. Invalidate that role,\n // re-mint, and retry with the NEW bearer \u2014 retrying the same string can\n // only 401 again. Once only; `reMinted` also guards the case where the\n // re-mint itself hands back a token the server rejects.\n if (/invalid_token|\"code\":\\s*\"401\"/.test(msg) && !reMinted) {\n const role = roleForToken(bearer);\n if (role) {\n reMinted = true;\n authProvider.invalidate?.(role);\n try {\n await refreshRoleTokens();\n } catch (refreshErr) {\n // Re-minting failed (a spent/revoked grant chain) \u2014 that is the\n // operator-actionable error, not the 401 it was masking.\n throw refreshErr;\n }\n bearer = tokenForRole(role);\n assertBearerPresent(bearer, name);\n console.error(\n `[callTool ${name}] 401 on a cached ${role} token \u2014 re-minted and retrying once (AGE-840)`,\n );\n continue;\n }\n }\n const transient =\n !msg.startsWith(`${name} failed:`) && TRANSIENT_CALL_RE.test(msg);\n if (!transient || attempt >= TRANSIENT_CALL_DELAYS_MS.length) throw err;\n console.error(\n `[callTool ${name}] transient failure (attempt ${attempt + 1}): ${msg.slice(0, 120)} \u2014 retrying`,\n );\n await new Promise((r) =>\n setTimeout(r, TRANSIENT_CALL_DELAYS_MS[attempt]),\n );\n }\n }\n}\n\nconst PLANNER_PROMPT = `You are the PLANNER/EXECUTOR in a Jentrix review loop.\nYou have been handed a runId for the current turn. Work ONLY through the Jentrix\nMCP tools (the stacks-review-loop skill explains the protocol). If the phase is a\nplan phase: read the job with get_agent_job, read any open findings, then call\nsubmit_plan(jobId, runId, ...) with the plan's objective/acceptanceCriteria and,\nif revising, resolutions that say how you fixed each finding.\nIF the job's templateKey is \"decomposition\", submit_plan MUST ALSO include a\nharnessStages array \u2014 the concrete ordered stages the accept gate will mint. Each\nstage: { title, objective, approach, expectedBranchBehavior, acceptanceCriteria[],\nsuggestedTests[], riskNotes[], tracesToCriteria[], verificationCommands[],\ncriterionEvidence[] }. tracesToCriteria must quote\nthe ACCEPTED spec's structured definitionOfDone verbatim (see get_spec /\nget_agent_job) \u2014 never invent criterion labels. criterionEvidence maps each\ntraced criterion to its proof: { criterion (verbatim), mode: \"AUTOMATED\" |\n\"OPERATOR\", requiredTier: \"UNIT_MOCKED\" | \"INTEGRATION_LOCAL\" |\n\"PROD_TOPOLOGY_LOCAL\" | \"MANAGED_STAGING\" | \"PRODUCTION_DRILL\",\nverificationCommands[] } \u2014 across the WHOLE run every spec criterion must be\nmapped exactly once, an AUTOMATED criterion needs at least one runnable\ncommand, and a human action (deploy, env var, restart) is OPERATOR, never\nhidden behind stage completion. verificationCommands (stage level) is the\nunion of the stage's AUTOMATED commands \u2014 the RUNNER executes them itself to\nmint attested test evidence; executor prose never satisfies the gate. Put the\ndetailed per-surface requirements in each stage's own acceptanceCriteria.\nDescribing stages only in the objective prose is NOT enough \u2014 without the\nharnessStages array the gate has nothing to mint and the reviewer cannot\nverify the plan.\nTHIS PROPOSAL IS THE ENTIRE PLAN (AGE-781): stages execute with NO per-stage\nplan loop \u2014 each stage attempt opens directly at execution with your frozen\nstage plan as its whole brief. Two consequences. (1) approach is the\nexecutor's brief: name the files/modules to touch, the mechanism, and the\nordering, per stage \u2014 an executor cannot re-plan a vague stage, it can only\nfail it. (2) GROUND every criterion (AGE-782/M19): a criterion that asserts\nbehavior over EXISTING code or schema must name the artifact it depends on\n(file path, model.field), and you must VERIFY each named artifact exists in\nthe mapped planning checkout (Read/Glob/Grep) before submitting. A criterion\nrequiring a schema field that does not exist, in a stage that declares \"no\nmigration\", is an unsatisfiable frozen contract \u2014 it deadlocked a real run\nfor 11 rounds. State each stage's grounding facts in its riskNotes (e.g.\n\"grounded: Workspace.updatedAt exists at prisma/schema.prisma:NN\"). Criteria\nmust be jointly satisfiable AGAINST THE CODEBASE AS IT EXISTS, not merely\nwell-formed.\nIF the job's templateKey is \"authoring\" (AGE-521 \u2014 PRD\u2192spec is the lossy hop;\nmake the loss explicit): you are drafting the run's spec FROM the PRD named in\nthe objective. Read the PRD file in the mapped checkout. EVERY definitionOfDone\ncriterion must cite its PRD source inline (append \"\u2014 [PRD \u00A7<section>]\"), and\nevery PRD section you deliberately exclude must appear in nonGoals with a\nreason. A PRD section that is neither cited by a criterion nor excluded in\nnonGoals is a coverage hole the reviewer will reject.\nIF the job is a harness STAGE job (get_agent_job shows a harness block) and the\nphase is a plan phase (AGE-520 \u2014 stage scope contract): fetch the run's\naccepted spec (get_harness gives specId \u2192 get_spec) and the sibling registry\n(list_harness_stages, response_format \"detailed\"). Your stage owns EXACTLY the\nharness block's criteria. Plan to satisfy those and nothing else: never pull a\nsibling stage's criterion into this stage, and never drop an owned one \u2014 the\nspec is your read-only global context, the stage slice is your contract.\nIf the phase is an execution phase: do the work in the mapped repo, then\nsubmit_execution_result(jobId, runId, executionSummary, artifactIds). Do NOT call\nclaim/heartbeat/fail. Finish with a one-line summary.`;\n\nconst REVIEWER_PROMPT = `You are the REVIEWER in a Jentrix review loop. You have\na runId for the current turn. Read the job with get_agent_job (and the latest\nplan version / execution summary), then call submit_review(jobId, runId, verdict,\nreviewerSummary, findings[], verifiedFindingIds[]). Mark any previously-addressed\nfindings you have verified. ALWAYS pass reviewerSummary \u2014 it is the only thing a\nhuman operator reads to learn why the job moved, and a rejection that reopens an\nexisting finding submits no new ones, so without it the job page shows a revision\nphase with no explanation.\n${loadRubric(\"reviewer-disposition\")}\nIF the job's templateKey is \"decomposition\", review the get_agent_job\ndecompositionProposal array (the exact ordered stages the accept gate will\nmint): verify the stages are ordered + independently shippable, each has its own\nacceptanceCriteria + suggestedTests, tracesToCriteria references only the accepted\nspec's stored criteria, and every spec concern is owned by some stage (no orphan).\nIf decompositionProposal is null/empty, the planner did not submit harnessStages \u2014\nCHANGES_REQUESTED asking for the harnessStages array.\nTHIS REVIEW IS THE LAST GATE BEFORE EXECUTION (AGE-781): stages run with NO\nper-stage plan loop \u2014 what you approve here is frozen as each stage's entire\ncontract and brief, and after the mint NOTHING can amend it short of a human\nre-decomposition. Therefore: (1) verify each stage's approach is a concrete,\nexecutable brief (files/mechanism/ordering), not a restatement of the title;\n(2) GROUND-CHECK the criteria against the checkout \u2014 for every criterion that\nasserts behavior over existing code or schema, grep the named artifact\n(schema field, module, function) in your checkout and REJECT (severity >= 60,\nbasisKind BASELINE_REQUIREMENT) any criterion that depends on an artifact\nthat does not exist unless the same stage explicitly creates it; (3) check\nthe stage's criteria are JOINTLY satisfiable \u2014 a criterion demanding a\nmechanism (e.g. an updatedAt-based CAS) next to a constraint that forbids its\nprerequisite (e.g. \"no migration\" with no such column) is an unsatisfiable\nfrozen contract and MUST be rejected here, because the executor cannot fix\nscope and the run will burn its bounded attempts re-proving the conflict.\nIF the job's templateKey is \"authoring\" (AGE-521): verify PRD coverage. Read\nthe PRD file in the checkout. Every PRD section must be either cited by a\ndefinitionOfDone criterion (\"[PRD \u00A7<section>]\") or excluded in nonGoals with a\nreason. An uncited, unexcluded PRD section is a blocking finding (severity\n>=60, basisKind BASELINE_REQUIREMENT, basisRef the PRD section) \u2014 the spec is\nthe only place downstream coverage guards can see the PRD, so a hole here\npropagates silently.\nSTAGE SCOPE CONTRACT (AGE-520 \u2014 harness stage jobs): judge this stage ONLY\nagainst ITS OWN criteria (the harness block / the frozen stage plan; confirm\nownership with list_harness_stages response_format \"detailed\" and the accepted\nspec via get_harness \u2192 get_spec). Evidence for criteria owned by OTHER stages\nis OUT OF SCOPE here: file such observations as severity <40 follow-ups naming\nthe owning stage, never as blockers \u2014 a whole-PRD expectation held against one\nstage parks the run for nothing.\nIF get_agent_job shows a \"harness\" block (a harness stage job), ALSO reconcile\nthe findings ledger: call list_harness_findings({harnessRunId, harnessStageId})\nand judge every OPEN/FIXED row against the evidence in front of you \u2014 for each\nFIXED claim the evidence GENUINELY covers, call\nupdate_harness_finding({findingId, status: \"VERIFIED\", verifiedRunId: <your runId>});\nREOPEN a hollow claim (status: \"OPEN\", resolutionNote explaining what is missing);\na covered row still sitting OPEN goes OPEN\u2192FIXED\u2192VERIFIED (two calls). Never\nreject solely because ledger rows predate this job \u2014 verify what the current\nevidence covers and reject only for what genuinely remains. submit_review's\nverifiedFindingIds reaches only THIS job's findings; the ledger tools cover\nprior rounds. Execution evidence for a harness stage NEVER includes a commit\nSHA: the stage commit happens AFTER validation, behind the governed commit\nboundary \u2014 the recorded stage result plus diff/test artifacts ARE the complete\nexecution-time record, so never request a commit as execution evidence.\nWhen an acceptance criterion names a trust or exactly-once boundary, review the\nliteral production path, not a similarly-shaped test double: comments, an\nunwired adapter seam, an in-memory Set/Map, or a caller promise to authenticate\ndo not prove it. Distinguish at-least-once model generation from exactly-once\nresult application, and require irreversible git/GitHub effects to reconcile\nfrom provider-authoritative state after success-before-finalize. For signed gate\nsignals, require authenticated source-record consumption, signature mint, and\ndurable signal-outbox insert to share the stated atomic ingress; then verify the\nworkflow rejects bad binding/version/nonce/signature and worker authority.\nDo NOT call claim/heartbeat/fail. Finish with a one-line summary.`;\n\n/** AGE-926: a turn that ENDS without submitting is a failed turn, not a quiet\n * one. A provider can deliver a terminal API error \u2014 an exceeded output\n * ceiling, a refusal \u2014 as the session's RESULT TEXT rather than by throwing,\n * so the runner sees a clean return, logs the text as if it were a summary,\n * and walks away leaving the job claimed until its heartbeat lapses. Observed\n * on a planner leg that died at 02:14:45 whose job did not park until\n * 03:05:24, recorded as the generic \"Agent run heartbeat expired\" with the\n * real cause visible only in this process's stdout.\n *\n * The check reads a DURABLE fact rather than pattern-matching the text: every\n * plan and review turn ends by calling its submit tool, and that submit\n * settles this run SUCCEEDED server-side. A run still open once the session\n * has returned means nothing was submitted, whatever the text claims.\n *\n * Deliberately one-sided \u2014 it only fails a turn it can PROVE did not submit.\n * An unreadable job or an unrecognized run returns silently and leaves the\n * pre-existing heartbeat path as the backstop: failing a live turn on a bad\n * read would be a worse defect than the slow park this replaces. */\nasync function assertTurnSubmitted(\n jobId: string,\n runId: string,\n role: string,\n summary: string,\n): Promise<void> {\n let run: { id?: string; status?: string } | undefined;\n try {\n const res = await callTool(RUNNER_TOKEN, \"get_agent_job\", { jobId });\n const job = (res.job ?? res) as {\n runs?: { id?: string; status?: string }[];\n };\n run = job.runs?.find((r) => r.id === runId);\n } catch (e) {\n console.error(\n `[job ${jobId}] could not verify ${role} submission: ${e instanceof Error ? e.message : e}`,\n );\n return;\n }\n if (!run?.status || run.status === \"SUCCEEDED\") return;\n throw new Error(\n `${role} turn ended without submitting a result (run ${run.status}). ` +\n `Provider's final output: ${summary.slice(0, 400)}`,\n );\n}\n\nasync function drive(\n jobId: string,\n toRole: string,\n phase: string,\n repoOwnerName: string | undefined,\n // Stage 3: for a harness reviewer turn, the stage's WORKTREE (read-only) \u2014 the\n // uncommitted changes live there now, not the shared checkout. A GENERIC (non-\n // harness) reviewer has none and legitimately reads the shared checkout.\n reviewerWorktreeCwd?: string,\n // Stage 3 (fail-closed): true when this is a HARNESS reviewer whose read-only\n // review MUST run against the stage worktree (the uncommitted change lives\n // there). When required-but-absent we refuse to fall back to the shared\n // checkout \u2014 approving against a tree without the stage's changes is worse\n // than parking the stage for a human.\n reviewerWorktreeRequired?: boolean,\n groundingError?: string,\n): Promise<void> {\n if (shutdownRequested) return;\n const isReviewer = toRole === \"REVIEWER\";\n const isExecution = EXECUTION_PHASES.has(phase);\n const expectedBinding =\n ROLE_BINDINGS?.[\n isReviewer ? \"reviewer\" : isExecution ? \"executor\" : \"planner\"\n ];\n const provider =\n expectedBinding?.runtimeAdapterKey ??\n (isReviewer ? \"codex\" : agentProvider());\n // Per-leg Claude model pin: planner legs (authoring/planning/revision) and\n // executor legs may run different models (STACKS_PLANNER_MODEL /\n // STACKS_EXECUTOR_MODEL). Codex reviewer legs pin via STACKS_CODEX_MODEL.\n const turnModel =\n expectedBinding?.model ??\n (provider === \"claude\"\n ? claudeLegModel(isExecution ? \"executor\" : \"planner\")\n : codexModel());\n const workerClaimToken = expectedBinding\n ? await mintClaimCredential(expectedBinding)\n : undefined;\n if (shutdownRequested) return;\n // 1. Claim the current turn (admin token) \u2192 runId. The presentation (pinned\n // model + build-stamped revision + capabilities) rides claimPresentation \u2014\n // the control plane refuses a schema-incompatible worker, an unattested\n // validator lane, or an unrunnable model BEFORE any model turn burns\n // (M12.3b/M13.4b; un-stamped dev leaves the compatibility guard inert).\n const claim = await callTool(RUNNER_TOKEN, \"claim_agent_job\", {\n jobId,\n ...claimPresentation(provider, { model: turnModel }),\n ...(expectedBinding ? { provider: expectedBinding.provider } : {}),\n ...(workerClaimToken ? { workerClaimToken } : {}),\n });\n const runId = String(claim.runId);\n let execution = null;\n try {\n execution = expectedBinding\n ? resolveClaimExecution(claim, expectedBinding)\n : null;\n } catch (error) {\n await callTool(RUNNER_TOKEN, \"fail_agent_job\", {\n jobId,\n runId,\n error: error instanceof Error ? error.message : \"role route refused\",\n }).catch(() => {});\n throw error;\n }\n\n // Execution turns get repo tools scoped to the mapped checkout, so the\n // executor actually implements the change instead of only recording it.\n // REVIEWER turns get the SAME checkout READ-ONLY, so the review verifies\n // claims against the actual working tree (which holds the stage's\n // uncommitted changes) instead of judging the executor's prose \u2014 a reviewer\n // that can check reality rejects less and its approvals mean more.\n const checkout = repoOwnerName ? REPOS[repoOwnerName] : undefined;\n // M18.3 R7: the checkout decision comes from the DURABLE run role the control\n // plane just returned, through the same total, fail-closed map the harness\n // path uses (agents/lib/role-repo-access.ts). Behaviour-preserving for every\n // shipped leg \u2014 EXECUTING/EXECUTION_REVISION open as EXECUTOR (writable),\n // PLAN_*/EXECUTION_REVIEW as PLANNER/REVIEWER (read-only) \u2014 but now a role\n // this runner does not recognize can only ever get a read-only tree, instead\n // of whatever the phase happened to imply.\n const repoAccess = repoAccessForRole(\n typeof claim.role === \"string\" ? claim.role : null,\n );\n const repoCwd = repoAccess.provisionWorktree ? checkout : undefined;\n // A harness reviewer reads the stage's WORKTREE (where the uncommitted change\n // lives); a generic reviewer reads the shared checkout.\n const reviewerCwd = isReviewer\n ? (reviewerWorktreeCwd ?? checkout)\n : undefined;\n // AGE-523: PLANNING/authoring legs read the shared checkout READ-ONLY so the\n // planner can ingest in-repo sources (PRDs under prds/, docs) \u2014 the M18\n // authoring contract requires the PRD body verbatim, and it exists only in\n // the repo. Only execution legs get a writable tree; no mapped repo keeps\n // the old MCP-only world.\n const planningReadCwd =\n !repoAccess.provisionWorktree && !isReviewer ? checkout : undefined;\n if (isExecution && (!repoOwnerName || !repoCwd)) {\n // No checkout to work in \u2014 FAIL the run instead of producing a hollow\n // \"execution\" with no code changes. The job blocks for a human.\n const reason = repoOwnerName\n ? `No STACKS_RUNNER_REPOS entry for ${repoOwnerName} \u2014 cannot execute.`\n : \"Job has no repoOwnerName \u2014 cannot execute in a checkout.\";\n console.error(`[job ${jobId}] ${reason}`);\n await callTool(RUNNER_TOKEN, \"fail_agent_job\", {\n jobId,\n runId,\n error: reason,\n }).catch((e) => console.error(`[fail ${jobId}]`, e));\n return;\n }\n\n // Stage 3 fail-closed: a HARNESS reviewer must read the stage's WORKTREE (its\n // uncommitted changes live there, not in the shared checkout). If the worktree\n // could not be adopted (missing, pruned, or marker-mismatched), FAIL the run\n // instead of falling back to the shared checkout \u2014 reviewing/approving against\n // the wrong tree is worse than parking the stage for a human to resolve.\n if (isReviewer && reviewerWorktreeRequired && !reviewerWorktreeCwd) {\n const reason =\n \"Harness reviewer could not adopt the stage worktree (missing, pruned, or marker-mismatched); refusing to review against the shared checkout, which lacks the stage's uncommitted changes. Resolve the worktree, then retry the stage.\";\n console.error(`[job ${jobId}] ${reason}`);\n await callTool(RUNNER_TOKEN, \"fail_agent_job\", {\n jobId,\n runId,\n error: reason,\n }).catch((e) => console.error(`[fail ${jobId}]`, e));\n return;\n }\n // AGE-497: every role that reads the shared checkout fails here, not just the\n // reviewer. An executor grounding a stage on a checkout that could not reach\n // its base cuts the stage branch from an older tree \u2014 the failure this used to\n // let through silently.\n if (groundingError) {\n const reason = `Harness grounding checkout is stale or unavailable: ${groundingError}`;\n console.error(`[job ${jobId}] ${reason}`);\n await callTool(RUNNER_TOKEN, \"fail_agent_job\", {\n jobId,\n runId,\n error: reason,\n }).catch((e) => console.error(`[fail ${jobId}]`, e));\n return;\n }\n\n // 2. Heartbeat the run while the session works (admin token). Self-stops on\n // CONFLICT: the turn was superseded externally (job failed + stage retried),\n // so hammering a dead run is pure noise.\n let sessionDone = false;\n const heartbeat: ReturnType<typeof setInterval> = setInterval(() => {\n void callTool(RUNNER_TOKEN, \"heartbeat_agent_job\", { jobId, runId }).catch(\n (e) => {\n if (sessionDone) {\n // The turn already finished locally (returned, threw, or timed out) \u2014\n // the run's fate is decided, so a straggler tick's CONFLICT/expiry is\n // expected; don't misreport a finished turn as superseded.\n clearInterval(heartbeat);\n return;\n }\n const msg = e instanceof Error ? e.message : String(e);\n console.error(`[heartbeat ${jobId}] ${msg}`);\n if (msg.includes(\"not the job's active run\")) {\n console.error(\n `[job ${jobId}] turn superseded externally \u2014 stopping its heartbeat.`,\n );\n clearInterval(heartbeat);\n }\n },\n );\n }, HEARTBEAT_MS);\n\n // AGE-938: the provider-reported usage for this attempt, recorded post-turn\n // via record_run_usage (runner-attested \u2014 the model's own submit cannot\n // carry a receipt it does not have).\n let turnUsage: AgentTurnUsage | null = null;\n\n try {\n // 3. Run the role session with its OWN token (turn-guard passes). Raced\n // against the turn timeout: a session that never returns fails the job\n // (recoverable) instead of wedging its pool slot forever.\n const repoNote =\n repoCwd && !isReviewer\n ? ` Your checkout is at ${repoCwd}; implement the change there with the file/bash tools, then attach evidence as artifacts.`\n : reviewerCwd\n ? ` A READ-ONLY checkout is at ${reviewerCwd} \u2014 verify the executor's claims and the current diff against the actual working tree (it holds the stage's uncommitted changes). Never modify it.`\n : planningReadCwd\n ? ` A READ-ONLY checkout is at ${planningReadCwd} \u2014 read in-repo sources from there (e.g. the PRD under prds/). Never modify it.`\n : \"\";\n // Same conventions + parallel-work block the executor gets (harness-runner\n // injects the executor's own). Only for a leg that HAS a checkout to read\n // it in; fail-soft \u2014 a context read never costs a turn.\n const contextCwd = reviewerCwd ?? planningReadCwd ?? repoCwd ?? null;\n const projectContext = contextCwd\n ? await buildProjectContext(\n { git: (dir, args) => runGit(dir, args) },\n { cwd: contextCwd, role: isReviewer ? \"reviewer\" : \"planner\" },\n ).catch(() => \"\")\n : \"\";\n const runSessionOnce = async (): Promise<string> => {\n const session = runJentrixAgent(\n `Act on Jentrix agent job ${jobId}. Your runId is ${runId}.${repoNote}${projectContext}`,\n {\n systemPrompt: isReviewer ? REVIEWER_PROMPT : PLANNER_PROMPT,\n // AGE-938: capture the provider-reported usage for THIS attempt.\n // Last report wins across in-run session retries \u2014 a retried session\n // is an init failure with zero model turns, so nothing real is lost.\n onUsage: (usage) => {\n turnUsage = usage;\n },\n maxTurns: isExecution ? EXEC_MAX_TURNS : PLAN_MAX_TURNS,\n model: execution?.model ?? turnModel,\n ...(typeof execution?.generationControls?.reasoningMode === \"string\"\n ? {\n reasoningMode: execution.generationControls.reasoningMode,\n }\n : {}),\n ...(provider === \"claude\" && process.env.STACKS_CLAUDE_EXECUTABLE\n ? { executablePath: process.env.STACKS_CLAUDE_EXECUTABLE }\n : {}),\n ...(provider === \"codex\" && process.env.STACKS_CODEX_EXECUTABLE\n ? { executablePath: process.env.STACKS_CODEX_EXECUTABLE }\n : {}),\n // The Claude executor turn gets a WRITABLE checkout; the Codex reviewer\n // turn gets the same checkout READ-ONLY (shell reads under the\n // read-only sandbox \u2014 see providers/codex.ts). Every repoReadOnly here\n // is MAP-DERIVED (M18.3 R7) \u2014 never a hand-written literal, so a role\n // the map calls read-only cannot be handed a writable tree by a leg\n // that forgot to pass the flag.\n ...(repoCwd && !isReviewer\n ? { repoCwd, repoReadOnly: repoAccess.repoReadOnly }\n : {}),\n ...(isReviewer && reviewerCwd\n ? { repoCwd: reviewerCwd, repoReadOnly: repoAccess.repoReadOnly }\n : {}),\n ...(planningReadCwd\n ? {\n repoCwd: planningReadCwd,\n repoReadOnly: repoAccess.repoReadOnly,\n }\n : {}),\n },\n {\n connection: {\n url: MCP_URL,\n token: isReviewer ? REVIEWER_TOKEN : PLANNER_TOKEN,\n },\n provider,\n },\n );\n // Orphan-safety: if the timeout wins the race, a late rejection from the\n // abandoned session must not crash the process.\n session.catch(() => {});\n let turnTimer: ReturnType<typeof setTimeout> | undefined;\n try {\n return await Promise.race([\n session,\n new Promise<never>((_, reject) => {\n turnTimer = setTimeout(\n () =>\n reject(\n new Error(\n `turn timed out after ${TURN_TIMEOUT_MS}ms (provider session stalled)`,\n ),\n ),\n TURN_TIMEOUT_MS,\n );\n }),\n ]);\n } finally {\n clearTimeout(turnTimer);\n }\n };\n try {\n // AGE-414: a session whose stacks MCP server failed to connect throws at\n // init with ZERO model turns burned. The claim + heartbeat are still\n // valid, so retry the SESSION in-run before failing the job \u2014 a\n // transient connect failure becomes a non-event instead of a 15-minute\n // heartbeat rot into BLOCKED.\n let summary: string;\n for (let attempt = 0; ; attempt++) {\n try {\n summary = await runSessionOnce();\n break;\n } catch (err) {\n // Retriable in-run: a tool-less session (AGE-414/423) or a transient\n // HTTP failure from the MCP endpoint (Vercel 504/502 blips killed a\n // stage-1 executor turn after its plan was already approved).\n const retriable =\n err instanceof Error &&\n (err.name === \"JentrixMcpUnavailableError\" ||\n /Streamable HTTP error|fetch failed|50[234]/.test(err.message));\n if (!retriable || attempt >= MCP_CONNECT_RETRY_DELAYS_MS.length)\n throw err;\n console.error(\n `[job ${jobId}] retriable session failure (attempt ${attempt + 1}): ${err instanceof Error ? err.message.slice(0, 120) : err} \u2014 retrying session`,\n );\n await new Promise((r) =>\n setTimeout(r, MCP_CONNECT_RETRY_DELAYS_MS[attempt]),\n );\n }\n }\n console.log(`[job ${jobId}] ${toRole}: ${summary}`);\n // Throws into the catch below, which fails the job with this reason \u2014\n // so the real cause is the recorded blockedReason instead of a heartbeat\n // expiry ~51 minutes later that names the wrong subsystem.\n await assertTurnSubmitted(jobId, runId, toRole, summary);\n } finally {\n sessionDone = true;\n }\n } catch (err) {\n // 4. Provider/agent error \u2192 fail the run (admin token); the job blocks.\n console.error(`[job ${jobId}] ${toRole} failed:`, err);\n await callTool(RUNNER_TOKEN, \"fail_agent_job\", {\n jobId,\n runId,\n error: err instanceof Error ? err.message : \"runner error\",\n }).catch((e) => console.error(`[fail ${jobId}]`, e));\n } finally {\n clearInterval(heartbeat);\n // AGE-938: record the attempt's usage AFTER the turn settled, on both\n // outcomes (a failed turn still spent tokens). Legal on the closed run;\n // write-once server-side; loss here must never affect the job.\n if (turnUsage) {\n await callTool(RUNNER_TOKEN, \"record_run_usage\", {\n jobId,\n runId,\n usage: turnUsage,\n }).catch((e) => console.error(`[usage ${jobId}]`, e));\n }\n }\n}\n\n// ---------------------------------------------------------------------------\n// Harness-aware routing (H10.6). A Harness Automation STAGE rides the same\n// stage_execution loop, but its EXECUTOR turn must record stage evidence + commit\n// evidence, cross the authorize/commit/push boundary, and honor freeze by THIS\n// process. The agent.handoff webhook carries only the jobId, so we poll\n// get_agent_job to detect the `harness` block and route the executor turn to the\n// harness protocol. Plan/review turns stay on the generic path (they only operate\n// MCP \u2014 no checkout needed).\n// ---------------------------------------------------------------------------\n\n/** Run one git command in a checkout (the runner's shell-capable leg, BOUNDED to\n * STACKS_RUNNER_REPOS by the harness-runner module before it is ever called).\n * `env` carries a single-use push token to git's credential helper WITHOUT\n * placing it in argv (the token never appears in a process listing). */\nconst runGit: RunGit = (cwd, args, env) =>\n new Promise<string>((resolve, reject) => {\n const child = spawn(\"git\", args, {\n cwd,\n env: env ? { ...process.env, ...env } : process.env,\n });\n let out = \"\";\n let err = \"\";\n child.stdout.on(\"data\", (d) => (out += d));\n child.stderr.on(\"data\", (d) => (err += d));\n child.on(\"error\", reject);\n child.on(\"close\", (code) =>\n code === 0\n ? resolve(out.trim())\n : reject(new Error(`git ${args[0]} failed (${code}): ${err.trim()}`)),\n );\n });\n\n/**\n * S1 documentation commit guard, PRODUCTION wiring. Runs `pnpm docs:sync` /\n * `pnpm docs:check` in the managed verification container over the stage worktree.\n * `sync` regenerates the checked-in\n * generated docs before the reviewer turn; `check` reports whether a public\n * contract is stale (non-zero exit) so the runner blocks the local commit via the\n * server's checksum-bound DOCUMENTATION_REVIEW finding. Adds NO dependency \u2014 pnpm\n * is already the toolchain.\n */\nconst touchesPublicContract = (changedFiles: readonly string[]): boolean =>\n changedFiles.some(\n (file) =>\n file.startsWith(\"src/lib/mcp/\") ||\n file === \"scripts/tool-workflows.ts\" ||\n file === \"docs/agent-platform.md\" ||\n /^src\\/server\\/.+\\/schemas\\.ts$/.test(file),\n );\n\nconst docsGuard: HarnessRunnerDeps[\"docsGuard\"] = {\n sync: async (cwd, changedFiles) => {\n // Internal UI/test changes cannot move generated public-contract docs \u2014\n // skip the sandboxed regeneration for them; contract changes retain it.\n if (!touchesPublicContract(changedFiles)) return;\n const result = await runManagedVerificationCommand({\n cwd,\n command: \"pnpm docs:sync\",\n timeoutMs: 900_000,\n });\n if (result.exitCode !== 0) {\n throw new Error(\n `docs:sync failed (${result.exitCode}): ${(result.stderr || result.stdout).trim()}`,\n );\n }\n },\n check: async (cwd, changedFiles) => {\n if (!touchesPublicContract(changedFiles)) {\n return {\n ok: true,\n staleDocs: [],\n output:\n \"No public-contract changes in the diff \u2014 documentation guard passed.\",\n };\n }\n const result = await runManagedVerificationCommand({\n cwd,\n command: \"pnpm docs:check\",\n timeoutMs: 900_000,\n });\n const output = `${result.stdout}${result.stderr}`;\n const staleDocs: string[] = [];\n if (/tool-registry\\.generated\\.json/.test(output))\n staleDocs.push(\"src/lib/mcp/tool-registry.generated.json\");\n if (/agent-platform\\.md/.test(output))\n staleDocs.push(\"docs/agent-platform.md\");\n return { ok: result.exitCode === 0, staleDocs, output };\n },\n};\n\n// D5 (2026-07): the raw-token push/PR seams (brokerPushCredential /\n// createPullRequest, always null-wired here) were DELETED \u2014 push/PR egress is\n// the sandbox-side broker (M12.5) or a fail-closed defer to the governed\n// delivery path / an operator.\n\n// M12.1: the reference runner executes every agent turn THROUGH an\n// ExecutionBackend (host driver by default \u2192 identical Jentrix-side records;\n// STACKS_EXECUTION_DRIVER=docker runs the turn in an ephemeral, resource-limited,\n// deny-by-default-egress container). The backend enforces the turn's wall-time\n// budget, so a stalled turn is killed with a structured failure rather than hanging.\nconst { backend: executionBackend, kind: executionKind } =\n makeExecutionBackend();\nconsole.log(`workflow-runner: execution driver = ${executionKind}`);\n\n/**\n * Read FRESH Jentrix state to decide whether the attempt that owns a colliding\n * stage branch is still live, is confirmed superseded, or is unprovable (Stage 3\n * ownership check). Uses the runner's ADMIN token to read get_agent_job for BOTH\n * the owning attempt and the current one:\n * \u2022 LIVE \u2014 the old job has an active run, a non-terminal phase, or a pending\n * commit/merge gate (a commit continuation) \u2192 conflict, change nothing.\n * \u2022 SUPERSEDED \u2014 the old job is terminal (DONE/CANCELLED/BLOCKED, incl. a lease\n * takeover that blocked it) with NO active run and NO pending commit, AND the\n * current attempt is a NEWER job for the SAME stage \u2192 detach + reuse the branch.\n * \u2022 UNPROVABLE \u2014 anything unreadable or unconfirmable \u2192 fail closed.\n */\nconst readOwnerState: OwnerStateReader = async (owner, current) => {\n // Reaching here means the worktree manager found the resolved stage branch\n // already checked out by ANOTHER attempt \u2014 a branch-ownership conflict. Count\n // every evaluation for telemetry (the verdict below decides live/superseded/\n // unprovable; all three are collisions that had to be adjudicated).\n branchOwnershipConflicts += 1;\n let oldJob: Record<string, unknown>;\n try {\n oldJob = await callTool(RUNNER_TOKEN, \"get_agent_job\", {\n jobId: owner.jobId,\n });\n } catch (e) {\n return {\n status: \"unprovable\",\n detail: `get_agent_job(${owner.jobId}) failed: ${e instanceof Error ? e.message : String(e)}`,\n };\n }\n const phase = String(oldJob.phase ?? \"\");\n const hasActiveRun = oldJob.activeRunId != null;\n const terminal = [\"DONE\", \"CANCELLED\", \"BLOCKED\"].includes(phase);\n const approvals = Array.isArray(oldJob.approvals)\n ? (oldJob.approvals as Array<Record<string, unknown>>)\n : [];\n const pendingCommit = approvals.some(\n (a) =>\n a?.status === \"PENDING\" && (a?.kind === \"COMMIT\" || a?.kind === \"MERGE\"),\n );\n if (hasActiveRun || !terminal || pendingCommit) {\n const why = hasActiveRun\n ? \"with an active run\"\n : pendingCommit\n ? \"with a pending commit gate\"\n : \"still in flight\";\n return {\n status: \"live\",\n detail: `owning job ${owner.jobId} is ${phase} ${why}`,\n };\n }\n // Terminal, no active run, no pending commit continuation. Confirm a NEWER stage\n // job (this current attempt) replaced it \u2014 else we can't prove supersession.\n let curJob: Record<string, unknown>;\n try {\n curJob = await callTool(RUNNER_TOKEN, \"get_agent_job\", {\n jobId: current.jobId,\n });\n } catch (e) {\n return {\n status: \"unprovable\",\n detail: `get_agent_job(${current.jobId}) failed: ${e instanceof Error ? e.message : String(e)}`,\n };\n }\n const curStageId =\n (curJob.harness as { stageId?: string } | null | undefined)?.stageId ??\n null;\n const sameStage = curStageId === owner.stageId;\n const newer =\n typeof curJob.createdAt === \"string\" && typeof oldJob.createdAt === \"string\"\n ? curJob.createdAt > oldJob.createdAt\n : true;\n if (sameStage && newer) {\n return {\n status: \"superseded\",\n detail: `owning job ${owner.jobId} is ${phase} with no active run or pending commit; replaced by newer job ${current.jobId}`,\n } satisfies OwnerVerdict;\n }\n return {\n status: \"unprovable\",\n detail: `owning job ${owner.jobId} is ${phase}, but the current attempt ${current.jobId} is not a confirmed superseding successor (stage ${curStageId ?? \"?\"} vs ${owner.stageId})`,\n };\n};\n\n// Stage 3: the per-job worktree manager over the parsed repo entries + the runner's\n// git seam + the fresh-Jentrix-state owner reader. This is the PRODUCTION wiring of\n// the executor's per-job worktree; the smoke tests inject a deterministic fake.\nconst worktreeManager = new RunnerWorktreeManager(\n REPO_ENTRIES,\n runGit,\n readOwnerState,\n { log: (msg) => console.log(msg) },\n);\n\nconst harnessDeps: HarnessRunnerDeps = {\n callTool,\n worktree: worktreeManager,\n // S1 documentation commit guard: docs:sync before final review, docs:check\n // before authorizing the local commit (a stale public contract blocks it).\n docsGuard,\n preflightVerification: preflightManagedVerification,\n // HAI S3: the runner executes the stage's DECLARED verification commands\n // itself (foreground, timed) to mint attested TEST_EVIDENCE. The command\n // text is gate-approved stage-plan content and runs inside an ephemeral,\n // env-scrubbed, deny-egress container over the stage worktree. A startup\n // failure reports exitCode 127 so the attestation records the honest outcome.\n runCommand: runManagedVerificationCommand,\n runAgentTurn: ({\n prompt,\n systemPrompt,\n repoCwd,\n repoReadOnly,\n signal,\n runnerOwnsSubmissions,\n execution,\n }) =>\n runTurnThroughBackend(executionBackend, executionKind, {\n prompt,\n systemPrompt,\n repoCwd,\n ...(runnerOwnsSubmissions ? { runnerOwnsSubmissions } : {}),\n // M18.3 R7: forwarded from the dispatch role's map entry \u2014 the providers\n // enforce it (claude withholds write/edit tools, codex sandboxes the\n // shell read-only). Undefined for the executor lane = today's behavior.\n ...(repoReadOnly ? { repoReadOnly } : {}),\n maxTurns:\n typeof execution?.generationControls?.maxTurns === \"number\"\n ? execution.generationControls.maxTurns\n : EXEC_MAX_TURNS,\n model: execution?.model,\n ...(typeof execution?.generationControls?.reasoningMode === \"string\"\n ? { reasoningMode: execution.generationControls.reasoningMode }\n : {}),\n ...(execution?.runtimeAdapterKey === \"claude\" &&\n process.env.STACKS_CLAUDE_EXECUTABLE\n ? { executablePath: process.env.STACKS_CLAUDE_EXECUTABLE }\n : {}),\n ...(execution?.runtimeAdapterKey === \"codex\" &&\n process.env.STACKS_CODEX_EXECUTABLE\n ? { executablePath: process.env.STACKS_CODEX_EXECUTABLE }\n : {}),\n connection: { url: MCP_URL, token: PLANNER_TOKEN },\n provider: execution?.runtimeAdapterKey ?? agentProvider(),\n signal,\n }),\n git: runGit,\n // M12.5 (AGE-175): when STACKS_SANDBOX_BROKER_ENABLED=1 + a grant transport is\n // configured, the push/PR egress goes THROUGH the sandbox-side broker (which owns\n // credential injection) and this runner never holds the raw token. Undefined by\n // default \u21D2 push/PR defers fail-closed to the governed path / an operator (D5).\n sandboxEgress: makeSandboxEgress(),\n sleep: (ms) => delay(ms),\n};\n\nconst harnessCfg: HarnessRunnerConfig = {\n tokens: { runner: RUNNER_TOKEN, planner: PLANNER_TOKEN },\n repos: REPOS,\n evidenceTier:\n process.env.STACKS_VERIFICATION_EVIDENCE_TIER ??\n DEFAULT_RUNNER_EVIDENCE_TIER,\n heartbeatMs: HEARTBEAT_MS,\n commitPollMs: 10_000,\n commitPollMax: 30,\n // M12.3b (AGE-173): present this runner's build-stamped revision on the harness\n // stage claim \u2014 the SAME single source of truth the generic drive() claim uses \u2014\n // so an incompatible harness worker is refused fail-closed by the control plane.\n revision: resolveRevisionStamp(),\n executorBinding: ROLE_BINDINGS?.executor,\n mintClaimCredential,\n stopping: () => shutdownRequested,\n log: (msg) => console.log(msg),\n};\n\n// ---------------------------------------------------------------------------\n// S4 pools + telemetry. BOTH the webhook and the poll input submit to these SAME\n// two pool objects, so the queued/running job-id dedup registry SPANS both\n// inputs: a webhook delivery and a poll delivery for one job collapse before\n// consuming a slot in either pool. The server-side claim CAS remains the FINAL\n// ownership guard \u2014 these pools only avoid wasting a slot on a peer-owned job.\n// ---------------------------------------------------------------------------\nfunction poolTelemetry(): Record<string, number> {\n const now = Date.now();\n let oldestJobAgeMs = 0;\n for (const at of jobEnqueuedAt.values()) {\n oldestJobAgeMs = Math.max(oldestJobAgeMs, now - at);\n }\n const a = agentPool.snapshot();\n const c = commitPool.snapshot();\n return {\n agentQueueDepth: a.queueDepth,\n agentActive: a.active,\n agentMax: a.effectiveMax,\n agentInflight: a.inflight,\n commitQueueDepth: c.queueDepth,\n commitActive: c.active,\n commitMax: c.effectiveMax,\n commitInflight: c.inflight,\n oldestJobAgeMs,\n claimToExecMs: lastClaimToExecMs,\n branchOwnershipConflicts,\n };\n}\nfunction emitPoolTelemetry(reason: string): void {\n console.log(\n `[runner-pool] ${JSON.stringify({ reason, ...poolTelemetry() })}`,\n );\n}\n\nconst agentPool = new BoundedDedupPool(\n \"agent-turn\",\n MAX_CONCURRENT_JOBS,\n AGENT_JOBS_CONFIGURED,\n {\n watchdogMs: WATCHDOG_MS,\n log: (m) => console.log(m),\n onStart: (jobId, queueLatencyMs) => {\n lastClaimToExecMs = queueLatencyMs;\n emitPoolTelemetry(`start:${jobId}`);\n },\n onSettle: () => emitPoolTelemetry(\"settle\"),\n },\n);\nconst commitPool = new BoundedDedupPool(\n \"commit\",\n MAX_CONCURRENT_COMMITS,\n COMMIT_JOBS_CONFIGURED,\n {\n watchdogMs: WATCHDOG_MS,\n log: (m) => console.log(m),\n onStart: (jobId, queueLatencyMs) => {\n lastClaimToExecMs = queueLatencyMs;\n emitPoolTelemetry(`commit-start:${jobId}`);\n },\n onSettle: () => emitPoolTelemetry(\"commit-settle\"),\n },\n);\n\n/**\n * Submit `work` for `jobId` to `pool`. Records the enqueue time for job-age\n * telemetry and clears it on TRUE settle (so a watchdog-detached orphan keeps\n * ageing until it really finishes). Returns false when the pool collapsed a\n * duplicate delivery (already queued/running/watchdog-detached).\n */\nfunction submitJob(\n pool: BoundedDedupPool,\n jobId: string,\n work: () => Promise<void>,\n): boolean {\n if (shutdownRequested) return false;\n const enqueuedAt = Date.now();\n const accepted = pool.submit(jobId, async () => {\n if (shutdownRequested) return;\n try {\n await work();\n } finally {\n jobEnqueuedAt.delete(jobId);\n }\n });\n if (accepted) {\n jobEnqueuedAt.set(jobId, enqueuedAt);\n emitPoolTelemetry(`enqueue:${jobId}`);\n } else {\n emitPoolTelemetry(`dedupe:${jobId}`);\n }\n return accepted;\n}\n\n/**\n * Resolve the current bearer token for each role from the mode-selected provider\n * and mirror the two harness tokens into harnessCfg. The provider caches +\n * refreshes short-lived tokens, so calling this at each drive keeps a\n * long-running managed / self-hosted server's tokens fresh; the deprecated\n * legacy-PAT path just returns the static tokens (a cheap no-op). Every generic\n * drive() call site reads the module-level RUNNER_TOKEN / PLANNER_TOKEN /\n * REVIEWER_TOKEN at use-time, so a refresh here is picked up by the next call.\n */\nasync function refreshRoleTokens(\n opts: { legStart?: boolean } = {},\n): Promise<void> {\n // Leg start: force FRESH planner/reviewer tokens (full 1h TTL) \u2014 the agent\n // session embeds its role token in MCP headers for the whole leg, and a mint\n // ROTATES the bearer server-side, so the leg must start fresh and nothing\n // may re-mint that role until the leg ends. Safe at agentMax=1 (one agent\n // leg in flight); a concurrency raise needs per-leg tokens instead.\n if (opts.legStart) {\n authProvider.invalidate?.(\"planner\");\n authProvider.invalidate?.(\"reviewer\");\n }\n const [runner, planner, reviewer] = await Promise.all([\n authProvider.tokenFor(\"runner\"),\n authProvider.tokenFor(\"planner\"),\n authProvider.tokenFor(\"reviewer\"),\n ]);\n RUNNER_TOKEN = runner;\n PLANNER_TOKEN = planner;\n REVIEWER_TOKEN = reviewer;\n // AGE-899: record BEFORE anything can rotate them again, so a bearer captured\n // by an in-flight call stays attributable to its role after it is superseded.\n rememberTokenRole(runner, \"runner\");\n rememberTokenRole(planner, \"planner\");\n rememberTokenRole(reviewer, \"reviewer\");\n // harnessCfg.tokens was captured at module load \u2014 refresh it in place so the\n // harness protocol reads the current short-lived tokens.\n harnessCfg.tokens.runner = RUNNER_TOKEN;\n harnessCfg.tokens.planner = PLANNER_TOKEN;\n}\n\n/**\n * Route one actionable handoff. A harness stage EXECUTOR turn goes to the harness\n * protocol; everything else (plan/review turns, and non-harness jobs) stays on the\n * generic M7 `drive()`. Detection polls get_agent_job (the only place the harness\n * binding is surfaced).\n */\nasync function driveTurn(\n jobId: string,\n toRole: string,\n phase: string,\n repoOwnerName: string | undefined,\n): Promise<void> {\n // Refresh short-lived role tokens before touching MCP \u2014 leg start forces\n // FRESH planner/reviewer tokens so the session's embedded bearer spans the\n // whole leg (mints rotate; see refreshRoleTokens).\n await refreshRoleTokens({ legStart: true });\n const currentJob =\n toRole === \"REVIEWER\" || EXECUTION_PHASES.has(phase)\n ? await getHarnessStageJob(harnessDeps, harnessCfg, jobId).catch(\n () => null,\n )\n : null;\n if (EXECUTION_PHASES.has(phase)) {\n const job = currentJob;\n if (job?.harness) {\n const { disposition } = await driveHarnessStage(harnessDeps, harnessCfg, {\n jobId,\n });\n console.log(`[harness ${jobId}] ${disposition}`);\n return;\n }\n }\n // A harness EXECUTION reviewer gets the stage's WORKTREE read-only (Stage 3):\n // adopt the executor's worktree so the reviewer verifies against the actual\n // uncommitted change. For that turn the worktree is REQUIRED \u2014 if it can't be\n // adopted, drive() FAILS CLOSED rather than reviewing against the shared checkout\n // (which lacks the stage's uncommitted changes). A PLAN reviewer needs none:\n // the stage worktree is only created at the first execution turn\n // (ensureExecutionCwd), so requiring adoption at PLAN_REVIEW fails closed on a\n // legitimately absent tree (AGE-350, found live in the M15 run).\n let reviewerWorktreeCwd: string | undefined;\n let reviewerWorktreeRequired = false;\n let groundingError: string | undefined;\n if (toRole === \"REVIEWER\" && phase === \"EXECUTION_REVIEW\") {\n const job = currentJob;\n const h = job?.harness;\n if (h?.repo && REPOS[h.repo]) {\n // This IS a harness stage reviewer \u2014 the read-only stage worktree is\n // mandatory; a failed adoption must not silently degrade to the checkout.\n reviewerWorktreeRequired = true;\n const branch = resolveStageBranch(h);\n reviewerWorktreeCwd =\n (await worktreeManager\n .adoptExecutionCwd({\n repo: h.repo,\n jobId,\n stageId: h.stageId,\n branch,\n })\n .catch(() => null)) ?? undefined;\n }\n }\n // AGE-497: refresh + ASSERT the shared checkout for every leg that touches it,\n // not just the reviewer's. `refreshGroundingCheckout` fetches, fast-forwards,\n // and throws when HEAD did not reach the base \u2014 it would have caught the stale\n // m14 clone on day one, but it only ever ran on the reviewer leg. The executor\n // is the leg that CUTS STAGE BRANCHES from this checkout, so it is the one that\n // most needs the base to be real. A reviewer holding its own per-job worktree\n // is the one case that does not read the shared checkout at all.\n if (\n currentJob?.harnessRun &&\n !(toRole === \"REVIEWER\" && reviewerWorktreeRequired)\n ) {\n const run = currentJob.harnessRun;\n const repo = run.repo ?? repoOwnerName;\n if (!repo || !REPOS[repo]) {\n groundingError = repo\n ? `no STACKS_RUNNER_REPOS entry for ${repo}`\n : \"harness run has no repository\";\n } else {\n try {\n await worktreeManager.refreshGroundingCheckout(\n repo,\n run.baseBranch ?? \"main\",\n );\n } catch (e) {\n groundingError = e instanceof Error ? e.message : String(e);\n }\n }\n }\n await drive(\n jobId,\n toRole,\n phase,\n repoOwnerName,\n reviewerWorktreeCwd,\n reviewerWorktreeRequired,\n groundingError,\n );\n}\n\nconst server = createServer((req, res) => {\n if (req.method !== \"POST\") {\n res.writeHead(405).end();\n return;\n }\n let rawBody = \"\";\n req.on(\"data\", (chunk) => (rawBody += chunk));\n req.on(\"end\", () => {\n // No secret configured (poll mode): the webhook leg is disabled outright \u2014\n // an HMAC with an empty key would otherwise \"verify\" for anyone who knows\n // the scheme.\n if (!SECRET) {\n res.writeHead(503).end(\"webhook disabled (no secret; poll mode)\");\n return;\n }\n if (!verifySignature(req.headers, rawBody)) {\n res.writeHead(401).end(\"bad signature\");\n return;\n }\n const event = req.headers[\"x-stacks-event\"];\n const body = JSON.parse(rawBody) as {\n data?: {\n jobId?: string;\n toRole?: string;\n turn?: string;\n phase?: string;\n repoOwnerName?: string;\n };\n };\n const jobId = body.data?.jobId;\n const toRole = body.data?.toRole ?? body.data?.turn;\n const phase = body.data?.phase ?? \"\";\n const repoOwnerName = body.data?.repoOwnerName;\n\n // Ack fast \u2014 Jentrix retries failed deliveries; the run can take a while.\n res.writeHead(202).end(\"queued\");\n\n // A harness stage is validated LATER than its execution turn (after the\n // reviewer + the human FINAL_ACCEPTANCE gate). Jentrix emits\n // `harness.stage_validated` (carrying the stage's jobId) when the commit\n // boundary is ready \u2014 react by driving the post-validation commit boundary.\n if (event === \"harness.stage_validated\" && jobId) {\n // Post-validation commit continuation \u2192 the DEDICATED commit pool (kept\n // low-latency even when the agent-turn pool is full). Dedup spans webhook +\n // poll: a poll commit-watch for the same jobId collapses on this pool.\n submitJob(commitPool, jobId, async () => {\n // Refresh short-lived role tokens before the commit boundary.\n await refreshRoleTokens();\n const { disposition } = await driveHarnessStageCommit(\n harnessDeps,\n harnessCfg,\n { jobId },\n );\n console.log(`[harness commit ${jobId}] ${disposition}`);\n });\n return;\n }\n\n // Only agent turns are actionable here; HUMAN turns wait for the gate UI.\n if (event !== \"agent.handoff\" || !jobId || !toRole) return;\n if (toRole !== \"PLANNER\" && toRole !== \"REVIEWER\") return;\n // Agent turn \u2192 the bounded agent-turn pool. A retried/duplicate delivery or a\n // racing poll drive for the SAME jobId collapses before consuming a slot.\n submitJob(agentPool, jobId, () =>\n driveTurn(jobId, toRole, phase, repoOwnerName),\n );\n });\n});\n\n// ---------------------------------------------------------------------------\n// Poll mode (STACKS_POLL_MS > 0) \u2014 the webhook-less fallback. Each tick:\n// 1. list_agent_jobs per agent-turn phase \u2192 submit PLANNER/REVIEWER turns to\n// the SAME bounded agentPool the webhook path uses (shared job-id dedup, so\n// a poll and a webhook drive for one job collapse; get_agent_job re-reads\n// turn/phase fresh so a stale list row never mis-drives; claim_agent_job's\n// server-side CAS is the ultimate double-claim guard).\n// 2. Jobs whose executor turn we drove \u2014 plus jobs parked at the human\n// FINAL_ACCEPTANCE gate \u2014 are watched for the post-validation commit\n// boundary and submitted to the DEDICATED commitPool, so a commit-gate wait\n// can never block the next agent turn (which may be the very reviewer that\n// unblocks the gate).\n// ---------------------------------------------------------------------------\n\nconst AGENT_TURN_PHASES = [\n \"PLAN_DRAFTING\",\n \"PLAN_REVIEW\",\n \"PLAN_REVISION\",\n \"EXECUTING\",\n \"EXECUTION_REVIEW\",\n \"EXECUTION_REVISION\",\n] as const;\n\n// Jobs parked awaiting the post-validation commit boundary \u2014 a PERSISTENT watch\n// keyed by jobId, carrying the stage coordinates once known (null until the\n// first context read). F5 (AGE-502): the watch is STATUS-SCOPED \u2014 each tick\n// reads every watched run's stage statuses in ONE list_harness_stages call and\n// drives the commit boundary ONLY for stages actually at VALIDATED/COMMIT_GATE/\n// COMMITTED. A stage still EXECUTING used to be blind-driven every tick\n// (multi-call, \"not committable\"), which is what filled runner.log with\n// sub-second commit-start/settle cycles and burned the 60/min token budget.\nconst commitWatch = new Map<\n string,\n { harnessRunId: string; stageId: string } | null\n>();\n// AGE-415: ids dropped for TERMINAL reasons (committed, run cancelled/archived,\n// stage blocked/skipped, not a harness job, unmapped repo). pollTick re-adds\n// every FINAL_ACCEPTANCE_GATE job each tick \u2014 a zombie job of a cancelled run\n// sits in that phase forever, so without this the watch busy-loops on it.\nconst commitWatchDead = new Set<string>();\n// Stage statuses the commit boundary acts on; everything else is a silent keep\n// (the stage may still validate) or a dead drop (it never will).\nconst COMMIT_ADJACENT_STATUSES = new Set([\n \"VALIDATED\",\n \"COMMIT_GATE\",\n \"COMMITTED\",\n]);\nconst DEAD_STAGE_STATUSES = new Set([\"BLOCKED\", \"SKIPPED\"]);\n\n/** Jobs listed for one phase (first page \u2014 actionable turns are few). */\nasync function jobsInPhase(\n workspaceId: string,\n phase: string,\n): Promise<{ id: string; turn: string }[]> {\n // AGE-835: per-phase isolation \u2014 under a degraded network one failed list\n // used to abort the WHOLE tick (and sequential retry ladders across the six\n // phase lists could outlive the tick watchdog), so no phase ever got\n // claimed. A phase whose list fails is skipped THIS tick; the others proceed.\n try {\n const res = await callTool(RUNNER_TOKEN, \"list_agent_jobs\", {\n workspaceId,\n phase,\n });\n return (res.jobs as { id: string; turn: string }[] | undefined) ?? [];\n } catch (err) {\n console.error(\n `[poll] list ${phase} failed (skipping this tick): ${err instanceof Error ? err.message.slice(0, 120) : String(err)}`,\n );\n return [];\n }\n}\n\n/** Submit one watched job's commit-boundary drive to the commit pool (the pool\n * bounds concurrency + collapses a re-submit while one is still in flight). */\nfunction driveWatchedCommit(jobId: string): void {\n submitJob(commitPool, jobId, async () => {\n if (!commitWatch.has(jobId)) return;\n // Refresh short-lived role tokens before the commit boundary \u2014 the commit\n // pool runs independently of the agent-turn pool, so it must re-provision.\n await refreshRoleTokens();\n try {\n const { disposition } = await driveHarnessStageCommit(\n harnessDeps,\n harnessCfg,\n { jobId },\n );\n if (\n disposition.startsWith(\"committed\") ||\n disposition === \"not_a_harness_stage_job\" ||\n // AGE-410: a CANCELLED/ARCHIVED run can never authorize the commit.\n disposition.startsWith(\"run terminal\") ||\n /stage (BLOCKED|SKIPPED)/.test(disposition)\n ) {\n commitWatch.delete(jobId);\n commitWatchDead.add(jobId);\n }\n if (disposition !== \"not_a_harness_stage_job\") {\n console.log(`[poll commit ${jobId}] ${disposition}`);\n }\n } catch (err) {\n // An unmapped repo can never succeed \u2014 stop watching; anything else\n // (transient network, freeze) stays watched for the next tick.\n if (err instanceof Error && err.name === \"UnmappedRepoError\") {\n commitWatch.delete(jobId);\n commitWatchDead.add(jobId);\n }\n throw err;\n }\n });\n}\n\n/** F5 (AGE-502): the status-scoped commit-watch pump. Learns each watched\n * job's stage coordinates once, then reads every watched run's stage statuses\n * in ONE list call per tick and drives ONLY commit-adjacent stages. Paced\n * inherently to the poll interval (this runs once per tick; the commit pool's\n * dedup collapses re-submits while a drive is still in flight). */\nasync function pumpCommitWatch(): Promise<void> {\n // Learn missing stage coordinates (one get_agent_job, once per job ever).\n for (const [jobId, ctx] of [...commitWatch]) {\n if (ctx) continue;\n const job = await getHarnessStageJob(harnessDeps, harnessCfg, jobId).catch(\n () => null,\n );\n if (!job) continue; // transient read failure \u2014 keep watched, retry next tick\n if (!job.harness) {\n // Not a harness stage job \u2014 it will never have a commit boundary.\n commitWatch.delete(jobId);\n commitWatchDead.add(jobId);\n continue;\n }\n commitWatch.set(jobId, {\n harnessRunId: job.harness.harnessRunId,\n stageId: job.harness.stageId,\n });\n }\n // One status list per watched run.\n const runIds = new Set(\n [...commitWatch.values()].flatMap((c) => (c ? [c.harnessRunId] : [])),\n );\n const statusesByRun = new Map<string, Map<string, string>>();\n for (const runId of runIds) {\n const statuses = await listStageStatuses(\n harnessDeps,\n harnessCfg,\n runId,\n ).catch(() => null);\n if (statuses) statusesByRun.set(runId, statuses);\n }\n for (const [jobId, ctx] of [...commitWatch]) {\n if (!ctx) continue; // coordinates unknown this tick\n const statuses = statusesByRun.get(ctx.harnessRunId);\n if (!statuses) continue; // list failed \u2014 keep watched, retry next tick\n const status = statuses.get(ctx.stageId);\n if (status === undefined || DEAD_STAGE_STATUSES.has(status)) {\n // Archived/missing or terminally parked \u2014 the boundary will never open\n // for this attempt (a retry mints a NEW job that re-enters the watch).\n commitWatch.delete(jobId);\n commitWatchDead.add(jobId);\n continue;\n }\n if (!COMMIT_ADJACENT_STATUSES.has(status)) continue; // silent keep\n driveWatchedCommit(jobId);\n }\n}\n\n/** AGE-923: the tick's stall detector. 180s of NO reported progress \u2014 not 180s\n * of work \u2014 is a wedge. Every await in the tick path reports its step. */\nconst tickWatchdog = createStallWatchdog({ stallMs: 180_000 });\n\nasync function pollTick(workspaceId: string): Promise<void> {\n for (const phase of AGENT_TURN_PHASES) {\n const rows = await jobsInPhase(workspaceId, phase);\n tickWatchdog.progress(`jobsInPhase(${phase})`);\n for (const row of rows) {\n if (row.turn !== \"PLANNER\" && row.turn !== \"REVIEWER\") continue;\n // Already queued/running in the shared registry \u2192 skip the fresh re-read;\n // submitJob() below is the authoritative dedup (a webhook racing this poll\n // read collapses on submit).\n if (agentPool.has(row.id)) continue;\n // Re-read the full job fresh: the list row can be a tick stale, and the\n // full view carries repoOwnerName + the harness block for routing.\n const job = await getHarnessStageJob(\n harnessDeps,\n harnessCfg,\n row.id,\n ).catch(() => null);\n tickWatchdog.progress(`getHarnessStageJob(${row.id})`);\n if (!job || (job.turn !== \"PLANNER\" && job.turn !== \"REVIEWER\")) continue;\n // F6 (AGE-503): a job with an ACTIVE run cannot be claimed \u2014 every claim\n // would CONFLICT (\"it has an active run\"). A live peer owns it, or a\n // zombie run is awaiting sweep expiry; either way the next tick\n // re-evaluates from fresh state. This ends the identical-claim storms\n // (10+ CONFLICTs per job per tick in runner.log). Never blind-claim.\n if (job.activeRunId) continue;\n const isExecution = EXECUTION_PHASES.has(job.phase);\n const harnessJob = job.harness;\n if (!pollScopeAllows(POLL_HARNESS_RUN_ID, jobHarnessRunId(job))) continue;\n submitJob(agentPool, job.id, () =>\n driveTurn(\n job.id,\n job.turn,\n job.phase,\n job.repoOwnerName ?? undefined,\n ).finally(() => {\n // An executor turn on a harness stage will need its commit boundary\n // driven once validated (reviewer + human gate happen in between).\n if (isExecution && harnessJob && !commitWatchDead.has(job.id))\n commitWatch.set(job.id, {\n harnessRunId: harnessJob.harnessRunId,\n stageId: harnessJob.stageId,\n });\n }),\n );\n }\n }\n // Harness jobs parked at the human FINAL_ACCEPTANCE gate: once a human\n // approves, the stage validates with NO further handoff a poller could see \u2014\n // watch them for the commit boundary (non-harness jobs settle out of the\n // watch on their first \"not_a_harness_stage_job\").\n const gateRows = await jobsInPhase(workspaceId, \"FINAL_ACCEPTANCE_GATE\");\n tickWatchdog.progress(\"jobsInPhase(FINAL_ACCEPTANCE_GATE)\");\n for (const row of gateRows) {\n if (commitWatchDead.has(row.id)) continue;\n if (POLL_HARNESS_RUN_ID) {\n const job = await getHarnessStageJob(\n harnessDeps,\n harnessCfg,\n row.id,\n ).catch(() => null);\n tickWatchdog.progress(`getHarnessStageJob(gate ${row.id})`);\n if (!job || !pollScopeAllows(POLL_HARNESS_RUN_ID, jobHarnessRunId(job)))\n continue;\n // Store the coordinates we just read (saves pumpCommitWatch a learn call).\n if (!commitWatch.get(row.id) && job.harness) {\n commitWatch.set(row.id, {\n harnessRunId: job.harness.harnessRunId,\n stageId: job.harness.stageId,\n });\n continue;\n }\n }\n if (!commitWatch.has(row.id)) commitWatch.set(row.id, null);\n }\n // AGE-835: a harness job that reached DONE while no runner was watching (a\n // wedged poll loop, or a restart between the acceptance gate and the commit)\n // leaves its stage parked at VALIDATED/COMMIT_GATE with nobody driving the\n // boundary \u2014 the FINAL_ACCEPTANCE_GATE sweep above never re-discovers it and\n // the harness.stage_validated webhook leg is disabled in poll mode. Sweep the\n // first page of DONE jobs (newest-first) into the same watch; non-harness and\n // out-of-scope rows are dead-marked so each costs one read per process, and\n // pumpCommitWatch's status-scoping ignores stages that are not commit-adjacent.\n const doneRows = await jobsInPhase(workspaceId, \"DONE\");\n tickWatchdog.progress(\"jobsInPhase(DONE)\");\n for (const row of doneRows) {\n if (commitWatchDead.has(row.id) || commitWatch.has(row.id)) continue;\n const job = await getHarnessStageJob(harnessDeps, harnessCfg, row.id).catch(\n () => null,\n );\n tickWatchdog.progress(`getHarnessStageJob(done ${row.id})`);\n if (!job) continue;\n if (\n !job.harness ||\n !pollScopeAllows(POLL_HARNESS_RUN_ID, jobHarnessRunId(job))\n ) {\n commitWatchDead.add(row.id);\n continue;\n }\n commitWatch.set(row.id, {\n harnessRunId: job.harness.harnessRunId,\n stageId: job.harness.stageId,\n });\n }\n await pumpCommitWatch();\n tickWatchdog.progress(\"pumpCommitWatch\");\n}\n\n/** Resolve the single workspace the runner token is pinned to (poll + once). */\nasync function resolvePollWorkspace(): Promise<string> {\n const res = await callTool(RUNNER_TOKEN, \"list_workspaces\", {});\n const workspaces = (res.workspaces as { id: string }[] | undefined) ?? [];\n const workspaceId = workspaces[0]?.id;\n if (!workspaceId) {\n console.error(\"[poll] runner token sees no workspace \u2014 cannot poll.\");\n process.exit(1);\n }\n if (workspaces.length > 1) {\n console.error(\n `[poll] runner token sees ${workspaces.length} workspaces \u2014 polling ${workspaceId}. Pin the token to one workspace.`,\n );\n }\n return workspaceId;\n}\n\n/** One watchdog-raced tick, shared by the immortal poll loop and once mode.\n * AGE-835: the loop wedged twice on a tick that HUNG instead of throwing (a\n * stalled auth fetch serialized every later obtain behind it; an MCP connect\n * had no timeout). Tick work is reads + pool submits, so abandoning a stuck\n * tick loses nothing.\n * AGE-923: the watchdog supervises PROGRESS, not total elapsed \u2014 see\n * lib/tick-watchdog.ts for why a flat budget fired on ticks that then\n * succeeded. Every await below reports the step it finished. */\nasync function tickWithWatchdog(workspaceId: string): Promise<void> {\n await tickWatchdog.guard(\n (async () => {\n // Refresh short-lived role tokens each tick (no-op for legacy PATs).\n await refreshRoleTokens();\n tickWatchdog.progress(\"refreshRoleTokens\");\n await pollTick(workspaceId);\n })(),\n );\n}\n\n/** AGE-836 once mode: tick until the workspace has nothing for us AND nothing\n * is in flight \u2014 two consecutive quiet ticks; lib/run-once.ts explains why\n * `inflight` (a watchdog-detached orphan still counts) and why two \u2014 then\n * exit 0. launchd's StartInterval provides the cadence, the sweep (AGE-292)\n * the convergence: an exit at any point strands nothing. A tick that FAILS\n * while the pools sit idle also walks toward exit \u2014 under a dead network the\n * right move is a fresh process in one respawn interval, not a wedged loop. */\nasync function runOnce(workspaceId: string): Promise<never> {\n console.log(\n `[once] dispatch mode: workspace ${workspaceId}, tick ${ONCE_TICK_MS}ms${\n POLL_HARNESS_RUN_ID ? `, scope harness ${POLL_HARNESS_RUN_ID}` : \"\"\n }`,\n );\n let idleTicks = 0;\n for (;;) {\n if (shutdownRequested) await finishShutdown();\n try {\n await tickWithWatchdog(workspaceId);\n } catch (err) {\n console.error(\"[once] tick failed:\", err);\n }\n idleTicks = nextIdleTicks(\n [agentPool.snapshot(), commitPool.snapshot()],\n idleTicks,\n );\n if (idleTicks >= IDLE_TICKS_TO_EXIT) {\n console.log(\"[once] idle \u2014 exiting for launchd respawn.\");\n process.exit(0);\n }\n await delay(ONCE_TICK_MS);\n }\n}\n\nasync function finishShutdown(): Promise<never> {\n let waitedMs = 0;\n while (\n nextIdleTicks([agentPool.snapshot(), commitPool.snapshot()], 0) === 0\n ) {\n await delay(50);\n waitedMs += 50;\n // AGE-927: a turn can legitimately hold this loop for tens of minutes (a\n // reviewer leg observed at 35min). Silence reads as a hang and is exactly\n // what invites the `kill -9` that abandons the turn \u2014 say what we are\n // waiting on, periodically, so the wait is legible as progress.\n if (waitedMs % DRAIN_PROGRESS_MS === 0) {\n console.log(\n `workflow-runner: still draining \u2014 ${agentPool.snapshot().inflight} agent turn(s), ` +\n `${commitPool.snapshot().inflight} commit(s) in flight after ${Math.round(waitedMs / 1000)}s.`,\n );\n }\n }\n console.log(\"workflow-runner: shutdown complete.\");\n process.exit(0);\n}\n\n/** How often the drain reports what it is still waiting on. */\nconst DRAIN_PROGRESS_MS = 30_000;\n\nfunction requestShutdown(signal: NodeJS.Signals): void {\n shutdownRequested = true;\n console.log(`workflow-runner: ${signal} received; stopping new claims.`);\n const inflight =\n agentPool.snapshot().inflight + commitPool.snapshot().inflight;\n if (inflight > 0) {\n // AGE-927: the drain below protects these turns, but ONLY if this process\n // is the one that got the signal. `pnpm workflow-runner` forks node under a\n // pnpm parent, so signalling the parent \u2014 or `pkill -f workflow-runner`,\n // which matches BOTH \u2014 tears the child down before the drain can run. An\n // abandoned turn is invisible until its heartbeat TTL expires (~12min\n // observed), and the job then parks reporting \"heartbeat expired\" rather\n // than the real cause. Warn at the moment the operator can still back out.\n console.log(\n `workflow-runner: WAITING on ${inflight} in-flight turn(s) before exit. ` +\n `Do not kill this process or its parent \u2014 an abandoned turn is discarded ` +\n `and its job parks on the heartbeat TTL with a misleading reason.`,\n );\n }\n if (server.listening) server.close();\n void finishShutdown();\n}\n\n/**\n * AGE-497. Two things, both at start-up and both non-fatal:\n *\n * 1. DERIVE `STACKS_SCHEMA_REVISION` from the checkout when it is unset, and\n * write it into `process.env` so the shared `resolveRevisionStamp()` \u2014 which\n * every claim presents through `claimPresentation` \u2014 picks it up with no\n * change to the mirrored revision contract or to any call site.\n * 2. PROBE the control plane's `/api/health` with the resulting stamp, so a\n * mismatch is reported here instead of at the first burnt claim.\n *\n * Neither exits: an un-stamped dev runner against an un-stamped dev control\n * plane is legitimate, and the probe reports what actually matters.\n */\nlet lastRevisionProbeAt = 0;\n\nasync function reportRevisionHealth(): Promise<void> {\n lastRevisionProbeAt = Date.now();\n const probe = await probeRevisionHealth({\n mcpUrl: MCP_URL,\n stamp: resolveRevisionStamp(),\n });\n const line = `[revision] ${probe.status}: ${probe.message}`;\n if (probe.status === \"incompatible\") console.error(line);\n else console.log(line);\n}\n\n/**\n * AGE-497. REFUSE to start on a checkout a stage cannot legitimately be grounded\n * from \u2014 parked on a stage branch, detached, behind its upstream, or pointing at\n * the wrong repository.\n *\n * The check itself is not new (`checkRepos` computed the right numbers all\n * along); what was missing is that it only ever ran inside the manually-invoked\n * `pnpm harness:preflight`, and its verdict was a WARN. A runner was pointed at a\n * spent execution clone for over a week because nothing ran it. This runs on every\n * launch \u2014 and once mode is launchd-respawned per unit of work, so it re-runs\n * there too.\n *\n * Placed BEFORE `refreshRoleTokens()` so a misconfigured runner exits without\n * spending the one-time self-hosted bootstrap grant.\n */\nasync function assertReposUsable(): Promise<void> {\n const override = process.env[STALE_CHECKOUT_OVERRIDE] === \"1\";\n let rows;\n try {\n rows = applyStaleCheckoutOverride(\n await checkRepos({\n env: process.env,\n exists: existsSync,\n git: (cwd, args) => runGit(cwd, args),\n }),\n override,\n );\n } catch (err) {\n console.error(\n \"workflow-runner: could not validate STACKS_RUNNER_REPOS:\",\n err instanceof Error ? err.message : String(err),\n );\n process.exit(1);\n }\n console.log(renderTable(rows));\n if (rows.some((r) => r.status === \"FAIL\")) {\n console.error(\n `workflow-runner: refusing to start \u2014 STACKS_RUNNER_REPOS points at a checkout that cannot ground a stage (see the FAIL rows above). Fix agents/.env, or set ${STALE_CHECKOUT_OVERRIDE}=1 to start anyway.`,\n );\n process.exit(1);\n }\n}\n\nfunction stampSchemaRevision(): void {\n if (\n !process.env.STACKS_SCHEMA_REVISION &&\n typeof __STACKS_BUNDLED_SCHEMA_REVISION__ === \"string\"\n ) {\n process.env.STACKS_SCHEMA_REVISION = __STACKS_BUNDLED_SCHEMA_REVISION__;\n }\n if (\n !process.env.STACKS_APP_REVISION &&\n typeof __STACKS_BUNDLED_APP_REVISION__ === \"string\"\n ) {\n process.env.STACKS_APP_REVISION = __STACKS_BUNDLED_APP_REVISION__;\n }\n const resolved = resolveSchemaRevision(process.env, (p) => readdirSync(p));\n if (resolved.source === \"migrations\" && resolved.revision) {\n process.env.STACKS_SCHEMA_REVISION = resolved.revision;\n }\n const line = `workflow-runner: schema revision \u2014 ${resolved.detail}`;\n if (resolved.source === \"none\") console.warn(line);\n else console.log(line);\n}\n\nvoid (async () => {\n process.once(\"SIGINT\", () => requestShutdown(\"SIGINT\"));\n process.once(\"SIGTERM\", () => requestShutdown(\"SIGTERM\"));\n stampSchemaRevision();\n await assertReposUsable();\n\n // Provision role tokens BEFORE accepting any handoff \u2014 a drive must never\n // present an empty/expired token. Fail closed: exit if auth can't be provisioned\n // (a bad bootstrap token, an unreachable exchange, or a missing legacy PAT).\n try {\n await refreshRoleTokens();\n } catch (err) {\n console.error(\n \"Failed to provision runner auth:\",\n err instanceof Error ? err.message : String(err),\n );\n process.exit(1);\n }\n console.log(`workflow-runner: auth mode = ${authProvider.mode}`);\n console.log(\n `workflow-runner: pools \u2014 agent-turn max ${MAX_CONCURRENT_JOBS} (hard cap ${MAX_AGENT_JOBS_HARD}), commit max ${MAX_CONCURRENT_COMMITS} (hard cap ${MAX_COMMIT_JOBS_HARD}); job-id dedup shared across webhook + poll.`,\n );\n await reportRevisionHealth();\n\n if (RUN_ONCE) {\n // Once mode: no webhook listener (the sweep covers that leg's latency;\n // skipping it lets a canary run beside a long-lived runner on this host).\n await runOnce(await resolvePollWorkspace());\n }\n\n server.listen(PORT, HOST, () => {\n console.log(\n `workflow-runner listening on ${HOST}:${PORT} (POST agent.handoff here${POLL_MS > 0 ? `; poll mode every ${POLL_MS}ms` : \"\"})`,\n );\n });\n\n if (POLL_MS > 0) {\n const workspaceId = await resolvePollWorkspace();\n console.log(\n `[poll] webhook-less mode: polling workspace ${workspaceId} every ${POLL_MS}ms`,\n );\n if (POLL_HARNESS_RUN_ID) {\n console.log(\n `[poll] scope: harness ${POLL_HARNESS_RUN_ID} (all other workspace jobs ignored)`,\n );\n }\n while (!shutdownRequested) {\n try {\n await tickWithWatchdog(workspaceId);\n } catch (err) {\n console.error(\"[poll] tick failed:\", err);\n }\n // AGE-497: prod redeploys under a long-lived runner, so re-ask on a slow\n // timer \u2014 the drift is otherwise silent until a claim fails closed.\n if (Date.now() - lastRevisionProbeAt >= REVISION_PROBE_MS) {\n await reportRevisionHealth();\n }\n await delay(POLL_MS);\n }\n }\n})();\n", "/**\n * Claude Agent SDK runtime (the default). Auth: ANTHROPIC_API_KEY from the\n * environment (or a local Claude Code login).\n */\nimport {\n query,\n type EffortLevel,\n type Options,\n} from \"@anthropic-ai/claude-agent-sdk\";\n\nimport { buildExecutorHooks } from \"../executor-hooks.js\";\nimport type { JentrixAgentConfig, JentrixConnection } from \"../jentrix.js\";\n\n/** The pinned Claude model (STACKS_AGENT_MODEL override). Exported so the\n * workflow runner can record it on claim_agent_job \u2014 a silent model change\n * must be diagnosable from the run ledger. */\nexport function claudeModel(): string {\n return process.env.STACKS_AGENT_MODEL ?? \"claude-opus-4-8\";\n}\n\n/** Per-leg Claude model pins. Planner legs (authoring / planning / plan\n * revision) and executor legs (stage execution) may run different models:\n * STACKS_PLANNER_MODEL / STACKS_EXECUTOR_MODEL override per leg, both\n * falling back to the process-wide STACKS_AGENT_MODEL pin. */\nexport function claudeLegModel(leg: \"planner\" | \"executor\"): string {\n const override =\n leg === \"planner\"\n ? process.env.STACKS_PLANNER_MODEL\n : process.env.STACKS_EXECUTOR_MODEL;\n const trimmed = override?.trim();\n return trimmed ? trimmed : claudeModel();\n}\n\nconst CLAUDE_EFFORTS: readonly EffortLevel[] = [\n \"low\",\n \"medium\",\n \"high\",\n \"xhigh\",\n \"max\",\n];\n\nconst SCRUBBED_ENV_KEYS = new Set([\n \"STACKS_TOKEN\",\n \"STACKS_RUNNER_TOKEN\",\n \"STACKS_PLANNER_TOKEN\",\n \"STACKS_REVIEWER_TOKEN\",\n \"STACKS_WEBHOOK_SECRET\",\n \"STACKS_BOOTSTRAP_TOKEN\",\n \"STACKS_CLAIM_URL\",\n \"STACKS_RUNNER_AUTH_STATE\",\n \"STACKS_WORKER_HEARTBEAT_TOKEN\",\n \"STACKS_RUNNER_ROLE_BINDINGS\",\n]);\n\n/** AGE-926: the output ceiling a leg gets when the host sets none. A submit\n * payload grows with the work it carries \u2014 a 50-criterion `submit_plan` blew\n * the SDK's 32000 default and killed the leg *mid-submit*, discarding a\n * 19-minute planning turn whose only remaining artifact was the error text.\n * The failure lands at the most expensive moment of the most expensive turn,\n * so the default belongs here rather than in each operator's env. 64000 is the\n * SDK's documented streaming default and half of what claude-opus-5 allows:\n * high enough that hitting it means the payload should be split, not that the\n * ceiling should grow again. An explicit host value always wins. */\nexport const DEFAULT_MAX_OUTPUT_TOKENS = 64_000;\n\nexport function claudeEnv(): Record<string, string> {\n const env = Object.fromEntries(\n Object.entries(process.env).filter(\n (entry): entry is [string, string] =>\n entry[1] !== undefined && !SCRUBBED_ENV_KEYS.has(entry[0]),\n ),\n );\n // `??=` and not `||=`: an explicit \"0\" is a deliberate (if odd) host choice,\n // and silently replacing it would be the same class of surprise this fixes.\n env.CLAUDE_CODE_MAX_OUTPUT_TOKENS ??= String(DEFAULT_MAX_OUTPUT_TOKENS);\n return env;\n}\n\n/** Pinned reasoning effort for Claude turns (STACKS_CLAUDE_EFFORT). Unset \u21D2\n * the SDK default; an unknown value warns and uses the default \u2014 mirroring\n * codexReasoningEffort's never-silently-escalate posture. */\nexport function claudeEffort(): EffortLevel | undefined {\n const raw = process.env.STACKS_CLAUDE_EFFORT?.trim();\n if (!raw) return undefined;\n if ((CLAUDE_EFFORTS as readonly string[]).includes(raw)) {\n return raw as EffortLevel;\n }\n console.error(\n `Unknown STACKS_CLAUDE_EFFORT \"${raw}\" \u2014 using the SDK default (valid: ${CLAUDE_EFFORTS.join(\", \")}).`,\n );\n return undefined;\n}\n\n/** AGE-414: thrown when the jentrix MCP server is not connected at session init.\n * Without the Jentrix surface the model can only refuse (burning the turn) \u2014\n * and a refusal still counts as a \"successful\" result, so the claimed run\n * would rot until heartbeat expiry. Throwing here lets the runner retry the\n * session in-run (claim + heartbeat stay valid) or fail the job immediately. */\nexport class JentrixMcpUnavailableError extends Error {\n override name = \"JentrixMcpUnavailableError\";\n}\n\nfunction claudeOptions(\n config: JentrixAgentConfig,\n connection: JentrixConnection,\n abortController: AbortController,\n): Options {\n // Default world: the Jentrix tool surface and nothing else. An M7 executor\n // turn opts into repo tools scoped to its checkout so it can implement a\n // change (Read/Write/Edit/Bash + cwd); a REVIEWER turn opts into read-only\n // inspection (repoReadOnly) so it can verify claims without being able to\n // touch the tree. Server-side scopes still gate Jentrix.\n const allowedTools = config.repoCwd\n ? config.repoReadOnly\n ? [\"mcp__jentrix__*\", \"Read\", \"Glob\", \"Grep\"]\n : [\"mcp__jentrix__*\", \"Read\", \"Write\", \"Edit\", \"Bash\"]\n : [\"mcp__jentrix__*\"];\n // AGE-402: allowedTools only AUTO-APPROVES \u2014 every other harness tool stays\n // visible, and each attempt costs a turn plus a permission denial (the M17\n // authoring planner burned 37/40 turns on denied Bash/Read probes). Remove\n // out-of-world tools from the model's view entirely: disallow the mutating/\n // escape hatches a tools-only or read-only turn must never reach. Names not\n // present in a given SDK version are ignored, so the list is a superset.\n const disallowedTools = config.repoCwd\n ? config.repoReadOnly\n ? [\n \"Write\",\n \"Edit\",\n \"NotebookEdit\",\n \"Bash\",\n \"Task\",\n \"WebFetch\",\n \"WebSearch\",\n ]\n : // \"Skill\" joins the deny list now that `settingSources: ['project']`\n // makes the checkout's `.claude/skills` discoverable: those include the\n // operator's harness-driving skill, and a stage turn must never be\n // taught to drive the lifecycle it is being run by. CLAUDE.md is the\n // context this turn needs; the skills are not.\n [\"Task\", \"WebFetch\", \"WebSearch\", \"Skill\"]\n : [\n \"Bash\",\n \"Read\",\n \"Write\",\n \"Edit\",\n \"NotebookEdit\",\n \"Glob\",\n \"Grep\",\n \"Task\",\n \"WebFetch\",\n \"WebSearch\",\n \"Skill\",\n // ToolSearch deliberately NOT denied (AGE-423): when the host CLI\n // defers MCP tools, ToolSearch is the only path to the jentrix surface.\n ];\n // Freeze (H10.6): the SDK cancels the query when its abortController fires.\n // Bridge the incoming AbortSignal (raised by the runner's heartbeat pump on a\n // frozen run) to the controller the SDK understands (also used by the AGE-414\n // init check to cancel a session whose jentrix MCP server failed to connect).\n if (config.signal) {\n if (config.signal.aborted) abortController.abort();\n else\n config.signal.addEventListener(\"abort\", () => abortController.abort(), {\n once: true,\n });\n }\n const effort = CLAUDE_EFFORTS.includes(config.reasoningMode as EffortLevel)\n ? (config.reasoningMode as EffortLevel)\n : claudeEffort();\n return {\n model: config.model ?? claudeModel(),\n ...(effort ? { effort } : {}),\n // AGE-423: the host runtime may DEFER MCP tools behind ToolSearch (a\n // server-gated behavior that flipped on mid-day 2026-07-20) \u2014 teach the\n // model the load path. The sentinel makes a genuinely tool-less session\n // self-report in one cheap turn instead of producing a plausible refusal\n // that reads as success and orphans the claimed run.\n systemPrompt: `${config.systemPrompt}\\n\\nThe mcp__jentrix__ tools may be DEFERRED: if they are not in your tool list, load them with ToolSearch (e.g. query \"select:mcp__jentrix__get_agent_job\" or a keyword search) before use \u2014 verified to work. Only if the mcp__jentrix__ tools are absent AND ToolSearch is unavailable or cannot find them, reply with exactly STACKS_MCP_UNAVAILABLE and nothing else.`,\n maxTurns: config.maxTurns ?? 30,\n ...(config.repoCwd ? { cwd: config.repoCwd } : {}),\n abortController,\n env: claudeEnv(),\n ...(config.executablePath\n ? { pathToClaudeCodeExecutable: config.executablePath }\n : {}),\n // AGE-423: never load the operator's USER/LOCAL Claude Code settings \u2014\n // without that the session inherits every user-level MCP server (claude.ai\n // connectors, plugins; 25 servers observed) into the harness agent world.\n // 'project' is required for the checkout's CLAUDE.md (\"Must include\n // 'project' to load CLAUDE.md files\" \u2014 SDK Options) and loads only\n // .claude/settings.json from the repo, never ~/.claude: a checkout turn\n // that cannot read the project's own architecture rules re-invents\n // conventions the reviewer then rejects. Tools-only turns keep total\n // isolation \u2014 they have no checkout and would only pay the token cost.\n settingSources: config.repoCwd ? [\"project\"] : [],\n mcpServers: {\n jentrix: {\n type: \"http\",\n url: connection.url,\n headers: { Authorization: `Bearer ${connection.token}` },\n },\n },\n allowedTools,\n disallowedTools,\n // W3: mechanical enforcement of the two executor contracts that were prose\n // only \u2014 the runner owns a stage's submissions, and a turn may not end with\n // verification still running in the background. Harness stage executor legs\n // only (see JentrixAgentConfig.runnerOwnsSubmissions).\n ...(config.runnerOwnsSubmissions && config.repoCwd\n ? { hooks: buildExecutorHooks({ cwd: config.repoCwd }) }\n : {}),\n };\n}\n\nexport async function runClaudeAgent(\n prompt: string,\n config: JentrixAgentConfig,\n connection: JentrixConnection,\n): Promise<string> {\n const verbose = process.env.STACKS_AGENT_VERBOSE === \"1\";\n const abortController = new AbortController();\n const session = query({\n prompt,\n options: claudeOptions(config, connection, abortController),\n });\n for await (const message of session) {\n // AGE-414/423: fail fast ONLY on a terminal init status. \"pending\" is the\n // NORMAL init state for HTTP servers (connect in flight), and the tools\n // may be deferred behind ToolSearch anyway \u2014 the prompt's ToolSearch\n // guidance + STACKS_MCP_UNAVAILABLE sentinel handle everything else.\n if (message.type === \"system\" && message.subtype === \"init\") {\n const servers = (\n message as unknown as {\n mcp_servers?: { name: string; status: string }[];\n }\n ).mcp_servers;\n const status = servers?.find((s) => s.name === \"jentrix\")?.status;\n if (\n status === \"failed\" ||\n status === \"needs-auth\" ||\n status === \"disabled\"\n ) {\n abortController.abort();\n throw new JentrixMcpUnavailableError(\n `jentrix MCP server failed at session init (status: ${status})`,\n );\n }\n }\n if (verbose && message.type === \"assistant\") {\n for (const block of message.message.content) {\n if (block.type === \"text\") console.error(`[agent] ${block.text}`);\n if (block.type === \"tool_use\") console.error(`[tool] ${block.name}`);\n }\n }\n if (message.type === \"result\") {\n // AGE-938: the result message carries the session's provider-reported\n // usage \u2014 report it on BOTH outcomes (a failed turn still spent tokens).\n // Anthropic's input_tokens EXCLUDES the cache fields (siblings), so\n // total input is the three summed; the split rides beside it.\n const usage = (\n message as {\n usage?: {\n input_tokens?: number;\n cache_creation_input_tokens?: number;\n cache_read_input_tokens?: number;\n output_tokens?: number;\n };\n }\n ).usage;\n const costUsd = (message as { total_cost_usd?: number }).total_cost_usd;\n if (config.onUsage && usage) {\n try {\n config.onUsage({\n inputTokens:\n (usage.input_tokens ?? 0) +\n (usage.cache_creation_input_tokens ?? 0) +\n (usage.cache_read_input_tokens ?? 0),\n outputTokens: usage.output_tokens ?? 0,\n ...(typeof usage.cache_read_input_tokens === \"number\"\n ? { cacheReadTokens: usage.cache_read_input_tokens }\n : {}),\n ...(typeof usage.cache_creation_input_tokens === \"number\"\n ? { cacheCreationTokens: usage.cache_creation_input_tokens }\n : {}),\n ...(typeof costUsd === \"number\" ? { costUsd } : {}),\n });\n } catch {\n /* usage reporting must never break the turn */\n }\n }\n if (message.subtype === \"success\") {\n // AGE-423: the sentinel means the session started tool-less (jentrix\n // MCP lost the connect race) \u2014 surface it as the retriable error.\n if (message.result.trim() === \"STACKS_MCP_UNAVAILABLE\") {\n throw new JentrixMcpUnavailableError(\n \"session self-reported missing mcp__jentrix__ tools (connect race lost)\",\n );\n }\n return message.result;\n }\n throw new Error(`Agent run failed: ${message.subtype}`);\n }\n }\n throw new Error(\"Agent run ended without a result message\");\n}\n", "/**\n * Agent SDK hooks for harness EXECUTOR legs (Harness Reliability W3).\n *\n * Every role contract used to be prose in a system prompt, and the runner\n * registered zero hooks \u2014 so a model could narrate compliance it did not have\n * and nothing stopped it at the boundary. These are the two contracts worth\n * enforcing mechanically, both observed failing on the M18 run:\n *\n * 1. The RUNNER owns a harness stage's submissions. It executes the declared\n * verification commands itself, captures the diff, and attests the\n * evidence; the executor's job is to change the tree and describe what it\n * changed. An executor that submits anyway races the runner and lands a\n * claim about a tree nobody captured. PreToolUse DENIES those calls while\n * the worktree still has uncommitted changes, naming the dirty paths, so\n * the ledger never receives a claim about work that is not in the subject\n * the evidence binds to.\n *\n * 2. Evidence is an observed result, never an intention (AGENT_GUIDELINES \u00A75).\n * A turn ends the moment the model produces its final message: a suite\n * still running in the background at that point is evidence LOST, and the\n * summary that says \"tests are running\" becomes the stage's execution\n * record. Stop BLOCKS that ending \u2014 bounded to two nudges per turn, then\n * allows, because an unbounded Stop block against a confused model is a new\n * wedge and W1's park checkpoint is the backstop.\n *\n * Deliberately NOT enforced: \"ends with a dirty tree\" is the NORMAL, correct\n * ending for a harness executor turn \u2014 the runner captures the diff from that\n * tree straight afterwards. Blocking it would fire on every healthy turn.\n *\n * Claude legs only; Codex legs cannot be hooked (their honesty is enforced\n * server-side by the attested evidence gate and the review disposition rules).\n */\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\n\nimport type {\n HookCallbackMatcher,\n HookEvent,\n HookInput,\n HookJSONOutput,\n PreToolUseHookInput,\n StopHookInput,\n} from \"@anthropic-ai/claude-agent-sdk\";\n\nconst execFileP = promisify(execFile);\n\n/** Read git state in the turn's worktree. Injected so the hooks are testable. */\nexport type HookGit = (cwd: string, args: string[]) => Promise<string>;\n\nconst defaultGit: HookGit = async (cwd, args) => {\n const { stdout } = await execFileP(\"git\", args, {\n cwd,\n maxBuffer: 16 * 1024 * 1024,\n });\n return stdout;\n};\n\n/** How many times one turn may be nudged before Stop is allowed through. */\nexport const STOP_BLOCK_LIMIT = 2;\n\n/** Artifact kinds whose body IS a claim about the tree \u2014 the runner authors\n * these from what it actually observed, never the model. */\nconst TREE_CLAIMING_ARTIFACT_KINDS = new Set([\n \"DIFF_OR_PATCH\",\n \"TEST_EVIDENCE\",\n \"EXECUTION_SUMMARY\",\n]);\n\n/**\n * Does this tool call make a claim about the working tree that the RUNNER owns?\n * PURE \u2014 exported for the smoke test. Tool names arrive MCP-prefixed\n * (`mcp__jentrix__\u2026`), and a bare name is accepted too so the check does not\n * depend on the server label.\n */\nexport function isRunnerOwnedSubmission(\n toolName: string,\n toolInput: unknown,\n): boolean {\n const name = toolName.replace(/^mcp__[^_]+__/, \"\");\n if (name === \"submit_execution_result\") return true;\n if (name === \"submit_harness_stage_result\") return true;\n if (name === \"submit_harness_artifact\") {\n const kind = (toolInput as { kind?: unknown } | null)?.kind;\n return typeof kind === \"string\" && TREE_CLAIMING_ARTIFACT_KINDS.has(kind);\n }\n return false;\n}\n\n/** Porcelain lines for the worktree; [] when git cannot be read (fail-soft \u2014 a\n * hook must never be the reason a turn dies). */\nasync function dirtyPaths(git: HookGit, cwd: string): Promise<string[]> {\n try {\n const out = await git(cwd, [\"status\", \"--porcelain\"]);\n return out\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter(Boolean);\n } catch {\n return [];\n }\n}\n\nexport interface ExecutorHookOptions {\n /** The job's worktree \u2014 the tree every claim is about. */\n cwd: string;\n git?: HookGit;\n log?: (msg: string) => void;\n}\n\n/**\n * Build the `hooks` option for one harness executor turn. The Stop counter is\n * per-turn because this returns a fresh closure per session.\n */\nexport function buildExecutorHooks(\n opts: ExecutorHookOptions,\n): Partial<Record<HookEvent, HookCallbackMatcher[]>> {\n const git = opts.git ?? defaultGit;\n const log = opts.log ?? (() => {});\n let stopBlocks = 0;\n\n const preToolUse = async (input: HookInput): Promise<HookJSONOutput> => {\n const call = input as PreToolUseHookInput;\n if (!isRunnerOwnedSubmission(call.tool_name, call.tool_input)) return {};\n const dirty = await dirtyPaths(git, opts.cwd);\n if (dirty.length === 0) return {};\n const named = dirty.slice(0, 10).join(\"; \");\n const more = dirty.length > 10 ? ` (+${dirty.length - 10} more)` : \"\";\n log(\n `[executor-hook] denied ${call.tool_name}: ${dirty.length} uncommitted change(s) in ${opts.cwd}`,\n );\n return {\n hookSpecificOutput: {\n hookEventName: \"PreToolUse\",\n permissionDecision: \"deny\",\n permissionDecisionReason:\n `${call.tool_name} is the RUNNER's to submit, and the worktree still has ` +\n `${dirty.length} uncommitted change(s): ${named}${more}. The runner captures the diff, ` +\n `executes the stage's declared verification commands itself, and attests the evidence ` +\n `after your turn ends \u2014 a submission now would record a claim about a tree nothing has ` +\n `captured. Finish your edits and end the turn with your summary (including the ` +\n `ADDRESSED_FINDINGS line); if this stage commits locally, commit first so the claim ` +\n `matches HEAD.`,\n },\n };\n };\n\n const stop = async (input: HookInput): Promise<HookJSONOutput> => {\n const end = input as StopHookInput;\n const pending = end.background_tasks ?? [];\n if (pending.length === 0) return {};\n if (stopBlocks >= STOP_BLOCK_LIMIT) {\n // Bounded on purpose: an unbounded block against a model that cannot\n // resolve the nudge is a new wedge, and the park checkpoint (W1) plus the\n // runner's own foreground verification are the backstops.\n log(\n `[executor-hook] stop allowed after ${stopBlocks} block(s) with ${pending.length} background task(s) still in flight`,\n );\n return {};\n }\n stopBlocks += 1;\n log(\n `[executor-hook] blocked stop #${stopBlocks}: ${pending.length} background task(s) still running`,\n );\n return {\n decision: \"block\",\n reason:\n `${pending.length} background task(s) are still running. Your session ends the moment ` +\n `you produce a final message, so a suite left in the background is evidence LOST and the ` +\n `summary becomes this stage's execution record. Wait for each command in the FOREGROUND, ` +\n `read its actual exit code, and report the real result \u2014 a red result reported honestly ` +\n `is a working system; a result you did not see is not evidence.`,\n };\n };\n\n return {\n PreToolUse: [{ hooks: [preToolUse] }],\n Stop: [{ hooks: [stop] }],\n };\n}\n", "/**\n * OpenAI Codex runtime \u2014 runs the same agents on a ChatGPT subscription.\n *\n * Auth: the SDK spawns the bundled `codex` binary, which reads the\n * credentials cached by `codex login` (~/.codex/auth.json). No OpenAI API\n * key needed. The Jentrix MCP server is injected per-run via config\n * overrides \u2014 your global ~/.codex/config.toml is never edited. It IS still\n * read as the base config, though, so every behavior-critical knob (model,\n * reasoning effort) is pinned explicitly below \u2014 an interactive `codex`\n * model switch must never silently re-model an unattended agent turn.\n *\n * Tool surface parity with the Claude runtime: web search and image viewing\n * are disabled. Tools-only agents (no repoCwd) run with the shell OFF and a\n * read-only sandbox, so their only world is the Jentrix MCP tools (the PAT's\n * scopes are enforced server-side regardless \u2014 P2.1). A repo turn enables the\n * shell with the orchestrator's credentials scrubbed from the child env:\n * reviewers remain read-only while executors receive workspace-write access to\n * their isolated worktree.\n */\nimport { Codex, type ModelReasoningEffort } from \"@openai/codex-sdk\";\n\nimport type { JentrixAgentConfig, JentrixConnection } from \"../jentrix.js\";\n\n// The model every Codex turn runs unless explicitly overridden. Pinned (never\n// \"the CLI's current default\"): the SDK-spawned codex binary reads\n// ~/.codex/config.toml as its BASE config, so an unset model here silently\n// follows whatever the operator last picked interactively \u2014 that is how the\n// Jul-2026 gpt-5.6-sol@high rollout re-modeled the harness reviewer and turned\n// the review loop non-convergent. gpt-5.5 is the loop's validated model;\n// gpt-5.6-terra@medium is the calibrated 5.6-generation alternative.\nconst DEFAULT_CODEX_MODEL = \"gpt-5.5\";\n\nconst REASONING_EFFORTS: readonly ModelReasoningEffort[] = [\n \"minimal\",\n \"low\",\n \"medium\",\n \"high\",\n \"xhigh\",\n];\n\n/** Resolve the Codex model pin. STACKS_CODEX_MODEL wins \u2014 the per-provider\n * override the multi-provider workflow runner needs (STACKS_AGENT_MODEL would\n * also repoint the Claude planner/executor turns); STACKS_AGENT_MODEL keeps\n * its documented applies-to-the-active-provider meaning for the single-provider\n * reference agents. */\nexport function codexModel(): string {\n return (\n process.env.STACKS_CODEX_MODEL ??\n process.env.STACKS_AGENT_MODEL ??\n DEFAULT_CODEX_MODEL\n );\n}\n\n/** Resolve the pinned reasoning effort (STACKS_CODEX_EFFORT, default medium \u2014\n * the provider default; explicit so a config.toml `model_reasoning_effort`\n * can never silently escalate an unattended reviewer to high/xhigh). */\nexport function codexReasoningEffort(): ModelReasoningEffort {\n const raw = process.env.STACKS_CODEX_EFFORT ?? \"medium\";\n if ((REASONING_EFFORTS as readonly string[]).includes(raw)) {\n return raw as ModelReasoningEffort;\n }\n console.error(\n `Unknown STACKS_CODEX_EFFORT \"${raw}\" \u2014 using \"medium\" (valid: ${REASONING_EFFORTS.join(\", \")}).`,\n );\n return \"medium\";\n}\n\n/**\n * Credentials STRIPPED from the codex child environment. Shell commands run as\n * children of the codex process and inherit its env, so with the shell enabled\n * (checkout-inspection turns, below) a prompt-injected `env` would otherwise\n * read the ORCHESTRATOR's credentials \u2014 the runner admin token, the other\n * roles' tokens, the Claude API key. The per-turn bearer (STACKS_MCP_BEARER)\n * is the only Jentrix credential a codex turn needs.\n */\nconst SCRUBBED_ENV_KEYS = new Set([\n \"ANTHROPIC_API_KEY\",\n \"STACKS_TOKEN\",\n \"STACKS_RUNNER_TOKEN\",\n \"STACKS_PLANNER_TOKEN\",\n \"STACKS_REVIEWER_TOKEN\",\n \"STACKS_WEBHOOK_SECRET\",\n \"STACKS_BOOTSTRAP_TOKEN\",\n \"STACKS_CLAIM_URL\",\n \"STACKS_RUNNER_AUTH_STATE\",\n \"STACKS_WORKER_HEARTBEAT_TOKEN\",\n \"STACKS_RUNNER_ROLE_BINDINGS\",\n]);\n\n/** The child env: process.env (HOME for ~/.codex login, PATH, \u2026) minus the\n * orchestrator credentials, plus this turn's MCP bearer. */\nexport function codexEnv(bearer: string): Record<string, string> {\n const env: Record<string, string> = {};\n for (const [key, value] of Object.entries(process.env)) {\n if (value !== undefined && !SCRUBBED_ENV_KEYS.has(key)) env[key] = value;\n }\n env.STACKS_MCP_BEARER = bearer;\n return env;\n}\n\nexport async function runCodexAgent(\n prompt: string,\n config: JentrixAgentConfig,\n connection: JentrixConnection,\n): Promise<string> {\n const verbose = process.env.STACKS_AGENT_VERBOSE === \"1\";\n // Repo turns use the shell against the explicitly scoped checkout. Reviewers\n // are marked repoReadOnly and stay in the read-only sandbox; executors run in\n // an isolated harness worktree and need workspace-write to implement changes.\n const hasCheckout = Boolean(config.repoCwd);\n const canWriteCheckout = hasCheckout && !config.repoReadOnly;\n const codex = new Codex({\n ...(config.executablePath\n ? { codexPathOverride: config.executablePath }\n : {}),\n // The Codex CLI reads the MCP bearer from the env var named below. It must be\n // the PER-ROLE token this run was handed (connection.token) \u2014 NOT the process\n // STACKS_TOKEN \u2014 so a multi-token orchestrator (the workflow runner: reviewer\n // \u2260 runner \u2260 planner) authenticates each turn as the right principal and the\n // server turn-guard (the submitting token must equal the phase's role token)\n // passes. Without this every Codex turn authenticates as the process\n // STACKS_TOKEN and a reviewer submit_review is rejected CONFLICT \"workflow\n // expects a different role\". The env is SCRUBBED of the orchestrator's other\n // credentials (see codexEnv).\n env: codexEnv(connection.token),\n config: {\n mcp_servers: {\n jentrix: {\n url: connection.url,\n bearer_token_env_var: \"STACKS_MCP_BEARER\",\n },\n },\n features: { shell_tool: hasCheckout },\n tools: { web_search: false, view_image: false },\n },\n });\n const thread = codex.startThread({\n // ALWAYS pinned (see codexModel/codexReasoningEffort above) \u2014 never left to\n // the CLI default, which is really the operator's ~/.codex/config.toml.\n model: config.model ?? codexModel(),\n modelReasoningEffort: REASONING_EFFORTS.includes(\n config.reasoningMode as ModelReasoningEffort,\n )\n ? (config.reasoningMode as ModelReasoningEffort)\n : codexReasoningEffort(),\n sandboxMode: canWriteCheckout ? \"workspace-write\" : \"read-only\",\n approvalPolicy: \"never\",\n skipGitRepoCheck: true,\n ...(config.repoCwd ? { workingDirectory: config.repoCwd } : {}),\n });\n\n // Codex threads take one prompt \u2014 the persona rides in front.\n const fullPrompt = `${config.systemPrompt}\\n\\n---\\n\\n${prompt}`;\n\n // AGE-938: sum provider-reported per-turn usage and hand it to the caller.\n // OpenAI's input_tokens INCLUDES cached (cached_input_tokens is a subset \u2192\n // cacheReadTokens); Codex has no cache-creation concept and reports no cost\n // (subscription auth) \u2014 those fields stay unreported, never fabricated.\n interface CodexUsage {\n input_tokens?: number;\n cached_input_tokens?: number;\n output_tokens?: number;\n }\n const sums = { input: 0, cached: 0, output: 0 };\n let sawUsage = false;\n let sawCached = false;\n const addUsage = (usage: CodexUsage | undefined) => {\n if (!usage) return;\n sawUsage = true;\n sums.input += usage.input_tokens ?? 0;\n sums.output += usage.output_tokens ?? 0;\n if (typeof usage.cached_input_tokens === \"number\") {\n sawCached = true;\n sums.cached += usage.cached_input_tokens;\n }\n };\n const reportUsage = () => {\n if (!config.onUsage || !sawUsage) return;\n try {\n config.onUsage({\n inputTokens: sums.input,\n outputTokens: sums.output,\n ...(sawCached ? { cacheReadTokens: sums.cached } : {}),\n });\n } catch {\n /* usage reporting must never break the turn */\n }\n };\n\n if (verbose) {\n const { events } = await thread.runStreamed(fullPrompt);\n let final = \"\";\n for await (const event of events) {\n if (event.type === \"item.completed\") {\n const item = event.item as { type?: string; text?: string };\n if (item.type === \"agent_message\" && item.text) final = item.text;\n console.error(`[codex] ${item.type ?? \"item\"}`);\n }\n if (event.type === \"turn.completed\") {\n addUsage((event as { usage?: CodexUsage }).usage);\n }\n if (event.type === \"turn.failed\") {\n reportUsage();\n throw new Error(\"Codex run failed\");\n }\n }\n reportUsage();\n if (!final) throw new Error(\"Codex run ended without a final response\");\n return final;\n }\n\n const turn = await thread.run(fullPrompt);\n addUsage((turn as { usage?: CodexUsage }).usage);\n reportUsage();\n if (!turn.finalResponse) {\n throw new Error(\"Codex run ended without a final response\");\n }\n return turn.finalResponse;\n}\n", "/**\n * Shared plumbing for the Jentrix reference agents (P4.2).\n *\n * Every agent talks to Jentrix EXCLUSIVELY through the MCP server \u2014 the same\n * surface any third-party agent uses \u2014 authenticated by a PAT minted on\n * /account/tokens. No filesystem or bash tools are allowed: the agent's\n * world is the Jentrix tool surface.\n *\n * Two interchangeable runtimes (STACKS_AGENT_PROVIDER):\n * \"claude\" (default) \u2014 Claude Agent SDK; needs ANTHROPIC_API_KEY.\n * \"codex\" \u2014 OpenAI Codex SDK; uses your `codex login`\n * credentials (ChatGPT subscription, no API key).\n * Same prompts, same MCP server, same badges \u2014 the Jentrix platform is\n * runtime-neutral by construction.\n */\nimport { runClaudeAgent } from \"./providers/claude.js\";\nimport { runCodexAgent } from \"./providers/codex.js\";\n\n/**\n * AGE-938: provider-reported usage for one agent turn \u2014 the shape\n * `record_run_usage` accepts. inputTokens is TOTAL input; the cache fields\n * are disjoint subsets of it. Absent field = the runtime did not report it.\n */\nexport interface AgentTurnUsage {\n inputTokens?: number;\n outputTokens?: number;\n cacheReadTokens?: number;\n cacheCreationTokens?: number;\n costUsd?: number;\n}\n\nexport interface JentrixAgentConfig {\n /** Agent persona + task rules. Keep it short; the tools carry the schema. */\n systemPrompt: string;\n /**\n * AGE-938: called with the provider-reported usage when the runtime exposes\n * it (Claude: the result message; Codex: summed turn.completed events).\n * Never called with estimated values. Failures in the callback are the\n * caller's problem \u2014 providers invoke it fire-and-forget.\n */\n onUsage?: (usage: AgentTurnUsage) => void;\n /**\n * Upper bound on agentic turns \u2014 a runaway guard, not a target.\n * Claude-only: Codex manages its own loop budget.\n */\n maxTurns?: number;\n /**\n * Model override for THIS turn. Claude-only: Codex pins its model via\n * STACKS_CODEX_MODEL. Unset \u21D2 the process-wide claudeModel() pin. Lets the\n * multi-role runner pin planner and executor legs to different models\n * (STACKS_PLANNER_MODEL / STACKS_EXECUTOR_MODEL \u2014 see claudeLegModel).\n */\n model?: string;\n /** Durable release-selected reasoning mode for this turn. */\n reasoningMode?: string;\n /** Absolute provider executable selected by the local runtime probe. */\n executablePath?: string;\n /**\n * Repo-execution context (M7 executor turns). When set, the Claude runtime\n * additionally gets Read/Write/Edit/Bash scoped to `cwd` so the agent can\n * actually implement a change in a checkout \u2014 NOT just operate Jentrix. Leave\n * unset for the default tools-only world (every other agent).\n */\n repoCwd?: string;\n /**\n * Read-only checkout INSPECTION (M7 reviewer turns): the agent can read the\n * working tree at `repoCwd` to verify claims against reality, but cannot\n * modify it. Claude: Read/Glob/Grep only (no Write/Edit/Bash); Codex: the\n * shell under its read-only sandbox. Ignored without `repoCwd`.\n */\n repoReadOnly?: boolean;\n /**\n * Abort signal (H10.6). When a harness run is frozen mid-turn, the runner\n * aborts this signal so the runtime stops the in-flight subprocess \u2014 freeze is\n * honored by the external process, not only by Jentrix server guards.\n */\n signal?: AbortSignal;\n /**\n * W3: this is a HARNESS stage executor leg, where the RUNNER submits the\n * stage result and attests the evidence. The Claude runtime then registers the\n * executor hooks (see lib/executor-hooks.ts): a submission attempted while the\n * worktree is dirty is denied, and a turn ending with background work still\n * running is nudged (twice, then allowed).\n *\n * Scoped deliberately: on a GENERIC M7 execution leg the model is supposed to\n * call `submit_execution_result` itself, from a checkout that is legitimately\n * dirty (nothing commits there), so an unscoped hook would deny every healthy\n * non-harness execution turn.\n */\n runnerOwnsSubmissions?: boolean;\n}\n\nexport interface JentrixConnection {\n url: string;\n token: string;\n}\n\nfunction requireEnv(name: string): string {\n const value = process.env[name];\n if (!value) {\n console.error(\n `Missing ${name}. Copy agents/.env.example to agents/.env and fill it in ` +\n `(export the vars or use \\`node --env-file=.env\\`).`,\n );\n process.exit(1);\n }\n return value;\n}\n\nexport function stacksConnection(): JentrixConnection {\n return {\n url: process.env.STACKS_MCP_URL ?? \"http://localhost:3000/api/mcp\",\n token: requireEnv(\"STACKS_TOKEN\"),\n };\n}\n\nexport type AgentProvider = \"claude\" | \"codex\";\n\nexport function agentProvider(): AgentProvider {\n const raw = process.env.STACKS_AGENT_PROVIDER ?? \"claude\";\n if (raw === \"claude\" || raw === \"codex\") return raw;\n console.error(\n `Unknown STACKS_AGENT_PROVIDER \"${raw}\" \u2014 use \"claude\" (Claude Agent SDK, ` +\n `ANTHROPIC_API_KEY) or \"codex\" (OpenAI Codex SDK, \\`codex login\\`).`,\n );\n process.exit(1);\n}\n\n/**\n * Run one agent task to completion on the configured runtime and return the\n * final result text. Streams progress to stderr when STACKS_AGENT_VERBOSE=1.\n *\n * `opts` lets a multi-agent orchestrator (the M7 workflow runner) override the\n * connection (a per-role PAT, so the turn-guard sees the right token) and the\n * provider per call (planner on Claude, reviewer on Codex) without touching the\n * process-wide env. Both default to the env-derived values.\n */\nexport async function runJentrixAgent(\n prompt: string,\n config: JentrixAgentConfig,\n opts: {\n connection?: JentrixConnection;\n provider?: AgentProvider;\n /** Abort the in-flight turn (freeze) \u2014 threaded into config.signal. */\n signal?: AbortSignal;\n } = {},\n): Promise<string> {\n const connection = opts.connection ?? stacksConnection();\n const provider = opts.provider ?? agentProvider();\n const cfg = opts.signal ? { ...config, signal: opts.signal } : config;\n return provider === \"codex\"\n ? runCodexAgent(prompt, cfg, connection)\n : runClaudeAgent(prompt, cfg, connection);\n}\n\n/** ISO timestamp for \"N hours ago\" \u2014 used for list_activity `since` params. */\nexport function hoursAgo(hours: number): string {\n return new Date(Date.now() - hours * 60 * 60 * 1000).toISOString();\n}\n", "/**\n * Execution contracts \u2014 Zod schemas + inferred types (M12.1).\n *\n * These are the wire/data contracts every ExecutionBackend and SandboxDriver\n * speaks. A RUN is one bounded unit of sandboxed work (a harness stage turn, a\n * standup digest, \u2026) described entirely by a {@link RunManifest}: what code it\n * runs over, what it may mount, which env it inherits, which capabilities it may\n * reach, its resource ceilings, and its egress posture. The backend returns a\n * single structured {@link ResultEnvelope} \u2014 success OR a typed failure (crucially,\n * a resource-limit kill is a *structured failure*, never a silent hang/timeout).\n *\n * Everything here is pure data (no Node imports) so it is equally usable by the\n * app, the reference runner, and tests.\n */\nimport { z } from \"zod\";\n\n/** A POSIX-ish env var name (used for the env allowlist). */\nconst ENV_NAME = /^[A-Za-z_][A-Za-z0-9_]*$/;\n\n// ---------------------------------------------------------------------------\n// Mounts + code snapshot\n// ---------------------------------------------------------------------------\n\nexport const MountModeSchema = z.enum([\"ro\", \"rw\"]);\nexport type MountMode = z.infer<typeof MountModeSchema>;\n\n/** A declared bind mount: a host path made visible inside the sandbox. */\nexport const MountSchema = z.object({\n /** Host source path (absolute) or a named volume. */\n source: z.string().min(1),\n /** Mount point inside the sandbox (absolute). */\n target: z.string().min(1),\n /** Read-only by default \u2014 writable mounts must be declared explicitly. */\n mode: MountModeSchema.default(\"ro\"),\n});\nexport type Mount = z.infer<typeof MountSchema>;\n\n/**\n * A reference to the code the run executes over. The preconfigured-checkout case\n * (`kind: \"checkout\"`, `ref` = an absolute host path) is what the reference runner\n * uses; `git`/`image` are provided for a hosted deployment that provisions the\n * snapshot itself.\n */\nexport const CodeSnapshotSchema = z.object({\n kind: z.enum([\"checkout\", \"git\", \"image\"]).default(\"checkout\"),\n /** checkout \u2192 host path; git \u2192 repo url/slug; image \u2192 container image ref. */\n ref: z.string().min(1),\n /** Optional pinned commit/branch (git snapshots). */\n commit: z.string().optional(),\n /** Optional sub-path within the snapshot to treat as the workdir. */\n path: z.string().optional(),\n});\nexport type CodeSnapshot = z.infer<typeof CodeSnapshotSchema>;\n\n// ---------------------------------------------------------------------------\n// Resource limits\n// ---------------------------------------------------------------------------\n\n/**\n * The run's resource ceilings. `wallMs` is REQUIRED \u2014 every run is deadline-bound\n * so a stalled turn is killed, not left to hang. `cpuMs` is the CPU-time budget\n * (enforced via `ulimit -t` on the host driver and `--ulimit cpu` on Docker); a\n * run that burns past it is killed with a structured resource-limit failure.\n */\nexport const ResourceLimitsSchema = z.object({\n /** Fractional CPU cores for throttling (Docker `--cpus`). Advisory on host. */\n cpus: z.number().positive().optional(),\n /** Hard CPU-time budget in ms \u2014 breaching it KILLS the run (SIGXCPU). */\n cpuMs: z.number().int().positive().optional(),\n /** Memory ceiling in bytes (Docker `--memory`; best-effort on host). */\n memoryBytes: z.number().int().positive().optional(),\n /** Disk/file-size ceiling in bytes (Docker `--ulimit fsize`). */\n diskBytes: z.number().int().positive().optional(),\n /** Wall-clock deadline in ms \u2014 REQUIRED. Breaching it KILLS the run. */\n wallMs: z.number().int().positive(),\n /** Max process/thread count (Docker `--pids-limit`). */\n pids: z.number().int().positive().optional(),\n});\nexport type ResourceLimits = z.infer<typeof ResourceLimitsSchema>;\n\n// ---------------------------------------------------------------------------\n// Egress profile\n// ---------------------------------------------------------------------------\n\n/**\n * The run's network posture. DENY-BY-DEFAULT: absent an explicit profile a run\n * gets no network. `allowlist` requests egress to specific hosts; `open` requests\n * unrestricted egress. Enforcement is the driver's job \u2014 and the LocalDockerDriver\n * only honors a non-deny profile when the operator has set STACKS_SANDBOX_ALLOW_NET=1\n * (the single dev bypass, mirroring the webhook SSRF allow-flag). Off by default.\n */\nexport const EgressProfileSchema = z.object({\n mode: z.enum([\"deny\", \"allowlist\", \"open\"]).default(\"deny\"),\n /** Hosts permitted when `mode === \"allowlist\"` (advisory; needs a proxy to filter per-host). */\n allow: z.array(z.string()).default([]),\n});\nexport type EgressProfile = z.infer<typeof EgressProfileSchema>;\n\n// ---------------------------------------------------------------------------\n// Runtime class + risk class\n// ---------------------------------------------------------------------------\n\n/**\n * The container/VM runtime the sandbox runs under. `runc` is the stock OCI runtime\n * (a shared-kernel container \u2014 NOT a trust boundary for hostile code). `gvisor`\n * (runsc) interposes an application kernel; `microvm` (Firecracker/Kata-class) is\n * a hardware-virtualized boundary for the most hostile code. Selection is\n * RISK-CLASS-DRIVEN (see {@link RiskClass}) and expressed here on the manifest so\n * the driver can pick `--runtime` \u2014 even though the MANAGED runtime is brought up\n * in M12 infra-a/infra-b; the local Docker driver honors whatever `--runtime` the\n * host has installed and otherwise runs stock runc.\n */\nexport const RuntimeClassSchema = z.enum([\"runc\", \"gvisor\", \"microvm\"]);\nexport type RuntimeClass = z.infer<typeof RuntimeClassSchema>;\n\n/**\n * The trust posture of a capability (and, aggregated, of the whole run). Drives\n * the runtime-class selection: `trusted` code may run under stock runc, `standard`\n * work is isolated under gVisor, and `hostile` code (untrusted input, third-party\n * plugins) is pushed to a microVM boundary.\n */\nexport const RiskClassSchema = z.enum([\"trusted\", \"standard\", \"hostile\"]);\nexport type RiskClass = z.infer<typeof RiskClassSchema>;\n\n// ---------------------------------------------------------------------------\n// Capability handles\n// ---------------------------------------------------------------------------\n\n/**\n * A capability the run may exercise, referenced by an OPAQUE handle \u2014 never raw\n * secret material. The host resolves/injects the real thing at the sandbox\n * boundary (e.g. an MCP bearer, a single-use git push token). Keeping capabilities\n * as handles is what lets a manifest be logged/persisted without leaking secrets.\n *\n * `riskClass` is the per-capability trust posture. The sandbox controller reduces\n * the capabilities' risk classes to the run's {@link RuntimeClass} (the strictest\n * wins) \u2014 this is the \"per-capability, risk-class-driven\" runtime selection.\n */\nexport const CapabilityHandleSchema = z.object({\n id: z.string().min(1),\n kind: z.enum([\"mcp\", \"git\", \"secret\", \"network\", \"custom\"]).default(\"custom\"),\n /** Opaque reference the host resolves at injection time (never the secret itself). */\n ref: z.string().optional(),\n /** Trust posture of this capability \u2014 drives runtime-class selection. */\n riskClass: RiskClassSchema.default(\"standard\"),\n});\nexport type CapabilityHandle = z.infer<typeof CapabilityHandleSchema>;\n\n/** The env allowlist: only these names may be inherited into the sandbox. */\nexport const EnvAllowlistSchema = z.array(z.string().regex(ENV_NAME));\n\n// ---------------------------------------------------------------------------\n// Run manifest\n// ---------------------------------------------------------------------------\n\nexport const RunManifestSchema = z.object({\n /** Correlation id for the run (the ExecutionBackend keys everything on this). */\n runId: z.string().min(1),\n /** Optional Jentrix AgentJob id this run backs (for record correlation). */\n jobId: z.string().optional(),\n /**\n * The argv executed inside the sandbox. REQUIRED for container/subprocess\n * drivers; may be empty for an in-process host run (see `inProcess`).\n */\n command: z.array(z.string()).default([]),\n /** The code the run executes over. */\n codeSnapshot: CodeSnapshotSchema,\n /**\n * The PINNED OCI base image the sandbox boots from (e.g. `ghcr.io/acme/runner@sha256:\u2026`).\n * When set it wins over the driver's default image and a `codeSnapshot.kind:\"image\"`\n * ref \u2014 the base image is declared in the manifest so a run starts from immutable,\n * reproducible material. The sandbox controller REQUIRES this to be digest-pinned.\n */\n image: z.string().min(1).optional(),\n /**\n * The runtime class the sandbox runs under (runc | gvisor | microvm). Absent \u21D2 the\n * driver's default (stock runc). Risk-class-driven \u2014 set by the controller from the\n * capabilities' risk classes.\n */\n runtimeClass: RuntimeClassSchema.optional(),\n /** Working directory inside the sandbox (defaults to the snapshot path/mount). */\n workdir: z.string().optional(),\n /** Declared bind mounts (read-only unless a mount opts into rw). */\n mounts: z.array(MountSchema).default([]),\n /** The ONLY env names that may be inherited from the host into the sandbox. */\n envAllowlist: EnvAllowlistSchema.default([]),\n /** Explicit env values (still gated by the allowlist for pass-through). */\n env: z.record(z.string(), z.string()).default({}),\n /** Capability handles the run may exercise (opaque references, never secrets). */\n capabilities: z.array(CapabilityHandleSchema).default([]),\n /** Resource ceilings \u2014 wall-time required; others optional. */\n limits: ResourceLimitsSchema,\n /** Network posture \u2014 deny by default. */\n egress: EgressProfileSchema.default({ mode: \"deny\", allow: [] }),\n /**\n * When true, the HostProcessDriver runs the caller-supplied in-process runner\n * (the reference runner's agent turn) INSTEAD of spawning `command` \u2014 this is\n * the \"former direct-exec path\" preserved behind the same contract. Container\n * drivers ignore this and always run `command`.\n */\n inProcess: z.boolean().default(false),\n /** Free-form labels for observability (never load-bearing). */\n labels: z.record(z.string(), z.string()).default({}),\n});\nexport type RunManifest = z.infer<typeof RunManifestSchema>;\nexport type RunManifestInput = z.input<typeof RunManifestSchema>;\n\n/** Parse + fill defaults, throwing on an invalid manifest. */\nexport function parseManifest(input: RunManifestInput): RunManifest {\n return RunManifestSchema.parse(input);\n}\n\n// ---------------------------------------------------------------------------\n// Lifecycle + heartbeat + cancel\n// ---------------------------------------------------------------------------\n\n/** The lifecycle a run moves through. Terminal: SUCCEEDED/FAILED/CANCELED/TIMED_OUT/KILLED. */\nexport const LifecycleStateSchema = z.enum([\n \"PENDING\", // claimed, not yet started\n \"STARTING\", // sandbox provisioning\n \"RUNNING\", // command executing\n \"SUCCEEDED\", // exited 0\n \"FAILED\", // exited non-zero, or a resource kill other than wall-time\n \"CANCELED\", // canceled/frozen by the caller\n \"TIMED_OUT\", // wall-time budget exceeded \u2192 killed\n \"KILLED\", // killed by a CPU/memory/disk limit or an external signal\n]);\nexport type LifecycleState = z.infer<typeof LifecycleStateSchema>;\n\nconst TERMINAL: ReadonlySet<LifecycleState> = new Set<LifecycleState>([\n \"SUCCEEDED\",\n \"FAILED\",\n \"CANCELED\",\n \"TIMED_OUT\",\n \"KILLED\",\n]);\nexport function isTerminalState(state: LifecycleState): boolean {\n return TERMINAL.has(state);\n}\n\nexport const ResourceUsageSchema = z.object({\n wallMs: z.number().int().nonnegative(),\n cpuMs: z.number().int().nonnegative().optional(),\n memoryBytes: z.number().int().nonnegative().optional(),\n});\nexport type ResourceUsage = z.infer<typeof ResourceUsageSchema>;\n\n/**\n * A liveness + usage sample for an in-flight run. The backend emits these on a\n * cadence (and one final terminal beat); a stalled run is one whose wall budget\n * has gone negative \u2014 the backend's own wall timer will already be killing it.\n */\nexport const HeartbeatSchema = z.object({\n runId: z.string(),\n state: LifecycleStateSchema,\n at: z.string(),\n usage: ResourceUsageSchema,\n /** Wall budget left (ms); negative \u21D2 over budget (cancel imminent). */\n wallRemainingMs: z.number().int().optional(),\n});\nexport type Heartbeat = z.infer<typeof HeartbeatSchema>;\n\n/** A cancel/freeze request: SIGTERM, then SIGKILL after `graceMs`. */\nexport const CancelRequestSchema = z.object({\n runId: z.string(),\n reason: z.string().default(\"canceled\"),\n graceMs: z.number().int().nonnegative().default(2000),\n});\nexport type CancelRequest = z.infer<typeof CancelRequestSchema>;\n/** Loose caller shape (reason/graceMs optional \u2014 the backend fills defaults). */\nexport type CancelRequestInput = z.input<typeof CancelRequestSchema>;\n\n// ---------------------------------------------------------------------------\n// Result envelope\n// ---------------------------------------------------------------------------\n\n/** Which declared limit a resource kill attributed to. */\nexport const ResourceLimitKindSchema = z.enum([\n \"cpu\",\n \"memory\",\n \"disk\",\n \"wall_time\",\n \"pids\",\n]);\nexport type ResourceLimitKind = z.infer<typeof ResourceLimitKindSchema>;\n\n/** The category of a run failure. */\nexport const FailureKindSchema = z.enum([\n \"resource_limit_exceeded\", // killed for breaching cpu/memory/disk/wall-time/pids\n \"nonzero_exit\", // the command exited non-zero\n \"canceled\", // canceled/frozen by the caller\n \"driver_error\", // the sandbox faulted (docker/spawn failure)\n \"startup_error\", // the sandbox could not be provisioned\n]);\nexport type FailureKind = z.infer<typeof FailureKindSchema>;\n\nexport const ResultFailureSchema = z.object({\n kind: FailureKindSchema,\n /** The specific limit breached \u2014 set iff `kind === \"resource_limit_exceeded\"`. */\n limit: ResourceLimitKindSchema.nullable().default(null),\n message: z.string(),\n /** The POSIX signal the run died from, when known (e.g. \"SIGKILL\", \"SIGXCPU\"). */\n signal: z.string().nullable().default(null),\n});\nexport type ResultFailure = z.infer<typeof ResultFailureSchema>;\n\n/**\n * The single structured result of a run. A resource-limit kill is reported here\n * as `status: \"failed\" | \"timed_out\"` with a populated `failure` naming the exact\n * limit \u2014 never as an unstructured hang. `summary` carries the agent-turn text the\n * reference runner records as evidence.\n */\nexport const ResultEnvelopeSchema = z.object({\n runId: z.string(),\n /** The driver that produced this result (\"host-process\" | \"local-docker\"). */\n driver: z.string(),\n status: z.enum([\"succeeded\", \"failed\", \"canceled\", \"timed_out\"]),\n state: LifecycleStateSchema,\n exitCode: z.number().int().nullable(),\n startedAt: z.string(),\n endedAt: z.string(),\n usage: ResourceUsageSchema,\n stdout: z.string().default(\"\"),\n stderr: z.string().default(\"\"),\n /** Agent-turn summary text (reference-runner evidence); defaults to stdout. */\n summary: z.string().default(\"\"),\n failure: ResultFailureSchema.nullable().default(null),\n});\nexport type ResultEnvelope = z.infer<typeof ResultEnvelopeSchema>;\n\n/** True when the run was killed for breaching a declared resource budget. */\nexport function isResourceLimitExceeded(env: ResultEnvelope): boolean {\n return env.failure?.kind === \"resource_limit_exceeded\";\n}\n\n/** True when the run finished cleanly (exit 0). */\nexport function isSuccess(env: ResultEnvelope): boolean {\n return env.status === \"succeeded\";\n}\n", "/**\n * Deployment-compatibility revisions \u2014 the SINGLE SOURCE OF TRUTH contract\n * (M12.3b, AGE-173).\n *\n * A deployed Jentrix plane is assembled from independently-shipped images \u2014 the\n * CONTROL PLANE (the Next app), the WORKER (the polling reference runner), and the\n * SANDBOX images (the sandbox controller). Each is BUILD-STAMPED with two revisions:\n *\n * \u2022 schemaRevision \u2014 the database/contract schema the image was built against\n * (the latest Prisma migration id). A worker running against a control plane\n * whose schema has moved on is EXACTLY the \"silent unknown-field / stale-client\"\n * failure mode this module exists to make LOUD and fail-closed.\n * \u2022 appRevision \u2014 the application build the image was cut from (the git SHA).\n *\n * Both are read from the environment (`STACKS_SCHEMA_REVISION` / `STACKS_APP_REVISION`,\n * with `VERCEL_GIT_COMMIT_SHA` as an app-revision fallback) so ONE build stamps ALL\n * images identically \u2014 that shared build stamp is the single source of truth. An\n * un-stamped process resolves to {@link UNKNOWN_REVISION}.\n *\n * The guard is FAIL-CLOSED but never a FALSE POSITIVE: it rejects only when the\n * control plane HAS a known revision that the worker's presented revision does not\n * match (including a stale worker presenting `unknown` against a stamped control\n * plane). An un-stamped control plane (dev/test) cannot meaningfully compare, so the\n * guard is inert \u2014 matched AND un-stamped deployments claim and run normally.\n *\n * Pure data \u2014 ZERO imports (only reads env + compares strings) \u2014 so the app, the\n * worker, the sandbox controller, and the reference runner all speak the identical\n * contract without dragging in a dependency (the worker package has no `zod`). The\n * app keeps a byte-for-byte MIRROR at `src/lib/revision.ts` because Next cannot\n * import from `packages/`; a mismatch is caught by the two sides' unit tests.\n */\n\n/** The sentinel an UN-STAMPED (dev / test / legacy) process resolves to. */\nexport const UNKNOWN_REVISION = \"unknown\";\n\n/** A component's build-stamped identity. */\nexport interface RevisionStamp {\n /** The schema/contract revision (latest Prisma migration id). */\n schemaRevision: string;\n /** The application build revision (git SHA). */\n appRevision: string;\n}\n\n/** A minimal env shape \u2014 avoids a hard Node dependency in the pure contract. */\nexport type RevisionEnv = Record<string, string | undefined>;\n\nfunction clean(value: string | undefined): string {\n return (value ?? \"\").trim();\n}\n\nfunction safeProcessEnv(): RevisionEnv {\n return typeof process !== \"undefined\" && process.env ? process.env : {};\n}\n\n/**\n * Resolve a component's build-stamped revision from the environment. Because every\n * image is stamped from ONE build, the control plane and a compatible worker resolve\n * identical stamps; an un-stamped process resolves to {@link UNKNOWN_REVISION}.\n */\nexport function resolveRevisionStamp(\n env: RevisionEnv = safeProcessEnv(),\n): RevisionStamp {\n const schema = clean(env.STACKS_SCHEMA_REVISION);\n const app =\n clean(env.STACKS_APP_REVISION) || clean(env.VERCEL_GIT_COMMIT_SHA);\n return {\n schemaRevision: schema || UNKNOWN_REVISION,\n appRevision: app || UNKNOWN_REVISION,\n };\n}\n\n/** True when a revision carries a real (build-stamped) value, not the sentinel. */\nexport function isStamped(revision: string): boolean {\n return revision.length > 0 && revision !== UNKNOWN_REVISION;\n}\n\n/**\n * STRICTLY: is this worker positively known to be running THIS build?\n *\n * Deliberately narrower than {@link compareRevisions}. That comparison is\n * *inert* when the control plane is un-stamped \u2014 nothing to compare against, so\n * it reports a match and refuses nobody, which is right for a compatibility gate\n * that must not break dev. This predicate answers the opposite question, the one\n * you ask before granting a capability ON THE STRENGTH of the worker's code:\n * both dimensions must be stamped on BOTH sides and equal. Un-stamped anywhere\n * \u21D2 false, because \"we cannot tell\" must never read as \"yes\".\n *\n * M18.3 R7 uses it at the validator dispatch boundary: an attempt is opened\n * read-only only for a runner whose build the control plane can positively\n * identify as carrying the read-only checkout lane.\n */\nexport function isRevisionAttested(\n control: RevisionStamp,\n worker: RevisionStamp,\n): boolean {\n return (\n isStamped(control.schemaRevision) &&\n isStamped(control.appRevision) &&\n control.schemaRevision === worker.schemaRevision &&\n control.appRevision === worker.appRevision\n );\n}\n\nexport type RevisionDimension = \"schema\" | \"app\";\n\n/** The verdict of comparing a worker's revision against the control plane's. */\nexport interface RevisionCompatibility {\n compatible: boolean;\n schemaMatch: boolean;\n appMatch: boolean;\n /** Which dimensions disagreed (empty when compatible). */\n mismatches: RevisionDimension[];\n control: RevisionStamp;\n worker: RevisionStamp;\n /** A legible one-line reason, or null when compatible. */\n reason: string | null;\n}\n\n/**\n * Compare a worker's presented revision against the control plane's own. FAIL-CLOSED\n * on a KNOWN-vs-different mismatch (including a worker presenting `unknown` against a\n * stamped control plane \u2014 a stale / legacy client). INERT when the control plane is\n * itself un-stamped: there is nothing to compare against, so no false positives in\n * dev / test.\n */\nexport function compareRevisions(\n control: RevisionStamp,\n worker: RevisionStamp,\n): RevisionCompatibility {\n const schemaMatch =\n !isStamped(control.schemaRevision) ||\n control.schemaRevision === worker.schemaRevision;\n const appMatch =\n !isStamped(control.appRevision) ||\n control.appRevision === worker.appRevision;\n const mismatches: RevisionDimension[] = [];\n if (!schemaMatch) mismatches.push(\"schema\");\n if (!appMatch) mismatches.push(\"app\");\n const compatible = mismatches.length === 0;\n return {\n compatible,\n schemaMatch,\n appMatch,\n mismatches,\n control,\n worker,\n reason: compatible\n ? null\n : describeRevisionMismatch(control, worker, mismatches),\n };\n}\n\n/** A legible, operator-facing one-liner describing a revision mismatch. */\nexport function describeRevisionMismatch(\n control: RevisionStamp,\n worker: RevisionStamp,\n mismatches: RevisionDimension[],\n): string {\n const parts = mismatches.map((dimension) =>\n dimension === \"schema\"\n ? `schema revision ${worker.schemaRevision} != control plane ${control.schemaRevision}`\n : `app revision ${worker.appRevision} != control plane ${control.appRevision}`,\n );\n return (\n `Worker deployment is incompatible with the control plane: ${parts.join(\"; \")}. ` +\n `Redeploy the worker to match \u2014 it will not claim runs until it does.`\n );\n}\n\nexport type RevisionHealthStatus = \"ok\" | \"incompatible\" | \"unstamped\";\n\n/** A legible health summary of the revision state, for a probe or a banner. */\nexport interface RevisionHealth {\n status: RevisionHealthStatus;\n control: RevisionStamp;\n /** The worker under comparison, when a stamp was presented. */\n worker: RevisionStamp | null;\n compatibility: RevisionCompatibility | null;\n /** A legible operator-facing message (always set). */\n message: string;\n}\n\n/**\n * Summarize the revision state legibly. With a worker stamp it reports\n * ok / incompatible; without one it reports whether the control plane is itself\n * build-stamped (an un-stamped plane runs with the guard inert).\n */\nexport function revisionHealth(\n control: RevisionStamp,\n worker?: RevisionStamp | null,\n): RevisionHealth {\n if (worker) {\n const compatibility = compareRevisions(control, worker);\n if (!compatibility.compatible) {\n return {\n status: \"incompatible\",\n control,\n worker,\n compatibility,\n message: compatibility.reason as string,\n };\n }\n return {\n status: \"ok\",\n control,\n worker,\n compatibility,\n message: `Worker matches the control plane (schema ${control.schemaRevision}, app ${control.appRevision}).`,\n };\n }\n const stamped =\n isStamped(control.schemaRevision) && isStamped(control.appRevision);\n if (!stamped) {\n return {\n status: \"unstamped\",\n control,\n worker: null,\n compatibility: null,\n message: `Control plane is not build-stamped (schema ${control.schemaRevision}, app ${control.appRevision}) \u2014 the revision compatibility guard is inert.`,\n };\n }\n return {\n status: \"ok\",\n control,\n worker: null,\n compatibility: null,\n message: `Control plane revision: schema ${control.schemaRevision}, app ${control.appRevision}.`,\n };\n}\n", "/**\n * Shared worktree lifecycle helper (Concurrent Harness Execution PRD, Decision 11).\n *\n * ONE native-Git worktree per harness execution attempt (`AgentJob`). Both the\n * reference runner and the Temporal worker use THIS helper for path derivation,\n * create/adopt validation, superseded-branch detach, and safe cleanup, so the two\n * processes can never drift.\n *\n * Contract (deliberately narrow):\n * \u2022 Shells out to `git` with argv ARRAYS only (injectable {@link RunGit} seam)\n * and uses Node stdlib fs/path/crypto only \u2014 NO runtime dependency (the\n * Temporal worker package has no zod), NO Jentrix API / workflow-policy logic.\n * \u2022 The worktree dir + sibling marker are DETERMINISTICALLY derived from trusted\n * repo config + the opaque jobId; every resolved path is proven to stay under\n * the configured root after normalization AND realpath/symlink resolution.\n * \u2022 The ownership marker is a SIBLING of the worktree, never inside it (the\n * runner uses `git add -A`), and holds identifiers only.\n * \u2022 Adoption, detach, and cleanup all fail CLOSED on a mismatched marker, a path\n * outside the root, or a symlink escape \u2014 nothing is ever overwritten or\n * recursively deleted.\n */\nimport { execFile } from \"node:child_process\";\nimport { createHash } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport {\n lstat,\n mkdir,\n readFile,\n realpath,\n rm,\n writeFile,\n} from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { promisify } from \"node:util\";\n\nconst execFileP = promisify(execFile);\n\n/** Trusted repo mapping for one configured repository (from STACKS_RUNNER_REPOS). */\nexport interface WorktreeRepoConfig {\n /** \"owner/name\" \u2014 the configured repo identity. Filesystem paths NEVER come from\n * tool/MCP input; only this operator-configured identity + checkout are trusted. */\n repo: string;\n /** Absolute path to the configured source checkout (the Git source). */\n checkout: string;\n /** STACKS_RUNNER_WORKTREE_ROOT \u2014 the worktree parent. When omitted, a sibling\n * `.stacks-worktrees` directory next to {@link checkout} is used. */\n worktreeRoot?: string;\n}\n\n/** The four opaque identifiers that key + validate an attempt's worktree. */\nexport interface WorktreeIdentity {\n /** \"owner/name\" \u2014 must equal the resolving config's repo. */\n repo: string;\n /** The AgentJob id \u2014 the durable attempt identity. Validated as an opaque id,\n * NEVER interpreted as a path. */\n jobId: string;\n /** The harness stage identity. */\n stageId: string;\n /** The resolved stage branch (e.g. `harness/{taskKey}-{slug}-stage-{n}`). */\n branch: string;\n}\n\nexport type WorktreeMarkerStatus = \"active\" | \"superseded-detached\";\n\n/** The on-disk ownership marker \u2014 identifiers only (no paths, no secrets). */\nexport interface WorktreeMarker extends WorktreeIdentity {\n status: WorktreeMarkerStatus;\n}\n\n/** Purely-derived paths for an attempt's worktree (no filesystem access). */\nexport interface ResolvedWorktree {\n /** The worktree parent root (`<worktreeRoot>` or the `.stacks-worktrees` sibling). */\n root: string;\n /** Filesystem-safe encoding of the repo identity. */\n repoKey: string;\n /** `<root>/<repoKey>/<jobId>/` \u2014 the linked worktree directory. */\n dir: string;\n /** `<root>/<repoKey>/<jobId>.marker.json` \u2014 the SIBLING ownership marker. */\n markerPath: string;\n}\n\nexport interface EnsureWorktreeResult {\n dir: string;\n markerPath: string;\n marker: WorktreeMarker;\n /** true when the worktree was freshly created, false when an existing one was adopted. */\n created: boolean;\n}\n\nexport interface CleanupResult {\n removed: boolean;\n reason: \"clean\" | \"source-dirty\" | \"absent\";\n /** Porcelain status lines when retained as source-dirty (for operator reporting). */\n dirty?: string[];\n}\n\n/** The outcome of a park/rescue checkpoint (see {@link checkpointWorktree}). */\nexport interface CheckpointResult {\n committed: boolean;\n reason: \"committed\" | \"clean\" | \"absent\";\n /** The stage branch's new tip when a checkpoint landed. */\n sha?: string;\n /** Paths the checkpoint captured (operator reporting). */\n files?: string[];\n}\n\n/**\n * Run a git command; returns stdout. `env` (when given) is merged into the child's\n * environment (used to hand a credential helper a single-use token WITHOUT placing\n * it in argv). Structurally identical to the runner's own git seam so the runner\n * can pass its instrumented implementation in.\n */\nexport type RunGit = (\n cwd: string,\n args: string[],\n env?: Record<string, string>,\n) => Promise<string>;\n\nexport const defaultRunGit: RunGit = async (cwd, args, env) => {\n const { stdout } = await execFileP(\"git\", args, {\n cwd,\n env: env ? { ...process.env, ...env } : process.env,\n maxBuffer: 64 * 1024 * 1024,\n });\n return stdout;\n};\n\n/** A fail-closed lifecycle error carrying a machine-readable code + actionable message. */\nexport class WorktreeError extends Error {\n constructor(\n readonly code:\n | \"INVALID_JOB_ID\"\n | \"PATH_ESCAPE\"\n | \"MARKER_MISSING\"\n | \"MARKER_INVALID\"\n | \"MARKER_MISMATCH\"\n | \"REPO_MISMATCH\"\n | \"BRANCH_MISMATCH\"\n | \"NOT_A_WORKTREE\"\n | \"MISSING_REF\"\n | \"CREATE_FAILED\"\n | \"NOT_FOUND\"\n | \"CHECKPOINT_UNREACHABLE\",\n message: string,\n ) {\n super(message);\n this.name = \"WorktreeError\";\n }\n}\n\n// A cuid/uuid-shaped opaque id: no path separators, no dots (so it can never be\n// `..`, a traversal segment, or collide with the `.marker.json` sibling suffix).\nconst JOB_ID_RE = /^[A-Za-z0-9_-]{1,200}$/;\n\nfunction validateJobId(jobId: string): void {\n if (!JOB_ID_RE.test(jobId)) {\n throw new WorktreeError(\n \"INVALID_JOB_ID\",\n `jobId ${JSON.stringify(jobId)} is not an opaque id (expected ${JOB_ID_RE}); refusing to interpret it as a path.`,\n );\n }\n}\n\n/** Filesystem-safe encoding of a repo identity: readable slug + disambiguating hash. */\nexport function repoKeyFor(repo: string): string {\n const slug = repo\n .replace(/[^A-Za-z0-9._-]+/g, \"_\")\n .replace(/^_+|_+$/g, \"\")\n .slice(0, 64);\n const hash = createHash(\"sha256\").update(repo).digest(\"hex\").slice(0, 12);\n return slug ? `${slug}-${hash}` : hash;\n}\n\nfunction assertUnder(base: string, target: string): void {\n const b = path.resolve(base);\n const t = path.resolve(target);\n if (t !== b && !t.startsWith(b + path.sep)) {\n throw new WorktreeError(\"PATH_ESCAPE\", `path ${t} escapes ${b}`);\n }\n}\n\n/**\n * Deterministically derive the worktree dir + sibling marker path. Pure: validates\n * the jobId and normalizes/contains the paths, but touches no filesystem.\n */\nexport function resolveWorktreePaths(\n config: WorktreeRepoConfig,\n identity: WorktreeIdentity,\n): ResolvedWorktree {\n validateJobId(identity.jobId);\n const root = path.resolve(\n config.worktreeRoot ??\n path.join(\n path.dirname(path.resolve(config.checkout)),\n \".stacks-worktrees\",\n ),\n );\n const repoKey = repoKeyFor(config.repo);\n const base = path.join(root, repoKey);\n const dir = path.join(base, identity.jobId);\n const markerPath = path.join(base, `${identity.jobId}.marker.json`);\n // repoKey is sanitized and jobId is validated, so these hold by construction \u2014\n // check anyway (defense in depth against a future change loosening either).\n assertUnder(base, dir);\n assertUnder(base, markerPath);\n return { root, repoKey, dir, markerPath };\n}\n\n/**\n * Resolve `target` under `root` following symlinks, tolerating a not-yet-created\n * leaf (probes the deepest EXISTING ancestor). Throws PATH_ESCAPE on any escape.\n * `root` must already exist.\n */\nasync function realpathContained(\n root: string,\n target: string,\n): Promise<string> {\n const realRoot = await realpath(root);\n let probe = path.resolve(target);\n const tail: string[] = [];\n while (!existsSync(probe)) {\n tail.unshift(path.basename(probe));\n const parent = path.dirname(probe);\n if (parent === probe) break;\n probe = parent;\n }\n const realProbe = await realpath(probe);\n const realTarget = tail.length ? path.join(realProbe, ...tail) : realProbe;\n if (realTarget !== realRoot && !realTarget.startsWith(realRoot + path.sep)) {\n throw new WorktreeError(\n \"PATH_ESCAPE\",\n `resolved path ${realTarget} escapes worktree root ${realRoot} (symlink escape refused)`,\n );\n }\n return realTarget;\n}\n\n/**\n * Prove the sibling ownership marker stays under `root` after symlink resolution\n * AND that the marker itself is not a symlink. The marker is a regular file THIS\n * helper owns, so a symlink there is only ever an escape attempt \u2014 including a\n * broken one whose target `realpath` can't resolve (which `realpathContained`\n * would otherwise walk past when probing existing ancestors). Tolerates a\n * not-yet-written marker (create writes it after this check).\n */\nasync function assertMarkerContained(\n root: string,\n markerPath: string,\n): Promise<void> {\n try {\n if ((await lstat(markerPath)).isSymbolicLink()) {\n throw new WorktreeError(\n \"PATH_ESCAPE\",\n `ownership marker path ${markerPath} is a symlink; refusing to follow it (symlink escape refused).`,\n );\n }\n } catch (err) {\n if (err instanceof WorktreeError) throw err;\n // ENOENT: marker not present yet \u2014 fall through to ancestor containment.\n }\n await realpathContained(root, markerPath);\n}\n\nfunction markerMatches(\n marker: WorktreeMarker,\n identity: WorktreeIdentity,\n): boolean {\n return (\n marker.repo === identity.repo &&\n marker.jobId === identity.jobId &&\n marker.stageId === identity.stageId &&\n marker.branch === identity.branch\n );\n}\n\nasync function writeMarker(\n markerPath: string,\n marker: WorktreeMarker,\n): Promise<void> {\n // Owner-only perms: a marker never holds secrets, but the worktree tree beside it\n // may hold copied ignored config, so keep the whole area owner-only by default.\n await writeFile(markerPath, JSON.stringify(marker, null, 2) + \"\\n\", {\n encoding: \"utf8\",\n mode: 0o600,\n });\n}\n\nexport async function readMarker(markerPath: string): Promise<WorktreeMarker> {\n let raw: string;\n try {\n raw = await readFile(markerPath, \"utf8\");\n } catch {\n throw new WorktreeError(\n \"MARKER_MISSING\",\n `ownership marker not found at ${markerPath}`,\n );\n }\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch {\n throw new WorktreeError(\n \"MARKER_INVALID\",\n `ownership marker at ${markerPath} is not valid JSON`,\n );\n }\n const m = parsed as Record<string, unknown>;\n const ok =\n m &&\n typeof m.repo === \"string\" &&\n typeof m.jobId === \"string\" &&\n typeof m.stageId === \"string\" &&\n typeof m.branch === \"string\" &&\n (m.status === \"active\" || m.status === \"superseded-detached\");\n if (!ok) {\n throw new WorktreeError(\n \"MARKER_INVALID\",\n `ownership marker at ${markerPath} is missing required identifiers`,\n );\n }\n return m as unknown as WorktreeMarker;\n}\n\nasync function branchExists(\n runGit: RunGit,\n checkout: string,\n branch: string,\n): Promise<boolean> {\n const out = (await runGit(checkout, [\"branch\", \"--list\", branch])).trim();\n return out.length > 0;\n}\n\n/**\n * True iff `ref` resolves to a commit in `checkout`. `rev-parse --verify\n * --quiet <ref>^{commit}` prints the commit sha (exit 0) when it resolves and\n * fails (non-zero / empty) otherwise \u2014 so a missing named ref, a tag, or an empty\n * ref all read as \"does not resolve\". Never interprets the mutable HEAD as a base.\n */\nasync function refResolvesToCommit(\n runGit: RunGit,\n checkout: string,\n ref: string,\n): Promise<boolean> {\n try {\n const out = (\n await runGit(checkout, [\n \"rev-parse\",\n \"--verify\",\n \"--quiet\",\n `${ref}^{commit}`,\n ])\n ).trim();\n return out.length > 0;\n } catch {\n return false;\n }\n}\n\n/** The shared object store (`--git-common-dir`), realpath'd \u2014 identifies the repo. */\nasync function commonGitDir(runGit: RunGit, cwd: string): Promise<string> {\n const raw = (await runGit(cwd, [\"rev-parse\", \"--git-common-dir\"])).trim();\n return realpath(path.resolve(cwd, raw));\n}\n\n/**\n * Create a fresh worktree via `git worktree add`. When the stage branch already\n * exists (a retry/restart on the same branch) it is checked out at its current tip;\n * otherwise it is created from the provided `executionBaseRef`. Writes the sibling\n * ownership marker and re-verifies containment after creation.\n */\nexport async function createWorktree(opts: {\n config: WorktreeRepoConfig;\n identity: WorktreeIdentity;\n executionBaseRef: string;\n runGit?: RunGit;\n}): Promise<EnsureWorktreeResult> {\n const runGit = opts.runGit ?? defaultRunGit;\n const { root, dir, markerPath } = resolveWorktreePaths(\n opts.config,\n opts.identity,\n );\n await mkdir(path.dirname(dir), { recursive: true });\n await realpathContained(root, dir);\n // Refuse a pre-planted symlink at the sibling marker path BEFORE `git worktree\n // add`, so create can never write the marker through a symlink out of the root.\n await assertMarkerContained(root, markerPath);\n const marker: WorktreeMarker = { ...opts.identity, status: \"active\" };\n try {\n if (\n await branchExists(runGit, opts.config.checkout, opts.identity.branch)\n ) {\n await runGit(opts.config.checkout, [\n \"worktree\",\n \"add\",\n dir,\n opts.identity.branch,\n ]);\n } else {\n // Verify the resolved executionBaseRef resolves to a commit BEFORE creating\n // the worktree \u2014 a missing named ref yields an actionable MISSING_REF error\n // (a runner lacking the ref fetches ONLY it through the brokered repository\n // boundary) instead of an opaque `git worktree add` failure. This is also the\n // never-substitute-HEAD guard: an empty/unresolvable base ref is refused\n // here, so a fresh branch is never silently cut from the checkout's HEAD.\n if (\n !(await refResolvesToCommit(\n runGit,\n opts.config.checkout,\n opts.executionBaseRef,\n ))\n ) {\n throw new WorktreeError(\n \"MISSING_REF\",\n `executionBaseRef ${JSON.stringify(opts.executionBaseRef)} does not resolve to a commit in ${opts.config.checkout}; fetch only that ref through the brokered repository boundary (e.g. \\`git fetch <remote> ${opts.executionBaseRef}\\`) before creating the worktree for job ${opts.identity.jobId}.`,\n );\n }\n await runGit(opts.config.checkout, [\n \"worktree\",\n \"add\",\n \"-b\",\n opts.identity.branch,\n dir,\n opts.executionBaseRef,\n ]);\n }\n } catch (err) {\n // A typed WorktreeError (e.g. the MISSING_REF pre-check) is already\n // actionable \u2014 surface it verbatim instead of masking it as CREATE_FAILED.\n if (err instanceof WorktreeError) throw err;\n throw new WorktreeError(\n \"CREATE_FAILED\",\n `git worktree add for job ${opts.identity.jobId} (branch ${opts.identity.branch} from ${opts.executionBaseRef}) failed: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n await writeMarker(markerPath, marker);\n await realpathContained(root, dir);\n return { dir, markerPath, marker, created: true };\n}\n\n/**\n * Adopt an EXISTING worktree directory (restart recovery). Succeeds ONLY when the\n * sibling marker AND Git metadata agree on repo/job/stage/branch; any mismatch,\n * path escape, or symlink escape fails closed and the directory is never touched.\n */\nexport async function adoptWorktree(opts: {\n config: WorktreeRepoConfig;\n identity: WorktreeIdentity;\n runGit?: RunGit;\n}): Promise<EnsureWorktreeResult> {\n const runGit = opts.runGit ?? defaultRunGit;\n const { root, dir, markerPath } = resolveWorktreePaths(\n opts.config,\n opts.identity,\n );\n const realDir = await realpathContained(root, dir);\n\n await assertMarkerContained(root, markerPath);\n const marker = await readMarker(markerPath);\n if (!markerMatches(marker, opts.identity)) {\n throw new WorktreeError(\n \"MARKER_MISMATCH\",\n `worktree at ${dir} is owned by ${marker.repo}#${marker.jobId} stage ${marker.stageId} (branch ${marker.branch}), not ${opts.identity.repo}#${opts.identity.jobId} stage ${opts.identity.stageId} (branch ${opts.identity.branch}); refusing to overwrite.`,\n );\n }\n\n const insideWorkTree = (\n await runGit(dir, [\"rev-parse\", \"--is-inside-work-tree\"])\n ).trim();\n if (insideWorkTree !== \"true\") {\n throw new WorktreeError(\"NOT_A_WORKTREE\", `${dir} is not a Git work tree`);\n }\n const topLevel = await realpath(\n (await runGit(dir, [\"rev-parse\", \"--show-toplevel\"])).trim(),\n );\n if (topLevel !== realDir) {\n throw new WorktreeError(\n \"NOT_A_WORKTREE\",\n `${dir} is not the top of its work tree (git reports ${topLevel})`,\n );\n }\n const head = (\n await runGit(dir, [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"])\n ).trim();\n if (head !== opts.identity.branch) {\n throw new WorktreeError(\n \"BRANCH_MISMATCH\",\n `worktree at ${dir} has branch ${head} checked out but the attempt expects ${opts.identity.branch}; refusing to adopt.`,\n );\n }\n const [worktreeRepo, configuredRepo] = await Promise.all([\n commonGitDir(runGit, dir),\n commonGitDir(runGit, opts.config.checkout),\n ]);\n if (worktreeRepo !== configuredRepo) {\n throw new WorktreeError(\n \"REPO_MISMATCH\",\n `worktree at ${dir} belongs to a different repository (${worktreeRepo}) than the configured checkout (${configuredRepo}).`,\n );\n }\n return { dir: realDir, markerPath, marker, created: false };\n}\n\n/** Derive \u2192 adopt if the directory already exists, else create. */\nexport async function ensureWorktree(opts: {\n config: WorktreeRepoConfig;\n identity: WorktreeIdentity;\n executionBaseRef: string;\n runGit?: RunGit;\n}): Promise<EnsureWorktreeResult> {\n const { dir } = resolveWorktreePaths(opts.config, opts.identity);\n if (existsSync(dir)) {\n return adoptWorktree(opts);\n }\n return createWorktree(opts);\n}\n\n/**\n * Free a superseded attempt's stage branch WITHOUT discarding its work: run\n * `git checkout --detach` inside the OLD worktree (preserves all dirty files) and\n * stamp its retained marker `superseded-detached`. The caller must have already\n * proven, from fresh Jentrix state, that the old attempt is superseded \u2014 this helper\n * contains no such policy, only the mechanical, marker-validated detach.\n */\nexport async function detachSupersededWorktree(opts: {\n config: WorktreeRepoConfig;\n /** The OLD (superseded) attempt's identity. */\n identity: WorktreeIdentity;\n runGit?: RunGit;\n}): Promise<{ dir: string; markerPath: string; marker: WorktreeMarker }> {\n const runGit = opts.runGit ?? defaultRunGit;\n const { root, dir, markerPath } = resolveWorktreePaths(\n opts.config,\n opts.identity,\n );\n if (!existsSync(dir)) {\n throw new WorktreeError(\"NOT_FOUND\", `no worktree to detach at ${dir}`);\n }\n const realDir = await realpathContained(root, dir);\n await assertMarkerContained(root, markerPath);\n const marker = await readMarker(markerPath);\n if (!markerMatches(marker, opts.identity)) {\n throw new WorktreeError(\n \"MARKER_MISMATCH\",\n `worktree at ${dir} is not owned by ${opts.identity.repo}#${opts.identity.jobId}; refusing to detach.`,\n );\n }\n // Detach preserves the working tree (tracked + untracked stay on disk).\n await runGit(dir, [\"checkout\", \"--detach\"]);\n const stamped: WorktreeMarker = { ...marker, status: \"superseded-detached\" };\n await writeMarker(markerPath, stamped);\n return { dir: realDir, markerPath, marker: stamped };\n}\n\n/**\n * Commit a parked/abandoned attempt's dirty worktree ONTO its stage branch, so a\n * park never strands work (Harness Reliability W1).\n *\n * An attempt that parks \u2014 cap park, adjudication park, failed turn, killed\n * runner \u2014 never reaches its commit gate. The next attempt gets a FRESH worktree\n * keyed by its own job id and checks out the stage branch at a tip that has none\n * of the prior attempt's changes: the diff is still on disk, but invisible to\n * every reviewer, gate, and operator (M18 needed ten manual rescue commits; one\n * attempt alone left 2,881 uncommitted lines behind).\n *\n * The load-bearing guard is the BRANCH REF, not the commit: a commit made in a\n * DETACHED worktree succeeds and advances nothing, which is exactly how work\n * gets stranded invisibly. So this refuses to commit unless the worktree has the\n * expected branch checked out, and re-reads `refs/heads/<branch>` afterwards to\n * prove the ref actually moved. A clean tree commits nothing (no empty commits,\n * no noise); a missing worktree is `absent`, not an error.\n */\nexport async function checkpointWorktree(opts: {\n config: WorktreeRepoConfig;\n identity: WorktreeIdentity;\n /** Commit message \u2014 the caller names the park reason. */\n message: string;\n runGit?: RunGit;\n}): Promise<CheckpointResult> {\n const runGit = opts.runGit ?? defaultRunGit;\n const { root, dir, markerPath } = resolveWorktreePaths(\n opts.config,\n opts.identity,\n );\n if (!existsSync(dir)) return { committed: false, reason: \"absent\" };\n\n // Same fail-closed validation as every other mutating helper: containment,\n // then the ownership marker, before anything is written.\n await realpathContained(root, dir);\n await assertMarkerContained(root, markerPath);\n const marker = await readMarker(markerPath);\n if (!markerMatches(marker, opts.identity)) {\n throw new WorktreeError(\n \"MARKER_MISMATCH\",\n `worktree at ${dir} is owned by ${marker.repo}#${marker.jobId} (branch ${marker.branch}), not ${opts.identity.repo}#${opts.identity.jobId} (branch ${opts.identity.branch}); refusing to checkpoint it.`,\n );\n }\n\n const porcelain = (await runGit(dir, [\"status\", \"--porcelain\"])).trim();\n if (!porcelain) return { committed: false, reason: \"clean\" };\n\n // A commit only reaches the stage branch from a branch-ATTACHED worktree.\n const head = (\n await runGit(dir, [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"])\n ).trim();\n if (head !== opts.identity.branch) {\n throw new WorktreeError(\n \"CHECKPOINT_UNREACHABLE\",\n `worktree at ${dir} has ${head === \"HEAD\" ? \"a DETACHED HEAD\" : `branch ${head}`} checked out, not ${opts.identity.branch}: a commit here would never advance the stage branch, so ${porcelain.split(\"\\n\").length} uncommitted change(s) cannot be checkpointed. Reconcile that worktree by hand (\\`git -C ${dir} status\\`) before the stage continues.`,\n );\n }\n const branchRef = `refs/heads/${opts.identity.branch}`;\n const before = (await runGit(dir, [\"rev-parse\", branchRef])).trim();\n\n await runGit(dir, [\"add\", \"-A\"]);\n const staged = (await runGit(dir, [\"diff\", \"--cached\", \"--name-only\"]))\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter(Boolean);\n // Porcelain can be non-empty while `add -A` stages nothing (e.g. a path the\n // index already matches). Never create an empty commit.\n if (staged.length === 0) return { committed: false, reason: \"clean\" };\n await runGit(dir, [\"commit\", \"-m\", opts.message]);\n\n const after = (await runGit(dir, [\"rev-parse\", branchRef])).trim();\n if (!after || after === before) {\n throw new WorktreeError(\n \"CHECKPOINT_UNREACHABLE\",\n `checkpoint commit in ${dir} did not advance ${branchRef} (still ${before.slice(0, 12)}); ${staged.length} change(s) remain stranded there. Reconcile that worktree by hand before the stage continues.`,\n );\n }\n return { committed: true, reason: \"committed\", sha: after, files: staged };\n}\n\n/**\n * Safely remove a delivered worktree.\n *\n * Ordering matters:\n * 1. `git worktree prune` FIRST (PRD amendment b), so a worktree that was\n * manually `rm -rf`'d cannot wedge its branch.\n * 2. Validate containment (realpath/symlink) AND the ownership marker immediately\n * before any removal.\n * 3. Classify: `git status --porcelain` (no `--ignored`) surfaces exactly tracked\n * changes + non-ignored untracked files. Non-empty \u21D2 SOURCE-DIRTY \u21D2 retain.\n * 4. Otherwise clean/ignored-only \u21D2 `git clean -fdX` (removes ignored output\n * only), then `git worktree remove` WITHOUT force, then delete the marker.\n *\n * Never recursively deletes an arbitrary path: only git-managed removal + the single\n * derived marker file. The caller decides WHEN cleanup is allowed (terminal state,\n * no active run) \u2014 that policy is not in this helper.\n */\nexport async function cleanupWorktree(opts: {\n config: WorktreeRepoConfig;\n identity: WorktreeIdentity;\n runGit?: RunGit;\n}): Promise<CleanupResult> {\n const runGit = opts.runGit ?? defaultRunGit;\n const { root, dir, markerPath } = resolveWorktreePaths(\n opts.config,\n opts.identity,\n );\n\n // (1) Prune first \u2014 reconcile any manually-deleted worktree so its branch is free.\n await runGit(opts.config.checkout, [\"worktree\", \"prune\"]);\n\n if (!existsSync(dir)) {\n // Already gone (e.g. manually removed). Prune freed the branch; drop the stale\n // marker \u2014 but only after proving it's contained and not a symlink escape.\n if (existsSync(markerPath)) {\n await assertMarkerContained(root, markerPath);\n await rm(markerPath, { force: true });\n }\n return { removed: false, reason: \"absent\" };\n }\n\n // (2) Containment + marker validated immediately before any destructive op.\n const realDir = await realpathContained(root, dir);\n await assertMarkerContained(root, markerPath);\n const marker = await readMarker(markerPath);\n if (!markerMatches(marker, opts.identity)) {\n throw new WorktreeError(\n \"MARKER_MISMATCH\",\n `worktree at ${dir} is owned by ${marker.repo}#${marker.jobId}, not ${opts.identity.repo}#${opts.identity.jobId}; refusing to remove.`,\n );\n }\n\n // (3) Source-dirty classification: any porcelain line = tracked change or\n // non-ignored untracked file (ignored files never appear without --ignored).\n const porcelain = (await runGit(dir, [\"status\", \"--porcelain\"])).trim();\n if (porcelain.length > 0) {\n return {\n removed: false,\n reason: \"source-dirty\",\n dirty: porcelain.split(\"\\n\"),\n };\n }\n\n // (4) Clean or ignored-only: drop disposable ignored output, then remove via git.\n await runGit(dir, [\"clean\", \"-fdX\"]);\n await runGit(opts.config.checkout, [\"worktree\", \"remove\", realDir]);\n await rm(markerPath, { force: true });\n return { removed: true, reason: \"clean\" };\n}\n", "/**\n * DriverExecutionBackend \u2014 the run lifecycle the reference runner executes\n * through (M12.1). It owns LIMIT ENFORCEMENT (the wall-time kill) and turns a\n * driver's raw outcome into the single structured {@link ResultEnvelope}. A run\n * that breaches its CPU or wall-time budget is KILLED and reported as a typed\n * `resource_limit_exceeded` failure \u2014 never left to hang.\n */\nimport {\n parseManifest,\n ResultEnvelopeSchema,\n type CancelRequestInput,\n type Heartbeat,\n type LifecycleState,\n type ResourceUsage,\n type ResultEnvelope,\n type ResultFailure,\n type RunManifest,\n type RunManifestInput,\n} from \"./schemas.js\";\nimport type {\n ClaimRequest,\n ExecutionBackend,\n ExecutionTicket,\n RunOptions,\n Sandbox,\n SandboxDriver,\n} from \"./types.js\";\n\nconst DEFAULT_HEARTBEAT_MS = 5_000;\nconst CANCEL_GRACE_MS = 2_000;\n\ninterface InFlight {\n runId: string;\n manifest?: RunManifest;\n sandbox?: Sandbox;\n startedAt: number;\n state: LifecycleState;\n wallTimer?: ReturnType<typeof setTimeout>;\n heartbeatTimer?: ReturnType<typeof setInterval>;\n walltimeExceeded: boolean;\n canceled: boolean;\n cancelReason?: string;\n settled?: Promise<ResultEnvelope>;\n final?: ResultEnvelope;\n}\n\nexport class DriverExecutionBackend implements ExecutionBackend {\n readonly driver: string;\n private readonly sandboxDriver: SandboxDriver;\n private readonly now: () => number;\n private readonly runs = new Map<string, InFlight>();\n\n constructor(driver: SandboxDriver, opts: { now?: () => number } = {}) {\n this.sandboxDriver = driver;\n this.driver = driver.name;\n this.now = opts.now ?? Date.now;\n }\n\n async claim(req: ClaimRequest): Promise<ExecutionTicket> {\n let rec = this.runs.get(req.runId);\n if (!rec) {\n rec = {\n runId: req.runId,\n startedAt: this.now(),\n state: \"PENDING\",\n walltimeExceeded: false,\n canceled: false,\n };\n this.runs.set(req.runId, rec);\n }\n return {\n runId: req.runId,\n claimedAt: new Date(this.now()).toISOString(),\n state: rec.state,\n };\n }\n\n async run(\n input: RunManifest,\n opts: RunOptions = {},\n ): Promise<ResultEnvelope> {\n const manifest = parseManifest(input);\n const log = opts.log ?? (() => {});\n const rec: InFlight = this.runs.get(manifest.runId) ?? {\n runId: manifest.runId,\n startedAt: this.now(),\n state: \"PENDING\",\n walltimeExceeded: false,\n canceled: false,\n };\n rec.manifest = manifest;\n rec.startedAt = this.now();\n rec.state = \"STARTING\";\n rec.walltimeExceeded = false;\n rec.canceled = false;\n rec.final = undefined;\n this.runs.set(manifest.runId, rec);\n\n let sandbox: Sandbox;\n try {\n sandbox = await this.sandboxDriver.create(manifest, {\n signal: opts.signal,\n inProcessRunner: opts.inProcessRunner,\n log,\n });\n } catch (err) {\n // The sandbox could not be provisioned \u2014 a structured startup failure.\n const envelope = this.finalize(rec, {\n status: \"failed\",\n state: \"FAILED\",\n exitCode: null,\n stdout: \"\",\n stderr: err instanceof Error ? err.message : String(err),\n summary: \"\",\n failure: {\n kind: \"startup_error\",\n limit: null,\n message: err instanceof Error ? err.message : String(err),\n signal: null,\n },\n });\n return envelope;\n }\n\n rec.sandbox = sandbox;\n rec.state = \"RUNNING\";\n\n // WALL-TIME ENFORCEMENT: the backend's own deadline. On breach it kills the\n // sandbox with a `wall_time` reason so the outcome resolves promptly.\n rec.wallTimer = setTimeout(() => {\n rec.walltimeExceeded = true;\n rec.state = \"TIMED_OUT\";\n log(\n `[execution ${manifest.runId}] wall-time budget ${manifest.limits.wallMs}ms exceeded \u2014 killing.`,\n );\n void sandbox.kill({\n reason: \"wall-time budget exceeded\",\n limit: \"wall_time\",\n graceMs: CANCEL_GRACE_MS,\n });\n }, manifest.limits.wallMs);\n // NOTE: the wall timer is intentionally NOT unref'd \u2014 it is the load-bearing\n // deadline enforcement. It is cleared the moment the run settles.\n\n // Optional heartbeat sampling.\n const hbMs = opts.heartbeatMs ?? DEFAULT_HEARTBEAT_MS;\n if (opts.onHeartbeat && hbMs > 0) {\n rec.heartbeatTimer = setInterval(() => {\n void this.heartbeat(manifest.runId)\n .then((hb) => opts.onHeartbeat?.(hb))\n .catch(() => {});\n }, hbMs);\n (rec.heartbeatTimer as { unref?: () => void }).unref?.();\n }\n\n const settled = (async (): Promise<ResultEnvelope> => {\n const outcome = await sandbox.wait();\n if (rec.wallTimer) clearTimeout(rec.wallTimer);\n if (rec.heartbeatTimer) clearInterval(rec.heartbeatTimer);\n // Best-effort cleanup (idempotent).\n await this.sandboxDriver.terminate(sandbox).catch(() => {});\n\n let status: ResultEnvelope[\"status\"];\n let state: LifecycleState;\n let failure: ResultFailure | null = null;\n\n if (rec.canceled && !rec.walltimeExceeded) {\n status = \"canceled\";\n state = \"CANCELED\";\n failure = {\n kind: \"canceled\",\n limit: null,\n message: rec.cancelReason ?? \"run canceled\",\n signal: outcome.signal,\n };\n } else if (rec.walltimeExceeded) {\n status = \"timed_out\";\n state = \"TIMED_OUT\";\n failure = {\n kind: \"resource_limit_exceeded\",\n limit: \"wall_time\",\n message: `wall-time budget of ${manifest.limits.wallMs}ms exceeded`,\n signal: outcome.signal,\n };\n } else if (outcome.resourceLimit) {\n // The driver observed a CPU/memory/disk kill (e.g. SIGXCPU).\n status = \"failed\";\n state = \"KILLED\";\n failure = {\n kind: \"resource_limit_exceeded\",\n limit: outcome.resourceLimit,\n message: `${outcome.resourceLimit} budget exceeded \u2014 run killed`,\n signal: outcome.signal,\n };\n } else if (outcome.exitCode === 0) {\n status = \"succeeded\";\n state = \"SUCCEEDED\";\n } else {\n status = \"failed\";\n state = \"FAILED\";\n failure = {\n kind: outcome.exitCode === null ? \"driver_error\" : \"nonzero_exit\",\n limit: null,\n message:\n outcome.exitCode === null\n ? outcome.stderr || \"run ended without an exit code\"\n : `run exited with code ${outcome.exitCode}`,\n signal: outcome.signal,\n };\n }\n\n return this.finalize(rec, {\n status,\n state,\n exitCode: outcome.exitCode,\n stdout: outcome.stdout,\n stderr: outcome.stderr,\n summary: outcome.summary ?? \"\",\n failure,\n });\n })();\n\n rec.settled = settled;\n return settled;\n }\n\n async heartbeat(runId: string): Promise<Heartbeat> {\n const rec = this.runs.get(runId);\n if (!rec) throw new Error(`heartbeat: unknown run ${runId}`);\n if (rec.final) {\n return {\n runId,\n state: rec.final.state,\n at: new Date(this.now()).toISOString(),\n usage: rec.final.usage,\n wallRemainingMs: 0,\n };\n }\n const usage: ResourceUsage = rec.sandbox\n ? await rec.sandbox.usage()\n : { wallMs: Math.max(0, this.now() - rec.startedAt) };\n const wallMs = rec.manifest?.limits.wallMs;\n return {\n runId,\n state: rec.state,\n at: new Date(this.now()).toISOString(),\n usage,\n ...(wallMs !== undefined\n ? { wallRemainingMs: wallMs - usage.wallMs }\n : {}),\n };\n }\n\n async cancel(req: CancelRequestInput | string): Promise<ResultEnvelope> {\n const runId = typeof req === \"string\" ? req : req.runId;\n const reason =\n typeof req === \"string\" ? \"canceled\" : (req.reason ?? \"canceled\");\n const graceMs =\n typeof req === \"string\"\n ? CANCEL_GRACE_MS\n : (req.graceMs ?? CANCEL_GRACE_MS);\n const rec = this.runs.get(runId);\n if (!rec) throw new Error(`cancel: unknown run ${runId}`);\n if (rec.final) return rec.final;\n rec.canceled = true;\n rec.cancelReason = reason;\n rec.state = \"CANCELED\";\n if (rec.sandbox) {\n await rec.sandbox.kill({ reason, graceMs }).catch(() => {});\n }\n if (rec.settled) return rec.settled;\n // Claimed but never run: synthesize a canceled terminal envelope.\n return this.finalize(rec, {\n status: \"canceled\",\n state: \"CANCELED\",\n exitCode: null,\n stdout: \"\",\n stderr: \"\",\n summary: \"\",\n failure: { kind: \"canceled\", limit: null, message: reason, signal: null },\n });\n }\n\n async report(runId: string): Promise<ResultEnvelope | null> {\n return this.runs.get(runId)?.final ?? null;\n }\n\n /** Build, validate, store, and return the terminal envelope for a run. */\n private finalize(\n rec: InFlight,\n parts: {\n status: ResultEnvelope[\"status\"];\n state: LifecycleState;\n exitCode: number | null;\n stdout: string;\n stderr: string;\n summary: string;\n failure: ResultFailure | null;\n },\n ): ResultEnvelope {\n const endedAt = this.now();\n const envelope = ResultEnvelopeSchema.parse({\n runId: rec.runId,\n driver: this.driver,\n status: parts.status,\n state: parts.state,\n exitCode: parts.exitCode,\n startedAt: new Date(rec.startedAt).toISOString(),\n endedAt: new Date(endedAt).toISOString(),\n usage: { wallMs: Math.max(0, endedAt - rec.startedAt) },\n stdout: parts.stdout,\n stderr: parts.stderr,\n summary: parts.summary || lastNonEmptyLine(parts.stdout),\n failure: parts.failure,\n } satisfies Record<string, unknown>);\n rec.final = envelope;\n rec.state = envelope.state;\n rec.sandbox = undefined;\n return envelope;\n }\n}\n\nfunction lastNonEmptyLine(text: string): string {\n const lines = text\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter(Boolean);\n return lines.length ? lines[lines.length - 1] : \"\";\n}\n\n/** Convenience factory. */\nexport function createExecutionBackend(\n driver: SandboxDriver,\n opts: { now?: () => number } = {},\n): ExecutionBackend {\n return new DriverExecutionBackend(driver, opts);\n}\n", "/**\n * Shared driver plumbing: env-allowlist resolution, a minimal spawn seam (so\n * tests can drive drivers without a real subprocess/daemon), and stream capture.\n */\nimport { spawn as nodeSpawn } from \"node:child_process\";\nimport type { Readable } from \"node:stream\";\n\nimport type { RunManifest } from \"../schemas.js\";\n\n/**\n * The env passed INTO a sandbox is deny-by-default: only names in the manifest's\n * `envAllowlist` are eligible, taking their value from the manifest's explicit\n * `env` first, else the provided base env (the host process env). Anything not on\n * the allowlist is dropped \u2014 a sandbox never silently inherits the host's secrets.\n */\nexport function resolveSandboxEnv(\n manifest: RunManifest,\n baseEnv: NodeJS.ProcessEnv = process.env,\n): Record<string, string> {\n const out: Record<string, string> = {};\n for (const name of manifest.envAllowlist) {\n if (Object.prototype.hasOwnProperty.call(manifest.env, name)) {\n out[name] = manifest.env[name];\n } else if (typeof baseEnv[name] === \"string\") {\n out[name] = baseEnv[name] as string;\n }\n }\n // Explicit manifest.env entries that are ALSO on the allowlist are already\n // covered above; entries off the allowlist are intentionally not passed.\n return out;\n}\n\n/** A child process, narrowed to what the drivers use (Node's ChildProcess fits). */\nexport interface ChildLike {\n readonly pid?: number;\n readonly stdout: Readable | null;\n readonly stderr: Readable | null;\n on(event: \"error\", cb: (err: Error) => void): unknown;\n /** Fires after the process exits AND its stdio has flushed/closed. */\n on(\n event: \"close\",\n cb: (code: number | null, signal: NodeJS.Signals | null) => void,\n ): unknown;\n kill(signal?: NodeJS.Signals | number): boolean;\n}\n\n/** Injectable spawn seam \u2014 defaults to node:child_process.spawn. */\nexport type SpawnFn = (\n command: string,\n args: string[],\n options: {\n cwd?: string;\n env?: NodeJS.ProcessEnv;\n detached?: boolean;\n },\n) => ChildLike;\n\nexport const defaultSpawn: SpawnFn = (command, args, options) =>\n nodeSpawn(command, args, {\n cwd: options.cwd,\n env: options.env,\n detached: options.detached,\n stdio: [\"ignore\", \"pipe\", \"pipe\"],\n }) as unknown as ChildLike;\n\n/** Accumulate a readable stream into a bounded string (guards against a flood). */\nexport function captureStream(\n stream: Readable | null,\n onChunk: (text: string) => void,\n maxBytes = 1_000_000,\n): void {\n if (!stream) return;\n let total = 0;\n stream.setEncoding(\"utf8\");\n stream.on(\"data\", (chunk: string) => {\n if (total >= maxBytes) return;\n total += Buffer.byteLength(chunk);\n onChunk(chunk);\n });\n}\n\n/** The final non-empty line of text \u2014 the reference runner's turn summary. */\nexport function lastLine(text: string): string {\n const lines = text\n .split(\"\\n\")\n .map((l) => l.trimEnd())\n .filter((l) => l.trim().length > 0);\n return lines.length ? lines[lines.length - 1] : \"\";\n}\n", "/**\n * HostProcessDriver \u2014 the reference runner's former direct-exec path, preserved\n * behind the SandboxDriver contract (M12.1).\n *\n * Two modes, chosen by the manifest:\n * \u2022 `inProcess: true` \u2014 runs the caller-supplied {@link InProcessRunner} in THIS\n * process (the reference runner's agent turn). This is the byte-for-byte prior\n * behavior, so Jentrix-side records are identical to the pre-refactor runner.\n * Wall-time/cancel are enforced by aborting the turn's AbortSignal (JS can't be\n * preempted, so a runner that ignores the signal is force-settled after a grace).\n * \u2022 otherwise \u2014 spawns `command` as a real subprocess. CPU-time is enforced with\n * `ulimit -t` (a breach delivers SIGXCPU \u2192 the driver reports a `cpu` kill);\n * wall-time is enforced by the ExecutionBackend killing the process group.\n *\n * Host processes share the host network, so the egress profile is ADVISORY here \u2014\n * true deny-by-default network isolation is the LocalDockerDriver's job.\n */\nimport type {\n LifecycleState,\n RunManifest,\n ResourceLimitKind,\n ResourceUsage,\n} from \"../schemas.js\";\nimport type {\n DriverRunOptions,\n ExecOutcome,\n InProcessRunner,\n Sandbox,\n SandboxDriver,\n SandboxHandle,\n SnapshotRef,\n} from \"../types.js\";\nimport {\n captureStream,\n defaultSpawn,\n lastLine,\n resolveSandboxEnv,\n type ChildLike,\n type SpawnFn,\n} from \"./shared.js\";\n\nconst DRIVER = \"host-process\";\n\nexport interface HostProcessDriverOptions {\n /** Injectable spawn seam (tests). Defaults to node:child_process.spawn. */\n spawn?: SpawnFn;\n /** Base env the allowlist filters (defaults to process.env). */\n baseEnv?: NodeJS.ProcessEnv;\n /** Injectable clock (ms). Defaults to Date.now. */\n now?: () => number;\n}\n\ntype State = LifecycleState;\n\n/** Shell prelude that applies POSIX rlimits before exec-ing the run's argv. */\nfunction ulimitPrelude(manifest: RunManifest): string {\n const parts: string[] = [];\n const cpuMs = manifest.limits.cpuMs;\n if (cpuMs) {\n // RLIMIT_CPU is whole seconds; round UP so a sub-second budget still bounds.\n const cpuSec = Math.max(1, Math.ceil(cpuMs / 1000));\n parts.push(`ulimit -t ${cpuSec} 2>/dev/null || true`);\n }\n if (manifest.limits.memoryBytes) {\n // Virtual-memory ceiling in KB. Unsupported on some platforms (macOS) \u2014 the\n // `|| true` keeps it best-effort; Docker's --memory is the real enforcement.\n const kb = Math.max(1, Math.ceil(manifest.limits.memoryBytes / 1024));\n parts.push(`ulimit -v ${kb} 2>/dev/null || true`);\n }\n if (manifest.limits.diskBytes) {\n // Max file size in 1024-byte blocks (best-effort disk proxy).\n const blocks = Math.max(1, Math.ceil(manifest.limits.diskBytes / 1024));\n parts.push(`ulimit -f ${blocks} 2>/dev/null || true`);\n }\n return parts.length ? parts.join(\"; \") + \"; \" : \"\";\n}\n\n/** A run backed by a real host subprocess. */\nclass SubprocessSandbox implements Sandbox {\n readonly handle: SandboxHandle;\n private _state: State = \"STARTING\";\n private readonly child: ChildLike;\n private readonly startedAt: number;\n private readonly now: () => number;\n private stdout = \"\";\n private stderr = \"\";\n private killedByUs = false;\n private killLimit: ResourceLimitKind | null = null;\n private readonly outcome: Promise<ExecOutcome>;\n\n constructor(\n manifest: RunManifest,\n spawn: SpawnFn,\n baseEnv: NodeJS.ProcessEnv,\n now: () => number,\n ) {\n this.now = now;\n this.startedAt = now();\n if (manifest.command.length === 0) {\n throw new Error(\n \"HostProcessDriver: a subprocess manifest must declare a non-empty `command`.\",\n );\n }\n const cwd =\n manifest.workdir ??\n (manifest.codeSnapshot.kind === \"checkout\"\n ? manifest.codeSnapshot.path\n ? `${manifest.codeSnapshot.ref}/${manifest.codeSnapshot.path}`\n : manifest.codeSnapshot.ref\n : undefined);\n const script = `${ulimitPrelude(manifest)}exec \"$@\"`;\n // The sandbox env is deny-by-default (allowlist-gated). PATH is INFRASTRUCTURE,\n // not host state \u2014 inject a baseline so the shell and coreutils resolve; without\n // it a host run cannot even find `sh`. Everything else stays allowlist-gated.\n const sandboxEnv = resolveSandboxEnv(manifest, baseEnv);\n if (!sandboxEnv.PATH) {\n sandboxEnv.PATH = baseEnv.PATH ?? \"/usr/bin:/bin:/usr/sbin:/sbin\";\n }\n // detached \u2192 the child leads its own process group, so a wall-time/cancel\n // kill can signal the WHOLE group (the shell plus anything it spawned).\n this.child = spawn(\n \"/bin/sh\",\n [\"-c\", script, \"stacks-sandbox\", ...manifest.command],\n {\n cwd,\n env: sandboxEnv,\n detached: true,\n },\n );\n this._state = \"RUNNING\";\n this.handle = {\n driver: DRIVER,\n id: this.child.pid ? String(this.child.pid) : \"unknown\",\n runId: manifest.runId,\n createdAt: new Date(this.startedAt).toISOString(),\n meta: { pid: this.child.pid },\n };\n captureStream(this.child.stdout, (t) => (this.stdout += t));\n captureStream(this.child.stderr, (t) => (this.stderr += t));\n\n this.outcome = new Promise<ExecOutcome>((resolve) => {\n let settled = false;\n const settle = (o: ExecOutcome) => {\n if (settled) return;\n settled = true;\n resolve(o);\n };\n this.child.on(\"error\", (err) => {\n this._state = \"FAILED\";\n settle({\n exitCode: null,\n signal: null,\n stdout: this.stdout,\n stderr: this.stderr || String(err?.message ?? err),\n killed: this.killedByUs,\n summary: lastLine(this.stdout),\n });\n });\n this.child.on(\"close\", (code, signal) => {\n // SIGXCPU is the kernel's RLIMIT_CPU breach signal \u2014 a `cpu` kill the\n // driver itself observed (distinct from a backend-initiated wall-time kill).\n const resourceLimit: ResourceLimitKind | null =\n this.killLimit ?? (signal === \"SIGXCPU\" ? \"cpu\" : null);\n this._state = code === 0 ? \"SUCCEEDED\" : \"FAILED\";\n settle({\n exitCode: code,\n signal,\n stdout: this.stdout,\n stderr: this.stderr,\n killed: this.killedByUs,\n resourceLimit,\n summary: lastLine(this.stdout),\n });\n });\n });\n }\n\n get state(): State {\n return this._state;\n }\n\n wait(): Promise<ExecOutcome> {\n return this.outcome;\n }\n\n async kill(req?: {\n reason?: string;\n limit?: ResourceLimitKind;\n graceMs?: number;\n }): Promise<void> {\n this.killedByUs = true;\n this.killLimit = req?.limit ?? null;\n const grace = req?.graceMs ?? 2000;\n const signalGroup = (sig: NodeJS.Signals) => {\n const pid = this.child.pid;\n try {\n if (pid) process.kill(-pid, sig);\n else this.child.kill(sig);\n } catch {\n // Already gone / not permitted \u2014 fall back to a direct child kill.\n try {\n this.child.kill(sig);\n } catch {\n /* already dead */\n }\n }\n };\n signalGroup(\"SIGTERM\");\n const timer = setTimeout(() => signalGroup(\"SIGKILL\"), grace);\n (timer as { unref?: () => void }).unref?.();\n }\n\n async usage(): Promise<ResourceUsage> {\n return { wallMs: Math.max(0, this.now() - this.startedAt) };\n }\n}\n\n/** A run backed by an in-process turn (the reference runner's direct-exec path). */\nclass InProcessSandbox implements Sandbox {\n readonly handle: SandboxHandle;\n private _state: State = \"RUNNING\";\n private readonly controller = new AbortController();\n private readonly startedAt: number;\n private readonly now: () => number;\n private killed = false;\n private killLimit: ResourceLimitKind | null = null;\n private readonly outcome: Promise<ExecOutcome>;\n private settleFn!: (o: ExecOutcome) => void;\n private done = false;\n\n constructor(\n manifest: RunManifest,\n runner: InProcessRunner,\n opts: DriverRunOptions,\n now: () => number,\n ) {\n this.now = now;\n this.startedAt = now();\n this.handle = {\n driver: DRIVER,\n id: `inproc-${manifest.runId}`,\n runId: manifest.runId,\n createdAt: new Date(this.startedAt).toISOString(),\n };\n this.outcome = new Promise<ExecOutcome>((resolve) => {\n this.settleFn = (o) => {\n if (this.done) return;\n this.done = true;\n resolve(o);\n };\n });\n // A caller cancel (opts.signal) is a freeze/cancel \u2014 abort the turn.\n if (opts.signal) {\n if (opts.signal.aborted) void this.kill({ reason: \"canceled\" });\n else\n opts.signal.addEventListener(\n \"abort\",\n () => void this.kill({ reason: \"canceled\" }),\n { once: true },\n );\n }\n runner({ manifest, signal: this.controller.signal })\n .then((r) => {\n this._state = this.killed ? \"KILLED\" : \"SUCCEEDED\";\n this.settleFn({\n exitCode: r.exitCode ?? 0,\n signal: null,\n stdout: r.summary,\n stderr: \"\",\n summary: r.summary,\n killed: this.killed,\n resourceLimit: this.killLimit,\n });\n })\n .catch((err: unknown) => {\n this._state = \"FAILED\";\n this.settleFn({\n exitCode: 1,\n signal: null,\n stdout: \"\",\n stderr: err instanceof Error ? err.message : String(err),\n summary: \"\",\n killed: this.killed,\n resourceLimit: this.killLimit,\n });\n });\n }\n\n get state(): State {\n return this._state;\n }\n\n wait(): Promise<ExecOutcome> {\n return this.outcome;\n }\n\n async kill(req?: {\n reason?: string;\n limit?: ResourceLimitKind;\n graceMs?: number;\n }): Promise<void> {\n this.killed = true;\n this.killLimit = req?.limit ?? null;\n this._state = req?.limit === \"wall_time\" ? \"TIMED_OUT\" : \"KILLED\";\n this.controller.abort();\n // JS can't be preempted: if the turn ignores the abort, force-settle after a\n // grace so the backend never hangs waiting on a runaway in-process run.\n const grace = req?.graceMs ?? 2000;\n // Ref'd on purpose: this force-settle is the backstop for a runner that\n // ignores the abort \u2014 it must fire even if nothing else keeps the loop alive.\n setTimeout(() => {\n this.settleFn({\n exitCode: null,\n signal: \"SIGKILL\",\n stdout: \"\",\n stderr: \"in-process run did not stop on abort within the grace period\",\n summary: \"\",\n killed: true,\n resourceLimit: this.killLimit,\n });\n }, grace);\n }\n\n async usage(): Promise<ResourceUsage> {\n return { wallMs: Math.max(0, this.now() - this.startedAt) };\n }\n}\n\nexport class HostProcessDriver implements SandboxDriver {\n readonly name = DRIVER;\n private readonly spawn: SpawnFn;\n private readonly baseEnv: NodeJS.ProcessEnv;\n private readonly now: () => number;\n\n constructor(opts: HostProcessDriverOptions = {}) {\n this.spawn = opts.spawn ?? defaultSpawn;\n this.baseEnv = opts.baseEnv ?? process.env;\n this.now = opts.now ?? Date.now;\n }\n\n async create(\n manifest: RunManifest,\n opts: DriverRunOptions = {},\n ): Promise<Sandbox> {\n if (manifest.inProcess) {\n if (!opts.inProcessRunner) {\n throw new Error(\n \"HostProcessDriver: an in-process manifest requires an inProcessRunner.\",\n );\n }\n return new InProcessSandbox(\n manifest,\n opts.inProcessRunner,\n opts,\n this.now,\n );\n }\n return new SubprocessSandbox(manifest, this.spawn, this.baseEnv, this.now);\n }\n\n async resume(): Promise<Sandbox> {\n // Host subprocesses are ephemeral to this process \u2014 nothing to re-attach to.\n throw new Error(\n \"HostProcessDriver does not support resume(): host runs are ephemeral.\",\n );\n }\n\n async snapshot(): Promise<SnapshotRef> {\n throw new Error(\"HostProcessDriver does not support snapshot().\");\n }\n\n async terminate(sandbox: Sandbox): Promise<void> {\n // Best-effort: ensure nothing lingers.\n await sandbox.kill({ reason: \"terminate\", graceMs: 0 }).catch(() => {});\n }\n}\n", "/**\n * LocalDockerDriver \u2014 runs each run in an EPHEMERAL container over a preconfigured\n * checkout, with enforced resource limits and a DENY-BY-DEFAULT egress profile (M12.1).\n *\n * Resource enforcement is delegated to the kernel via docker flags: `--cpus`\n * (throttle) + `--ulimit cpu` (hard CPU-time budget; a breach kills the run \u2014 SIGXCPU\n * on some platforms, SIGKILL/exit-137 on Docker Desktop's Linux VM), `--memory` (OOM\n * kill), `--ulimit fsize` (disk/file-size), `--pids-limit`. Wall-time is enforced\n * by the ExecutionBackend (which `kill()`s the container). Egress is `--network none`\n * UNLESS the operator sets STACKS_SANDBOX_ALLOW_NET=1 \u2014 the single dev bypass, off by\n * default, mirroring the webhook SSRF allow-flag (STACKS_WEBHOOK_ALLOW_PRIVATE).\n */\nimport type {\n EgressProfile,\n LifecycleState,\n RunManifest,\n ResourceLimitKind,\n ResourceUsage,\n RuntimeClass,\n} from \"../schemas.js\";\nimport type {\n DriverRunOptions,\n ExecOutcome,\n Sandbox,\n SandboxDriver,\n SandboxHandle,\n SnapshotRef,\n} from \"../types.js\";\nimport {\n captureStream,\n defaultSpawn,\n lastLine,\n resolveSandboxEnv,\n type ChildLike,\n type SpawnFn,\n} from \"./shared.js\";\n\nconst DRIVER = \"local-docker\";\n/** Default mount point + workdir for a bind-mounted checkout. */\nconst DEFAULT_WORKDIR = \"/workspace\";\n/**\n * The Docker host-gateway alias. When a run has network, the container reaches\n * host-run services (the Jentrix MCP server, the provider API proxy) through this\n * name. Docker Desktop resolves it automatically, but a Linux engine needs the\n * explicit `--add-host \u2026:host-gateway` this driver adds.\n */\nexport const HOST_GATEWAY_ALIAS = \"host.docker.internal\";\n\nexport interface LocalDockerDriverOptions {\n /** The preconfigured runner image for `checkout`-kind snapshots. */\n image?: string;\n /** Injectable command runner (tests). Defaults to node:child_process.spawn. */\n spawn?: SpawnFn;\n /** The docker binary (default \"docker\"). */\n dockerPath?: string;\n /** Base env the allowlist filters (defaults to process.env). */\n baseEnv?: NodeJS.ProcessEnv;\n /** Injectable clock (ms). Defaults to Date.now. */\n now?: () => number;\n /**\n * Whether the operator has opted into sandbox network egress. Default reads\n * STACKS_SANDBOX_ALLOW_NET === \"1\". Even when true, a `deny` egress profile\n * still gets no network \u2014 the flag only lets a non-deny profile take effect.\n */\n allowNet?: () => boolean;\n /**\n * The URL of a running egress proxy that enforces + audits the run's allowlist.\n * When set, an `allowlist`-profile run is routed THROUGH the proxy (the accepted\n * allowlisted data path) instead of fail-closing to deny. Injectable as a\n * function so a per-run proxy can be started lazily.\n */\n egressProxyUrl?: () => string | undefined;\n /**\n * The per-run user-defined Docker network the sandbox joins to reach an\n * in-container (sidecar) egress gateway by DNS name. When set (alongside a\n * matching `egressProxyUrl`), an `allowlist` run is `--network`'d onto it \u2014 the\n * firewall-independent in-container allowlisted egress path. Injectable as a\n * function so a per-run network can be created lazily.\n */\n egressNetwork?: () => string | undefined;\n /**\n * Container-name prefix (default `stacks-run-`). The managed EVAL path sets\n * `stacks-eval-` so a container is deterministically `stacks-eval-<runId>`\n * (runId = the sandboxRun id) \u2014 the R10 orphan-reaping contract: a worker can\n * list + reap its own containers by name/label after a crash.\n */\n namePrefix?: string;\n /**\n * Driver-level labels stamped on EVERY run (e.g. `{ \"stacks.kind\": \"eval\" }`),\n * merged under the canonical `stacks.runId` and the per-run manifest labels. A\n * reconciler filters a class of containers with `docker ps --filter label=\u2026`.\n */\n labels?: Record<string, string>;\n log?: (msg: string) => void;\n}\n\n/** The default container-name prefix (harness/generic runs). */\nexport const DEFAULT_CONTAINER_NAME_PREFIX = \"stacks-run-\";\n\n/** Docker container/object names must match [a-zA-Z0-9][a-zA-Z0-9_.-]*. */\nfunction sanitizeName(\n runId: string,\n prefix: string = DEFAULT_CONTAINER_NAME_PREFIX,\n): string {\n const cleaned = runId.replace(/[^a-zA-Z0-9_.-]/g, \"-\");\n return `${prefix}${cleaned}`.slice(0, 200);\n}\n\n/**\n * The Docker `--runtime` value for a runtime class. `runc` is the daemon default\n * (no flag). `gvisor` maps to `runsc`; `microvm` to `kata-runtime`. The MANAGED\n * runtime installs these (M12 infra-a/infra-b) \u2014 the local driver simply passes the\n * flag through, so a host without the runtime installed surfaces a clear docker\n * error rather than silently dropping the isolation request.\n */\nconst RUNTIME_FLAG: Record<RuntimeClass, string | null> = {\n runc: null,\n gvisor: \"runsc\",\n microvm: \"kata-runtime\",\n};\n\n/** The `--runtime <name>` args for a manifest's runtime class ([] for stock runc). */\nexport function runtimeArgs(runtimeClass: RuntimeClass | undefined): string[] {\n if (!runtimeClass) return [];\n const flag = RUNTIME_FLAG[runtimeClass];\n return flag ? [\"--runtime\", flag] : [];\n}\n\n/** Whether the run gets network: the operator flag AND a non-deny egress profile. */\nexport function egressAllowsNetwork(\n manifest: RunManifest,\n allowNet: boolean,\n): boolean {\n return allowNet && manifest.egress.mode !== \"deny\";\n}\n\n/**\n * The egress posture the driver ACTUALLY enforces for a run (real enforcement, not\n * the declared intent). Deny-by-default is enforced at the kernel via `--network\n * none`; a non-deny profile only takes effect when the operator opted into\n * `STACKS_SANDBOX_ALLOW_NET` \u2014 otherwise the local driver has no per-host egress\n * proxy and DOWNGRADES the run to `deny` (fail-closed). The result is data the\n * sandbox controller records + audits, so the run record shows what network the\n * container really got rather than only what it asked for.\n */\nexport interface EgressEnforcement {\n /** What the manifest declared. */\n requestedMode: EgressProfile[\"mode\"];\n /** What the driver actually applied at the kernel (`--network none` \u21D2 \"deny\"). */\n enforcedMode: EgressProfile[\"mode\"];\n /** Whether the container got a network at all. */\n netEnabled: boolean;\n /** True when a non-deny request was fail-closed to deny (no local egress proxy). */\n downgraded: boolean;\n /**\n * The egress proxy URL the container is pointed at (via HTTP(S)_PROXY) when an\n * `allowlist` profile is enforced through a proxy \u2014 the REAL allowlisted egress\n * data path. Undefined for deny / direct-net runs.\n */\n proxyUrl?: string;\n /**\n * The user-defined Docker network the sandbox is attached to when the allowlist\n * gateway runs as an in-container sidecar (the sandbox reaches the gateway by\n * container DNS name on this network \u2014 the firewall-independent in-container\n * data path). Undefined when the proxy is host-bound / for deny/direct-net runs.\n */\n network?: string;\n /** Human-readable reason for the enforced posture. */\n reason: string;\n}\n\n/** Options controlling how egress is enforced (an allowlist egress proxy). */\nexport interface EgressEnforcementOptions {\n /**\n * A running egress proxy's URL. When set, an `allowlist` profile is HONORED by\n * routing the container's egress through the proxy (which enforces + audits the\n * allowlist) instead of fail-closing to deny \u2014 the accepted allowlisted data\n * path. Deny and open profiles ignore it.\n */\n proxyUrl?: string;\n /**\n * A user-defined Docker network the sandbox joins to reach an in-container\n * (sidecar) egress gateway by DNS name. When set alongside `proxyUrl` for an\n * `allowlist` run, the sandbox is `--network`'d onto it instead of getting the\n * host-gateway bridge \u2014 so the container\u2192gateway hop routes regardless of the\n * host firewall (the zero-skip in-container path).\n */\n network?: string;\n}\n\n/** Resolve the network posture the driver enforces for a manifest (pure, testable). */\nexport function resolveEgressEnforcement(\n manifest: RunManifest,\n allowNet: boolean,\n opts: EgressEnforcementOptions = {},\n): EgressEnforcement {\n const requestedMode = manifest.egress.mode;\n\n // The ACCEPTED allowlisted data path: an `allowlist` profile with a configured\n // egress proxy is honored by routing egress THROUGH the proxy (the proxy is the\n // enforcement + audit choke point), so the run gets a network locked to the\n // allowlist \u2014 no operator allow-net flag required.\n if (requestedMode === \"allowlist\" && opts.proxyUrl) {\n return {\n requestedMode,\n enforcedMode: \"allowlist\",\n netEnabled: true,\n downgraded: false,\n proxyUrl: opts.proxyUrl,\n ...(opts.network ? { network: opts.network } : {}),\n reason: opts.network\n ? `egress \"allowlist\" honored via in-container gateway on network ${opts.network} (${opts.proxyUrl})`\n : `egress \"allowlist\" honored via egress proxy (${opts.proxyUrl})`,\n };\n }\n\n const netEnabled = egressAllowsNetwork(manifest, allowNet);\n const enforcedMode: EgressProfile[\"mode\"] = netEnabled\n ? requestedMode\n : \"deny\";\n const downgraded = requestedMode !== \"deny\" && !netEnabled;\n const reason = netEnabled\n ? `egress \"${requestedMode}\" honored (STACKS_SANDBOX_ALLOW_NET set)`\n : requestedMode === \"deny\"\n ? \"deny-by-default: --network none (no egress declared)\"\n : `egress \"${requestedMode}\" requested but STACKS_SANDBOX_ALLOW_NET not set \u2014 ` +\n \"fail-closed to --network none (no local egress proxy)\";\n return { requestedMode, enforcedMode, netEnabled, downgraded, reason };\n}\n\n/**\n * Build the `docker run` argv for a manifest. Pure + exported so the argv (resource\n * flags, `--network none`, mounts, env) is unit-testable without a docker daemon.\n */\n/**\n * Rewrite a localhost egress-proxy URL so a container can reach it: the proxy\n * binds to the host's loopback, which inside a container is the container itself\n * \u2014 the Docker host gateway alias is how the container reaches the host.\n */\nexport function containerProxyUrl(proxyUrl: string): string {\n return proxyUrl.replace(\n /127\\.0\\.0\\.1|0\\.0\\.0\\.0|localhost|\\[::1\\]/,\n HOST_GATEWAY_ALIAS,\n );\n}\n\nexport function buildDockerArgs(\n manifest: RunManifest,\n opts: {\n image?: string;\n netEnabled: boolean;\n baseEnv?: NodeJS.ProcessEnv;\n /** When set, inject HTTP(S)_PROXY so all egress routes through the allowlist proxy. */\n proxyUrl?: string;\n /**\n * When set, attach the sandbox to this user-defined Docker network (so it can\n * reach an in-container sidecar egress gateway by DNS name) instead of the\n * host-gateway bridge \u2014 the firewall-independent in-container egress path.\n */\n network?: string;\n /** Container-name prefix (default `stacks-run-`). */\n namePrefix?: string;\n /** Driver-level labels merged onto the run (under the manifest's own labels). */\n labels?: Record<string, string>;\n },\n): string[] {\n // The pinned OCI base image declared on the manifest wins over a\n // codeSnapshot(image) ref, which wins over the driver's default image.\n const image =\n manifest.image ??\n (manifest.codeSnapshot.kind === \"image\"\n ? manifest.codeSnapshot.ref\n : opts.image);\n if (!image) {\n throw new Error(\n \"LocalDockerDriver: no image \u2014 declare `manifest.image`, pass `image` for \" +\n \"checkout-kind snapshots, or use a codeSnapshot of kind 'image'.\",\n );\n }\n const workdir = manifest.workdir ?? DEFAULT_WORKDIR;\n const args: string[] = [\"run\", \"--rm\", \"--init\"];\n args.push(\"--name\", sanitizeName(manifest.runId, opts.namePrefix));\n // Run-identity labels (R10 orphan reaping): stamp the canonical `stacks.runId`,\n // any driver-level class labels (e.g. `stacks.kind=eval`), and the manifest's\n // own labels as `--label`. This is what lets a worker LIST its containers\n // (`docker ps --filter label=stacks.kind=eval`) and reap orphans by name after\n // a crash \u2014 the mechanism, not just a test.\n const labels: Record<string, string> = {\n \"stacks.runId\": manifest.runId,\n ...(opts.labels ?? {}),\n ...manifest.labels,\n };\n for (const [key, value] of Object.entries(labels)) {\n args.push(\"--label\", `${key}=${value}`);\n }\n // Risk-class-driven runtime selection (gVisor / microVM) \u2014 expressed on the\n // manifest, honored by the driver.\n args.push(...runtimeArgs(manifest.runtimeClass));\n\n // Resource ceilings.\n const { limits } = manifest;\n if (limits.cpus) args.push(\"--cpus\", String(limits.cpus));\n if (limits.cpuMs) {\n // Hard CPU-time budget in whole seconds (RLIMIT_CPU) \u2192 SIGXCPU on breach.\n const cpuSec = Math.max(1, Math.ceil(limits.cpuMs / 1000));\n args.push(\"--ulimit\", `cpu=${cpuSec}:${cpuSec}`);\n }\n if (limits.memoryBytes) args.push(\"--memory\", String(limits.memoryBytes));\n if (limits.diskBytes) {\n args.push(\"--ulimit\", `fsize=${limits.diskBytes}:${limits.diskBytes}`);\n }\n if (limits.pids) args.push(\"--pids-limit\", String(limits.pids));\n\n // DENY-BY-DEFAULT egress: no network unless explicitly allowed for this run.\n if (opts.network) {\n // In-container egress gateway (sidecar): attach the sandbox to the per-run\n // user-defined network so it reaches the gateway by container DNS name \u2014 the\n // container\u2192gateway hop routes regardless of the host firewall. No host-gateway\n // bridge is needed (and NOT --network none \u2014 egress is honored via the gateway).\n args.push(\"--network\", opts.network);\n } else if (!opts.netEnabled) {\n args.push(\"--network\", \"none\");\n } else {\n // Network is enabled ONLY to reach host-run services. Map the Docker host\n // gateway so an in-container executor can resolve `host.docker.internal` and\n // actually connect to (and authenticate against) the host's Jentrix MCP server \u2014\n // without this a localhost-rewritten MCP URL resolves nowhere and every agent\n // tool call fails auth. Harmless when the run doesn't use it.\n args.push(\"--add-host\", `${HOST_GATEWAY_ALIAS}:host-gateway`);\n }\n\n // The preconfigured checkout is bind-mounted at the workdir; explicit mounts\n // ride alongside (read-only unless a mount opts into rw).\n if (manifest.codeSnapshot.kind === \"checkout\") {\n const src = manifest.codeSnapshot.path\n ? `${manifest.codeSnapshot.ref}/${manifest.codeSnapshot.path}`\n : manifest.codeSnapshot.ref;\n args.push(\"-v\", `${src}:${workdir}:rw`);\n }\n for (const m of manifest.mounts) {\n args.push(\"-v\", `${m.source}:${m.target}:${m.mode}`);\n }\n args.push(\"--workdir\", workdir);\n\n // Env is allowlist-gated (resolveSandboxEnv drops anything off the allowlist).\n const env = resolveSandboxEnv(manifest, opts.baseEnv ?? {});\n for (const [name, value] of Object.entries(env)) {\n args.push(\"-e\", `${name}=${value}`);\n }\n\n // The allowlisted egress data path: point ALL of the container's egress at the\n // enforcing proxy (which allows only allowlisted hosts and audits the rest).\n // Driver-injected control env \u2014 not host env, so it bypasses the allowlist gate.\n if (opts.proxyUrl) {\n // An in-container (sidecar) gateway is already a container-DNS URL reachable on\n // the shared network \u2014 inject it verbatim. A host-bound proxy binds loopback,\n // which inside a container is the container itself, so rewrite it to the host\n // gateway alias.\n const proxy = opts.network\n ? opts.proxyUrl\n : containerProxyUrl(opts.proxyUrl);\n for (const name of [\n \"HTTP_PROXY\",\n \"HTTPS_PROXY\",\n \"http_proxy\",\n \"https_proxy\",\n ]) {\n args.push(\"-e\", `${name}=${proxy}`);\n }\n // Nothing bypasses the proxy (empty NO_PROXY) \u2014 every host goes through the\n // allowlist choke point.\n args.push(\"-e\", \"NO_PROXY=\", \"-e\", \"no_proxy=\");\n }\n\n args.push(image, ...manifest.command);\n return args;\n}\n\n/** A run backed by a `docker run` foreground process. */\nclass DockerSandbox implements Sandbox {\n readonly handle: SandboxHandle;\n private _state: LifecycleState = \"RUNNING\";\n private readonly child: ChildLike;\n private readonly containerName: string;\n private readonly startedAt: number;\n private readonly now: () => number;\n private readonly dockerPath: string;\n private readonly spawn: SpawnFn;\n private readonly hasMemLimit: boolean;\n private readonly hasCpuLimit: boolean;\n private readonly hasDiskLimit: boolean;\n private stdout = \"\";\n private stderr = \"\";\n private killedByUs = false;\n private killLimit: ResourceLimitKind | null = null;\n private readonly outcome: Promise<ExecOutcome>;\n\n constructor(\n manifest: RunManifest,\n args: string[],\n spawn: SpawnFn,\n dockerPath: string,\n now: () => number,\n namePrefix?: string,\n ) {\n this.now = now;\n this.spawn = spawn;\n this.dockerPath = dockerPath;\n this.startedAt = now();\n this.containerName = sanitizeName(manifest.runId, namePrefix);\n this.hasMemLimit = Boolean(manifest.limits.memoryBytes);\n this.hasCpuLimit = Boolean(manifest.limits.cpuMs);\n this.hasDiskLimit = Boolean(manifest.limits.diskBytes);\n this.child = spawn(dockerPath, args, { env: process.env });\n this.handle = {\n driver: DRIVER,\n id: this.containerName,\n runId: manifest.runId,\n createdAt: new Date(this.startedAt).toISOString(),\n meta: { containerName: this.containerName, pid: this.child.pid },\n };\n captureStream(this.child.stdout, (t) => (this.stdout += t));\n captureStream(this.child.stderr, (t) => (this.stderr += t));\n\n this.outcome = new Promise<ExecOutcome>((resolve) => {\n let settled = false;\n const settle = (o: ExecOutcome) => {\n if (settled) return;\n settled = true;\n resolve(o);\n };\n this.child.on(\"error\", (err) => {\n this._state = \"FAILED\";\n settle({\n exitCode: null,\n signal: null,\n stdout: this.stdout,\n stderr: this.stderr || String(err?.message ?? err),\n killed: this.killedByUs,\n summary: lastLine(this.stdout),\n });\n });\n this.child.on(\"close\", (code, signal) => {\n // Attribute an UNREQUESTED fatal-signal container exit to the declared budget\n // most likely responsible. This must be inferable from the exit code + the\n // manifest's limits ALONE: an exited `--rm` container is gone before\n // `docker inspect .State.OOMKilled` can read it, so no post-mortem probe is\n // possible. Platform reality (verified against Docker Desktop's Linux VM,\n // arm64): a `--ulimit cpu` (RLIMIT_CPU) breach delivers SIGKILL \u2192 exit 137,\n // NOT the textbook SIGXCPU \u2192 152. So a CPU-budget kill must be recognized from\n // 137 as well, or the M12.1 observable exit would degrade to a generic\n // `nonzero_exit` on the Docker driver.\n let resourceLimit: ResourceLimitKind | null = this.killLimit;\n if (!resourceLimit && !this.killedByUs) {\n const signalKilled =\n signal === \"SIGKILL\" ||\n signal === \"SIGXCPU\" ||\n signal === \"SIGXFSZ\" ||\n code === 137 || // 128 + SIGKILL(9)\n code === 152 || // 128 + SIGXCPU(24)\n code === 153; // 128 + SIGXFSZ(25)\n if (signal === \"SIGXFSZ\" || code === 153) {\n // Unambiguous disk/file-size signal: an RLIMIT_FSIZE (`--ulimit fsize`)\n // breach delivers SIGXFSZ (signal 25) \u2192 exit 153 to a process that writes\n // past its file-size budget. Under Docker's `--init` the command is not\n // PID 1, so the signal actually terminates it (verified live, arm64).\n resourceLimit = \"disk\";\n } else if (signal === \"SIGXCPU\" || code === 152) {\n // Unambiguous CPU-time signal (platforms that deliver SIGXCPU).\n resourceLimit = \"cpu\";\n } else if (signalKilled && this.hasCpuLimit) {\n // RLIMIT_CPU hard-limit kill (SIGKILL/137 on this platform). CPU takes\n // precedence over memory here because it is the M12.1 uniquely-owned exit\n // that MUST surface as a structured resource-limit failure. (Both budgets\n // are ambiguous under a bare 137, but either verdict is still a structured\n // resource_limit_exceeded, and CPU is the criterion under test.)\n resourceLimit = \"cpu\";\n } else if (signalKilled && this.hasMemLimit) {\n resourceLimit = \"memory\"; // OOM kill (best-effort).\n } else if (signalKilled && this.hasDiskLimit) {\n resourceLimit = \"disk\"; // fsize kill on a platform that used SIGKILL.\n }\n }\n this._state = code === 0 ? \"SUCCEEDED\" : \"FAILED\";\n settle({\n exitCode: code,\n signal,\n stdout: this.stdout,\n stderr: this.stderr,\n killed: this.killedByUs,\n resourceLimit,\n summary: lastLine(this.stdout),\n });\n });\n });\n }\n\n get state(): LifecycleState {\n return this._state;\n }\n\n wait(): Promise<ExecOutcome> {\n return this.outcome;\n }\n\n async kill(req?: {\n reason?: string;\n limit?: ResourceLimitKind;\n graceMs?: number;\n }): Promise<void> {\n this.killedByUs = true;\n this.killLimit = req?.limit ?? null;\n // `docker kill` stops the container itself (the foreground `docker run` child\n // dying does not guarantee the container stops); best-effort + detached.\n try {\n const killer = this.spawn(this.dockerPath, [\"kill\", this.containerName], {\n env: process.env,\n });\n killer.on(\"error\", () => {});\n } catch {\n /* daemon unreachable \u2014 fall through to the child kill */\n }\n try {\n this.child.kill(\"SIGKILL\");\n } catch {\n /* already gone */\n }\n }\n\n async usage(): Promise<ResourceUsage> {\n return { wallMs: Math.max(0, this.now() - this.startedAt) };\n }\n}\n\nexport class LocalDockerDriver implements SandboxDriver {\n readonly name = DRIVER;\n private readonly image?: string;\n private readonly spawn: SpawnFn;\n private readonly dockerPath: string;\n private readonly baseEnv: NodeJS.ProcessEnv;\n private readonly now: () => number;\n private readonly allowNet: () => boolean;\n private readonly egressProxyUrl: () => string | undefined;\n private readonly egressNetwork: () => string | undefined;\n private readonly namePrefix?: string;\n private readonly labels: Record<string, string>;\n private readonly log: (msg: string) => void;\n\n constructor(opts: LocalDockerDriverOptions = {}) {\n this.image = opts.image;\n this.spawn = opts.spawn ?? defaultSpawn;\n this.dockerPath = opts.dockerPath ?? \"docker\";\n this.baseEnv = opts.baseEnv ?? process.env;\n this.now = opts.now ?? Date.now;\n this.allowNet =\n opts.allowNet ?? (() => process.env.STACKS_SANDBOX_ALLOW_NET === \"1\");\n this.egressProxyUrl = opts.egressProxyUrl ?? (() => undefined);\n this.egressNetwork = opts.egressNetwork ?? (() => undefined);\n this.namePrefix = opts.namePrefix;\n this.labels = opts.labels ?? {};\n this.log = opts.log ?? (() => {});\n }\n\n async create(\n manifest: RunManifest,\n _opts: DriverRunOptions = {},\n ): Promise<Sandbox> {\n if (manifest.command.length === 0) {\n throw new Error(\n \"LocalDockerDriver: a manifest must declare a non-empty `command`.\",\n );\n }\n const allowNet = this.allowNet();\n const proxyUrl = this.egressProxyUrl();\n const network = this.egressNetwork();\n const enforcement = resolveEgressEnforcement(manifest, allowNet, {\n proxyUrl,\n ...(network ? { network } : {}),\n });\n if (enforcement.downgraded) {\n this.log(`[local-docker ${manifest.runId}] ${enforcement.reason}`);\n }\n const args = buildDockerArgs(manifest, {\n image: this.image,\n netEnabled: enforcement.netEnabled,\n baseEnv: this.baseEnv,\n ...(enforcement.proxyUrl ? { proxyUrl: enforcement.proxyUrl } : {}),\n ...(enforcement.network ? { network: enforcement.network } : {}),\n ...(this.namePrefix ? { namePrefix: this.namePrefix } : {}),\n ...(Object.keys(this.labels).length ? { labels: this.labels } : {}),\n });\n return new DockerSandbox(\n manifest,\n args,\n this.spawn,\n this.dockerPath,\n this.now,\n this.namePrefix,\n );\n }\n\n async resume(handle: SandboxHandle): Promise<Sandbox> {\n // --rm containers are gone once exited; resume is only meaningful for a still\n // -running container. Not supported for the ephemeral run model.\n throw new Error(\n `LocalDockerDriver does not support resume() for ephemeral (--rm) runs (${handle.id}).`,\n );\n }\n\n async snapshot(sandbox: Sandbox): Promise<SnapshotRef> {\n // `docker commit` the live container into an image. Best-effort; requires the\n // container to still exist (not yet --rm'd).\n const name = sandbox.handle.id;\n const image = `stacks-snapshot-${name}`;\n try {\n const child = this.spawn(this.dockerPath, [\"commit\", name, image], {\n env: process.env,\n });\n child.on(\"error\", () => {});\n } catch {\n /* daemon unreachable */\n }\n return {\n driver: DRIVER,\n id: image,\n createdAt: new Date(this.now()).toISOString(),\n sourceSandboxId: name,\n };\n }\n\n async terminate(sandbox: Sandbox): Promise<void> {\n await sandbox.kill({ reason: \"terminate\", graceMs: 0 }).catch(() => {});\n }\n}\n", "/**\n * Turn-summary wire protocol between the docker container entrypoint (run-turn.ts)\n * and the execution bridge (execution.ts) \u2014 M12.1.\n *\n * The host driver runs the turn IN-PROCESS and gets the agent's summary as a return\n * value, so the FULL (usually multi-line) summary is preserved verbatim. The docker\n * driver instead reads the container's stdout, where a naive \"last non-empty line\"\n * capture would TRUNCATE a multi-line summary \u2014 and that summary is recorded as the\n * stage's TEST_EVIDENCE artifact, so a truncated capture would make the docker-driver\n * Jentrix-side records DIFFER from the pre-refactor/host records.\n *\n * To keep the records identical, run-turn.ts wraps the summary in these delimiters\n * and the bridge recovers the whole region from stdout. Kept in a tiny standalone\n * module so the container entrypoint doesn't pull in the driver/child-process graph.\n */\nexport const TURN_SUMMARY_BEGIN = \"<<<STACKS_TURN_SUMMARY_BEGIN>>>\";\nexport const TURN_SUMMARY_END = \"<<<STACKS_TURN_SUMMARY_END>>>\";\n\n/** Wrap a turn summary for stdout emission by the container entrypoint. */\nexport function frameTurnSummary(summary: string): string {\n return `${TURN_SUMMARY_BEGIN}\\n${summary}\\n${TURN_SUMMARY_END}\\n`;\n}\n\n/**\n * Recover the FULL turn summary the container emitted from its captured stdout.\n * Uses `lastIndexOf` so incidental stdout noise before the region is tolerated;\n * falls back to the driver-provided value when the delimiters are absent.\n */\nexport function extractTurnSummary(stdout: string, fallback: string): string {\n const begin = stdout.lastIndexOf(TURN_SUMMARY_BEGIN);\n const end = stdout.lastIndexOf(TURN_SUMMARY_END);\n if (begin >= 0 && end > begin) {\n return stdout.slice(begin + TURN_SUMMARY_BEGIN.length, end).trim();\n }\n return fallback;\n}\n", "/**\n * runner-pool.ts \u2014 bounded, job-id-deduplicating work pool for the reference\n * workflow runner (Concurrent Harness Execution PRD \u00A77, Stage 4 \"S4\").\n *\n * Replaces the runner's two single serialized promise chains with two of these:\n * \u2022 an AGENT-TURN pool (STACKS_RUNNER_MAX_CONCURRENT_JOBS, default 1) bounding\n * planner/reviewer/executor turns;\n * \u2022 a COMMIT pool (STACKS_RUNNER_MAX_CONCURRENT_COMMITS, default 1) bounding\n * post-validation commit/push continuations \u2014 a DEDICATED pool so a freshly\n * approved commit never sits behind a long model turn, even when the\n * agent-turn pool is full.\n *\n * Server-side `claim_agent_job` CAS is STILL the final ownership guard; this pool\n * only avoids WASTING a slot on a delivery that a peer already owns. Two local\n * invariants the runner leans on:\n *\n * \u2022 DEDUP \u2014 a jobId already queued/running/detached collapses a duplicate\n * delivery (webhook OR poll \u2014 both call submit() on the SAME pool object, so\n * the registry spans both inputs) BEFORE it consumes a slot. submit() returns\n * false for a collapsed duplicate.\n *\n * \u2022 WATCHDOG DETACH keeps the jobId in the dedup registry \u2014 the slot frees so a\n * hung provider session can't wedge throughput, but the jobId stays\n * \"inflight\" until the orphaned work TRULY settles, so a re-delivery of the\n * SAME jobId can never race the orphan on the SAME job-scoped worktree. (A\n * retry mints a NEW jobId \u2192 a different worktree dir, so it is not a\n * duplicate and proceeds in its own slot.)\n *\n * The pool is a plain in-memory local-queue optimization by design \u2014 the PRD is\n * explicit that \"the runner deduplicates the LOCAL queue by job id\" while the\n * server-side claim CAS remains the trust boundary. It shells out to nothing and\n * adds no dependency.\n */\n\n/** A point-in-time gauge for the telemetry line. */\nexport interface PoolSnapshot {\n kind: string;\n /** The raw STACKS_RUNNER_MAX_CONCURRENT_* value the operator configured. */\n configuredMax: number;\n /** configuredMax clamped to [1, hardMax] \u2014 the bound actually enforced. */\n effectiveMax: number;\n /** Slots consumed right now (bounded by effectiveMax). */\n active: number;\n /** Tasks waiting for a slot. */\n queueDepth: number;\n /** Dedup-registry size: queued + running + watchdog-detached job ids. */\n inflight: number;\n}\n\ninterface Pending {\n jobId: string;\n run: () => Promise<void>;\n enqueuedAt: number;\n}\n\nexport interface BoundedDedupPoolOpts {\n /** Hard upper bound on a single task; when exceeded the SLOT is released and\n * the orphan keeps running (attempt-guarded, worktree retained). */\n watchdogMs: number;\n /** Injectable clock for deterministic tests (defaults to Date.now). */\n now?: () => number;\n log?: (msg: string) => void;\n /** Fired when a task actually STARTS running \u2014 queueLatencyMs is submit\u2192start\n * (the pool's per-pool queue latency the PRD reports separately). */\n onStart?: (jobId: string, queueLatencyMs: number) => void;\n /** Fired after any slot free or true settle \u2014 a hook to re-emit telemetry. */\n onSettle?: () => void;\n}\n\n/**\n * Clamp an operator-configured concurrency to a finite documented maximum. A\n * missing / non-integer / < 1 value falls back to `fallback` (never unbounded);\n * anything above `hardMax` is clamped down to it. Both pools document their\n * finite maxima at the call site.\n */\nexport function parseBoundedMax(\n raw: string | undefined,\n fallback: number,\n hardMax: number,\n): number {\n const n = Number(raw);\n if (!Number.isInteger(n) || n < 1) return Math.min(fallback, hardMax);\n return Math.min(n, hardMax);\n}\n\n/**\n * F8 (AGE-505): parse a positive-integer env knob (a timeout in ms, a turn\n * budget, a port) with a NaN-safe fallback. `Number(undefined)`/typos silently\n * produced NaN timeouts and budgets before \u2014 a NaN setTimeout fires\n * immediately and a NaN maxTurns disables the budget entirely.\n */\nexport function parsePositiveInt(\n raw: string | undefined,\n fallback: number,\n): number {\n const n = Number(raw);\n if (!Number.isFinite(n) || !Number.isInteger(n) || n < 1) return fallback;\n return n;\n}\n\nexport class BoundedDedupPool {\n private active = 0;\n private readonly queue: Pending[] = [];\n private readonly inflight = new Set<string>();\n\n constructor(\n readonly kind: string,\n /** The bound actually enforced (already clamped by parseBoundedMax). */\n readonly effectiveMax: number,\n private readonly configuredMax: number,\n private readonly opts: BoundedDedupPoolOpts,\n ) {}\n\n private now(): number {\n return this.opts.now ? this.opts.now() : Date.now();\n }\n\n /**\n * Enqueue `run` for `jobId`. Returns false (a no-op) when `jobId` is already\n * queued/running/detached \u2014 the duplicate is COLLAPSED before it consumes a\n * slot. Returns true when the job was newly enqueued.\n */\n submit(jobId: string, run: () => Promise<void>): boolean {\n if (this.inflight.has(jobId)) {\n this.opts.log?.(\n `[pool:${this.kind}] duplicate delivery for job ${jobId} collapsed (already queued/running).`,\n );\n return false;\n }\n this.inflight.add(jobId);\n this.queue.push({ jobId, run, enqueuedAt: this.now() });\n this.pump();\n return true;\n }\n\n /**\n * True when `jobId` is already queued/running/watchdog-detached. Lets the poll\n * loop skip the expensive fresh get_agent_job re-read for a job already in the\n * shared registry; submit() is still the authoritative dedup guard (a webhook\n * delivery racing the poll read collapses on submit()).\n */\n has(jobId: string): boolean {\n return this.inflight.has(jobId);\n }\n\n snapshot(): PoolSnapshot {\n return {\n kind: this.kind,\n configuredMax: this.configuredMax,\n effectiveMax: this.effectiveMax,\n active: this.active,\n queueDepth: this.queue.length,\n inflight: this.inflight.size,\n };\n }\n\n private pump(): void {\n while (this.active < this.effectiveMax && this.queue.length > 0) {\n const item = this.queue.shift() as Pending;\n this.active += 1;\n this.opts.onStart?.(\n item.jobId,\n Math.max(0, this.now() - item.enqueuedAt),\n );\n this.runOne(item);\n }\n }\n\n private runOne(item: Pending): void {\n let slotReleased = false;\n const releaseSlot = (reason: \"settled\" | \"watchdog\"): void => {\n if (slotReleased) return;\n slotReleased = true;\n this.active -= 1;\n if (reason === \"watchdog\") {\n this.opts.log?.(\n `[pool:${this.kind}] job ${item.jobId} exceeded ${this.opts.watchdogMs}ms \u2014 releasing the slot; the orphan stays attempt-guarded (worktree retained, a re-delivery of ${item.jobId} stays collapsed) and the server-side claim CAS rejects its late writes.`,\n );\n }\n this.pump();\n this.opts.onSettle?.();\n };\n const timer = setTimeout(\n () => releaseSlot(\"watchdog\"),\n this.opts.watchdogMs,\n );\n // Errors are consumed HERE \u2014 a failed/detached task must never surface as an\n // unhandled rejection.\n const work = item\n .run()\n .catch((err) =>\n this.opts.log?.(\n `[pool:${this.kind}] job ${item.jobId} failed: ${\n err instanceof Error ? err.message : String(err)\n }`,\n ),\n );\n // The SLOT is freed on the watchdog OR the true settle, whichever first.\n // The DEDUP registry entry is dropped ONLY on the true settle \u2014 so a job the\n // watchdog detached keeps its registry slot until its orphan really finishes,\n // never sharing its worktree with a same-jobId re-delivery.\n void work.finally(() => {\n clearTimeout(timer);\n releaseSlot(\"settled\");\n this.inflight.delete(item.jobId);\n this.opts.onSettle?.();\n });\n }\n}\n", "/**\n * Reference-runner \u2194 ExecutionBackend bridge (M12.1).\n *\n * The reference runner used to run each agent turn by calling `runJentrixAgent`\n * directly (the \"direct-exec path\"). It now runs every turn THROUGH an\n * {@link ExecutionBackend} (@stacks/execution): the backend enforces the turn's\n * wall-time/CPU budget and returns a structured result envelope.\n *\n * Two drivers, selected by STACKS_EXECUTION_DRIVER:\n * \u2022 \"host\" (default) \u2014 HostProcessDriver in-process mode. It runs the SAME\n * `runJentrixAgent` call as before, so the Jentrix-side records\n * (AgentJob/AgentRun/Activity/artifacts) are IDENTICAL to the pre-refactor\n * runner. This is the former direct-exec path, preserved behind the contract.\n * \u2022 \"docker\" \u2014 LocalDockerDriver: the turn runs in an ephemeral container over\n * the mounted checkout (entrypoint: run-turn.ts) with enforced limits and a\n * deny-by-default egress profile. Because an agent turn must reach the MCP\n * server + provider API, the container needs egress: set\n * STACKS_SANDBOX_ALLOW_NET=1 (the single dev bypass, off by default) or run it\n * behind an egress proxy. Requires a preconfigured image (STACKS_SANDBOX_IMAGE).\n */\nimport {\n createExecutionBackend,\n HostProcessDriver,\n LocalDockerDriver,\n isResourceLimitExceeded,\n type ExecutionBackend,\n type ResultEnvelope,\n type RunManifestInput,\n} from \"../../packages/execution/src/index.js\";\n\nimport {\n runJentrixAgent,\n type AgentProvider,\n type JentrixConnection,\n} from \"./jentrix.js\";\nimport { extractTurnSummary } from \"./turn-protocol.js\";\nimport { parsePositiveInt } from \"./runner-pool.js\";\n\nexport type ExecutionDriverKind = \"host\" | \"docker\";\n\n/** The seam the reference runner writes its Jentrix-side records through. */\nexport type RunAgentFn = typeof runJentrixAgent;\n\n/**\n * Rewrite a host-facing MCP URL to one an IN-CONTAINER executor can reach.\n *\n * Inside a container `localhost`/`127.0.0.1` is the container itself \u2014 NOT the host\n * running Jentrix \u2014 so handing a loopback MCP URL to a docker-driver turn makes every\n * agent tool call fail to connect: an executor \"authentication failure\" that leaves\n * the turn unable to do (or verify) any work. Loopback hosts are mapped to the Docker\n * host-gateway alias, which the LocalDockerDriver wires up via\n * `--add-host host.docker.internal:host-gateway`. Non-loopback URLs pass through.\n */\nexport function containerMcpUrl(rawUrl: string): string {\n try {\n const u = new URL(rawUrl);\n if ([\"localhost\", \"127.0.0.1\", \"0.0.0.0\", \"::1\"].includes(u.hostname)) {\n u.hostname = \"host.docker.internal\";\n }\n return u.toString();\n } catch {\n return rawUrl;\n }\n}\n\n/** The execution driver the runner uses (default host \u2014 identical prior records). */\nexport function executionDriverKind(): ExecutionDriverKind {\n return process.env.STACKS_EXECUTION_DRIVER === \"docker\" ? \"docker\" : \"host\";\n}\n\n/** The sandbox egress bypass \u2014 off by default, mirroring the webhook allow-flag. */\nexport function sandboxNetAllowed(): boolean {\n return process.env.STACKS_SANDBOX_ALLOW_NET === \"1\";\n}\n\n/** Default wall-time budget for an agent turn (generous \u2014 real turns are long).\n * F8 (AGE-505): NaN-safe \u2014 a typo'd env value falls back to the default. */\nconst DEFAULT_WALL_MS = parsePositiveInt(\n process.env.STACKS_EXEC_WALL_MS,\n 45 * 60 * 1000,\n);\n\n/**\n * The in-container entrypoint argv for the docker driver (image-provided).\n *\n * Resolved PER CALL (not frozen at import) so an operator \u2014 or a live record-parity\n * test \u2014 can override it via STACKS_SANDBOX_TURN_CMD. A value that starts with \"[\"\n * is parsed as a JSON argv array (so an argument containing spaces survives intact);\n * otherwise it is whitespace-split. Defaults to the image-provided run-turn.ts.\n */\nexport function dockerTurnCommand(\n env: NodeJS.ProcessEnv = process.env,\n): string[] {\n const raw = env.STACKS_SANDBOX_TURN_CMD;\n if (!raw || !raw.trim()) {\n return [\"node\", \"--import\", \"tsx\", \"/app/agents/run-turn.ts\"];\n }\n const trimmed = raw.trim();\n if (trimmed.startsWith(\"[\")) {\n try {\n const parsed = JSON.parse(trimmed);\n if (\n Array.isArray(parsed) &&\n parsed.length > 0 &&\n parsed.every((s) => typeof s === \"string\")\n ) {\n return parsed as string[];\n }\n } catch {\n /* not valid JSON \u2014 fall through to whitespace split */\n }\n }\n return trimmed.split(/\\s+/);\n}\n\nlet turnCounter = 0;\nlet verificationCounter = 0;\nlet verificationBackend: ExecutionBackend | null = null;\n\nexport function makeExecutionBackend(\n kind: ExecutionDriverKind = executionDriverKind(),\n): { backend: ExecutionBackend; kind: ExecutionDriverKind } {\n const driver =\n kind === \"docker\"\n ? new LocalDockerDriver({\n image: process.env.STACKS_SANDBOX_IMAGE,\n log: (m) => console.log(m),\n })\n : new HostProcessDriver();\n return { backend: createExecutionBackend(driver), kind };\n}\n\nconst VERIFICATION_WRAPPER = `set -e\nif [ ! -d \"$STACKS_VERIFICATION_DEPENDENCIES\" ]; then\n echo \"managed verification dependencies are missing\" >&2\n exit 127\nfi\nworkspace=/tmp/stacks-verification-workspace\nmkdir \"$workspace\"\ntar -C /workspace --exclude=./node_modules -cf - . | tar -C \"$workspace\" -xf -\nln -s \"$STACKS_VERIFICATION_DEPENDENCIES\" \"$workspace/node_modules\"\nlink_pkg() {\n if [ -n \"$2\" ] && [ -d \"$2\" ] && [ -d \"$workspace/$1\" ]; then\n rm -rf \"$workspace/$1/node_modules\"\n ln -s \"$2\" \"$workspace/$1/node_modules\"\n fi\n}\nlink_pkg services/worker \"$STACKS_VERIFICATION_WORKER_DEPENDENCIES\"\nlink_pkg agents \"$STACKS_VERIFICATION_AGENTS_DEPENDENCIES\"\nlink_pkg cli \"$STACKS_VERIFICATION_CLI_DEPENDENCIES\"\ncd \"$workspace\"\nexport PATH=\"$workspace/node_modules/.bin:/app/node_modules/.bin:/app/agents/node_modules/.bin:/usr/local/bin:/usr/bin:/bin\"\nexec sh -lc \"$STACKS_VERIFICATION_COMMAND\"`;\n\n/** A verification command's complete managed-sandbox contract. Exported so the\n * deny-egress and scrubbed-environment boundary is pinned by a small test. */\nexport function managedVerificationManifest(\n cwd: string,\n command: string,\n timeoutMs: number,\n): RunManifestInput {\n const env = {\n CI: \"1\",\n // The verification image preloads the lockfile-pinned pnpm release here.\n // HOME is intentionally scrubbed to /tmp, so Corepack otherwise ignores\n // that cache and attempts a denied registry download before tests start.\n COREPACK_HOME: \"/root/.cache/node/corepack\",\n HOME: \"/tmp\",\n NODE_ENV: \"test\",\n NO_COLOR: \"1\",\n PATH: \"/workspace/node_modules/.bin:/app/node_modules/.bin:/app/agents/node_modules/.bin:/usr/local/bin:/usr/bin:/bin\",\n // pnpm 11 defaults verifyDepsBeforeRun to \"install\". The worktree consumes\n // dependencies from the digest-pinned verification image, so an implicit\n // install would both ignore that immutable input and retry the registry\n // forever under the intentional deny-egress policy.\n PNPM_CONFIG_VERIFY_DEPS_BEFORE_RUN: \"false\",\n STACKS_VERIFICATION_COMMAND: command,\n STACKS_VERIFICATION_DEPENDENCIES:\n process.env.STACKS_VERIFICATION_DEPENDENCIES ?? \"/app/node_modules\",\n // AGE-907: the repo has THREE dependency-firewalled standalone packages\n // (own lockfile + `.npmrc ignore-workspace`) whose node_modules are all\n // gitignored \u2014 so each is absent from the stage checkout AND not covered by\n // the root tree above. Without its tree, a command targeting one of them can\n // only run by installing, which deny-egress hangs on until the wall clock.\n // Every link is SOFT (the wrapper skips a missing dir) so an image built\n // before any of these existed keeps running every other command unchanged.\n STACKS_VERIFICATION_WORKER_DEPENDENCIES:\n process.env.STACKS_VERIFICATION_WORKER_DEPENDENCIES ??\n \"/app/services/worker/node_modules\",\n STACKS_VERIFICATION_AGENTS_DEPENDENCIES:\n process.env.STACKS_VERIFICATION_AGENTS_DEPENDENCIES ??\n \"/app/agents/node_modules\",\n STACKS_VERIFICATION_CLI_DEPENDENCIES:\n process.env.STACKS_VERIFICATION_CLI_DEPENDENCIES ??\n \"/app/cli/node_modules\",\n };\n return {\n runId: `harness-verify-${process.pid}-${verificationCounter++}`,\n command: [\"sh\", \"-lc\", VERIFICATION_WRAPPER],\n codeSnapshot: { kind: \"checkout\", ref: cwd },\n workdir: \"/workspace\",\n envAllowlist: Object.keys(env),\n env,\n capabilities: [],\n limits: {\n cpus: 2,\n memoryBytes: 4 * 1024 * 1024 * 1024,\n pids: 512,\n wallMs: timeoutMs,\n },\n egress: { mode: \"deny\", allow: [] },\n labels: { kind: \"harness-verification\" },\n };\n}\n\nfunction managedVerificationBackend(): ExecutionBackend {\n if (verificationBackend) return verificationBackend;\n const image =\n process.env.STACKS_VERIFICATION_IMAGE ?? process.env.STACKS_SANDBOX_IMAGE;\n if (!image) {\n throw new Error(\n \"managed verification requires STACKS_VERIFICATION_IMAGE (or STACKS_SANDBOX_IMAGE)\",\n );\n }\n verificationBackend = createExecutionBackend(\n new LocalDockerDriver({\n image,\n allowNet: () => false,\n baseEnv: {},\n log: (message) => console.log(message),\n }),\n );\n return verificationBackend;\n}\n\nexport interface ManagedVerificationResult {\n command: string;\n exitCode: number;\n timedOut: boolean;\n stdout: string;\n stderr: string;\n startedAt: string;\n finishedAt: string;\n}\n\n// ---------------------------------------------------------------------------\n// D2 (AGE-507): the HOST verification lane for E2E. `pnpm test:e2e` provisions\n// its own isolated Docker pgvector database and drives a real dev server \u2014\n// it needs the Docker socket and localhost networking, which the sealed\n// deny-egress container rightly lacks. Instead of a cluster to seal E2E (the\n// deleted D1 lane), E2E runs as a runner-attested HOST command under a small\n// explicit env allowlist (never the runner's tokens/keys); unit/lint/typecheck\n// keep the sealed container. The attested tier stays INTEGRATION_LOCAL.\n// ---------------------------------------------------------------------------\n\nconst HOST_VERIFICATION_COMMAND_RE = /\\btest:e2e\\b/;\n\nexport function isHostVerificationCommand(command: string): boolean {\n return HOST_VERIFICATION_COMMAND_RE.test(command);\n}\n\n/** Pass-through host vars the E2E toolchain needs (docker CLI, pnpm, node). */\nconst HOST_ENV_PASSTHROUGH = [\n \"PATH\",\n \"HOME\",\n \"TMPDIR\",\n \"SHELL\",\n \"USER\",\n \"LANG\",\n \"DOCKER_HOST\",\n \"DOCKER_CONFIG\",\n] as const;\n\n/** The scrubbed host-lane environment: the explicit passthrough list + CI\n * knobs, and NOTHING else \u2014 no STACKS_* tokens, no provider keys. The E2E\n * suite reads its DB URL from the worktree's own .env.local. */\nexport function hostVerificationEnv(\n base: NodeJS.ProcessEnv = process.env,\n): Record<string, string> {\n const env: Record<string, string> = {\n CI: \"1\",\n NODE_ENV: \"test\",\n NO_COLOR: \"1\",\n };\n for (const key of HOST_ENV_PASSTHROUGH) {\n const value = base[key];\n if (value) env[key] = value;\n }\n return env;\n}\n\nasync function runHostVerificationCommand(input: {\n cwd: string;\n command: string;\n timeoutMs: number;\n signal?: AbortSignal;\n}): Promise<ManagedVerificationResult> {\n const startedAt = new Date().toISOString();\n const { spawn } = await import(\"node:child_process\");\n return new Promise((resolve) => {\n let timedOut = false;\n const child = spawn(\"sh\", [\"-lc\", input.command], {\n cwd: input.cwd,\n env: hostVerificationEnv(),\n });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout.on(\"data\", (d) => (stdout += d));\n child.stderr.on(\"data\", (d) => (stderr += d));\n const finish = (exitCode: number) => {\n clearTimeout(timer);\n input.signal?.removeEventListener(\"abort\", onAbort);\n resolve({\n command: input.command,\n exitCode,\n timedOut,\n stdout,\n stderr,\n startedAt,\n finishedAt: new Date().toISOString(),\n });\n };\n const timer = setTimeout(() => {\n timedOut = true;\n child.kill(\"SIGKILL\");\n }, input.timeoutMs);\n const onAbort = () => child.kill(\"SIGKILL\");\n input.signal?.addEventListener(\"abort\", onAbort, { once: true });\n child.on(\"error\", () => finish(127));\n child.on(\"close\", (code) => finish(timedOut ? 124 : (code ?? 1)));\n });\n}\n\n/** Execute one planner-declared command in an ephemeral, env-scrubbed,\n * deny-egress container. The stage worktree is its only writable host mount.\n * E2E commands take the D2 host lane above. */\nexport async function runManagedVerificationCommand(input: {\n cwd: string;\n command: string;\n timeoutMs: number;\n signal?: AbortSignal;\n}): Promise<ManagedVerificationResult> {\n if (isHostVerificationCommand(input.command)) {\n return runHostVerificationCommand(input);\n }\n const startedAt = new Date().toISOString();\n const envelope = await managedVerificationBackend().run(\n managedVerificationManifest(input.cwd, input.command, input.timeoutMs),\n { signal: input.signal },\n );\n return {\n command: input.command,\n exitCode:\n envelope.exitCode ??\n (envelope.status === \"timed_out\"\n ? 124\n : envelope.status === \"canceled\"\n ? 130\n : 127),\n timedOut: envelope.status === \"timed_out\",\n stdout: envelope.stdout,\n stderr: envelope.stderr,\n startedAt,\n finishedAt: new Date().toISOString(),\n };\n}\n\n/** Prove Docker + the configured verification image can start before each Harness\n * turn is claimed. Re-run every time so a recovered daemon/image resumes at the\n * closest safe point without requiring a runner restart. */\nexport function preflightManagedVerification(): Promise<void> {\n return runManagedVerificationCommand({\n cwd: process.cwd(),\n command: \"command -v sh >/dev/null\",\n timeoutMs: 30_000,\n }).then((result) => {\n if (result.exitCode !== 0 || result.timedOut) {\n throw new Error(\n `managed verification preflight failed (${result.timedOut ? \"timed out\" : `exit ${result.exitCode}`}): ${result.stderr.trim()}`,\n );\n }\n });\n}\n\nexport interface TurnSpec {\n /** Execution-layer run id (distinct from the Jentrix AgentRun id). */\n runId?: string;\n jobId?: string;\n prompt: string;\n systemPrompt: string;\n /** Writable checkout for an executor turn; unset for a tools-only turn. */\n repoCwd?: string;\n /** W3: harness STAGE executor leg \u2014 the runtime registers the executor hooks\n * (runner-owned submissions, foreground-evidence stop nudge). */\n runnerOwnsSubmissions?: boolean;\n /**\n * M18.3 R7: run against `repoCwd` READ-ONLY. Set from the dispatch role's\n * entry in `role-repo-access.ts` (true for a validator or any unrecognized\n * role) and enforced by the providers \u2014 claude withholds the write/edit\n * tools, codex runs the shell under a read-only sandbox. Threaded through\n * BOTH drivers below so the docker path is not a hole in the guarantee.\n */\n repoReadOnly?: boolean;\n maxTurns: number;\n /** Claude-only model override for this turn (see JentrixAgentConfig.model). */\n model?: string;\n connection: JentrixConnection;\n provider: AgentProvider;\n /** Aborted on freeze/cancel \u2014 threaded into the turn so it stops. */\n signal?: AbortSignal;\n /** Wall-time budget (ms). Defaults to STACKS_EXEC_WALL_MS. */\n wallMs?: number;\n /** Optional hard CPU-time budget (ms). */\n cpuMs?: number;\n}\n\n/**\n * The allowlisted env the docker driver injects so `run-turn.ts` can reconstruct\n * and run the SAME agent turn IN-CONTAINER as the in-process host path. Exported so\n * record-parity tests can assert the container is handed identical turn inputs (and\n * a REACHABLE, loopback-rewritten MCP URL) without a live daemon.\n */\nexport function dockerTurnEnv(spec: TurnSpec): Record<string, string> {\n return {\n STACKS_TURN_PROMPT: spec.prompt,\n STACKS_TURN_SYSTEM_PROMPT: spec.systemPrompt,\n STACKS_TURN_MAX_TURNS: String(spec.maxTurns),\n STACKS_TURN_MODEL: spec.model ?? \"\",\n STACKS_TURN_PROVIDER: spec.provider,\n STACKS_TURN_REPO_CWD: spec.repoCwd ? \"/workspace\" : \"\",\n // W3: the container path reconstructs the SAME runJentrixAgent call, so the\n // executor hooks must ride across too \u2014 otherwise the docker driver would\n // silently run without them.\n STACKS_TURN_RUNNER_OWNS_SUBMISSIONS: spec.runnerOwnsSubmissions ? \"1\" : \"\",\n // M18.3 R7: the read-only verdict crosses into the container too, so a\n // docker-driven validator turn is sandboxed exactly like the host one.\n STACKS_TURN_REPO_READ_ONLY: spec.repoReadOnly ? \"1\" : \"\",\n // Loopback \u2192 host-gateway so the containerized executor can actually reach and\n // AUTHENTICATE against the host's Jentrix MCP server (see containerMcpUrl).\n STACKS_MCP_URL: containerMcpUrl(spec.connection.url),\n STACKS_MCP_BEARER: spec.connection.token,\n };\n}\n\n/**\n * Run ONE agent turn through the ExecutionBackend and return its summary text.\n * On the host driver this is byte-for-byte the prior in-process `runJentrixAgent`\n * call (identical records) plus wall-time enforcement; a budget kill surfaces as a\n * thrown error so the runner fails the job (blocks for a human) \u2014 never a silent hang.\n *\n * `deps.runAgent` overrides the Jentrix-writing call on the HOST path (default: the\n * real `runJentrixAgent`); tests inject a recorder to evidence record parity offline.\n */\nexport async function runTurnThroughBackend(\n backend: ExecutionBackend,\n kind: ExecutionDriverKind,\n spec: TurnSpec,\n deps: { runAgent?: RunAgentFn } = {},\n): Promise<string> {\n const runAgent = deps.runAgent ?? runJentrixAgent;\n const runId = spec.runId ?? `exec-${Date.now()}-${turnCounter++}`;\n const wallMs = spec.wallMs ?? DEFAULT_WALL_MS;\n const egress: RunManifestInput[\"egress\"] = sandboxNetAllowed()\n ? { mode: \"open\" }\n : { mode: \"deny\" };\n\n if (kind === \"host\") {\n const manifest: RunManifestInput = {\n runId,\n jobId: spec.jobId,\n inProcess: true,\n command: [],\n codeSnapshot: { kind: \"checkout\", ref: spec.repoCwd ?? process.cwd() },\n ...(spec.repoCwd ? { workdir: spec.repoCwd } : {}),\n capabilities: [{ id: \"mcp:stacks\", kind: \"mcp\" }],\n limits: { wallMs, ...(spec.cpuMs ? { cpuMs: spec.cpuMs } : {}) },\n egress,\n };\n const envelope = await backend.run(manifest, {\n signal: spec.signal,\n inProcessRunner: async ({ signal }) => ({\n // The SAME call the direct-exec path made \u2014 identical Jentrix-side records.\n summary: await runAgent(\n spec.prompt,\n {\n systemPrompt: spec.systemPrompt,\n maxTurns: spec.maxTurns,\n ...(spec.model ? { model: spec.model } : {}),\n ...(spec.repoCwd ? { repoCwd: spec.repoCwd } : {}),\n ...(spec.runnerOwnsSubmissions\n ? { runnerOwnsSubmissions: true }\n : {}),\n ...(spec.repoReadOnly ? { repoReadOnly: spec.repoReadOnly } : {}),\n },\n {\n connection: spec.connection,\n provider: spec.provider,\n signal,\n },\n ),\n }),\n });\n return summaryOrThrow(envelope);\n }\n\n // Docker: the turn runs in an ephemeral container over the mounted checkout.\n // The turn spec rides in via allowlisted env (never on the command line) and is\n // reconstructed by run-turn.ts into the identical `runJentrixAgent` call.\n const turnEnv = dockerTurnEnv(spec);\n const manifest: RunManifestInput = {\n runId,\n jobId: spec.jobId,\n command: dockerTurnCommand(),\n codeSnapshot: {\n kind: \"checkout\",\n ref: spec.repoCwd ?? process.cwd(),\n },\n workdir: \"/workspace\",\n envAllowlist: [\n ...Object.keys(turnEnv),\n // Provider credentials + infra inherited from the host env.\n \"ANTHROPIC_API_KEY\",\n \"STACKS_AGENT_MODEL\",\n \"STACKS_CLAUDE_EFFORT\",\n \"HOME\",\n \"PATH\",\n ],\n env: turnEnv,\n capabilities: [{ id: \"mcp:stacks\", kind: \"mcp\" }],\n limits: { wallMs, ...(spec.cpuMs ? { cpuMs: spec.cpuMs } : {}) },\n // A containerized agent turn needs egress to the MCP server + provider API;\n // it only runs when the operator has enabled it (deny-by-default otherwise).\n // The allowlisted host is the REACHABLE (host-gateway-rewritten) MCP host.\n egress: sandboxNetAllowed()\n ? { mode: \"allowlist\", allow: [new URL(turnEnv.STACKS_MCP_URL).host] }\n : { mode: \"deny\" },\n };\n const envelope = await backend.run(manifest, { signal: spec.signal });\n // Recover the FULL container summary from stdout (the framed region), so the\n // captured evidence is byte-for-byte the host driver's in-process summary rather\n // than a truncated last line \u2014 this is what keeps the Jentrix-side records identical.\n return summaryOrThrow(envelope, (e) =>\n extractTurnSummary(e.stdout, e.summary),\n );\n}\n\n/** The turn summary on success; a descriptive throw on any structured failure. */\nfunction summaryOrThrow(\n envelope: ResultEnvelope,\n extractSummary: (e: ResultEnvelope) => string = (e) => e.summary,\n): string {\n if (envelope.status === \"succeeded\") return extractSummary(envelope);\n const f = envelope.failure;\n if (isResourceLimitExceeded(envelope)) {\n throw new Error(\n `agent turn killed: ${f?.limit} budget exceeded (${envelope.state}) \u2014 ${f?.message}`,\n );\n }\n throw new Error(\n `agent turn ${envelope.status} (${envelope.state}): ${\n f?.message ?? envelope.stderr ?? \"no detail\"\n }`,\n );\n}\n", "/**\n * Reference-runner authentication selector (M12.4b, AGE-174; legacy PATs\n * removed 2026-07, D4/AGE-509).\n *\n * The reference `workflow-runner` supports two provisioning modes, selected by\n * `STACKS_RUNNER_MODE`:\n *\n * \u2022 `managed` \u2014 the Jentrix-operated plane. Zero standing PATs; every role token\n * is minted per-run from workload identity (see `managed-auth.ts`).\n * \u2022 `self-hosted` \u2014 a runner on your own box. Authenticates via the M11.1\n * bootstrap + claim-URL flow: a ONE-TIME bootstrap token is redeemed at a\n * single-use, short-TTL claim URL for short-lived role tokens (refreshed\n * thereafter). No standing PAT required.\n *\n * The pre-M12.4 standing-PAT path (STACKS_RUNNER_TOKEN / STACKS_PLANNER_TOKEN /\n * STACKS_REVIEWER_TOKEN) was DELETED: nothing reads those env vars anymore, and\n * an unset mode is a configuration error naming the two real modes.\n *\n * `resolveRunnerAuth` returns a `RunnerTokenProvider`; the runner resolves each\n * role's bearer token through it at use-time, so short-lived tokens refresh\n * transparently.\n */\nimport {\n mkdirSync,\n readFileSync,\n renameSync,\n unlinkSync,\n writeFileSync,\n} from \"node:fs\";\nimport { dirname } from \"node:path\";\n\nimport {\n createCachingTokenProvider,\n createHttpCapabilityMinter,\n createManagedTokenProvider,\n type CachingProviderOptions,\n type CapabilityMinter,\n type ManagedRunContext,\n type MintedToken,\n type RunnerRole,\n type RunnerTokenProvider,\n} from \"./managed-auth.js\";\n\nexport type {\n MintedToken,\n RunnerRole,\n RunnerTokenProvider,\n} from \"./managed-auth.js\";\n\n/**\n * Refuse to authenticate a call with an empty bearer (AGE-687).\n *\n * The runner's module-level role tokens start as `\"\"` and are (re)written only\n * by `refreshRoleTokens()`, which runs on the drive/commit/poll ticks and at leg\n * starts. A caller firing on its OWN timer \u2014 the heartbeat pump \u2014 can therefore\n * read one before the first refresh lands or while a re-mint is in flight.\n * Interpolating that into `Bearer ${token}` emits the literal header `Bearer `,\n * which the endpoint reports as `invalid_token / \"No authorization provided\"` \u2014\n * indistinguishable from a revoked token, and it burns both transient retries on\n * a condition no retry can fix at that call site.\n *\n * Failing fast and legibly is the correct direction: the token is missing\n * locally, not rejected remotely, and the caller's next tick has a real one.\n */\nexport function assertBearerPresent(token: string, context: string): void {\n if (token) return;\n throw new Error(\n `${context} refused: no bearer token available (role token not yet minted, or a re-mint is in flight). This is a local credential gap, not a server rejection.`,\n );\n}\n\n/**\n * A source of short-lived role tokens for the self-hosted path \u2014 the M11.1\n * bootstrap + claim-URL flow. Injectable so tests can drive it without HTTP.\n */\nexport interface RoleTokenSource {\n obtain(role: RunnerRole): Promise<MintedToken>;\n}\n\nexport interface SelfHostedTokenProviderDeps {\n source: RoleTokenSource;\n cache?: CachingProviderOptions;\n}\n\n/** Self-hosted provider: short-lived tokens from the bootstrap + claim-URL flow. */\nexport function createSelfHostedTokenProvider(\n deps: SelfHostedTokenProviderDeps,\n): RunnerTokenProvider {\n return createCachingTokenProvider(\n \"self-hosted\",\n (role) => deps.source.obtain(role),\n deps.cache,\n );\n}\n\nexport interface BootstrapClaimConfig {\n /** One-time bootstrap token (NOT a standing PAT) redeemed at the claim URL. */\n bootstrapToken: string;\n /** Single-use, short-TTL claim URL where the runner claims its credentials. */\n claimUrl: string;\n /** Injectable for tests; defaults to the global `fetch`. */\n fetchImpl?: typeof fetch;\n /** AGE-837: persist the ROTATED refresh credential here so a respawned\n * process (launchd once-mode) resumes the chain instead of re-presenting\n * the spent bootstrap. Secret material \u2014 written 0600, must be gitignored.\n * Unset = the pre-AGE-837 in-memory-only behavior. */\n statePath?: string;\n}\n\n/** Best-effort read of a persisted refresh credential; absent/corrupt = null. */\nfunction readPersistedRefresh(path: string | undefined): string | null {\n if (!path) return null;\n try {\n const parsed = JSON.parse(readFileSync(path, \"utf8\")) as {\n refreshToken?: unknown;\n };\n return typeof parsed.refreshToken === \"string\" && parsed.refreshToken\n ? parsed.refreshToken\n : null;\n } catch {\n return null;\n }\n}\n\n/** Atomically persist the newest refresh credential (tmp + rename, 0600). A\n * write failure only WARNS: auth still works in-process; the cost is one\n * fresh-grant ritual after the next restart, not a failed claim now. */\nfunction persistRefresh(path: string | undefined, refreshToken: string): void {\n if (!path) return;\n try {\n mkdirSync(dirname(path), { recursive: true });\n const tmp = `${path}.tmp`;\n writeFileSync(\n tmp,\n `${JSON.stringify({ refreshToken, rotatedAt: new Date().toISOString() })}\\n`,\n { mode: 0o600 },\n );\n renameSync(tmp, path);\n } catch (err) {\n console.error(\n `[auth] failed to persist refresh state to ${path}: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n}\n\nfunction dropPersistedRefresh(path: string | undefined): void {\n if (!path) return;\n try {\n unlinkSync(path);\n } catch {\n // Already gone (or never written) \u2014 the goal state.\n }\n}\n\n/**\n * Default self-hosted token source: the M11.1 bootstrap + claim-URL flow. The\n * FIRST claim redeems the one-time bootstrap token; the claim endpoint returns a\n * short-lived role token plus a refresh credential, and subsequent obtains\n * refresh with that credential \u2014 the bootstrap token is never a standing PAT and\n * is spent exactly once. Fails closed (throws) on any non-2xx or a response\n * missing the short-lived token.\n */\nexport function createBootstrapClaimSource(\n cfg: BootstrapClaimConfig,\n): RoleTokenSource {\n const doFetch = cfg.fetchImpl ?? fetch;\n // AGE-837: a persisted chain outranks the configured bootstrap \u2014 the\n // bootstrap in env is SPENT the moment any process redeems it, so on a\n // respawn the disk state is the only credential that can still work.\n let refreshToken: string | null = readPersistedRefresh(cfg.statePath);\n // Serialize claims: concurrent first-obtains must NOT each spend the one-time\n // bootstrap token \u2014 the first claim rotates to the refresh credential before\n // the next runs. A rejection never poisons the queue.\n let queue: Promise<unknown> = Promise.resolve();\n\n const post = (\n grant: \"bootstrap\" | \"refresh\",\n token: string,\n role: RunnerRole,\n ) =>\n doFetch(cfg.claimUrl, {\n method: \"POST\",\n headers: { \"content-type\": \"application/json\" },\n body: JSON.stringify({ role, grant, token }),\n // AGE-835: a claim fetch that stalls (no server response, dead socket)\n // hangs this queue FOREVER \u2014 rejections don't poison it, but an unsettled\n // promise does, and every later obtain chains behind it. Fail loudly\n // instead; the next tick re-obtains.\n signal: AbortSignal.timeout(30_000),\n });\n\n const claimOne = async (role: RunnerRole): Promise<MintedToken> => {\n let res = refreshToken\n ? await post(\"refresh\", refreshToken, role)\n : await post(\"bootstrap\", cfg.bootstrapToken, role);\n // AGE-922: a 401 on the REFRESH grant means the PERSISTED chain is dead \u2014\n // it says nothing about the bootstrap in env, which the operator may have\n // just re-minted precisely because of this 401. Dropping the file alone was\n // not enough on either axis: the in-memory `refreshToken` survived, so every\n // later obtain in this process re-presented the dead credential, and the\n // thrown message told the operator to mint a grant they had already minted.\n // Clear BOTH and retry once on the bootstrap, so a stale state file\n // self-heals instead of costing a hand-deleted file plus a restart.\n if (res.status === 401 && refreshToken) {\n refreshToken = null;\n dropPersistedRefresh(cfg.statePath);\n console.error(\n `[auth] persisted refresh chain rejected (401) \u2014 falling back to the configured bootstrap grant (AGE-922).`,\n );\n res = await post(\"bootstrap\", cfg.bootstrapToken, role);\n }\n if (!res.ok) {\n // Reaching here on a 401 means the BOOTSTRAP itself was rejected (the\n // refresh fallback above already ran), so the ritual really is owed.\n if (res.status === 401) dropPersistedRefresh(cfg.statePath);\n throw new Error(\n `claim-URL redemption failed (${res.status}) for the ${role} role${\n res.status === 401\n ? \" \u2014 the configured bootstrap grant is spent, expired, or revoked (a persisted refresh chain, if any, was already retried and dropped); mint a fresh bootstrap grant (POST /api/agents/bootstrap) and update STACKS_BOOTSTRAP_TOKEN + STACKS_CLAIM_URL in agents/.env\"\n : \"\"\n }`,\n );\n }\n const body = (await res.json()) as {\n token?: string;\n expiresAt?: string;\n refreshToken?: string;\n };\n if (!body.token || !body.expiresAt) {\n throw new Error(\n `claim-URL returned no short-lived token for the ${role} role`,\n );\n }\n // Rotate to the refresh credential so the one-time bootstrap is spent once;\n // persist it so a respawned process resumes the chain (AGE-837).\n if (body.refreshToken) {\n refreshToken = body.refreshToken;\n persistRefresh(cfg.statePath, body.refreshToken);\n }\n return { token: body.token, expiresAt: body.expiresAt };\n };\n\n return {\n obtain(role) {\n const run = queue.then(() => claimOne(role));\n queue = run.catch(() => {});\n return run;\n },\n };\n}\n\nexport interface ResolveRunnerAuthDeps {\n env?: NodeJS.ProcessEnv;\n cache?: CachingProviderOptions;\n /** Managed mode: the capability minter + run context. Defaults to the HTTP\n * minter built from workload-identity env when omitted. */\n managed?: {\n minter?: CapabilityMinter;\n runContext?: ManagedRunContext;\n onMint?: (role: RunnerRole, minted: MintedToken) => void;\n };\n /** Self-hosted mode: the role-token source. Defaults to the bootstrap +\n * claim-URL source built from env when omitted. */\n selfHosted?: { source?: RoleTokenSource };\n}\n\nfunction required(env: NodeJS.ProcessEnv, name: string): string {\n const value = env[name];\n if (!value || !value.trim()) {\n throw new Error(\n `STACKS_RUNNER_MODE requires ${name} \u2014 see agents/README.md.`,\n );\n }\n return value;\n}\n\nfunction defaultManagedProvider(\n env: NodeJS.ProcessEnv,\n deps: ResolveRunnerAuthDeps,\n): RunnerTokenProvider {\n const minter =\n deps.managed?.minter ??\n createHttpCapabilityMinter({\n exchangeUrl: required(env, \"STACKS_TOKEN_EXCHANGE_URL\"),\n // The worker's short-lived workload-identity SVID (M12.4a) \u2014 not a PAT.\n svid: required(env, \"STACKS_WORKLOAD_SVID\"),\n });\n const runContext = deps.managed?.runContext ?? {\n runId: required(env, \"STACKS_RUN_ID\"),\n workspaceId: required(env, \"STACKS_WORKSPACE_ID\"),\n };\n return createManagedTokenProvider({\n minter,\n runContext,\n env,\n onMint: deps.managed?.onMint,\n cache: deps.cache,\n });\n}\n\nfunction defaultSelfHostedProvider(\n env: NodeJS.ProcessEnv,\n deps: ResolveRunnerAuthDeps,\n): RunnerTokenProvider {\n const source =\n deps.selfHosted?.source ??\n createBootstrapClaimSource({\n bootstrapToken: required(env, \"STACKS_BOOTSTRAP_TOKEN\"),\n claimUrl: required(env, \"STACKS_CLAIM_URL\"),\n // AGE-837: default ON \u2014 resuming the persisted chain across restarts is\n // what kills the fresh-grant-per-restart ritual (launchd once-mode\n // respawns above all). Relative to the runner's cwd (agents/).\n statePath:\n env.STACKS_AUTH_STATE_PATH?.trim() || \".runner-auth-state.json\",\n });\n return createSelfHostedTokenProvider({ source, cache: deps.cache });\n}\n\n/**\n * Select and construct the runner's token provider from the environment.\n *\n * STACKS_RUNNER_MODE=managed \u2192 workload identity (zero PATs)\n * STACKS_RUNNER_MODE=self-hosted \u2192 M11.1 bootstrap + claim-URL (short-lived)\n * anything else \u2192 configuration error (the legacy\n * standing-PAT path was deleted, D4)\n */\nexport function resolveRunnerAuth(\n deps: ResolveRunnerAuthDeps = {},\n): RunnerTokenProvider {\n const env = deps.env ?? process.env;\n const mode = (env.STACKS_RUNNER_MODE ?? \"\").trim().toLowerCase();\n\n if (mode === \"managed\") return defaultManagedProvider(env, deps);\n if (mode === \"self-hosted\" || mode === \"selfhosted\") {\n return defaultSelfHostedProvider(env, deps);\n }\n if (mode) {\n throw new Error(\n `Unknown STACKS_RUNNER_MODE=\"${mode}\". Use \"managed\" or \"self-hosted\".`,\n );\n }\n throw new Error(\n \"No runner auth configured. Set STACKS_RUNNER_MODE=self-hosted (M11.1 \" +\n \"bootstrap + claim-URL \u2014 mint a grant via POST /api/agents/bootstrap, \" +\n \"then set STACKS_BOOTSTRAP_TOKEN + STACKS_CLAIM_URL) or =managed \" +\n \"(workload identity). The standing-PAT path was removed (D4, 2026-07).\",\n );\n}\n", "/**\n * Standing-PAT retirement policy (M12.4b, AGE-174).\n *\n * This module is THE single place that NAMES the standing personal-access-token\n * env vars the managed execution path must never carry. It only ever *forbids*\n * them \u2014 it never reads one for consumption. Keeping the names here (and NOT in\n * the managed-path modules) is deliberate: the managed-path grep test\n * (`runner-auth.smoke.test.ts`) can then assert that no managed-path file so much\n * as mentions a standing-PAT env var, with this policy file as the one allowed\n * declaration site.\n *\n * Background: before M12.4 the reference runner authenticated every role with a\n * long-lived PAT (`STACKS_RUNNER_TOKEN` / `STACKS_PLANNER_TOKEN` /\n * `STACKS_REVIEWER_TOKEN`). M12.4a introduced the workload-identity plane +\n * per-run capability tokens; M12.4b (this) retires the standing PATs from the\n * managed plane entirely and deprecates them in the reference runner. The only\n * code allowed to read one is the explicitly-deprecated legacy provider in\n * `runner-auth.ts`, and only for backward-compatible self-hosted runners.\n */\n\n/**\n * The standing PAT env vars retired from the managed execution path. The managed\n * plane authenticates via workload identity + short-lived per-run capability\n * tokens (M12.4a) and carries NONE of these.\n */\nexport const STANDING_PAT_ENV_VARS = [\n \"STACKS_RUNNER_TOKEN\",\n \"STACKS_PLANNER_TOKEN\",\n \"STACKS_REVIEWER_TOKEN\",\n] as const;\n\nexport type StandingPatEnvVar = (typeof STANDING_PAT_ENV_VARS)[number];\n\n/**\n * Thrown when a standing PAT is present in an environment that must be\n * PAT-free \u2014 the managed execution path. Fail-closed: the managed plane refuses\n * to start rather than silently authenticate with a long-lived credential.\n */\nexport class StandingPatOnManagedPathError extends Error {\n readonly present: string[];\n constructor(present: string[]) {\n super(\n `Managed execution path refuses to start: standing PAT env var(s) present ` +\n `(${present.join(\", \")}). The managed plane authenticates via workload ` +\n `identity + per-run capability tokens (M12.4a) and must carry ZERO ` +\n `standing PATs in any env or config. Unset them on the managed plane, or ` +\n `run the deprecated self-hosted legacy path deliberately.`,\n );\n this.name = \"StandingPatOnManagedPathError\";\n this.present = present;\n }\n}\n\n/**\n * Fail closed if any standing PAT leaked into a managed-path environment.\n * Iterates the forbidden NAMES (a variable lookup \u2014 never a literal\n * `process.env.STACKS_*_TOKEN` read) so this presence check can never be mistaken\n * for consumption by the managed-path grep.\n */\nexport function assertNoStandingPatsOnManagedPath(\n env: NodeJS.ProcessEnv = process.env,\n): void {\n const present = STANDING_PAT_ENV_VARS.filter((name) => {\n const value = env[name];\n return typeof value === \"string\" && value.trim().length > 0;\n });\n if (present.length > 0) throw new StandingPatOnManagedPathError(present);\n}\n", "/**\n * Managed execution-path authentication (M12.4b, AGE-174).\n *\n * The managed plane (Jentrix-operated workers) authenticates with ZERO standing\n * PATs. Instead it holds a short-lived, auto-rotated workload-identity SVID\n * (M12.4a) and trades it \u2014 per run \u2014 for narrow, short-TTL capability tokens via\n * the control-plane token exchange. This module is the runner-side seam for that\n * flow:\n *\n * \u2022 `createManagedTokenProvider` fails CLOSED the instant a standing PAT is\n * present in its environment (`assertNoStandingPatsOnManagedPath`), then\n * resolves each role's bearer token by MINTING a capability token from\n * workload identity \u2014 never from a PAT env var.\n * \u2022 `createHttpCapabilityMinter` is the production wiring: it presents the\n * worker's SVID to the control-plane exchange endpoint and receives a\n * run/workspace/role-scoped capability token (a NARROWING of the run's P2.1\n * authorization \u2014 see `@stacks/identity`).\n *\n * INVARIANT (asserted by the managed-path grep in `runner-auth.smoke.test.ts`):\n * this file \u2014 and every other managed-path module \u2014 never READS a standing-PAT\n * env var. The forbidden names live only in `standing-pat-policy.ts`.\n */\nimport { assertNoStandingPatsOnManagedPath } from \"./standing-pat-policy.js\";\n\n/** The three principals the runner authenticates (claim \u2260 submit principal). */\nexport type RunnerRole = \"runner\" | \"planner\" | \"reviewer\";\n\n/** How a role token was provisioned. `legacy-pat` is the deprecated path. */\nexport type RunnerAuthMode = \"managed\" | \"self-hosted\" | \"legacy-pat\";\n\n/** A minted bearer token + its expiry. Short-lived by construction (minutes). */\nexport interface MintedToken {\n token: string;\n /** ISO-8601 expiry. */\n expiresAt: string;\n}\n\n/**\n * Resolves a currently-valid bearer token for a runner role, minting/refreshing\n * as needed. The workflow-runner calls `tokenFor` at each use so a long-running\n * server never presents an expired short-lived token.\n */\nexport interface RunnerTokenProvider {\n readonly mode: RunnerAuthMode;\n tokenFor(role: RunnerRole): Promise<string>;\n /** Drop the cached token for a role so the next `tokenFor` mints fresh.\n * Used at LEG boundaries: every mint ROTATES the server-side bearer, so a\n * mid-leg refresh kills the in-flight session's embedded token \u2014 but a leg\n * must also START with a full-TTL token or it dies at submit. Invalidate +\n * obtain at leg start; leave the small expiry skew everywhere else. */\n invalidate?(role: RunnerRole): void;\n}\n\n/** The run this managed worker was dispatched for (per-run capability scope). */\nexport interface ManagedRunContext {\n runId: string;\n workspaceId: string;\n}\n\n/** Trades workload identity for a short-lived, role-scoped capability token. */\nexport interface CapabilityMinter {\n mint(role: RunnerRole, ctx: ManagedRunContext): Promise<MintedToken>;\n}\n\nexport interface CachingProviderOptions {\n /** Re-mint a role token this many ms before it expires (default 30s). */\n refreshSkewMs?: number;\n now?: () => number;\n}\n\n/**\n * Wrap a per-role `fetchToken` in an expiry-aware cache: a cached token is\n * reused while comfortably before expiry, otherwise re-minted. Both the managed\n * and self-hosted providers build on this so their short-lived tokens refresh\n * transparently across a long-running server's lifetime.\n */\nexport function createCachingTokenProvider(\n mode: RunnerAuthMode,\n fetchToken: (role: RunnerRole) => Promise<MintedToken>,\n opts: CachingProviderOptions = {},\n): RunnerTokenProvider {\n const skew = opts.refreshSkewMs ?? 30_000;\n const now = opts.now ?? (() => Date.now());\n const cache = new Map<RunnerRole, MintedToken>();\n return {\n mode,\n async tokenFor(role) {\n const cached = cache.get(role);\n if (cached) {\n const expMs = Date.parse(cached.expiresAt);\n if (Number.isFinite(expMs) && expMs - now() > skew) return cached.token;\n }\n const minted = await fetchToken(role);\n cache.set(role, minted);\n return minted.token;\n },\n invalidate(role) {\n cache.delete(role);\n },\n };\n}\n\nexport interface ManagedTokenProviderDeps {\n /** Trades the worker's SVID for per-run, role-scoped capability tokens. */\n minter: CapabilityMinter;\n /** The run this managed worker executes (per-run token scope). */\n runContext: ManagedRunContext;\n /** Environment checked for standing PATs at construction (default process.env). */\n env?: NodeJS.ProcessEnv;\n /** Non-secret audit hook fired after each mint (never the token itself). */\n onMint?: (role: RunnerRole, minted: MintedToken) => void;\n cache?: CachingProviderOptions;\n}\n\n/**\n * The managed provider. Fails CLOSED if any standing PAT is present in its\n * environment, then resolves every role token by minting a capability token from\n * workload identity \u2014 the managed plane carries ZERO standing PATs.\n */\nexport function createManagedTokenProvider(\n deps: ManagedTokenProviderDeps,\n): RunnerTokenProvider {\n // The managed plane must carry no standing PAT \u2014 refuse to start otherwise.\n assertNoStandingPatsOnManagedPath(deps.env ?? process.env);\n return createCachingTokenProvider(\n \"managed\",\n async (role) => {\n const minted = await deps.minter.mint(role, deps.runContext);\n deps.onMint?.(role, minted);\n return minted;\n },\n deps.cache,\n );\n}\n\n/**\n * The scopes/actions each role requests from the token exchange. The exchange\n * still NARROWS to the run's authorization \u2229 the SVID's upper bound, so this is\n * an upper request, never a grant (see `@stacks/identity` `exchangeCapabilityToken`).\n */\nexport const ROLE_CAPABILITY_REQUEST: Record<\n RunnerRole,\n { scopes: string[]; actions: string[] }\n> = {\n // The admin principal: claim / heartbeat / fail / authorize the local commit.\n runner: {\n scopes: [\"read\", \"write\", \"admin\"],\n actions: [\"job:claim\", \"job:heartbeat\", \"job:fail\", \"repo:commit\"],\n },\n // The executor principal: submit plan/execution results (turn-guard).\n planner: { scopes: [\"read\", \"write\"], actions: [\"job:submit\"] },\n // The reviewer principal: submit reviews (turn-guard).\n reviewer: { scopes: [\"read\", \"write\"], actions: [\"job:submit\"] },\n};\n\nexport interface HttpCapabilityMinterConfig {\n /** Control-plane token-exchange endpoint (mTLS in production). */\n exchangeUrl: string;\n /** The worker's presented workload-identity SVID (short-lived, auto-rotated). */\n svid: string;\n /** Injectable for tests; defaults to the global `fetch`. */\n fetchImpl?: typeof fetch;\n}\n\n/**\n * Production capability minter: presents the worker's SVID to the control-plane\n * token-exchange endpoint and receives a run/workspace/role-scoped capability\n * token. Fails closed (throws) on any non-2xx or a response missing the token \u2014\n * it never falls back to a PAT.\n */\nexport function createHttpCapabilityMinter(\n cfg: HttpCapabilityMinterConfig,\n): CapabilityMinter {\n const doFetch = cfg.fetchImpl ?? fetch;\n return {\n async mint(role, ctx) {\n const spec = ROLE_CAPABILITY_REQUEST[role];\n const res = await doFetch(cfg.exchangeUrl, {\n method: \"POST\",\n headers: {\n \"content-type\": \"application/json\",\n // The SVID is the mTLS-channel-delivered identity, NOT a bearer PAT.\n authorization: `SVID ${cfg.svid}`,\n },\n body: JSON.stringify({\n role,\n runId: ctx.runId,\n workspaceId: ctx.workspaceId,\n scopes: spec.scopes,\n actions: spec.actions,\n }),\n // AGE-835: a stalled exchange must reject, never hang the caller.\n signal: AbortSignal.timeout(30_000),\n });\n if (!res.ok) {\n throw new Error(\n `token-exchange failed (${res.status}) minting the ${role} capability`,\n );\n }\n const body = (await res.json()) as {\n token?: string;\n expiresAt?: string;\n };\n if (!body.token || !body.expiresAt) {\n throw new Error(\n `token-exchange returned no capability token for the ${role} role`,\n );\n }\n return { token: body.token, expiresAt: body.expiresAt };\n },\n };\n}\n", "/**\n * AGE-899: which role minted a given bearer, including bearers that have since\n * been rotated out.\n *\n * The AGE-840 re-mint asks \"which role does this 401'ing token belong to?\" so it\n * can invalidate that role and mint a fresh one. Answering by identity against\n * the CURRENT role tokens is not enough, and that gap is what made the fix miss\n * in production: a long call \u2014 a heartbeat, an executor turn \u2014 captures its\n * bearer, `refreshRoleTokens` swaps the module-level tokens underneath it, and\n * the 401 that follows then resolves to no role at all. The re-mint declines and\n * the caller wedges for the rest of the token's TTL. Observed live on 2026-08-02:\n * the re-mint fired correctly at 02:29 and failed to fire at 05:28, costing a\n * stage attempt against the immutable retry cap.\n *\n * A superseded bearer only has to stay recognizable long enough for its\n * in-flight call to fail, so the history is capped rather than unbounded \u2014 it\n * can never grow with process uptime.\n */\nimport type { RunnerRole } from \"./runner-auth.js\";\n\n/** Several generations across three roles; far more than any in-flight call needs. */\nexport const TOKEN_ROLE_HISTORY_MAX = 12;\n\nconst history = new Map<string, RunnerRole>();\n\n/** Record a freshly minted token. Call BEFORE anything can rotate it again. */\nexport function rememberTokenRole(token: string, role: RunnerRole): void {\n if (!token) return;\n // Re-insert so the most recently minted tokens are the last to be pruned:\n // Map iterates in insertion order, so delete-then-set moves this key to the\n // end and the eviction below always takes the genuinely oldest entry.\n history.delete(token);\n history.set(token, role);\n while (history.size > TOKEN_ROLE_HISTORY_MAX) {\n const oldest = history.keys().next().value;\n if (oldest === undefined) break;\n history.delete(oldest);\n }\n}\n\n/** The role that minted this bearer, or null if it is not one of ours. */\nexport function roleForKnownToken(token: string): RunnerRole | null {\n if (!token) return null;\n return history.get(token) ?? null;\n}\n\n/** Test seam \u2014 the history is process-global by design. */\nexport function resetTokenRoleHistoryForTests(): void {\n history.clear();\n}\n", "/**\n * Harness-aware runner protocol (H10.6).\n *\n * The generic M7 `workflow-runner` reacts to `agent.handoff` and runs the\n * plan \u2192 review \u2192 execute \u2192 review loop. A Harness Automation STAGE rides the\n * SAME loop (`templateKey === \"stage_execution\"`), but its execution turn has\n * extra obligations that this module implements:\n *\n * 1. DETECT a harness stage job. The `agent.handoff` webhook carries only the\n * jobId \u2014 `get_agent_job(jobId)` returns a `harness` block (run/stage ids,\n * branch/repo/base + strategy/template, commit policy, acceptance criteria)\n * when, and only when, the job executes a HarnessStage.\n * 2. EXECUTION TURN (driveHarnessStage, on the EXECUTING handoff \u2014 it does NOT\n * commit; the local commit is only authorizable once the stage is validated):\n * execute in the mapped checkout (the run's repo \u2192 STACKS_RUNNER_REPOS), then\n * \u2022 `submit_harness_artifact` \u00D72 \u2014 capture the diff (DIFF_OR_PATCH) + test\n * evidence (TEST_EVIDENCE), the two gate-required kinds beyond the\n * EXECUTION_SUMMARY,\n * \u2022 `submit_harness_stage_result` \u2014 the structured evidence + the linked\n * artifacts (NO commit yet), what the validation gate reads, and\n * \u2022 `submit_execution_result` \u2014 the generic M7 submission that advances\n * EXECUTING \u2192 EXECUTION_REVIEW so the reviewer turn opens.\n * 3. COMMIT BOUNDARY (driveHarnessCommit, once the stage is VALIDATED/COMMIT_GATE\n * \u2014 opportunistically after submit when an ALLOW policy auto-approved, else on\n * a later invocation after a human approves the acceptance gate): AUTHORIZE the\n * local commit with `authorize_harness_local_commit` BEFORE running\n * `git commit` (a `repo:commit` permission check that honors freeze/leases/\n * policy \u2014 it mints NO credential and approves NO gate), then report the SHA\n * via `submit_harness_stage_result` (the local-commit evidence the boundary\n * needs to advance to COMMITTED).\n * 4. PUSH/PR only AFTER the commit boundary authorizes it: poll the stage until\n * it is COMMITTED (push/PR authorized), then broker a SINGLE-USE\n * `repo:push` / `repo:pr_create` credential (the injected\n * `brokerPushCredential` seam \u2014 a real deployment wires it to the M8 governed\n * broker) and perform the external git write. There is NO standing raw repo\n * token, and the broker fails closed (no push) while frozen or on a deny.\n * 5. FREEZE. `heartbeat_agent_job` returns `{ frozen: true }` when the run is\n * frozen \u2014 this module ABORTS the in-flight subprocess and performs no\n * further submit / commit-evidence / credential / push / PR until resume.\n * Freeze is honored by THIS external process, not only by Jentrix guards.\n *\n * Everything that touches the outside world (MCP, the agent runtime, git, the\n * clock) is INJECTED, so the smoke test (`harness-runner.smoke.test.ts`) drives a\n * fake repo with mocked provider turns and no real Claude/Codex/GitHub.\n *\n * Security invariants Codex validates (H10.6 focus):\n * \u2022 No agent self-approves a human gate \u2014 the runner only AUTHORIZES the local\n * commit (never the commit/merge gate) and waits for the gate to advance.\n * \u2022 No standing repo credential \u2014 push/PR creds are brokered single-use.\n * \u2022 Freeze is honored by the external process.\n * \u2022 The shell-capable checkout path is BOUNDED to configured repos \u2014 an\n * unmapped repo aborts before any agent/git/credential action.\n */\n\nimport { createHash } from \"node:crypto\";\n\nimport { claudeLegModel, claudeModel } from \"./providers/claude.js\";\nimport { codexModel } from \"./providers/codex.js\";\nimport {\n workerCapabilities,\n type WorkerCapabilitiesDecl,\n} from \"./providers/capabilities.js\";\nimport {\n resolveClaimExecution,\n type ExpectedRoleBinding,\n type ResolvedClaimExecution,\n} from \"./runtime-routing.js\";\nimport { buildProjectContext, measureBaseDrift } from \"./project-context.js\";\nimport { loadRubric } from \"./rubrics.js\";\nimport {\n missingReadOnlyCheckoutReason,\n repoAccessForRole,\n} from \"./role-repo-access.js\";\nimport { agentProvider } from \"./jentrix.js\";\nimport {\n resolveRevisionStamp,\n type RevisionStamp,\n} from \"../../packages/execution/src/revision.js\";\nimport type {\n StageWorktreeIdentity,\n WorktreeManager,\n} from \"./harness-worktree.js\";\n\nexport interface HarnessStageJobContext {\n harnessRunId: string;\n stageId: string;\n stageNumber: number;\n stageTitle: string;\n branch: string | null;\n branchTemplate: string | null;\n /** AGE-690: the run's anchor task key \u2014 what `{taskKey}` in `branchTemplate`\n * resolves to. Carried on THIS context (not a webhook payload) so the poll\n * leg resolves the same branch the webhook leg does. Optional: a server\n * predating AGE-690 omits it. */\n taskKey?: string | null;\n repo: string | null;\n baseBranch: string | null;\n branchStrategy: string;\n commitPolicy: string | null;\n acceptanceCriteria: string[];\n /** AGE-781: the decomposition-reviewed implementation approach \u2014 rendered\n * into the executor prompt (stages run with no per-stage plan turn).\n * Absent/null on legacy plans and servers predating the field. */\n approach?: string | null;\n /** HAI S3: commands the RUNNER executes itself (foreground, per-command\n * timeout, in the stage worktree) to mint attested TEST_EVIDENCE. Executor\n * prose never satisfies the evidence gate. Absent/empty on legacy plans. */\n verificationCommands?: string[];\n /** HAI S3: the AUTOMATED policy criteria the attested evidence covers \u2014\n * passed through as criterionRefs on the TEST_EVIDENCE capture. */\n automatedCriteria?: string[];\n /** Stage 2: the NAMED ref the stage's execution worktree branches FROM (own\n * branch tip on a retry, the run base on the first stage / after a predecessor\n * merged, else the preceding stage's branch tip). NEVER the checkout HEAD \u2014\n * createWorktree verifies it resolves to a commit before cutting the branch. */\n executionBaseRef: string;\n}\n\n/** The slice of `get_agent_job` this protocol reads. */\nexport interface AgentJobView {\n id: string;\n phase: string;\n turn: string;\n repoOwnerName: string | null;\n /** F6 (AGE-503): non-null while an attempt owns the turn \u2014 a claim on such a\n * job can only CONFLICT (\"it has an active run\"), so pollers skip it and let\n * the sweep expire a zombie run instead of storming identical claims. */\n activeRunId?: string | null;\n harness: HarnessStageJobContext | null;\n harnessRun: {\n id: string;\n repo: string | null;\n baseBranch: string | null;\n } | null;\n}\n\n/** A single MCP tool call with a specific token (admin or role). */\nexport type CallTool = (\n token: string,\n name: string,\n args: Record<string, unknown>,\n) => Promise<Record<string, unknown>>;\n\n/** Run one agent turn in a checkout and return its final summary text. */\nexport type RunAgentTurn = (args: {\n prompt: string;\n systemPrompt: string;\n repoCwd: string;\n /**\n * M18.3 R7: run the turn against `repoCwd` READ-ONLY \u2014 the providers already\n * enforce it (claude.ts withholds the write/edit tools; codex.ts runs the\n * shell under a read-only sandbox). Set from the dispatch role's entry in\n * `role-repo-access.ts`, never by hand.\n */\n repoReadOnly?: boolean;\n /** Aborted when the run is frozen \u2014 the runtime must stop the subprocess. */\n signal: AbortSignal;\n /** W3: this is a harness STAGE executor leg \u2014 the runner submits the result\n * and attests the evidence, so the runtime registers the executor hooks. */\n runnerOwnsSubmissions?: boolean;\n execution?: ResolvedClaimExecution;\n}) => Promise<string>;\n\n/** Run a git command in a checkout; returns trimmed stdout. `env` (when given) is\n * merged into the child's environment \u2014 used to hand a single-use push token to a\n * credential helper WITHOUT placing it in the command line (argv). */\nexport type RunGit = (\n cwd: string,\n args: string[],\n env?: Record<string, string>,\n) => Promise<string>;\n\n/** HAI S3: one runner-executed verification command's observed outcome. */\nexport interface VerificationRunResult {\n command: string;\n exitCode: number;\n timedOut: boolean;\n stdout: string;\n stderr: string;\n startedAt: string;\n finishedAt: string;\n}\n\n/** HAI S3: execute ONE declared verification command in the stage worktree,\n * FOREGROUND, with a hard timeout \u2014 the runner itself, never the agent turn.\n * The command text is gate-approved stage-plan content (the same trust level\n * as bootstrap argv), so the production wiring may run it through a shell.\n * MUST resolve (never reject) with the observed exit/timeout \u2014 a spawn\n * failure is reported as exitCode 127. */\nexport type RunVerificationCommand = (args: {\n cwd: string;\n command: string;\n timeoutMs: number;\n signal: AbortSignal;\n}) => Promise<VerificationRunResult>;\n\nexport interface HarnessRunnerTokens {\n /** read,write,admin \u2014 claim/heartbeat/fail/authorize/broker. */\n runner: string;\n /** read,write \u2014 the executor session principal (turn-guard). */\n planner: string;\n}\n\n/** The only tier a local runner attests (D1 deleted the stronger local lane). */\nexport const DEFAULT_RUNNER_EVIDENCE_TIER = \"INTEGRATION_LOCAL\";\n\n/**\n * D5 dedup: what a worker PRESENTS on `claim_agent_job` \u2014 the pinned model\n * (silent-model-change forensics, M12.3b's fail-closed revision guard, and the\n * M13.4b capability preflight). Shared by the generic M7 drive and the harness\n * stage claim, which used to duplicate this block.\n */\nexport function claimPresentation(\n provider: \"claude\" | \"codex\",\n opts: {\n revision?: RevisionStamp;\n capabilities?: unknown;\n /** The model THIS claim's leg will actually launch (per-leg Claude pins \u2014\n * see claudeLegModel); unset \u21D2 the provider's process-wide pin. */\n model?: string;\n } = {},\n): {\n provider: string;\n model: string;\n schemaRevision: string;\n appRevision: string;\n capabilities: unknown;\n} {\n const revision = opts.revision ?? resolveRevisionStamp();\n const model =\n opts.model ?? (provider === \"codex\" ? codexModel() : claudeModel());\n // M18 bring-up: the release registry + eval-plane egress allowlist key Claude\n // releases by the BILLING provider (\"anthropic\"), while the runner's leg union\n // stays \"claude\" | \"codex\". STACKS_CLAUDE_PROVIDER_LABEL relabels what claude\n // legs PRESENT so claims match an anthropic-pinned release; unset \u21D2 \"claude\".\n const presentedProvider =\n provider === \"claude\"\n ? (process.env.STACKS_CLAUDE_PROVIDER_LABEL?.trim() ?? provider)\n : provider;\n return {\n provider: presentedProvider,\n model,\n schemaRevision: revision.schemaRevision,\n appRevision: revision.appRevision,\n capabilities:\n opts.capabilities ??\n workerCapabilities({\n model,\n // Claude claims always vouch for BOTH per-leg pins: the agent release\n // may pin the planner leg's model while this claim launches the\n // executor leg's (or vice versa) \u2014 either must pass the M13.4b\n // capability preflight.\n extraAcceptedModels:\n provider === \"codex\"\n ? process.env.STACKS_CODEX_ACCEPTED_MODELS\n : [\n process.env.STACKS_CLAUDE_ACCEPTED_MODELS,\n claudeLegModel(\"planner\"),\n claudeLegModel(\"executor\"),\n ]\n .filter(Boolean)\n .join(\",\"),\n }),\n };\n}\n\nexport interface HarnessRunnerConfig {\n tokens: HarnessRunnerTokens;\n /** \"owner/name\" \u2192 local checkout path. The executor path is BOUNDED to this. */\n repos: Record<string, string>;\n /** Heartbeat cadence (ms). */\n heartbeatMs: number;\n /** Poll cadence while waiting for the commit boundary to authorize push (ms). */\n commitPollMs: number;\n /** Max polls before giving up on the commit boundary (then the human drives). */\n commitPollMax: number;\n /** HAI S3: per-command timeout for runner-executed verification commands\n * (default 15 min). A timed-out command is attested timedOut \u2014 the gate\n * blocks on it. */\n verificationTimeoutMs?: number;\n /** HAI S3: the evidence tier this runner attests at (default\n * INTEGRATION_LOCAL \u2014 a local runner). The SERVER caps the claim at the\n * token's maxEvidenceTier ceiling regardless of what is declared here. */\n evidenceTier?: string;\n /**\n * M12.3b (AGE-173): this runner's build-stamped deployment revision, PRESENTED on\n * every `claim_agent_job` so the control plane refuses a schema-incompatible claim\n * FAIL-CLOSED and can require strict schema+app attestation for validator dispatch \u2014\n * the harness execution runner must never execute against an incompatible schema.\n * Defaults to the\n * shared, env-resolved stamp (`resolveRevisionStamp()`) \u2014 the SAME single source of\n * truth the generic M7 runner and the worker/sandbox images stamp from; an\n * un-stamped dev runner presents `unknown` (the control plane's guard is inert).\n */\n revision?: RevisionStamp;\n /**\n * M13.4b (Quality & Release Plane): what this worker can actually run, PRESENTED\n * on every `claim_agent_job` so the control plane refuses a release pinning a\n * model the installed SDK cannot run BEFORE opening a run (zero claims burned).\n * Defaults to `workerCapabilities({ model: claudeLegModel(\"executor\") })` \u2014 the harness\n * executor is always the Claude runtime; it always vouches for the model it\n * launches (never omitted, so the model dimension actually fires in production).\n */\n capabilities?: WorkerCapabilitiesDecl;\n /** Setup-resolved executor binding. Omitted only by the deprecated env path. */\n executorBinding?: ExpectedRoleBinding;\n mintClaimCredential?: (\n binding: ExpectedRoleBinding,\n ) => Promise<string | undefined>;\n stopping?: () => boolean;\n log?: (msg: string) => void;\n}\n\n/**\n * M12.5 (AGE-175) \u2014 the SANDBOX-SIDE egress broker. When wired, the push and PR are\n * performed by a broker that OWNS the credential injection (git credential helper for\n * push, App-token `Authorization` header for PR), so this runner never holds the raw\n * token at all: it hands the broker a non-secret request and gets back only the\n * result. This is the production replacement for the token-returning\n * `brokerPushCredential` + `createPullRequest` seams \u2014 injection moves sandbox-side.\n *\n * Both methods fail CLOSED (return null) when the broker refuses (frozen / policy /\n * grant unresolved); the runner then defers to the governed path, exactly as the\n * no-op seams did. `openPr` returning null defers PR creation to inbound correlation.\n */\nexport interface SandboxEgressBroker {\n push(req: {\n harnessRunId: string;\n stageId: string;\n repo: string;\n branch: string;\n cwd: string;\n }): Promise<{ pushed: boolean } | null>;\n openPr(req: {\n harnessRunId: string;\n stageId: string;\n repo: string;\n branch: string;\n baseBranch: string | null;\n title: string;\n }): Promise<{ url: string; number: number } | null>;\n}\n\n/**\n * S1 documentation commit guard. The managed harness runs `docs:sync` before the\n * final review turn (so a public-contract change lands its generated doc entry in\n * the diff the reviewer sees) and `docs:check` immediately before authorizing the\n * local commit (a stale public contract BLOCKS via a server-recorded, checksum-bound\n * DOCUMENTATION_REVIEW finding). Injected so the smoke tests stub it and a real\n * deployment wires it to spawn `pnpm docs:sync` / `pnpm docs:check` in the worktree.\n */\nexport interface DocsGuard {\n /** Regenerate the checked-in generated docs in the worktree (`pnpm docs:sync`). */\n sync(cwd: string, changedFiles: string[]): Promise<void>;\n /** Run the public-contract docs check (`pnpm docs:check`) over the worktree change. */\n check(\n cwd: string,\n changedFiles: string[],\n ): Promise<{ ok: boolean; staleDocs: string[]; output: string }>;\n}\n\nexport interface HarnessRunnerDeps {\n callTool: CallTool;\n runAgentTurn: RunAgentTurn;\n git: RunGit;\n /**\n * HAI S3: execute a declared verification command (foreground, timed) so the\n * runner \u2014 never the executor \u2014 authors TEST_EVIDENCE. Optional for older\n * test harnesses: when absent and a stage declares commands, NO test\n * evidence is captured (the stage honestly fails its gate) and the\n * structured report lists the commands under testsNotRun.\n */\n runCommand?: RunVerificationCommand;\n /** Fail-fast managed verification preflight. Production wires this before the\n * claim so a missing daemon/image consumes zero model turns. */\n preflightVerification?: () => Promise<void>;\n /**\n * S1: the documentation commit guard. Absent \u21D2 the guard is skipped (the\n * reference/smoke path); the managed workflow-runner wires the real one, so the\n * managed harness always runs docs:sync before review and docs:check before commit.\n */\n docsGuard?: DocsGuard;\n /**\n * M12.5: the sandbox-side broker that OWNS credential injection \u2014 the ONLY\n * push/PR egress (D5, 2026-07: the raw-token seams were deleted). When\n * absent (the default), push/PR defer fail-closed: the stage stays COMMITTED\n * on Jentrix and the governed delivery path (or an operator) performs the\n * externally-visible write.\n */\n sandboxEgress?: SandboxEgressBroker;\n /**\n * Stage 3: the per-job WORKTREE the executor/commit turn works in. The executor's\n * workingDirectory is this worktree (never the shared checkout), so diff/test\n * evidence is captured from it alone, a same-job revision turn reuses it, and the\n * reviewer receives it read-only. Injected so the smoke tests drive a fake and the\n * production runner wires the real RunnerWorktreeManager.\n */\n worktree: WorktreeManager;\n /** Injectable for deterministic timing in tests. */\n sleep: (ms: number) => Promise<void>;\n}\n\n/**\n * W7: the executor's evidence contract is a VERSIONED rubric file\n * (`agents/rubrics/executor-evidence.md`), not an inline literal \u2014 one source,\n * diffable when the contract changes, and loaded fail-closed (a turn without its\n * contract is the silent degradation this program removes).\n */\nexport function harnessExecutorSystemPrompt(): string {\n return loadRubric(\"executor-evidence\");\n}\n\n/**\n * The harness-flow gate: the verification command EVERY executor job runs last,\n * on top of whatever the stage declares.\n *\n * The harness drives itself with the same repo it is changing, so a stage can\n * quietly break the machinery carrying it \u2014 and the symptom shows up rounds\n * later as a wedged stage nobody can attribute (M18 stage 6 burned five review\n * rounds on a cap counter that never reset). This gate runs the suites that\n * prove the flow still converges and never parks silently: sweep-only liveness,\n * decision-table totality, and the review-round/park accounting. Seconds, not\n * minutes \u2014 the full Playwright e2e provisions a database container per run and\n * cannot be a per-turn gate; it stays on the stage's own command list where a\n * stage needs it.\n */\nexport const HARNESS_FLOW_GATE_COMMAND = \"pnpm test:harness-flow\";\n\n/** Thrown when the run is frozen mid-turn \u2014 STOP all further work until resume. */\nexport class HarnessFrozenError extends Error {\n constructor(stageId: string) {\n super(\n `Harness run frozen \u2014 paused stage ${stageId} before any submit/commit/push.`,\n );\n this.name = \"HarnessFrozenError\";\n }\n}\n\n/** Thrown when the job's repo is not in STACKS_RUNNER_REPOS \u2014 the executor path\n * is bounded to configured checkouts, never a tools-only assumption. */\nexport class UnmappedRepoError extends Error {\n constructor(repo: string | null) {\n super(\n repo\n ? `No STACKS_RUNNER_REPOS entry for ${repo} \u2014 cannot execute a harness stage there.`\n : \"Harness stage has no repo configured on its run \u2014 cannot execute.\",\n );\n this.name = \"UnmappedRepoError\";\n }\n}\n\n/**\n * Detect whether an agent job is a harness stage execution job. Returns its\n * harness context (truthy) or null. The single source of truth is the `harness`\n * block on `get_agent_job` \u2014 never the handoff payload (which omits it).\n */\nexport async function getHarnessStageJob(\n deps: Pick<HarnessRunnerDeps, \"callTool\">,\n cfg: Pick<HarnessRunnerConfig, \"tokens\">,\n jobId: string,\n): Promise<AgentJobView> {\n const job = (await deps.callTool(cfg.tokens.runner, \"get_agent_job\", {\n jobId,\n })) as unknown as AgentJobView;\n return job;\n}\n\n/**\n * Parse the executor's trailing `ADDRESSED_FINDINGS:` line into the finding ids\n * it explicitly claims (the last such line wins \u2014 an executor may quote the\n * instruction earlier in its summary). Conservative by design: no line, or\n * \"none\", means NO claims \u2014 an unlisted row stays OPEN for the next round\n * rather than being falsely marked FIXED. (The blanket mark-everything-FIXED\n * this replaces claimed rows even on no-edit rounds, which taught the reviewer\n * to distrust the ledger and reject every round.)\n */\nexport function parseAddressedFindingIds(summary: string): string[] {\n const matches = [...summary.matchAll(/ADDRESSED_FINDINGS:\\s*([^\\n]*)/gi)];\n const line = matches.at(-1)?.[1]?.trim();\n if (!line || /^none\\b/i.test(line)) return [];\n return [\n ...new Set(\n line\n .split(/[,\\s]+/)\n // Strip wrapping punctuation an agent might add (`id`, \"id\", [id], id.)\n .map((s) => s.replace(/^[^A-Za-z0-9_-]+|[^A-Za-z0-9_-]+$/g, \"\"))\n .filter(Boolean),\n ),\n ];\n}\n\n/** Resolve the branch the stage should land on: the stage's pinned branch, else\n * the run branchTemplate with {taskKey}/{slug}/{number} filled.\n *\n * AGE-690: `{taskKey}` comes from `ctx` \u2014 the SAME `get_agent_job` read that\n * carries `branchTemplate` \u2014 and from nowhere else. It used to be a separate\n * parameter threaded from the `agent.handoff` webhook payload, which the POLL\n * leg never supplies; the absent key then became the literal \"task\", so every\n * poll-driven branch silently dropped the anchor key the M8 head-branch matcher\n * resolves the task by, and every PR off one would land ORPHAN. A run with no\n * anchor task has no key at all: it gets an obviously-synthetic, stage-scoped\n * token instead \u2014 unique (never colliding across runs the way \"task\" did) and\n * visibly not a task key, rather than a valid-looking name that fails silently. */\nexport function resolveStageBranch(ctx: HarnessStageJobContext): string {\n if (ctx.branch) return ctx.branch;\n const template = ctx.branchTemplate ?? \"harness/{taskKey}-stage-{number}\";\n return (\n template\n .replaceAll(\n \"{taskKey}\",\n (ctx.taskKey ?? `unanchored-${ctx.stageId}`).toLowerCase(),\n )\n .replaceAll(\"{slug}\", String(ctx.stageId))\n .replaceAll(\"{number}\", String(ctx.stageNumber))\n // A leftover placeholder would make an invalid ref \u2014 strip the braces.\n .replaceAll(/[{}]/g, \"\")\n );\n}\n\n/**\n * A FRESH freeze read, awaited at every external boundary. Both the heartbeat pump\n * (execution turn) and the one-shot probe (commit phase) implement it; the\n * boundaries `await source.check()` right before crossing, so a freeze that lands\n * between a prior poll and the boundary is caught (not a stale latched boolean).\n * `frozen` exposes the last known value for cheap inline guards.\n */\nexport interface FreezeSource {\n /** Last known frozen state (cheap inline guard). */\n readonly frozen: boolean;\n /** Re-read the run's frozen state NOW and return it. */\n check(): Promise<boolean>;\n}\n\n/**\n * A heartbeat pump that ALSO enforces freeze. It heartbeats on `cfg.heartbeatMs`;\n * the instant a heartbeat returns `{ frozen: true }` it ABORTS the controller (so\n * the running subprocess stops) and latches `frozen = true`. Boundaries call\n * `check()` for a FRESH read right before crossing \u2014 Jentrix cannot kill a local\n * process, so the runner is contractually the enforcer.\n */\nexport class HeartbeatPump implements FreezeSource {\n frozen = false;\n private timer: ReturnType<typeof setInterval> | null = null;\n private subprocessDone = false;\n readonly controller = new AbortController();\n\n constructor(\n private readonly deps: Pick<HarnessRunnerDeps, \"callTool\">,\n private readonly cfg: Pick<\n HarnessRunnerConfig,\n \"tokens\" | \"heartbeatMs\" | \"log\"\n >,\n private readonly jobId: string,\n private readonly runId: string,\n ) {}\n\n /** Perform one heartbeat now and react to a frozen response. Exposed so the\n * caller can also check freeze synchronously at a boundary (a \"freeze tick\"). */\n async beat(): Promise<void> {\n let res: Record<string, unknown>;\n try {\n res = await this.deps.callTool(\n this.cfg.tokens.runner,\n \"heartbeat_agent_job\",\n {\n jobId: this.jobId,\n runId: this.runId,\n },\n );\n } catch (e) {\n const msg = String(e);\n if (msg.includes(\"not the job's active run\")) {\n // Superseded turn (the job was failed + relaunched externally): stop the\n // pump and abort the subprocess \u2014 every submit from this turn would be\n // rejected by the server-side turn CAS anyway, so working on is waste.\n // EXCEPT once the subprocess has finished: submit_execution_result\n // completes this run, so the post-submit boundary beats ALWAYS conflict\n // on a successful turn \u2014 that is turn completion, not supersession, and\n // logging/aborting would misread every good turn as a failure.\n if (!this.subprocessDone) {\n this.cfg.log?.(`[heartbeat ${this.jobId}] ${msg}`);\n this.cfg.log?.(\n `[harness ${this.jobId}] turn superseded \u2014 aborting the stage subprocess`,\n );\n this.controller.abort();\n }\n this.stop();\n return;\n }\n // A heartbeat error (e.g. expired run) is logged; the run lifecycle is\n // handled by the caller's claim/fail. Do not crash the pump.\n this.cfg.log?.(`[heartbeat ${this.jobId}] ${msg}`);\n return;\n }\n if (res.frozen === true) {\n if (!this.frozen) {\n this.frozen = true;\n this.cfg.log?.(\n `[harness ${this.jobId}] FROZEN \u2014 aborting the stage subprocess`,\n );\n this.controller.abort();\n }\n }\n }\n\n /** A FRESH freeze read (one heartbeat) for a boundary check. */\n async check(): Promise<boolean> {\n await this.beat();\n return this.frozen;\n }\n\n /** The stage subprocess exited. From here on a heartbeat CONFLICT is the\n * normal end of a submitted turn (see beat()), never a supersession \u2014 there\n * is no subprocess left to abort, and the submits enforce their own turn CAS. */\n markSubprocessDone(): void {\n this.subprocessDone = true;\n }\n\n start(): void {\n if (this.timer) return;\n this.timer = setInterval(() => void this.beat(), this.cfg.heartbeatMs);\n // Don't keep the event loop alive for the heartbeat alone.\n (this.timer as { unref?: () => void }).unref?.();\n }\n\n stop(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n }\n}\n\n/** Capture the working-tree diff + a stat summary as evidence text. Best-effort:\n * a git failure yields an empty summary rather than aborting the report. */\ninterface CapturedChange {\n changedFiles: string[];\n diffLines: number;\n diffSummary: string;\n patch: string;\n /** AGE-901: did the patch read actually SUCCEED? An empty `patch` has two\n * causes that must not be conflated \u2014 a genuinely clean tree (a recordable\n * subject: the diff of \"no change\") and a failed capture (git error, no repo).\n * Only the latter may suppress attestation; treating both as \"no subject\"\n * makes a verification-only stage structurally unable to validate. */\n patchRead: boolean;\n}\n\n/** The shared diff-reading core (D5 dedup): name-only / stat / numstat / patch\n * over one git range. Best-effort per stream \u2014 a git failure yields the empty\n * value for that stream, never a throw. */\nasync function readDiff(\n deps: Pick<HarnessRunnerDeps, \"git\">,\n cwd: string,\n range: string[],\n): Promise<CapturedChange> {\n const capture: CapturedChange = {\n changedFiles: [],\n diffLines: 0,\n diffSummary: \"\",\n patch: \"\",\n patchRead: false,\n };\n try {\n const names = await deps.git(cwd, [\"diff\", \"--name-only\", ...range]);\n capture.changedFiles = names\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter(Boolean);\n } catch {\n /* no diff available */\n }\n try {\n capture.diffSummary = await deps.git(cwd, [\"diff\", \"--stat\", ...range]);\n } catch {\n /* no stat available */\n }\n try {\n // ACTUAL changed-line count = \u03A3(added + deleted) across files, from numstat\n // (NOT the count of --stat lines, which is ~file count) \u2014 so the\n // high_risk_change diff-size policy keys off the real change magnitude.\n const numstat = await deps.git(cwd, [\"diff\", \"--numstat\", ...range]);\n capture.diffLines = numstat\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean)\n .reduce((sum, line) => {\n const [added, deleted] = line.split(/\\s+/);\n // Binary files report \"-\" for both; count those as 0 lines.\n const a = Number(added);\n const d = Number(deleted);\n return (\n sum + (Number.isFinite(a) ? a : 0) + (Number.isFinite(d) ? d : 0)\n );\n }, 0);\n } catch {\n /* no numstat available */\n }\n try {\n capture.patch = await deps.git(cwd, [\"diff\", ...range]);\n capture.patchRead = true;\n } catch {\n /* no patch available \u2014 leaves patchRead false, the honestly-absent case */\n }\n return capture;\n}\n\nexport async function captureDiffEvidence(\n deps: Pick<HarnessRunnerDeps, \"git\">,\n cwd: string,\n): Promise<CapturedChange> {\n let intentToAdd: string[] = [];\n // Plain `git diff HEAD` omits untracked files. Temporarily add only an\n // intent-to-add index entry so Git can render their complete patch and bind\n // test evidence to the real subject. The content is never staged, and the\n // index entries are removed before returning.\n try {\n const untracked = await deps.git(cwd, [\n \"ls-files\",\n \"--others\",\n \"--exclude-standard\",\n \"-z\",\n ]);\n intentToAdd = untracked.split(\"\\0\").filter(Boolean);\n if (intentToAdd.length) {\n await deps.git(cwd, [\"add\", \"--intent-to-add\", \"--\", ...intentToAdd]);\n }\n } catch {\n intentToAdd = [];\n }\n const capture = await readDiff(deps, cwd, [\"HEAD\"]);\n if (intentToAdd.length) {\n try {\n await deps.git(cwd, [\"reset\", \"--quiet\", \"--\", ...intentToAdd]);\n } catch {\n /* evidence remains valid; commit-time git add still owns final staging */\n }\n }\n return capture;\n}\n\n/** W2: what a verification command's own output says actually ran. Mirrored (never\n * imported) across the agents/ dependency firewall \u2014 the server's\n * RunnerAttestationSchema is the other half of this contract. */\nexport interface AttestedTestCounts {\n testsRun: number;\n testsPassed: number;\n testsSkipped: number;\n suites: number;\n}\n\n/** Strip ANSI SGR sequences so a colorized runner (FORCE_COLOR, a TTY) parses the\n * same as a piped one. */\nconst stripAnsi = (s: string): string =>\n // eslint-disable-next-line no-control-regex\n s.replace(new RegExp(`${String.fromCharCode(27)}\\\\[[0-9;]*m`, \"g\"), \"\");\n\n/**\n * W2: parse test counts out of a verification command's captured output.\n *\n * Exit code 0 is not proof that anything RAN \u2014 a suite whose cases were all\n * skipped exits 0 and used to attest as clean evidence (observed: a live-DB\n * file, 14/14 skipped, recorded as the stage's test evidence). The counts\n * existed only in the executor's prose, which the gate rightly ignores.\n *\n * Detection is OUTPUT-driven, not command-driven: the declared commands are\n * gate-approved script names (`pnpm test:harness-flow`) that never say \"vitest\",\n * so recognizing vitest's own summary is both simpler and more general than\n * pattern-matching the command text. Anything unrecognized returns null \u2014 the\n * attestation then says `counts: null` explicitly rather than fabricating zeros.\n *\n * Vitest's summary, whose shape this pins:\n * Test Files 4 passed (4)\n * Tests 1 passed | 2 skipped | 1 todo (4)\n * and, when nothing matched the filter, `No test files found`.\n */\nexport function parseTestCounts(output: string): AttestedTestCounts | null {\n const text = stripAnsi(output);\n // The LAST summary wins (a script may run several suites in sequence).\n const testsLine = [...text.matchAll(/^\\s*Tests\\s{2,}(.+)$/gm)].at(-1)?.[1];\n const filesLine = [...text.matchAll(/^\\s*Test Files\\s{2,}(.+)$/gm)].at(\n -1,\n )?.[1];\n if (!testsLine) {\n // A filter that matched no file is REAL vacuity, not an unparseable command.\n return /^\\s*No test files found/m.test(text)\n ? { testsRun: 0, testsPassed: 0, testsSkipped: 0, suites: 0 }\n : null;\n }\n const total = /\\((\\d+)\\)\\s*$/.exec(testsLine);\n if (!total) return null;\n const count = (line: string, label: string): number => {\n const m = new RegExp(`(\\\\d+)\\\\s+${label}`).exec(line);\n return m ? Number(m[1]) : 0;\n };\n return {\n testsRun: Number(total[1]),\n testsPassed: count(testsLine, \"passed\"),\n // `todo` cases never executed either \u2014 counting them as skipped keeps\n // \"nothing actually ran\" honest.\n testsSkipped: count(testsLine, \"skipped\") + count(testsLine, \"todo\"),\n suites: filesLine ? Number(/\\((\\d+)\\)\\s*$/.exec(filesLine)?.[1] ?? 0) : 0,\n };\n}\n\n/** Bound one captured stream for artifact storage (redaction is server-side on\n * ingest; this only caps the size \u2014 keep the TAIL, where failures print). */\nfunction boundOutput(s: string, max = 60_000): string {\n return s.length <= max\n ? s\n : `\u2026[${s.length - max} chars truncated]\\n${s.slice(-max)}`;\n}\n\nconst sha256 = (s: string): string =>\n createHash(\"sha256\").update(s).digest(\"hex\");\n\n/**\n * Capture the stage's DIFF_OR_PATCH + TEST_EVIDENCE artifacts (the two evidence\n * kinds, beyond the EXECUTION_SUMMARY `submit_harness_stage_result` writes itself)\n * and return their artifactIds so the stage result can LINK them.\n *\n * HAI S3: TEST_EVIDENCE is no longer the executor's prose \u2014 each entry is a\n * RUNNER-executed verification command's captured output, submitted with a\n * runner attestation via the RUNNER token (the token that claimed the attempt;\n * the server verifies that identity and the tier ceiling). The DIFF is captured\n * FIRST via the role token; its returned checksum is the attestation's\n * subjectDigest, binding every piece of test evidence to the exact reviewed\n * diff. `submit_harness_artifact` redacts on ingest and returns null when R2 is\n * unconfigured \u2014 evidence is then simply not linked (the stage stays\n * un-validatable \u2014 honest, not silently validated).\n */\nexport async function captureStageEvidence(\n deps: Pick<HarnessRunnerDeps, \"callTool\">,\n cfg: Pick<HarnessRunnerConfig, \"tokens\" | \"evidenceTier\">,\n ctx: HarnessStageJobContext,\n args: {\n patch: string;\n /** AGE-901: whether the diff READ succeeded (see `CapturedChange.patchRead`).\n * An empty `patch` with `patchRead: true` is a clean tree \u2014 a real subject\n * that must still be recorded, so a verification-only stage can attest its\n * declared commands. Defaults false, which preserves the old fail-closed\n * behavior for any caller that cannot say. */\n patchRead?: boolean;\n verification: VerificationRunResult[];\n /** Identity of the claimed attempt every capture binds to. REQUIRED, not\n * optional: the sole call site runs strictly after `claim_agent_job`\n * returns a runId, so an unattested capture is unreachable \u2014 and making it\n * unrepresentable is the honest shape. The server enforces the same thing\n * from its side (an attested capture whose jobId/runId is not the stage's\n * live attempt is refused, harness-specs/05 \u00A72.4), and AGE-689's dedup keys\n * are DERIVED from this identity, so a nullable attempt would silently take\n * the diff capture back to \"no key \u21D2 no dedup\". */\n attest: {\n jobId: string;\n runId: string;\n baseHead: string;\n cwd: string;\n };\n /** W5: how far this attempt's checkout trails the run's base branch,\n * measured at claim time. Stacking on an unmerged predecessor is correct \u2014\n * this makes the resulting drift a recorded fact instead of a silent one. */\n drift?: { behindBase: number; baseSha: string } | null;\n },\n): Promise<\n Array<{ artifactId: string; kind: \"DIFF_OR_PATCH\" | \"TEST_EVIDENCE\" }>\n> {\n const linked: Array<{\n artifactId: string;\n kind: \"DIFF_OR_PATCH\" | \"TEST_EVIDENCE\";\n }> = [];\n // 1. The diff (role token \u2014 the executor's work product). Its checksum is\n // the subject digest every attestation binds to.\n let subjectDigest: string | null = null;\n // AGE-901: a CLEAN TREE is a subject, not a missing one. A verification-only\n // stage (an exit floor) correctly changes nothing, and gating the artifact on\n // a non-empty patch made every such stage structurally unable to validate \u2014\n // no DIFF_OR_PATCH meant no subjectDigest, which meant not one of its declared\n // commands could attest. Recording \"no change\" explicitly keeps the subject\n // real while leaving the genuinely-unrecorded case (`patchRead` false: git\n // failed, no repo) suppressed exactly as before.\n const noChange = !args.patch.trim() && args.patchRead === true;\n if (args.patch.trim() || noChange) {\n const res = (await deps.callTool(\n cfg.tokens.planner,\n \"submit_harness_artifact\",\n {\n harnessRunId: ctx.harnessRunId,\n harnessStageId: ctx.stageId,\n kind: \"DIFF_OR_PATCH\",\n title: `Stage ${ctx.stageNumber} diff${noChange ? \" (no change)\" : \"\"}`,\n body: noChange\n ? `# No change\\n\\nThe working tree is clean at this attempt's HEAD: the stage's declared work product is zero source changes (a verification-only stage). The diff was read successfully and is empty \u2014 this is the recorded subject, not an absent one.\\n`\n : args.patch,\n // AGE-689: callTool retries transient transport faults, and a retry of\n // a submit that ACTUALLY LANDED creates a second link when no key is\n // given (\"No key \u21D2 no dedup\" \u2014 harness-specs/05 \u00A72). Keyed on attempt\n // identity + kind, so a replay returns the stored response instead.\n idempotencyKey: `${args.attest.jobId}:${args.attest.runId}:DIFF_OR_PATCH`,\n },\n )) as {\n artifact?: { artifactId?: string; checksum?: string } | null;\n };\n if (res.artifact?.artifactId) {\n linked.push({\n artifactId: res.artifact.artifactId,\n kind: \"DIFF_OR_PATCH\",\n });\n subjectDigest = res.artifact.checksum ?? null;\n }\n }\n // 2. One attested TEST_EVIDENCE capture per runner-executed command (RUNNER\n // token \u2014 the claiming identity; the server rejects any other issuer).\n // `subjectDigest` alone gates this: no diff artifact (an UNREAD diff, or R2\n // unconfigured so the capture returned null) means there is nothing to bind\n // an attestation TO, so the evidence is honestly absent and the stage stays\n // un-validatable \u2014 never attested against an unrecorded subject. AGE-901: a\n // read-and-empty diff is recorded above, so it reaches here with a digest.\n if (subjectDigest) {\n for (const v of args.verification) {\n const body =\n `# Verification command (runner-executed)\\n\\n` +\n `$ ${v.command}\\n` +\n `exit ${v.exitCode}${v.timedOut ? \" (TIMED OUT)\" : \"\"} \u2014 started ${v.startedAt}, finished ${v.finishedAt}\\n\\n` +\n `## stdout\\n\\n${boundOutput(v.stdout) || \"(empty)\"}\\n\\n` +\n `## stderr\\n\\n${boundOutput(v.stderr) || \"(empty)\"}\\n`;\n const res = (await deps.callTool(\n cfg.tokens.runner,\n \"submit_harness_artifact\",\n {\n harnessRunId: ctx.harnessRunId,\n harnessStageId: ctx.stageId,\n kind: \"TEST_EVIDENCE\",\n title: `Stage ${ctx.stageNumber} verification: ${v.command.slice(0, 120)}`,\n body,\n criterionRefs: ctx.automatedCriteria ?? [],\n // AGE-689: one evidence link per command per attempt, even when\n // callTool retries a submit that already landed. The command is what\n // makes it unique within an attempt \u2014 the gate matches evidence to\n // each DECLARED command, so that is the right granularity. Hashed\n // (AGE-835): the raw command blew the server's 200-char key limit on\n // long multi-file vitest lines, failing the whole evidence leg.\n idempotencyKey: `${args.attest.jobId}:${args.attest.runId}:TEST_EVIDENCE:${createHash(\"sha256\").update(v.command).digest(\"hex\").slice(0, 32)}`,\n attestation: {\n version: 1,\n issuer: \"runner\",\n jobId: args.attest.jobId,\n runId: args.attest.runId,\n repo: ctx.repo ?? \"(unmapped)\",\n branch: ctx.branch ?? \"(unresolved)\",\n baseHead: args.attest.baseHead,\n subjectDigest,\n command: v.command,\n cwd: args.attest.cwd,\n startedAt: v.startedAt,\n finishedAt: v.finishedAt,\n exitCode: v.exitCode,\n timedOut: v.timedOut,\n stdoutHash: sha256(v.stdout),\n stderrHash: sha256(v.stderr),\n evidenceTier: cfg.evidenceTier ?? DEFAULT_RUNNER_EVIDENCE_TIER,\n // W2: `version` stays 1 (an older control plane must still parse\n // this); the payload revision + counts ride their own keys. Counts\n // come from the SAME bytes stdoutHash covers, so they are bound to\n // attested output rather than to a side file nothing verifies.\n attestationVersion: 2,\n counts: parseTestCounts(`${v.stdout}\\n${v.stderr}`),\n // W5: the attempt's drift from the run's base branch. Recorded on\n // the attestation because it is the only durable, attempt-bound\n // payload the runner authors \u2014 a stage that trails its base by 5\n // commits was reviewed against a tree the deployed server has\n // already moved past, and that used to be invisible.\n ...(args.drift\n ? {\n behindBase: args.drift.behindBase,\n ...(args.drift.baseSha\n ? { baseSha: args.drift.baseSha }\n : {}),\n }\n : {}),\n },\n },\n )) as { artifact?: { artifactId?: string } | null };\n if (res.artifact?.artifactId) {\n linked.push({\n artifactId: res.artifact.artifactId,\n kind: \"TEST_EVIDENCE\",\n });\n }\n }\n }\n return linked;\n}\n\n/**\n * The local commit leg (boundary 1): AUTHORIZE \u2192 `git commit` \u2192 return the SHA.\n * `authorize_harness_local_commit` is a permission check ONLY; it mints no\n * credential. A non-ALLOW decision throws (CONFLICT/FORBIDDEN) and we do NOT\n * commit. The authorization carries the RESOLVED branch + the pre-commit change\n * (paths + line count) so branch-scoped leases and the high_risk_change / diff-size\n * policy evaluate the ACTUAL target BEFORE the local commit (not an empty payload).\n * Freeze is re-checked right before the commit.\n */\nexport async function authorizeAndCommit(\n deps: Pick<HarnessRunnerDeps, \"callTool\" | \"git\" | \"docsGuard\">,\n cfg: Pick<HarnessRunnerConfig, \"tokens\">,\n freeze: FreezeSource,\n ctx: HarnessStageJobContext,\n args: { cwd: string; branch: string; message: string },\n): Promise<{ sha: string | null; changedFiles: string[]; diffLines: number }> {\n if (await freeze.check()) throw new HarnessFrozenError(ctx.stageId);\n // Capture the PENDING change BEFORE committing so the authorization checks the\n // real branch/paths/size (the commit boundary's policy keys off these) AND so the\n // caller can report the committed files (a post-commit diff is empty).\n const pending = await captureDiffEvidence(deps, args.cwd);\n // S1 documentation commit guard: run `docs:check` over the pending change\n // IMMEDIATELY before authorizing. The outcome (+ a stable checksum of the change)\n // is handed to the server, which records a checksum-bound DOCUMENTATION_REVIEW\n // finding and BLOCKS this authorization when a public contract is missing its\n // generated doc entry. The guard only CHECKS here \u2014 it never re-syncs-and-stages\n // behind the reviewer (docs:sync ran before the review turn, in the diff they saw).\n let docsArgs: Record<string, unknown> = {};\n if (deps.docsGuard) {\n const result = await deps.docsGuard.check(args.cwd, pending.changedFiles);\n docsArgs = {\n docsCheckOk: result.ok,\n docsChecksum: createHash(\"sha256\").update(pending.patch).digest(\"hex\"),\n docsStaleSummary: result.staleDocs.length\n ? result.staleDocs.join(\", \")\n : result.ok\n ? undefined\n : result.output.slice(0, 1000) || undefined,\n };\n }\n // Authorization-only: throws if the stage is not VALIDATED/COMMIT_GATE, the run\n // is frozen, a lease blocks, repo:commit policy is not ALLOW, OR the docs guard\n // blocks (stale public contract). Passes the resolved branch + change so the\n // policy/lease check sees the actual target.\n await deps.callTool(cfg.tokens.runner, \"authorize_harness_local_commit\", {\n harnessStageId: ctx.stageId,\n branch: args.branch,\n changedPaths: pending.changedFiles,\n diffLines: pending.diffLines,\n ...docsArgs,\n });\n // FRESH freeze read right before touching git \u2014 a freeze that landed during\n // authorization must stop the commit (the local commit IS a boundary).\n if (await freeze.check()) throw new HarnessFrozenError(ctx.stageId);\n // Stage the work onto the stage branch and commit locally.\n await deps.git(args.cwd, [\"checkout\", \"-B\", args.branch]);\n await deps.git(args.cwd, [\"add\", \"-A\"]);\n if (await freeze.check()) throw new HarnessFrozenError(ctx.stageId);\n // IDEMPOTENT on resume: if a prior attempt already committed (then got frozen\n // before reporting), there is nothing staged now \u2014 DON'T create an empty commit;\n // re-use the existing HEAD so the resume re-reports the SAME commit. The change\n // we report is then taken from HEAD~1..HEAD (the already-committed change).\n const staged = (await deps.git(args.cwd, [\"diff\", \"--cached\", \"--name-only\"]))\n .split(\"\\n\")\n .map((s) => s.trim())\n .filter(Boolean);\n if (staged.length > 0) {\n await deps.git(args.cwd, [\"commit\", \"-m\", args.message]);\n }\n const sha = (await deps.git(args.cwd, [\"rev-parse\", \"HEAD\"])).trim();\n // When we just committed, the pending capture above is the committed change; on a\n // resume (nothing staged) report the last commit's change instead.\n const reported =\n staged.length > 0 ? pending : await captureCommittedChange(deps, args.cwd);\n return {\n sha: sha || null,\n changedFiles: reported.changedFiles,\n diffLines: reported.diffLines,\n };\n}\n\n/** The change in an already-committed range (`baseRef..HEAD`; default the last\n * commit) \u2014 used when the work was committed BEFORE evidence capture: a resume\n * whose prior attempt committed then froze (authorizeAndCommit), or an executor\n * turn that committed locally so the post-turn working tree is clean (AGE-306).\n * Same shape as `captureDiffEvidence`. Best-effort: a git failure yields an\n * empty change. */\nasync function captureCommittedChange(\n deps: Pick<HarnessRunnerDeps, \"git\">,\n cwd: string,\n baseRef = \"HEAD~1\",\n): Promise<CapturedChange> {\n return readDiff(deps, cwd, [baseRef, \"HEAD\"]);\n}\n\n/**\n * The push/PR egress leg (boundaries 2+3) \u2014 performed ONLY after the commit\n * boundary authorizes it. Polls the stage until it is COMMITTED (Jentrix records\n * `pushPrAuthorized` on that transition), then requests SINGLE-USE brokered\n * `repo:push` / `repo:pr_create` credentials and performs the external git write.\n * No standing token: each credential is minted per call and expires. Returns\n * whether the push happened (false = still gated/awaiting a human \u2192 the human\n * drives the gate; the runner does not loop forever).\n */\nexport async function pushAfterAuthorized(\n deps: Pick<HarnessRunnerDeps, \"git\" | \"sleep\" | \"sandboxEgress\">,\n cfg: Pick<HarnessRunnerConfig, \"commitPollMs\" | \"commitPollMax\" | \"log\">,\n freeze: FreezeSource,\n ctx: HarnessStageJobContext,\n args: { cwd: string; branch: string; commitSha: string; repo: string },\n waitForAuthorized: () => Promise<\"authorized\" | \"gated\" | \"blocked\">,\n): Promise<{ pushed: boolean; reason?: string }> {\n // Wait for the commit boundary to authorize push/PR (the stage reaches\n // COMMITTED, recording pushPrAuthorized). A pending COMMIT gate means a human\n // must approve first, and a BLOCKED stage means a human must resolve it \u2014 in\n // both cases we stop rather than spin (the runner never forces a gate).\n const state = await waitForAuthorized();\n if (await freeze.check()) return { pushed: false, reason: \"frozen\" };\n if (state === \"blocked\") {\n return { pushed: false, reason: \"stage blocked \u2014 a human must resolve it\" };\n }\n if (state === \"gated\") {\n return {\n pushed: false,\n reason: \"commit gate pending \u2014 awaiting a human approval before push/PR\",\n };\n }\n\n // M12.5: push + PR go THROUGH the sandbox-side broker, which owns credential\n // injection \u2014 this runner never holds the raw token. D5 (2026-07): the old\n // raw-token leg (brokerPushCredential + createPullRequest seams, always\n // null-wired in production) was DELETED \u2014 without a broker the push defers\n // fail-closed and the governed delivery path (or an operator) performs the\n // externally-visible write.\n if (deps.sandboxEgress) {\n return pushViaSandboxBroker(deps, cfg, freeze, ctx, args);\n }\n return {\n pushed: false,\n reason:\n \"no push egress configured \u2014 the stage stays COMMITTED; the governed delivery path (or an operator) pushes\",\n };\n}\n\n/**\n * M12.5 egress leg via the SANDBOX-SIDE broker (broker-owns-injection path). The\n * runner hands the broker non-secret requests and gets back only results; the raw\n * push/PR credential is confined to the broker's injection helper and destroyed\n * there \u2014 it never enters this process's git argv/env or the returned values.\n * Freeze is re-checked before each broker call; a broker refusal (null) fails closed\n * exactly like the legacy path (defer to the governed path, never push un-brokered).\n */\nasync function pushViaSandboxBroker(\n deps: Pick<HarnessRunnerDeps, \"sandboxEgress\">,\n cfg: Pick<HarnessRunnerConfig, \"log\">,\n freeze: FreezeSource,\n ctx: HarnessStageJobContext,\n args: { cwd: string; branch: string; commitSha: string; repo: string },\n): Promise<{ pushed: boolean; reason?: string }> {\n const log = cfg.log ?? (() => {});\n const broker = deps.sandboxEgress!;\n if (await freeze.check())\n return { pushed: false, reason: \"frozen before push\" };\n const pushed = await broker.push({\n harnessRunId: ctx.harnessRunId,\n stageId: ctx.stageId,\n repo: args.repo,\n branch: args.branch,\n cwd: args.cwd,\n });\n if (!pushed?.pushed) {\n return {\n pushed: false,\n reason: \"sandbox broker push failed closed (frozen/policy)\",\n };\n }\n log(\n `[harness ${ctx.stageId}] pushed ${args.branch} via sandbox broker (${args.commitSha.slice(0, 8)})`,\n );\n // PR uses a SEPARATE brokered credential \u2014 re-check freeze before opening it.\n if (await freeze.check()) {\n return { pushed: true, reason: \"frozen after push, before PR\" };\n }\n const pr = await broker.openPr({\n harnessRunId: ctx.harnessRunId,\n stageId: ctx.stageId,\n repo: args.repo,\n branch: args.branch,\n baseBranch: ctx.baseBranch,\n title: `Harness stage ${ctx.stageNumber}: ${ctx.stageTitle}`,\n });\n log(\n pr\n ? `[harness ${ctx.stageId}] opened PR ${pr.url} via sandbox broker`\n : `[harness ${ctx.stageId}] PR deferred to governed path + inbound correlation`,\n );\n return { pushed: true };\n}\n\n/**\n * AGE-298 (H6b): per-process deadman dedupe \u2014 SPLIT (review P2): the ERROR\n * marker and the anchor-task comment are tracked separately, and a stage only\n * enters the commented set AFTER create_comment succeeds. A transient comment\n * failure (or a temporarily missing taskId) therefore RETRIES on the next\n * budget exhaustion instead of being permanently consumed. A runner restart\n * legitimately re-escalates both.\n */\nconst deadmanMarkedStages = new Set<string>();\nconst deadmanCommentedStages = new Set<string>();\n\n/**\n * Review r3 (P2) \u2014 MIRROR of `src/server/harness/gate-visibility.ts` (the\n * agents package cannot import the app tree; keep the two in sync): a PENDING\n * approval is a VISIBLE human park only when a human can actually act on it \u2014\n * a COMMIT gate by kind (it rides a DONE job), or any other kind only while\n * its job is genuinely parked in a gate phase. A stale PENDING\n * FINAL_ACCEPTANCE row on a DONE job is the exact AGE-293 impossible-state\n * regression: the Control Tower escalates it, so the deadman must too \u2014\n * treating it as \"visibly parked\" would suppress the one alert that exists.\n */\nconst HARNESS_GATE_PHASES = [\n \"PLAN_APPROVAL_GATE\",\n \"FINAL_ACCEPTANCE_GATE\",\n \"MERGE_GATE\",\n \"DEPLOY_GATE\",\n];\n\nfunction isActionablePendingGate(\n kind: string | undefined,\n jobPhase: string | undefined,\n): boolean {\n if (kind === \"COMMIT\") return true;\n return HARNESS_GATE_PHASES.includes(jobPhase ?? \"\");\n}\n\n/** Test seam: forget prior escalations (each smoke case is its own world). */\nexport function resetCommitDeadmanForTests(): void {\n deadmanMarkedStages.clear();\n deadmanCommentedStages.clear();\n}\n\n/**\n * AGE-298 (H6b): the commit poller's deadman. `waitForCommitAuthorized` used\n * to exhaust its budget and report the catch-all \"gated\" forever \u2014 during\n * AGE-291 the runner spun on \"not committable (stage EXECUTING)\" for 18 hours\n * while nothing was actually gated. On budget exhaustion this probes DURABLE\n * state: if the pairing is impossible \u2014 the job is DONE, the stage never\n * reached COMMITTED/SKIPPED/BLOCKED, and no ACTIONABLE approval is pending\n * (per the mirrored gate-visibility predicate above) \u2014 it emits a\n * distinct ERROR-level marker line (monitor-alertable) and, holding a\n * write-scoped PAT, posts a comment on the run's anchor task so a human sees\n * the stuck stage where they already look. Once per stage per process;\n * best-effort by contract (a probe/comment failure never breaks the poller).\n */\nasync function commitDeadmanProbe(\n deps: Pick<HarnessRunnerDeps, \"callTool\">,\n cfg: Pick<HarnessRunnerConfig, \"tokens\" | \"log\">,\n ctx: HarnessStageJobContext,\n jobId: string,\n stageStatusNow: string | null,\n): Promise<void> {\n const log = cfg.log ?? (() => {});\n if (\n deadmanMarkedStages.has(ctx.stageId) &&\n deadmanCommentedStages.has(ctx.stageId)\n ) {\n return; // fully escalated this process \u2014 nothing left to do\n }\n try {\n if (\n !stageStatusNow ||\n [\"COMMITTED\", \"SKIPPED\", \"BLOCKED\"].includes(stageStatusNow)\n ) {\n return; // terminal or human-parked \u2014 the plain \"gated\"/\"blocked\" story\n }\n const job = (await deps.callTool(cfg.tokens.runner, \"get_agent_job\", {\n jobId,\n })) as {\n phase?: string;\n taskId?: string;\n approvals?: Array<{ status?: string; kind?: string }>;\n };\n // Only an ACTIONABLE pending gate counts as visibly parked (the shared\n // gate-visibility predicate) \u2014 a stale FINAL_ACCEPTANCE approval left\n // PENDING on a DONE job suppresses nothing.\n const pendingGate = (job.approvals ?? []).some(\n (a) =>\n a.status === \"PENDING\" && isActionablePendingGate(a.kind, job.phase),\n );\n if (job.phase !== \"DONE\" || pendingGate) return; // visibly parked \u2014 fine\n if (!deadmanMarkedStages.has(ctx.stageId)) {\n deadmanMarkedStages.add(ctx.stageId);\n // The distinct, greppable, monitor-alertable marker (ERROR level).\n log(\n `[harness-deadman] ERROR: impossible state \u2014 stage ${ctx.stageId} ` +\n `(run ${ctx.harnessRunId}, stage ${ctx.stageNumber}) is ${stageStatusNow} ` +\n `while job ${jobId} is DONE with no actionable pending gate; the commit ` +\n `poller budget is exhausted and nothing external will fire (AGE-291 class). ` +\n `The server sweep should converge it \u2014 escalating on the anchor task.`,\n );\n }\n // The comment dedupes SEPARATELY and only after SUCCESS (review P2): a\n // transient failure or missing taskId retries on the next exhaustion.\n if (!deadmanCommentedStages.has(ctx.stageId) && job.taskId) {\n await deps.callTool(cfg.tokens.planner, \"create_comment\", {\n taskId: job.taskId,\n body:\n `\uD83D\uDEA8 Harness commit-poller deadman: stage ${ctx.stageNumber} ` +\n `(\\`${ctx.stageId}\\`, run \\`${ctx.harnessRunId}\\`) is stuck ` +\n `${stageStatusNow} while its execution job \\`${jobId}\\` is DONE ` +\n `with no actionable pending gate \u2014 the AGE-291 impossible-state ` +\n `class. The runner's poll budget is exhausted; the cron sweep should ` +\n `converge it (STUCK_HARNESSES has the item), else retry the stage.`,\n });\n deadmanCommentedStages.add(ctx.stageId);\n }\n } catch (e) {\n // Best-effort: never break the poller over its own escalation.\n log(`[harness-deadman] escalation failed for stage ${ctx.stageId}: ${e}`);\n }\n}\n\n/**\n * Poll `list_harness_stages` until the stage is COMMITTED (push/PR authorized),\n * BLOCKED/SKIPPED (human must resolve), or the poll budget is exhausted (treated\n * as still-gated \u2014 a human drives the gate; the AGE-298 deadman first probes for\n * the impossible pairing and escalates it once per stage per process). Separated\n * from the push so the smoke test can drive the wait deterministically.\n */\nexport async function waitForCommitAuthorized(\n deps: Pick<HarnessRunnerDeps, \"callTool\" | \"sleep\">,\n cfg: Pick<\n HarnessRunnerConfig,\n \"tokens\" | \"commitPollMs\" | \"commitPollMax\" | \"log\"\n >,\n freeze: FreezeSource,\n ctx: HarnessStageJobContext,\n opts: { jobId?: string } = {},\n): Promise<\"authorized\" | \"gated\" | \"blocked\"> {\n for (let i = 0; i < cfg.commitPollMax; i++) {\n // A FRESH freeze read each poll \u2014 a freeze mid-wait stops us before push.\n if (await freeze.check()) return \"gated\";\n // Paginated lookup (handles a 50+-stage harness).\n const status = await stageStatus(deps, cfg, ctx);\n if (status === \"COMMITTED\") return \"authorized\";\n if (status === \"BLOCKED\" || status === \"SKIPPED\") return \"blocked\";\n await deps.sleep(cfg.commitPollMs);\n }\n // Budget exhausted. Re-read freeze AND stage status FRESH (review P2): the\n // stage may have committed/blocked \u2014 or the run frozen \u2014 during the final\n // sleep, and a stale snapshot must neither false-alarm the deadman nor\n // mis-report the disposition.\n if (await freeze.check()) return \"gated\";\n const finalStatus = await stageStatus(deps, cfg, ctx);\n if (finalStatus === \"COMMITTED\") return \"authorized\";\n if (finalStatus === \"BLOCKED\" || finalStatus === \"SKIPPED\") return \"blocked\";\n if (opts.jobId) {\n await commitDeadmanProbe(deps, cfg, ctx, opts.jobId, finalStatus);\n }\n return \"gated\";\n}\n\n/**\n * Drive ONE harness stage EXECUTION turn end to end. This is the EXECUTING-phase\n * handoff: it does NOT commit. A harness stage rides the M7 loop, so the commit is\n * a SEPARATE, post-validation boundary (`authorize_harness_local_commit` rejects\n * anything not already VALIDATED/COMMIT_GATE) \u2014 `driveHarnessCommit` handles that\n * once the stage is validated. The execution turn:\n * 1. executes in the checkout (freeze aborts the subprocess),\n * 2. captures the diff + test evidence and links them via submit_harness_artifact,\n * 3. records submit_harness_stage_result (evidence linked; NO commit yet \u2014 the\n * stage isn't validated), and\n * 4. satisfies the generic M7 submit_execution_result so the loop advances to\n * the reviewer turn.\n * It then OPPORTUNISTICALLY runs the commit boundary if the stage is ALREADY\n * VALIDATED/COMMIT_GATE (e.g. an auto-approved gate under an ALLOW policy); when a\n * human gate is still pending it returns \"awaiting validation\" and the commit runs\n * on a later invocation.\n *\n * Returns a terminal disposition for the runner's log. Throws nothing for the\n * common gated/frozen cases \u2014 those are reported, not failed (a real provider\n * error still propagates so the caller can `fail_agent_job`).\n */\nexport async function driveHarnessStage(\n deps: HarnessRunnerDeps,\n cfg: HarnessRunnerConfig,\n input: { jobId: string },\n): Promise<{ disposition: string }> {\n const log = cfg.log ?? (() => {});\n const job = await getHarnessStageJob(deps, cfg, input.jobId);\n const ctx = job.harness;\n if (!ctx) {\n // Not a harness stage job \u2014 the caller should have routed this to the generic\n // path. Defensive: report rather than act.\n return { disposition: \"not_a_harness_stage_job\" };\n }\n\n // BOUND the executor path to a configured checkout BEFORE claiming/working \u2014 a\n // tools-only reference-agent assumption must never leak into the executor path.\n // The actual working directory is a per-job WORKTREE resolved AFTER the claim\n // (inside the try below), so the ownership check runs as the newest attempt.\n const repo = ctx.repo;\n if (!repo || !cfg.repos[repo]) {\n throw new UnmappedRepoError(repo);\n }\n\n await deps.preflightVerification?.();\n\n // Claim the turn with the ADMIN token \u2192 runId. The presentation (pinned\n // model + build-stamped revision + capabilities) rides claimPresentation \u2014\n // the control plane refuses a schema-incompatible worker (and an unattested\n // validator lane) BEFORE any model turn burns (M12.3b/M13.4b; un-stamped dev\n // leaves the compatibility guard inert).\n const configured = cfg.executorBinding;\n if (cfg.stopping?.()) return { disposition: \"shutdown_requested\" };\n const provider = configured?.runtimeAdapterKey ?? agentProvider();\n const model =\n configured?.model ??\n (provider === \"claude\" ? claudeLegModel(\"executor\") : codexModel());\n const workerClaimToken = configured\n ? await cfg.mintClaimCredential?.(configured)\n : undefined;\n if (cfg.stopping?.()) return { disposition: \"shutdown_requested\" };\n const claim = await deps.callTool(cfg.tokens.runner, \"claim_agent_job\", {\n jobId: input.jobId,\n ...claimPresentation(provider, {\n revision: cfg.revision,\n capabilities: cfg.capabilities,\n model,\n }),\n ...(configured ? { provider: configured.provider } : {}),\n ...(workerClaimToken ? { workerClaimToken } : {}),\n });\n const runId = String(claim.runId);\n let execution: ResolvedClaimExecution | undefined;\n try {\n execution = configured\n ? resolveClaimExecution(claim, configured)\n : undefined;\n } catch (error) {\n await deps\n .callTool(cfg.tokens.runner, \"fail_agent_job\", {\n jobId: input.jobId,\n runId,\n error: error instanceof Error ? error.message : \"role route refused\",\n })\n .catch(() => {});\n throw error;\n }\n // M18.3 R7 \u2014 THE CHECKOUT DECISION, made from the DURABLE run role the control\n // plane just returned, not from the leg's shape. `claim_agent_job` answers with\n // the role it opened the run as; `repoAccessForRole` is total and fail-closed,\n // so EXECUTOR gets the writable worktree it always got and every other role \u2014\n // VALIDATOR, or anything this runner does not recognize \u2014 gets an adopt-only,\n // read-only tree. Resolved ONCE here and consumed at both sites below (the\n // worktree call and the model session), so there is no second place where a\n // writable checkout could be conjured up.\n const repoAccess = repoAccessForRole(\n typeof claim.role === \"string\" ? claim.role : null,\n );\n\n const pump = new HeartbeatPump(deps, cfg, input.jobId, runId);\n pump.start();\n try {\n // 0. The stage's OPEN review-findings ledger is required executor scope:\n // without feeding it into the turn (and claiming FIXED on submit, below)\n // the rows stay OPEN forever and a findings-aware reviewer rejects every\n // round regardless of evidence quality. Fixer claims, reviewer verifies.\n const openFindings: Array<{\n id?: unknown;\n title?: unknown;\n body?: unknown;\n suggestedFix?: unknown;\n resolutionNote?: unknown;\n reopenCount?: unknown;\n }> = await deps\n .callTool(cfg.tokens.planner, \"list_harness_findings\", {\n harnessRunId: ctx.harnessRunId,\n harnessStageId: ctx.stageId,\n status: \"OPEN\",\n // Concise omits body/resolution fields \u2014 exactly the information an\n // executor needs to avoid repeating a rejected evidence substitution.\n response_format: \"detailed\",\n })\n .then((r) => (Array.isArray(r.findings) ? r.findings : []))\n .catch(() => []);\n const findingsBlock = openFindings.length\n ? `\\nOpen review findings on this stage \u2014 these are the reviewer's FULL objections, not optional hints. Address EVERY requirement in the body and suggested fix with production-path code plus completed evidence. Do not substitute an in-memory model, a comment, or a future adapter seam for the requested trust/effect boundary:\\n\\n${openFindings\n .map((f, index) => {\n // W3: a REOPENED row is the loop oscillating on one finding \u2014 the\n // second reopen parks the stage for human adjudication, so the\n // executor must know it is on its last pass at this objection\n // rather than treating the row as freshly raised.\n const reopens =\n typeof f.reopenCount === \"number\" && f.reopenCount > 0\n ? ` \u2014 REOPENED ${f.reopenCount}\u00D7 (a prior fix for this exact finding was rejected; two reopens park the stage for human adjudication, so do not repeat a rejected approach)`\n : \"\";\n const sections = [\n `Finding ${index + 1} [${String(f.id)}]${reopens}: ${String(f.title)}`,\n typeof f.body === \"string\" && f.body.trim()\n ? `Reviewer rationale:\\n${f.body.trim()}`\n : null,\n typeof f.suggestedFix === \"string\" && f.suggestedFix.trim()\n ? `Required fix/evidence:\\n${f.suggestedFix.trim()}`\n : null,\n typeof f.resolutionNote === \"string\" && f.resolutionNote.trim()\n ? `Prior attempted resolution (verify it; do not repeat it if rejected):\\n${f.resolutionNote.trim()}`\n : null,\n ].filter((part): part is string => part !== null);\n return sections.join(\"\\n\");\n })\n .join(\n \"\\n\\n---\\n\\n\",\n )}\\n\\nEnd your summary with the line \"ADDRESSED_FINDINGS: <comma-separated ids>\" naming ONLY the findings you actually completed (or \"ADDRESSED_FINDINGS: none\") \u2014 only those are claimed FIXED for the reviewer to verify; the rest stay OPEN.\\n`\n : \"\";\n\n // 1. EXECUTE in the per-job WORKTREE (role token; turn-guard passes). The\n // signal is aborted if a heartbeat reports the run frozen mid-turn.\n const branch = resolveStageBranch(ctx);\n // Resolve the executor's workingDirectory: the job's own native-Git worktree\n // (created from executionBaseRef or the reused stage-branch tip; adopted on a\n // restart; ownership-checked before reusing a shared stage branch). Diff/test\n // evidence below is captured from THIS worktree only. A resolution failure\n // (ownership conflict / unprovable / missing ref) throws \u2192 fail_agent_job parks\n // the stage for a human with the actionable diagnostic.\n //\n // M18.3 R7: which of the two worktree primitives runs is decided by\n // `repoAccess.provisionWorktree`, i.e. by the durable run role. The\n // read-only lane calls `adoptExecutionCwd` \u2014 which creates nothing,\n // bootstraps nothing and copies nothing \u2014 and PARKS when there is no tree to\n // adopt. It must never degrade to `ensureExecutionCwd` (that IS the writable\n // lane) nor to the shared grounding checkout (which lacks the stage's\n // uncommitted change, so any verdict would describe the wrong tree) \u2014 the\n // same fail-closed rule the harness reviewer leg already follows.\n const identity = {\n repo,\n jobId: input.jobId,\n stageId: ctx.stageId,\n branch,\n };\n let cwd: string;\n if (repoAccess.provisionWorktree) {\n cwd = await deps.worktree.ensureExecutionCwd(\n identity,\n ctx.executionBaseRef,\n );\n } else {\n const adopted = await deps.worktree.adoptExecutionCwd(identity);\n if (!adopted) {\n const reason = missingReadOnlyCheckoutReason({\n role: typeof claim.role === \"string\" ? claim.role : null,\n stageId: ctx.stageId,\n });\n log(`[harness ${ctx.stageId}] ${reason}`);\n await deps\n .callTool(cfg.tokens.runner, \"fail_agent_job\", {\n jobId: input.jobId,\n runId,\n error: reason,\n })\n .catch(() => {});\n return { disposition: \"read_only_checkout_unavailable\" };\n }\n cwd = adopted;\n }\n // Snapshot HEAD before the turn: a local-commit stage's executor commits its\n // own work, leaving a clean tree \u2014 evidence then comes from the\n // preTurnHead..HEAD range (step 2), not the (empty) working-tree diff.\n const preTurnHead = await deps\n .git(cwd, [\"rev-parse\", \"HEAD\"])\n .then((s) => s.trim())\n .catch(() => null);\n // The repo's own conventions + the base-branch commits this worktree does\n // NOT have (parallel work on the same repo \u2014 the M18 shape). Fail-soft.\n const projectContext = await buildProjectContext(\n { git: (dir, args) => deps.git(dir, args) },\n { cwd, baseBranch: ctx.baseBranch, role: \"executor\" },\n ).catch(() => \"\");\n // W5: measure the drift ONCE, before the turn, so the number the executor is\n // told and the number the attestation records are the same fact.\n const drift = await measureBaseDrift(\n { git: (dir, args) => deps.git(dir, args) },\n { cwd, baseBranch: ctx.baseBranch },\n ).catch(() => null);\n if (drift && drift.behindBase > 0) {\n log(\n `[harness ${ctx.stageId}] behind base by ${drift.behindBase} commit(s) (${ctx.baseBranch ?? \"main\"} @ ${drift.baseSha.slice(0, 12)}) \u2014 stacked work reviewed against an older tree`,\n );\n }\n // A read-only attempt is told the truth about its tree. The RUNNER executes\n // the declared verification commands either way (step 2b below) and attests\n // the result \u2014 that is the only channel a validator's TEST_EVIDENCE can\n // arrive through, so the turn's job is to read and report, not to implement.\n // AGE-781: the decomposition-reviewed implementation approach \u2014 the\n // executor's brief. Stages open at EXECUTING with no per-stage plan turn,\n // so this reviewed sketch is the only \"how\" beyond the criteria. Advisory\n // by design: the criteria stay the literal contract, and an executor that\n // finds the approach wrong in the checkout follows the code, not the sketch.\n const approachBlock = ctx.approach\n ? `Reviewed implementation approach (the decomposition's brief \u2014 follow it unless the checkout proves it wrong, and say so in the summary if it is):\\n${ctx.approach}\\n`\n : \"\";\n const taskPrompt = repoAccess.repoReadOnly\n ? `Verify Harness stage ${ctx.stageNumber} (\"${ctx.stageTitle}\") against the READ-ONLY checkout at ${cwd} on branch ${branch}. ` +\n `You may read the tree and report findings; you cannot modify it, and you must not try. ` +\n `The RUNNER \u2014 not you \u2014 executes this stage's declared verification commands and attests the result as TEST_EVIDENCE. ` +\n `Acceptance criteria (literal contract; judge each clause against production-path evidence):\\n- ${ctx.acceptanceCriteria.join(\"\\n- \")}\\n` +\n approachBlock +\n findingsBlock +\n `Report what verification found.`\n : `Implement Harness stage ${ctx.stageNumber} (\"${ctx.stageTitle}\") in ${cwd} on branch ${branch}. ` +\n `Acceptance criteria (literal contract; satisfy each clause with production-path evidence):\\n- ${ctx.acceptanceCriteria.join(\"\\n- \")}\\n` +\n approachBlock +\n findingsBlock +\n `Run the relevant tests and report what you changed.`;\n const summary = await deps.runAgentTurn({\n prompt: taskPrompt + projectContext,\n // W7: the executor rubric is a versioned file injected once, so the system\n // prompt is a function call here rather than the old module constant.\n systemPrompt: harnessExecutorSystemPrompt(),\n repoCwd: cwd,\n // M18.3 R7: map-derived, never a hand-written literal. False for EXECUTOR\n // (today's behavior, unchanged); true for a validator or any unrecognized\n // role, which the providers enforce by withholding the write/edit tools\n // (claude) and running the shell read-only (codex).\n repoReadOnly: repoAccess.repoReadOnly,\n signal: pump.controller.signal,\n // W3: the runner \u2014 not this turn \u2014 submits the stage result and attests\n // the evidence, so the runtime denies a submission attempted over an\n // uncommitted tree and nudges a turn ending with verification still\n // running in the background.\n runnerOwnsSubmissions: true,\n execution,\n });\n pump.markSubprocessDone();\n log(`[harness ${ctx.stageId}] executor: ${summary}`);\n\n // 1b. S1 documentation commit guard \u2014 regenerate the checked-in generated docs\n // BEFORE the reviewer turn, so a public-contract change (e.g. a new MCP tool)\n // lands its generated doc entry in the SAME diff the reviewer and the evidence\n // capture below see. This never silently stages behind the reviewer: the\n // regenerated files show up in the diff evidence, and the authoritative gate\n // is docs:check at the commit boundary, which blocks if the tree is still stale.\n if (deps.docsGuard) {\n try {\n const preDocs = await captureDiffEvidence(deps, cwd);\n await deps.docsGuard.sync(cwd, preDocs.changedFiles);\n } catch (err) {\n log(\n `[harness ${ctx.stageId}] docs:sync failed (non-blocking; commit-time docs:check still gates): ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n }\n\n // 2. Capture the diff + test evidence and link them (the validation gate needs\n // DIFF_OR_PATCH + TEST_EVIDENCE; submit_harness_stage_result writes the\n // EXECUTION_SUMMARY itself). The executor's summary carries its test results.\n // A FRESH freeze read BEFORE the evidence submits \u2014 \"no submit while frozen\"\n // covers the artifact captures too (the capture is an MCP mutation).\n if (await pump.check()) throw new HarnessFrozenError(ctx.stageId);\n let evidence = await captureDiffEvidence(deps, cwd);\n // AGE-306: an executor that committed during its turn (local-commit stages)\n // leaves a clean tree \u2014 the working-tree diff is empty, and skipping the\n // DIFF_OR_PATCH artifact wedges FINAL_ACCEPTANCE on \"missing evidence\".\n // When HEAD moved across the turn, the committed range IS the turn's change;\n // an unmoved HEAD stays empty (never fabricate evidence from prior commits).\n if (!evidence.patch.trim() && preTurnHead) {\n const postTurnHead = await deps\n .git(cwd, [\"rev-parse\", \"HEAD\"])\n .then((s) => s.trim())\n .catch(() => null);\n if (postTurnHead && postTurnHead !== preTurnHead) {\n const committed = await captureCommittedChange(deps, cwd, preTurnHead);\n if (committed.patch.trim()) evidence = committed;\n }\n }\n // 2b. HAI S3: the RUNNER executes the stage's declared verification\n // commands itself \u2014 foreground, per-command timeout, in the worktree.\n // The executor's prose NEVER becomes TEST_EVIDENCE; only these observed\n // results do, each submitted with a runner attestation bound to the\n // diff checksum. Missing runCommand dep or declared-but-unrun commands\n // leave the evidence honestly absent (the gate blocks, never fakes).\n // The stage's own commands PLUS the mandatory harness-flow gate, always\n // last. It rides the existing verification path deliberately: the runner\n // executes it in the foreground, its real exit code becomes attested\n // TEST_EVIDENCE, and a red gate lands in `risks` + `testsNotRun` where the\n // validation gate and the reviewer both see it. A stage that already\n // declares it is not run twice.\n const declaredCommands = [\n ...(ctx.verificationCommands ?? []).filter(\n (c) => c.trim() !== HARNESS_FLOW_GATE_COMMAND,\n ),\n HARNESS_FLOW_GATE_COMMAND,\n ];\n const verification: VerificationRunResult[] = [];\n for (const command of declaredCommands) {\n if (!deps.runCommand) break;\n if (await pump.check()) throw new HarnessFrozenError(ctx.stageId);\n log(`[harness ${ctx.stageId}] verify: ${command}`);\n verification.push(\n await deps.runCommand({\n cwd,\n command,\n timeoutMs: cfg.verificationTimeoutMs ?? 900_000,\n signal: pump.controller.signal,\n }),\n );\n }\n const evidenceArtifacts = await captureStageEvidence(deps, cfg, ctx, {\n patch: evidence.patch,\n patchRead: evidence.patchRead,\n verification,\n attest: {\n jobId: input.jobId,\n runId,\n baseHead: preTurnHead ?? \"(unknown)\",\n cwd,\n },\n drift,\n });\n\n // 3. Record the structured stage result \u2014 evidence linked, NO commit (the stage\n // is not validated yet; reporting a commit now would be rejected by the\n // boundary anyway). The commit + its SHA report happen in driveHarnessCommit\n // AFTER validation. FRESH freeze read right before the submit. HAI S3:\n // the structured report is populated HONESTLY from the observed runs \u2014\n // commandsRun = executed, testsRun = passed, testsNotRun = declared but\n // not executed or failed, risks = the failures.\n if (await pump.check()) throw new HarnessFrozenError(ctx.stageId);\n const executed = new Set(verification.map((v) => v.command));\n const passed = verification.filter((v) => v.exitCode === 0 && !v.timedOut);\n const failed = verification.filter((v) => v.exitCode !== 0 || v.timedOut);\n await submitStageResultResilient(\n deps,\n cfg,\n {\n harnessRunId: ctx.harnessRunId,\n stageId: ctx.stageId,\n changedFiles: evidence.changedFiles,\n commandsRun: verification.map((v) => v.command),\n testsRun: passed.map((v) => v.command),\n testsNotRun: [\n ...declaredCommands.filter((c) => !executed.has(c)),\n ...failed.map((v) => v.command),\n ],\n risks: failed.map(\n (v) =>\n `verification failed: ${v.command} (${v.timedOut ? \"timed out\" : `exit ${v.exitCode}`})`,\n ),\n diffLines: evidence.diffLines,\n branch,\n evidenceArtifacts,\n // AGE-297: every stage-result submission is attempt-bound (required) \u2014\n // a superseded attempt's late submit is refused server-side.\n jobId: input.jobId,\n },\n // Stable per-attempt key: a post-504 retry replays the landed write.\n `stage-result:${runId}`,\n );\n\n // 3b. Claim FIXED ONLY on the ledger rows the executor explicitly reported\n // completing (its ADDRESSED_FINDINGS line) \u2014 BEFORE the reviewer turn\n // opens, so it reads a consistent ledger. NEVER a blanket claim: a\n // round that fixed 2 of 6 rows (or made no edits at all) used to mark\n // all 6 FIXED, which taught the reviewer to distrust every claim and\n // reject every round. Unlisted rows stay OPEN \u2014 honest, and the\n // reviewer's own OPEN\u2192FIXED\u2192VERIFIED path still covers a row the\n // executor fixed but forgot to list. The reviewer VERIFIES or REOPENS\n // each claim (update_harness_finding enforces legal transitions; an\n // already-resolved row is a tolerated failure, not a stop).\n const openIds = new Set(openFindings.map((f) => String(f.id)));\n const addressedIds = parseAddressedFindingIds(summary).filter((id) =>\n openIds.has(id),\n );\n for (const findingId of addressedIds) {\n await deps\n .callTool(cfg.tokens.planner, \"update_harness_finding\", {\n findingId,\n status: \"FIXED\",\n resolutionNote: `Addressed in stage ${ctx.stageNumber} execution (run ${runId}) \u2014 see the execution summary and evidence artifacts.`,\n })\n .catch(() => {});\n }\n\n // 4. Satisfy the generic M7 execution submission so the state machine advances\n // EXECUTING \u2192 EXECUTION_REVIEW and the reviewer turn opens. FRESH freeze read.\n if (await pump.check()) throw new HarnessFrozenError(ctx.stageId);\n try {\n await deps.callTool(cfg.tokens.planner, \"submit_execution_result\", {\n jobId: input.jobId,\n runId,\n executionSummary: summary,\n });\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n if (!message.includes(\"It is not this agent's turn\")) throw error;\n\n // The tools-capable executor can occasionally submit the generic result\n // despite the runner-only instruction. Converge only when a fresh read of\n // this exact job proves that transition already landed; any other conflict\n // remains a real failure.\n const fresh = (await deps.callTool(cfg.tokens.runner, \"get_agent_job\", {\n jobId: input.jobId,\n })) as unknown as AgentJobView;\n if (\n fresh.id !== input.jobId ||\n fresh.phase !== \"EXECUTION_REVIEW\" ||\n fresh.harness?.stageId !== ctx.stageId\n ) {\n throw error;\n }\n log(\n `[harness ${ctx.stageId}] execution result already submitted; continuing from EXECUTION_REVIEW`,\n );\n }\n\n // 5. OPPORTUNISTIC commit: if the stage is ALREADY VALIDATED/COMMIT_GATE (an\n // auto-approved gate under an ALLOW policy), run the commit boundary now.\n // Otherwise the human gate is still pending \u2014 defer; the commit runs on a\n // later invocation of driveHarnessCommit.\n if (await pump.check()) throw new HarnessFrozenError(ctx.stageId);\n const status = await stageStatus(deps, cfg, ctx);\n if (status === \"VALIDATED\" || status === \"COMMIT_GATE\") {\n const commit = await driveHarnessCommit(deps, cfg, pump, ctx, {\n cwd,\n branch,\n jobId: input.jobId,\n });\n return { disposition: `executed; ${commit.disposition}` };\n }\n return {\n disposition: `executed; awaiting validation (stage ${status ?? \"?\"})`,\n };\n } catch (err) {\n if (err instanceof HarnessFrozenError) {\n // Deliberately NOT checkpointed: a local commit is a freeze boundary, and\n // the worktree is retained + re-adopted by this same job on resume, so a\n // freeze never strands work.\n log(err.message);\n return { disposition: \"frozen\" };\n }\n // W1: this turn is about to PARK the job for a human. Commit whatever it left\n // in the worktree onto the stage branch FIRST \u2014 the retry gets a fresh\n // worktree from the branch tip, so anything uncommitted here dies invisibly.\n await checkpointParkedWorktree(deps, cfg, ctx, {\n jobId: input.jobId,\n branch: resolveStageBranch(ctx),\n reason: `failed turn: ${err instanceof Error ? err.message : \"harness runner error\"}`,\n });\n // A real provider/git/MCP error AFTER the claim must FAIL the run (admin token)\n // so the job BLOCKS for a human promptly, rather than sitting active until the\n // heartbeat lapses \u2014 same contract as the generic M7 drive() path.\n await deps\n .callTool(cfg.tokens.runner, \"fail_agent_job\", {\n jobId: input.jobId,\n runId,\n error: err instanceof Error ? err.message : \"harness runner error\",\n })\n .catch((e) =>\n log(`[harness ${input.jobId}] fail_agent_job failed: ${e}`),\n );\n throw err;\n } finally {\n pump.stop();\n }\n}\n\n/**\n * W1: make a park LOSSLESS. A parking attempt never reaches its commit gate, and\n * the next attempt gets a fresh worktree checked out at the stage branch's tip \u2014\n * so any uncommitted work left here is invisible to the reviewer, the gates, and\n * the operator (the M18 run needed ten manual \"operator checkpoint\" commits;\n * attempt #7 alone left 2,881 lines behind). Committing it onto the branch makes\n * it part of the diff the next round reviews.\n *\n * Best-effort by contract: a checkpoint failure is LOGGED with the worktree path\n * (the work is still on disk, and `pnpm harness-worktrees` reports it) and never\n * masks the park itself \u2014 the human needs the original reason.\n */\nasync function checkpointParkedWorktree(\n deps: Pick<HarnessRunnerDeps, \"worktree\">,\n cfg: Pick<HarnessRunnerConfig, \"log\">,\n ctx: HarnessStageJobContext,\n args: { jobId: string; branch: string; reason: string },\n): Promise<void> {\n const log = cfg.log ?? (() => {});\n if (!ctx.repo) return;\n try {\n const res = await deps.worktree.checkpointExecutionCwd(\n {\n repo: ctx.repo,\n jobId: args.jobId,\n stageId: ctx.stageId,\n branch: args.branch,\n },\n `harness checkpoint: stage ${ctx.stageNumber} job ${args.jobId} (${args.reason})`,\n );\n if (res.committed) {\n log(\n `[harness ${ctx.stageId}] park checkpoint: committed ${res.files?.length ?? 0} path(s) to ${args.branch} (${res.sha?.slice(0, 12)}) \u2014 the next attempt inherits this work`,\n );\n }\n } catch (e) {\n log(\n `[harness ${ctx.stageId}] park checkpoint FAILED \u2014 uncommitted work may be stranded in this attempt's worktree: ${\n e instanceof Error ? e.message : String(e)\n }`,\n );\n }\n}\n\n/** The stage's current status via list_harness_stages, PAGINATING until the stage\n * is found (the server caps each page at 50; a harness with 50+ stages would\n * otherwise read a late stage as \"not found\"). Returns null only when the stage is\n * absent from every page. */\n/**\n * F3 (AGE-500): submit the stage result with a STABLE idempotency key and one\n * delayed final replay. A gateway 504 whose write actually landed stores the\n * response under the key server-side, so the replay returns it instead of\n * failing a green turn \u2014 the old path called fail_agent_job after a landed\n * submit, and the re-claim then stormed \"not the job's active run\" CONFLICTs.\n * App-level tool errors (the isError envelope) stay deterministic failures.\n */\nasync function submitStageResultResilient(\n deps: Pick<HarnessRunnerDeps, \"callTool\" | \"sleep\">,\n cfg: Pick<HarnessRunnerConfig, \"tokens\">,\n args: Record<string, unknown>,\n idempotencyKey: string,\n): Promise<void> {\n const payload = { ...args, idempotencyKey };\n try {\n await deps.callTool(\n cfg.tokens.planner,\n \"submit_harness_stage_result\",\n payload,\n );\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n // A structured tool error is deterministic \u2014 replaying cannot change it.\n if (msg.startsWith(\"submit_harness_stage_result failed:\")) throw err;\n // Transport-level failure that survived callTool's own retries: ONE more\n // replay after a longer wait. With the key it is a read when the first\n // write landed, and an execute when it truly did not.\n await deps.sleep(30_000);\n await deps.callTool(\n cfg.tokens.planner,\n \"submit_harness_stage_result\",\n payload,\n );\n }\n}\n\n/** All stage statuses for a run in ONE paginated list_harness_stages walk \u2014\n * the F5/F4 commit-watch reads every watched stage of a run from a single\n * call per tick instead of a multi-call drive per watched job. */\nexport async function listStageStatuses(\n deps: Pick<HarnessRunnerDeps, \"callTool\">,\n cfg: Pick<HarnessRunnerConfig, \"tokens\">,\n harnessRunId: string,\n): Promise<Map<string, string>> {\n const statuses = new Map<string, string>();\n let cursor: string | undefined;\n // Bounded page walk (defensive against an unbounded cursor loop).\n for (let page = 0; page < 100; page++) {\n const res = (await deps.callTool(cfg.tokens.runner, \"list_harness_stages\", {\n harnessRunId,\n ...(cursor ? { cursor } : {}),\n })) as {\n stages?: Array<{ id: string; status: string }>;\n nextCursor?: string | null;\n };\n for (const s of res.stages ?? []) statuses.set(s.id, s.status);\n if (!res.nextCursor) break;\n cursor = res.nextCursor;\n }\n return statuses;\n}\n\nasync function stageStatus(\n deps: Pick<HarnessRunnerDeps, \"callTool\">,\n cfg: Pick<HarnessRunnerConfig, \"tokens\">,\n ctx: HarnessStageJobContext,\n): Promise<string | null> {\n const statuses = await listStageStatuses(deps, cfg, ctx.harnessRunId);\n return statuses.get(ctx.stageId) ?? null;\n}\n\n/**\n * Drive the post-validation COMMIT boundary for a stage that has reached\n * VALIDATED/COMMIT_GATE: AUTHORIZE the local commit (a permission check that mints\n * no credential and approves no gate), `git commit`, report the SHA via\n * submit_harness_stage_result (which records the commit evidence bound to this\n * attempt and lets the boundary advance the stage to COMMITTED), then PUSH/PR via\n * a single-use brokered credential once the boundary authorizes it. The runner\n * NEVER approves the commit gate itself \u2014 when policy parks the stage at a pending\n * COMMIT gate it stops and the human approves in the Control Tower. Freeze is\n * re-checked at every boundary. Exported so the runner can invoke it on its own\n * (after a later VALIDATED signal) and the smoke test can drive it deterministically.\n */\nexport async function driveHarnessCommit(\n deps: HarnessRunnerDeps,\n cfg: HarnessRunnerConfig,\n freeze: FreezeSource,\n ctx: HarnessStageJobContext,\n args: { cwd: string; branch: string; jobId: string },\n): Promise<{ disposition: string }> {\n const log = cfg.log ?? (() => {});\n if (await freeze.check()) return { disposition: \"frozen\" };\n\n // AUTHORIZE \u2192 commit locally. authorize_harness_local_commit throws on a\n // non-validated/frozen/lease-blocked/policy-deny stage, so a red stage can never\n // commit. It mints NO credential and approves NO gate. It returns the committed\n // change (captured pre-commit, since a post-commit diff is empty). It re-checks\n // freeze FRESH at each of its own boundaries.\n const commit = await authorizeAndCommit(deps, cfg, freeze, ctx, {\n cwd: args.cwd,\n branch: args.branch,\n message: `Harness stage ${ctx.stageNumber}: ${ctx.stageTitle}`,\n });\n if (!commit.sha) return { disposition: \"commit produced no SHA\" };\n\n // FRESH freeze read before the commit-evidence submit. If a freeze landed after\n // the local commit, don't report (the server would park it on a frozen run\n // anyway) \u2014 on resume the runner re-drives and re-reports the same commit.\n if (await freeze.check()) return { disposition: \"frozen\" };\n // Report the SHA + the committed files \u2014 this records the commit evidence (bound\n // to this attempt's jobId) the boundary needs to advance VALIDATED/COMMIT_GATE \u2192\n // COMMITTED. No new evidence artifacts here (they were linked on the execution\n // turn); this report is the local-commit report (boundary 1's second half).\n await submitStageResultResilient(\n deps,\n cfg,\n {\n harnessRunId: ctx.harnessRunId,\n stageId: ctx.stageId,\n changedFiles: commit.changedFiles,\n diffLines: commit.diffLines,\n branch: args.branch,\n commit: commit.sha,\n jobId: args.jobId,\n },\n // Keyed on the attempt + the exact SHA: a retry of the same commit report\n // replays; a NEW SHA (re-commit) is a different key, never a replay.\n `commit-evidence:${args.jobId}:${commit.sha}`,\n );\n\n // PUSH/PR egress \u2014 only after the boundary authorizes it (the stage reaches\n // COMMITTED). Brokered single-use credentials; never a standing token. A pending\n // commit gate or a blocked stage stops the runner (no self-approve).\n const result = await pushAfterAuthorized(\n deps,\n cfg,\n freeze,\n ctx,\n {\n cwd: args.cwd,\n branch: args.branch,\n commitSha: commit.sha,\n repo: ctx.repo ?? \"\",\n },\n () =>\n waitForCommitAuthorized(deps, cfg, freeze, ctx, { jobId: args.jobId }),\n );\n if (!result.pushed) {\n log(`[harness ${ctx.stageId}] push deferred: ${result.reason}`);\n return { disposition: `committed; push ${result.reason}` };\n }\n // A frozen-before-PR push still pushed, but the PR is deferred \u2014 surface it so a\n // resume (the COMMITTED-stage path) retries the PR rather than masking it. The\n // worktree is RETAINED (a resume needs it) \u2014 no cleanup on a deferred/frozen leg.\n if (result.reason) {\n return { disposition: `committed_and_pushed; ${result.reason}` };\n }\n // Fully delivered (COMMITTED + pushed + PR done): a safe terminal Jentrix state\n // with no active run \u2014 clean up the worktree (source-dirty/orphaned retained).\n await maybeCleanupWorktree(deps, cfg, ctx, {\n branch: args.branch,\n jobId: args.jobId,\n });\n return { disposition: \"committed_and_pushed\" };\n}\n\n/**\n * Stage 3 cleanup: once the stage is a safe TERMINAL Jentrix state (COMMITTED and\n * fully delivered \u2014 pushed, not frozen/gated), remove the delivered worktree via\n * the S1 safe path (git clean -fdX ignored \u2192 `git worktree remove` \u2192 prune). A\n * source-dirty or orphaned worktree is RETAINED and reported (a human decides). The\n * worktree deliberately survives freeze, PRE_EXECUTION/FINAL_ACCEPTANCE/COMMIT\n * gates, same-job revisions, and a process restart \u2014 those never reach this leg.\n * Best-effort: a cleanup failure never changes the commit disposition.\n */\nasync function maybeCleanupWorktree(\n deps: Pick<HarnessRunnerDeps, \"worktree\">,\n cfg: Pick<HarnessRunnerConfig, \"log\">,\n ctx: HarnessStageJobContext,\n args: { branch: string; jobId: string },\n): Promise<void> {\n const log = cfg.log ?? (() => {});\n if (!ctx.repo) return;\n try {\n const res = await deps.worktree.cleanupExecutionWorktree({\n repo: ctx.repo,\n jobId: args.jobId,\n stageId: ctx.stageId,\n branch: args.branch,\n });\n if (res.removed) {\n log(`[harness ${ctx.stageId}] worktree removed (delivered)`);\n } else if (res.reason === \"source-dirty\") {\n log(\n `[harness ${ctx.stageId}] worktree RETAINED (source-dirty, ${res.dirty?.length ?? 0} change(s)) \u2014 inspect + remove manually via the harness-worktrees command.`,\n );\n }\n } catch (e) {\n log(`[harness ${ctx.stageId}] worktree cleanup skipped: ${e}`);\n }\n}\n\n/**\n * A freeze probe for the post-validation commit phase, which (unlike the execution\n * turn) has no active M7 run to heartbeat. `check()` reads the run's frozen state\n * FRESH via `get_harness` at every boundary, so a freeze landing between boundaries\n * is caught; the server guards (authorize throws, submit/broker park/fail-closed on\n * a frozen run) are the backstop. A read failure leaves the last known state (never\n * force-unfreezes).\n */\nexport class FreezeProbe implements FreezeSource {\n frozen = false;\n constructor(\n private readonly deps: Pick<HarnessRunnerDeps, \"callTool\">,\n private readonly cfg: Pick<HarnessRunnerConfig, \"tokens\">,\n private readonly harnessRunId: string,\n ) {}\n async check(): Promise<boolean> {\n try {\n const res = (await this.deps.callTool(\n this.cfg.tokens.runner,\n \"get_harness\",\n {\n // The op's schema keys on harnessRunId (NOT harnessId).\n harnessRunId: this.harnessRunId,\n },\n )) as { harness?: { frozen?: boolean; status?: string } };\n this.frozen =\n res.harness?.frozen === true || res.harness?.status === \"FROZEN\";\n } catch {\n // A read failure shouldn't force-unfreeze; leave the last known state.\n }\n return this.frozen;\n }\n}\n\n/**\n * The LIVE post-validation commit entry point. A harness stage is validated LATER\n * than its execution turn (after the reviewer + the human FINAL_ACCEPTANCE gate),\n * at which point Jentrix emits `harness.stage_validated` (and the server commit\n * boundary parks awaiting the runner's commit evidence). The runner reacts to that\n * webhook by calling this: it re-reads the job's harness context, confirms the\n * stage is VALIDATED/COMMIT_GATE, and drives the commit boundary. Returns a\n * disposition; a non-validated stage (e.g. a stale/duplicate signal) is a no-op.\n */\nexport async function driveHarnessStageCommit(\n deps: HarnessRunnerDeps,\n cfg: HarnessRunnerConfig,\n input: { jobId: string },\n): Promise<{ disposition: string }> {\n const log = cfg.log ?? (() => {});\n const job = await getHarnessStageJob(deps, cfg, input.jobId);\n const ctx = job.harness;\n if (!ctx) return { disposition: \"not_a_harness_stage_job\" };\n\n // Bound the checkout, same as the execution turn.\n const repo = ctx.repo;\n if (!repo || !cfg.repos[repo]) throw new UnmappedRepoError(repo);\n\n const status = await stageStatus(deps, cfg, ctx);\n // AGE-410: bail BEFORE touching a worktree. This poller used to resolve the\n // worktree first, so every tick paid a bootstrap (pnpm install) for a stage\n // that was not committable \u2014 a gate-parked job on a cancelled run churned one\n // per poll, forever. Order: cheap status reads, then the worktree.\n if (\n status !== \"COMMITTED\" &&\n status !== \"VALIDATED\" &&\n status !== \"COMMIT_GATE\"\n ) {\n // A terminal run can never authorize this commit \u2014 tell the pump to drop\n // the watch instead of re-probing every tick (server-side cancel semantics\n // are AGE-410; this keeps the poller honest meanwhile).\n const run = (await deps.callTool(cfg.tokens.runner, \"get_harness\", {\n harnessRunId: ctx.harnessRunId,\n response_format: \"concise\",\n })) as { harness?: { status?: string } };\n const runStatus = run.harness?.status;\n if (runStatus === \"CANCELLED\" || runStatus === \"ARCHIVED\") {\n return { disposition: `run terminal (${runStatus}) \u2014 dropping watch` };\n }\n return { disposition: `not committable (stage ${status ?? \"?\"})` };\n }\n // The branch is read from the stage (the execution turn pinned it), so a resume\n // never re-resolves a different default-template branch. AGE-690: and if it did,\n // `ctx.taskKey` comes from this same job read, so the resolution no longer\n // depends on which channel woke the runner.\n const branch = resolveStageBranch(ctx);\n // Resolve the SAME per-job worktree the execution turn used: adopted when it\n // survived (the common case \u2014 a worktree survives validation/COMMIT gates), or\n // recreated from the stage-branch tip after a process restart that lost the dir.\n const cwd = await deps.worktree.ensureExecutionCwd(\n { repo, jobId: input.jobId, stageId: ctx.stageId, branch },\n ctx.executionBaseRef,\n );\n // The post-validation phase has no active M7 run to heartbeat, so freeze is read\n // FRESH via get_harness at every boundary (FreezeProbe.check()).\n const probe = new FreezeProbe(deps, cfg, ctx.harnessRunId);\n\n // RESUME after a freeze that landed AFTER the push but before the PR: the stage is\n // already COMMITTED (committed + pushed), so re-run ONLY the idempotent push/PR\n // leg (a re-push of the same branch is a no-op; PR-create defers to inbound\n // correlation when one already exists). Never re-commit a COMMITTED stage.\n if (status === \"COMMITTED\") {\n if (await probe.check()) return { disposition: \"frozen\" };\n const headSha = await currentHeadSha(deps, cwd);\n const result = await pushAfterAuthorized(\n deps,\n cfg,\n probe,\n ctx,\n { cwd, branch, commitSha: headSha, repo },\n // Already COMMITTED \u2014 push/PR is authorized; no need to wait.\n async () => \"authorized\",\n );\n // Fully delivered on resume (pushed, no freeze/deferral) \u2192 clean up; a deferred\n // resume RETAINS the worktree for the next attempt.\n if (result.pushed && !result.reason) {\n await maybeCleanupWorktree(deps, cfg, ctx, {\n branch,\n jobId: input.jobId,\n });\n }\n return {\n disposition: result.pushed\n ? \"committed_and_pushed (resume)\"\n : `committed; push ${result.reason} (resume)`,\n };\n }\n\n if (await probe.check()) {\n log(`[harness ${ctx.stageId}] frozen \u2014 deferring commit`);\n return { disposition: \"frozen\" };\n }\n try {\n return await driveHarnessCommit(deps, cfg, probe, ctx, {\n cwd,\n branch,\n jobId: input.jobId,\n });\n } catch (err) {\n if (err instanceof HarnessFrozenError) {\n log(err.message);\n return { disposition: \"frozen\" };\n }\n throw err;\n }\n}\n\n/** The current HEAD SHA (best-effort; empty string on failure). */\nasync function currentHeadSha(\n deps: Pick<HarnessRunnerDeps, \"git\">,\n cwd: string,\n): Promise<string> {\n try {\n return (await deps.git(cwd, [\"rev-parse\", \"HEAD\"])).trim();\n } catch {\n return \"\";\n }\n}\n", "/**\n * Worker capability declaration for the M13.4b claim/launch PREFLIGHT.\n *\n * Every governed claim (`claim_agent_job`) must PRESENT what this worker can\n * actually run so the control plane can refuse \u2014 with zero claims burned, before\n * any `AgentRun` is opened \u2014 a release that pins a model the installed SDK/binary\n * cannot execute. That is the exact `gpt-5.6-sol` incident: the account's selected\n * model needed a newer Codex runtime than the worker had installed, and the job\n * only failed at RUN TIME as an unhandled provider exception.\n *\n * The declaration is honest BY CONSTRUCTION: the worker always vouches for the\n * exact model it is about to launch (`claudeModel()` / `codexModel()`), so a\n * release pinning ANY other model is refused at preflight rather than blowing up\n * mid-turn. An operator whose installed runtime genuinely runs a broader set\n * BROADENS the list via env (per-provider, since Claude and Codex model names do\n * not overlap). The optional image/sandbox digests + code-snapshot inventory pass\n * through from env only when the operator stamps them; unset \u21D2 that dimension\n * reads as unverified server-side (never a false refusal).\n *\n * This closes the P0 for the CHECKED-IN runners: the gate no longer fires only for\n * hypothetical callers that opt into the optional field \u2014 the real runners opt in.\n */\n\n/** The `capabilities` object sent on `claim_agent_job` (matches ClaimAgentJobSchema.capabilities). */\nexport interface WorkerCapabilitiesDecl {\n /** Models this worker's installed SDK/binary can actually run \u2014 ALWAYS non-empty. */\n acceptedModels: string[];\n /** Installed SDK/binary revision (only when the operator stamps it). */\n sdkRevision?: string;\n /** Worker image digest (only when stamped). */\n workerImageDigest?: string;\n /** Sandbox base image digest (only when stamped). */\n sandboxBaseImageDigest?: string;\n /** Code-snapshot refs the worker can check out (only when stamped). */\n availableCodeSnapshots?: string[];\n}\n\n/** Parse a comma/whitespace-separated env list into a trimmed, non-empty array (or undefined). */\nfunction parseList(raw: string | undefined): string[] | undefined {\n if (!raw) return undefined;\n const items = raw\n .split(/[,\\s]+/)\n .map((s) => s.trim())\n .filter(Boolean);\n return items.length ? items : undefined;\n}\n\n/** A trimmed non-empty env string, or undefined. */\nfunction envString(raw: string | undefined): string | undefined {\n const v = raw?.trim();\n return v ? v : undefined;\n}\n\n/**\n * Build this worker's capability declaration for a claim.\n *\n * @param model The model the worker will actually launch for THIS role/turn \u2014 it\n * is always included in `acceptedModels`, because the worker can, by definition,\n * run the model it is about to invoke.\n * @param extraAcceptedModels Raw env value (e.g. `process.env.STACKS_CLAUDE_ACCEPTED_MODELS`)\n * listing additional models the operator's installed runtime can run. Per-provider\n * because Claude and Codex model names are disjoint \u2014 the caller picks the env.\n * @param env The environment to read the optional worker/image/sandbox stamps from\n * (defaults to `process.env`; injectable for tests).\n */\nexport function workerCapabilities(opts: {\n model: string;\n extraAcceptedModels?: string;\n env?: NodeJS.ProcessEnv;\n}): WorkerCapabilitiesDecl {\n const env = opts.env ?? process.env;\n // The worker ALWAYS vouches for the model it is launching (guarantees non-empty),\n // plus any operator-declared extras its installed runtime can also run.\n const extras = parseList(opts.extraAcceptedModels) ?? [];\n const acceptedModels = Array.from(new Set([opts.model, ...extras]));\n\n const decl: WorkerCapabilitiesDecl = { acceptedModels };\n\n const sdkRevision = envString(env.STACKS_SDK_REVISION);\n if (sdkRevision) decl.sdkRevision = sdkRevision;\n const workerImageDigest = envString(env.STACKS_WORKER_IMAGE_DIGEST);\n if (workerImageDigest) decl.workerImageDigest = workerImageDigest;\n const sandboxBaseImageDigest = envString(\n env.STACKS_SANDBOX_BASE_IMAGE_DIGEST,\n );\n if (sandboxBaseImageDigest)\n decl.sandboxBaseImageDigest = sandboxBaseImageDigest;\n const availableCodeSnapshots = parseList(env.STACKS_AVAILABLE_CODE_SNAPSHOTS);\n if (availableCodeSnapshots)\n decl.availableCodeSnapshots = availableCodeSnapshots;\n\n return decl;\n}\n", "import type { AgentProvider } from \"./jentrix.js\";\n\nexport type WorkflowRole = \"planner\" | \"executor\" | \"reviewer\";\n\nexport interface ExpectedRoleBinding {\n agentId: string;\n runtimeAdapterKey: AgentProvider;\n provider: string;\n providerConnectionId: string;\n model: string;\n source: \"active_release\" | \"worker_draft\";\n requiresClaimCredential: boolean;\n}\n\nexport type RunnerRoleBindings = Record<WorkflowRole, ExpectedRoleBinding>;\n\nexport interface ResolvedClaimExecution {\n runtimeAdapterKey: AgentProvider;\n providerConnectionId: string;\n model: string;\n generationControls: Record<string, unknown> | null;\n permissions: Record<string, unknown> | null;\n}\n\nfunction record(value: unknown): Record<string, unknown> | null {\n return value && typeof value === \"object\" && !Array.isArray(value)\n ? (value as Record<string, unknown>)\n : null;\n}\n\nfunction parseBinding(value: unknown, role: WorkflowRole): ExpectedRoleBinding {\n const row = record(value);\n if (!row)\n throw new Error(`RUNNER_CONFIG_INVALID: ${role} role binding is missing.`);\n for (const key of [\n \"agentId\",\n \"provider\",\n \"providerConnectionId\",\n \"model\",\n \"source\",\n ] as const) {\n if (typeof row[key] !== \"string\" || row[key].length === 0) {\n throw new Error(`RUNNER_CONFIG_INVALID: ${role}.${key} is missing.`);\n }\n }\n if (row.runtimeAdapterKey !== \"claude\" && row.runtimeAdapterKey !== \"codex\") {\n throw new Error(\n `RUNNER_CONFIG_INVALID: ${role} names an unknown runtime adapter.`,\n );\n }\n if (row.source !== \"active_release\" && row.source !== \"worker_draft\") {\n throw new Error(\n `RUNNER_CONFIG_INVALID: ${role} binding source is invalid.`,\n );\n }\n if (typeof row.requiresClaimCredential !== \"boolean\") {\n throw new Error(\n `RUNNER_CONFIG_INVALID: ${role}.requiresClaimCredential is missing.`,\n );\n }\n return row as unknown as ExpectedRoleBinding;\n}\n\nexport function parseRoleBindings(raw: string): RunnerRoleBindings {\n let value: unknown;\n try {\n value = JSON.parse(raw);\n } catch {\n throw new Error(\n \"RUNNER_CONFIG_INVALID: STACKS_RUNNER_ROLE_BINDINGS is not valid JSON.\",\n );\n }\n const row = record(value);\n if (!row)\n throw new Error(\"RUNNER_CONFIG_INVALID: role bindings must be an object.\");\n return {\n planner: parseBinding(row.planner, \"planner\"),\n executor: parseBinding(row.executor, \"executor\"),\n reviewer: parseBinding(row.reviewer, \"reviewer\"),\n };\n}\n\nexport function resolveClaimExecution(\n claim: Record<string, unknown>,\n expected: ExpectedRoleBinding,\n): ResolvedClaimExecution {\n const execution = record(claim.workerExecution);\n if (!execution) {\n throw new Error(\n \"ROLE_PLAN_UNSATISFIED: the claimed job has no durable worker execution binding; publish and activate a configured release.\",\n );\n }\n const adapter = execution.runtimeAdapterKey;\n const connectionId = execution.providerConnectionId;\n const model = execution.model;\n if (\n (adapter !== \"claude\" && adapter !== \"codex\") ||\n typeof connectionId !== \"string\" ||\n typeof model !== \"string\"\n ) {\n throw new Error(\n \"ROLE_PLAN_UNSATISFIED: the claim returned a malformed worker execution binding.\",\n );\n }\n if (\n adapter !== expected.runtimeAdapterKey ||\n connectionId !== expected.providerConnectionId ||\n model !== expected.model\n ) {\n throw new Error(\n `ROLE_PLAN_UNSATISFIED: claimed ${adapter}/${connectionId}/${model} does not match the configured durable ${expected.runtimeAdapterKey}/${expected.providerConnectionId}/${expected.model} binding.`,\n );\n }\n return {\n runtimeAdapterKey: adapter,\n providerConnectionId: connectionId,\n model,\n generationControls: record(execution.generationControls),\n permissions: record(execution.permissions),\n };\n}\n", "/**\n * Project-context injection for the three harness roles (planner, executor,\n * reviewer).\n *\n * Two gaps this closes, both observed on the M18 run:\n *\n * 1. CONVENTIONS. The Claude legs run with `settingSources: ['project']` so the\n * SDK loads the checkout's CLAUDE.md natively (see providers/claude.ts); the\n * Codex legs read AGENTS.md, which is a symlink to the same file. Neither is\n * guaranteed to be *noticed* \u2014 an explicit instruction naming the file as the\n * contract the reviewer enforces costs ~60 tokens and is the difference\n * between a turn that follows the repo's ops-core/MCP/enum rules and one that\n * re-invents them and gets rejected.\n *\n * 2. PARALLEL WORK. A stage worktree is cut from its base ref once and never\n * rebased, so commits landing on the base branch mid-run (harness fixes while\n * the same repo's PRD is being implemented \u2014 the M18 shape exactly) are\n * invisible to every role. Naming them keeps a role from re-fixing what was\n * already fixed, or from reasoning about a file the deployed server no longer\n * matches.\n *\n * Fail-soft by construction: every git read is best-effort, and a failure\n * degrades to the conventions block alone. A context builder must never be the\n * reason a turn dies.\n */\n\nexport interface ProjectContextDeps {\n /** Run a git command in `cwd` and return stdout (the runner's bounded RunGit). */\n git: (cwd: string, args: string[]) => Promise<string>;\n}\n\nexport type ProjectRole = \"planner\" | \"executor\" | \"reviewer\";\n\nexport interface ProjectContextInput {\n /** The role's checkout (worktree for the executor, read-only for the others). */\n cwd: string;\n /** The run's base branch. Defaults to `main` when the caller has none. */\n baseBranch?: string | null;\n role: ProjectRole;\n}\n\n/** W5: how far this checkout's lineage trails the run's base branch. */\nexport interface BaseDrift {\n /** Commits on the base branch that are not in this checkout's history. */\n behindBase: number;\n /** The base branch's tip sha (empty when the ref could not be read). */\n baseSha: string;\n /** This checkout's HEAD sha (empty when unreadable). */\n headSha: string;\n}\n\n/**\n * W5: measure drift between this checkout and the run's base branch. Stacking a\n * stage on an unmerged predecessor is CORRECT, so drift is not an error \u2014 it is\n * a fact that was previously invisible: while M18 stage 6 sat unmerged for two\n * days, `main` advanced five harness fixes and stage 7 planned against a stale\n * CLAUDE.md. Measured and surfaced; never auto-rebased (that stays an operator\n * act). Best-effort: an unreadable ref reports zero rather than failing a turn.\n */\nexport async function measureBaseDrift(\n deps: ProjectContextDeps,\n input: { cwd: string; baseBranch?: string | null },\n): Promise<BaseDrift> {\n const base = (input.baseBranch || \"main\").trim() || \"main\";\n const ref = `refs/remotes/origin/${base}`;\n const read = async (args: string[]): Promise<string> =>\n (await deps.git(input.cwd, args).catch(() => \"\")).trim();\n // `rev-list --count HEAD..<base>` is exactly \"commits on the base branch this\n // checkout does not have\" \u2014 it already accounts for the merge base, so a\n // stacked stage counts only what actually landed after its lineage diverged.\n const count = await read([\"rev-list\", \"--count\", `HEAD..${ref}`]);\n return {\n behindBase: Number.isFinite(Number(count)) ? Number(count) : 0,\n baseSha: await read([\"rev-parse\", ref]),\n headSha: await read([\"rev-parse\", \"HEAD\"]),\n };\n}\n\n/** How many parallel commits to name before summarizing the rest. */\nconst MAX_LISTED_COMMITS = 20;\n\nconst ROLE_LINE: Record<ProjectRole, string> = {\n planner:\n \"Plan WITHIN these conventions \u2014 a plan that proposes a second engine, a parallel store, or a new enum where the repo says otherwise is rejected before it is executed.\",\n executor:\n \"Implement WITHIN these conventions and do not re-fix what a parallel commit already fixed; read the current file before changing code a listed commit touched.\",\n reviewer:\n \"Judge the diff against these conventions as well as the plan \u2014 and do not raise as a defect something a listed parallel commit already resolved on the base branch.\",\n};\n\n/**\n * Build the injected context block for one role's turn. Returns \"\" only if\n * every section is empty (never throws).\n */\nexport async function buildProjectContext(\n deps: ProjectContextDeps,\n input: ProjectContextInput,\n): Promise<string> {\n const sections = [\n `CONVENTIONS \u2014 read \\`AGENT_GUIDELINES.md\\` at the checkout root FIRST: it is the operating contract for every agent in this repo (the non-negotiable invariants, the map of \\`src/server\\` subsystems, your role's authority limits, and the evidence rules), and it names where each rule is enforced. Then read \\`CLAUDE.md\\` (\\`AGENTS.md\\` is the same file) for the product-surface architecture it points to. For anything under \\`src/server/harness\\`, \\`src/server/workflows\\`, or \\`agents/\\`, \\`harness-specs/\\` is the SOURCE OF TRUTH for how the engine behaves \u2014 open \\`harness-specs/README.md\\` and read the file its index points you to BEFORE claiming a state, gate, refusal, or env var works a particular way, and update that spec in the same change when you alter engine behavior. A change that ignores any of these is rejected at review regardless of test results. ${ROLE_LINE[input.role]}`,\n ];\n\n const truth = await gitTruth(deps, input);\n if (truth) sections.push(truth);\n\n const parallel = await baseBranchDelta(deps, input);\n if (parallel) sections.push(parallel);\n\n return `\\n\\n## Project context (injected by the runner)\\n\\n${sections.join(\"\\n\\n\")}\\n`;\n}\n\n/**\n * W3: runner-computed GIT TRUTH for this turn \u2014 HEAD, how dirty the tree is, and\n * how far the checkout trails the base branch.\n *\n * A role that reasons about the tree from memory (or from a prior round's\n * summary) writes claims the attested ledger then contradicts; M18 stage 7's\n * executor \"audited instead of fixing\" partly because the state it reasoned\n * about lived in prose it could rationalize past. Naming the facts every turn is\n * the cheap half of the fix \u2014 the enforcing half is the hooks + the evidence\n * gate. Best-effort: unreadable git degrades to no section.\n */\nasync function gitTruth(\n deps: ProjectContextDeps,\n input: ProjectContextInput,\n): Promise<string | null> {\n const drift = await measureBaseDrift(deps, input);\n if (!drift.headSha) return null;\n const dirty = (\n await deps.git(input.cwd, [\"status\", \"--porcelain\"]).catch(() => \"\")\n )\n .split(\"\\n\")\n .map((l) => l.trim())\n .filter(Boolean);\n const base = (input.baseBranch || \"main\").trim() || \"main\";\n const drifted =\n drift.behindBase > 0\n ? `${drift.behindBase} commit(s) BEHIND \\`${base}\\`${drift.baseSha ? ` (${drift.baseSha.slice(0, 12)})` : \"\"}`\n : `up to date with \\`${base}\\``;\n return `GIT TRUTH (measured by the runner in this checkout, not remembered): HEAD is \\`${drift.headSha.slice(0, 12)}\\`, the tree has ${dirty.length} uncommitted change(s), and this checkout is ${drifted}. These are the facts your claims are checked against \u2014 the runner captures the diff from THIS tree and attests the verification commands itself.`;\n}\n\n/**\n * Commits on the base branch that this checkout does NOT have. Uses the local\n * remote-tracking ref \u2014 the worktree manager already fast-forwards it to the run\n * base, so this costs no network round-trip and a missing ref simply yields \"\".\n */\nasync function baseBranchDelta(\n deps: ProjectContextDeps,\n input: ProjectContextInput,\n): Promise<string | null> {\n const base = (input.baseBranch || \"main\").trim() || \"main\";\n const ref = `refs/remotes/origin/${base}`;\n const out = await deps\n .git(input.cwd, [\n \"log\",\n \"--oneline\",\n \"--no-decorate\",\n `-${MAX_LISTED_COMMITS + 1}`,\n `HEAD..${ref}`,\n ])\n .catch(() => \"\");\n const commits = out\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter(Boolean);\n if (commits.length === 0) return null;\n const listed = commits.slice(0, MAX_LISTED_COMMITS);\n const overflow =\n commits.length > MAX_LISTED_COMMITS\n ? `\\n \u2026and more \u2014 run \\`git log --oneline HEAD..${ref}\\` for the full list.`\n : \"\";\n return `PARALLEL WORK \u2014 \\`${base}\\` has moved since this branch was cut. ${listed.length}${overflow ? \"+\" : \"\"} commit(s) are on the base branch but NOT in your checkout, and the DEPLOYED server already has them:\\n ${listed.join(\"\\n \")}${overflow}`;\n}\n", "/**\n * Versioned role rubrics (Harness Reliability W7).\n *\n * The executor's evidence contract and the reviewer's disposition rubric used to\n * live as inline template literals in two different files \u2014 unversioned,\n * partially duplicated, and impossible to diff when a role's behavior changed.\n * They are runtime content injected into every role turn, so they live in THIS\n * repo (the one the runner clones), next to the runner that injects them.\n *\n * Injection stays explicit: the Agent SDK does not auto-discover skills, and the\n * Codex legs get their prompt assembled the same way.\n *\n * FAIL CLOSED on a missing rubric. A role turn that runs without its contract is\n * exactly the silent degradation this program exists to remove \u2014 a loud startup\n * error naming the path is strictly better than a turn that quietly reverts to\n * \"whatever the model assumes\".\n */\nimport { readFileSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nexport type RubricName = \"executor-evidence\" | \"reviewer-disposition\";\n\nconst RUBRIC_DIR = path.join(\n path.dirname(fileURLToPath(import.meta.url)),\n \"..\",\n \"rubrics\",\n);\n\nconst cache = new Map<RubricName, string>();\n\n/** The rubric's text, cached. Throws (naming the path) when it is missing. */\nexport function loadRubric(name: RubricName): string {\n const cached = cache.get(name);\n if (cached) return cached;\n const file = path.join(RUBRIC_DIR, `${name}.md`);\n let text: string;\n try {\n text = readFileSync(file, \"utf8\").trim();\n } catch {\n throw new Error(\n `Missing role rubric ${name} at ${file} \u2014 a role turn must never run without its contract. Restore agents/rubrics/ (it ships with the runner) and retry.`,\n );\n }\n if (!rubricVersion(text)) {\n throw new Error(\n `Role rubric ${name} at ${file} carries no version marker (<!-- rubric-version: ${name}/N -->); refusing to inject an unversioned contract.`,\n );\n }\n cache.set(name, text);\n return text;\n}\n\n/** The `<!-- rubric-version: name/N -->` marker, or null when absent. PURE. */\nexport function rubricVersion(text: string): string | null {\n return /<!--\\s*rubric-version:\\s*([^\\s]+)\\s*-->/.exec(text)?.[1] ?? null;\n}\n", "/**\n * The runner's checkout-access lane, keyed off the DURABLE run role (M18.3 R7).\n *\n * ZERO IMPORTS, ON PURPOSE \u2014 three things depend on it and each one breaks if a\n * single import lands here:\n *\n * 1. **The dependency firewall stays intact.** `agents/` is its own pnpm package\n * with its own lockfile, excluded from the app's tsconfig and eslint. A module\n * with no imports can be read by the app's test suite across that firewall\n * WITHOUT dragging the Claude/Codex SDKs into the app's dependency graph.\n * 2. **The frozen root suite can EXECUTE it.** `src/server/harness/validator-semantics.test.ts`\n * imports this file directly and runs every case in-process. That suite rides\n * the stage's frozen verification commands, so the decision below is\n * runner-attested rather than asserted in executor prose. (`pnpm typecheck`\n * type-checks this file as an imported file \u2014 tsconfig `exclude` filters the\n * default include glob, never files reached through an import.)\n * 3. **There is exactly one copy of the rule per side.** The table below must\n * equal `REPO_ACCESS_BY_DISPATCH_ROLE` in `src/server/harness/validator-semantics.ts`\n * entry-for-entry, including the fail-closed default. That equality is\n * asserted by the attested suite, so drift is a red test, not a silent\n * divergence between what the control plane promises and what the runner does.\n *\n * WHY THIS EXISTS. A claim is the one doorway where an attempt is handed both its\n * Jentrix authority and \u2014 on the runner's side of that answer \u2014 its checkout.\n * Nothing downstream can take a writable worktree back once it has been handed\n * over, so \"this attempt may not mutate the repository\" is not something a later\n * boundary can retrofit; it is a property of how the attempt was DISPATCHED. The\n * runner used to decide that from the leg's SHAPE (`isExecution` / `isReviewer`,\n * derived from the job phase). This module moves the decision onto the durable\n * identity the control plane returns from `claim_agent_job` \u2014 `AgentRun.role` \u2014\n * so every leg the deployed runner drives resolves its checkout the same way,\n * through one total, fail-closed function.\n *\n * FAIL-CLOSED IS THE LOAD-BEARING PART. The map is TOTAL: a role it does not\n * recognize \u2014 VALIDATOR, a role a later milestone adds, a typo, an empty string\n * from a control plane that stopped returning the field \u2014 resolves to READ-ONLY,\n * ADOPT-ONLY. A writable worktree is only ever handed out by an entry that says\n * so in so many words. That is what makes the guarantee survive a change nobody\n * remembered to update this file for: the new thing is read-only until someone\n * deliberately writes it down here, and writing it down means the attested\n * mirror-conformance test forces the same entry into the server's table.\n */\n\n/** How a dispatched attempt may touch the repository checkout. */\nexport interface RepoAccess {\n /** `read-write` is the ONLY mode that may provision or mutate a worktree. */\n readonly mode: \"read-write\" | \"read-only\";\n /**\n * May the dispatcher CREATE the attempt's worktree (`ensureExecutionCwd` /\n * `git worktree add`)? False means adopt-an-existing-tree or nothing \u2014 the\n * runner never brings a writable checkout into being for this role.\n */\n readonly provisionWorktree: boolean;\n /**\n * The flag the provider sandboxes already enforce (`lib/providers/claude.ts`\n * withholds the write/edit tools; `lib/providers/codex.ts` runs the shell under\n * a read-only sandbox). Passed straight through to the model session.\n */\n readonly repoReadOnly: boolean;\n /** May this attempt author a repository mutation (local commit, push, PR)? */\n readonly canCommit: boolean;\n}\n\n/** A writable worktree \u2014 the executor lane, and the only one there is. */\nconst READ_WRITE: RepoAccess = {\n mode: \"read-write\",\n provisionWorktree: true,\n repoReadOnly: false,\n canCommit: true,\n};\n\n/**\n * Read-only, adopt-only. The planner and reviewer legs already ran this way\n * (they read a checkout they never provision); a VALIDATOR attempt runs here\n * too, and so does anything unrecognized.\n */\nconst READ_ONLY: RepoAccess = {\n mode: \"read-only\",\n provisionWorktree: false,\n repoReadOnly: true,\n canCommit: false,\n};\n\n/**\n * The authority table. MIRROR of `REPO_ACCESS_BY_DISPATCH_ROLE` in\n * `src/server/harness/validator-semantics.ts` \u2014 keep them identical.\n *\n * EXECUTOR is the single read-write entry: an execution turn implements the\n * change, so it gets the writable worktree it always got (byte-for-byte today's\n * behavior). PLANNER and REVIEWER are read-only, which is also exactly what they\n * do today \u2014 they are listed explicitly rather than left to the default so that\n * the table states the whole shipped world and a future edit to the default\n * cannot silently change them.\n */\nexport const REPO_ACCESS_BY_ROLE: Readonly<Record<string, RepoAccess>> = {\n EXECUTOR: READ_WRITE,\n PLANNER: READ_ONLY,\n REVIEWER: READ_ONLY,\n VALIDATOR: READ_ONLY,\n};\n\n/**\n * What an UNRECOGNIZED role gets. Read-only, adopt-only \u2014 never a writable\n * worktree. See the header: this is the entry that makes the guarantee hold for\n * roles this file has never heard of.\n */\nexport const FAIL_CLOSED_REPO_ACCESS: RepoAccess = READ_ONLY;\n\n/**\n * The total function every dispatch path calls. Null, undefined, an empty\n * string, an unknown role \u2014 all read-only. Case-sensitive on purpose: the\n * control plane returns the enum name verbatim, and quietly normalizing a\n * near-miss like \"executor\" into the writable lane is exactly the kind of\n * helpfulness that hands out a checkout nobody authorized.\n */\nexport function repoAccessForRole(role: string | null | undefined): RepoAccess {\n if (typeof role !== \"string\") return FAIL_CLOSED_REPO_ACCESS;\n const entry = Object.prototype.hasOwnProperty.call(REPO_ACCESS_BY_ROLE, role)\n ? REPO_ACCESS_BY_ROLE[role]\n : undefined;\n return entry ?? FAIL_CLOSED_REPO_ACCESS;\n}\n\n/**\n * The operator-facing diagnostic when a read-only attempt has no tree to adopt.\n *\n * The read-only lane must NEVER degrade to \"create one instead\" (that is the\n * writable lane it was just refused) or to \"read the shared checkout\" (which\n * lacks the stage's uncommitted change, so any verdict it produces is about the\n * wrong tree \u2014 the same fail-closed rule the harness reviewer leg already\n * follows). Parking the attempt with this sentence is the honest third option.\n */\nexport function missingReadOnlyCheckoutReason(ctx: {\n role: string | null | undefined;\n stageId: string;\n}): string {\n return (\n `A ${String(ctx.role ?? \"(unset)\")} attempt on stage ${ctx.stageId} runs read-only (M18.3 R7), so it may ` +\n \"adopt an existing worktree but never create one \u2014 and no worktree for this stage exists to adopt. \" +\n \"Refusing to fall back to a writable checkout (that is the lane this role was denied) or to the shared \" +\n \"grounding checkout (which lacks the stage's uncommitted changes, so any verdict would describe the \" +\n \"wrong tree). Run the stage's executor assignment first so the tree exists, then re-run this attempt.\"\n );\n}\n", "/**\n * Reference-runner worktree manager (Concurrent Harness Execution PRD, Stage 3).\n *\n * S1 (`packages/execution/src/worktree.ts`) is the dependency-free MECHANICS\n * (path derivation, create/adopt/detach/cleanup, marker validation, containment).\n * THIS module is the reference runner's POLICY layer on top of it \u2014 the part that\n * needs the runner's git seam AND fresh Jentrix state:\n *\n * \u2022 per-repo config: STACKS_RUNNER_REPOS stays back-compatible with string\n * values (\"owner/name\" -> checkout) and also accepts an operator object\n * { cwd, bootstrap:[[argv]], copyIgnoredFiles, worktreeRoot } (parseRunnerRepos);\n * \u2022 ensureExecutionCwd \u2014 the per-job worktree the executor/commit turn works in:\n * prune FIRST (amendment b), adopt this job's own worktree on restart, else run\n * the branch-OWNERSHIP check before creating on a shared stage branch, then\n * create/adopt, run idempotent bootstrap argv, and copy allowlisted ignored\n * config (owner-only, git-check-ignore confirmed);\n * \u2022 adoptExecutionCwd \u2014 read-only adoption for the reviewer + a commit resume;\n * \u2022 cleanupExecutionWorktree \u2014 the S1 safe cleanup, caller-gated to a terminal\n * Jentrix state (git clean -fdX ignored + `git worktree remove` + prune, source-\n * dirty retained);\n * \u2022 list \u2014 the operator listing (repo/job/stage/age/source-cleanliness).\n *\n * The runner NEVER assumes a branch template is globally unique: because the\n * null/legacy fallback `harness/{taskKey}-stage-{number}` and the current stage-id\n * `{slug}` substitution let legacy, null, custom, and same-anchor runs resolve to\n * the SAME branch, ensureExecutionCwd applies the ownership check on THAT headline\n * multi-harness path \u2014 a collision with a live or unprovable attempt is rejected\n * with the owning branch/job named, and no checkout is reset, renamed, or stolen.\n */\nimport { execFile } from \"node:child_process\";\nimport { constants as fsConstants, existsSync, realpathSync } from \"node:fs\";\nimport { chmod, copyFile, mkdir, readdir, stat } from \"node:fs/promises\";\nimport * as path from \"node:path\";\nimport { promisify } from \"node:util\";\n\nimport {\n adoptWorktree,\n checkpointWorktree,\n cleanupWorktree,\n createWorktree,\n detachSupersededWorktree,\n readMarker,\n resolveWorktreePaths,\n WorktreeError,\n type CheckpointResult,\n type CleanupResult,\n type RunGit,\n type WorktreeIdentity,\n type WorktreeMarker,\n type WorktreeRepoConfig,\n} from \"../../packages/execution/src/worktree.js\";\n\nconst execFileP = promisify(execFile);\n\n/** One configured repository: the S1 path config plus the runner's per-repo\n * operator options (bootstrap argv + ignored-config allowlist). */\nexport interface RunnerRepoEntry {\n config: WorktreeRepoConfig;\n /** argv arrays run in the worktree AFTER containment/ownership validation.\n * Idempotent by contract (may re-run on adoption). Empty by default. */\n bootstrap: string[][];\n /** Repo-relative paths of IGNORED config to copy into a fresh worktree, each\n * re-confirmed ignored by `git check-ignore` at copy time. Empty by default \u2014\n * no ignored file is copied unless explicitly allowlisted. */\n copyIgnoredFiles: string[];\n}\n\n/** The four identifiers that key + validate an attempt's worktree at the runner\n * boundary (a superset-free view of the S1 WorktreeIdentity). */\nexport interface StageWorktreeIdentity {\n repo: string;\n jobId: string;\n stageId: string;\n branch: string;\n}\n\n/** A runner-owned worktree row for the operator listing (LOCAL paths \u2014 printed to\n * stdout for a human, NEVER persisted into Jentrix activity or artifacts). */\nexport interface RunnerWorktreeInfo {\n repo: string;\n jobId: string;\n stageId: string;\n branch: string;\n status: WorktreeMarker[\"status\"];\n /** Absolute local path (operator-facing only). */\n dir: string;\n /** Age of the worktree (ms) from its marker mtime. */\n ageMs: number;\n /** True when `git status --porcelain` is non-empty (tracked changes or non-\n * ignored untracked files) \u2014 retained by cleanup, needs a manual decision. */\n sourceDirty: boolean;\n /** Present when git no longer has a live worktree at `dir` (orphaned/prunable). */\n orphaned: boolean;\n}\n\n/** The verdict of reading FRESH Jentrix state for a branch's current owner. */\nexport type OwnerVerdict =\n | { status: \"live\"; detail: string }\n | { status: \"superseded\"; detail: string }\n | { status: \"unprovable\"; detail: string };\n\n/**\n * Read FRESH Jentrix state to decide whether the OLD attempt that owns a colliding\n * stage branch is still the live/current owner, is confirmed superseded, or is\n * unprovable. Injected so the manager stays testable and the \"read fresh Jentrix\n * state\" concern lives in ONE wired place (the runner's callTool). `current` is the\n * attempt asking to reuse the branch (this runner's claimed job).\n */\nexport type OwnerStateReader = (\n owner: { jobId: string; stageId: string; branch: string },\n current: { jobId: string; stageId: string },\n) => Promise<OwnerVerdict>;\n\n/** Run an arbitrary bootstrap argv in a cwd (spawn seam; git is separate). */\nexport type RunCommand = (cwd: string, argv: string[]) => Promise<void>;\n\nconst defaultRunCommand: RunCommand = async (cwd, argv) => {\n await execFileP(argv[0], argv.slice(1), {\n cwd,\n maxBuffer: 64 * 1024 * 1024,\n });\n};\n\n/** A fail-closed ownership error \u2014 the branch's owner is live or unprovable, so the\n * worktree/branch is left untouched (never reset, renamed, or stolen).\n * `CHECKPOINT_FAILED` (W1) is the same posture applied to work rather than to the\n * branch: the superseded attempt's uncommitted diff could not be rescued onto the\n * branch, so the claim is refused loudly instead of silently overwriting it. */\nexport class WorktreeOwnershipError extends Error {\n constructor(\n readonly code: \"LIVE_CONFLICT\" | \"UNPROVABLE\" | \"CHECKPOINT_FAILED\",\n message: string,\n ) {\n super(message);\n this.name = \"WorktreeOwnershipError\";\n }\n}\n\n/** What the reference runner depends on for per-job worktree lifecycle. */\nexport interface WorktreeManager {\n /** Fast-forward the shared read-only grounding checkout to the run base. */\n refreshGroundingCheckout(repo: string, baseBranch: string): Promise<string>;\n /** Create/adopt this job's worktree and return its absolute dir: prune first,\n * adopt on restart, else ownership-check + create on the stage branch, then run\n * idempotent bootstrap + copy allowlisted ignored config. */\n ensureExecutionCwd(\n identity: StageWorktreeIdentity,\n executionBaseRef: string,\n ): Promise<string>;\n /** Adopt an EXISTING worktree (reviewer read-only / commit resume). Returns its\n * dir, or null when absent. No create / bootstrap / copy. */\n adoptExecutionCwd(identity: StageWorktreeIdentity): Promise<string | null>;\n /** W1: commit a parked attempt's dirty tree onto its stage branch so the park is\n * LOSSLESS. Clean tree \u21D2 no commit; a worktree that cannot reach the branch\n * (detached/other branch) throws rather than stranding the work silently. */\n checkpointExecutionCwd(\n identity: StageWorktreeIdentity,\n message: string,\n ): Promise<CheckpointResult>;\n /** Safe cleanup (caller-gated to a terminal Jentrix state with no active run). */\n cleanupExecutionWorktree(\n identity: StageWorktreeIdentity,\n ): Promise<CleanupResult>;\n /** Operator listing of runner-owned worktrees (absolute paths \u2014 stdout only). */\n list(): Promise<RunnerWorktreeInfo[]>;\n}\n\n/** One entry parsed from `git worktree list --porcelain`. */\ninterface GitWorktreeRow {\n path: string;\n branch: string | null;\n detached: boolean;\n}\n\n/**\n * Parse STACKS_RUNNER_REPOS. Back-compatible with string values (\"owner/name\" ->\n * checkout path) and also accepts the operator object form. Throws a legible error\n * on a malformed entry rather than silently dropping config.\n */\nexport function parseRunnerRepos(\n raw: unknown,\n): Record<string, RunnerRepoEntry> {\n const out: Record<string, RunnerRepoEntry> = {};\n if (raw == null) return out;\n if (typeof raw !== \"object\" || Array.isArray(raw)) {\n throw new Error(\n \"STACKS_RUNNER_REPOS must be a JSON object mapping 'owner/name' -> checkout | { cwd, bootstrap, copyIgnoredFiles }.\",\n );\n }\n for (const [repo, value] of Object.entries(raw as Record<string, unknown>)) {\n if (typeof value === \"string\") {\n out[repo] = {\n config: { repo, checkout: value },\n bootstrap: [],\n copyIgnoredFiles: [],\n };\n continue;\n }\n if (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n throw new Error(\n `STACKS_RUNNER_REPOS['${repo}'] must be a checkout path string or an object { cwd, ... }.`,\n );\n }\n const obj = value as Record<string, unknown>;\n const cwd = obj.cwd;\n if (typeof cwd !== \"string\" || !cwd.trim()) {\n throw new Error(\n `STACKS_RUNNER_REPOS['${repo}'].cwd must be a non-empty checkout path.`,\n );\n }\n const bootstrap = parseBootstrap(repo, obj.bootstrap);\n const copyIgnoredFiles = parseCopyIgnored(repo, obj.copyIgnoredFiles);\n const worktreeRoot =\n typeof obj.worktreeRoot === \"string\" && obj.worktreeRoot.trim()\n ? obj.worktreeRoot\n : undefined;\n out[repo] = {\n config: {\n repo,\n checkout: cwd,\n ...(worktreeRoot ? { worktreeRoot } : {}),\n },\n bootstrap,\n copyIgnoredFiles,\n };\n }\n return out;\n}\n\nfunction parseBootstrap(repo: string, value: unknown): string[][] {\n if (value == null) return [];\n if (!Array.isArray(value)) {\n throw new Error(\n `STACKS_RUNNER_REPOS['${repo}'].bootstrap must be an array of argv arrays.`,\n );\n }\n return value.map((argv, i) => {\n if (\n !Array.isArray(argv) ||\n argv.length === 0 ||\n !argv.every((a) => typeof a === \"string\")\n ) {\n throw new Error(\n `STACKS_RUNNER_REPOS['${repo}'].bootstrap[${i}] must be a non-empty array of string args.`,\n );\n }\n return argv as string[];\n });\n}\n\nfunction parseCopyIgnored(repo: string, value: unknown): string[] {\n if (value == null) return [];\n if (!Array.isArray(value) || !value.every((v) => typeof v === \"string\")) {\n throw new Error(\n `STACKS_RUNNER_REPOS['${repo}'].copyIgnoredFiles must be an array of repo-relative path strings.`,\n );\n }\n return value as string[];\n}\n\n/** Derive the owner\u2192checkout map the generic (non-worktree) drive path still uses. */\nexport function checkoutMap(\n entries: Record<string, RunnerRepoEntry>,\n): Record<string, string> {\n return Object.fromEntries(\n Object.entries(entries).map(([repo, e]) => [repo, e.config.checkout]),\n );\n}\n\n/** Reference-runner worktree manager over the S1 mechanics + a git seam + a fresh\n * Jentrix-state reader. */\nexport class RunnerWorktreeManager implements WorktreeManager {\n constructor(\n private readonly entries: Record<string, RunnerRepoEntry>,\n private readonly runGit: RunGit,\n private readonly readOwnerState: OwnerStateReader,\n private readonly opts: {\n runCommand?: RunCommand;\n log?: (msg: string) => void;\n } = {},\n ) {}\n\n private entryFor(repo: string): RunnerRepoEntry {\n const entry = this.entries[repo];\n if (!entry) {\n throw new Error(\n `No STACKS_RUNNER_REPOS entry for ${repo} \u2014 cannot resolve a worktree.`,\n );\n }\n return entry;\n }\n\n private wtId(identity: StageWorktreeIdentity): WorktreeIdentity {\n return {\n repo: identity.repo,\n jobId: identity.jobId,\n stageId: identity.stageId,\n branch: identity.branch,\n };\n }\n\n async refreshGroundingCheckout(\n repo: string,\n baseBranch: string,\n ): Promise<string> {\n const entry = this.entryFor(repo);\n const branch = baseBranch.trim() || \"main\";\n const remoteRef = `refs/remotes/origin/${branch}`;\n await this.runGit(entry.config.checkout, [\n \"fetch\",\n \"origin\",\n `+refs/heads/${branch}:${remoteRef}`,\n ]);\n await this.runGit(entry.config.checkout, [\"merge\", \"--ff-only\", remoteRef]);\n const [head, baseHead] = await Promise.all([\n this.runGit(entry.config.checkout, [\"rev-parse\", \"HEAD\"]),\n this.runGit(entry.config.checkout, [\"rev-parse\", remoteRef]),\n ]);\n if (head !== baseHead) {\n throw new Error(\n `grounding checkout HEAD ${head.slice(0, 12)} did not reach ${branch} ${baseHead.slice(0, 12)}`,\n );\n }\n return entry.config.checkout;\n }\n\n async ensureExecutionCwd(\n identity: StageWorktreeIdentity,\n executionBaseRef: string,\n ): Promise<string> {\n const entry = this.entryFor(identity.repo);\n const wtId = this.wtId(identity);\n const { dir } = resolveWorktreePaths(entry.config, wtId);\n\n // (1) Prune FIRST (amendment b) \u2014 reconcile any manually-removed worktree so a\n // stale registration can't wedge the stage branch before the ownership check.\n await this.runGit(entry.config.checkout, [\"worktree\", \"prune\"]);\n\n if (existsSync(dir)) {\n // This job's OWN worktree already exists (restart / same-job revision turn):\n // adopt it (marker + git must agree, else S1 fails closed) and re-run the\n // idempotent bootstrap/copy.\n const res = await adoptWorktree({\n config: entry.config,\n identity: wtId,\n runGit: this.runGit,\n });\n await this.bootstrapAndCopy(entry, res.dir);\n return res.dir;\n }\n\n // Fresh worktree for this job. The stage branch may be owned by ANOTHER\n // attempt's worktree (retry, or a same-anchor/legacy/null-template collision):\n // resolve ownership from durable Git metadata + fresh Jentrix state BEFORE\n // touching the branch. detach-on-superseded is the only mutation it performs.\n await this.ownershipCheckBeforeRetry(entry, wtId);\n\n const res = await createWorktree({\n config: entry.config,\n identity: wtId,\n executionBaseRef,\n runGit: this.runGit,\n });\n await this.bootstrapAndCopy(entry, res.dir);\n return res.dir;\n }\n\n async adoptExecutionCwd(\n identity: StageWorktreeIdentity,\n ): Promise<string | null> {\n const entry = this.entryFor(identity.repo);\n const wtId = this.wtId(identity);\n // Prune first so a manually-removed worktree reads as absent (null), not as a\n // spurious adoption failure.\n await this.runGit(entry.config.checkout, [\"worktree\", \"prune\"]);\n const { dir } = resolveWorktreePaths(entry.config, wtId);\n if (!existsSync(dir)) return null;\n const res = await adoptWorktree({\n config: entry.config,\n identity: wtId,\n runGit: this.runGit,\n });\n return res.dir;\n }\n\n async checkpointExecutionCwd(\n identity: StageWorktreeIdentity,\n message: string,\n ): Promise<CheckpointResult> {\n const entry = this.entryFor(identity.repo);\n return checkpointWorktree({\n config: entry.config,\n identity: this.wtId(identity),\n message,\n runGit: this.runGit,\n });\n }\n\n async cleanupExecutionWorktree(\n identity: StageWorktreeIdentity,\n ): Promise<CleanupResult> {\n const entry = this.entryFor(identity.repo);\n return cleanupWorktree({\n config: entry.config,\n identity: this.wtId(identity),\n runGit: this.runGit,\n });\n }\n\n async list(): Promise<RunnerWorktreeInfo[]> {\n const rows: RunnerWorktreeInfo[] = [];\n for (const entry of Object.values(this.entries)) {\n // `git worktree list` reflects LIVE registrations\u2026\n const live = await this.listGitWorktrees(entry.config.checkout).catch(\n () => [] as GitWorktreeRow[],\n );\n const liveByRealDir = new Map<string, GitWorktreeRow>();\n for (const w of live) {\n liveByRealDir.set(realDirKey(w.path), w);\n }\n // \u2026but the ownership MARKERS on disk are the source of truth for what the\n // runner owns. Enumerate every sibling marker (not just the ones a live\n // worktree registration still points at), so a STALE marker whose worktree\n // registration/path is gone \u2014 a manual `rm -rf`, or a `git worktree remove`\n // that lost the marker \u2014 is reported ORPHANED for manual cleanup instead of\n // silently vanishing because `git worktree list` no longer shows it.\n const base = path.dirname(\n resolveWorktreePaths(entry.config, MARKER_SCAN_IDENTITY).dir,\n );\n for (const markerPath of await listMarkerFiles(base)) {\n const marker = await readMarker(markerPath).catch(() => null);\n if (!marker || marker.repo !== entry.config.repo) continue;\n // S1 derives dir + marker as `<base>/<jobId>` and\n // `<base>/<jobId>.marker.json`, so the worktree dir is the marker path\n // minus the `.marker.json` sibling suffix.\n const dir = markerPath.slice(0, -MARKER_SUFFIX.length);\n const present = existsSync(dir);\n // Orphaned when git no longer has a live worktree at the dir OR the dir\n // itself is gone \u2014 either way the marker outlived its worktree.\n const orphaned = !liveByRealDir.has(realDirKey(dir)) || !present;\n const sourceDirty = present ? await this.isSourceDirty(dir) : false;\n rows.push({\n repo: marker.repo,\n jobId: marker.jobId,\n stageId: marker.stageId,\n branch: marker.branch,\n status: marker.status,\n dir,\n ageMs: await markerAgeMs(markerPath),\n sourceDirty,\n orphaned,\n });\n }\n }\n return rows;\n }\n\n // -------------------------------------------------------------------------\n // Ownership check (retry / same-anchor branch collision).\n // -------------------------------------------------------------------------\n\n private async ownershipCheckBeforeRetry(\n entry: RunnerRepoEntry,\n wtId: WorktreeIdentity,\n ): Promise<void> {\n const ourDir = safeRealpath(resolveWorktreePaths(entry.config, wtId).dir);\n const live = await this.listGitWorktrees(entry.config.checkout);\n // Any OTHER worktree with our target branch checked out is a collision \u2014 the\n // runner NEVER assumes the branch template is globally unique.\n const conflict = live.find(\n (w) => w.branch === wtId.branch && safeRealpath(w.path) !== ourDir,\n );\n if (!conflict) return; // no live checkout holds the branch \u2014 safe to create\n\n // Resolve the owner marker (a SIBLING of the conflicting worktree dir). A\n // worktree that holds the branch but has no runner marker (e.g. the main\n // checkout, or a foreign worktree) is UNPROVABLE \u2014 fail closed, steal nothing.\n const markerPath = markerPathFor(conflict.path);\n const marker = existsSync(markerPath)\n ? await readMarker(markerPath).catch(() => null)\n : null;\n if (!marker || marker.branch !== wtId.branch) {\n throw new WorktreeOwnershipError(\n \"UNPROVABLE\",\n `Stage branch ${wtId.branch} is checked out at ${conflict.path}, which carries no resolvable runner ownership marker; refusing to reset/rename/steal it. Free that checkout manually, then retry job ${wtId.jobId}.`,\n );\n }\n if (marker.jobId === wtId.jobId) return; // somehow ours (dir differed) \u2014 no-op\n\n // Read FRESH Jentrix state for the owning attempt.\n let verdict: OwnerVerdict;\n try {\n verdict = await this.readOwnerState(\n {\n jobId: marker.jobId,\n stageId: marker.stageId,\n branch: wtId.branch,\n },\n { jobId: wtId.jobId, stageId: wtId.stageId },\n );\n } catch (err) {\n throw new WorktreeOwnershipError(\n \"UNPROVABLE\",\n `Could not read Jentrix state for the attempt (job ${marker.jobId}, stage ${marker.stageId}) owning branch ${wtId.branch}: ${\n err instanceof Error ? err.message : String(err)\n }. Failing closed \u2014 the worktree at ${conflict.path} is unchanged.`,\n );\n }\n\n if (verdict.status === \"live\") {\n throw new WorktreeOwnershipError(\n \"LIVE_CONFLICT\",\n `Stage branch ${wtId.branch} is owned by a live attempt (job ${marker.jobId}, stage ${marker.stageId}) at ${conflict.path} \u2014 ${verdict.detail}. Refusing to reset/rename/steal it; resolve or supersede that attempt before retrying job ${wtId.jobId}.`,\n );\n }\n if (verdict.status === \"unprovable\") {\n throw new WorktreeOwnershipError(\n \"UNPROVABLE\",\n `Ownership of stage branch ${wtId.branch} (job ${marker.jobId}, stage ${marker.stageId}) is unprovable \u2014 ${verdict.detail}. Failing closed; the worktree at ${conflict.path} is unchanged.`,\n );\n }\n\n // W1 claim-time rescue: the superseded attempt parked (or its runner died)\n // without reaching a commit gate, so its worktree may still hold uncommitted\n // work. Detaching preserves those files ON DISK but leaves them off the\n // branch \u2014 the fresh worktree below checks the branch out at a tip that has\n // none of them, and the diff becomes invisible to every reviewer and gate.\n // Checkpoint it onto the branch FIRST, while the old worktree still has that\n // branch attached. If the checkpoint cannot reach the branch, refuse the\n // claim with the path named: parking loudly beats losing work silently.\n const rescued = await this.rescueSupersededWork(entry, marker, wtId);\n\n // Confirmed superseded \u2192 detach the OLD worktree (files preserved, marker\n // stamped superseded-detached), which frees the branch for our fresh worktree\n // to reuse. detachSupersededWorktree re-validates the marker before touching it.\n this.opts.log?.(\n `[harness-worktree] branch ${wtId.branch} superseded (${verdict.detail}) \u2014 ${rescued}detaching old worktree (job ${marker.jobId}) to reuse the branch for job ${wtId.jobId}`,\n );\n await detachSupersededWorktree({\n config: entry.config,\n identity: {\n repo: marker.repo,\n jobId: marker.jobId,\n stageId: marker.stageId,\n branch: marker.branch,\n },\n runGit: this.runGit,\n });\n }\n\n /**\n * W1: checkpoint a confirmed-superseded attempt's dirty tree onto the stage\n * branch before the detach that would strand it. Returns a log fragment naming\n * what was rescued (empty when there was nothing to rescue). A checkpoint that\n * cannot reach the branch REFUSES the claim \u2014 the work stays on disk, named in\n * the error, and a human reconciles it; overwriting it silently is the defect\n * this exists to kill.\n */\n private async rescueSupersededWork(\n entry: RunnerRepoEntry,\n marker: WorktreeMarker,\n wtId: WorktreeIdentity,\n ): Promise<string> {\n const oldIdentity: WorktreeIdentity = {\n repo: marker.repo,\n jobId: marker.jobId,\n stageId: marker.stageId,\n branch: marker.branch,\n };\n let res: CheckpointResult;\n try {\n res = await checkpointWorktree({\n config: entry.config,\n identity: oldIdentity,\n message: `harness checkpoint: stage ${marker.stageId} job ${marker.jobId} (claim-time rescue by job ${wtId.jobId})`,\n runGit: this.runGit,\n });\n } catch (err) {\n const oldDir = resolveWorktreePaths(entry.config, oldIdentity).dir;\n throw new WorktreeOwnershipError(\n \"CHECKPOINT_FAILED\",\n `Stage branch ${wtId.branch} is held by a superseded attempt (job ${marker.jobId}) whose uncommitted work at ${oldDir} could NOT be checkpointed onto the branch: ${\n err instanceof Error ? err.message : String(err)\n } Refusing the claim for job ${wtId.jobId} rather than reusing the branch and losing that work \u2014 reconcile ${oldDir} by hand, then retry.`,\n );\n }\n if (!res.committed) return \"\";\n this.opts.log?.(\n `[harness-worktree] rescued ${res.files?.length ?? 0} uncommitted path(s) from superseded job ${marker.jobId} onto ${marker.branch} (${res.sha?.slice(0, 12)})`,\n );\n return `rescued ${res.files?.length ?? 0} uncommitted path(s) onto the branch, `;\n }\n\n // -------------------------------------------------------------------------\n // Bootstrap + ignored-config copy (fresh + idempotent-on-adoption).\n // -------------------------------------------------------------------------\n\n private async bootstrapAndCopy(\n entry: RunnerRepoEntry,\n dir: string,\n ): Promise<void> {\n // Copy the allowlisted ignored config FIRST (a bootstrap step may consume it,\n // e.g. a .env the install/build reads), THEN run bootstrap. Both only after\n // the worktree passed containment/ownership validation above.\n await this.copyIgnoredConfig(entry, dir);\n await this.runBootstrap(entry, dir);\n }\n\n private async runBootstrap(\n entry: RunnerRepoEntry,\n dir: string,\n ): Promise<void> {\n const run = this.opts.runCommand ?? defaultRunCommand;\n for (const argv of entry.bootstrap) {\n if (argv.length === 0) continue;\n // Idempotent by contract (may re-run on adoption). Never logged with args\n // beyond the command name (an argv could carry a secret).\n this.opts.log?.(`[harness-worktree] bootstrap: ${argv[0]} \u2026`);\n await run(dir, argv);\n }\n }\n\n private async copyIgnoredConfig(\n entry: RunnerRepoEntry,\n dir: string,\n ): Promise<void> {\n if (entry.copyIgnoredFiles.length === 0) return; // nothing copied by default\n let copied = 0;\n for (const rel of entry.copyIgnoredFiles) {\n // Repo-relative only \u2014 reject absolute paths + `..` traversal outright.\n if (path.isAbsolute(rel) || rel.split(/[\\\\/]+/).includes(\"..\")) {\n throw new Error(\n `copyIgnoredFiles entry ${JSON.stringify(rel)} must be a repo-relative path with no '..'.`,\n );\n }\n const src = path.join(entry.config.checkout, rel);\n if (!existsSync(src)) continue; // absent source \u2014 nothing to copy\n // `git check-ignore` MUST confirm the path is ignored \u2014 never copy a tracked\n // file (that would shadow real source in the worktree).\n if (!(await this.isIgnored(entry.config.checkout, rel))) continue;\n const dest = path.join(dir, rel);\n assertUnder(dir, dest); // dest can never escape the worktree\n await mkdir(path.dirname(dest), { recursive: true, mode: 0o700 });\n // Copy, then clamp to owner-only. copyFile without an existing dest inherits\n // umask; chmod pins 0o600 so the (possibly secret) config is owner-only.\n await copyFile(src, dest, fsConstants.COPYFILE_FICLONE);\n await chmod(dest, 0o600);\n copied += 1;\n }\n // NEVER log file names/contents (an ignored config can be a secret) \u2014 count only.\n if (copied > 0) {\n this.opts.log?.(\n `[harness-worktree] copied ${copied} ignored config file(s)`,\n );\n }\n }\n\n private async isIgnored(checkout: string, rel: string): Promise<boolean> {\n try {\n // `git check-ignore <path>` prints the path + exits 0 when ignored; exits 1\n // (which runGit surfaces as a rejection) when NOT ignored. `--` guards a\n // path that looks like a flag.\n const out = await this.runGit(checkout, [\"check-ignore\", \"--\", rel]);\n return out.trim().length > 0;\n } catch {\n return false;\n }\n }\n\n // -------------------------------------------------------------------------\n // Git helpers.\n // -------------------------------------------------------------------------\n\n private async listGitWorktrees(checkout: string): Promise<GitWorktreeRow[]> {\n const out = await this.runGit(checkout, [\n \"worktree\",\n \"list\",\n \"--porcelain\",\n ]);\n const rows: GitWorktreeRow[] = [];\n let cur: Partial<GitWorktreeRow> | null = null;\n for (const line of out.split(\"\\n\")) {\n if (line.startsWith(\"worktree \")) {\n if (cur?.path) rows.push(finishRow(cur));\n cur = { path: line.slice(\"worktree \".length).trim() };\n } else if (line.startsWith(\"branch \")) {\n const ref = line.slice(\"branch \".length).trim();\n if (cur) cur.branch = ref.replace(/^refs\\/heads\\//, \"\");\n } else if (line.trim() === \"detached\") {\n if (cur) cur.detached = true;\n }\n }\n if (cur?.path) rows.push(finishRow(cur));\n return rows;\n }\n\n private async isSourceDirty(dir: string): Promise<boolean> {\n try {\n const porcelain = await this.runGit(dir, [\"status\", \"--porcelain\"]);\n return porcelain.trim().length > 0;\n } catch {\n return false;\n }\n }\n}\n\nfunction finishRow(cur: Partial<GitWorktreeRow>): GitWorktreeRow {\n return {\n path: cur.path as string,\n branch: cur.branch ?? null,\n detached: cur.detached ?? false,\n };\n}\n\n/** The sibling ownership-marker path for a listed worktree dir. */\nfunction markerPathFor(worktreeDir: string): string {\n return path.join(\n path.dirname(worktreeDir),\n `${path.basename(worktreeDir)}.marker.json`,\n );\n}\n\nfunction assertUnder(base: string, target: string): void {\n const b = path.resolve(base);\n const t = path.resolve(target);\n if (t !== b && !t.startsWith(b + path.sep)) {\n throw new WorktreeError(\"PATH_ESCAPE\", `path ${t} escapes ${b}`);\n }\n}\n\nfunction safeRealpath(p: string): string {\n // realpathSync would throw on a not-yet-existing path; for comparison we only\n // need a normalized absolute form, and existing dirs are compared by realpath at\n // the S1 layer. path.resolve is enough here (git already emits absolute paths).\n return path.resolve(p);\n}\n\n/** Realpath-normalized key for a worktree dir so a live `git worktree list` path\n * and a marker-derived dir compare equal across symlinked roots (e.g. macOS\n * /var \u2192 /private/var). Falls back to path.resolve when the dir is gone. */\nfunction realDirKey(p: string): string {\n try {\n return realpathSync(p);\n } catch {\n return path.resolve(p);\n }\n}\n\nconst MARKER_SUFFIX = \".marker.json\";\n\n/** A dummy identity used ONLY to derive a repo's worktree base dir\n * (`<root>/<repoKey>`) via resolveWorktreePaths \u2014 the jobId leaf is discarded\n * (we take its parent). \"scan\" satisfies the S1 opaque-jobId shape check. */\nconst MARKER_SCAN_IDENTITY: WorktreeIdentity = {\n repo: \"_\",\n jobId: \"scan\",\n stageId: \"_\",\n branch: \"_\",\n};\n\n/** Enumerate the sibling ownership markers directly under a repo's worktree base.\n * Tolerates a not-yet-created base (no worktrees \u21D2 empty list). */\nasync function listMarkerFiles(base: string): Promise<string[]> {\n let names: string[];\n try {\n names = await readdir(base);\n } catch {\n return [];\n }\n return names\n .filter((n) => n.endsWith(MARKER_SUFFIX))\n .map((n) => path.join(base, n));\n}\n\nasync function markerAgeMs(markerPath: string): Promise<number> {\n try {\n const s = await stat(markerPath);\n return Math.max(0, Date.now() - s.mtimeMs);\n } catch {\n return 0;\n }\n}\n", "/**\n * Sandbox-side broker adapters \u2014 production credential injection (M12.5, AGE-175).\n *\n * M12.3a shipped the {@link CredentialBroker} that turns a capability handle into a\n * short-lived credential; M12.4a gave it a workload-identity resolver. Both stop at\n * \"here is a token string\". This module is the M12.5 half: the ADAPTERS that take a\n * resolved M4 grant and INJECT the secret into exactly ONE authorized process/action,\n * then DESTROY it \u2014 so the agent process can *request* an action but can never *read*\n * the secret.\n *\n * The trust split is the whole point:\n * \u2022 The AGENT (the untrusted workload inside the sandbox) only ever holds an OPAQUE,\n * single-use {@link ActionHandle} \u2014 a nonce + the authorized action + non-secret\n * target. It requests \"perform handle H with params P\"; it never sees material.\n * \u2022 The BROKER (this module, owned by the sandbox host/controller, a separate trust\n * domain) resolves the grant behind the handle, injects the credential into the\n * ONE authorized effect, runs it, destroys the material, and returns only the\n * non-secret result.\n *\n * Three production adapters, one authorized effect each:\n * \u2022 repo:push \u2192 git credential helper (secret in the git child's ENV, never\n * argv, never the parent/agent env).\n * \u2022 repo:pr_create \u2192 GitHub App-token `Authorization` header on the PR-create call.\n * \u2022 deploy:production \u2192 Vercel `Authorization: Bearer` header on the deploy call\n * (and release:rollback over the same Vercel adapter).\n *\n * Every adapter enforces, in code (proven by the conformance suite):\n * \u2022 single-use \u2014 a handle performs at most once; the grant resolve is single-use\n * server-side too.\n * \u2022 TTL expiry \u2014 an expired handle (or grant) fails closed before any injection.\n * \u2022 scope-narrow \u2014 the requested target must lie within the resolved grant's scope\n * (repo \u2208 repositories, contents:write present; environment match);\n * a violation fails closed WITHOUT injecting and revokes the grant.\n * \u2022 audit \u2014 granted \u2192 resolved \u2192 injected \u2192 destroyed (or \u2192 revoked/denied)\n * rows, carrying NO material.\n * \u2022 revoke-on-fail \u2014 an injected action that throws revokes the grant before it\n * surfaces the error.\n *\n * Dependency-free apart from node builtins + the execution package (matches the rest\n * of this standalone package). Everything with a side effect (grant resolve/revoke,\n * git, http, clock, nonce) is INJECTED so the conformance/adversarial/observable-exit\n * suites drive it hermetically and a real deployment wires the live effects.\n */\nimport { randomUUID } from \"node:crypto\";\nimport { spawn } from \"node:child_process\";\n\n/** The externally-visible actions a sandbox-side adapter can inject a credential for. */\nexport type BrokerAction =\n | \"repo:push\"\n | \"repo:pr_create\"\n | \"deploy:production\"\n | \"release:rollback\";\n\n/** Non-secret binding of an action to its target (what the agent is allowed to ask). */\nexport interface ActionTarget {\n /** \"owner/name\" \u2014 the repo a push/PR is bound to. */\n repo?: string;\n /** The git branch a push/PR targets. */\n branch?: string;\n /** The deploy environment (\"production\"). */\n environment?: string;\n}\n\n/**\n * The OPAQUE, single-use action handle handed to the agent. It carries NO secret \u2014\n * only a nonce, the one authorized action, the non-secret target, and the id of the\n * M4 grant it will consume (an opaque reference, not material). A leaked handle is\n * useless without the broker (which alone can resolve the grant) and is single-use.\n */\nexport interface ActionHandle {\n handleId: string;\n action: BrokerAction;\n capabilityId: string;\n /** The M4 grant id this handle consumes \u2014 an opaque ref, NOT a secret. */\n grantId: string;\n target: ActionTarget;\n /** ISO timestamp after which the handle is dead (fail closed). */\n expiresAt: string;\n}\n\n/** The scope a resolved M4 grant is narrowed to (mirrors the CredentialGrant.scope). */\nexport interface GrantScope {\n /**\n * The GitHub repositories the grant's token is scoped to. Each entry is EITHER a\n * fully-qualified `owner/name` (compared whole) OR a bare short name (the GitHub\n * installation-token form) \u2014 a bare short name is honored ONLY when {@link owner}\n * pins the account it belongs to. Never compare short names alone: a grant for\n * `acme/api` must never authorize `evil/api` (see {@link repoWithinScope}).\n */\n repositories?: string[];\n /**\n * The GitHub account/owner login the grant's installation is bound to. A GitHub App\n * installation lives under exactly one account, so bare `repositories` short names\n * are attributable to THIS owner and no other. Required to authorize a bare short\n * name; when absent, only fully-qualified `owner/name` entries can match (fail\n * closed otherwise), so the owner can never be spoofed.\n */\n owner?: string;\n /** GitHub installation-token permissions, e.g. { contents: \"write\" }. */\n permissions?: Record<string, string>;\n /** The single environment a cloud grant authorizes. */\n environment?: string;\n}\n\n/**\n * True iff the FULL `owner/name` `repo` is authorized by `scope`. The check is\n * OWNER-AWARE (the M12.5 finding this closes): a bare short-name entry in\n * `scope.repositories` is honored ONLY when `scope.owner` pins the same account, and\n * a fully-qualified entry must match `owner/name` whole (case-insensitive, per\n * GitHub). A `repo` that is not fully-qualified, or whose owner we cannot attribute to\n * the grant, fails closed \u2014 so a grant scoped to `acme/api` never authorizes the\n * same-short-name `evil/api`.\n */\nexport function repoWithinScope(scope: GrantScope, repo: string): boolean {\n if (!repo.includes(\"/\")) return false; // require a fully-qualified owner/name\n const [owner, name] = repo.split(\"/\");\n if (!owner || !name) return false;\n const target = repo.toLowerCase();\n const ownerLc = owner.toLowerCase();\n const nameLc = name.toLowerCase();\n const scopeOwner = scope.owner?.toLowerCase();\n for (const entry of scope.repositories ?? []) {\n if (entry.includes(\"/\")) {\n // Fully-qualified entry \u2014 must match the whole owner/name.\n if (entry.toLowerCase() === target) return true;\n } else if (\n scopeOwner &&\n scopeOwner === ownerLc &&\n entry.toLowerCase() === nameLc\n ) {\n // Bare short name \u2014 honored ONLY under the grant's pinned owner.\n return true;\n }\n }\n return false;\n}\n\n/**\n * A resolved M4 grant: the SECRET plus its narrowed scope + expiry. This value NEVER\n * leaves the broker \u2014 it lives only inside a `perform*` call and is destroyed after\n * the single injection.\n */\nexport interface ResolvedGrant {\n /** The raw credential material (installation token / Vercel token). */\n material: string;\n expiresAt: string;\n scope: GrantScope;\n}\n\n/**\n * The M4 grant plane, injected. In production `resolve` is wired to the control\n * plane's `resolveGrantForExecution` (single-use: ISSUED\u2192USED atomically, fails\n * closed on expired/revoked/action-mismatch) and `revoke` to `revokeCredentialGrant`.\n * The broker treats BOTH as authoritative \u2014 it never fabricates or caches material.\n */\nexport interface GrantPlane {\n /** Resolve a grant to material. MUST be single-use + fail-closed server-side. */\n resolve(grantId: string, action: BrokerAction): Promise<ResolvedGrant>;\n /** Revoke a grant (revocation-on-failure). Best-effort; never throws material. */\n revoke(grantId: string, reason: string): Promise<void>;\n}\n\n/** A single non-secret audit row. `detail` MUST never contain material. */\nexport interface BrokerAuditRow {\n ts: string;\n phase:\n | \"granted\"\n | \"resolved\"\n | \"injected\"\n | \"destroyed\"\n | \"revoked\"\n | \"denied\";\n handleId: string;\n grantId: string;\n action: BrokerAction;\n capabilityId: string;\n outcome: \"ok\" | \"failed\";\n detail?: string;\n}\n\n/**\n * Run a git command in a checkout. `secretEnv` is merged into the CHILD process\n * environment ONLY \u2014 never the parent/agent env, never argv (a token-in-URL would\n * leak into `ps`/git error output). Returns the child's stdout + exit code.\n */\nexport type GitInjector = (args: {\n cwd: string;\n argv: string[];\n secretEnv: Record<string, string>;\n}) => Promise<{ stdout: string; stderr: string; exitCode: number }>;\n\n/**\n * Perform an authenticated HTTP request. `authHeader` carries the secret and is sent\n * ONLY as the `Authorization` request header to the destination \u2014 never in the URL,\n * body, or any surface the agent or MCP transport can read.\n */\nexport type HttpInjector = (args: {\n method: string;\n url: string;\n authHeader: string;\n headers?: Record<string, string>;\n body?: string;\n}) => Promise<{ status: number; body: string }>;\n\nexport interface SandboxBrokerDeps {\n grants: GrantPlane;\n git: GitInjector;\n http: HttpInjector;\n /** Non-secret audit sink (grant/injection/destruction feed). */\n audit?: (row: BrokerAuditRow) => void;\n now?: () => number;\n /** Opaque handle-id minter (default randomUUID) \u2014 injectable for determinism. */\n mintHandleId?: () => string;\n /** GitHub REST base (PR create). Default https://api.github.com. */\n githubApiBase?: string;\n /** Vercel REST base (deploy/rollback). Default https://api.vercel.com. */\n vercelApiBase?: string;\n}\n\n/** A structured, fail-closed broker error. `message`/`code` carry NO material. */\nexport class BrokerAdapterError extends Error {\n constructor(\n readonly code:\n | \"HANDLE_EXPIRED\"\n | \"HANDLE_CONSUMED\"\n | \"ACTION_MISMATCH\"\n | \"SCOPE_VIOLATION\"\n | \"GRANT_UNRESOLVED\"\n | \"INJECTION_FAILED\",\n message: string,\n ) {\n super(message);\n this.name = \"BrokerAdapterError\";\n }\n}\n\nexport interface PushResult {\n pushed: boolean;\n branch: string;\n remote: string;\n}\nexport interface PrResult {\n url: string;\n number: number;\n}\nexport interface DeployResult {\n deploymentId: string | null;\n status: string;\n url: string | null;\n}\n\n/**\n * The default git injector: spawns real `git`, merging `secretEnv` into the CHILD\n * env only. The secret never touches argv or the parent process env.\n */\nexport const spawnGitInjector: GitInjector = ({ cwd, argv, secretEnv }) =>\n new Promise((resolve, reject) => {\n const child = spawn(\"git\", argv, {\n cwd,\n // The ONLY place the secret exists: this child's environment. It is gone the\n // moment the process exits \u2014 never inherited by the agent workload.\n env: { ...process.env, ...secretEnv },\n });\n let stdout = \"\";\n let stderr = \"\";\n child.stdout.on(\"data\", (d) => (stdout += d));\n child.stderr.on(\"data\", (d) => (stderr += d));\n child.on(\"error\", reject);\n child.on(\"close\", (code) =>\n resolve({\n stdout: stdout.trim(),\n stderr: stderr.trim(),\n exitCode: code ?? 0,\n }),\n );\n });\n\n/**\n * The default http injector: `fetch` with the secret only in the Authorization\n * header. Requires a global `fetch` (Node \u2265 18). The body is read back as text.\n */\nexport const fetchHttpInjector: HttpInjector = async ({\n method,\n url,\n authHeader,\n headers,\n body,\n}) => {\n const res = await fetch(url, {\n method,\n headers: { ...(headers ?? {}), Authorization: authHeader },\n body,\n redirect: \"manual\",\n });\n return { status: res.status, body: await res.text() };\n};\n\n/**\n * The sandbox-side credential broker. It mints opaque handles for the agent and\n * OWNS the injection of every credential \u2014 the agent never touches material.\n */\nexport class SandboxBroker {\n private readonly now: () => number;\n private readonly mintHandleId: () => string;\n private readonly audit: (row: BrokerAuditRow) => void;\n private readonly githubApiBase: string;\n private readonly vercelApiBase: string;\n /** Handles consumed exactly once \u2014 the in-broker half of single-use. */\n private readonly consumed = new Set<string>();\n\n constructor(private readonly deps: SandboxBrokerDeps) {\n this.now = deps.now ?? Date.now;\n this.mintHandleId = deps.mintHandleId ?? (() => `ah_${randomUUID()}`);\n this.audit = deps.audit ?? (() => {});\n this.githubApiBase = deps.githubApiBase ?? \"https://api.github.com\";\n this.vercelApiBase = deps.vercelApiBase ?? \"https://api.vercel.com\";\n }\n\n /**\n * Mint an OPAQUE, single-use action handle for the agent. No secret is touched\n * here \u2014 the handle only names an already-issued M4 grant + the one authorized\n * action + target. `ttlSeconds` bounds the handle independently of the grant.\n */\n grantHandle(req: {\n action: BrokerAction;\n capabilityId: string;\n grantId: string;\n target: ActionTarget;\n ttlSeconds?: number;\n }): ActionHandle {\n const ttl = req.ttlSeconds ?? 600;\n const handle: ActionHandle = {\n handleId: this.mintHandleId(),\n action: req.action,\n capabilityId: req.capabilityId,\n grantId: req.grantId,\n target: req.target,\n expiresAt: new Date(this.now() + ttl * 1000).toISOString(),\n };\n this.emit(handle, \"granted\", \"ok\");\n return handle;\n }\n\n // ---- The three production adapters (one authorized effect each) ----------\n\n /**\n * repo:push \u2014 inject a single-use GitHub token into a git push via a credential\n * helper that reads it from the git child's ENV. The secret never appears in argv\n * (no token-in-URL), the parent/agent env, or any returned value.\n */\n async performPush(\n handle: ActionHandle,\n params: {\n cwd: string;\n branch: string;\n refspec?: string;\n /** Override the remote (GitHub Enterprise host or a test remote); default\n * https://github.com/<owner>/<name>.git. The credential-helper injection is\n * identical regardless. */\n remoteUrl?: string;\n },\n ): Promise<PushResult> {\n return this.withGrant(handle, \"repo:push\", async (grant) => {\n const repo = handle.target.repo ?? \"\";\n this.assertRepoInScope(handle, grant, repo, \"contents\");\n const [owner, name] = repo.split(\"/\");\n const remoteUrl =\n params.remoteUrl ?? `https://github.com/${owner}/${name}.git`;\n const refspec = params.refspec ?? `${params.branch}:${params.branch}`;\n // The credential helper reads the token from $STACKS_GIT_TOKEN \u2014 passed ONLY\n // in the child env below, never on the command line.\n const helper =\n '!f() { echo \"username=x-access-token\"; echo \"password=$STACKS_GIT_TOKEN\"; }; f';\n const res = await this.deps.git({\n cwd: params.cwd,\n argv: [\"-c\", `credential.helper=${helper}`, \"push\", remoteUrl, refspec],\n secretEnv: { STACKS_GIT_TOKEN: grant.material },\n });\n if (res.exitCode !== 0) {\n throw new BrokerAdapterError(\n \"INJECTION_FAILED\",\n `git push failed (exit ${res.exitCode})`,\n );\n }\n return {\n pushed: true,\n branch: params.branch,\n remote: `${owner}/${name}`,\n };\n });\n }\n\n /**\n * repo:pr_create \u2014 inject the App-installation token as the `Authorization` header\n * on the GitHub PR-create REST call. The token is only ever a request header to\n * api.github.com; the returned {url, number} carries no material.\n */\n async performPrCreate(\n handle: ActionHandle,\n params: {\n repo: string;\n head: string;\n base: string;\n title: string;\n body?: string;\n },\n ): Promise<PrResult> {\n return this.withGrant(handle, \"repo:pr_create\", async (grant) => {\n this.assertRepoInScope(handle, grant, params.repo, \"pull_requests\");\n const res = await this.deps.http({\n method: \"POST\",\n url: `${this.githubApiBase}/repos/${params.repo}/pulls`,\n // The secret lives ONLY here \u2014 a request header to GitHub.\n authHeader: `Bearer ${grant.material}`,\n headers: {\n Accept: \"application/vnd.github+json\",\n \"X-GitHub-Api-Version\": \"2022-11-28\",\n \"Content-Type\": \"application/json\",\n },\n body: JSON.stringify({\n title: params.title,\n head: params.head,\n base: params.base,\n body: params.body ?? \"\",\n }),\n });\n if (res.status < 200 || res.status >= 300) {\n throw new BrokerAdapterError(\n \"INJECTION_FAILED\",\n `PR create failed (HTTP ${res.status})`,\n );\n }\n const parsed = JSON.parse(res.body) as {\n html_url?: string;\n number?: number;\n };\n return {\n url: parsed.html_url ?? \"\",\n number: parsed.number ?? 0,\n };\n });\n }\n\n /**\n * deploy:production / release:rollback \u2014 inject the Vercel token as an\n * `Authorization: Bearer` header on the deploy REST call. The environment target\n * must match the grant scope. Returns the deployment id/url \u2014 never the token.\n */\n async performDeploy(\n handle: ActionHandle,\n params: {\n projectId: string;\n environment: string;\n commitSha?: string;\n teamId?: string;\n },\n ): Promise<DeployResult> {\n const action = handle.action;\n if (action !== \"deploy:production\" && action !== \"release:rollback\") {\n throw new BrokerAdapterError(\n \"ACTION_MISMATCH\",\n `handle authorizes ${action}, not a deploy`,\n );\n }\n return this.withGrant(handle, action, async (grant) => {\n this.assertEnvInScope(handle, grant, params.environment);\n const q = params.teamId\n ? `?teamId=${encodeURIComponent(params.teamId)}`\n : \"\";\n const res = await this.deps.http({\n method: \"POST\",\n url: `${this.vercelApiBase}/v13/deployments${q}`,\n // The secret lives ONLY here \u2014 a request header to Vercel.\n authHeader: `Bearer ${grant.material}`,\n headers: { \"Content-Type\": \"application/json\" },\n body: JSON.stringify({\n name: params.projectId,\n project: params.projectId,\n target: params.environment,\n gitSource: params.commitSha\n ? { type: \"github\", sha: params.commitSha }\n : undefined,\n }),\n });\n if (res.status < 200 || res.status >= 300) {\n throw new BrokerAdapterError(\n \"INJECTION_FAILED\",\n `deploy failed (HTTP ${res.status})`,\n );\n }\n const parsed = JSON.parse(res.body) as {\n id?: string;\n url?: string;\n readyState?: string;\n status?: string;\n };\n return {\n deploymentId: parsed.id ?? null,\n status: parsed.readyState ?? parsed.status ?? \"PENDING\",\n url: parsed.url ?? null,\n };\n });\n }\n\n // ---- Shared injection lifecycle -----------------------------------------\n\n /**\n * The single-use / TTL / resolve / scope / inject / destroy / revoke-on-fail\n * lifecycle shared by every adapter. `run` is the ONE authorized effect; the\n * resolved grant (material) is visible only inside it and destroyed after.\n */\n private async withGrant<T>(\n handle: ActionHandle,\n expected: BrokerAction,\n run: (grant: ResolvedGrant) => Promise<T>,\n ): Promise<T> {\n // 1. Action must match the handle (defense against a coerced handle reuse).\n if (handle.action !== expected) {\n this.emit(handle, \"denied\", \"failed\", \"action mismatch\");\n throw new BrokerAdapterError(\n \"ACTION_MISMATCH\",\n `handle authorizes ${handle.action}, not ${expected}`,\n );\n }\n // 2. TTL \u2014 an expired handle fails closed before ANY grant resolve/injection.\n if (this.now() >= Date.parse(handle.expiresAt)) {\n this.emit(handle, \"denied\", \"failed\", \"handle expired\");\n throw new BrokerAdapterError(\"HANDLE_EXPIRED\", \"action handle expired\");\n }\n // 3. Single-use \u2014 claim the handle BEFORE resolving material so a concurrent or\n // replayed call cannot double-inject. (The server resolve is single-use too.)\n if (this.consumed.has(handle.handleId)) {\n this.emit(handle, \"denied\", \"failed\", \"handle already consumed\");\n throw new BrokerAdapterError(\n \"HANDLE_CONSUMED\",\n \"action handle already consumed\",\n );\n }\n this.consumed.add(handle.handleId);\n\n // 4. Resolve the grant to material (single-use + fail-closed server-side).\n let grant: ResolvedGrant;\n try {\n grant = await this.deps.grants.resolve(handle.grantId, expected);\n } catch (err) {\n this.emit(handle, \"denied\", \"failed\", \"grant unresolved\");\n throw new BrokerAdapterError(\n \"GRANT_UNRESOLVED\",\n `grant did not resolve: ${errText(err)}`,\n );\n }\n // The grant's own expiry is authoritative too \u2014 fail closed if already past it.\n if (this.now() >= Date.parse(grant.expiresAt)) {\n await this.revoke(handle, \"grant expired at injection\");\n throw new BrokerAdapterError(\"HANDLE_EXPIRED\", \"grant expired\");\n }\n this.emit(handle, \"resolved\", \"ok\");\n\n // 5. Inject into the ONE authorized effect. A scope violation raised inside `run`\n // (via assert*) or an effect failure revokes the grant (revoke-on-failure).\n let material: string | null = grant.material;\n try {\n const result = await run(grant);\n this.emit(handle, \"injected\", \"ok\");\n return result;\n } catch (err) {\n // Revoke-on-failure: a scope violation or a failed injection kills the grant\n // so a partially-used credential can never be retried.\n await this.revoke(handle, `injection failed: ${errText(err)}`);\n if (err instanceof BrokerAdapterError) throw err;\n throw new BrokerAdapterError(\"INJECTION_FAILED\", errText(err));\n } finally {\n // 6. Destroy the material \u2014 drop every in-broker reference. The git child env\n // is already gone; the http header was request-scoped. Nothing persists it.\n material = null;\n void material;\n (grant as { material: string }).material = \"\";\n this.emit(handle, \"destroyed\", \"ok\");\n }\n }\n\n /** Scope-narrowing for repo actions: the FULL `owner/name` target must be\n * authorized by the grant's `repositories` (owner-aware \u2014 see\n * {@link repoWithinScope}), and the required permission must be present at write\n * level. A violation throws inside `withGrant` \u2192 revoke-on-failure fires. */\n private assertRepoInScope(\n handle: ActionHandle,\n grant: ResolvedGrant,\n repo: string,\n requiredPermission: \"contents\" | \"pull_requests\",\n ): void {\n const permOk =\n (grant.scope.permissions?.[requiredPermission] ?? \"\") === \"write\";\n if (!permOk || !repoWithinScope(grant.scope, repo)) {\n this.emit(handle, \"denied\", \"failed\", \"scope violation (repo)\");\n throw new BrokerAdapterError(\n \"SCOPE_VIOLATION\",\n `grant does not authorize ${requiredPermission}:write on ${repo}`,\n );\n }\n }\n\n /** Scope-narrowing for cloud actions: the deploy environment must equal the\n * grant's single authorized environment. */\n private assertEnvInScope(\n handle: ActionHandle,\n grant: ResolvedGrant,\n environment: string,\n ): void {\n if ((grant.scope.environment ?? \"\") !== environment) {\n this.emit(handle, \"denied\", \"failed\", \"scope violation (environment)\");\n throw new BrokerAdapterError(\n \"SCOPE_VIOLATION\",\n `grant authorizes environment ${grant.scope.environment ?? \"<none>\"}, not ${environment}`,\n );\n }\n }\n\n private async revoke(handle: ActionHandle, reason: string): Promise<void> {\n try {\n await this.deps.grants.revoke(handle.grantId, reason);\n } catch {\n /* revoke is best-effort \u2014 the grant's short TTL bounds the window anyway */\n }\n this.emit(handle, \"revoked\", \"failed\", reason);\n }\n\n private emit(\n handle: ActionHandle,\n phase: BrokerAuditRow[\"phase\"],\n outcome: BrokerAuditRow[\"outcome\"],\n detail?: string,\n ): void {\n this.audit({\n ts: new Date(this.now()).toISOString(),\n phase,\n handleId: handle.handleId,\n grantId: handle.grantId,\n action: handle.action,\n capabilityId: handle.capabilityId,\n outcome,\n detail,\n });\n }\n}\n\nfunction errText(err: unknown): string {\n return err instanceof Error ? err.message : String(err);\n}\n\n// ---------------------------------------------------------------------------\n// Scraping-resistance: prove a secret NEVER transits an agent-visible surface.\n// ---------------------------------------------------------------------------\n\n/** A named surface the agent (or the MCP transport) can read, for absence scanning. */\nexport interface AgentVisibleSurface {\n name: string;\n /** The surface content as a string (env dump, argv join, MCP transcript, log). */\n content: string;\n}\n\n/**\n * Scan agent-visible surfaces for a literal secret. Returns the names of any surface\n * that LEAKED it (empty = clean). Used by the adversarial + observable-exit proofs:\n * the broker's injection helpers keep the secret out of the agent env, process args,\n * and MCP transport, and this is the grep that proves it.\n */\nexport function scanForSecret(\n secret: string,\n surfaces: AgentVisibleSurface[],\n): string[] {\n if (!secret) return [];\n return surfaces.filter((s) => s.content.includes(secret)).map((s) => s.name);\n}\n\n/**\n * Assert a secret is absent from every agent-visible surface \u2014 throws (fail closed)\n * naming the leaking surface if not. The one-line \"grep proves no secret value ever\n * transits the agent-visible env or MCP transport\" from the M12.5 observable exit.\n */\nexport function assertSecretAbsent(\n secret: string,\n surfaces: AgentVisibleSurface[],\n): void {\n const leaked = scanForSecret(secret, surfaces);\n if (leaked.length > 0) {\n throw new Error(\n `secret leaked into agent-visible surface(s): ${leaked.join(\", \")}`,\n );\n }\n}\n", "/**\n * Production wiring for the M12.5 sandbox-side broker adapters (AGE-175).\n *\n * This is the factory that REPLACES the reference runner's fail-closed no-op seams\n * (`brokerPushCredential` / `createPullRequest`, and the M8 `brokerCloudToken` deploy\n * path) with a broker that OWNS credential injection sandbox-side. It composes the\n * dependency-free {@link SandboxBroker} (from @stacks/sandbox-controller) with a\n * deployment-supplied M4 grant plane:\n *\n * \u2022 {@link DeliveryGrantSource.issueGrant} \u2014 issues an M4 grant for one action +\n * target (server-side `brokerRepoToken` / `brokerCloudToken`); returns only an\n * OPAQUE grant id, never material.\n * \u2022 {@link SandboxBroker}'s `GrantPlane.resolve` \u2014 resolves that grant to material\n * server-side (`resolveGrantForExecution`, single-use ISSUED\u2192USED) and injects it\n * into the ONE authorized process/action, then destroys it.\n *\n * The whole thing is FEATURE-GATED: `createSandboxEgress` / `createDeliveryDeploy`\n * return `undefined` unless `STACKS_SANDBOX_BROKER_ENABLED=1` AND a grant source is\n * supplied \u2014 so a runner with no configured grant plane keeps the exact fail-closed\n * no-op behaviour (the harness runner treats `undefined` as \"use the legacy path\" and\n * a null result as \"defer to the governed path\"). The adapters import ONLY the\n * dependency-free `adapters.js` module (no zod / no @stacks/execution) so the agents\n * package typechecks without pulling the controller's full dependency tree.\n */\nimport {\n SandboxBroker,\n type BrokerAction,\n type DeployResult,\n} from \"../../services/sandbox-controller/src/adapters.js\";\n\nimport type { SandboxEgressBroker } from \"./harness-runner.js\";\n\n/** Whether the sandbox broker is enabled (mirrors the controller's own flag). */\nexport function isSandboxBrokerEnabled(\n env: NodeJS.ProcessEnv = process.env,\n): boolean {\n return env.STACKS_SANDBOX_BROKER_ENABLED === \"1\";\n}\n\n/**\n * Issues M4 grants for the delivery egress actions. A real deployment implements\n * this over the control plane (`brokerRepoToken` for repo:*, `brokerCloudToken` for\n * deploy:*), returning ONLY an opaque grant id \u2014 the material is resolved later, at\n * the broker's injection boundary, by the {@link SandboxBroker}'s grant plane.\n * Returns null to fail closed (frozen / policy deny / provider unconfigured).\n */\nexport interface DeliveryGrantSource {\n issueGrant(req: {\n action: BrokerAction;\n repo?: string;\n environment?: string;\n harnessRunId?: string;\n stageId?: string;\n jobId?: string;\n runId?: string;\n }): Promise<string | null>;\n}\n\n/**\n * Build the harness runner's {@link SandboxEgressBroker} from a {@link SandboxBroker}\n * + an M4 grant source. Returns `undefined` (\u21D2 the runner uses the legacy no-op path)\n * unless the flag is on and a grant source is present. Each call issues a fresh\n * single-use grant, mints an OPAQUE handle for it, and asks the broker to perform the\n * action \u2014 the raw credential never returns to the runner. Any failure fails closed\n * (null) so the runner defers to the governed path, never pushing un-brokered.\n */\nexport function createSandboxEgress(opts: {\n broker: SandboxBroker;\n grants: DeliveryGrantSource;\n env?: NodeJS.ProcessEnv;\n}): SandboxEgressBroker | undefined {\n if (!isSandboxBrokerEnabled(opts.env)) return undefined;\n const { broker, grants } = opts;\n return {\n async push(req) {\n const grantId = await grants\n .issueGrant({\n action: \"repo:push\",\n repo: req.repo,\n harnessRunId: req.harnessRunId,\n stageId: req.stageId,\n })\n .catch(() => null);\n if (!grantId) return null; // fail closed \u2014 defer to the governed path\n const handle = broker.grantHandle({\n action: \"repo:push\",\n capabilityId: `stage:${req.stageId}`,\n grantId,\n target: { repo: req.repo, branch: req.branch },\n });\n try {\n const res = await broker.performPush(handle, {\n cwd: req.cwd,\n branch: req.branch,\n });\n return { pushed: res.pushed };\n } catch {\n return null; // broker failed closed (frozen / scope / injection)\n }\n },\n async openPr(req) {\n const grantId = await grants\n .issueGrant({\n action: \"repo:pr_create\",\n repo: req.repo,\n harnessRunId: req.harnessRunId,\n stageId: req.stageId,\n })\n .catch(() => null);\n if (!grantId) return null;\n const handle = broker.grantHandle({\n action: \"repo:pr_create\",\n capabilityId: `stage:${req.stageId}`,\n grantId,\n target: { repo: req.repo, branch: req.branch },\n });\n try {\n const pr = await broker.performPrCreate(handle, {\n repo: req.repo,\n head: req.branch,\n base: req.baseBranch ?? \"main\",\n title: req.title,\n });\n // A broker that returns an empty PR (e.g. a 2xx with no body) still defers.\n return pr.number > 0 ? { url: pr.url, number: pr.number } : null;\n } catch {\n return null;\n }\n },\n };\n}\n\n/**\n * The M8 cloud-deploy seam, now sandbox-side. `brokerCloudToken` (server) issues the\n * `deploy:production` / `release:rollback` M4 grant; this broker resolves it and\n * injects the Vercel token as a bearer header on the deploy call \u2014 the token never\n * leaves the broker. Returns null (fail closed) when disabled / unconfigured.\n */\nexport function createDeliveryDeploy(opts: {\n broker: SandboxBroker;\n grants: DeliveryGrantSource;\n env?: NodeJS.ProcessEnv;\n}):\n | ((req: {\n projectId: string;\n environment: string;\n commitSha?: string;\n teamId?: string;\n harnessRunId?: string;\n stageId?: string;\n rollback?: boolean;\n }) => Promise<DeployResult | null>)\n | undefined {\n if (!isSandboxBrokerEnabled(opts.env)) return undefined;\n const { broker, grants } = opts;\n return async (req) => {\n const action: BrokerAction = req.rollback\n ? \"release:rollback\"\n : \"deploy:production\";\n const grantId = await grants\n .issueGrant({\n action,\n environment: req.environment,\n harnessRunId: req.harnessRunId,\n stageId: req.stageId,\n })\n .catch(() => null);\n if (!grantId) return null;\n const handle = broker.grantHandle({\n action,\n capabilityId: `deploy:${req.environment}`,\n grantId,\n target: { environment: req.environment },\n });\n try {\n return await broker.performDeploy(handle, {\n projectId: req.projectId,\n environment: req.environment,\n commitSha: req.commitSha,\n teamId: req.teamId,\n });\n } catch {\n return null;\n }\n };\n}\n", "/**\n * Runtime construction of the M12.5 sandbox-side egress broker for the reference\n * runner (AGE-175). Keeps `workflow-runner.ts` thin: it just calls\n * {@link makeSandboxEgress}, which returns `undefined` (\u21D2 the harness runner uses the\n * legacy fail-closed no-op path, unchanged) UNLESS both are true:\n *\n * \u2022 `STACKS_SANDBOX_BROKER_ENABLED=1`, and\n * \u2022 `STACKS_BROKER_GRANT_URL` names the control-plane grant transport.\n *\n * When configured, it wires a real {@link SandboxBroker} (real git + fetch injectors)\n * to an HTTP grant plane. The grant plane issues M4 grants and resolves them to\n * material SERVER-SIDE \u2014 the runner only ever sees opaque grant ids + results, and\n * the broker confines the material to its one injection. The transport is\n * deliberately small and header-authenticated (`STACKS_BROKER_GRANT_TOKEN`).\n */\nimport {\n SandboxBroker,\n fetchHttpInjector,\n spawnGitInjector,\n type BrokerAction,\n type GrantPlane,\n type ResolvedGrant,\n} from \"../../services/sandbox-controller/src/adapters.js\";\n\nimport {\n createSandboxEgress,\n isSandboxBrokerEnabled,\n type DeliveryGrantSource,\n} from \"./sandbox-broker-adapters.js\";\nimport type { SandboxEgressBroker } from \"./harness-runner.js\";\n\n/** The control-plane grant transport: issues + resolves + revokes M4 grants over\n * HTTP. It NEVER returns material to the runner \u2014 only `resolve` (called by the\n * broker at its injection boundary) yields material, server-authenticated. */\nclass HttpGrantPlane implements GrantPlane, DeliveryGrantSource {\n constructor(\n private readonly baseUrl: string,\n private readonly token: string | undefined,\n private readonly fetchFn: typeof fetch = fetch,\n ) {}\n\n private headers(): Record<string, string> {\n return {\n \"content-type\": \"application/json\",\n ...(this.token ? { authorization: `Bearer ${this.token}` } : {}),\n };\n }\n\n async issueGrant(req: {\n action: BrokerAction;\n repo?: string;\n environment?: string;\n harnessRunId?: string;\n stageId?: string;\n jobId?: string;\n runId?: string;\n }): Promise<string | null> {\n const res = await this.fetchFn(`${this.baseUrl}/grants/issue`, {\n method: \"POST\",\n headers: this.headers(),\n body: JSON.stringify(req),\n });\n if (!res.ok) return null; // fail closed (frozen / policy deny / unconfigured)\n const body = (await res.json()) as { grantId?: string };\n return body.grantId ?? null;\n }\n\n async resolve(grantId: string, action: BrokerAction): Promise<ResolvedGrant> {\n const res = await this.fetchFn(`${this.baseUrl}/grants/resolve`, {\n method: \"POST\",\n headers: this.headers(),\n body: JSON.stringify({ grantId, action }),\n });\n if (!res.ok) {\n throw new Error(`grant resolve failed (HTTP ${res.status})`);\n }\n return (await res.json()) as ResolvedGrant;\n }\n\n async revoke(grantId: string, reason: string): Promise<void> {\n await this.fetchFn(`${this.baseUrl}/grants/revoke`, {\n method: \"POST\",\n headers: this.headers(),\n body: JSON.stringify({ grantId, reason }),\n }).catch(() => {});\n }\n}\n\n/**\n * Build the sandbox egress broker for the reference runner, or `undefined` when the\n * flag/transport are not configured (the default \u2014 the runner keeps the legacy\n * fail-closed no-op path). `env`/`fetchFn` are injectable for tests.\n */\nexport function makeSandboxEgress(\n env: NodeJS.ProcessEnv = process.env,\n fetchFn: typeof fetch = fetch,\n): SandboxEgressBroker | undefined {\n if (!isSandboxBrokerEnabled(env)) return undefined;\n const grantUrl = env.STACKS_BROKER_GRANT_URL;\n if (!grantUrl) return undefined; // no grant transport \u2192 fail-closed no-op\n const grants = new HttpGrantPlane(\n grantUrl,\n env.STACKS_BROKER_GRANT_TOKEN,\n fetchFn,\n );\n const broker = new SandboxBroker({\n grants,\n git: spawnGitInjector,\n http: fetchHttpInjector,\n });\n return createSandboxEgress({ broker, grants, env });\n}\n", "/**\n * Optional webhook-less runner scope. An unset scope preserves the historical\n * workspace-wide poller; a configured harness id admits only jobs that prove\n * they belong to that exact run. Generic jobs and other harnesses fail closed.\n */\nexport function pollScopeAllows(\n configuredHarnessRunId: string | undefined,\n jobHarnessRunId: string | null | undefined,\n): boolean {\n const scope = configuredHarnessRunId?.trim();\n if (!scope) return true;\n return jobHarnessRunId === scope;\n}\n\n/** Resolve the run id from either job shape: authoring/decomposition jobs have\n * no stage-level `harness` block yet, while stage jobs carry both forms. */\nexport function jobHarnessRunId(job: {\n harness?: { harnessRunId?: string | null } | null;\n harnessRun?: { id?: string | null } | null;\n}): string | null | undefined {\n return job.harness?.harnessRunId ?? job.harnessRun?.id;\n}\n", "/**\n * run-once.ts \u2014 the exit decision for the runner's once mode (AGE-836).\n *\n * Once mode (STACKS_RUNNER_ONCE=1) lives for the duration of the work it\n * found, then exits; launchd re-spawns it on an interval, so a wedged process\n * can never outlive one respawn cycle the way the immortal poll loop could.\n * The ONLY exit gate is this decision, and both halves are load-bearing:\n *\n * \u2022 `inflight`, never `active` \u2014 the pool gauge that still counts a\n * watchdog-DETACHED orphan turn. Exiting while one runs would kill its\n * SDK session mid-turn; `active` drops to 0 the moment the watchdog frees\n * the slot, `inflight` only on the true settle.\n *\n * \u2022 TWO consecutive idle ticks \u2014 a transition that lands between ticks (a\n * gate side effect draining post-response, a follow-on job minted by the\n * turn that just settled) gets one more look before the process yields\n * the burst to the next spawn. One idle tick would exit into a 2-minute\n * respawn latency for work that was seconds away from discoverable.\n */\n\n/** Structural subset of runner-pool's PoolSnapshot \u2014 all this decision needs. */\nexport interface PoolInflightSnapshot {\n inflight: number;\n}\n\n/** Consecutive idle ticks required before a once-mode process exits. */\nexport const IDLE_TICKS_TO_EXIT = 2;\n\n/**\n * Fold one tick's pool observation into the idle streak: any queued, running,\n * or watchdog-detached work in ANY pool resets the streak to zero; a fully\n * quiet tick extends it. The caller exits at IDLE_TICKS_TO_EXIT.\n */\nexport function nextIdleTicks(\n pools: PoolInflightSnapshot[],\n idleTicks: number,\n): number {\n const busy = pools.some((p) => p.inflight > 0);\n return busy ? 0 : idleTicks + 1;\n}\n", "/**\n * tick-watchdog.ts \u2014 the poll loop's hang detector (AGE-835, corrected AGE-923).\n *\n * AGE-835 raced each tick against a flat 180s timer, so the watchdog measured\n * TOTAL ELAPSED and read every slow tick as a wedge. It is not a hang detector\n * at that budget: one `callTool` can legitimately outlast it, because a\n * RATE_LIMITED reply carries `retryAfterSeconds` up to 60 (the server's bucket\n * is per-minute) and the caller honors it up to four times \u2014 ~244s of\n * DELIBERATE, bounded waiting inside a single supervised call, before the tick's\n * other serial reads are counted at all. That is the \"no completion in 180s on\n * a tick that then succeeds\" observation: the tick was never stuck.\n *\n * A wedge is the absence of PROGRESS, not the presence of duration. So the tick\n * reports each step it finishes and the watchdog fires only when nothing has\n * been reported for `stallMs` \u2014 a genuinely stalled await still trips it (it\n * reports nothing, ever), while a slow-but-live tick no longer does. The last\n * reported step rides in the message, so the next occurrence names the step\n * that overran instead of leaving it to be isolated by hand.\n */\n\nexport interface StallWatchdog {\n /** Report that a step of the supervised work finished. Resets the deadline. */\n progress(step: string): void;\n /** Race `work` against a stall \u2014 NOT against total elapsed time. */\n guard<T>(work: Promise<T>): Promise<T>;\n}\n\nexport function createStallWatchdog(opts: {\n stallMs: number;\n /** How often staleness is sampled. Small values only for tests. */\n checkMs?: number;\n now?: () => number;\n}): StallWatchdog {\n const now = opts.now ?? Date.now;\n const checkMs = opts.checkMs ?? Math.max(1_000, Math.floor(opts.stallMs / 6));\n let lastAt = now();\n let lastStep = \"start\";\n\n return {\n progress(step) {\n lastAt = now();\n lastStep = step;\n },\n guard(work) {\n lastAt = now();\n return Promise.race([\n work,\n new Promise<never>((_, reject) => {\n const timer = setInterval(() => {\n const idleMs = now() - lastAt;\n if (idleMs < opts.stallMs) return;\n clearInterval(timer);\n reject(\n new Error(\n `tick watchdog: no progress for ${Math.round(idleMs / 1000)}s ` +\n `(last completed step: ${lastStep})`,\n ),\n );\n }, checkMs);\n // Deliberately NOT unref'd: a wedged await holds nothing open, so an\n // unref'd sampler would let the loop drain and never fire \u2014 silently\n // absent in exactly the case it exists for. It cannot outlive the\n // tick either, since settling clears it below.\n // Stop sampling when the work settles \u2014 otherwise every tick leaks an\n // interval. The trailing catch keeps a rejected `work` from surfacing\n // twice (the race already delivers it to the caller).\n void work.finally(() => clearInterval(timer)).catch(() => {});\n }),\n ]);\n },\n };\n}\n", "/**\n * Runner revision stamp derivation + the live drift probe (AGE-497).\n *\n * Two halves of one operator complaint: the schema stamp is a hand-maintained\n * value that must equal the control plane's, and a mismatch is SILENT until a\n * claim fails closed with a 409.\n *\n * \u2022 {@link resolveSchemaRevision} \u2014 the stamp is DERIVED from the checkout's\n * newest migration directory when `STACKS_SCHEMA_REVISION` is unset. That is\n * the same value `revisionVerdict` (lib/preflight.ts) already compares\n * against and calls \"the expected value\" \u2014 this uses it instead of asking an\n * operator to hand-copy it. An explicit env value still WINS, because a\n * deliberate pin is what a rollback needs (deploy/RUNBOOK.md).\n * \u2022 {@link probeRevisionHealth} \u2014 asks the control plane's own `/api/health`\n * what it thinks of this runner's stamp, so drift is reported at startup and\n * on a slow timer instead of at the first burnt claim. The endpoint already\n * accepts a worker stamp and answers with the verdict; nothing new server-side.\n *\n * Derivation NEVER hard-fails the runner: an unstamped dev runner against an\n * unstamped dev control plane is legitimate (the compatibility guard is inert),\n * and the probe is the honest oracle for whether `unknown` actually matters here.\n */\nimport * as path from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nimport type { RevisionStamp } from \"../../packages/execution/src/revision.js\";\n\n/**\n * Newest migration id in a `prisma/migrations` listing (they sort lexically).\n *\n * Lives HERE rather than in `preflight.ts` (its original home, which still\n * re-exports it) so the dependency runs one way: preflight consumes the stamp\n * resolution, and the resolution never reaches back into preflight.\n */\nexport function newestMigration(entries: readonly string[]): string | null {\n const dirs = entries.filter((e) => /^\\d{8,}_/.test(e)).sort();\n return dirs.length ? dirs[dirs.length - 1] : null;\n}\n\n/** Where a resolved schema revision came from \u2014 reported in the startup log. */\nexport type SchemaRevisionSource = \"env\" | \"migrations\" | \"none\";\n\nexport interface SchemaRevisionResolution {\n /** The resolved stamp, or null when nothing could be derived. */\n revision: string | null;\n source: SchemaRevisionSource;\n /** A legible one-liner for the startup log. */\n detail: string;\n}\n\n/**\n * The migrations directory of the RUNNER'S OWN tree, resolved from this module's\n * location (`agents/lib/` \u2192 repo root) rather than from cwd or configuration.\n *\n * Deliberately NOT the configured `STACKS_RUNNER_REPOS` checkout, which is the\n * repo the runner drives STAGES in \u2014 a different working copy that legitimately\n * sits at a different commit, and that need not be a Jentrix repo at all (a target\n * project with no `prisma/migrations` would derive nothing and silently present\n * `unknown`, failing every claim closed). The schema stamp describes the contract\n * THIS runner's code was built against, which is the same tree the app stamp's\n * `git rev-parse HEAD` reads.\n */\nexport function runnerMigrationsDir(\n moduleUrl: string = import.meta.url,\n): string {\n return path.resolve(\n path.dirname(fileURLToPath(moduleUrl)),\n \"../../prisma/migrations\",\n );\n}\n\n/**\n * Resolve the schema revision this runner should present. PURE apart from the\n * injected `listDir` seam.\n *\n * An explicit `STACKS_SCHEMA_REVISION` wins \u2014 a deliberate pin is what a rollback\n * needs; otherwise the newest migration directory IS the value, which is exactly\n * what `revisionVerdict` already compares a hand-set stamp against.\n */\nexport function resolveSchemaRevision(\n env: Record<string, string | undefined>,\n listDir: (path: string) => string[],\n migrationsDir: string = runnerMigrationsDir(),\n): SchemaRevisionResolution {\n const explicit = (env.STACKS_SCHEMA_REVISION ?? \"\").trim();\n if (explicit) {\n return {\n revision: explicit,\n source: \"env\",\n detail: `STACKS_SCHEMA_REVISION=${explicit} (explicit \u2014 derivation skipped)`,\n };\n }\n\n let entries: string[];\n try {\n entries = listDir(migrationsDir);\n } catch {\n entries = [];\n }\n const newest = newestMigration(entries);\n return newest\n ? {\n revision: newest,\n source: \"migrations\",\n detail: `derived ${newest} from ${migrationsDir}`,\n }\n : {\n revision: null,\n source: \"none\",\n detail: `no migration directories under ${migrationsDir} \u2014 presenting 'unknown', which a stamped control plane refuses fail-closed`,\n };\n}\n\n/** The control plane's revision probe URL for a given MCP endpoint + stamp. PURE. */\nexport function healthUrlFor(mcpUrl: string, stamp: RevisionStamp): string {\n const url = new URL(\"/api/health\", mcpUrl);\n url.searchParams.set(\"schemaRevision\", stamp.schemaRevision);\n url.searchParams.set(\"appRevision\", stamp.appRevision);\n return url.toString();\n}\n\nexport type RevisionProbeStatus =\n | \"ok\"\n | \"incompatible\"\n | \"unstamped\"\n | \"unreachable\";\n\nexport interface RevisionProbeResult {\n status: RevisionProbeStatus;\n message: string;\n}\n\n/** Interpret an `/api/health` body. PURE \u2014 the fetch seam lives in the caller. */\nexport function readProbeBody(body: unknown): RevisionProbeResult {\n const revision =\n body && typeof body === \"object\"\n ? ((body as Record<string, unknown>).revision as\n | Record<string, unknown>\n | undefined)\n : undefined;\n const status = revision?.status;\n const message = revision?.message;\n if (status === \"ok\" || status === \"incompatible\" || status === \"unstamped\") {\n return {\n status,\n message:\n typeof message === \"string\" && message.trim()\n ? message\n : `control plane reported ${status}`,\n };\n }\n return {\n status: \"unreachable\",\n message: \"control plane /api/health returned an unrecognized body\",\n };\n}\n\n/**\n * Ask the control plane whether THIS runner's stamp is compatible. Never throws\n * and never blocks a start: an unreachable probe reports `unreachable` \u2014 the\n * claim guard remains the authority, this only makes its verdict early and loud.\n */\nexport async function probeRevisionHealth(opts: {\n mcpUrl: string;\n stamp: RevisionStamp;\n fetchImpl?: typeof fetch;\n timeoutMs?: number;\n}): Promise<RevisionProbeResult> {\n const doFetch = opts.fetchImpl ?? fetch;\n try {\n const res = await doFetch(healthUrlFor(opts.mcpUrl, opts.stamp), {\n signal: AbortSignal.timeout(opts.timeoutMs ?? 5_000),\n });\n return readProbeBody(await res.json());\n } catch (err) {\n return {\n status: \"unreachable\",\n message: `could not reach the control plane revision probe: ${\n err instanceof Error ? err.message : String(err)\n }`,\n };\n }\n}\n", "/**\n * `pnpm harness:preflight` \u2014 prove the runner can actually run a stage BEFORE a\n * claim burns (Harness Reliability W6).\n *\n * Bring-up cost about two hours of live debugging on the M18 run, and not one\n * failure was novel: an expired grant, a repo path that moved, a schema stamp\n * nobody re-bumped after a migration, a stopped verification container, a model\n * pin the release would refuse. Each one surfaced as a claim failing mid-flight,\n * minutes apart, with the diagnosis buried in runner logs.\n *\n * Every check here shells out to the same thing the runbook already names \u2014 no\n * new infrastructure, no new state. Decisions are PURE (`renderTable`,\n * `exitCodeFor`, the individual predicates); everything that touches the world is\n * injected, so the smoke test drives the whole table with stubs.\n *\n * Honesty rules, same as the evidence contract: a check that cannot run reports\n * SKIP with the reason, never PASS. A check that FAILS exits non-zero. WARN is\n * for a real observation that is not a blocker (a checkout trailing origin).\n */\nimport { parseRunnerRepos } from \"./harness-worktree.js\";\nimport {\n newestMigration,\n resolveSchemaRevision,\n runnerMigrationsDir,\n type SchemaRevisionResolution,\n} from \"./revision-stamp.js\";\n\n// Re-exported from its new home so existing importers (and the smoke test) are\n// unaffected by the move that broke the preflight \u2194 revision-stamp cycle.\nexport { newestMigration };\n\nexport type CheckStatus = \"PASS\" | \"FAIL\" | \"WARN\" | \"SKIP\";\n\nexport interface CheckResult {\n name: string;\n status: CheckStatus;\n detail: string;\n}\n\nexport interface PreflightDeps {\n env: Record<string, string | undefined>;\n /** Resolve a role's bearer (exercises the D4 bootstrap grant on self-hosted). */\n resolveToken: (role: \"runner\" | \"planner\" | \"reviewer\") => Promise<string>;\n /** List the MCP tool names the endpoint exposes to this bearer. */\n listTools: (token: string) => Promise<string[]>;\n /** Call one MCP tool (used for the identity probe). */\n callTool: (\n token: string,\n name: string,\n args: Record<string, unknown>,\n ) => Promise<Record<string, unknown>>;\n git: (cwd: string, args: string[]) => Promise<string>;\n exists: (path: string) => boolean;\n /** Directory listing (used to read the repo's migration ids). */\n listDir: (path: string) => string[];\n /** Prove the managed verification substrate can start a container. */\n verificationPreflight: () => Promise<void>;\n /** TCP reachability probe for the codex bridge. */\n probeTcp: (host: string, port: number) => Promise<boolean>;\n /** Is the claim URL answering? MUST NOT redeem anything \u2014 the self-hosted\n * bootstrap grant is one-time, and spending it here would break the very\n * runner start this command exists to protect. */\n probeClaimUrl: (url: string) => Promise<boolean>;\n}\n\n// --- Pure predicates --------------------------------------------------------\n\n/** Env keys without which the runner cannot start at all. */\nexport const REQUIRED_ENV = [\n \"STACKS_MCP_URL\",\n \"STACKS_RUNNER_REPOS\",\n \"STACKS_RUNNER_MODE\",\n] as const;\n\nexport function missingEnv(env: PreflightDeps[\"env\"]): string[] {\n return REQUIRED_ENV.filter((k) => !(env[k] ?? \"\").trim());\n}\n\n/**\n * The schema revision the runner PRESENTS on every claim must match the schema\n * the control plane was built against, or the fail-closed claim guard refuses\n * every claim.\n *\n * Since AGE-497 the stamp DERIVES from this runner tree's newest migration\n * directory, so the healthy state carries no explicit value at all and there is\n * nothing to re-stamp \u2014 this check exists for the two states that are still\n * wrong: nothing derivable (presenting 'unknown', which a stamped control plane\n * refuses), and an explicit PIN that has fallen behind the repo. A pin is\n * legitimate for a rollback, so a stale one is reported as a pin to release,\n * never as a value to hand-bump.\n */\nexport function revisionVerdict(\n resolution: SchemaRevisionResolution,\n latestMigration: string | null,\n): CheckResult {\n const name = \"schema revision\";\n if (resolution.source === \"none\") {\n return {\n name,\n status: \"FAIL\",\n detail: `${resolution.detail} \u2014 a stamped control plane refuses every claim fail-closed.`,\n };\n }\n if (resolution.source === \"migrations\") {\n return {\n name,\n status: \"PASS\",\n detail: `derived ${resolution.revision} (no explicit stamp; nothing to re-stamp)`,\n };\n }\n const stamped = resolution.revision as string;\n if (!latestMigration) {\n return {\n name,\n status: \"SKIP\",\n detail: `pinned to ${stamped}; could not read prisma/migrations to compare`,\n };\n }\n return stamped === latestMigration\n ? {\n name,\n status: \"PASS\",\n detail: `${stamped} (explicit pin, matches the newest migration)`,\n }\n : {\n name,\n status: \"FAIL\",\n detail: `STACKS_SCHEMA_REVISION is explicitly pinned to ${stamped} but this tree's newest migration is ${latestMigration}. Unset it to derive the stamp (the default), or move the pin if you are deliberately holding a rollback. Every claim fails closed until it matches the control plane.`,\n };\n}\n\n/**\n * What a claim will PRESENT: the per-leg model pins plus the accepted-models set\n * built exactly the way `claimPresentation`/`workerCapabilities` build it \u2014 the\n * launched model is always vouched for, and a Claude claim additionally vouches\n * for BOTH leg pins.\n *\n * INFORMATIONAL by design. It reports rather than fails, because a pin missing\n * from `STACKS_*_ACCEPTED_MODELS` is *not* a refusal cause (the worker vouches\n * for what it launches), and the check that does have teeth \u2014 pin vs. the ACTIVE\n * RELEASE's pinned model \u2014 is run-scoped and already enforced server-side at\n * launch. Reporting the resolved pins is still worth a row: a silent model change\n * must be diagnosable from the ledger, and this is where an operator sees which\n * models the next claim will actually present.\n */\nexport function modelPinVerdict(env: PreflightDeps[\"env\"]): CheckResult {\n const list = (raw: string | undefined): string[] =>\n (raw ?? \"\")\n .split(/[,\\s]+/)\n .map((s) => s.trim())\n .filter(Boolean);\n const planner = (\n env.STACKS_PLANNER_MODEL ??\n env.STACKS_AGENT_MODEL ??\n \"\"\n ).trim();\n const executor = (\n env.STACKS_EXECUTOR_MODEL ??\n env.STACKS_AGENT_MODEL ??\n \"\"\n ).trim();\n const codex = (env.STACKS_CODEX_MODEL ?? \"\").trim();\n const pins = [\n planner && `planner=${planner}`,\n executor && `executor=${executor}`,\n codex && `codex=${codex}`,\n ].filter(Boolean);\n if (pins.length === 0) {\n return {\n name: \"model pins\",\n status: \"SKIP\",\n detail: \"no model pins configured \u2014 the provider default applies\",\n };\n }\n // Mirror the claim's vouching rule so the row shows the ACTUAL presented set.\n const vouched = new Set([\n ...list(env.STACKS_CLAUDE_ACCEPTED_MODELS),\n ...list(env.STACKS_CODEX_ACCEPTED_MODELS),\n ...[planner, executor, codex].filter(Boolean),\n ]);\n return {\n name: \"model pins\",\n status: \"PASS\",\n detail: `${pins.join(\", \")} \u00B7 vouched: ${[...vouched].join(\", \")}`,\n };\n}\n\n/**\n * Normalize a git remote URL to a lowercase `owner/name`, or null when it is not\n * a recognizable GitHub-style remote. PURE.\n *\n * The HOST is deliberately not compared. The push path builds its own URL from\n * the trusted `owner`/`name` (services/sandbox-controller/src/adapters.ts), so\n * the local remote's host is not what gets pushed to, and comparing it would\n * false-positive an SSH-vs-HTTPS or GHE-vs-github.com checkout.\n */\nexport function normalizeRemoteRepo(url: string): string | null {\n const raw = url.trim();\n if (!raw) return null;\n // scp-like: git@github.com:owner/name.git (no scheme, colon-separated path).\n const scp = /^[^/]+@([^:/]+):(.+)$/.exec(raw);\n let pathPart: string;\n if (scp) {\n pathPart = scp[2];\n } else {\n try {\n pathPart = new URL(raw).pathname;\n } catch {\n return null;\n }\n }\n const trimmed = pathPart\n .replace(/\\/+$/, \"\")\n .replace(/\\.git$/, \"\")\n .split(\"/\")\n .filter(Boolean);\n if (trimmed.length < 2) return null;\n return `${trimmed[0]}/${trimmed[1]}`.toLowerCase();\n}\n\n/**\n * Does the checkout's `origin` actually point at the repo it is mapped to?\n *\n * Weak by construction and that is worth stating: a SECOND clone of the SAME\n * repository passes this. It guards against a genuinely wrong repository, not\n * against the wrong copy of the right one \u2014 {@link checkoutBranchVerdict} and\n * {@link freshnessVerdict} are what catch that.\n *\n * `remote` is raw `git remote get-url origin` output, or null when there is no\n * origin at all \u21D2 SKIP: a check that cannot run never reports PASS, and a\n * local-only checkout cannot break execution (worktrees branch from local refs\n * and push builds its own URL). PURE.\n */\nexport function remoteIdentityVerdict(\n name: string,\n repo: string,\n remote: string | null,\n): CheckResult {\n if (remote === null || !remote.trim()) {\n return {\n name,\n status: \"SKIP\",\n detail: \"no origin remote \u2014 cannot verify the checkout's repository\",\n };\n }\n const actual = normalizeRemoteRepo(remote);\n if (!actual) {\n return {\n name,\n status: \"SKIP\",\n detail: `origin ${remote.trim()} is not a recognizable GitHub-style remote \u2014 cannot verify`,\n };\n }\n return actual === repo.toLowerCase()\n ? { name, status: \"PASS\", detail: `origin is ${actual}` }\n : {\n name,\n status: \"FAIL\",\n detail: `mapped to ${repo} but origin is ${actual} \u2014 STACKS_RUNNER_REPOS points at the wrong repository`,\n };\n}\n\n/** Stage branches are `harness/\u2026`; a SOURCE checkout must never be parked on one. */\nconst STAGE_BRANCH_PREFIX = \"harness/\";\n\n/**\n * Is the checkout on a branch a runner may ground stages from? PURE.\n *\n * `head` is `git symbolic-ref --short -q HEAD` output (\"\" \u21D2 detached).\n *\n * This is the row that catches the AGE-497 incident. A source checkout parked on\n * a stage branch is never legitimate: `refreshGroundingCheckout` fast-forwards it\n * to the base and every stage worktree is cut from it, so a `harness/` HEAD means\n * the checkout is a spent execution tree, not a base.\n */\nexport function checkoutBranchVerdict(\n name: string,\n head: string,\n base: string,\n): CheckResult {\n const branch = head.trim();\n if (!branch) {\n return {\n name,\n status: \"FAIL\",\n detail:\n \"checkout is in detached HEAD \u2014 a runner cannot ground stages from it\",\n };\n }\n if (branch.startsWith(STAGE_BRANCH_PREFIX)) {\n return {\n name,\n status: \"FAIL\",\n detail: `checkout is parked on stage branch ${branch} \u2014 this is a spent execution tree, not a base. Point STACKS_RUNNER_REPOS at a checkout tracking ${base}.`,\n };\n }\n return branch === base\n ? { name, status: \"PASS\", detail: `on ${branch}` }\n : {\n name,\n status: \"WARN\",\n detail: `on ${branch}, not the base branch ${base} \u2014 stages will branch from it`,\n };\n}\n\n/**\n * Is the checkout current with its upstream? PURE.\n *\n * FAILS when the fetch SUCCEEDED (a real, current lag \u2014 the runtime path already\n * throws on exactly this in `refreshGroundingCheckout`, so a WARN here while the\n * live path throws is an inconsistency, not a policy). Stays a WARN when the\n * fetch failed, because the number then came off a stale cached ref and an\n * offline machine must not be blocked on evidence it could not gather.\n */\nexport function freshnessVerdict(\n name: string,\n cwd: string,\n behind: number,\n fetched: boolean,\n upstream: string,\n): CheckResult {\n if (behind <= 0) {\n return {\n name,\n status: \"PASS\",\n detail: `${cwd}: current with ${upstream}${fetched ? \"\" : \" (fetch failed \u2014 number may be stale)\"}`,\n };\n }\n return fetched\n ? {\n name,\n status: \"FAIL\",\n detail: `${cwd}: ${behind} commit(s) behind ${upstream} \u2014 stages would branch from an older base. Pull it, then restart the runner.`,\n }\n : {\n name,\n status: \"WARN\",\n detail: `${cwd}: ${behind} commit(s) behind ${upstream} (fetch failed \u2014 number may be stale)`,\n };\n}\n\n/** Fixed-width PASS/FAIL table. PURE. */\nexport function renderTable(rows: readonly CheckResult[]): string {\n const width = Math.max(4, ...rows.map((r) => r.name.length));\n const lines = rows.map(\n (r) => `${r.status.padEnd(4)} ${r.name.padEnd(width)} ${r.detail}`,\n );\n const failed = rows.filter((r) => r.status === \"FAIL\").length;\n const warned = rows.filter((r) => r.status === \"WARN\").length;\n const skipped = rows.filter((r) => r.status === \"SKIP\").length;\n return [\n ...lines,\n \"\",\n failed\n ? `${failed} check(s) FAILED \u2014 fix the rows above before starting the runner.`\n : `All checks passed${warned ? ` (${warned} warning(s))` : \"\"}${\n skipped ? `, ${skipped} skipped` : \"\"\n }.`,\n ].join(\"\\n\");\n}\n\n/** Non-zero when ANY check failed. PURE. */\nexport function exitCodeFor(rows: readonly CheckResult[]): number {\n return rows.some((r) => r.status === \"FAIL\") ? 1 : 0;\n}\n\n// --- The checks -------------------------------------------------------------\n\nasync function attempt(\n name: string,\n fn: () => Promise<CheckResult>,\n): Promise<CheckResult> {\n try {\n return await fn();\n } catch (e) {\n return {\n name,\n status: \"FAIL\",\n detail: e instanceof Error ? e.message : String(e),\n };\n }\n}\n\n/** Every check, in the order an operator debugs them. */\nexport async function runPreflight(\n deps: PreflightDeps,\n): Promise<CheckResult[]> {\n const rows: CheckResult[] = [];\n const env = deps.env;\n\n const missing = missingEnv(env);\n rows.push(\n missing.length\n ? {\n name: \"environment\",\n status: \"FAIL\",\n detail: `missing ${missing.join(\", \")}`,\n }\n : {\n name: \"environment\",\n status: \"PASS\",\n detail: `mode=${env.STACKS_RUNNER_MODE}, mcp=${env.STACKS_MCP_URL}`,\n },\n );\n\n // The runner credential.\n //\n // On a SELF-HOSTED runner the bootstrap grant is ONE-TIME: the first claim\n // spends it and rotates to an in-process refresh credential. So resolving a\n // bearer here would consume the very grant the runner is about to need, and\n // the runner would then fail to start \u2014 a preflight that breaks the thing it\n // is checking. (Observed on the first live run of this command, 2026-07-27.)\n // The endpoint is probed for reachability instead, and the row says plainly\n // that grant validity was NOT proven. On the MANAGED path the exchange is\n // repeatable, so the bearer is really resolved.\n let runnerToken: string | null = null;\n const selfHosted = /^self-?hosted$/i.test(env.STACKS_RUNNER_MODE ?? \"\");\n rows.push(\n await attempt(\"runner credential\", async () => {\n if (selfHosted) {\n const claimUrl = (env.STACKS_CLAIM_URL ?? \"\").trim();\n if (!claimUrl || !(env.STACKS_BOOTSTRAP_TOKEN ?? \"\").trim()) {\n return {\n name: \"runner credential\",\n status: \"FAIL\",\n detail:\n \"self-hosted mode needs STACKS_BOOTSTRAP_TOKEN + STACKS_CLAIM_URL \u2014 mint a grant with POST /api/agents/bootstrap\",\n };\n }\n const reachable = await deps.probeClaimUrl(claimUrl);\n return reachable\n ? {\n name: \"runner credential\",\n status: \"SKIP\",\n detail:\n \"claim URL is reachable; the bootstrap grant is ONE-TIME so it is deliberately NOT redeemed here (redeeming would spend the grant the runner needs). Mint a fresh grant immediately before starting the runner.\",\n }\n : {\n name: \"runner credential\",\n status: \"FAIL\",\n detail: `claim URL ${claimUrl} is unreachable \u2014 the runner cannot obtain any role token`,\n };\n }\n runnerToken = await deps.resolveToken(\"runner\");\n return {\n name: \"runner credential\",\n status: \"PASS\",\n detail: `resolved a ${env.STACKS_RUNNER_MODE ?? \"?\"} runner bearer (${runnerToken.slice(0, 4)}\u2026)`,\n };\n }),\n );\n\n // The endpoint probe uses a read token when one is configured, so the MCP and\n // workspace rows stay meaningful on the self-hosted path without spending the\n // one-time grant above.\n const probeToken = runnerToken ?? (env.STACKS_TOKEN ?? \"\").trim() ?? null;\n rows.push(\n await attempt(\"MCP surface\", async () => {\n if (!probeToken) {\n return {\n name: \"MCP surface\",\n status: \"SKIP\",\n detail:\n \"no bearer available to probe with (the one-time grant is not spent here; set STACKS_TOKEN for a read-only probe)\",\n };\n }\n const tools = await deps.listTools(probeToken);\n return tools.length > 0\n ? {\n name: \"MCP surface\",\n status: \"PASS\",\n detail: `${tools.length} tools at ${env.STACKS_MCP_URL}`,\n }\n : {\n name: \"MCP surface\",\n status: \"FAIL\",\n detail: \"the endpoint exposed ZERO tools to this bearer\",\n };\n }),\n );\n\n rows.push(\n await attempt(\"workspace access\", async () => {\n if (!probeToken) {\n return {\n name: \"workspace access\",\n status: \"SKIP\",\n detail: \"no bearer available to probe with\",\n };\n }\n const res = (await deps.callTool(probeToken, \"list_workspaces\", {})) as {\n workspaces?: Array<{ slug?: string }>;\n };\n const slugs = (res.workspaces ?? []).map((w) => w.slug).filter(Boolean);\n return slugs.length\n ? {\n name: \"workspace access\",\n status: \"PASS\",\n detail: slugs.join(\", \"),\n }\n : {\n name: \"workspace access\",\n status: \"FAIL\",\n detail: \"the bearer authenticated but sees no workspace\",\n };\n }),\n );\n\n rows.push(...(await checkRepos(deps)));\n\n rows.push(\n await attempt(\"schema revision\", async () => {\n // The runner's OWN tree, never the configured work checkout \u2014 that one\n // legitimately sits at another commit and need not be a Jentrix repo at\n // all. Same resolution the runner presents on every claim.\n const dir = runnerMigrationsDir();\n const resolution = resolveSchemaRevision(\n env,\n (p) => safeList(deps, p),\n dir,\n );\n return revisionVerdict(resolution, newestMigration(safeList(deps, dir)));\n }),\n );\n\n rows.push(modelPinVerdict(env));\n\n rows.push(\n await attempt(\"verification substrate\", async () => {\n await deps.verificationPreflight();\n return {\n name: \"verification substrate\",\n status: \"PASS\",\n detail: `${env.STACKS_VERIFICATION_IMAGE ?? \"default image\"} started a container`,\n };\n }),\n );\n\n rows.push(await checkCodexBridge(deps));\n\n return rows;\n}\n\n/**\n * The narrow slice of {@link PreflightDeps} the repo checks actually touch, so\n * the RUNNER can call {@link checkRepos} at start-up without assembling the whole\n * preflight surface (tokens, docker, TCP probes).\n */\nexport type RepoCheckDeps = Pick<PreflightDeps, \"env\" | \"exists\" | \"git\">;\n\n/**\n * Downgrade the checkout-state FAILs to WARN. Exists because a developer\n * debugging a stage in place has a legitimately `harness/`-parked checkout, and\n * a guard with no hatch gets worked around by reverting the guard.\n */\nexport const STALE_CHECKOUT_OVERRIDE = \"STACKS_RUNNER_ALLOW_STALE_CHECKOUT\";\n\n/**\n * The two row kinds {@link STALE_CHECKOUT_OVERRIDE} may soften. Everything else\n * stays FAIL under the override: a wrong repository, a missing checkout, or an\n * unparseable `STACKS_RUNNER_REPOS` is never made correct by local debugging.\n */\nconst DOWNGRADABLE_ROW_SUFFIXES = [\" branch\", \" freshness\"] as const;\n\n/** Apply {@link STALE_CHECKOUT_OVERRIDE} to a row set. PURE. */\nexport function applyStaleCheckoutOverride(\n rows: readonly CheckResult[],\n enabled: boolean,\n): CheckResult[] {\n if (!enabled) return [...rows];\n return rows.map((r) =>\n r.status === \"FAIL\" &&\n DOWNGRADABLE_ROW_SUFFIXES.some((suffix) => r.name.endsWith(suffix))\n ? {\n ...r,\n status: \"WARN\" as const,\n detail: `${r.detail} [${STALE_CHECKOUT_OVERRIDE}=1 \u2014 downgraded]`,\n }\n : r,\n );\n}\n\n/**\n * Validate every configured checkout. Exported because the runner runs this at\n * start-up and REFUSES to start on a FAIL \u2014 the AGE-497 lesson is that a check\n * living only in a manually-invoked command is a check nobody runs.\n */\nexport async function checkRepos(deps: RepoCheckDeps): Promise<CheckResult[]> {\n const raw = safeJson(deps.env.STACKS_RUNNER_REPOS);\n let repos: ReturnType<typeof parseRunnerRepos>;\n try {\n repos = parseRunnerRepos(raw);\n } catch (e) {\n return [\n {\n name: \"repos\",\n status: \"FAIL\",\n detail: e instanceof Error ? e.message : String(e),\n },\n ];\n }\n const entries = Object.entries(repos);\n if (entries.length === 0) {\n return [\n { name: \"repos\", status: \"FAIL\", detail: \"STACKS_RUNNER_REPOS is empty\" },\n ];\n }\n const rows: CheckResult[] = [];\n for (const [repo, entry] of entries) {\n const name = `repo ${repo}`;\n const cwd = entry.config.checkout;\n if (!deps.exists(cwd)) {\n rows.push({\n name,\n status: \"FAIL\",\n detail: `checkout ${cwd} does not exist`,\n });\n continue;\n }\n const gitOut = async (args: string[]): Promise<string> =>\n (await deps.git(cwd, args).catch(() => \"\")).trim();\n\n rows.push(\n await attempt(`${name} branch`, async () => {\n const inside = await gitOut([\"rev-parse\", \"--is-inside-work-tree\"]);\n if (inside !== \"true\") {\n return {\n name,\n status: \"FAIL\",\n detail: `${cwd} is not a git checkout`,\n };\n }\n // The REPO's default branch, from origin/HEAD \u2014 never the current\n // branch's upstream. A checkout parked on a stage branch tracks that\n // stage branch, so deriving the base from the upstream would advise the\n // operator to \"track harness/\u2026-stage-9\", which is the broken state\n // itself. Not every clone has origin/HEAD set, hence the fallback.\n const base =\n (\n await gitOut([\n \"symbolic-ref\",\n \"--short\",\n \"refs/remotes/origin/HEAD\",\n ])\n ).replace(/^origin\\//, \"\") || \"main\";\n const head = await gitOut([\"symbolic-ref\", \"--short\", \"-q\", \"HEAD\"]);\n return checkoutBranchVerdict(`${name} branch`, head, base);\n }),\n );\n\n rows.push(\n await attempt(`${name} origin`, async () =>\n remoteIdentityVerdict(\n `${name} origin`,\n repo,\n (await gitOut([\"remote\", \"get-url\", \"origin\"])) || null,\n ),\n ),\n );\n\n rows.push(\n await attempt(`${name} freshness`, async () => {\n const upstream =\n (await gitOut([\"rev-parse\", \"--abbrev-ref\", \"@{upstream}\"])) ||\n \"origin/main\";\n // Fetching is what makes the freshness number mean anything; an offline\n // machine still gets a comparison against whatever ref it has.\n let fetched = true;\n try {\n await deps.git(cwd, [\"fetch\", \"--quiet\", \"origin\"]);\n } catch {\n fetched = false;\n }\n const behind = await gitOut([\n \"rev-list\",\n \"--count\",\n `HEAD..${upstream}`,\n ]);\n return freshnessVerdict(\n `${name} freshness`,\n cwd,\n Number(behind) || 0,\n fetched,\n upstream,\n );\n }),\n );\n }\n return rows;\n}\n\nasync function checkCodexBridge(deps: PreflightDeps): Promise<CheckResult> {\n const name = \"codex bridge\";\n const provider = (deps.env.STACKS_AGENT_PROVIDER ?? \"\").trim();\n const port = Number(deps.env.STACKS_CODEX_BRIDGE_PORT ?? 8791);\n const usesCodex =\n provider === \"codex\" || Boolean((deps.env.STACKS_CODEX_MODEL ?? \"\").trim());\n if (!usesCodex) {\n return { name, status: \"SKIP\", detail: \"no codex leg configured\" };\n }\n const up = await deps.probeTcp(\"127.0.0.1\", port).catch(() => false);\n return up\n ? { name, status: \"PASS\", detail: `answering on 127.0.0.1:${port}` }\n : {\n name,\n status: \"FAIL\",\n detail: `nothing answering on 127.0.0.1:${port} \u2014 start it with \\`pnpm --dir agents codex-provider-bridge\\``,\n };\n}\n\nfunction safeJson(raw: string | undefined): unknown {\n if (!raw?.trim()) return null;\n try {\n return JSON.parse(raw);\n } catch {\n throw new Error(\"STACKS_RUNNER_REPOS is not valid JSON\");\n }\n}\n\nfunction safeList(deps: PreflightDeps, path: string): string[] {\n try {\n return deps.listDir(path);\n } catch {\n return [];\n }\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
6
|
"names": ["spawn", "existsSync", "SCRUBBED_ENV_KEYS", "execFile", "promisify", "execFileP", "runGit", "runGit", "spawn", "resolve", "DRIVER", "spawn", "resolve", "spawn", "resolve", "manifest", "envelope", "dirname", "cache", "path", "dirname", "createHash", "readFileSync", "path", "createHash", "execFile", "existsSync", "mkdir", "path", "promisify", "execFileP", "promisify", "execFile", "runGit", "readOwnerState", "existsSync", "res", "assertUnder", "mkdir", "resolve", "jobHarnessRunId", "path", "fileURLToPath", "attempt", "resolve", "spawn", "existsSync"]
|
|
7
7
|
}
|