Pi 0.85.1 and Claude Code 2.1.289 (Agent SDK 0.3.289), 34 cases against a scripted local model in a loopback-only network namespace. MATRIX.md has the command, outcome, model-visible message and fail-closed column per case, and one rely-on line per case. Evidence under evidence/. Co-Authored-By: Claude Opus 5.5 <[email protected]>
25 lines
1.3 KiB
TypeScript
25 lines
1.3 KiB
TypeScript
// 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;
|
|
});
|
|
}
|