rea/tests/conformance/providers/conformanceTrustGate.test.ts

185 lines
5.7 KiB
TypeScript

import { describe, expect, it } from "vitest";
import type { VerifierContract } from "../../../src/domain/conformancePackage.js";
import {
compareDimension,
evaluateTrustGate,
isSemanticDimension,
isVolatileDimension,
} from "../../../src/domain/conformanceTrustGate.js";
const contract: VerifierContract = {
scenario_id: "s1",
dimensions: [
{ name: "exit_code", required: true, comparison: "exact" },
{ name: "stdout", required: true, comparison: "semantic" },
{ name: "timing", required: true, comparison: "fuzzy" },
],
timing_tolerance_ms: 100,
};
describe("conformance trust gates", () => {
it("classifies volatile dimensions correctly", () => {
expect(isVolatileDimension("timing")).toBe(true);
expect(isVolatileDimension("timestamp")).toBe(true);
expect(isVolatileDimension("pid")).toBe(true);
expect(isVolatileDimension("exit_code")).toBe(false);
});
it("classifies semantic dimensions correctly", () => {
expect(isSemanticDimension("exit_code")).toBe(true);
expect(isSemanticDimension("stdout")).toBe(true);
expect(isSemanticDimension("timing")).toBe(false);
});
it("matches identical values", () => {
const result = compareDimension("exit_code", 0, 0);
expect(result.status).toBe("match");
});
it("detects mismatches", () => {
const result = compareDimension("exit_code", 0, 1);
expect(result.status).toBe("mismatch");
});
it("ignores volatile dimensions", () => {
const result = compareDimension("timing", 100, 200);
expect(result.status).toBe("match");
expect(result.message).toContain("volatile");
});
it("handles truncated evidence", () => {
const result = compareDimension("exit_code", 0, null, {
truncated: true,
});
expect(result.status).toBe("truncated");
});
it("handles undefined values", () => {
const result = compareDimension("exit_code", undefined, undefined);
expect(result.status).toBe("unknown");
});
it("handles missing actual", () => {
const result = compareDimension("exit_code", 0, undefined);
expect(result.status).toBe("unknown");
});
it("keeps semantic unknown and truncated values out of equivalence", () => {
expect(
compareDimension(
"process_tree",
{ processes: [] },
{ status: "unknown" },
),
).toMatchObject({ status: "unknown" });
expect(
compareDimension("process_tree", { processes: [] }, { truncated: true }),
).toMatchObject({ status: "truncated" });
expect(
compareDimension(
"process_tree",
{ status: "unknown" },
{ status: "unknown" },
),
).toMatchObject({ status: "unknown" });
});
it("projects Evidence envelopes and links a divergence to the observed ID", () => {
const expectedEvidenceId = `ev_${"1".repeat(64)}`;
const actualEvidenceId = `ev_${"2".repeat(64)}`;
const result = evaluateTrustGate(
contract,
{
evidence_id: expectedEvidenceId,
normalized_result: { exit_code: 0, stdout: "hello" },
},
{
evidence_id: actualEvidenceId,
normalized_result: { exit_code: 1, stdout: "hello" },
},
);
expect(result.verdict).toBe("fail");
expect(result.dimension_results[0]?.evidence_ids).toEqual([
actualEvidenceId,
expectedEvidenceId,
]);
expect(result.first_divergence).toMatchObject({
dimension: "exit_code",
evidence_id: actualEvidenceId,
});
});
it("scopes process residual unknowns without hiding complete dimensions", () => {
const processContract: VerifierContract = {
...contract,
dimensions: [
{ name: "exit_code", required: true, comparison: "exact" },
{ name: "process_tree", required: true, comparison: "semantic" },
],
};
const result = evaluateTrustGate(
processContract,
{ exit_code: 0, process_tree: { processes: [] } },
{
exit_code: 0,
process_tree: { processes: [] },
residual_unknowns: [{ scope: "process", reason: "event gap" }],
},
);
expect(result.verdict).toBe("unknown");
expect(result.dimension_results).toEqual(
expect.arrayContaining([
expect.objectContaining({ name: "exit_code", status: "match" }),
expect.objectContaining({ name: "process_tree", status: "unknown" }),
]),
);
});
it("passes when all dimensions match", () => {
const result = evaluateTrustGate(
contract,
{ exit_code: 0, stdout: "hello" },
{ exit_code: 0, stdout: "hello" },
);
expect(result.verdict).toBe("pass");
});
it("fails when a required dimension mismatches", () => {
const result = evaluateTrustGate(
contract,
{ exit_code: 0, stdout: "hello" },
{ exit_code: 1, stdout: "hello" },
);
expect(result.verdict).toBe("fail");
expect(result.first_divergence).not.toBeNull();
expect(result.first_divergence!.dimension).toBe("exit_code");
});
it("reports unknown when both dimensions are undefined", () => {
const result = evaluateTrustGate(contract, {}, {});
// exit_code and stdout are both undefined -> unknown
// timing is volatile -> match
expect(result.verdict).toBe("unknown");
});
it("ignores volatile dimension differences", () => {
const result = evaluateTrustGate(
contract,
{ exit_code: 0, stdout: "hello", timing: 100 },
{ exit_code: 0, stdout: "hello", timing: 200 },
);
expect(result.verdict).toBe("pass");
});
it("truncated evidence is not treated as equivalence", () => {
const result = evaluateTrustGate(
contract,
{ exit_code: 0, stdout: "hello" },
{ exit_code: 0, stdout: "hello" },
{ truncated: true },
);
expect(result.verdict).toBe("fail");
});
});