fix(confidence-engine): unwrap focused deconstruction response

This commit is contained in:
2026-09-06 14:47:23 +01:00
parent a0f90e8885
commit 188dd04ab9
3 changed files with 116 additions and 36 deletions
+92 -29
View File
@@ -13,18 +13,22 @@ import { describe, it, expect, vi } from "vitest";
function makeMockProvider(inventedTargetNodeId) {
return {
generateReconstruction: vi.fn().mockResolvedValue({
targetNodeId: inventedTargetNodeId,
observations: ["doc is minimal", "processes in founder's head"],
uncertainties: ["whether formal docs can capture tacit knowledge"],
assumptions: ["documentation is primary mechanism for knowledge transfer"],
relationships: [
{ from: "founder", to: "processes", type: "holds", rationale: "tacit" },
{ from: "ops-context", to: "docs-infra", type: "depends_on", rationale: "formal docs required" },
],
possibleFollowUpQuestions: [
"What processes does the founder hold tacitly?",
"How is knowledge transferred when founder is unavailable?",
],
response: {
targetNodeId: inventedTargetNodeId,
observations: ["doc is minimal", "processes in founder's head"],
uncertainties: ["whether formal docs can capture tacit knowledge"],
assumptions: ["documentation is primary mechanism for knowledge transfer"],
relationships: [
{ from: "founder", to: "processes", type: "holds", rationale: "tacit" },
{ from: "ops-context", to: "docs-infra", type: "depends_on", rationale: "formal docs required" },
],
possibleFollowUpQuestions: [
"What processes does the founder hold tacitly?",
"How is knowledge transferred when founder is unavailable?",
],
},
providerApiPath: "/api/chat",
providerExecution: { chatRequestAttempted: true },
}),
};
}
@@ -85,12 +89,16 @@ describe("focused-deconstruct targetNodeId identity boundary", () => {
vi.doMock("@/lib/llm/provider", () => ({
getProvider: () => ({
generateReconstruction: vi.fn().mockResolvedValue({
targetNodeId: "some-invented-id",
observations: mockObs,
uncertainties: mockUnc,
assumptions: mockAssm,
relationships: mockRel,
possibleFollowUpQuestions: mockFuq,
response: {
targetNodeId: "some-invented-id",
observations: mockObs,
uncertainties: mockUnc,
assumptions: mockAssm,
relationships: mockRel,
possibleFollowUpQuestions: mockFuq,
},
providerApiPath: "/api/chat",
providerExecution: { chatRequestAttempted: true },
}),
}),
}));
@@ -158,17 +166,21 @@ describe("focused-deconstruct targetNodeId identity boundary", () => {
vi.doMock("@/lib/llm/provider", () => ({
getProvider: () => ({
generateReconstruction: vi.fn().mockResolvedValue({
targetNodeId: modelInventedId,
observations: ["Documentation is minimal."],
uncertainties: [],
assumptions: [
"That formal documentation is the primary mechanism for capturing or transferring the founder's tacit knowledge of processes.",
],
relationships: [
{ from: "Founder", to: "Processes", type: "holds" },
{ from: "Operational Context", to: "Documentation Infrastructure", type: "affects" },
],
possibleFollowUpQuestions: [],
response: {
targetNodeId: modelInventedId,
observations: ["Documentation is minimal."],
uncertainties: [],
assumptions: [
"That formal documentation is the primary mechanism for capturing or transferring the founder's tacit knowledge of processes.",
],
relationships: [
{ from: "Founder", to: "Processes", type: "holds" },
{ from: "Operational Context", to: "Documentation Infrastructure", type: "affects" },
],
possibleFollowUpQuestions: [],
},
providerApiPath: "/api/chat",
providerExecution: { chatRequestAttempted: true },
}),
}),
}));
@@ -217,4 +229,55 @@ describe("focused-deconstruct targetNodeId identity boundary", () => {
const stored = { ...json };
expect(stored.targetNodeId).toBe(originalNodeId);
});
it("provider envelope fields do not leak into API response", async () => {
vi.resetModules();
vi.doMock("@/lib/llm/provider", () => ({
getProvider: () => ({
generateReconstruction: vi.fn().mockResolvedValue({
response: {
targetNodeId: "nk04xvk",
observations: ["obs"],
uncertainties: ["unc"],
assumptions: ["asm"],
relationships: [],
possibleFollowUpQuestions: ["fuq"],
},
providerApiPath: "/api/chat",
providerExecution: { chatRequestAttempted: true, chatRequestSucceeded: true },
}),
}),
}));
const { POST } = await import("../app/api/focused-investigation/deconstruct/route.js");
const response = await POST(
new Request("http://localhost/api/focused-investigation/deconstruct", {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify({
targetNodeId: "nk04xvk",
targetLabel: "label",
targetDescription: "desc",
centralStatement: "central",
question: "q?",
answer: "a.",
}),
}),
);
expect(response.status).toBe(200);
const json = await response.json();
// Semantic fields present
expect(json.success).toBe(true);
expect(json.targetNodeId).toBe("nk04xvk");
expect(json.observations).toEqual(["obs"]);
expect(json.possibleFollowUpQuestions).toEqual(["fuq"]);
// Provider envelope fields must NOT appear in the response
expect(json.providerApiPath).toBeUndefined();
expect(json.providerExecution).toBeUndefined();
});
});