|
| 1 | +#!/usr/bin/env node |
| 2 | +/** |
| 3 | + * Agent-facing `gh` policy shim. |
| 4 | + * |
| 5 | + * Installed at `.tools/bin/gh` by `scripts/install-git-hooks.mjs`. |
| 6 | + * When coding-agent env markers are set, blocks undraft side channels |
| 7 | + * (`gh pr ready`, ready_for_review API). Use `pnpm pr:ready` instead |
| 8 | + * (sets AGENT_PR_SHIP=1 for the real call). |
| 9 | + * |
| 10 | + * Humans / non-agents: transparent pass-through to the next `gh` on PATH. |
| 11 | + */ |
| 12 | +import * as NodeChildProcess from "node:child_process"; |
| 13 | +import * as NodePath from "node:path"; |
| 14 | +import * as NodeProcess from "node:process"; |
| 15 | +import * as NodeURL from "node:url"; |
| 16 | +import { isCodingAgent } from "./lib/agent-env.mjs"; |
| 17 | +import { findRealGh, inspectAgentGhCommand } from "./lib/agent-gh-policy.mjs"; |
| 18 | + |
| 19 | +const selfPath = NodeURL.fileURLToPath(import.meta.url); |
| 20 | +const argv = NodeProcess.argv.slice(2); |
| 21 | + |
| 22 | +if (isCodingAgent()) { |
| 23 | + const decision = inspectAgentGhCommand(argv); |
| 24 | + if (decision.blocked) { |
| 25 | + console.error(`agent gh: blocked: ${decision.reason}`); |
| 26 | + NodeProcess.exit(1); |
| 27 | + } |
| 28 | +} |
| 29 | + |
| 30 | +const realGh = findRealGh({ selfPath }); |
| 31 | +if (!realGh) { |
| 32 | + console.error("agent gh: could not resolve real `gh` binary (set AGENT_GH_REAL)"); |
| 33 | + NodeProcess.exit(127); |
| 34 | +} |
| 35 | + |
| 36 | +// Avoid re-entering this shim if PATH still prefers us. |
| 37 | +const env = { ...NodeProcess.env }; |
| 38 | +const toolsBin = NodePath.resolve(NodePath.dirname(selfPath), "..", ".tools", "bin"); |
| 39 | +const pathParts = (env["PATH"] ?? "").split(NodePath.delimiter).filter(Boolean); |
| 40 | +env["PATH"] = pathParts.filter((p) => NodePath.resolve(p) !== toolsBin).join(NodePath.delimiter); |
| 41 | +env["AGENT_GH_REAL"] = realGh; |
| 42 | + |
| 43 | +const result = NodeChildProcess.spawnSync(realGh, argv, { |
| 44 | + stdio: "inherit", |
| 45 | + env, |
| 46 | + shell: false, |
| 47 | +}); |
| 48 | +NodeProcess.exit(result.status === null ? 1 : result.status); |
0 commit comments