experiment(confidence-engine): expose reconstruction provider seam

This commit is contained in:
2026-09-06 08:01:29 +01:00
parent 860ee6fc5b
commit 1daf2bb6ce
7 changed files with 115 additions and 13 deletions
+18
View File
@@ -356,6 +356,24 @@ describe("lib/graph/orchestrator startCase", () => {
);
});
it("forwards an injected reconstruction provider to analyseScenario", async () => {
mockAnalyseScenario.mockResolvedValue(makeAnalysisResult());
const reconstructionProvider = { generateReconstruction: vi.fn() };
const { startCase } = await import("@/lib/graph/orchestrator.js");
const result = await startCase(
{ scenario: "Scenario text" },
{ reconstructionProvider, reconstructionModelName: "experiment-model" },
);
expect(result.success).toBe(true);
expect(mockAnalyseScenario).toHaveBeenCalledWith("Scenario text", {
promptVersion: undefined,
reconstructionProvider,
reconstructionModelName: "experiment-model",
});
});
it("rejects invalid request input without throwing", async () => {
const { startCase } = await import("@/lib/graph/orchestrator.js");
@@ -112,6 +112,35 @@ describe("normaliseAnalysisResponse", () => {
});
describe("analyseScenario compatibility", () => {
it("uses an injected reconstruction provider with the production prompt path", async () => {
const injectedProvider = {
generateReconstruction: vi.fn().mockResolvedValue({
inputClassification: { primaryType: "other", classificationReason: "test", confidence: "low" },
reconstruction: {
summary: "summary", actors: [], systemsOrObjects: [], expectedStates: [], observedStates: [],
differences: [], knownTransitions: [], unexplainedTransitions: [], contradictions: [],
importantUnknowns: [], plausibleInterpretations: [],
},
evidence: [],
nextQuestion: { id: "q1", question: "What next?", targets: [], reason: "test", expectedInformationValue: "low" },
}),
};
const { analyseScenario } = await import("@/lib/analysis.js");
const result = await analyseScenario("Scenario text", {
promptVersion: "v0.3",
reconstructionProvider: injectedProvider,
reconstructionModelName: "experiment-model",
});
expect(result.success).toBe(true);
expect(injectedProvider.generateReconstruction).toHaveBeenCalledWith(
"prompt",
"experiment-model",
);
expect(mockGenerateReconstruction).not.toHaveBeenCalled();
});
it("preserves an attempted provider API path on provider failure", async () => {
const providerError = new Error("Provider failed");
providerError.providerApiPath = "/api/chat";
@@ -14,10 +14,12 @@ import { execFile } from "child_process";
import { writeFile, unlink } from "fs/promises";
import { join, dirname } from "path";
import { fileURLToPath } from "url";
import { createRequire } from "module";
const __dirname = dirname(fileURLToPath(import.meta.url));
const rootDir = join(__dirname, "..", "..");
const helperPath = join(rootDir, "scripts", "start-case-experiment-helper.cjs");
const require = createRequire(import.meta.url);
function runHelper(args = [], envOverrides = {}) {
return new Promise((resolve, reject) => {
@@ -128,6 +130,34 @@ describe("start-case-experiment-helper.cjs apparatus", () => {
// ── D — Success output ──────────────────────────────────────────
describe("D — success output", () => {
it("forwards an explicit reconstruction provider through the startCase path", async () => {
const { runStartCaseExperiment } = require(helperPath);
const reconstructionProvider = { generateReconstruction() {} };
const startCase = async (input, dependencies) => {
expect(input).toEqual({ scenario: "Provider seam scenario" });
expect(dependencies).toMatchObject({
reconstructionProvider,
reconstructionModelName: "gpt-5.6-terra",
});
return {
success: true,
situationGraph: { nodes: [], edges: [] },
assessment: null,
selectedQuestion: null,
summary: "test",
};
};
const result = await runStartCaseExperiment(
{ scenario: "Provider seam scenario" },
null,
{ reconstructionProvider, reconstructionModelName: "gpt-5.6-terra", startCase },
);
expect(result.success).toBe(true);
expect(result.summary).toBe("test");
});
it("exit code is 0", async () => {
const result = await runHelper(["Success test scenario"]);
expect(result.exitCode).toBe(0);