@agentproto/worktree 0.2.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"index.mjs"}
1
+ {"version":3,"sources":["../src/salvage.ts","../src/services/proxy-server.ts","../src/forge.ts","../src/gc.ts"],"names":["netConnect","resolve","fetch"],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Salvage-before-discard (PLAN.md §5.2 layer 4). `worktree archive` re-earns\n * its name by snapshotting a worktree's uncommitted state before it removes\n * anything: `git diff HEAD` → `changes.patch`, plus a byte-copy of every\n * unignored untracked file, into\n * `~/.agentproto/worktree-salvage/<repoName>/<slug>-<tipSha7>-<date>/` with a\n * `MANIFEST.json`. Every file is fsynced before this returns — only once the\n * snapshot is durable does the caller proceed to force-remove.\n *\n * Deliberately forge-independent: no PR lookup here. This writer's only job\n * is \"don't lose bytes before deletion,\" not classification — `ls --status`\n * (status.ts) already owns the forge-derived `integration` axis, and gc\n * (PR-D) is where a salvage manifest and a status entry would be cross-\n * referenced, not here.\n */\n\nimport { copyFile, mkdir, open, writeFile } from \"node:fs/promises\"\nimport { homedir } from \"node:os\"\nimport { dirname, join, resolve } from \"node:path\"\nimport { execArgv } from \"./exec.js\"\nimport { computeProvenance, type ProvenanceInfo } from \"./provenance.js\"\n\nexport const SALVAGE_ROOT = (): string => resolve(homedir(), \".agentproto\", \"worktree-salvage\")\n\nexport interface SalvageManifest {\n repo: string\n /** `null` for a detached HEAD. */\n branch: string | null\n tipSha: string\n createdAt: string\n /** Relative paths of every unignored untracked file that was copied in. */\n untrackedFiles: string[]\n /** Whether `changes.patch` has any content (tracked-file changes existed). */\n hasPatch: boolean\n provenance: ProvenanceInfo\n}\n\nexport interface SalvageWorktreeInput {\n repoName: string\n worktreePath: string\n branch: string | null\n tipSha: string\n /** Identifies this worktree in the salvage directory name, e.g. its slug or branch. */\n slug: string\n sessionsPath?: string\n /** Injectable clock so tests can freeze `createdAt` / the directory name. */\n now?: () => string\n /** Override for `~/.agentproto/worktree-salvage` — tests use a temp dir. */\n salvageRoot?: string\n}\n\nexport interface SalvageResult {\n dir: string\n manifest: SalvageManifest\n}\n\n/** Untracked, non-ignored files in the worktree — the same class `git worktree remove` refuses without `--force`. */\nasync function listUntrackedFiles(worktreePath: string): Promise<string[]> {\n const res = await execArgv(\"git\", [\"-C\", worktreePath, \"ls-files\", \"--others\", \"--exclude-standard\"], worktreePath)\n if (res.exitCode !== 0) {\n throw new Error(`git ls-files --others failed in ${worktreePath} (exit ${res.exitCode}): ${res.stderr.trim()}`)\n }\n return res.stdout.split(\"\\n\").filter(Boolean)\n}\n\n/** `git diff HEAD` — staged + unstaged changes to tracked files, uniformly. Empty string on a clean tree. */\nasync function diffHead(worktreePath: string): Promise<string> {\n const res = await execArgv(\"git\", [\"-C\", worktreePath, \"diff\", \"HEAD\"], worktreePath)\n if (res.exitCode !== 0) {\n throw new Error(`git diff HEAD failed in ${worktreePath} (exit ${res.exitCode}): ${res.stderr.trim()}`)\n }\n return res.stdout\n}\n\n/** Sanitize a path segment for use in the salvage directory name (no slashes, no leading dot-dot). */\nfunction sanitizeSegment(value: string): string {\n return value.replace(/[^a-zA-Z0-9._-]+/g, \"-\").replace(/^-+/, \"\") || \"worktree\"\n}\n\n/** fsync one file by path — the durability guarantee: only after this resolves is the byte \"saved\". */\nasync function fsyncFile(path: string): Promise<void> {\n const handle = await open(path, \"r+\")\n try {\n await handle.sync()\n } finally {\n await handle.close()\n }\n}\n\nasync function writeFileSynced(path: string, content: string): Promise<void> {\n await mkdir(dirname(path), { recursive: true })\n await writeFile(path, content, \"utf8\")\n await fsyncFile(path)\n}\n\n/**\n * Snapshot `worktreePath`'s uncommitted state into a fresh salvage\n * directory. Safe to call on a clean tree (writes an empty patch, no\n * untracked files, still a manifest) — every path this function returns is\n * fsynced before it resolves.\n */\nexport async function salvageWorktree(input: SalvageWorktreeInput): Promise<SalvageResult> {\n const now = input.now ?? (() => new Date().toISOString())\n const createdAt = now()\n const tipShort = input.tipSha.slice(0, 7)\n const dateStamp = createdAt.slice(0, 10)\n const dirName = `${sanitizeSegment(input.slug)}-${tipShort}-${dateStamp}`\n const dir = resolve(input.salvageRoot ?? SALVAGE_ROOT(), sanitizeSegment(input.repoName), dirName)\n await mkdir(dir, { recursive: true })\n\n const [patch, untrackedFiles, provenance] = await Promise.all([\n diffHead(input.worktreePath),\n listUntrackedFiles(input.worktreePath),\n computeProvenance(input.worktreePath, { sessionsPath: input.sessionsPath }),\n ])\n\n await writeFileSynced(join(dir, \"changes.patch\"), patch)\n\n for (const relPath of untrackedFiles) {\n const dest = join(dir, \"untracked\", relPath)\n await mkdir(dirname(dest), { recursive: true })\n await copyFile(join(input.worktreePath, relPath), dest)\n await fsyncFile(dest)\n }\n\n const manifest: SalvageManifest = {\n repo: input.repoName,\n branch: input.branch,\n tipSha: input.tipSha,\n createdAt,\n untrackedFiles,\n hasPatch: patch.length > 0,\n provenance,\n }\n await writeFileSynced(join(dir, \"MANIFEST.json\"), JSON.stringify(manifest, null, 2) + \"\\n\")\n\n return { dir, manifest }\n}\n","import http from \"node:http\"\nimport { connect as netConnect, type Socket } from \"node:net\"\nimport type { ProxyTable } from \"./proxy-table.js\"\n\n/**\n * A small HTTP reverse proxy over a {@link ProxyTable}. Routes\n * `http://<script>--<branch>--<repo>.localhost:<proxy-port>` to the matched\n * service's local port. Supports WebSocket (and any) `Upgrade` passthrough by\n * splicing raw sockets. Targets are always `127.0.0.1` — services bind\n * locally, the proxy is the only public-ish surface.\n */\n\nconst TARGET_HOST = \"127.0.0.1\"\n\nfunction notFound(table: ProxyTable, host: string | undefined): string {\n const known = table.entries().map(([h]) => h)\n return (\n `worktree-proxy: no service for host \"${host ?? \"(none)\"}\"\\n` +\n (known.length ? `known hosts:\\n${known.map((h) => ` ${h}`).join(\"\\n\")}\\n` : \"no services registered\\n\")\n )\n}\n\n/** Build (but don't start) the proxy HTTP server backed by `table`. */\nexport function createProxyServer(table: ProxyTable): http.Server {\n const server = http.createServer((req, res) => {\n const targetPort = table.lookup(req.headers.host)\n if (targetPort === undefined) {\n res.writeHead(502, { \"content-type\": \"text/plain\" })\n res.end(notFound(table, req.headers.host))\n return\n }\n\n const proxyReq = http.request(\n {\n host: TARGET_HOST,\n port: targetPort,\n method: req.method,\n path: req.url,\n headers: req.headers,\n },\n (proxyRes) => {\n res.writeHead(proxyRes.statusCode ?? 502, proxyRes.headers)\n proxyRes.pipe(res)\n },\n )\n proxyReq.on(\"error\", (err) => {\n if (!res.headersSent) res.writeHead(502, { \"content-type\": \"text/plain\" })\n res.end(`worktree-proxy: upstream error: ${err.message}\\n`)\n })\n req.pipe(proxyReq)\n })\n\n // WebSocket / generic Upgrade passthrough: splice the client socket to a\n // fresh TCP connection to the target, replaying the original request line\n // and headers so the upstream completes its own handshake.\n server.on(\"upgrade\", (req, clientSocket: Socket, head: Buffer) => {\n const targetPort = table.lookup(req.headers.host)\n if (targetPort === undefined) {\n clientSocket.end(\"HTTP/1.1 502 Bad Gateway\\r\\n\\r\\n\")\n return\n }\n\n const upstream = netConnect(targetPort, TARGET_HOST, () => {\n const headerLines = [`${req.method} ${req.url} HTTP/1.1`]\n for (let i = 0; i < req.rawHeaders.length; i += 2) {\n headerLines.push(`${req.rawHeaders[i]}: ${req.rawHeaders[i + 1]}`)\n }\n upstream.write(headerLines.join(\"\\r\\n\") + \"\\r\\n\\r\\n\")\n if (head && head.length) upstream.write(head)\n upstream.pipe(clientSocket)\n clientSocket.pipe(upstream)\n })\n\n const teardown = (): void => {\n clientSocket.destroy()\n upstream.destroy()\n }\n upstream.on(\"error\", teardown)\n clientSocket.on(\"error\", teardown)\n upstream.on(\"close\", () => clientSocket.destroy())\n clientSocket.on(\"close\", () => upstream.destroy())\n })\n\n return server\n}\n\nexport interface RunningProxy {\n /** The port the proxy is listening on. */\n port: number\n /** The underlying server. */\n server: http.Server\n /** Stop the proxy. */\n close(): Promise<void>\n}\n\n/** Start the proxy server on `port` (0 → OS-assigned). Resolves once listening. */\nexport function startProxy(table: ProxyTable, port = 0): Promise<RunningProxy> {\n const server = createProxyServer(table)\n // Track every accepted socket so shutdown can force-drop them. An upgraded\n // (WebSocket) connection is detached from the server's own tracking, so\n // `server.close()` alone would hang on it — we destroy them explicitly.\n const sockets = new Set<Socket>()\n server.on(\"connection\", (socket: Socket) => {\n sockets.add(socket)\n socket.once(\"close\", () => sockets.delete(socket))\n })\n return new Promise((resolve, reject) => {\n server.once(\"error\", reject)\n server.listen(port, () => {\n const address = server.address()\n const boundPort = address && typeof address === \"object\" ? address.port : port\n resolve({\n port: boundPort,\n server,\n close: () =>\n new Promise<void>((res) => {\n for (const socket of sockets) socket.destroy()\n sockets.clear()\n server.close(() => res())\n }),\n })\n })\n })\n}\n","/**\n * `ForgeClient` — the only network-facing surface the reconciliation rule\n * (`status.ts`) depends on. Kept as an interface (not a concrete `gh` call)\n * so:\n * 1. `status.ts` stays testable with a fake — the fixture-repo tests never\n * shell out to a real forge or touch the network.\n * 2. The shape is forge-portable by construction (PLAN.md §7.1): GitLab has\n * the same two facts — \"PRs/MRs whose head is this branch\" and \"PRs/MRs\n * that contain this commit\" — under different verbs\n * (`refs/merge-requests/<n>/head`, `GET /merge_requests?…`). Only\n * GitHub ships today; a `GitlabForgeClient` is a second implementation\n * of this same interface, not a redesign.\n *\n * Two implementations ship: `GhCliForgeClient` (shells out to the `gh` CLI,\n * inheriting the caller's own `gh auth` session — zero config) and\n * `RestForgeClient` (plain `fetch` against the GitHub REST API using\n * `GITHUB_TOKEN` — no new npm dependency). `createForgeClient` picks\n * whichever is usable; when neither is, callers get a client that always\n * reports itself unreachable, which the reconciliation rule already knows\n * how to fall back from (PLAN.md §1.3 step 5: memo, else `unknown(offline)`,\n * never a guess).\n */\n\nimport { z } from \"zod\"\nimport { execArgv } from \"./exec.js\"\n\n/** A pull/merge request as the reconciliation rule needs to see it. */\nexport interface ForgePullRequestRef {\n number: number\n state: \"open\" | \"closed\"\n merged: boolean\n mergedAt: string | null\n headRefName: string\n headRefOid: string\n}\n\n/**\n * Thrown by a `ForgeClient` method when the forge could not be reached or\n * queried at all (network failure, missing/unauthenticated CLI, non-2xx HTTP\n * response). Never thrown for a legitimate empty result (a branch/commit\n * with no PRs is a valid, resolvable answer — `[]`, not an error). Callers\n * treat this as PLAN.md §1.3 step 5: \"never guess.\"\n */\nexport class ForgeUnavailableError extends Error {\n constructor(message: string, options?: { cause?: unknown }) {\n super(message, options)\n this.name = \"ForgeUnavailableError\"\n }\n}\n\nexport interface ForgeClient {\n /** PRs/MRs (any state) whose head branch is exactly `branch`. */\n pullRequestsForBranch(branch: string): Promise<ForgePullRequestRef[]>\n /**\n * PRs/MRs associated with a specific commit SHA — the rename/retarget-proof\n * signal (PLAN.md §1.3 step 2b): finds the PR even if the branch was\n * renamed or deleted before merge.\n */\n pullRequestsForCommit(sha: string): Promise<ForgePullRequestRef[]>\n /**\n * Ensure `oid` (a PR's `headRefOid`) is present in the local object\n * database, fetching `refs/pull/<number>/head` if it isn't. Always\n * fetchable even after the head branch was deleted on the remote\n * (PLAN.md §1.3 step 2, verified for #273/#312/#325/#271).\n */\n ensurePullHeadFetched(prNumber: number, oid: string): Promise<void>\n}\n\n/** A client that always reports itself unreachable — the \"no gh, no token\" case. */\nexport class UnreachableForgeClient implements ForgeClient {\n constructor(private readonly reason: string) {}\n async pullRequestsForBranch(): Promise<ForgePullRequestRef[]> {\n throw new ForgeUnavailableError(this.reason)\n }\n async pullRequestsForCommit(): Promise<ForgePullRequestRef[]> {\n throw new ForgeUnavailableError(this.reason)\n }\n async ensurePullHeadFetched(): Promise<void> {\n throw new ForgeUnavailableError(this.reason)\n }\n}\n\n// ── gh CLI implementation ───────────────────────────────────────────────\n\nconst ghPrListItemSchema = z.object({\n number: z.number(),\n state: z.string(),\n headRefName: z.string(),\n headRefOid: z.string(),\n mergedAt: z.string().nullable(),\n})\ntype GhPrListItem = z.infer<typeof ghPrListItemSchema>\nconst ghPrListSchema = z.array(ghPrListItemSchema)\n\nfunction normalizeGhPrListItem(item: GhPrListItem): ForgePullRequestRef {\n const state = item.state.toUpperCase()\n return {\n number: item.number,\n state: state === \"OPEN\" ? \"open\" : \"closed\",\n merged: state === \"MERGED\" || item.mergedAt !== null,\n mergedAt: item.mergedAt,\n headRefName: item.headRefName,\n headRefOid: item.headRefOid,\n }\n}\n\nconst ghApiCommitPullSchema = z.object({\n number: z.number(),\n state: z.string(),\n merged_at: z.string().nullable(),\n head: z.object({ ref: z.string(), sha: z.string() }),\n})\ntype GhApiCommitPull = z.infer<typeof ghApiCommitPullSchema>\nconst ghApiCommitPullListSchema = z.array(ghApiCommitPullSchema)\n\nfunction normalizeGhApiCommitPull(item: GhApiCommitPull): ForgePullRequestRef {\n return {\n number: item.number,\n state: item.state === \"open\" ? \"open\" : \"closed\",\n merged: item.merged_at !== null,\n mergedAt: item.merged_at,\n headRefName: item.head.ref,\n headRefOid: item.head.sha,\n }\n}\n\n/**\n * GitHub's REST API answers \"commit unknown to this repo\" (e.g. a local\n * commit that was never pushed) with HTTP 422 on `commits/:sha/pulls` —\n * empirically verified against a real unpushed worktree commit, not the 404\n * the endpoint's own docs imply. `gh api` surfaces the status in its stderr\n * as `(HTTP nnn)`. Both 404 and 422 here mean the same legitimate thing:\n * zero associated PRs, not \"the forge is unreachable\" — never guess step 5\n * on a genuinely empty, well-formed answer.\n */\nfunction isCommitNotFoundError(output: string): boolean {\n return /\\(HTTP (404|422)\\)/.test(output)\n}\n\n/** Runs `gh` in `repoRoot` so it auto-detects owner/repo from the `origin` remote there. */\nexport class GhCliForgeClient implements ForgeClient {\n constructor(private readonly repoRoot: string) {}\n\n private async runRaw(args: readonly string[]): Promise<{ exitCode: number; stdout: string; stderr: string }> {\n try {\n return await execArgv(\"gh\", args, this.repoRoot)\n } catch (err) {\n throw new ForgeUnavailableError(\n `gh ${args.join(\" \")} could not be run: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n )\n }\n }\n\n private async run(args: readonly string[]): Promise<string> {\n const result = await this.runRaw(args)\n if (result.exitCode !== 0) {\n throw new ForgeUnavailableError(\n `gh ${args.join(\" \")} failed (exit ${result.exitCode}): ${result.stderr.trim() || result.stdout.trim()}`,\n )\n }\n return result.stdout\n }\n\n private parseOutput<T>(stdout: string, schema: z.ZodType<T[]>, args: readonly string[]): T[] {\n let parsed: unknown\n try {\n parsed = JSON.parse(stdout)\n } catch (err) {\n throw new ForgeUnavailableError(\n `gh ${args.join(\" \")} produced non-JSON output: ${err instanceof Error ? err.message : String(err)}`,\n )\n }\n const result = schema.safeParse(parsed)\n if (!result.success) {\n throw new ForgeUnavailableError(`gh ${args.join(\" \")} output did not match the expected shape`)\n }\n return result.data\n }\n\n async pullRequestsForBranch(branch: string): Promise<ForgePullRequestRef[]> {\n const args = [\n \"pr\",\n \"list\",\n \"--head\",\n branch,\n \"--state\",\n \"all\",\n \"--json\",\n \"number,state,headRefName,headRefOid,mergedAt\",\n ]\n const stdout = await this.run(args)\n return this.parseOutput(stdout, ghPrListSchema, args).map(normalizeGhPrListItem)\n }\n\n async pullRequestsForCommit(sha: string): Promise<ForgePullRequestRef[]> {\n const args = [\"api\", `repos/{owner}/{repo}/commits/${sha}/pulls`]\n const result = await this.runRaw(args)\n if (result.exitCode !== 0) {\n if (isCommitNotFoundError(result.stderr) || isCommitNotFoundError(result.stdout)) return []\n throw new ForgeUnavailableError(\n `gh ${args.join(\" \")} failed (exit ${result.exitCode}): ${result.stderr.trim() || result.stdout.trim()}`,\n )\n }\n return this.parseOutput(result.stdout, ghApiCommitPullListSchema, args).map(normalizeGhApiCommitPull)\n }\n\n async ensurePullHeadFetched(prNumber: number, oid: string): Promise<void> {\n const check = await execArgv(\"git\", [\"-C\", this.repoRoot, \"cat-file\", \"-e\", `${oid}^{commit}`], this.repoRoot)\n if (check.exitCode === 0) return\n const fetch = await execArgv(\n \"git\",\n [\"-C\", this.repoRoot, \"fetch\", \"origin\", `refs/pull/${prNumber}/head`],\n this.repoRoot,\n )\n if (fetch.exitCode !== 0) {\n throw new ForgeUnavailableError(\n `git fetch origin refs/pull/${prNumber}/head failed: ${fetch.stderr.trim() || fetch.stdout.trim()}`,\n )\n }\n }\n}\n\n// ── GITHUB_TOKEN REST fallback (no new npm dependency — global fetch) ───\n\nconst restPullRequestSchema = z.object({\n number: z.number(),\n state: z.string(),\n merged_at: z.string().nullable(),\n head: z.object({ ref: z.string(), sha: z.string() }),\n})\ntype RestPullRequest = z.infer<typeof restPullRequestSchema>\nconst restPullRequestListSchema = z.array(restPullRequestSchema)\n\nfunction normalizeRestPr(item: RestPullRequest): ForgePullRequestRef {\n return {\n number: item.number,\n state: item.state === \"open\" ? \"open\" : \"closed\",\n merged: item.merged_at !== null,\n mergedAt: item.merged_at,\n headRefName: item.head.ref,\n headRefOid: item.head.sha,\n }\n}\n\n/** Parse `owner/repo` out of a `git remote get-url origin` value (ssh or https form). */\nexport function parseGithubOwnerRepo(remoteUrl: string): { owner: string; repo: string } | null {\n const ssh = remoteUrl.match(/^git@github\\.com:([^/]+)\\/(.+?)(\\.git)?$/)\n if (ssh?.[1] && ssh[2]) return { owner: ssh[1], repo: ssh[2] }\n const https = remoteUrl.match(/^https:\\/\\/github\\.com\\/([^/]+)\\/(.+?)(\\.git)?\\/?$/)\n if (https?.[1] && https[2]) return { owner: https[1], repo: https[2] }\n return null\n}\n\nexport class RestForgeClient implements ForgeClient {\n constructor(\n private readonly owner: string,\n private readonly repo: string,\n private readonly repoRoot: string,\n private readonly token: string,\n private readonly fetchFn: typeof fetch = fetch,\n ) {}\n\n private headers(): Record<string, string> {\n return {\n Authorization: `Bearer ${this.token}`,\n Accept: \"application/vnd.github+json\",\n \"X-GitHub-Api-Version\": \"2022-11-28\",\n \"User-Agent\": \"agentproto-worktree-status\",\n }\n }\n\n private async get(path: string): Promise<Response> {\n try {\n return await this.fetchFn(`https://api.github.com${path}`, { headers: this.headers() })\n } catch (err) {\n throw new ForgeUnavailableError(\n `GitHub REST request to ${path} failed: ${err instanceof Error ? err.message : String(err)}`,\n { cause: err },\n )\n }\n }\n\n private async pullRequestList(res: Response): Promise<ForgePullRequestRef[]> {\n const body: unknown = await res.json()\n const result = restPullRequestListSchema.safeParse(body)\n if (!result.success) {\n throw new ForgeUnavailableError(`GitHub REST response did not match the expected PR list shape`)\n }\n return result.data.map(normalizeRestPr)\n }\n\n async pullRequestsForBranch(branch: string): Promise<ForgePullRequestRef[]> {\n const res = await this.get(\n `/repos/${this.owner}/${this.repo}/pulls?head=${this.owner}:${encodeURIComponent(branch)}&state=all&per_page=100`,\n )\n if (!res.ok) {\n throw new ForgeUnavailableError(`GitHub REST pulls?head= failed: ${res.status} ${res.statusText}`)\n }\n return this.pullRequestList(res)\n }\n\n async pullRequestsForCommit(sha: string): Promise<ForgePullRequestRef[]> {\n const res = await this.get(`/repos/${this.owner}/${this.repo}/commits/${sha}/pulls?per_page=100`)\n // 404 is what the endpoint's docs imply for an unknown commit; 422 is what\n // it empirically returns for one that was never pushed (verified live).\n // Both mean the same legitimate thing: zero associated PRs.\n if (res.status === 404 || res.status === 422) return []\n if (!res.ok) {\n throw new ForgeUnavailableError(`GitHub REST commits/:sha/pulls failed: ${res.status} ${res.statusText}`)\n }\n return this.pullRequestList(res)\n }\n\n async ensurePullHeadFetched(prNumber: number, oid: string): Promise<void> {\n const check = await execArgv(\"git\", [\"-C\", this.repoRoot, \"cat-file\", \"-e\", `${oid}^{commit}`], this.repoRoot)\n if (check.exitCode === 0) return\n const fetch2 = await execArgv(\n \"git\",\n [\"-C\", this.repoRoot, \"fetch\", \"origin\", `refs/pull/${prNumber}/head`],\n this.repoRoot,\n )\n if (fetch2.exitCode !== 0) {\n throw new ForgeUnavailableError(\n `git fetch origin refs/pull/${prNumber}/head failed: ${fetch2.stderr.trim() || fetch2.stdout.trim()}`,\n )\n }\n }\n}\n\n/** Cheap \"is `gh` on PATH and authenticated\" probe — avoids a slow failure per branch. */\nasync function ghIsUsable(repoRoot: string): Promise<boolean> {\n try {\n const res = await execArgv(\"gh\", [\"auth\", \"status\"], repoRoot)\n return res.exitCode === 0\n } catch {\n return false\n }\n}\n\n/**\n * Pick the best available `ForgeClient` for `repoRoot`: `gh` CLI first (zero\n * config, inherits the caller's own auth), else `GITHUB_TOKEN` REST, else a\n * client that always reports unreachable — the reconciliation rule already\n * knows how to fall back from that (memo, else `unknown(offline)`).\n */\nexport async function createForgeClient(repoRoot: string): Promise<ForgeClient> {\n if (await ghIsUsable(repoRoot)) return new GhCliForgeClient(repoRoot)\n\n const token = process.env.GITHUB_TOKEN\n if (token) {\n const remote = await execArgv(\"git\", [\"-C\", repoRoot, \"remote\", \"get-url\", \"origin\"], repoRoot)\n const parsed = remote.exitCode === 0 ? parseGithubOwnerRepo(remote.stdout.trim()) : null\n if (parsed) return new RestForgeClient(parsed.owner, parsed.repo, repoRoot, token)\n }\n\n return new UnreachableForgeClient(\n \"no usable forge client: `gh` is not installed/authenticated and GITHUB_TOKEN is not set (or origin isn't a GitHub remote)\",\n )\n}\n","/**\n * `gc` (PLAN.md §5, PR-D): plan → apply → salvage over the status engine's\n * classification (`status.ts`, PR-A). This module owns no new git knowledge\n * — it reuses `listGitWorktrees` / `computeWorktreeStatus` / `classify` for\n * every fact and `salvageWorktree` / `worktree.cleanup` (PR-C) for every\n * mutation. Its only original logic is sequencing the four safety layers\n * (PLAN.md §5.2):\n *\n * 1. `planGc` is pure read: it classifies every worktree and returns a\n * plan. Nothing is mutated by calling it — the CLI's dry-run default\n * *is* just \"call planGc, print it, stop.\"\n * 2. `applyGc` re-derives each worktree's class from scratch immediately\n * before touching it (a fresh `listGitWorktrees` + `computeWorktreeStatus`,\n * not a reuse of the plan's stale snapshot) and refuses to act if the\n * class changed since the plan was made.\n * 3. The actual removal is `worktree.cleanup` with NO discard flags for a\n * reclaim-class entry — git's own non-`--force` refusal is the backstop\n * this module leans on, never a force flag \"just in case.\"\n * 4. A salvage-class entry is only ever touched via `salvageWorktree`\n * followed by `worktree.cleanup` with both discard flags — snapshot\n * first, removal only after the snapshot is durable (mirrors `worktree\n * archive`'s CLI verb, PR-C).\n *\n * The main worktree (`repoRoot` itself) is never part of the plan: `git\n * worktree list`'s first entry is always the main checkout, and a repo\n * sitting on an up-to-date default branch is trivially `fresh ∧ clean` —\n * exactly what `reclaim` looks for. Git itself refuses to remove\n * the main working tree (\"is a main working tree\", verified empirically),\n * but this module doesn't lean on that as the only guard: the main worktree\n * is filtered out before classification even runs, so it can never appear\n * in a plan, let alone be attempted.\n */\n\nimport { basename } from \"node:path\"\nimport { runTool } from \"@agentproto/driver\"\nimport { cleanupWorktreeTool } from \"./tools/index.js\"\nimport { worktreeProvider } from \"./provider/index.js\"\nimport { salvageWorktree } from \"./salvage.js\"\nimport type { ForgeClient } from \"./forge.js\"\nimport {\n classify,\n listGitWorktrees,\n computeWorktreeStatus,\n type GitWorktreeRef,\n type IntegrationState,\n type LivenessState,\n type TreeState,\n type VerdictMemoStore,\n} from \"./status.js\"\n\nconst candidates = [worktreeProvider]\n\n// ── classification (PLAN.md §5.1) ───────────────────────────────────────\n\nexport type GcClass = \"reclaim\" | \"salvage\" | \"hold\"\n\nexport interface ClassifyForGcOptions {\n /**\n * A clean, idle/daemon-unreachable DETACHED worktree moves from `hold` to\n * `reclaim` (PLAN.md §5.1). This is the only reclassification power any\n * flag has: every other hold reason — partial, open, unknown(offline),\n * gone-unexplained, diverged — is untouched by any flag, ever. Default\n * false.\n */\n includeDetached?: boolean\n /** Threaded straight through to `classify`'s `RECENT_WRITE_HOLD_WINDOW_MS` guard. Defaults to `Date.now()`. */\n nowMs?: number\n}\n\n/**\n * gc's own classifier, layered on top of `classify` (status.ts) rather than\n * reimplementing it — reuse first (AGENTS.md, PLAN.md §0.6). The one thing\n * `classify` cannot know is `--include-detached`, a gc-specific flag; that\n * override lives here, not in the read-only status engine `ls --status`\n * also depends on.\n */\nexport function classifyForGc(\n tree: TreeState,\n integration: IntegrationState,\n liveness: LivenessState,\n options: ClassifyForGcOptions = {},\n): GcClass {\n if (options.includeDetached && integration.state === \"detached\") {\n const idleOrUnreachable = liveness.state === \"idle\" || liveness.state === \"daemon-unreachable\"\n if (tree.state === \"clean\" && idleOrUnreachable) return \"reclaim\"\n }\n return classify(tree, integration, liveness, options.nowMs).class\n}\n\n// ── plan ─────────────────────────────────────────────────────────────\n\nexport interface GcPlanEntry {\n path: string\n branch: string | null\n head: string\n tree: TreeState\n integration: IntegrationState\n liveness: LivenessState\n /** Classification per PLAN.md §5.1, after `--include-detached` (if set). */\n class: GcClass\n}\n\nexport interface PlanGcInput {\n repoRoot: string\n repoName: string\n forge: ForgeClient\n memo: VerdictMemoStore\n defaultBranchRef?: string\n sessionsPath?: string\n includeDetached?: boolean\n now?: () => string\n /** See `ComputeWorktreeStatusInput.nowMs` (status.ts) — kept separate from `now`. Defaults to `Date.now()`. */\n nowMs?: number\n}\n\n/** Every linked worktree of `repoRoot` except the main checkout itself — see the module docblock. */\nasync function linkedWorktreesOf(repoRoot: string): Promise<GitWorktreeRef[]> {\n const worktrees = await listGitWorktrees(repoRoot)\n return worktrees.filter((w) => w.path !== repoRoot)\n}\n\nfunction toPlanEntry(\n worktree: GitWorktreeRef,\n status: { tree: TreeState; integration: IntegrationState; liveness: LivenessState },\n includeDetached: boolean,\n nowMs: number,\n): GcPlanEntry {\n return {\n path: worktree.path,\n branch: worktree.branch,\n head: worktree.head,\n tree: status.tree,\n integration: status.integration,\n liveness: status.liveness,\n class: classifyForGc(status.tree, status.integration, status.liveness, { includeDetached, nowMs }),\n }\n}\n\n/**\n * The dry-run plan (PLAN.md §5.2 layer 1): classify every linked worktree,\n * mutate nothing. This is the human's decision surface — `gc` with no flags\n * is exactly \"call this, print it, stop.\"\n */\nexport async function planGc(input: PlanGcInput): Promise<GcPlanEntry[]> {\n const includeDetached = Boolean(input.includeDetached)\n // One frozen instant for the whole plan's recent-write checks.\n const nowMs = input.nowMs ?? Date.now()\n const worktrees = await linkedWorktreesOf(input.repoRoot)\n const entries: GcPlanEntry[] = []\n for (const worktree of worktrees) {\n const status = await computeWorktreeStatus({\n repoRoot: input.repoRoot,\n repoName: input.repoName,\n worktree,\n forge: input.forge,\n memo: input.memo,\n defaultBranchRef: input.defaultBranchRef,\n sessionsPath: input.sessionsPath,\n now: input.now,\n })\n entries.push(toPlanEntry(worktree, status, includeDetached, nowMs))\n }\n return entries\n}\n\n// ── apply ────────────────────────────────────────────────────────────\n\nexport interface ApplyGcOptions {\n repoRoot: string\n repoName: string\n forge: ForgeClient\n memo: VerdictMemoStore\n defaultBranchRef?: string\n sessionsPath?: string\n includeDetached?: boolean\n /** Archive (salvage-then-remove) every salvage-class entry. Default false — salvage entries are left untouched. */\n salvageDirty?: boolean\n now?: () => string\n /** See `ComputeWorktreeStatusInput.nowMs` (status.ts) — kept separate from `now`. Defaults to `Date.now()`. */\n nowMs?: number\n /** Override for `~/.agentproto/worktree-salvage` — tests use a temp dir. */\n salvageRoot?: string\n}\n\nexport type GcApplyOutcome =\n | { path: string; branch: string | null; result: \"reclaimed\" }\n | { path: string; branch: string | null; result: \"salvaged\"; salvageDir: string }\n | { path: string; branch: string | null; result: \"held\" }\n /** Salvage-class, but `--salvage-dirty` was not passed: left untouched by design. */\n | { path: string; branch: string | null; result: \"skipped-dirty\" }\n /** Layer 2: re-classified at apply time to something other than the plan said — refuses rather than acting on a stale plan. */\n | { path: string; branch: string | null; result: \"aborted-reclassified\"; from: GcClass; to: GcClass }\n /** The worktree named in the plan no longer exists (already removed by something else since the plan was made). */\n | { path: string; branch: string | null; result: \"aborted-vanished\" }\n /** git itself (or the salvage snapshot) refused — the TOCTOU backstop actually firing, or a real I/O failure. */\n | { path: string; branch: string | null; result: \"failed\"; message: string }\n\nasync function findWorktree(repoRoot: string, path: string): Promise<GitWorktreeRef | null> {\n const worktrees = await linkedWorktreesOf(repoRoot)\n return worktrees.find((w) => w.path === path) ?? null\n}\n\nasync function reclaimOne(options: ApplyGcOptions, worktree: GitWorktreeRef): Promise<GcApplyOutcome> {\n try {\n await runTool({\n tool: cleanupWorktreeTool,\n candidates,\n input: {\n repoRoot: options.repoRoot,\n cwd: worktree.path,\n ...(worktree.branch ? { branch: worktree.branch } : {}),\n // Branch deletion only ever runs for a `reclaim`-class entry, which by\n // construction requires `integration ∈ {merged(*), fresh}` and\n // `tree = clean` (PLAN.md's invariant: branch -D only when there's\n // nothing uncommitted to lose, never a hold class).\n deleteBranch: true,\n // No discardUntracked/discardModified, ever, on this path (PLAN.md\n // §5.2 layer 3): `reclaim` means `tree = clean`, so plain `git\n // worktree remove` should succeed on its own; if the tree turned\n // dirty in the instant between the re-check above and this call, git\n // itself refuses and that refusal surfaces below as `failed` — never\n // a force flag \"just in case.\"\n },\n })\n } catch (err) {\n return {\n path: worktree.path,\n branch: worktree.branch,\n result: \"failed\",\n message: err instanceof Error ? err.message : String(err),\n }\n }\n return { path: worktree.path, branch: worktree.branch, result: \"reclaimed\" }\n}\n\nasync function salvageOne(options: ApplyGcOptions, worktree: GitWorktreeRef): Promise<GcApplyOutcome> {\n let salvageDir: string\n try {\n const result = await salvageWorktree({\n repoName: options.repoName,\n worktreePath: worktree.path,\n branch: worktree.branch,\n tipSha: worktree.head,\n slug: worktree.branch ?? basename(worktree.path),\n sessionsPath: options.sessionsPath,\n now: options.now,\n salvageRoot: options.salvageRoot,\n })\n salvageDir = result.dir\n } catch (err) {\n return {\n path: worktree.path,\n branch: worktree.branch,\n result: \"failed\",\n message: `salvage failed, nothing removed: ${err instanceof Error ? err.message : String(err)}`,\n }\n }\n\n try {\n await runTool({\n tool: cleanupWorktreeTool,\n candidates,\n input: {\n repoRoot: options.repoRoot,\n cwd: worktree.path,\n ...(worktree.branch ? { branch: worktree.branch } : {}),\n deleteBranch: true,\n // Both discard flags: the snapshot above is already durable (fsynced)\n // before this call, so nothing on disk is lost by discarding it here\n // (PLAN.md §5.2 layer 4 — salvage before discard).\n discardUntracked: true,\n discardModified: true,\n },\n })\n } catch (err) {\n return {\n path: worktree.path,\n branch: worktree.branch,\n result: \"failed\",\n message: `salvaged to ${salvageDir}, but removal failed: ${err instanceof Error ? err.message : String(err)}`,\n }\n }\n\n return { path: worktree.path, branch: worktree.branch, result: \"salvaged\", salvageDir }\n}\n\nasync function applyOne(entry: GcPlanEntry, options: ApplyGcOptions): Promise<GcApplyOutcome> {\n if (entry.class === \"hold\") {\n return { path: entry.path, branch: entry.branch, result: \"held\" }\n }\n if (entry.class === \"salvage\" && !options.salvageDirty) {\n return { path: entry.path, branch: entry.branch, result: \"skipped-dirty\" }\n }\n\n // Layer 2 (PLAN.md §5.2): re-check immediately before touching anything.\n // Re-derive the worktree ref itself, not just its status — a branch can\n // flip between plan and apply (the rendezvous-deploy branch-flip mid-\n // session is the plan's own existence proof for this), so re-listing\n // `git worktree list` is required, not just recomputing against the\n // plan's stale (path, branch, head) tuple.\n const fresh = await findWorktree(options.repoRoot, entry.path)\n if (!fresh) {\n return { path: entry.path, branch: entry.branch, result: \"aborted-vanished\" }\n }\n const status = await computeWorktreeStatus({\n repoRoot: options.repoRoot,\n repoName: options.repoName,\n worktree: fresh,\n forge: options.forge,\n memo: options.memo,\n defaultBranchRef: options.defaultBranchRef,\n sessionsPath: options.sessionsPath,\n now: options.now,\n })\n const freshClass = classifyForGc(status.tree, status.integration, status.liveness, {\n includeDetached: Boolean(options.includeDetached),\n nowMs: options.nowMs,\n })\n if (freshClass !== entry.class) {\n return {\n path: entry.path,\n branch: fresh.branch,\n result: \"aborted-reclassified\",\n from: entry.class,\n to: freshClass,\n }\n }\n\n if (freshClass === \"reclaim\") return reclaimOne(options, fresh)\n // The only other class that reaches this point is \"salvage\" with\n // `options.salvageDirty` true (both earlier guards above already returned\n // for \"hold\" and for \"salvage\" without the flag).\n return salvageOne(options, fresh)\n}\n\n/**\n * Execute a plan (PLAN.md §5.2 layers 2–4). Every entry is re-classified\n * from scratch immediately before it's touched; a `hold` entry is never\n * touched, a `salvage` entry is only touched when `salvageDirty` is true,\n * and every removal goes through `worktree.cleanup` — never a hand-rolled\n * `git worktree remove`.\n */\nexport async function applyGc(plan: readonly GcPlanEntry[], options: ApplyGcOptions): Promise<GcApplyOutcome[]> {\n const outcomes: GcApplyOutcome[] = []\n for (const entry of plan) {\n outcomes.push(await applyOne(entry, options))\n }\n return outcomes\n}\n"]}
@@ -1,4 +1,4 @@
1
- export { worktreeProvider } from '../chunk-BBAH3VLQ.mjs';
2
- import '../chunk-FRVPZTQN.mjs';
1
+ export { worktreeProvider } from '../chunk-SEVCUXPY.mjs';
2
+ import '../chunk-CM3XGWTY.mjs';
3
3
  //# sourceMappingURL=index.mjs.map
4
4
  //# sourceMappingURL=index.mjs.map
@@ -1,4 +1,5 @@
1
1
  import * as _agentproto_tool from '@agentproto/tool';
2
+ import { z } from 'zod';
2
3
 
3
4
  /**
4
5
  * AIP-14 contract: create a git worktree off a base ref, on its own branch,
@@ -9,20 +10,39 @@ declare const provisionWorktreeTool: _agentproto_tool.ToolHandle<{
9
10
  repoRoot: string;
10
11
  slug: string;
11
12
  base?: string | undefined;
13
+ branch?: string | undefined;
14
+ dir?: string | undefined;
12
15
  depsCmd?: string | undefined;
13
16
  copyGlobs?: string[] | undefined;
14
17
  linkPaths?: string[] | undefined;
18
+ runSetup?: boolean | undefined;
15
19
  }, {
16
20
  cwd: string;
17
21
  branch: string;
18
22
  }, _agentproto_tool.ToolContext>;
19
23
 
20
- /** AIP-14 contract: remove a git worktree, optionally deleting its branch. */
24
+ /**
25
+ * AIP-14 contract: remove a git worktree, optionally deleting its branch.
26
+ *
27
+ * Guarded by default (PLAN.md §5.2 layer 3): with neither discard flag set,
28
+ * this runs a plain `git worktree remove` — git itself is the final arbiter
29
+ * and refuses on modified or unignored-untracked files, tolerating gitignored
30
+ * trees like `node_modules/`. `discardUntracked` / `discardModified` each
31
+ * authorize exactly one class of destruction git otherwise refuses; only
32
+ * when the flags cover everything actually dirty does `--force` get passed
33
+ * through. This replaces an unconditional `--force` that used to destroy
34
+ * real edits indiscriminately (the incident this contract change exists to
35
+ * prevent) — hence `riskLevel: 2`, up from the old unconditional-force `1`.
36
+ */
21
37
  declare const cleanupWorktreeTool: _agentproto_tool.ToolHandle<{
22
38
  repoRoot: string;
23
39
  cwd: string;
24
40
  branch?: string | undefined;
25
41
  deleteBranch?: boolean | undefined;
42
+ base?: string | undefined;
43
+ runTeardown?: boolean | undefined;
44
+ discardUntracked?: boolean | undefined;
45
+ discardModified?: boolean | undefined;
26
46
  }, {
27
47
  removed: true;
28
48
  }, _agentproto_tool.ToolContext>;
@@ -43,4 +63,96 @@ declare const runGateTool: _agentproto_tool.ToolHandle<{
43
63
  stderr: string;
44
64
  }, _agentproto_tool.ToolContext>;
45
65
 
46
- export { cleanupWorktreeTool, provisionWorktreeTool, runGateTool };
66
+ /**
67
+ * AIP-14 contract: run a one-shot named `scripts.<name>` command from the
68
+ * repo's committed `agentproto.json` inside a worktree, with the
69
+ * `AGENTPROTO_*` context env injected. For long-running services use
70
+ * `worktree.start-service` instead.
71
+ */
72
+ declare const runScriptTool: _agentproto_tool.ToolHandle<{
73
+ repoRoot: string;
74
+ worktreePath: string;
75
+ branch: string;
76
+ script: string;
77
+ base?: string | undefined;
78
+ }, {
79
+ passed: boolean;
80
+ exitCode: number;
81
+ stdout: string;
82
+ stderr: string;
83
+ }, _agentproto_tool.ToolContext>;
84
+
85
+ /**
86
+ * AIP-14 contract: start a declared `type: "service"` script for a worktree.
87
+ * Allocates the service's port (declared port if free, else ephemeral),
88
+ * injects AGENTPROTO_PORT/URL + peer env, and registers its hostname with the
89
+ * reverse proxy. Idempotent per worktree+name.
90
+ */
91
+ declare const startServiceTool: _agentproto_tool.ToolHandle<{
92
+ repoRoot: string;
93
+ worktreePath: string;
94
+ branch: string;
95
+ script: string;
96
+ base?: string | undefined;
97
+ proxyPort?: number | undefined;
98
+ }, {
99
+ name: string;
100
+ hostname: string;
101
+ port: number;
102
+ url: string;
103
+ pid: number | null;
104
+ status: "running" | "exited";
105
+ exitCode: number | null;
106
+ startedAt: string | null;
107
+ }, _agentproto_tool.ToolContext>;
108
+
109
+ /** AIP-14 contract: stop a running supervised service for a worktree. */
110
+ declare const stopServiceTool: _agentproto_tool.ToolHandle<{
111
+ worktreePath: string;
112
+ script: string;
113
+ }, {
114
+ stopped: boolean;
115
+ }, _agentproto_tool.ToolContext>;
116
+
117
+ /**
118
+ * AIP-14 contract: list every declared service for a worktree with its
119
+ * resolved port / proxy URL and current run status. Resolves (allocating
120
+ * ports for) the worktree's services on first call so declared-but-unstarted
121
+ * services still appear.
122
+ */
123
+ declare const listServicesTool: _agentproto_tool.ToolHandle<{
124
+ repoRoot: string;
125
+ worktreePath: string;
126
+ branch: string;
127
+ base?: string | undefined;
128
+ proxyPort?: number | undefined;
129
+ }, {
130
+ services: {
131
+ name: string;
132
+ hostname: string;
133
+ port: number;
134
+ url: string;
135
+ pid: number | null;
136
+ status: "running" | "exited";
137
+ exitCode: number | null;
138
+ startedAt: string | null;
139
+ }[];
140
+ }, _agentproto_tool.ToolContext>;
141
+
142
+ /** Shared shape of a supervised service's status across the service tools. */
143
+ declare const serviceStatusSchema: z.ZodObject<{
144
+ name: z.ZodString;
145
+ hostname: z.ZodString;
146
+ port: z.ZodNumber;
147
+ url: z.ZodString;
148
+ pid: z.ZodNullable<z.ZodNumber>;
149
+ status: z.ZodEnum<{
150
+ running: "running";
151
+ exited: "exited";
152
+ }>;
153
+ exitCode: z.ZodNullable<z.ZodNumber>;
154
+ startedAt: z.ZodNullable<z.ZodString>;
155
+ }, z.core.$strip>;
156
+ type ServiceStatusOutput = z.infer<typeof serviceStatusSchema>;
157
+
158
+ export { type ServiceStatusOutput, cleanupWorktreeTool, listServicesTool, provisionWorktreeTool, runGateTool, runScriptTool, serviceStatusSchema, startServiceTool, stopServiceTool };
@@ -1,4 +1,4 @@
1
- import '../chunk-PSFICTF7.mjs';
2
- export { cleanupWorktreeTool, provisionWorktreeTool, runGateTool } from '../chunk-FRVPZTQN.mjs';
1
+ import '../chunk-E3EM24BS.mjs';
2
+ export { cleanupWorktreeTool, listServicesTool, provisionWorktreeTool, runGateTool, runScriptTool, serviceStatusSchema, startServiceTool, stopServiceTool } from '../chunk-CM3XGWTY.mjs';
3
3
  //# sourceMappingURL=index.mjs.map
4
4
  //# sourceMappingURL=index.mjs.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@agentproto/worktree",
3
- "version": "0.2.0",
3
+ "version": "0.3.0",
4
4
  "description": "AIP-14 TOOL contracts + builtin AIP-30 PROVIDER for provisioning, gating, and cleaning up a git worktree — the primitive an AgentStep binds its `cwd` to for a launch-agent-in-a-worktree workflow.",
5
5
  "keywords": [
6
6
  "agentproto",
@@ -21,7 +21,7 @@
21
21
  "bugs": {
22
22
  "url": "https://github.com/agentproto/ts/issues"
23
23
  },
24
- "license": "MIT",
24
+ "license": "Apache-2.0",
25
25
  "type": "module",
26
26
  "main": "dist/index.mjs",
27
27
  "module": "dist/index.mjs",
@@ -58,10 +58,10 @@
58
58
  "dependencies": {
59
59
  "@modelcontextprotocol/sdk": "^1.29.0",
60
60
  "zod": "^4.4.3",
61
- "@agentproto/harness": "0.2.0",
62
- "@agentproto/driver": "0.1.2",
63
- "@agentproto/tool": "0.2.0",
64
- "@agentproto/workflow-runtime": "0.3.0"
61
+ "@agentproto/driver": "0.1.3",
62
+ "@agentproto/tool": "0.2.1",
63
+ "@agentproto/harness": "0.2.1",
64
+ "@agentproto/workflow-runtime": "0.4.0"
65
65
  },
66
66
  "devDependencies": {
67
67
  "@types/node": "^25.6.2",
@@ -1,170 +0,0 @@
1
- import { provisionWorktreeTool, cleanupWorktreeTool, runGateTool } from './chunk-FRVPZTQN.mjs';
2
- import { implementTool, defineDriver } from '@agentproto/driver';
3
- import { lstat, mkdir, symlink, copyFile, readdir } from 'fs/promises';
4
- import { resolve, join, dirname, posix } from 'path';
5
- import { ToolError } from '@agentproto/tool';
6
- import { spawn } from 'child_process';
7
-
8
- /**
9
- * @agentproto/worktree v0.1.0
10
- * git-worktree provision / gate / cleanup TOOL contracts + builtin PROVIDER.
11
- */
12
- function execArgv(command, args, cwd) {
13
- return new Promise((resolvePromise, reject) => {
14
- const child = spawn(command, args, { cwd, shell: false, env: process.env });
15
- let stdout = "";
16
- let stderr = "";
17
- child.stdout?.on("data", (d) => stdout += d.toString("utf8"));
18
- child.stderr?.on("data", (d) => stderr += d.toString("utf8"));
19
- child.on("error", reject);
20
- child.on("close", (code) => resolvePromise({ exitCode: code ?? -1, stdout, stderr }));
21
- });
22
- }
23
- function execShell(cmd, cwd) {
24
- return new Promise((resolvePromise, reject) => {
25
- const child = spawn(cmd, { cwd, shell: true, env: process.env });
26
- let stdout = "";
27
- let stderr = "";
28
- child.stdout?.on("data", (d) => stdout += d.toString("utf8"));
29
- child.stderr?.on("data", (d) => stderr += d.toString("utf8"));
30
- child.on("error", reject);
31
- child.on("close", (code) => resolvePromise({ exitCode: code ?? -1, stdout, stderr }));
32
- });
33
- }
34
- async function execGit(repoRoot, args) {
35
- const result = await execArgv("git", ["-C", repoRoot, ...args], repoRoot);
36
- if (result.exitCode !== 0) {
37
- throw new Error(`git ${args.join(" ")} failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`);
38
- }
39
- return result;
40
- }
41
- function escapeSegment(seg) {
42
- let out = "";
43
- for (const ch of seg) {
44
- if (ch === "*") out += "[^/]*";
45
- else if (ch === "?") out += "[^/]";
46
- else out += ch.replace(/[.+^${}()|[\]\\]/g, "\\$&");
47
- }
48
- return out;
49
- }
50
- function globToRegExp(pattern) {
51
- const segments = pattern.split("/");
52
- let out = "^";
53
- segments.forEach((seg, i) => {
54
- const isLast = i === segments.length - 1;
55
- if (seg === "**") {
56
- out += isLast ? ".*" : "(?:[^/]+/)*";
57
- return;
58
- }
59
- out += escapeSegment(seg);
60
- if (!isLast) out += "/";
61
- });
62
- return new RegExp(out + "$");
63
- }
64
- function globBaseDir(pattern) {
65
- const segments = pattern.split("/");
66
- const literal = [];
67
- for (const seg of segments) {
68
- if (seg.includes("*") || seg.includes("?")) break;
69
- literal.push(seg);
70
- }
71
- if (literal.length === segments.length) literal.pop();
72
- return literal.join("/");
73
- }
74
- async function walk(root, dirRel) {
75
- const abs = dirRel ? join(root, dirRel) : root;
76
- let entries;
77
- try {
78
- entries = await readdir(abs, { withFileTypes: true });
79
- } catch {
80
- return [];
81
- }
82
- const out = [];
83
- for (const entry of entries) {
84
- if (entry.name === ".git" || entry.name === "node_modules") continue;
85
- const rel = dirRel ? posix.join(dirRel, entry.name) : entry.name;
86
- if (entry.isDirectory()) {
87
- const children = await walk(root, rel);
88
- for (const child of children) out.push(child);
89
- } else if (entry.isFile()) {
90
- out.push(rel);
91
- }
92
- }
93
- return out;
94
- }
95
- async function expandGlob(root, pattern) {
96
- const regex = globToRegExp(pattern);
97
- const base = globBaseDir(pattern);
98
- const candidates = await walk(root, base);
99
- return candidates.filter((rel) => regex.test(rel));
100
- }
101
-
102
- // src/provider/bodies/provision-worktree.body.ts
103
- var provisionWorktreeBuiltin = implementTool(
104
- provisionWorktreeTool,
105
- async ({ input }) => {
106
- const base = input.base ?? "origin/main";
107
- const branch = `wt/${input.slug}`;
108
- const cwd = resolve(input.repoRoot, "..", "_worktrees", input.slug);
109
- await execGit(input.repoRoot, ["worktree", "add", "-b", branch, cwd, base]);
110
- for (const rel of input.linkPaths ?? []) {
111
- const target = resolve(input.repoRoot, rel);
112
- const dest = join(cwd, rel);
113
- const existing = await lstat(dest).catch(() => null);
114
- if (existing) continue;
115
- await mkdir(dirname(dest), { recursive: true });
116
- await symlink(target, dest, "dir");
117
- }
118
- if (input.depsCmd) {
119
- const result = await execShell(input.depsCmd, cwd);
120
- if (result.exitCode !== 0) {
121
- throw new ToolError({
122
- code: "execution_failed",
123
- message: `depsCmd '${input.depsCmd}' failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`
124
- });
125
- }
126
- }
127
- for (const pattern of input.copyGlobs ?? []) {
128
- const matches = await expandGlob(input.repoRoot, pattern);
129
- for (const rel of matches) {
130
- const dest = join(cwd, rel);
131
- await mkdir(dirname(dest), { recursive: true });
132
- await copyFile(join(input.repoRoot, rel), dest);
133
- }
134
- }
135
- return { cwd, branch };
136
- }
137
- );
138
- var cleanupWorktreeBuiltin = implementTool(
139
- cleanupWorktreeTool,
140
- async ({ input }) => {
141
- await execGit(input.repoRoot, ["worktree", "remove", "--force", input.cwd]);
142
- if (input.deleteBranch && input.branch) {
143
- await execGit(input.repoRoot, ["branch", "-D", input.branch]);
144
- }
145
- return { removed: true };
146
- }
147
- );
148
- var runGateBuiltin = implementTool(runGateTool, async ({ input }) => {
149
- const result = await execShell(input.cmd, input.cwd);
150
- return { passed: result.exitCode === 0, ...result };
151
- });
152
-
153
- // src/provider/worktree-provider.ts
154
- var worktreeProvider = defineDriver({
155
- id: "worktree-builtin",
156
- name: "Git Worktree (built-in)",
157
- description: "In-process provision / gate / cleanup of git worktrees via direct git and shell invocations. No sandboxing \u2014 the host owns the filesystem and process boundary.",
158
- version: "0.1.0",
159
- kind: "builtin",
160
- implements: [
161
- { tool: "worktree.provision", version: "0.1.0" },
162
- { tool: "worktree.cleanup", version: "0.1.0" },
163
- { tool: "worktree.run-gate", version: "0.1.0" }
164
- ],
165
- implementations: [provisionWorktreeBuiltin, cleanupWorktreeBuiltin, runGateBuiltin]
166
- });
167
-
168
- export { execArgv, execGit, execShell, expandGlob, globToRegExp, worktreeProvider };
169
- //# sourceMappingURL=chunk-BBAH3VLQ.mjs.map
170
- //# sourceMappingURL=chunk-BBAH3VLQ.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/exec.ts","../src/glob.ts","../src/provider/bodies/provision-worktree.body.ts","../src/provider/bodies/cleanup-worktree.body.ts","../src/provider/bodies/run-gate.body.ts","../src/provider/worktree-provider.ts"],"names":["join","implementTool"],"mappings":"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","file":"chunk-BBAH3VLQ.mjs","sourcesContent":["import { spawn } from \"node:child_process\"\n\nexport interface ExecResult {\n exitCode: number\n stdout: string\n stderr: string\n}\n\n/** Run an argv (no shell — args pass through verbatim, no injection risk). */\nexport function execArgv(\n command: string,\n args: readonly string[],\n cwd: string,\n): Promise<ExecResult> {\n return new Promise((resolvePromise, reject) => {\n const child = spawn(command, args, { cwd, shell: false, env: process.env })\n let stdout = \"\"\n let stderr = \"\"\n child.stdout?.on(\"data\", (d) => (stdout += d.toString(\"utf8\")))\n child.stderr?.on(\"data\", (d) => (stderr += d.toString(\"utf8\")))\n child.on(\"error\", reject)\n child.on(\"close\", (code) => resolvePromise({ exitCode: code ?? -1, stdout, stderr }))\n })\n}\n\n/**\n * Run a single command string through a shell. Callers pass `depsCmd` /\n * `gateCmd` as a trusted, developer-authored config value (the same trust\n * model as a CI job's `script:` line) — not untrusted end-user input.\n */\nexport function execShell(cmd: string, cwd: string): Promise<ExecResult> {\n return new Promise((resolvePromise, reject) => {\n const child = spawn(cmd, { cwd, shell: true, env: process.env })\n let stdout = \"\"\n let stderr = \"\"\n child.stdout?.on(\"data\", (d) => (stdout += d.toString(\"utf8\")))\n child.stderr?.on(\"data\", (d) => (stderr += d.toString(\"utf8\")))\n child.on(\"error\", reject)\n child.on(\"close\", (code) => resolvePromise({ exitCode: code ?? -1, stdout, stderr }))\n })\n}\n\nexport async function execGit(repoRoot: string, args: readonly string[]): Promise<ExecResult> {\n const result = await execArgv(\"git\", [\"-C\", repoRoot, ...args], repoRoot)\n if (result.exitCode !== 0) {\n throw new Error(`git ${args.join(\" \")} failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`)\n }\n return result\n}\n","import { readdir } from \"node:fs/promises\"\nimport { join, posix } from \"node:path\"\n\nfunction escapeSegment(seg: string): string {\n let out = \"\"\n for (const ch of seg) {\n if (ch === \"*\") out += \"[^/]*\"\n else if (ch === \"?\") out += \"[^/]\"\n else out += ch.replace(/[.+^${}()|[\\]\\\\]/g, \"\\\\$&\")\n }\n return out\n}\n\n/** Compile a `/`-separated glob (supporting `*`, `?`, `**`) into an anchored regex. */\nexport function globToRegExp(pattern: string): RegExp {\n const segments = pattern.split(\"/\")\n let out = \"^\"\n segments.forEach((seg, i) => {\n const isLast = i === segments.length - 1\n if (seg === \"**\") {\n out += isLast ? \".*\" : \"(?:[^/]+/)*\"\n return\n }\n out += escapeSegment(seg)\n if (!isLast) out += \"/\"\n })\n return new RegExp(out + \"$\")\n}\n\n/** The literal (non-wildcard) directory prefix of a glob — where to start walking. */\nfunction globBaseDir(pattern: string): string {\n const segments = pattern.split(\"/\")\n const literal: string[] = []\n for (const seg of segments) {\n if (seg.includes(\"*\") || seg.includes(\"?\")) break\n literal.push(seg)\n }\n // Drop the last literal segment if it's the pattern's final segment (a filename),\n // not a directory to walk into.\n if (literal.length === segments.length) literal.pop()\n return literal.join(\"/\")\n}\n\nasync function walk(root: string, dirRel: string): Promise<string[]> {\n const abs = dirRel ? join(root, dirRel) : root\n let entries\n try {\n entries = await readdir(abs, { withFileTypes: true })\n } catch {\n return []\n }\n const out: string[] = []\n for (const entry of entries) {\n if (entry.name === \".git\" || entry.name === \"node_modules\") continue\n const rel = dirRel ? posix.join(dirRel, entry.name) : entry.name\n // entry.isDirectory() is false for symlinked dirs (Dirent reports the link's own\n // type, not the target's) — keep it that way so we never follow symlinks.\n if (entry.isDirectory()) {\n const children = await walk(root, rel)\n for (const child of children) out.push(child)\n } else if (entry.isFile()) {\n out.push(rel)\n }\n }\n return out\n}\n\n/** Expand a glob against `root`, returning root-relative posix paths of matching files. */\nexport async function expandGlob(root: string, pattern: string): Promise<string[]> {\n const regex = globToRegExp(pattern)\n const base = globBaseDir(pattern)\n const candidates = await walk(root, base)\n return candidates.filter((rel) => regex.test(rel))\n}\n","import { mkdir, copyFile, symlink, lstat } from \"node:fs/promises\"\nimport { dirname, join, resolve } from \"node:path\"\nimport { implementTool } from \"@agentproto/driver\"\nimport { ToolError } from \"@agentproto/tool\"\nimport { provisionWorktreeTool } from \"../../tools/provision-worktree.tool.js\"\nimport { execGit, execShell } from \"../../exec.js\"\nimport { expandGlob } from \"../../glob.js\"\n\nexport const provisionWorktreeBuiltin = implementTool(\n provisionWorktreeTool,\n async ({ input }) => {\n const base = input.base ?? \"origin/main\"\n const branch = `wt/${input.slug}`\n const cwd = resolve(input.repoRoot, \"..\", \"_worktrees\", input.slug)\n\n await execGit(input.repoRoot, [\"worktree\", \"add\", \"-b\", branch, cwd, base])\n\n // Symlink gitignored, expensive-to-recreate trees from the host repo into\n // the worktree BEFORE depsCmd, so a workspace whose graph spans gitignored\n // dirs (sibling repos, node_modules) resolves without a full reinstall.\n for (const rel of input.linkPaths ?? []) {\n const target = resolve(input.repoRoot, rel)\n const dest = join(cwd, rel)\n // A fresh worktree shouldn't already carry a gitignored path; if it does\n // (a tracked dir, or a re-run), leave it untouched rather than clobber.\n const existing = await lstat(dest).catch(() => null)\n if (existing) continue\n await mkdir(dirname(dest), { recursive: true })\n await symlink(target, dest, \"dir\")\n }\n\n if (input.depsCmd) {\n const result = await execShell(input.depsCmd, cwd)\n if (result.exitCode !== 0) {\n throw new ToolError({\n code: \"execution_failed\",\n message: `depsCmd '${input.depsCmd}' failed (exit ${result.exitCode}): ${result.stderr || result.stdout}`,\n })\n }\n }\n\n for (const pattern of input.copyGlobs ?? []) {\n const matches = await expandGlob(input.repoRoot, pattern)\n for (const rel of matches) {\n const dest = join(cwd, rel)\n await mkdir(dirname(dest), { recursive: true })\n await copyFile(join(input.repoRoot, rel), dest)\n }\n }\n\n return { cwd, branch }\n },\n)\n","import { implementTool } from \"@agentproto/driver\"\nimport { cleanupWorktreeTool } from \"../../tools/cleanup-worktree.tool.js\"\nimport { execGit } from \"../../exec.js\"\n\nexport const cleanupWorktreeBuiltin = implementTool(\n cleanupWorktreeTool,\n async ({ input }) => {\n // --force: a provisioned worktree almost always carries untracked files\n // by the time cleanup runs (installed deps, copied secrets, agent output)\n // — plain `worktree remove` refuses those. Cleanup's whole job is to\n // tear the directory down regardless.\n await execGit(input.repoRoot, [\"worktree\", \"remove\", \"--force\", input.cwd])\n if (input.deleteBranch && input.branch) {\n await execGit(input.repoRoot, [\"branch\", \"-D\", input.branch])\n }\n return { removed: true as const }\n },\n)\n","import { implementTool } from \"@agentproto/driver\"\nimport { runGateTool } from \"../../tools/run-gate.tool.js\"\nimport { execShell } from \"../../exec.js\"\n\nexport const runGateBuiltin = implementTool(runGateTool, async ({ input }) => {\n const result = await execShell(input.cmd, input.cwd)\n return { passed: result.exitCode === 0, ...result }\n})\n","import { defineDriver } from \"@agentproto/driver\"\nimport { provisionWorktreeBuiltin } from \"./bodies/provision-worktree.body.js\"\nimport { cleanupWorktreeBuiltin } from \"./bodies/cleanup-worktree.body.js\"\nimport { runGateBuiltin } from \"./bodies/run-gate.body.js\"\n\n/**\n * AIP-30 PROVIDER for the three `worktree.*` TOOL contracts. `kind: \"builtin\"`\n * — runs in-process, shelling out to `git` / the caller's commands directly.\n * No subprocess-DRIVER indirection, no network hop.\n */\nexport const worktreeProvider = defineDriver({\n id: \"worktree-builtin\",\n name: \"Git Worktree (built-in)\",\n description:\n \"In-process provision / gate / cleanup of git worktrees via direct git \" +\n \"and shell invocations. No sandboxing — the host owns the filesystem \" +\n \"and process boundary.\",\n version: \"0.1.0\",\n kind: \"builtin\",\n implements: [\n { tool: \"worktree.provision\", version: \"0.1.0\" },\n { tool: \"worktree.cleanup\", version: \"0.1.0\" },\n { tool: \"worktree.run-gate\", version: \"0.1.0\" },\n ],\n implementations: [provisionWorktreeBuiltin, cleanupWorktreeBuiltin, runGateBuiltin],\n})\n"]}
@@ -1,67 +0,0 @@
1
- import { z } from 'zod';
2
- import { defineTool } from '@agentproto/tool';
3
-
4
- /**
5
- * @agentproto/worktree v0.1.0
6
- * git-worktree provision / gate / cleanup TOOL contracts + builtin PROVIDER.
7
- */
8
-
9
- var provisionWorktreeTool = defineTool({
10
- id: "worktree.provision",
11
- description: "Create a git worktree for `repoRoot` at a sibling '_worktrees/<slug>' directory, on a new branch 'wt/<slug>' cut from `base`. If `depsCmd` is given, it runs inside the new worktree afterwards (e.g. install deps). If `copyGlobs` is given, matching files under `repoRoot` (including gitignored ones, e.g. local secrets) are copied into the worktree at the same relative path. If `linkPaths` is given, each is symlinked from `repoRoot` into the worktree before `depsCmd` runs \u2014 for gitignored, expensive-to-recreate trees a fresh worktree lacks (node_modules, sibling workspace repos) so the workspace graph resolves without a full reinstall.",
12
- version: "0.1.0",
13
- inputSchema: z.object({
14
- repoRoot: z.string().describe("Absolute path to the git repository root."),
15
- base: z.string().optional().describe("Ref the new branch is cut from. Default 'origin/main'."),
16
- slug: z.string().regex(/^[a-z0-9][a-z0-9-]*$/, "slug must be lowercase kebab-case").describe("Short identifier \u2014 names both the worktree directory and its branch."),
17
- depsCmd: z.string().optional().describe("Shell command run inside the worktree after creation, e.g. 'pnpm install --prefer-offline'."),
18
- copyGlobs: z.array(z.string()).optional().describe("Glob patterns (relative to repoRoot) of gitignored files to copy into the worktree, e.g. 'envs/**/.env.local'."),
19
- linkPaths: z.array(z.string()).optional().describe("Relative paths (dirs or files) symlinked from repoRoot into the worktree before depsCmd, e.g. 'node_modules' or a gitignored sibling workspace repo. Lets the workspace graph resolve without a full reinstall.")
20
- }),
21
- outputSchema: z.object({
22
- cwd: z.string().describe("Absolute path to the created worktree."),
23
- branch: z.string().describe("The branch the worktree was created on.")
24
- }),
25
- mutates: ["fs:write"],
26
- approval: "auto",
27
- riskLevel: 1
28
- });
29
- var cleanupWorktreeTool = defineTool({
30
- id: "worktree.cleanup",
31
- description: "Remove a git worktree created by 'worktree.provision' (force-removed, since installed deps / copied secrets / agent output leave it with untracked files). If `deleteBranch` is true and `branch` is given, also force-delete that branch.",
32
- version: "0.1.0",
33
- inputSchema: z.object({
34
- repoRoot: z.string().describe("Absolute path to the git repository root."),
35
- cwd: z.string().describe("Absolute path to the worktree to remove."),
36
- branch: z.string().optional().describe("The worktree's branch, for deleteBranch."),
37
- deleteBranch: z.boolean().optional().describe("Also force-delete `branch` after removing the worktree.")
38
- }),
39
- outputSchema: z.object({
40
- removed: z.literal(true)
41
- }),
42
- mutates: ["fs:write"],
43
- approval: "auto",
44
- riskLevel: 1
45
- });
46
- var runGateTool = defineTool({
47
- id: "worktree.run-gate",
48
- description: "Run a gate command (e.g. 'pnpm test') inside `cwd` and report pass/fail from its exit code, along with captured stdout/stderr.",
49
- version: "0.1.0",
50
- inputSchema: z.object({
51
- cwd: z.string().describe("Directory to run the command in."),
52
- cmd: z.string().describe("Shell command to run, e.g. 'pnpm test'.")
53
- }),
54
- outputSchema: z.object({
55
- passed: z.boolean(),
56
- exitCode: z.number().int(),
57
- stdout: z.string(),
58
- stderr: z.string()
59
- }),
60
- mutates: [],
61
- approval: "auto",
62
- riskLevel: 1
63
- });
64
-
65
- export { cleanupWorktreeTool, provisionWorktreeTool, runGateTool };
66
- //# sourceMappingURL=chunk-FRVPZTQN.mjs.map
67
- //# sourceMappingURL=chunk-FRVPZTQN.mjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/tools/provision-worktree.tool.ts","../src/tools/cleanup-worktree.tool.ts","../src/tools/run-gate.tool.ts"],"names":["defineTool","z"],"mappings":"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","file":"chunk-FRVPZTQN.mjs","sourcesContent":["import { z } from \"zod\"\nimport { defineTool } from \"@agentproto/tool\"\n\n/**\n * AIP-14 contract: create a git worktree off a base ref, on its own branch,\n * optionally installing deps and copying gitignored files (secrets) into it.\n * Agnostic — no hardcoded package manager or env layout; both are inputs.\n */\nexport const provisionWorktreeTool = defineTool({\n id: \"worktree.provision\",\n description:\n \"Create a git worktree for `repoRoot` at a sibling '_worktrees/<slug>' \" +\n \"directory, on a new branch 'wt/<slug>' cut from `base`. If `depsCmd` is \" +\n \"given, it runs inside the new worktree afterwards (e.g. install deps). \" +\n \"If `copyGlobs` is given, matching files under `repoRoot` (including \" +\n \"gitignored ones, e.g. local secrets) are copied into the worktree at \" +\n \"the same relative path. If `linkPaths` is given, each is symlinked from \" +\n \"`repoRoot` into the worktree before `depsCmd` runs — for gitignored, \" +\n \"expensive-to-recreate trees a fresh worktree lacks (node_modules, \" +\n \"sibling workspace repos) so the workspace graph resolves without a full \" +\n \"reinstall.\",\n version: \"0.1.0\",\n inputSchema: z.object({\n repoRoot: z.string().describe(\"Absolute path to the git repository root.\"),\n base: z\n .string()\n .optional()\n .describe(\"Ref the new branch is cut from. Default 'origin/main'.\"),\n slug: z\n .string()\n .regex(/^[a-z0-9][a-z0-9-]*$/, \"slug must be lowercase kebab-case\")\n .describe(\"Short identifier — names both the worktree directory and its branch.\"),\n depsCmd: z\n .string()\n .optional()\n .describe(\"Shell command run inside the worktree after creation, e.g. 'pnpm install --prefer-offline'.\"),\n copyGlobs: z\n .array(z.string())\n .optional()\n .describe(\"Glob patterns (relative to repoRoot) of gitignored files to copy into the worktree, e.g. 'envs/**/.env.local'.\"),\n linkPaths: z\n .array(z.string())\n .optional()\n .describe(\"Relative paths (dirs or files) symlinked from repoRoot into the worktree before depsCmd, e.g. 'node_modules' or a gitignored sibling workspace repo. Lets the workspace graph resolve without a full reinstall.\"),\n }),\n outputSchema: z.object({\n cwd: z.string().describe(\"Absolute path to the created worktree.\"),\n branch: z.string().describe(\"The branch the worktree was created on.\"),\n }),\n mutates: [\"fs:write\"],\n approval: \"auto\",\n riskLevel: 1,\n})\n","import { z } from \"zod\"\nimport { defineTool } from \"@agentproto/tool\"\n\n/** AIP-14 contract: remove a git worktree, optionally deleting its branch. */\nexport const cleanupWorktreeTool = defineTool({\n id: \"worktree.cleanup\",\n description:\n \"Remove a git worktree created by 'worktree.provision' (force-removed, \" +\n \"since installed deps / copied secrets / agent output leave it with \" +\n \"untracked files). If `deleteBranch` is true and `branch` is given, also \" +\n \"force-delete that branch.\",\n version: \"0.1.0\",\n inputSchema: z.object({\n repoRoot: z.string().describe(\"Absolute path to the git repository root.\"),\n cwd: z.string().describe(\"Absolute path to the worktree to remove.\"),\n branch: z.string().optional().describe(\"The worktree's branch, for deleteBranch.\"),\n deleteBranch: z.boolean().optional().describe(\"Also force-delete `branch` after removing the worktree.\"),\n }),\n outputSchema: z.object({\n removed: z.literal(true),\n }),\n mutates: [\"fs:write\"],\n approval: \"auto\",\n riskLevel: 1,\n})\n","import { z } from \"zod\"\nimport { defineTool } from \"@agentproto/tool\"\n\n/**\n * AIP-14 contract: run a caller-provided gate/check command inside a\n * directory (typically a provisioned worktree) and report pass/fail.\n * `cmd` is a trusted, developer-authored config value (same trust model as\n * a CI job's `script:` line), run through a shell so it may include flags.\n */\nexport const runGateTool = defineTool({\n id: \"worktree.run-gate\",\n description:\n \"Run a gate command (e.g. 'pnpm test') inside `cwd` and report pass/fail \" +\n \"from its exit code, along with captured stdout/stderr.\",\n version: \"0.1.0\",\n inputSchema: z.object({\n cwd: z.string().describe(\"Directory to run the command in.\"),\n cmd: z.string().describe(\"Shell command to run, e.g. 'pnpm test'.\"),\n }),\n outputSchema: z.object({\n passed: z.boolean(),\n exitCode: z.number().int(),\n stdout: z.string(),\n stderr: z.string(),\n }),\n mutates: [],\n approval: \"auto\",\n riskLevel: 1,\n})\n"]}