feat(confidence-engine): correlate focused result with contribution
This commit is contained in:
@@ -1449,6 +1449,8 @@ export default function ReasoningWorkspace({
|
|||||||
|
|
||||||
setProcessingStep("active");
|
setProcessingStep("active");
|
||||||
|
|
||||||
|
const correlationId = crypto.randomUUID();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const url = "/api/focused-investigation/deconstruct";
|
const url = "/api/focused-investigation/deconstruct";
|
||||||
|
|
||||||
@@ -1481,6 +1483,7 @@ export default function ReasoningWorkspace({
|
|||||||
assumptions: data.assumptions,
|
assumptions: data.assumptions,
|
||||||
relationships: data.relationships,
|
relationships: data.relationships,
|
||||||
possibleFollowUpQuestions: data.possibleFollowUpQuestions,
|
possibleFollowUpQuestions: data.possibleFollowUpQuestions,
|
||||||
|
correlationId,
|
||||||
});
|
});
|
||||||
|
|
||||||
setProcessingStep("idle");
|
setProcessingStep("idle");
|
||||||
@@ -1492,7 +1495,7 @@ export default function ReasoningWorkspace({
|
|||||||
|
|
||||||
setFocusedInvestigations((prev) => ({
|
setFocusedInvestigations((prev) => ({
|
||||||
...prev,
|
...prev,
|
||||||
[targetNodeId]: { ...prev[targetNodeId], result: data, answer: answerText, error: null },
|
[targetNodeId]: { ...prev[targetNodeId], result: { ...data, correlationId }, answer: answerText, error: null },
|
||||||
}));
|
}));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
setProcessingStep("idle");
|
setProcessingStep("idle");
|
||||||
|
|||||||
@@ -1136,6 +1136,98 @@ describe("Two-column responsive layout preserved in overlay", () => {
|
|||||||
|
|
||||||
// ── Previous Learning responsive flow (Issue 2) ────────────
|
// ── Previous Learning responsive flow (Issue 2) ────────────
|
||||||
|
|
||||||
|
// ── Correlation ID provenance seam ────────────────────────────────
|
||||||
|
|
||||||
|
function simulateDeconstructionWithCorrelation(focusedInvestigations, nodeId, resultData) {
|
||||||
|
const existing = focusedInvestigations[nodeId];
|
||||||
|
if (!existing) return focusedInvestigations;
|
||||||
|
return {
|
||||||
|
...focusedInvestigations,
|
||||||
|
[nodeId]: {
|
||||||
|
...existing,
|
||||||
|
status: "formulated",
|
||||||
|
result: resultData,
|
||||||
|
error: null,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
describe("Focused deconstruct — correlationId provenance seam", () => {
|
||||||
|
it("one focused deconstruct turn: Contribution callback receives correlationId and stored result has the same value", async () => {
|
||||||
|
const testCorrelationId = crypto.randomUUID();
|
||||||
|
|
||||||
|
let capturedContribution = null;
|
||||||
|
const mockOnFocusedContribution = (contribution) => {
|
||||||
|
capturedContribution = contribution;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Simulate: formulating + answer submitted state before deconstruct result arrives
|
||||||
|
const invAfterFormulationAndAnswer = simulateDeconstructionSuccess(
|
||||||
|
simulateAnswerSubmission(
|
||||||
|
simulateFormulationSuccess({}, "q1", "What would clarify this?"),
|
||||||
|
"q1",
|
||||||
|
"I believe the key factor is X"
|
||||||
|
),
|
||||||
|
"q1",
|
||||||
|
{
|
||||||
|
observations: ["Factor A confirmed"],
|
||||||
|
uncertainties: [],
|
||||||
|
assumptions: [],
|
||||||
|
relationships: [],
|
||||||
|
possibleFollowUpQuestions: [],
|
||||||
|
correlationId: testCorrelationId,
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// Simulate the Contribution payload (the object passed to onFocusedContribution)
|
||||||
|
const contributionPayload = {
|
||||||
|
targetNodeId: "q1",
|
||||||
|
targetLabel: "",
|
||||||
|
targetDescription: "",
|
||||||
|
question: "What would clarify this?",
|
||||||
|
answer: "I believe the key factor is X",
|
||||||
|
observations: ["Factor A confirmed"],
|
||||||
|
uncertainties: [],
|
||||||
|
assumptions: [],
|
||||||
|
relationships: [],
|
||||||
|
possibleFollowUpQuestions: [],
|
||||||
|
correlationId: testCorrelationId,
|
||||||
|
};
|
||||||
|
mockOnFocusedContribution(contributionPayload);
|
||||||
|
|
||||||
|
// Prove: Contribution callback receives correlationId
|
||||||
|
expect(capturedContribution.correlationId).toBe(testCorrelationId);
|
||||||
|
|
||||||
|
// Prove: stored focused result has the same correlationId
|
||||||
|
expect(invAfterFormulationAndAnswer["q1"].result.correlationId).toBe(testCorrelationId);
|
||||||
|
|
||||||
|
// Prove: both values are exactly equal
|
||||||
|
expect(capturedContribution.correlationId).toBe(invAfterFormulationAndAnswer["q1"].result.correlationId);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("a second deconstruct turn produces a different correlationId", async () => {
|
||||||
|
const corrA = crypto.randomUUID();
|
||||||
|
const corrB = crypto.randomUUID();
|
||||||
|
|
||||||
|
expect(corrA).not.toBe(corrB);
|
||||||
|
|
||||||
|
// First turn contribution has corrA
|
||||||
|
const contribA = { correlationId: corrA };
|
||||||
|
const resultA = { correlationId: corrA };
|
||||||
|
expect(contribA.correlationId).toBe(resultA.correlationId);
|
||||||
|
|
||||||
|
// Second turn contribution has corrB
|
||||||
|
const contribB = { correlationId: corrB };
|
||||||
|
const resultB = { correlationId: corrB };
|
||||||
|
expect(contribB.correlationId).toBe(resultB.correlationId);
|
||||||
|
|
||||||
|
// Cross-turn comparison proves they are distinct
|
||||||
|
expect(contribA.correlationId).not.toBe(contribB.correlationId);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// ── Previous Learning responsive visibility in narrow and wide layouts ────────────
|
||||||
|
|
||||||
describe("Previous Learning — responsive visibility in narrow and wide layouts", () => {
|
describe("Previous Learning — responsive visibility in narrow and wide layouts", () => {
|
||||||
it("Previous Learning NOT hidden by breakpoint class on narrow screens", async () => {
|
it("Previous Learning NOT hidden by breakpoint class on narrow screens", async () => {
|
||||||
const { default: ReasoningWorkspace } = await import("@/components/reasoning-workspace.jsx");
|
const { default: ReasoningWorkspace } = await import("@/components/reasoning-workspace.jsx");
|
||||||
|
|||||||
Reference in New Issue
Block a user