test(uok): fail-closed contract for triage-apply gate emission
Adds the missing test case that confirms the fail-closed semantics the parallel worker shipped in slice 3a: when the trace writer cannot persist a UOK gate record (e.g. .sf/traces is unwritable), runTriageApply MUST abort before any subagent runs and surface the emission failure as the run error. This pins down the contract codex Q5 noted as soft: enrichment failures are debug-only, but PRIMARY gate emission for the apply flow is hard-required. Without observable gates, an apply that mutates the ledger has no audit trail — refusing is the right call. Test asserts: trace-dir write failure → ok=false, error contains "UOK gate emission failed for trusted-agent-source-gate", and the mocked agentRunner was never invoked. Suite: 1682/1682. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
454e051aed
commit
61d3031007
1 changed files with 29 additions and 1 deletions
|
|
@ -8,7 +8,14 @@
|
|||
* surface=headless, runControl=supervised, permissionProfile=high, traceId=
|
||||
* the flowId. The outcome reflects the decision (pass/fail/manual-attention).
|
||||
*/
|
||||
import { mkdirSync, mkdtempSync, readFileSync, readdirSync, rmSync } from "node:fs";
|
||||
import {
|
||||
mkdirSync,
|
||||
mkdtempSync,
|
||||
readFileSync,
|
||||
readdirSync,
|
||||
rmSync,
|
||||
writeFileSync,
|
||||
} from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { afterEach, beforeEach, describe, expect, test } from "vitest";
|
||||
|
|
@ -179,4 +186,25 @@ describe("runTriageApply emits gate_run trace events with schema-v2 metadata", (
|
|||
// Review gate must NOT fire because plan validation blocked the flow.
|
||||
expect(reviewEvents).toHaveLength(0);
|
||||
});
|
||||
|
||||
test("trace_write_failure_fails_closed_before_agents_run", async () => {
|
||||
const project = makeProject();
|
||||
writeFileSync(join(project, ".sf", "traces"), "not a directory");
|
||||
let calls = 0;
|
||||
|
||||
const result = await runTriageApply(project, "triage prompt", {
|
||||
candidateCount: 1,
|
||||
allowUntrustedRunner: true,
|
||||
agentRunner: async () => {
|
||||
calls += 1;
|
||||
return { ok: true, output: deciderPlan, exitCode: 0 };
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.ok).toBe(false);
|
||||
expect(result.error).toContain(
|
||||
"UOK gate emission failed for trusted-agent-source-gate",
|
||||
);
|
||||
expect(calls).toBe(0);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue