test(uok): assert triage-apply-mutation-gate fires after agree-path

Codex audit (Q4) flagged that the mutation gate landed in slice 3a but
the test suite only verified the three earlier gates. Add coverage:

- agree-path: mutation-gate fires with outcome=fail, rejectedCount=1,
  resolvedCount=0 (the test fixture has no real ledger entry for the
  decision id, so markResolved rejects it — the gate correctly surfaces
  the partial failure)
- disagree-path: mutation-gate does NOT fire (apply phase skipped)

Pins the 4-gate contract end-to-end. Suite: 4/4 in this file.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
Mikael Hugo 2026-05-14 18:16:04 +02:00
parent cf52aceb64
commit 7003da3f6a
3 changed files with 16 additions and 0 deletions

View file

@ -136,6 +136,17 @@ describe("runTriageApply emits gate_run trace events with schema-v2 metadata", (
expect(reviewEvents).toHaveLength(1);
expect(reviewEvents[0].outcome).toBe("pass");
expect(reviewEvents[0].surface).toBe("headless");
// Mutation gate fires after the agree-path apply phase (codex audit
// 2026-05-14 follow-up). Since the test project has no real ledger
// entry for sf-test-1, markResolved rejects it and the gate lands
// "fail" with rejectedCount=1, not "pass".
const mutationEvents = gates.get("triage-apply-mutation-gate") ?? [];
expect(mutationEvents).toHaveLength(1);
expect(mutationEvents[0].outcome).toBe("fail");
expect(mutationEvents[0].surface).toBe("headless");
expect(mutationEvents[0].rejectedCount).toBe(1);
expect(mutationEvents[0].resolvedCount).toBe(0);
});
test("disagree_path_emits_review_gate_as_fail", async () => {
@ -159,6 +170,11 @@ describe("runTriageApply emits gate_run trace events with schema-v2 metadata", (
expect(reviewEvents).toHaveLength(1);
expect(reviewEvents[0].outcome).toBe("fail");
expect(reviewEvents[0].surface).toBe("headless");
// Mutation gate must NOT fire on disagree path — no mutations means
// no apply phase ran.
const mutationEvents = gates.get("triage-apply-mutation-gate") ?? [];
expect(mutationEvents).toHaveLength(0);
});
test("unknown_id_in_plan_emits_validation_gate_fail_and_no_review_gate", async () => {