✔ sessionModel: agent vars win, then the system's execution settings (13.13889ms)
✔ a pi bundle: prompt, policy, tools and manifest, 0600 in a 0700 directory (4.754143ms)
✔ a claude-code bundle adds the wrapped gate hook and the MCP config (2.793955ms)
✔ a bundle is written once: an existing file refuses (2.706625ms)
✔ a path with a single quote can't go into the hook command (1.81122ms)
✔ allow exits 0, a deny exits 2 with the reason on stderr (124.816491ms)
✔ a missing or wrong policy, or a bad event, exits 2 (95.807838ms)
✔ the bundle's wrapped command: a missing gate or node still blocks (1096.785958ms)
✔ claude: typed tools through MCP, the hook blocks, builtins outside --tools don't exist (851.292573ms)
✔ claude: the hook alone blocks a path outside the workspace (519.27064ms)
✔ claude: a second turn resumes the first turn's session (776.321586ms)
✔ claude adapter: --restricted is always passed (5.499034ms)
✔ claude: CLAUDE.md files and auto-memory don't reach the model; without --restricted they do (867.702037ms)
✔ claude: a missing hook or MCP file refuses before claude starts (10.298703ms)
✔ pi: policy tools and typed tools pass, anything else is blocked (4.220059ms)
✔ claude: builtins map from pi names, typed tools need the mcp prefix (1.062326ms)
✔ file tool paths must resolve inside the workspace (1.522023ms)
✔ pi's own path normalisation can't be used to step out (1.483331ms)
✔ a symlink inside the workspace that points out is outside (1.269628ms)
✔ a dangling symlink is refused at any depth, in both harnesses (4.263112ms)
✔ claude path fields per tool (1.118926ms)
✔ glob patterns stay inside the workspace (1.022964ms)
✔ a path that can't be checked is blocked (0.454162ms)
✔ initialize, ping and tools/list (48.504759ms)
✔ tools/call goes through the tool socket; a refusal is an isError result (38.124036ms)
✔ unknown tools and methods are JSON-RPC errors and never reach the socket (33.297546ms)
✔ a missing argument is a usage error (30.763266ms)
✔ pi: typed tools reach the socket, the gate blocks, agent_end writes the marker (405.108517ms)
✔ pi: a write through a dangling symlink is blocked, and nothing appears outside (381.475986ms)
✔ pi: a missing extension refuses before any model call (7.159081ms)
✔ pi: an extension without its configuration fails pi's start (340.423518ms)
✔ founderCheck: founder variables, then a needed service without a usable token (1.358533ms)
✔ turnRequest names the sender, class, reply and decision (0.199896ms)
✔ a message becomes a turn, the answer goes back as a RESULT, SIGTERM releases and exits 0 (249.9341ms)
✔ a SIGTERM before the claim stops the runner with exit 0 and no claim (116.889992ms)
✔ typed tools carry the runner's capability; launch goes to the host's launch socket (423.548366ms)
✔ a RESULT gets no automatic reply; failed turns reply with the reason (1349.631237ms)
✔ SIGTERM during a turn kills the turn's process group and still exits 0 (177.09152ms)
✔ founder credentials stop before the claim (20) (194.175258ms)
✔ a refused claim exits 21; an ended run's capability exits 22 (236.143025ms)
✔ the launch ending under a running session exits 22 (118.270606ms)
✔ a broker that stays unreachable exits 23 after brokerRetries polls (250.227078ms)
✔ a broker that is down at the claim exits 23, not 21 (93.191317ms)
✔ no capability, or a malformed one, on stdin exits 2 (189.733487ms)
✔ a missing or malformed policy exits 2 before the claim (128.184915ms)
✔ the PM gets launch, its task verbs and the reads (6.94313ms)
✔ a coder gets no launch, no resolve_decision, and no task tools without a tracker (2.622772ms)
✔ launch only when the business's launch block names the instance as launcher (2.472817ms)
✔ an action outside the instance's authority has no tool (2.525087ms)
✔ callTool: one JSON line out, the result back, a refusal rejects (10.34312ms)
ℹ tests 50
ℹ suites 0
ℹ pass 50
ℹ fail 0
ℹ cancelled 0
ℹ skipped 0
ℹ todo 0
ℹ duration_ms 10459.373798
