fix: stabilise multi-turn question progression
This commit is contained in:
@@ -1443,6 +1443,159 @@ describe("applyValidatedProposal", () => {
|
||||
expect(secondResult.compatibilityFailures).toEqual([]);
|
||||
});
|
||||
|
||||
it("reselects a non-repeated comparison sibling instead of asking the same evidence question again", () => {
|
||||
const { graph, proposal } = makeComparabilityUpdateFixture();
|
||||
|
||||
const firstResult = applyValidatedProposal({
|
||||
situationGraph: graph,
|
||||
proposal,
|
||||
previousQuestion:
|
||||
"Were these figures measured on the same basis and at the same scale?",
|
||||
answer:
|
||||
"Yes. Both figures cover the same accounting period and are taken from the same management accounts.",
|
||||
});
|
||||
|
||||
expect(firstResult.success).toBe(true);
|
||||
expect(firstResult.selectedQuestion?.question).toBe(
|
||||
"What evidence would clarify how the two observations were measured?",
|
||||
);
|
||||
|
||||
const secondResult = applyValidatedProposal({
|
||||
situationGraph: firstResult.updatedSituationGraph,
|
||||
proposal: {
|
||||
addedNodes: [],
|
||||
updatedNodes: [
|
||||
{
|
||||
nodeId: firstResult.selectedQuestion.nodeId,
|
||||
previousStatus: "unknown",
|
||||
newStatus: "resolved",
|
||||
previousValue: null,
|
||||
newValue:
|
||||
"Both measures come from the same monthly reporting pack and use the same source system.",
|
||||
reason: "The answer resolves the measurement clarification child.",
|
||||
},
|
||||
],
|
||||
addedEdges: [],
|
||||
removedEdgeIds: [],
|
||||
resolvedUnknownNodeIds: [firstResult.selectedQuestion.nodeId],
|
||||
affectedNodeIds: [],
|
||||
selectedQuestion: null,
|
||||
},
|
||||
previousQuestion: firstResult.selectedQuestion.question,
|
||||
answer:
|
||||
"Both measures come from the same monthly reporting pack and use the same source system.",
|
||||
});
|
||||
|
||||
expect(secondResult.success).toBe(true);
|
||||
expect(secondResult.selectedQuestion?.nodeId).not.toBe(
|
||||
firstResult.selectedQuestion.nodeId,
|
||||
);
|
||||
expect(secondResult.selectedQuestion?.question).not.toBe(
|
||||
firstResult.selectedQuestion.question,
|
||||
);
|
||||
expect(secondResult.finalQuestion).not.toBe(
|
||||
firstResult.selectedQuestion.question,
|
||||
);
|
||||
expect(secondResult.noQuestionReason).toBeNull();
|
||||
expect(secondResult.selectedQuestion?.nodeId).toBe(
|
||||
secondResult.newActiveUnknownNodeId,
|
||||
);
|
||||
});
|
||||
|
||||
it("rejects a compound selected question before returning it", () => {
|
||||
const graph = makeCommercialUpdateFixture();
|
||||
|
||||
const result = applyValidatedProposal({
|
||||
situationGraph: graph,
|
||||
proposal: {
|
||||
...makeMeaningfulNoOpProposal(),
|
||||
selectedQuestion: {
|
||||
nodeId: "n-commercial-parent",
|
||||
question:
|
||||
"What changed during the period that could explain why work is taking longer, and how were the two observations measured?",
|
||||
reason: "Invalid compound follow-up.",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.success).toBe(false);
|
||||
expect(result.stage).toBe("proposal_compatibility");
|
||||
expect(result.errors).toContain(
|
||||
"selectedQuestion must be a single non-compound question",
|
||||
);
|
||||
});
|
||||
|
||||
it("allows a legitimate single-concept or-question", () => {
|
||||
const graph = makeCommercialUpdateFixture();
|
||||
|
||||
const result = applyValidatedProposal({
|
||||
situationGraph: graph,
|
||||
proposal: {
|
||||
...makeMeaningfulNoOpProposal(),
|
||||
selectedQuestion: {
|
||||
nodeId: "n-commercial-parent",
|
||||
question: "Is the problem caused by timing or measurement basis?",
|
||||
reason: "Single concept contrast.",
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
});
|
||||
|
||||
it("returns no question when the graph is truly complete after resolution", () => {
|
||||
const graph = makeGraph({
|
||||
centralStatement: "A single missing fact needs confirmation.",
|
||||
nodes: [
|
||||
makeNode({
|
||||
id: "n-only-unknown",
|
||||
label: "Missing fact",
|
||||
description:
|
||||
"Need the missing fact because the conclusion depends on it.",
|
||||
kind: "unknown",
|
||||
status: "unknown",
|
||||
confidence: "high",
|
||||
}),
|
||||
],
|
||||
edges: [],
|
||||
activeUnknownNodeId: "n-only-unknown",
|
||||
resolvedNodeIds: [],
|
||||
currentSummary: "Single unknown fixture",
|
||||
});
|
||||
|
||||
const result = applyValidatedProposal({
|
||||
situationGraph: graph,
|
||||
proposal: {
|
||||
addedNodes: [],
|
||||
updatedNodes: [
|
||||
{
|
||||
nodeId: "n-only-unknown",
|
||||
previousStatus: "unknown",
|
||||
newStatus: "resolved",
|
||||
previousValue: null,
|
||||
newValue: "Confirmed.",
|
||||
reason: "The answer resolves the only unknown.",
|
||||
},
|
||||
],
|
||||
addedEdges: [],
|
||||
removedEdgeIds: [],
|
||||
resolvedUnknownNodeIds: ["n-only-unknown"],
|
||||
affectedNodeIds: [],
|
||||
selectedQuestion: null,
|
||||
},
|
||||
previousQuestion: "What is the missing fact?",
|
||||
answer: "Confirmed.",
|
||||
});
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.selectedQuestion).toBeNull();
|
||||
expect(result.finalQuestion).toBeNull();
|
||||
expect(result.newActiveUnknownNodeId).toBeNull();
|
||||
expect(result.noQuestionReason).toBe(
|
||||
"No unresolved unknown candidates remain after this update.",
|
||||
);
|
||||
});
|
||||
|
||||
it("does not allow a decision-mode active unknown to remain a comparison child", () => {
|
||||
const graph = makeCommercialUpdateFixture();
|
||||
graph.nodes.push(
|
||||
|
||||
Reference in New Issue
Block a user