feat(confidence-engine): preserve initial reconstruction relationships

This commit is contained in:
2026-09-05 11:53:58 +01:00
parent 13fbceee7a
commit 7472b6ecb0
7 changed files with 485 additions and 23 deletions
+133 -10
View File
@@ -25,9 +25,9 @@ describe("v0.3 prompt", () => {
expect(PROMPT_VERSIONS).toContain("v0.3");
});
it("DEFAULT_PROMPT_VERSION was v0.3 on earlier branches (now v0.4)", () => {
// This test documents that the old default was v0.3; the new default is v0.4
expect(["v0.3", "v0.4"]).toContain(DEFAULT_PROMPT_VERSION);
it("DEFAULT_PROMPT_VERSION was v0.3 on earlier branches (now v0.5)", () => {
// This test documents that the old default was v0.3; the new default is v0.5
expect(["v0.3", "v0.4", "v0.5"]).toContain(DEFAULT_PROMPT_VERSION);
});
it("v0.2 remains available in PROMPT_VERSIONS", () => {
@@ -201,6 +201,45 @@ describe("v0.2 backward compatibility", () => {
});
});
describe("v0.5 prompt", () => {
it("is the production default", async () => {
const result = await buildPrompt("Default prompt scenario");
expect(DEFAULT_PROMPT_VERSION).toBe("v0.5");
expect(PROMPT_VERSIONS).toContain("v0.5");
expect(result.version).toBe("v0.5");
expect(result.prompt).toContain("Default prompt scenario");
});
it("keeps explicit v0.4 unchanged", async () => {
const result = await buildPrompt("Explicit v0.4 scenario", "v0.4");
expect(result.version).toBe("v0.4");
expect(result.prompt).toContain(
"with no dedicated schema field MUST be preserved explicitly in summary",
);
});
it("loads the v0.5 relationship contract", async () => {
const result = await buildPrompt("Explicit v0.5 scenario", "v0.5");
expect(result.version).toBe("v0.5");
expect(result.prompt).toContain("reconstruction.relationships");
expect(result.prompt).toContain("fromId");
expect(result.prompt).toContain("toId");
expect(result.prompt).toContain("MUST reference IDs of semantic units");
});
it("retains the provenance stop boundary and interpretation separation", async () => {
const { prompt } = await buildPrompt("Contract retention scenario", "v0.5");
expect(prompt).toContain("Explicit stop boundary for decomposition");
expect(prompt).toContain("Once the supplied meaning");
expect(prompt).toContain("Interpretation discipline");
expect(prompt).toContain("plausibleInterpretations");
});
});
// ──────────────────────────────────────────────
// Schema validation tests for v0.3-shaped output
// ──────────────────────────────────────────────
@@ -344,6 +383,90 @@ describe("v0.3 schema validation", () => {
const result = reconstructionV2Schema.safeParse(input);
expect(result.success).toBe(true);
expect(result.data.reconstruction.relationships).toEqual([]);
});
it("parses a valid reconstruction relationship", () => {
const input = {
inputClassification: {
primaryType: "decision_request",
classificationReason: "test",
confidence: "medium",
},
reconstruction: {
summary: "Decision depends on an unresolved quality question.",
actors: [],
systemsOrObjects: [],
expectedStates: [],
observedStates: [],
differences: [],
knownTransitions: [],
unexplainedTransitions: [],
contradictions: [],
importantUnknowns: [
{ id: "u1", description: "Whether a quality problem exists", confidence: "high" },
{ id: "u2", description: "Whether inspection is appropriate", confidence: "high" },
],
plausibleInterpretations: [],
relationships: [
{
id: "r1",
fromId: "u2",
toId: "u1",
relationship: "depends_on",
description: "Inspection appropriateness depends on the quality problem.",
confidence: "high",
},
],
},
evidence: [],
nextQuestion: {
id: "q1",
question: "What evidence establishes the quality problem?",
targets: ["u1"],
reason: "need evidence",
expectedInformationValue: "high",
},
};
const result = reconstructionV2Schema.safeParse(input);
expect(result.success).toBe(true);
expect(result.data.reconstruction.relationships).toEqual(input.reconstruction.relationships);
});
it("rejects invalid reconstruction relationship enums and missing endpoints", () => {
const validRelationship = {
id: "r1",
fromId: "u2",
toId: "u1",
relationship: "depends_on",
description: "u2 depends on u1",
confidence: "high",
};
const base = {
inputClassification: { primaryType: "other", classificationReason: "test", confidence: "low" },
reconstruction: {
summary: "test",
actors: [], systemsOrObjects: [], expectedStates: [], observedStates: [], differences: [],
knownTransitions: [], unexplainedTransitions: [], contradictions: [], importantUnknowns: [],
plausibleInterpretations: [], relationships: [validRelationship],
},
evidence: [],
nextQuestion: { id: "q1", question: "What next?", targets: [], reason: "test", expectedInformationValue: "low" },
};
expect(reconstructionV2Schema.safeParse({
...base,
reconstruction: { ...base.reconstruction, relationships: [{ ...validRelationship, relationship: "updates" }] },
}).success).toBe(false);
expect(reconstructionV2Schema.safeParse({
...base,
reconstruction: { ...base.reconstruction, relationships: [{ ...validRelationship, fromId: undefined }] },
}).success).toBe(false);
expect(reconstructionV2Schema.safeParse({
...base,
reconstruction: { ...base.reconstruction, relationships: [{ ...validRelationship, toId: undefined }] },
}).success).toBe(false);
});
it("validates evidence distinguishing direct_observation from inferred_relationship", () => {
@@ -676,8 +799,8 @@ describe("target scenario fixture validation", () => {
describe("diagnostics prompt version", () => {
it("DEFAULT_PROMPT_VERSION is exported correctly", () => {
// The current default is v0.4 (was v0.3)
expect(["v0.3", "v0.4"]).toContain(DEFAULT_PROMPT_VERSION);
// The current default is v0.5 (was v0.3)
expect(["v0.3", "v0.4", "v0.5"]).toContain(DEFAULT_PROMPT_VERSION);
});
it("PROMPT_VERSIONS includes both v0.2 and v0.3", () => {
@@ -801,8 +924,8 @@ describe("Finding disposition toggle — state machine", () => {
// ──────────────────────────────────────────────
describe("v0.4 prompt", () => {
it("DEFAULT_PROMPT_VERSION is v0.4 on this branch", () => {
expect(DEFAULT_PROMPT_VERSION).toBe("v0.4");
it("DEFAULT_PROMPT_VERSION is v0.5 on this branch", () => {
expect(DEFAULT_PROMPT_VERSION).toBe("v0.5");
});
it("v0.4 is in PROMPT_VERSIONS", () => {
@@ -879,12 +1002,12 @@ describe("v0.4 prompt", () => {
expect(result.prompt).toMatch(/exactly.*one.*question|Do NOT combine/i);
});
it("default buildPrompt (no version arg) resolves to v0.4", async () => {
it("default buildPrompt (no version arg) resolves to v0.5", async () => {
const result = await buildPrompt("Default version test");
expect(result.version).toBe(DEFAULT_PROMPT_VERSION);
expect(DEFAULT_PROMPT_VERSION).toBe("v0.4");
expect(DEFAULT_PROMPT_VERSION).toBe("v0.5");
// Should not contain v0.3 schema-specific differences array (it does have it)
// but the prompt should be from the v0.4 file which has the stop boundary text
// but the prompt should be from the v0.5 file which has the stop boundary text
expect(result.prompt.toLowerCase()).toMatch(/stop|explicit.*stop/);
});
});