// Row S0 probe gate for Pi: a `tool_call` handler that guards the `write` // tool. GATE_MODE picks the behaviour; GATE_LOG records each invocation, so // a run shows whether the gate ran at all. import { appendFileSync } from "node:fs"; const mode = process.env.GATE_MODE ?? "block"; const note = (s: string) => appendFileSync(process.env.GATE_LOG ?? "/dev/null", `${new Date().toISOString()} ${s}\n`); export default function (pi: any) { note(`loaded mode=${mode}`); pi.on("tool_call", async (event: any) => { note(`invoked tool=${event.toolName} mode=${mode}`); if (event.toolName !== "write") return undefined; if (mode === "block") return { block: true, reason: "PROBE-GATE: write is blocked by policy" }; if (mode === "throw") throw new Error("PROBE-GATE crashed (throw)"); if (mode === "throw-string") throw "PROBE-GATE crashed (non-Error throw)"; // "hang" never settles and holds nothing open; "slow" holds a timer, as a // gate waiting on I/O would, and blocks only after an hour. if (mode === "hang") return new Promise(() => {}); if (mode === "slow") return new Promise((r) => setTimeout(() => r({ block: true, reason: "PROBE-GATE: blocked after a delay" }), 3_600_000)); if (mode === "exit") process.exit(3); return undefined; }); }