fix(confidence-engine): await focused deconstruction provider

This commit is contained in:
2026-10-06 18:18:10 +01:00
parent 814360e368
commit d6dbc17bdf
3 changed files with 47 additions and 45 deletions
+42 -42
View File
@@ -29,104 +29,104 @@ function makeInvalidResponse() {
}
describe("focusedDeconstruct — success", () => {
it("calls provider.generateReconstruction exactly once and returns success", () => {
it("calls provider.generateReconstruction exactly once and returns success", async () => {
let callCount = 0;
const fake = { generateReconstruction() { callCount++; return { response: makeValidResponse() }; } };
const result = focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
const fake = { async generateReconstruction() { callCount++; return { response: makeValidResponse() }; } };
const result = await focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
expect(callCount).toBe(1);
expect(result.success).toBe(true);
});
it("preserves observations from provider response", () => {
const fake = { generateReconstruction() { return { response: makeValidResponse() }; } };
const result = focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
it("preserves observations from provider response", async () => {
const fake = { async generateReconstruction() { return { response: makeValidResponse() }; } };
const result = await focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
expect(Array.isArray(result.observations)).toBe(true);
expect(result.observations.length).toBeGreaterThan(0);
});
it("preserves uncertainties from provider response", () => {
const fake = { generateReconstruction() { return { response: makeValidResponse() }; } };
const result = focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
it("preserves uncertainties from provider response", async () => {
const fake = { async generateReconstruction() { return { response: makeValidResponse() }; } };
const result = await focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
expect(Array.isArray(result.uncertainties)).toBe(true);
expect(result.uncertainties.length).toBeGreaterThan(0);
});
it("preserves assumptions from provider response", () => {
const fake = { generateReconstruction() { return { response: makeValidResponse() }; } };
const result = focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
it("preserves assumptions from provider response", async () => {
const fake = { async generateReconstruction() { return { response: makeValidResponse() }; } };
const result = await focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
expect(Array.isArray(result.assumptions)).toBe(true);
expect(result.assumptions.length).toBeGreaterThan(0);
});
it("preserves relationships from provider response", () => {
const fake = { generateReconstruction() { return { response: makeValidResponse() }; } };
const result = focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
it("preserves relationships from provider response", async () => {
const fake = { async generateReconstruction() { return { response: makeValidResponse() }; } };
const result = await focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
expect(Array.isArray(result.relationships)).toBe(true);
expect(result.relationships.length).toBeGreaterThan(0);
});
it("preserves possibleFollowUpQuestions from provider response", () => {
const fake = { generateReconstruction() { return { response: makeValidResponse() }; } };
const result = focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
it("preserves possibleFollowUpQuestions from provider response", async () => {
const fake = { async generateReconstruction() { return { response: makeValidResponse() }; } };
const result = await focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
expect(Array.isArray(result.possibleFollowUpQuestions)).toBe(true);
expect(result.possibleFollowUpQuestions.length).toBeGreaterThan(0);
});
it("preserves caller target identity (result.targetNodeId === request targetNodeId)", () => {
const fake = { generateReconstruction() { return { response: makeValidResponse() }; } };
const result = focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
it("preserves caller target identity (result.targetNodeId === request targetNodeId)", async () => {
const fake = { async generateReconstruction() { return { response: makeValidResponse() }; } };
const result = await focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
expect(result.targetNodeId).toBe(FAKE_TARGET_NODE_ID);
});
it("passes correct prompt to provider", () => {
it("passes correct prompt to provider", async () => {
let capturedPrompt = null;
const fake = { generateReconstruction(prompt) { capturedPrompt = prompt; return { response: makeValidResponse() }; } };
focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
const fake = { async generateReconstruction(prompt) { capturedPrompt = prompt; return { response: makeValidResponse() }; } };
await focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
const expected = buildFocusedDeconstructPrompt({ targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
expect(capturedPrompt).toBe(expected);
});
it("passes modelName unchanged to provider", () => {
it("passes modelName unchanged to provider", async () => {
let capturedModel = null;
const fake = { generateReconstruction(prompt, receivedModel) { capturedModel = receivedModel; return { response: makeValidResponse() }; } };
focusedDeconstruct({ provider: fake, modelName: "my-custom-model-v2", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
const fake = { async generateReconstruction(prompt, receivedModel) { capturedModel = receivedModel; return { response: makeValidResponse() }; } };
await focusedDeconstruct({ provider: fake, modelName: "my-custom-model-v2", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
expect(capturedModel).toBe("my-custom-model-v2");
});
it("passes focusedDeconstructJsonSchema as the schema argument", () => {
it("passes focusedDeconstructJsonSchema as the schema argument", async () => {
let capturedSchema = null;
const fake = { generateReconstruction(prompt, modelName, schema) { capturedSchema = schema; return { response: makeValidResponse() }; } };
focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
const fake = { async generateReconstruction(prompt, modelName, schema) { capturedSchema = schema; return { response: makeValidResponse() }; } };
await focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
expect(capturedSchema).toBe(focusedDeconstructJsonSchema);
});
})
describe("focusedDeconstruct — validation failure", () => {
it("returns failure result when provider response fails canonical validation", () => {
const fake = { generateReconstruction() { return { response: makeInvalidResponse() }; } };
const result = focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
it("returns failure result when provider response fails canonical validation", async () => {
const fake = { async generateReconstruction() { return { response: makeInvalidResponse() }; } };
const result = await focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
expect(result.success).toBe(false);
});
it("validation errors remain available on failure result", () => {
const fake = { generateReconstruction() { return { response: makeInvalidResponse() }; } };
const result = focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
it("validation errors remain available on failure result", async () => {
const fake = { async generateReconstruction() { return { response: makeInvalidResponse() }; } };
const result = await focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
expect(Array.isArray(result.errors)).toBe(true);
expect(result.errors.length).toBeGreaterThan(0);
});
it("no second provider call occurs on validation failure", () => {
it("no second provider call occurs on validation failure", async () => {
let callCount = 0;
const fake = { generateReconstruction() { callCount++; return { response: makeInvalidResponse() }; } };
focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
const fake = { async generateReconstruction() { callCount++; return { response: makeInvalidResponse() }; } };
await focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER });
expect(callCount).toBe(1);
});
})
describe("focusedDeconstruct — provider failure", () => {
it("propagates error with original identity/metadata intact", () => {
it("propagates error with original identity/metadata intact", async () => {
const fake = {
generateReconstruction() {
async generateReconstruction() {
const err = new Error("Connection refused to ollama endpoint");
err.name = "ProviderError";
err.providerApiPath = "/api/v1/completions";
@@ -134,6 +134,6 @@ describe("focusedDeconstruct — provider failure", () => {
throw err;
},
};
expect(() => focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER })).toThrow("Connection refused to ollama endpoint");
await expect(focusedDeconstruct({ provider: fake, modelName: "test-model", targetNodeId: FAKE_TARGET_NODE_ID, targetLabel: FAKE_LABEL, targetDescription: FAKE_DESCRIPTION, centralStatement: FAKE_CENTRAL, question: FAKE_QUESTION, answer: FAKE_ANSWER })).rejects.toThrow("Connection refused to ollama endpoint");
});
})
@@ -331,7 +331,7 @@ async function composeDeepInvestigationCheckpoint({ situationGraph, previousQues
const centralStatement = situationGraph.centralStatement ?? "";
// Call production-focused deconstruct — exactly one provider generation
const focused = focusedDeconstruct({
const focused = await focusedDeconstruct({
provider,
modelName: model,
targetNodeId,
@@ -342,6 +342,8 @@ async function composeDeepInvestigationCheckpoint({ situationGraph, previousQues
answer,
});
providerGenerateCalls++; // focusedDeconstruct now uses the same provider (1 call)
if (!focused.success) {
throw new Error(`focusedDeconstruct failed for episode ${contribSeq}: ${JSON.stringify(focused.errors)}`);
}