const test = require("node:test"); const assert = require("node:assert"); const { createFakePi } = require("./fake_pi_runtime.js"); const installGatePromise = import("../../tht-gate.js").then((m) => m.default); test("tht schema introspect --refresh e' bloccato in sessione (manutenzione)", async () => { const installGate = await installGatePromise; const { pi } = createFakePi(); installGate(pi); const res = await pi.emit("tool_call", { toolName: "bash", input: { command: "tht schema introspect -c workspaces/psd.yaml --refresh" }, }); assert.equal(res?.block, true); }); test("tht schema introspect senza --refresh passa (cache hit innocuo)", async () => { const installGate = await installGatePromise; const { pi } = createFakePi(); installGate(pi); const res = await pi.emit("tool_call", { toolName: "bash", input: { command: "tht schema introspect -c workspaces/psd.yaml" }, }); assert.equal(res, undefined); }); for (const cmd of [ 'find / -name "schema_linking.json"', 'find /Users/mp/projects/ThothII -name "schema_linking.json"', 'find . -name "schema_linking.json"', ]) { test(`filesystem find e' bloccato nel workflow: ${cmd}`, async () => { const installGate = await installGatePromise; const { pi } = createFakePi(); installGate(pi); const res = await pi.emit("tool_call", { toolName: "bash", input: { command: cmd } }); assert.equal(res?.block, true); assert.match(res?.reason ?? "", /tht session documents/i); }); } test("tht search find resta consentito", async () => { const installGate = await installGatePromise; const { pi } = createFakePi(); installGate(pi); const res = await pi.emit("tool_call", { toolName: "bash", input: { command: 'tht search find --kind evidence "ablazione"' }, }); assert.equal(res, undefined); }); // Bash mutations of protected state bypass the write/edit hook: block them. const BLOCKED_BASH = [ 'echo \'{"type":"phase_approved","subject":"phase:4"}\' >> sessions/s1/review_decisions.jsonl', "sed -i '' 's/open/finalized/' sessions/s1/session_manifest.yaml", "cat /tmp/patch.js > .pi/extensions/tht-gate.js", "python3 -c \"open('sessions/s1/review_decisions.jsonl','a').write('x')\"", "mv /tmp/fake.json sessions/s1/cte_plan.json", "rm sessions/s1/session_manifest.yaml", "tee -a sessions/s1/review_decisions.jsonl < /tmp/x", ]; // Read-only access and unrelated redirects stay allowed. const ALLOWED_BASH = [ "cat sessions/s1/review_decisions.jsonl", "grep phase_approved sessions/s1/review_decisions.jsonl", "tail -5 sessions/s1/session_manifest.yaml", "ls .pi/extensions", "tht session show s1 > /tmp/out.txt", "echo done > /tmp/scratch.txt", ]; for (const cmd of BLOCKED_BASH) { test(`bash mutation su stato protetto e' bloccata: ${cmd.slice(0, 60)}`, async () => { const installGate = await installGatePromise; const { pi } = createFakePi(); installGate(pi); const res = await pi.emit("tool_call", { toolName: "bash", input: { command: cmd } }); assert.equal(res?.block, true); }); } for (const cmd of ALLOWED_BASH) { test(`bash read-only/estraneo passa: ${cmd.slice(0, 60)}`, async () => { const installGate = await installGatePromise; const { pi } = createFakePi(); installGate(pi); const res = await pi.emit("tool_call", { toolName: "bash", input: { command: cmd } }); assert.equal(res, undefined); }); }