feat(ai-judge): rework enforce mode as user-assumed-risk contract

- add config v2 with fixed judge model selection and fail-closed v1 enforce migration to shadow
- add built-in high-risk override for irreversible, publish, system, and credential shapes that always defers to the human
- remove the promotion gate, promotion records tool, and their tests
- fail closed with judge_model_unavailable when a configured judge model cannot be resolved
- notify once per session in enforce mode with the judge model and risk contract
- add ADR 0008 and update README and CONTEXT
This commit is contained in:
2026-08-21 23:11:40 +08:00
parent f4ba739878
commit 061c60c344
17 changed files with 1372 additions and 1137 deletions
@@ -3,18 +3,10 @@ import {
evaluateEnforceAuthority,
type EnforceGateState,
} from "../src/judge";
import {
loadPromotionRecords,
resolvePromotionGates,
type CandidateIdentity,
} from "../src/promotion";
const ALL_OPEN: EnforceGateState = {
auditHealthy: true,
telemetryHealth: "healthy",
cohortQualified: true,
ownerApprovalRecorded: true,
activationRecorded: true,
resultKind: "judgment",
verdict: "allow",
reviewAcknowledged: true,
@@ -23,7 +15,10 @@ const ALL_OPEN: EnforceGateState = {
};
describe("evaluateEnforceAuthority — every gate independently forces defer", () => {
it("allows only when every gate holds", () => {
it("allows when every gate holds — no promotion records required", () => {
// ADR 0008: the promotion gates (cohort qualification, owner
// approval, activation) are no longer authority inputs; a session
// with zero promotion records can hold Enforce authority.
expect(evaluateEnforceAuthority(ALL_OPEN)).toEqual({ kind: "allow" });
});
@@ -37,9 +32,6 @@ describe("evaluateEnforceAuthority — every gate independently forces defer", (
{ name: "telemetry disabled", patch: { telemetryHealth: "disabled" }, expectedReason: "telemetry_disabled" },
{ name: "telemetry write failed", patch: { telemetryHealth: "write_failed" }, expectedReason: "telemetry_write_failed" },
{ name: "telemetry integrity anomaly", patch: { telemetryHealth: "integrity_anomaly" }, expectedReason: "telemetry_integrity_anomaly" },
{ name: "cohort not qualified", patch: { cohortQualified: false }, expectedReason: "cohort_not_qualified" },
{ name: "owner approval absent", patch: { ownerApprovalRecorded: false }, expectedReason: "owner_approval_absent" },
{ name: "activation absent", patch: { activationRecorded: false }, expectedReason: "activation_absent" },
{ name: "preflight result", patch: { resultKind: "preflight_defer" }, expectedReason: "result_preflight_defer" },
{ name: "infrastructure result", patch: { resultKind: "infrastructure_failure" }, expectedReason: "result_infrastructure_failure" },
{ name: "semantic deny verdict", patch: { verdict: "deny" }, expectedReason: "verdict_deny" },
@@ -58,86 +50,3 @@ describe("evaluateEnforceAuthority — every gate independently forces defer", (
});
}
});
describe("evaluateEnforceAuthority — production state with no promotion records", () => {
// The real post-PIEXTENSIO-21 seam: an empty records file (the normal
// pre-promotion state) closes all promotion gates, so every mode and
// telemetry state defers — mechanically identical to v0.1's hardcoded
// closure, now derived from actual storage.
const emptySnapshot = loadPromotionRecords({
agentDir: "/nonexistent-agent-dir",
});
const identity: CandidateIdentity = {
judge: "@sikongjueluo/pi-permission-ai-judge@0.0.1",
permissionSystem: "25.4.0",
provider: "openai-codex",
model: "gpt-5.6-sol",
api: "openai-codex-responses",
promptVersion: "bash-shadow-v4",
toolSchemaVersion: "report-verdict-v1",
reviewSchemaVersion: "1",
timeoutCohort: 30000,
};
it("never grants authority for any mode or telemetry state without records", () => {
const modes = ["shadow", "enforce"] as const;
const healths = ["healthy", "disabled", "write_failed", "integrity_anomaly"] as const;
for (const mode of modes) {
for (const health of healths) {
const gates = resolvePromotionGates(emptySnapshot, identity);
const outcome = evaluateEnforceAuthority({
...ALL_OPEN,
mode,
telemetryHealth: health,
...gates,
});
expect(outcome.kind).toBe("defer");
}
}
});
it("blocks enforce on the cohort gate first even with healthy audit", () => {
const gates = resolvePromotionGates(emptySnapshot, identity);
const outcome = evaluateEnforceAuthority({
...ALL_OPEN,
...gates,
});
expect(outcome).toEqual({
kind: "defer",
blockedBy: "cohort_not_qualified",
});
});
it("grants authority only when every record kind exists for the exact identity", () => {
const records = [
{
kind: "cohort_qualified",
candidateIdentity: identity,
recordedAt: "2026-08-20T12:00:00Z",
basis: "cohort test",
},
{
kind: "owner_approval",
candidateIdentity: identity,
recordedAt: "2026-08-20T12:01:00Z",
basis: "approved",
},
{
kind: "activation",
candidateIdentity: identity,
recordedAt: "2026-08-20T12:02:00Z",
basis: "activated",
},
] as const;
const snapshot = {
records,
healthy: true,
diagnostic: null,
path: "unused",
};
const gates = resolvePromotionGates(snapshot, identity);
expect(evaluateEnforceAuthority({ ...ALL_OPEN, ...gates })).toEqual({
kind: "allow",
});
});
});