fix(confidence-engine): keep focused investigation in current presentation

This commit is contained in:
2026-08-26 11:30:59 +01:00
parent 81dda77392
commit 6288ef1031
2 changed files with 150 additions and 4 deletions
+128
View File
@@ -252,3 +252,131 @@ describe("No duplicate Situation cards — regression guard for removed Path D a
expect(countSituationCards(props)).toBe(0);
});
});
// ── Entry routing fix: Run A must render regardless of selectedQuestion ──
describe("Run A entry routing — selectedQuestion neutrality", () => {
/**
* Simulates the corrected post-Analyse entry condition from reasoning-workspace.jsx:
* const entering = status === "success" && hasGraph && propUnderstanding;
* BEFORE fix it was: `&& !hasSelectedQuestion` which caused Run B when selectedQuestion was populated.
*/
function simulateRunAEntry({ status, hasGraph, propUnderstanding, hasSelectedQuestion }) {
// Corrected entry condition — no longer gates on selectedQuestion
const entering = status === "success" && hasGraph && propUnderstanding;
if (!entering) return { run: "B", initialReflectionActive: false, postAnalyseStatus: null };
return {
run: "A",
initialReflectionActive: true,
postAnalyseStatus: "success",
hasSelectedQuestion, // preserved — not mutated by routing logic
};
}
/**
* Simulates CurrentInvestigationCard rendering: shown only when NOT in post-Analyse reflection.
*/
function currentInvestigationCardRendered(postAnalyseStatus) {
return postAnalyseStatus !== "success";
}
// ── Entry equivalence ──
it("selectedQuestion = null → Run A (initial-reflection-surface)", () => {
const result = simulateRunAEntry({
status: "success",
hasGraph: true,
propUnderstanding: "The company should pursue a phased European expansion.",
hasSelectedQuestion: false, // null
});
expect(result.run).toBe("A");
expect(result.initialReflectionActive).toBe(true);
expect(result.postAnalyseStatus).toBe("success");
expect(currentInvestigationCardRendered(result.postAnalyseStatus)).toBe(false);
});
it("selectedQuestion = populated object → Run A (initial-reflection-surface)", () => {
const result = simulateRunAEntry({
status: "success",
hasGraph: true,
propUnderstanding: "The company should pursue a phased European expansion.",
hasSelectedQuestion: true, // populated — was the old Run B trigger
});
expect(result.run).toBe("A");
expect(result.initialReflectionActive).toBe(true);
expect(result.postAnalyseStatus).toBe("success");
expect(currentInvestigationCardRendered(result.postAnalyseStatus)).toBe(false);
});
it("Green CurrentInvestigationCard NOT shown in either null or populated initial state", () => {
const nullCase = simulateRunAEntry({
status: "success", hasGraph: true, propUnderstanding: "X", hasSelectedQuestion: false,
});
const popCase = simulateRunAEntry({
status: "success", hasGraph: true, propUnderstanding: "X", hasSelectedQuestion: true,
});
expect(currentInvestigationCardRendered(nullCase.postAnalyseStatus)).toBe(false);
expect(currentInvestigationCardRendered(popCase.postAnalyseStatus)).toBe(false);
});
// ── Focused continuation invariant (populated selectedQuestion path) ──
it("Run A + click Open Question → formulation stays in Run A (lifecycle preserved)", () => {
// Start: post-Analyse reflection active, has selectedQuestion (Run B scenario)
let initialReflectionActive = true;
let postAnalyseStatus = "success";
let investigationHistoryLength = 0;
// Simulate lifecycle deactivation effect (the second useEffect in the component)
function checkDeactivate() {
if (!initialReflectionActive) return false; // already deactivated
if (postAnalyseStatus !== "success") return false;
if (investigationHistoryLength > 0) {
initialReflectionActive = false;
postAnalyseStatus = null;
return true; // deactivated
}
return false; // still active
}
// User clicks "Open Question" — starts focused formulation
expect(checkDeactivate()).toBe(false); // still in Run A
expect(initialReflectionActive).toBe(true);
expect(postAnalyseStatus).toBe("success");
// Answer entered → deconstruction processing
expect(checkDeactivate()).toBe(false); // still in Run A
expect(initialReflectionActive).toBe(true);
// Deconstruction completes — result available, history still empty (no turn submitted yet)
expect(checkDeactivate()).toBe(false);
// User submits a turn (leaves post-Analyse) → history grows
investigationHistoryLength = 1;
const deactivated = checkDeactivate();
expect(deactivated).toBe(true);
expect(initialReflectionActive).toBe(false);
expect(postAnalyseStatus).toBe(null);
// After deactivation, workspace grid renders with CurrentInvestigationCard
expect(currentInvestigationCardRendered(postAnalyseStatus)).toBe(true);
});
it("selectedQuestion data is preserved (not mutated) through routing", () => {
const selectedQuestionData = { nodeId: "u1", question: "What is the revenue model?" };
// Even with populated selectedQuestion, routing should enter Run A
const result = simulateRunAEntry({
status: "success", hasGraph: true, propUnderstanding: "X", hasSelectedQuestion: true,
});
expect(result.run).toBe("A");
// The entry function receives the original hasSelectedQuestion value — it does NOT mutate it
expect(result.hasSelectedQuestion).toBe(true);
});
});