{"version":3,"file":"worktree.d.ts","sourceRoot":"","sources":["../../src/code/worktree.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n\tcp,\n\tlstat,\n\tmkdir,\n\tmkdtemp,\n\treaddir,\n\treadFile,\n\treadlink,\n\trealpath,\n\trm,\n\trmdir,\n\tsymlink,\n\twriteFile,\n} from \"node:fs/promises\";\nimport { tmpdir } from \"node:os\";\nimport { basename, delimiter, dirname, join, relative, resolve, sep } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport type { EvoPaths } from \"../paths.ts\";\nimport { atomicWriteFile, atomicWriteJson, canonicalJson, readJson, sha256, withFileLock } from \"../storage.ts\";\nimport { type CommandResult, type CommandRunner, SpawnCommandRunner } from \"./command-runner.ts\";\n\nconst CODE_WORKSPACE_SCHEMA_VERSION = 1;\nconst GIT_OUTPUT_LIMIT = 64 * 1024 * 1024;\nconst VALIDATION_OUTPUT_LIMIT = 1024 * 1024;\nconst VALIDATION_TIMEOUT_MS = 15 * 60 * 1000;\nconst CODE_LOCK_STALE_MS = 4 * 60 * 60 * 1000;\nconst SANDBOX_ROOT = \"/evo-validation\";\nconst PROPOSAL_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;\nconst DIGEST_PATTERN = /^[a-f0-9]{64}$/;\nconst DEPENDENCY_FILE_NAMES = new Set([\n\t\"package.json\",\n\t\"package-lock.json\",\n\t\"npm-shrinkwrap.json\",\n\t\"pnpm-lock.yaml\",\n\t\"yarn.lock\",\n\t\"bun.lock\",\n\t\"bun.lockb\",\n\t\"deno.lock\",\n\t\"cargo.toml\",\n\t\"cargo.lock\",\n\t\"pyproject.toml\",\n\t\"poetry.lock\",\n\t\"uv.lock\",\n\t\"requirements.txt\",\n\t\"pipfile\",\n\t\"pipfile.lock\",\n\t\"go.mod\",\n\t\"go.sum\",\n\t\"gemfile\",\n\t\"gemfile.lock\",\n]);\n\nexport interface CodeValidationCheck {\n\tname: string;\n\tresult: CommandResult;\n}\n\nexport interface CodeL1Result {\n\tpassed: boolean;\n\terrors: string[];\n\tchecks: CodeValidationCheck[];\n}\n\nexport interface CodeValidationContext {\n\trepositoryRoot: string;\n\tworktreePath: string;\n\tbaseCommit: string;\n\tchangedPaths: string[];\n\tcommandRunner: CommandRunner;\n\tsignal?: AbortSignal;\n}\n\nexport interface CodeValidationExecutor {\n\tvalidate(context: CodeValidationContext): Promise<CodeL1Result>;\n}\n\nexport interface CodeWorktreeRevision {\n\tschemaVersion: 1;\n\tproposalId: string;\n\trevision: number;\n\tparentBundleDigest: string;\n\trepositoryRoot: string;\n\trepositoryIdentity: string;\n\tbaseCommit: string;\n\tbranch: string;\n\tworktreePath: string;\n\trevisionDirectory: string;\n\tpatchFile: string;\n\tdiffFile: string;\n\tchangedPaths: string[];\n\tdiff: string;\n\tapprovalDigest: string;\n\tdiffDigest: string;\n\tl1: CodeL1Result;\n}\n\ntype PersistedCodeWorktreeRevision = Omit<CodeWorktreeRevision, \"diff\">;\n\nexport interface CodeBuilderWorkspace {\n\trunId: string;\n\trepositoryRoot: string;\n\trepositoryIdentity: string;\n\tbaseCommit: string;\n\tworktreePath: string;\n}\n\nexport interface CodeBuilderSnapshot {\n\tpatch: string;\n\tchangedPaths: string[];\n\trepositoryRoot: string;\n\trepositoryIdentity: string;\n\tbaseCommit: string;\n}\n\nexport interface StageCodeWorktreeOptions {\n\tpaths: EvoPaths;\n\trepositoryCwd: string;\n\tproposalId: string;\n\trevision: number;\n\tparentBundleDigest: string;\n\tpatch: string;\n\texpectedRepositoryRoot?: string;\n\texpectedRepositoryIdentity?: string;\n\texpectedBaseCommit?: string;\n\tcommandRunner?: CommandRunner;\n\tvalidationExecutor?: CodeValidationExecutor;\n\tsignal?: AbortSignal;\n}\n\nexport interface RevalidateCodeWorktreeOptions {\n\tpaths: EvoPaths;\n\tproposalId: string;\n\trevision: number;\n\texpectedApprovalDigest: string;\n\texpectedRepositoryRoot: string;\n\texpectedRepositoryIdentity: string;\n\texpectedBaseCommit: string;\n\texpectedParentBundleDigest: string;\n\tcommandRunner?: CommandRunner;\n\tvalidationExecutor?: CodeValidationExecutor;\n\tsignal?: AbortSignal;\n}\n\ninterface RepositoryInfo {\n\troot: string;\n\tidentity: string;\n\tbaseCommit: string;\n}\n\ninterface CandidateSnapshot {\n\tchangedPaths: string[];\n\tdiff: string;\n\tapprovalDigest: string;\n\tdiffDigest: string;\n}\n\ninterface ValidationCommand {\n\tname: string;\n\tcommand: string;\n\targs: string[];\n\tcwd: string;\n}\n\nexport class CodeWorktreeIntegrityError extends Error {}\n\nfunction errorMessage(error: unknown): string {\n\treturn error instanceof Error ? error.message : String(error);\n}\n\nfunction assertProposalRevision(proposalId: string, revision: number): void {\n\tif (!PROPOSAL_ID_PATTERN.test(proposalId)) throw new Error(`Invalid proposal id: ${proposalId}`);\n\tif (!Number.isSafeInteger(revision) || revision <= 0) throw new Error(\"revision must be a positive safe integer\");\n}\n\nfunction assertBundleDigest(digest: string): void {\n\tif (!DIGEST_PATTERN.test(digest)) throw new Error(\"parentBundleDigest must be a sha256 digest\");\n}\n\nfunction revisionPaths(paths: EvoPaths, proposalId: string, revision: number) {\n\tconst revisionName = `r${revision}`;\n\tconst revisionDirectory = join(paths.proposals, proposalId, \"revisions\", String(revision));\n\treturn {\n\t\tbranch: `evo/${proposalId}/${revisionName}`,\n\t\tworktreePath: join(paths.worktrees, proposalId, revisionName),\n\t\trevisionDirectory,\n\t\tpatchFile: join(revisionDirectory, \"candidate.patch\"),\n\t\tdiffFile: join(revisionDirectory, \"code.diff\"),\n\t\tl1File: join(revisionDirectory, \"l1.json\"),\n\t\tworkspaceFile: join(revisionDirectory, \"workspace.json\"),\n\t};\n}\n\nasync function runCommand(\n\trunner: CommandRunner,\n\tcommand: string,\n\targs: readonly string[],\n\tcwd: string,\n\toptions: { timeoutMs?: number; env?: NodeJS.ProcessEnv; maxOutputBytes?: number; signal?: AbortSignal } = {},\n): Promise<CommandResult> {\n\treturn runner.run(command, args, {\n\t\tcwd,\n\t\tmaxOutputBytes: options.maxOutputBytes ?? GIT_OUTPUT_LIMIT,\n\t\t...(options.timeoutMs ? { timeoutMs: options.timeoutMs } : {}),\n\t\t...(options.env ? { env: options.env } : {}),\n\t\t...(options.signal ? { signal: options.signal } : {}),\n\t});\n}\n\nfunction assertSucceeded(result: CommandResult, label: string): void {\n\tif (result.code === 0 && !result.killed && !result.outputLimitExceeded) return;\n\tconst detail = result.stderr.trim() || result.stdout.trim() || `exit ${result.code}`;\n\tthrow new Error(`${label} failed: ${detail}`);\n}\n\nasync function runGit(\n\trunner: CommandRunner,\n\tcwd: string,\n\targs: readonly string[],\n\tlabel: string,\n): Promise<CommandResult> {\n\tconst result = await runCommand(runner, \"git\", [\"-C\", cwd, ...args], cwd);\n\tassertSucceeded(result, label);\n\treturn result;\n}\n\nasync function repositoryIdentity(runner: CommandRunner, cwd: string): Promise<string> {\n\tconst commonDirectory = (\n\t\tawait runGit(\n\t\t\trunner,\n\t\t\tcwd,\n\t\t\t[\"rev-parse\", \"--path-format=absolute\", \"--git-common-dir\"],\n\t\t\t\"Resolve Git common directory\",\n\t\t)\n\t).stdout.trim();\n\treturn sha256(await realpath(commonDirectory));\n}\n\nasync function inspectRepository(runner: CommandRunner, cwd: string): Promise<RepositoryInfo> {\n\tconst root = await realpath(\n\t\t(await runGit(runner, cwd, [\"rev-parse\", \"--show-toplevel\"], \"Resolve repository root\")).stdout.trim(),\n\t);\n\tconst baseCommit = (\n\t\tawait runGit(runner, root, [\"rev-parse\", \"--verify\", \"HEAD^{commit}\"], \"Resolve repository HEAD\")\n\t).stdout.trim();\n\treturn { root, identity: await repositoryIdentity(runner, root), baseCommit };\n}\n\n/**\n * Code candidates always patch Evo-Pi's own source repository — the git\n * repository containing this file — never the incidental working directory of\n * whichever session happened to trigger the evolution cycle.\n */\nexport async function resolveEvoSourceRepositoryRoot(runner?: CommandRunner): Promise<string> {\n\tconst commandRunner = runner ?? new SpawnCommandRunner();\n\tconst sourceDirectory = dirname(fileURLToPath(import.meta.url));\n\tconst root = await runGit(\n\t\tcommandRunner,\n\t\tsourceDirectory,\n\t\t[\"rev-parse\", \"--show-toplevel\"],\n\t\t\"Resolve Evo-Pi source repository root\",\n\t);\n\treturn realpath(root.stdout.trim());\n}\n\nfunction assertSafeChangedPath(path: string): void {\n\tif (!path || path.includes(\"\\\\\") || path.includes(\"\\0\") || path.startsWith(\"/\")) {\n\t\tthrow new Error(`Code proposal contains an unsafe path: ${JSON.stringify(path)}`);\n\t}\n\tconst segments = path.split(\"/\");\n\tif (segments.some((segment) => !segment || segment === \".\" || segment === \"..\")) {\n\t\tthrow new Error(`Code proposal contains an unsafe path: ${path}`);\n\t}\n\tconst normalized = path.toLowerCase();\n\tconst fileName = basename(normalized);\n\tif (normalized === \".git\" || normalized.startsWith(\".git/\") || normalized === \".gitmodules\") {\n\t\tthrow new Error(`Code proposal cannot change Git control paths: ${path}`);\n\t}\n\tif (\n\t\tnormalized.startsWith(\"packages/evo/src/prompts/\") ||\n\t\tnormalized.startsWith(\"packages/evo/src/registry/\") ||\n\t\tnormalized === \"packages/evo/src/storage.ts\"\n\t) {\n\t\tthrow new Error(`Code proposal cannot change Evo-Pi judge or apply/rollback paths: ${path}`);\n\t}\n\tif (\n\t\tDEPENDENCY_FILE_NAMES.has(fileName) ||\n\t\tnormalized.includes(\"/node_modules/\") ||\n\t\tnormalized.startsWith(\"node_modules/\") ||\n\t\tnormalized.includes(\"/install-lock/\") ||\n\t\tnormalized.startsWith(\"packages/coding-agent/install-lock/\") ||\n\t\tfileName.includes(\"lockfile\")\n\t) {\n\t\tthrow new Error(`Code proposal cannot change dependencies, lockfiles, or install metadata: ${path}`);\n\t}\n}\n\nasync function assertNoUnstagedChanges(runner: CommandRunner, worktreePath: string): Promise<void> {\n\tconst unstaged = await runCommand(runner, \"git\", [\"-C\", worktreePath, \"diff\", \"--quiet\", \"--\"], worktreePath);\n\tif (unstaged.code !== 0 || unstaged.killed || unstaged.outputLimitExceeded) {\n\t\tthrow new CodeWorktreeIntegrityError(\"Code worktree has unstaged changes after validation\");\n\t}\n\tconst untracked = await runGit(\n\t\trunner,\n\t\tworktreePath,\n\t\t[\"ls-files\", \"--others\", \"--exclude-standard\", \"-z\"],\n\t\t\"Inspect untracked candidate files\",\n\t);\n\tif (untracked.stdout.length > 0) {\n\t\tthrow new CodeWorktreeIntegrityError(\"Code worktree has untracked files after validation\");\n\t}\n}\n\nexport function codeApprovalDigest(options: {\n\trepositoryRoot: string;\n\trepositoryIdentity: string;\n\tbaseCommit: string;\n\tparentBundleDigest: string;\n\tdiff: string;\n}): string {\n\treturn sha256(\n\t\tcanonicalJson({\n\t\t\tschemaVersion: CODE_WORKSPACE_SCHEMA_VERSION,\n\t\t\trepositoryRoot: options.repositoryRoot,\n\t\t\trepositoryIdentity: options.repositoryIdentity,\n\t\t\tbaseCommit: options.baseCommit,\n\t\t\tparentBundleDigest: options.parentBundleDigest,\n\t\t\tdiff: options.diff,\n\t\t}),\n\t);\n}\n\nasync function inspectCandidate(\n\trunner: CommandRunner,\n\tworktreePath: string,\n\trepositoryRoot: string,\n\trepositoryIdentityValue: string,\n\tbaseCommit: string,\n\tparentBundleDigest: string,\n): Promise<CandidateSnapshot> {\n\tconst [names, raw, summary, numstat, whitespace, diff] = await Promise.all([\n\t\trunGit(runner, worktreePath, [\"diff\", \"--cached\", \"--name-only\", \"-z\", \"HEAD\", \"--\"], \"List candidate paths\"),\n\t\trunGit(runner, worktreePath, [\"diff\", \"--cached\", \"--raw\", \"-z\", \"HEAD\", \"--\"], \"Inspect candidate modes\"),\n\t\trunGit(runner, worktreePath, [\"diff\", \"--cached\", \"--summary\", \"HEAD\", \"--\"], \"Inspect candidate modes\"),\n\t\trunGit(\n\t\t\trunner,\n\t\t\tworktreePath,\n\t\t\t[\"diff\", \"--cached\", \"--numstat\", \"-z\", \"HEAD\", \"--\"],\n\t\t\t\"Inspect candidate binary files\",\n\t\t),\n\t\trunCommand(runner, \"git\", [\"-C\", worktreePath, \"diff\", \"--cached\", \"--check\", \"HEAD\", \"--\"], worktreePath),\n\t\trunGit(\n\t\t\trunner,\n\t\t\tworktreePath,\n\t\t\t[\"diff\", \"--cached\", \"--binary\", \"--full-index\", \"--no-ext-diff\", \"HEAD\", \"--\"],\n\t\t\t\"Render complete candidate diff\",\n\t\t),\n\t]);\n\tif (whitespace.code !== 0 || whitespace.killed || whitespace.outputLimitExceeded) {\n\t\tthrow new Error(`Candidate diff failed whitespace validation: ${whitespace.stderr || whitespace.stdout}`);\n\t}\n\tif (\n\t\t/\\b(?:120000|160000)\\b/.test(summary.stdout) ||\n\t\t/(?:^|\\0):(?:120000|160000) [0-7]{6} |(?:^|\\0):[0-7]{6} (?:120000|160000) /.test(raw.stdout)\n\t) {\n\t\tthrow new Error(\"Code proposal cannot add or modify symlinks or submodules\");\n\t}\n\tif (numstat.stdout.split(\"\\0\").some((entry) => entry.startsWith(\"-\\t-\\t\"))) {\n\t\tthrow new Error(\"Code proposal cannot contain binary changes\");\n\t}\n\tconst changedPaths = names.stdout.split(\"\\0\").filter(Boolean).sort();\n\tif (changedPaths.length === 0 || !diff.stdout) throw new Error(\"Code proposal patch is empty\");\n\tfor (const path of changedPaths) assertSafeChangedPath(path);\n\tconst approvalDigest = codeApprovalDigest({\n\t\trepositoryRoot,\n\t\trepositoryIdentity: repositoryIdentityValue,\n\t\tbaseCommit,\n\t\tparentBundleDigest,\n\t\tdiff: diff.stdout,\n\t});\n\treturn {\n\t\tchangedPaths,\n\t\tdiff: diff.stdout,\n\t\tapprovalDigest,\n\t\tdiffDigest: sha256(diff.stdout),\n\t};\n}\n\nasync function listEvoTests(worktreePath: string): Promise<string[]> {\n\tconst directory = join(worktreePath, \"packages\", \"evo\", \"test\");\n\ttry {\n\t\treturn (await readdir(directory, { withFileTypes: true }))\n\t\t\t.filter((entry) => entry.isFile() && entry.name.endsWith(\".test.ts\"))\n\t\t\t.map((entry) => `test/${entry.name}`)\n\t\t\t.sort();\n\t} catch (error) {\n\t\tif (typeof error === \"object\" && error !== null && \"code\" in error && error.code === \"ENOENT\") return [];\n\t\tthrow error;\n\t}\n}\n\nasync function fixedValidationCommands(context: CodeValidationContext): Promise<ValidationCommand[]> {\n\tconst commands: ValidationCommand[] = [\n\t\t{ name: \"repository-check\", command: \"npm\", args: [\"run\", \"check\"], cwd: context.worktreePath },\n\t];\n\tconst tests = new Map<string, Set<string>>();\n\tif (context.changedPaths.some((path) => path.startsWith(\"packages/evo/\"))) {\n\t\ttests.set(\"evo\", new Set(await listEvoTests(context.worktreePath)));\n\t}\n\tfor (const path of context.changedPaths) {\n\t\tconst match = /^packages\\/([^/]+)\\/(test\\/.*\\.test\\.ts)$/.exec(path);\n\t\tif (!match) continue;\n\t\tconst packageName = match[1];\n\t\tconst testPath = match[2];\n\t\tconst packageTests = tests.get(packageName) ?? new Set<string>();\n\t\tpackageTests.add(testPath);\n\t\ttests.set(packageName, packageTests);\n\t}\n\tfor (const [packageName, testPaths] of [...tests].sort(([left], [right]) => left.localeCompare(right))) {\n\t\tif (testPaths.size === 0) continue;\n\t\tcommands.push({\n\t\t\tname: `${packageName}-related-tests`,\n\t\t\tcommand: \"node\",\n\t\t\targs: [\n\t\t\t\tjoin(context.worktreePath, \"node_modules\", \"vitest\", \"dist\", \"cli.js\"),\n\t\t\t\t\"--run\",\n\t\t\t\t...[...testPaths].sort(),\n\t\t\t],\n\t\t\tcwd: join(context.worktreePath, \"packages\", packageName),\n\t\t});\n\t}\n\tif (commands.length === 1) {\n\t\tthrow new Error(\"The fixed validation profile has no related-test mapping for this candidate\");\n\t}\n\treturn commands;\n}\n\nfunction minimalValidationEnv(options: {\n\tworktreePath: string;\n\thome: string;\n\ttemporaryDirectory: string;\n\truntimeBin: string;\n}): NodeJS.ProcessEnv {\n\treturn {\n\t\tPATH: [join(options.worktreePath, \"node_modules\", \".bin\"), options.runtimeBin, \"/usr/bin\", \"/bin\"].join(\n\t\t\tdelimiter,\n\t\t),\n\t\tHOME: options.home,\n\t\tTMPDIR: options.temporaryDirectory,\n\t\tCI: \"1\",\n\t\tNO_COLOR: \"1\",\n\t\tnpm_config_cache: join(options.home, \".npm\"),\n\t\t...(process.env.LANG ? { LANG: process.env.LANG } : {}),\n\t\t...(process.env.LC_ALL ? { LC_ALL: process.env.LC_ALL } : {}),\n\t};\n}\n\nfunction macSandboxProfile(options: {\n\tvalidationRoot: string;\n\trepositoryNodeModules: string;\n\truntimeDirectory: string;\n\truntimeExecutable: string;\n}): string {\n\tconst escapeProfilePath = (value: string): string => value.replaceAll(\"\\\\\", \"\\\\\\\\\").replaceAll('\"', '\\\\\"');\n\treturn [\n\t\t\"(version 1)\",\n\t\t\"(deny default)\",\n\t\t\"(deny network*)\",\n\t\t\"(allow process*)\",\n\t\t\"(allow sysctl-read)\",\n\t\t`(allow file-read-metadata (literal \"${escapeProfilePath(options.runtimeDirectory)}\"))`,\n\t\t`(allow file-read* (subpath \"/System\") (subpath \"/usr\") (subpath \"/Library\") (literal \"${escapeProfilePath(options.runtimeExecutable)}\") (subpath \"${escapeProfilePath(options.repositoryNodeModules)}\") (subpath \"${escapeProfilePath(options.validationRoot)}\"))`,\n\t\t`(allow file-write* (subpath \"${escapeProfilePath(join(options.validationRoot, \"home\"))}\") (subpath \"${escapeProfilePath(join(options.validationRoot, \"tmp\"))}\") (literal \"/dev/null\"))`,\n\t].join(\" \");\n}\n\nfunction sandboxPath(hostPath: string, validationRoot: string): string {\n\tconst child = relative(validationRoot, hostPath);\n\tif (!child || child === \"..\" || child.startsWith(`..${sep}`)) {\n\t\tthrow new Error(\"Validation command escaped its private workspace\");\n\t}\n\treturn join(SANDBOX_ROOT, child);\n}\n\nasync function readOnlyBindArguments(paths: readonly string[]): Promise<string[]> {\n\tconst arguments_: string[] = [];\n\tfor (const path of paths) {\n\t\ttry {\n\t\t\tawait lstat(path);\n\t\t\targuments_.push(\"--ro-bind\", path, path);\n\t\t} catch (error) {\n\t\t\tif (typeof error !== \"object\" || error === null || !(\"code\" in error) || error.code !== \"ENOENT\") throw error;\n\t\t}\n\t}\n\treturn arguments_;\n}\n\nfunction sanitizedCommandResult(result: CommandResult): CommandResult {\n\treturn { ...result, stdout: \"\", stderr: \"\" };\n}\n\nfunction validationFailure(name: string, result: CommandResult): string {\n\tif (result.aborted) return `${name} aborted`;\n\tif (result.timedOut) return `${name} timed out`;\n\tif (result.outputLimitExceeded) return `${name} exceeded the output limit`;\n\tif (result.killed) return `${name} was terminated`;\n\treturn `${name} failed with exit ${result.code}`;\n}\n\nasync function validationWorkspaceDigest(root: string): Promise<string> {\n\tconst records: Array<Record<string, string | number>> = [];\n\tconst visit = async (directory: string, prefix: string): Promise<void> => {\n\t\tconst entries = (await readdir(directory, { withFileTypes: true })).sort((left, right) =>\n\t\t\tleft.name.localeCompare(right.name),\n\t\t);\n\t\tfor (const entry of entries) {\n\t\t\tconst childPath = join(directory, entry.name);\n\t\t\tconst child = prefix ? `${prefix}/${entry.name}` : entry.name;\n\t\t\tconst metadata = await lstat(childPath);\n\t\t\tconst mode = metadata.mode & 0o777;\n\t\t\tif (metadata.isDirectory()) {\n\t\t\t\trecords.push({ path: child, kind: \"directory\", mode });\n\t\t\t\tawait visit(childPath, child);\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (metadata.isFile()) {\n\t\t\t\trecords.push({ path: child, kind: \"file\", mode, digest: sha256(await readFile(childPath)) });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tif (metadata.isSymbolicLink()) {\n\t\t\t\trecords.push({ path: child, kind: \"symlink\", mode, target: await readlink(childPath) });\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\tthrow new Error(`Validation workspace contains unsupported entry: ${child}`);\n\t\t}\n\t};\n\tawait visit(root, \"\");\n\treturn sha256(canonicalJson(records));\n}\n\nfunction containsPath(parent: string, candidate: string): boolean {\n\tconst child = relative(parent, candidate);\n\treturn !child || (child !== \"..\" && !child.startsWith(`..${sep}`));\n}\n\nasync function resolveValidationDirectory(path: string, expectedName: string, label: string): Promise<string> {\n\tconst resolved = await realpath(path);\n\tif (basename(resolved).toLowerCase() !== expectedName || !(await lstat(resolved)).isDirectory()) {\n\t\tthrow new Error(`${label} is not a dedicated ${expectedName} directory`);\n\t}\n\treturn resolved;\n}\n\nasync function createMacDependencyLink(options: {\n\tsource: string;\n\ttarget: string;\n\trepositoryRoot: string;\n\trepositoryNodeModules: string;\n\tvalidationWorktree: string;\n}): Promise<void> {\n\tconst resolved = await realpath(options.source);\n\tconst metadata = await lstat(resolved);\n\tlet target = resolved;\n\tif (!containsPath(options.repositoryNodeModules, resolved)) {\n\t\tif (!containsPath(options.repositoryRoot, resolved)) {\n\t\t\tthrow new Error(`Dependency link escapes the repository dependency root: ${options.source}`);\n\t\t}\n\t\tconst child = relative(options.repositoryRoot, resolved);\n\t\tif (child === \"packages\" || !child.startsWith(`packages${sep}`)) {\n\t\t\tthrow new Error(`Workspace dependency link escaped repository packages: ${options.source}`);\n\t\t}\n\t\ttarget = join(options.validationWorktree, child);\n\t\tconst candidateMetadata = await lstat(target);\n\t\tif (\n\t\t\tcandidateMetadata.isDirectory() !== metadata.isDirectory() ||\n\t\t\tcandidateMetadata.isFile() !== metadata.isFile()\n\t\t) {\n\t\t\tthrow new Error(`Workspace dependency type changed in the validation copy: ${options.source}`);\n\t\t}\n\t}\n\tawait symlink(target, options.target, metadata.isDirectory() ? \"dir\" : \"file\");\n}\n\nasync function createMacDependencyView(\n\trepositoryRoot: string,\n\trepositoryNodeModules: string,\n\tvalidationRoot: string,\n\tvalidationWorktree: string,\n): Promise<void> {\n\tconst view = join(validationRoot, \"dependencies\", \"node_modules\");\n\tawait mkdir(view, { recursive: true, mode: 0o700 });\n\tfor (const entry of await readdir(repositoryNodeModules, { withFileTypes: true })) {\n\t\tconst source = join(repositoryNodeModules, entry.name);\n\t\tconst target = join(view, entry.name);\n\t\tif (entry.isDirectory() && entry.name.startsWith(\"@\")) {\n\t\t\tawait mkdir(target, { mode: 0o700 });\n\t\t\tfor (const child of await readdir(source)) {\n\t\t\t\tawait createMacDependencyLink({\n\t\t\t\t\tsource: join(source, child),\n\t\t\t\t\ttarget: join(target, child),\n\t\t\t\t\trepositoryRoot,\n\t\t\t\t\trepositoryNodeModules,\n\t\t\t\t\tvalidationWorktree,\n\t\t\t\t});\n\t\t\t}\n\t\t\tcontinue;\n\t\t}\n\t\tawait createMacDependencyLink({ source, target, repositoryRoot, repositoryNodeModules, validationWorktree });\n\t}\n\tawait symlink(\"../dependencies/node_modules\", join(validationWorktree, \"node_modules\"), \"dir\");\n}\n\nasync function runSandboxed(\n\tcontext: CodeValidationContext,\n\tvalidationCommand: ValidationCommand,\n\tvalidationRoot: string,\n): Promise<CommandResult> {\n\tconst repositoryRoot = await realpath(context.repositoryRoot);\n\tconst repositoryNodeModules = await resolveValidationDirectory(\n\t\tjoin(repositoryRoot, \"node_modules\"),\n\t\t\"node_modules\",\n\t\t\"Repository dependency root\",\n\t);\n\tif (containsPath(repositoryNodeModules, repositoryRoot)) {\n\t\tthrow new Error(\"Repository dependency root is too broad for sandbox mounting\");\n\t}\n\tconst runtimeExecutable = await realpath(process.execPath);\n\tif (!(await lstat(runtimeExecutable)).isFile()) {\n\t\tthrow new Error(\"Runtime executable is not a regular file\");\n\t}\n\tif (process.platform === \"linux\") {\n\t\tconst runtimeCoveredBySystem = [\"/usr\", \"/bin\", \"/lib\", \"/lib64\"].some((root) => {\n\t\t\tconst child = relative(root, runtimeExecutable);\n\t\t\treturn child !== \"..\" && !child.startsWith(`..${sep}`);\n\t\t});\n\t\tconst runtimeBin = runtimeCoveredBySystem ? dirname(runtimeExecutable) : `${SANDBOX_ROOT}/runtime`;\n\t\tconst env = minimalValidationEnv({\n\t\t\tworktreePath: `${SANDBOX_ROOT}/workspace`,\n\t\t\thome: `${SANDBOX_ROOT}/home`,\n\t\t\ttemporaryDirectory: `${SANDBOX_ROOT}/tmp`,\n\t\t\truntimeBin,\n\t\t});\n\t\tconst systemBinds = await readOnlyBindArguments([\"/usr\", \"/bin\", \"/lib\", \"/lib64\"]);\n\t\tconst systemFiles = await readOnlyBindArguments([\"/etc/passwd\", \"/etc/group\", \"/etc/ld.so.cache\"]);\n\t\treturn runCommand(\n\t\t\tcontext.commandRunner,\n\t\t\t\"bwrap\",\n\t\t\t[\n\t\t\t\t\"--die-with-parent\",\n\t\t\t\t\"--new-session\",\n\t\t\t\t\"--unshare-net\",\n\t\t\t\t\"--unshare-pid\",\n\t\t\t\t\"--unshare-ipc\",\n\t\t\t\t\"--unshare-uts\",\n\t\t\t\t\"--proc\",\n\t\t\t\t\"/proc\",\n\t\t\t\t\"--dev\",\n\t\t\t\t\"/dev\",\n\t\t\t\t\"--tmpfs\",\n\t\t\t\t\"/tmp\",\n\t\t\t\t...systemBinds,\n\t\t\t\t\"--dir\",\n\t\t\t\t\"/etc\",\n\t\t\t\t...systemFiles,\n\t\t\t\t\"--dir\",\n\t\t\t\tSANDBOX_ROOT,\n\t\t\t\t\"--ro-bind\",\n\t\t\t\tjoin(validationRoot, \"workspace\"),\n\t\t\t\t`${SANDBOX_ROOT}/workspace`,\n\t\t\t\t\"--bind\",\n\t\t\t\tjoin(validationRoot, \"home\"),\n\t\t\t\t`${SANDBOX_ROOT}/home`,\n\t\t\t\t\"--bind\",\n\t\t\t\tjoin(validationRoot, \"tmp\"),\n\t\t\t\t`${SANDBOX_ROOT}/tmp`,\n\t\t\t\t\"--dir\",\n\t\t\t\t`${SANDBOX_ROOT}/runtime`,\n\t\t\t\t\"--ro-bind\",\n\t\t\t\trepositoryNodeModules,\n\t\t\t\t`${SANDBOX_ROOT}/workspace/node_modules`,\n\t\t\t\t...(runtimeCoveredBySystem ? [] : [\"--ro-bind\", runtimeExecutable, `${SANDBOX_ROOT}/runtime/node`]),\n\t\t\t\t\"--chdir\",\n\t\t\t\tsandboxPath(validationCommand.cwd, validationRoot),\n\t\t\t\t\"--\",\n\t\t\t\tvalidationCommand.command,\n\t\t\t\t...validationCommand.args.map((argument) =>\n\t\t\t\t\targument.startsWith(validationRoot) ? sandboxPath(argument, validationRoot) : argument,\n\t\t\t\t),\n\t\t\t],\n\t\t\tvalidationRoot,\n\t\t\t{\n\t\t\t\ttimeoutMs: VALIDATION_TIMEOUT_MS,\n\t\t\t\tenv,\n\t\t\t\tmaxOutputBytes: VALIDATION_OUTPUT_LIMIT,\n\t\t\t\t...(context.signal ? { signal: context.signal } : {}),\n\t\t\t},\n\t\t);\n\t}\n\tif (process.platform === \"darwin\") {\n\t\tconst env = minimalValidationEnv({\n\t\t\tworktreePath: join(validationRoot, \"workspace\"),\n\t\t\thome: join(validationRoot, \"home\"),\n\t\t\ttemporaryDirectory: join(validationRoot, \"tmp\"),\n\t\t\truntimeBin: dirname(runtimeExecutable),\n\t\t});\n\t\treturn runCommand(\n\t\t\tcontext.commandRunner,\n\t\t\t\"/usr/bin/sandbox-exec\",\n\t\t\t[\n\t\t\t\t\"-p\",\n\t\t\t\tmacSandboxProfile({\n\t\t\t\t\tvalidationRoot,\n\t\t\t\t\trepositoryNodeModules,\n\t\t\t\t\truntimeDirectory: dirname(runtimeExecutable),\n\t\t\t\t\truntimeExecutable,\n\t\t\t\t}),\n\t\t\t\tvalidationCommand.command,\n\t\t\t\t...validationCommand.args,\n\t\t\t],\n\t\t\tvalidationCommand.cwd,\n\t\t\t{\n\t\t\t\ttimeoutMs: VALIDATION_TIMEOUT_MS,\n\t\t\t\tenv,\n\t\t\t\tmaxOutputBytes: VALIDATION_OUTPUT_LIMIT,\n\t\t\t\t...(context.signal ? { signal: context.signal } : {}),\n\t\t\t},\n\t\t);\n\t}\n\tthrow new Error(`OS sandbox validation is unavailable on ${process.platform}`);\n}\n\nexport class DefaultSandboxCodeValidationExecutor implements CodeValidationExecutor {\n\tasync validate(context: CodeValidationContext): Promise<CodeL1Result> {\n\t\tconst checks: CodeValidationCheck[] = [];\n\t\tconst errors: string[] = [];\n\t\tconst validationRoot = await mkdtemp(join(tmpdir(), \"evo-pi-validation-\"));\n\t\ttry {\n\t\t\tcontext.signal?.throwIfAborted();\n\t\t\tconst validationWorktree = join(validationRoot, \"workspace\");\n\t\t\tawait mkdir(join(validationRoot, \"home\"), { mode: 0o700 });\n\t\t\tawait mkdir(join(validationRoot, \"tmp\"), { mode: 0o700 });\n\t\t\tawait mkdir(join(validationRoot, \"runtime\"), { mode: 0o700 });\n\t\t\tawait cp(context.worktreePath, validationWorktree, {\n\t\t\t\trecursive: true,\n\t\t\t\tdereference: false,\n\t\t\t\tverbatimSymlinks: true,\n\t\t\t\tfilter: (source) => {\n\t\t\t\t\tconst child = relative(context.worktreePath, source);\n\t\t\t\t\tconst segments = child.split(sep);\n\t\t\t\t\treturn !segments.includes(\".git\") && !segments.includes(\"node_modules\");\n\t\t\t\t},\n\t\t\t});\n\t\t\tconst validationNodeModules = join(validationWorktree, \"node_modules\");\n\t\t\tif (process.platform === \"darwin\") {\n\t\t\t\tconst repositoryRoot = await realpath(context.repositoryRoot);\n\t\t\t\tconst repositoryNodeModules = await resolveValidationDirectory(\n\t\t\t\t\tjoin(repositoryRoot, \"node_modules\"),\n\t\t\t\t\t\"node_modules\",\n\t\t\t\t\t\"Repository dependency root\",\n\t\t\t\t);\n\t\t\t\tif (containsPath(repositoryNodeModules, repositoryRoot)) {\n\t\t\t\t\tthrow new Error(\"Repository dependency root is too broad for sandbox mounting\");\n\t\t\t\t}\n\t\t\t\tawait createMacDependencyView(repositoryRoot, repositoryNodeModules, validationRoot, validationWorktree);\n\t\t\t} else {\n\t\t\t\tawait mkdir(validationNodeModules, { mode: 0o700 });\n\t\t\t}\n\t\t\tconst beforeValidationDigest = await validationWorkspaceDigest(validationWorktree);\n\t\t\tconst validationContext: CodeValidationContext = {\n\t\t\t\t...context,\n\t\t\t\tworktreePath: validationWorktree,\n\t\t\t};\n\t\t\tfor (const command of await fixedValidationCommands(validationContext)) {\n\t\t\t\tconst result = await runSandboxed(validationContext, command, validationRoot);\n\t\t\t\tchecks.push({ name: command.name, result: sanitizedCommandResult(result) });\n\t\t\t\tconst failed = result.code !== 0 || result.killed || result.outputLimitExceeded;\n\t\t\t\tif (failed) errors.push(validationFailure(command.name, result));\n\t\t\t\tconst modified = (await validationWorkspaceDigest(validationWorktree)) !== beforeValidationDigest;\n\t\t\t\tif (modified) errors.push(\"Sandboxed validation modified the candidate instead of checking it read-only\");\n\t\t\t\tif (failed || modified) break;\n\t\t\t}\n\t\t} catch (error) {\n\t\t\tconst detail = errorMessage(error)\n\t\t\t\t.replace(/[\\r\\n\\t]+/g, \" \")\n\t\t\t\t.slice(0, 500);\n\t\t\terrors.push(`Sandboxed validation failed closed: ${detail}`);\n\t\t} finally {\n\t\t\tawait rm(validationRoot, { recursive: true, force: true }).catch(() => {});\n\t\t}\n\t\treturn { passed: errors.length === 0 && checks.length > 0, errors, checks };\n\t}\n}\n\nasync function persistRevision(paths: ReturnType<typeof revisionPaths>, revision: CodeWorktreeRevision): Promise<void> {\n\tawait atomicWriteFile(paths.diffFile, revision.diff);\n\tawait atomicWriteJson(paths.l1File, revision.l1);\n\tconst { diff: _diff, ...persisted } = revision;\n\tawait atomicWriteJson(paths.workspaceFile, persisted);\n}\n\nfunction buildRevision(options: {\n\tproposalId: string;\n\trevision: number;\n\tparentBundleDigest: string;\n\trepository: RepositoryInfo;\n\tpaths: ReturnType<typeof revisionPaths>;\n\tsnapshot: CandidateSnapshot;\n\tl1: CodeL1Result;\n}): CodeWorktreeRevision {\n\treturn {\n\t\tschemaVersion: 1,\n\t\tproposalId: options.proposalId,\n\t\trevision: options.revision,\n\t\tparentBundleDigest: options.parentBundleDigest,\n\t\trepositoryRoot: options.repository.root,\n\t\trepositoryIdentity: options.repository.identity,\n\t\tbaseCommit: options.repository.baseCommit,\n\t\tbranch: options.paths.branch,\n\t\tworktreePath: options.paths.worktreePath,\n\t\trevisionDirectory: options.paths.revisionDirectory,\n\t\tpatchFile: options.paths.patchFile,\n\t\tdiffFile: options.paths.diffFile,\n\t\tchangedPaths: options.snapshot.changedPaths,\n\t\tdiff: options.snapshot.diff,\n\t\tapprovalDigest: options.snapshot.approvalDigest,\n\t\tdiffDigest: options.snapshot.diffDigest,\n\t\tl1: options.l1,\n\t};\n}\n\nasync function removeEmptyRevisionParents(paths: ReturnType<typeof revisionPaths>): Promise<void> {\n\tfor (const directory of [\n\t\tdirname(paths.revisionDirectory),\n\t\tdirname(dirname(paths.revisionDirectory)),\n\t\tdirname(paths.worktreePath),\n\t]) {\n\t\tawait rmdir(directory).catch(() => undefined);\n\t}\n}\n\nfunction builderWorktreePath(paths: EvoPaths, runId: string): string {\n\tif (!PROPOSAL_ID_PATTERN.test(runId)) throw new Error(`Invalid evolution run id: ${runId}`);\n\treturn join(paths.worktrees, \"builders\", runId);\n}\n\nexport async function createCodeBuilderWorkspace(options: {\n\tpaths: EvoPaths;\n\trepositoryCwd: string;\n\trunId: string;\n\tcommandRunner?: CommandRunner;\n\tsignal?: AbortSignal;\n}): Promise<CodeBuilderWorkspace> {\n\tconst runner = options.commandRunner ?? new SpawnCommandRunner();\n\tconst repository = await inspectRepository(runner, options.repositoryCwd);\n\tconst worktreePath = builderWorktreePath(options.paths, options.runId);\n\toptions.signal?.throwIfAborted();\n\tawait mkdir(dirname(worktreePath), { recursive: true, mode: 0o700 });\n\tawait runGit(\n\t\trunner,\n\t\trepository.root,\n\t\t[\"worktree\", \"add\", \"--detach\", worktreePath, repository.baseCommit],\n\t\t\"Create isolated Builder worktree\",\n\t);\n\treturn {\n\t\trunId: options.runId,\n\t\trepositoryRoot: repository.root,\n\t\trepositoryIdentity: repository.identity,\n\t\tbaseCommit: repository.baseCommit,\n\t\tworktreePath,\n\t};\n}\n\nexport async function snapshotCodeBuilderWorkspace(options: {\n\tworkspace: CodeBuilderWorkspace;\n\tparentBundleDigest: string;\n\tcommandRunner?: CommandRunner;\n}): Promise<CodeBuilderSnapshot> {\n\tassertBundleDigest(options.parentBundleDigest);\n\tconst runner = options.commandRunner ?? new SpawnCommandRunner();\n\tconst identity = await repositoryIdentity(runner, options.workspace.worktreePath);\n\tif (identity !== options.workspace.repositoryIdentity) {\n\t\tthrow new CodeWorktreeIntegrityError(\"Builder worktree repository identity changed\");\n\t}\n\tconst head = (\n\t\tawait runGit(\n\t\t\trunner,\n\t\t\toptions.workspace.worktreePath,\n\t\t\t[\"rev-parse\", \"--verify\", \"HEAD^{commit}\"],\n\t\t\t\"Verify Builder base\",\n\t\t)\n\t).stdout.trim();\n\tif (head !== options.workspace.baseCommit) {\n\t\tthrow new CodeWorktreeIntegrityError(\"Builder worktree base commit changed\");\n\t}\n\tconst [tracked, untracked] = await Promise.all([\n\t\trunGit(\n\t\t\trunner,\n\t\t\toptions.workspace.worktreePath,\n\t\t\t[\"diff\", \"--name-only\", \"-z\", \"HEAD\", \"--\"],\n\t\t\t\"List Builder tracked changes\",\n\t\t),\n\t\trunGit(\n\t\t\trunner,\n\t\t\toptions.workspace.worktreePath,\n\t\t\t[\"ls-files\", \"--others\", \"--exclude-standard\", \"-z\"],\n\t\t\t\"List Builder untracked changes\",\n\t\t),\n\t]);\n\tconst changedPaths = [...new Set([...tracked.stdout.split(\"\\0\"), ...untracked.stdout.split(\"\\0\")].filter(Boolean))];\n\tif (changedPaths.length === 0) throw new Error(\"Builder did not modify its isolated worktree\");\n\tfor (const path of changedPaths) assertSafeChangedPath(path);\n\tawait runGit(runner, options.workspace.worktreePath, [\"add\", \"--all\", \"--\"], \"Stage Builder candidate\");\n\tconst snapshot = await inspectCandidate(\n\t\trunner,\n\t\toptions.workspace.worktreePath,\n\t\toptions.workspace.repositoryRoot,\n\t\toptions.workspace.repositoryIdentity,\n\t\toptions.workspace.baseCommit,\n\t\toptions.parentBundleDigest,\n\t);\n\tawait assertNoUnstagedChanges(runner, options.workspace.worktreePath);\n\treturn {\n\t\tpatch: snapshot.diff,\n\t\tchangedPaths: snapshot.changedPaths,\n\t\trepositoryRoot: options.workspace.repositoryRoot,\n\t\trepositoryIdentity: options.workspace.repositoryIdentity,\n\t\tbaseCommit: options.workspace.baseCommit,\n\t};\n}\n\nexport async function removeCodeBuilderWorkspace(\n\tworkspace: CodeBuilderWorkspace,\n\tcommandRunner: CommandRunner = new SpawnCommandRunner(),\n): Promise<void> {\n\tawait runGit(\n\t\tcommandRunner,\n\t\tworkspace.repositoryRoot,\n\t\t[\"worktree\", \"remove\", \"--force\", \"--\", workspace.worktreePath],\n\t\t\"Remove isolated Builder worktree\",\n\t);\n\tawait rmdir(dirname(workspace.worktreePath)).catch(() => undefined);\n}\n\nasync function cleanupFailedRevision(\n\trunner: CommandRunner,\n\trepositoryRoot: string,\n\tpaths: ReturnType<typeof revisionPaths>,\n\toptions: { removeWorktree: boolean; deleteBranch: boolean },\n): Promise<void> {\n\tif (options.removeWorktree) {\n\t\tawait runCommand(\n\t\t\trunner,\n\t\t\t\"git\",\n\t\t\t[\"-C\", repositoryRoot, \"worktree\", \"remove\", \"--force\", \"--\", paths.worktreePath],\n\t\t\trepositoryRoot,\n\t\t).catch(() => undefined);\n\t}\n\tif (options.deleteBranch) {\n\t\tawait runCommand(runner, \"git\", [\"-C\", repositoryRoot, \"branch\", \"-D\", \"--\", paths.branch], repositoryRoot).catch(\n\t\t\t() => undefined,\n\t\t);\n\t}\n\tawait rm(paths.revisionDirectory, { recursive: true, force: true }).catch(() => undefined);\n\tawait removeEmptyRevisionParents(paths);\n}\n\nexport async function stageCodeWorktree(options: StageCodeWorktreeOptions): Promise<CodeWorktreeRevision> {\n\tassertProposalRevision(options.proposalId, options.revision);\n\tassertBundleDigest(options.parentBundleDigest);\n\tif (!options.patch.trim()) throw new Error(\"Code proposal patch is empty\");\n\tconst runner = options.commandRunner ?? new SpawnCommandRunner();\n\tconst validationExecutor = options.validationExecutor ?? new DefaultSandboxCodeValidationExecutor();\n\tconst paths = revisionPaths(options.paths, options.proposalId, options.revision);\n\treturn withFileLock(\n\t\toptions.paths,\n\t\t`code-${options.proposalId}-r${options.revision}`,\n\t\tasync () => {\n\t\t\tconst repository = await inspectRepository(runner, options.repositoryCwd);\n\t\t\tif (options.expectedRepositoryRoot && repository.root !== options.expectedRepositoryRoot) {\n\t\t\t\tthrow new CodeWorktreeIntegrityError(\"Repository root changed after Builder snapshot\");\n\t\t\t}\n\t\t\tif (options.expectedRepositoryIdentity && repository.identity !== options.expectedRepositoryIdentity) {\n\t\t\t\tthrow new CodeWorktreeIntegrityError(\"Repository identity changed after Builder snapshot\");\n\t\t\t}\n\t\t\tif (options.expectedBaseCommit && repository.baseCommit !== options.expectedBaseCommit) {\n\t\t\t\tthrow new CodeWorktreeIntegrityError(\"Repository HEAD changed after Builder snapshot\");\n\t\t\t}\n\t\t\tlet revisionDirectoryCreated = false;\n\t\t\tlet branchCreated = false;\n\t\t\tlet worktreeAddAttempted = false;\n\t\t\ttry {\n\t\t\t\toptions.signal?.throwIfAborted();\n\t\t\t\tawait mkdir(dirname(paths.revisionDirectory), { recursive: true });\n\t\t\t\tawait mkdir(paths.revisionDirectory);\n\t\t\t\trevisionDirectoryCreated = true;\n\t\t\t\tawait mkdir(dirname(paths.worktreePath), { recursive: true });\n\t\t\t\tawait writeFile(paths.patchFile, options.patch, { encoding: \"utf8\", flag: \"wx\", mode: 0o600 });\n\t\t\t\tawait runGit(\n\t\t\t\t\trunner,\n\t\t\t\t\trepository.root,\n\t\t\t\t\t[\"branch\", \"--\", paths.branch, repository.baseCommit],\n\t\t\t\t\t\"Create code proposal branch\",\n\t\t\t\t);\n\t\t\t\tbranchCreated = true;\n\t\t\t\tworktreeAddAttempted = true;\n\t\t\t\tawait runGit(\n\t\t\t\t\trunner,\n\t\t\t\t\trepository.root,\n\t\t\t\t\t[\"worktree\", \"add\", paths.worktreePath, paths.branch],\n\t\t\t\t\t\"Create isolated code worktree\",\n\t\t\t\t);\n\t\t\t\tawait runGit(\n\t\t\t\t\trunner,\n\t\t\t\t\tpaths.worktreePath,\n\t\t\t\t\t[\"apply\", \"--check\", \"--index\", \"--\", paths.patchFile],\n\t\t\t\t\t\"Check code proposal patch\",\n\t\t\t\t);\n\t\t\t\tawait runGit(\n\t\t\t\t\trunner,\n\t\t\t\t\tpaths.worktreePath,\n\t\t\t\t\t[\"apply\", \"--index\", \"--\", paths.patchFile],\n\t\t\t\t\t\"Apply code proposal patch\",\n\t\t\t\t);\n\t\t\t\tconst beforeValidation = await inspectCandidate(\n\t\t\t\t\trunner,\n\t\t\t\t\tpaths.worktreePath,\n\t\t\t\t\trepository.root,\n\t\t\t\t\trepository.identity,\n\t\t\t\t\trepository.baseCommit,\n\t\t\t\t\toptions.parentBundleDigest,\n\t\t\t\t);\n\t\t\t\tconst l1 = await validationExecutor.validate({\n\t\t\t\t\trepositoryRoot: repository.root,\n\t\t\t\t\tworktreePath: paths.worktreePath,\n\t\t\t\t\tbaseCommit: repository.baseCommit,\n\t\t\t\t\tchangedPaths: beforeValidation.changedPaths,\n\t\t\t\t\tcommandRunner: runner,\n\t\t\t\t\t...(options.signal ? { signal: options.signal } : {}),\n\t\t\t\t});\n\t\t\t\tif (!l1.passed) throw new Error(\"Code proposal failed sandboxed L1 validation\");\n\t\t\t\tawait assertNoUnstagedChanges(runner, paths.worktreePath);\n\t\t\t\tconst snapshot = await inspectCandidate(\n\t\t\t\t\trunner,\n\t\t\t\t\tpaths.worktreePath,\n\t\t\t\t\trepository.root,\n\t\t\t\t\trepository.identity,\n\t\t\t\t\trepository.baseCommit,\n\t\t\t\t\toptions.parentBundleDigest,\n\t\t\t\t);\n\t\t\t\tif (\n\t\t\t\t\tsnapshot.approvalDigest !== beforeValidation.approvalDigest ||\n\t\t\t\t\tsnapshot.diff !== beforeValidation.diff\n\t\t\t\t) {\n\t\t\t\t\tthrow new CodeWorktreeIntegrityError(\"L1 validation mutated the code candidate\");\n\t\t\t\t}\n\t\t\t\tconst revision = buildRevision({\n\t\t\t\t\tproposalId: options.proposalId,\n\t\t\t\t\trevision: options.revision,\n\t\t\t\t\tparentBundleDigest: options.parentBundleDigest,\n\t\t\t\t\trepository,\n\t\t\t\t\tpaths,\n\t\t\t\t\tsnapshot,\n\t\t\t\t\tl1,\n\t\t\t\t});\n\t\t\t\tawait persistRevision(paths, revision);\n\t\t\t\treturn revision;\n\t\t\t} catch (error) {\n\t\t\t\tif (branchCreated || worktreeAddAttempted) {\n\t\t\t\t\tawait cleanupFailedRevision(runner, repository.root, paths, {\n\t\t\t\t\t\tremoveWorktree: worktreeAddAttempted,\n\t\t\t\t\t\tdeleteBranch: branchCreated,\n\t\t\t\t\t});\n\t\t\t\t} else if (revisionDirectoryCreated) {\n\t\t\t\t\tawait rm(paths.revisionDirectory, { recursive: true, force: true }).catch(() => undefined);\n\t\t\t\t\tawait removeEmptyRevisionParents(paths);\n\t\t\t\t}\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t},\n\t\t{ staleAfterMs: CODE_LOCK_STALE_MS },\n\t);\n}\n\nfunction isStringArray(value: unknown): value is string[] {\n\treturn Array.isArray(value) && value.every((entry) => typeof entry === \"string\");\n}\n\nfunction parsePersistedRevision(value: unknown): PersistedCodeWorktreeRevision {\n\tif (typeof value !== \"object\" || value === null || Array.isArray(value)) {\n\t\tthrow new CodeWorktreeIntegrityError(\"workspace.json must contain an object\");\n\t}\n\tconst record = value as Record<string, unknown>;\n\tif (\n\t\trecord.schemaVersion !== 1 ||\n\t\ttypeof record.proposalId !== \"string\" ||\n\t\t!Number.isSafeInteger(record.revision) ||\n\t\ttypeof record.parentBundleDigest !== \"string\" ||\n\t\ttypeof record.repositoryRoot !== \"string\" ||\n\t\ttypeof record.repositoryIdentity !== \"string\" ||\n\t\ttypeof record.baseCommit !== \"string\" ||\n\t\ttypeof record.branch !== \"string\" ||\n\t\ttypeof record.worktreePath !== \"string\" ||\n\t\ttypeof record.revisionDirectory !== \"string\" ||\n\t\ttypeof record.patchFile !== \"string\" ||\n\t\ttypeof record.diffFile !== \"string\" ||\n\t\t!isStringArray(record.changedPaths) ||\n\t\ttypeof record.approvalDigest !== \"string\" ||\n\t\ttypeof record.diffDigest !== \"string\" ||\n\t\ttypeof record.l1 !== \"object\" ||\n\t\trecord.l1 === null\n\t) {\n\t\tthrow new CodeWorktreeIntegrityError(\"workspace.json is invalid\");\n\t}\n\treturn value as PersistedCodeWorktreeRevision;\n}\n\nexport async function loadCodeWorktreeRevision(\n\tpaths: EvoPaths,\n\tproposalId: string,\n\trevision: number,\n): Promise<CodeWorktreeRevision> {\n\tassertProposalRevision(proposalId, revision);\n\tconst expectedPaths = revisionPaths(paths, proposalId, revision);\n\tconst persisted = parsePersistedRevision(await readJson<unknown>(expectedPaths.workspaceFile));\n\tconst diff = await readFile(expectedPaths.diffFile, \"utf8\");\n\treturn { ...persisted, diff };\n}\n\nfunction assertExpectedPath(actual: string, expected: string, label: string): void {\n\tif (resolve(actual) !== resolve(expected))\n\t\tthrow new CodeWorktreeIntegrityError(`${label} does not match its revision path`);\n}\n\nasync function assertWorktreeLocation(paths: EvoPaths, worktreePath: string): Promise<void> {\n\tconst [root, candidate] = await Promise.all([realpath(paths.worktrees), realpath(worktreePath)]);\n\tconst child = relative(root, candidate);\n\tif (!child || child === \"..\" || child.startsWith(`..${sep}`)) {\n\t\tthrow new CodeWorktreeIntegrityError(\"Code worktree is outside the Evo-Pi worktree directory\");\n\t}\n\tif (!(await lstat(candidate)).isDirectory())\n\t\tthrow new CodeWorktreeIntegrityError(\"Code worktree is not a directory\");\n}\n\nexport async function revalidateCodeWorktree(options: RevalidateCodeWorktreeOptions): Promise<CodeWorktreeRevision> {\n\tassertProposalRevision(options.proposalId, options.revision);\n\tassertBundleDigest(options.expectedParentBundleDigest);\n\tconst runner = options.commandRunner ?? new SpawnCommandRunner();\n\tconst validationExecutor = options.validationExecutor ?? new DefaultSandboxCodeValidationExecutor();\n\tconst paths = revisionPaths(options.paths, options.proposalId, options.revision);\n\treturn withFileLock(\n\t\toptions.paths,\n\t\t`code-${options.proposalId}-r${options.revision}`,\n\t\tasync () => {\n\t\t\tconst stored = await loadCodeWorktreeRevision(options.paths, options.proposalId, options.revision);\n\t\t\tif (stored.parentBundleDigest !== options.expectedParentBundleDigest) {\n\t\t\t\tthrow new CodeWorktreeIntegrityError(\"Stored parent bundle does not match the approved context\");\n\t\t\t}\n\t\t\tif (stored.proposalId !== options.proposalId || stored.revision !== options.revision) {\n\t\t\t\tthrow new CodeWorktreeIntegrityError(\"Stored code revision identity does not match the requested revision\");\n\t\t\t}\n\t\t\tassertExpectedPath(stored.repositoryRoot, options.expectedRepositoryRoot, \"repositoryRoot\");\n\t\t\tif (stored.repositoryIdentity !== options.expectedRepositoryIdentity) {\n\t\t\t\tthrow new CodeWorktreeIntegrityError(\"Stored repository identity does not match the approved workspace\");\n\t\t\t}\n\t\t\tif (stored.baseCommit !== options.expectedBaseCommit) {\n\t\t\t\tthrow new CodeWorktreeIntegrityError(\"Stored base commit does not match the approved workspace\");\n\t\t\t}\n\t\t\tassertExpectedPath(stored.worktreePath, paths.worktreePath, \"worktreePath\");\n\t\t\tassertExpectedPath(stored.revisionDirectory, paths.revisionDirectory, \"revisionDirectory\");\n\t\t\tassertExpectedPath(stored.patchFile, paths.patchFile, \"patchFile\");\n\t\t\tassertExpectedPath(stored.diffFile, paths.diffFile, \"diffFile\");\n\t\t\tif (stored.branch !== paths.branch)\n\t\t\t\tthrow new CodeWorktreeIntegrityError(\"Stored branch does not match the revision\");\n\t\t\tawait assertWorktreeLocation(options.paths, paths.worktreePath);\n\n\t\t\tconst actualIdentity = await repositoryIdentity(runner, paths.worktreePath);\n\t\t\tif (actualIdentity !== options.expectedRepositoryIdentity) {\n\t\t\t\tthrow new CodeWorktreeIntegrityError(\"Code worktree repository identity changed\");\n\t\t\t}\n\t\t\tconst head = (\n\t\t\t\tawait runGit(runner, paths.worktreePath, [\"rev-parse\", \"--verify\", \"HEAD^{commit}\"], \"Verify code base\")\n\t\t\t).stdout.trim();\n\t\t\tif (head !== options.expectedBaseCommit)\n\t\t\t\tthrow new CodeWorktreeIntegrityError(\"Code worktree base commit changed\");\n\t\t\tconst branch = (\n\t\t\t\tawait runGit(runner, paths.worktreePath, [\"branch\", \"--show-current\"], \"Verify code branch\")\n\t\t\t).stdout.trim();\n\t\t\tif (branch !== paths.branch) throw new CodeWorktreeIntegrityError(\"Code worktree branch changed\");\n\t\t\tawait assertNoUnstagedChanges(runner, paths.worktreePath);\n\n\t\t\tconst beforeValidation = await inspectCandidate(\n\t\t\t\trunner,\n\t\t\t\tpaths.worktreePath,\n\t\t\t\toptions.expectedRepositoryRoot,\n\t\t\t\tactualIdentity,\n\t\t\t\toptions.expectedBaseCommit,\n\t\t\t\toptions.expectedParentBundleDigest,\n\t\t\t);\n\t\t\tif (\n\t\t\t\tbeforeValidation.approvalDigest !== options.expectedApprovalDigest ||\n\t\t\t\tbeforeValidation.approvalDigest !== stored.approvalDigest ||\n\t\t\t\tbeforeValidation.diffDigest !== stored.diffDigest ||\n\t\t\t\tbeforeValidation.diff !== stored.diff ||\n\t\t\t\tcanonicalJson(beforeValidation.changedPaths) !== canonicalJson(stored.changedPaths)\n\t\t\t) {\n\t\t\t\tthrow new CodeWorktreeIntegrityError(\"Code proposal no longer matches the approved digest and stored diff\");\n\t\t\t}\n\n\t\t\tconst l1 = await validationExecutor.validate({\n\t\t\t\trepositoryRoot: options.expectedRepositoryRoot,\n\t\t\t\tworktreePath: paths.worktreePath,\n\t\t\t\tbaseCommit: options.expectedBaseCommit,\n\t\t\t\tchangedPaths: beforeValidation.changedPaths,\n\t\t\t\tcommandRunner: runner,\n\t\t\t\t...(options.signal ? { signal: options.signal } : {}),\n\t\t\t});\n\t\t\tawait assertNoUnstagedChanges(runner, paths.worktreePath);\n\t\t\tconst afterValidation = await inspectCandidate(\n\t\t\t\trunner,\n\t\t\t\tpaths.worktreePath,\n\t\t\t\toptions.expectedRepositoryRoot,\n\t\t\t\tactualIdentity,\n\t\t\t\toptions.expectedBaseCommit,\n\t\t\t\toptions.expectedParentBundleDigest,\n\t\t\t);\n\t\t\tif (\n\t\t\t\tafterValidation.approvalDigest !== beforeValidation.approvalDigest ||\n\t\t\t\tafterValidation.diff !== beforeValidation.diff\n\t\t\t) {\n\t\t\t\tthrow new CodeWorktreeIntegrityError(\"L1 validation mutated the approved code candidate\");\n\t\t\t}\n\t\t\tconst repository: RepositoryInfo = {\n\t\t\t\troot: options.expectedRepositoryRoot,\n\t\t\t\tidentity: actualIdentity,\n\t\t\t\tbaseCommit: options.expectedBaseCommit,\n\t\t\t};\n\t\t\tconst revision = buildRevision({\n\t\t\t\tproposalId: options.proposalId,\n\t\t\t\trevision: options.revision,\n\t\t\t\tparentBundleDigest: options.expectedParentBundleDigest,\n\t\t\t\trepository,\n\t\t\t\tpaths,\n\t\t\t\tsnapshot: afterValidation,\n\t\t\t\tl1,\n\t\t\t});\n\t\t\treturn revision;\n\t\t},\n\t\t{ staleAfterMs: CODE_LOCK_STALE_MS },\n\t);\n}\n"]}