reasoning: suppress explanation question without relationship structure
This commit is contained in:
@@ -436,7 +436,9 @@ function classifyObservationRelationshipWhenComparable(graph) {
|
|||||||
reason:
|
reason:
|
||||||
"There is not enough structure to classify the relationship safely.",
|
"There is not enough structure to classify the relationship safely.",
|
||||||
contradictionReasoningAllowed: false,
|
contradictionReasoningAllowed: false,
|
||||||
questionRequired: true,
|
questionRequired: false,
|
||||||
|
questionSuppressedReason:
|
||||||
|
"No meaningful relationship structure was established; uncertainty is preserved without fabricating an explanation problem.",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -128,6 +128,69 @@ describe("comparability assessment", () => {
|
|||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("returns questionRequired=false for fallback (no meaningful relationship structure)", () => {
|
||||||
|
// Two non-measurement-like observations with no shared concept and no known direction.
|
||||||
|
// They pass comparability (confirmed) but fall through all classification conditions:
|
||||||
|
// - not duplicate, no available+unavailable, no revenue/cash pair, no all-known-directions
|
||||||
|
// → hits the fallback which now returns questionRequired=false
|
||||||
|
const graph = {
|
||||||
|
centralStatement:
|
||||||
|
"Temperature was measured. Ice was observed.",
|
||||||
|
nodes: [
|
||||||
|
{
|
||||||
|
id: "obs-temperature",
|
||||||
|
label: "Temperature was measured.",
|
||||||
|
description: "Temperature was measured.",
|
||||||
|
kind: "observation",
|
||||||
|
status: "supported",
|
||||||
|
confidence: "high",
|
||||||
|
value: null,
|
||||||
|
unit: null,
|
||||||
|
evidenceIds: [],
|
||||||
|
dependsOn: [],
|
||||||
|
affects: [],
|
||||||
|
parentId: null,
|
||||||
|
childIds: [],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: "obs-ice",
|
||||||
|
label: "Ice was observed.",
|
||||||
|
description: "Ice was observed.",
|
||||||
|
kind: "observation",
|
||||||
|
status: "supported",
|
||||||
|
confidence: "high",
|
||||||
|
value: null,
|
||||||
|
unit: null,
|
||||||
|
evidenceIds: [],
|
||||||
|
dependsOn: [],
|
||||||
|
affects: [],
|
||||||
|
parentId: null,
|
||||||
|
childIds: [],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
edges: [],
|
||||||
|
activeUnknownNodeId: null,
|
||||||
|
resolvedNodeIds: [],
|
||||||
|
currentSummary: "Fallback regression fixture",
|
||||||
|
};
|
||||||
|
|
||||||
|
const relationship = classifyObservationRelationship(graph);
|
||||||
|
|
||||||
|
expect(relationship.relationshipStatus).toBe("insufficient_information");
|
||||||
|
expect(relationship.questionRequired).toBe(false);
|
||||||
|
// Verify reasoning stages exist and have correct status
|
||||||
|
const stages = relationship.reasoningStages;
|
||||||
|
expect(stages.length).toBe(2);
|
||||||
|
expect(stages[0].stage).toBe("comparability");
|
||||||
|
expect(stages[0].status).toBe("confirmed");
|
||||||
|
expect(stages[1].stage).toBe("relationship");
|
||||||
|
expect(stages[1].status).toBe("insufficient_information");
|
||||||
|
|
||||||
|
// questionRequired=false means buildEmergentReasoningUnknown returns early,
|
||||||
|
// so no "Explanation for why..." unknown is created — the engine preserves
|
||||||
|
// uncertainty rather than fabricating an explanation problem.
|
||||||
|
});
|
||||||
|
|
||||||
it("allows contradiction reasoning only for genuine contradictions", () => {
|
it("allows contradiction reasoning only for genuine contradictions", () => {
|
||||||
const serviceGraph = {
|
const serviceGraph = {
|
||||||
centralStatement:
|
centralStatement:
|
||||||
|
|||||||
@@ -279,4 +279,122 @@ describe("reasoning-pattern validation", () => {
|
|||||||
expect(result.selectedQuestion?.nodeId).not.toBe("n-incompatible-child");
|
expect(result.selectedQuestion?.nodeId).not.toBe("n-incompatible-child");
|
||||||
expect(result.selectedQuestion?.reasoningPattern).toBe("decision");
|
expect(result.selectedQuestion?.reasoningPattern).toBe("decision");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("preserves potentially_related with questionRequired=true for meaningful shared structure", () => {
|
||||||
|
// Two observations sharing "revenue" concept, both with known direction ("up").
|
||||||
|
// With confirmed comparability (via stored state), condition 2 triggers:
|
||||||
|
// sharedConcepts.size > 0 && all directions known → potentially_related
|
||||||
|
const graph = makeGraph({
|
||||||
|
centralStatement: "Revenue increased. Revenue doubled.",
|
||||||
|
nodes: [
|
||||||
|
makeNode({
|
||||||
|
id: "n-revenue-1",
|
||||||
|
label: "Revenue increased.",
|
||||||
|
description: "Revenue increased.",
|
||||||
|
kind: "observation",
|
||||||
|
status: "supported",
|
||||||
|
confidence: "high",
|
||||||
|
}),
|
||||||
|
makeNode({
|
||||||
|
id: "n-revenue-2",
|
||||||
|
label: "Revenue doubled.",
|
||||||
|
description: "Revenue doubled.",
|
||||||
|
kind: "observation",
|
||||||
|
status: "supported",
|
||||||
|
confidence: "high",
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
edges: [],
|
||||||
|
activeUnknownNodeId: null,
|
||||||
|
resolvedNodeIds: [],
|
||||||
|
currentSummary: "Potentially related regression fixture",
|
||||||
|
reasoningState: {
|
||||||
|
comparabilityStatus: "confirmed",
|
||||||
|
comparabilityReason: "Stored from earlier assessment.",
|
||||||
|
comparabilityEvidence: [],
|
||||||
|
relationshipStatus: "potentially_related",
|
||||||
|
relationshipReason: "Observations concern the same subject but do not assert a direct contradiction.",
|
||||||
|
relationshipAssessed: true,
|
||||||
|
contradictionReasoningAllowed: false,
|
||||||
|
reasoningStages: [
|
||||||
|
{ stage: "comparability", status: "confirmed", outcome: "Stored." },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const relationship = classifyObservationRelationship(graph);
|
||||||
|
|
||||||
|
expect(relationship.relationshipStatus).toBe("potentially_related");
|
||||||
|
expect(relationship.questionRequired).toBe(true);
|
||||||
|
|
||||||
|
const result = applyValidatedProposal({
|
||||||
|
situationGraph: graph,
|
||||||
|
proposal: {
|
||||||
|
addedNodes: [],
|
||||||
|
updatedNodes: [
|
||||||
|
{
|
||||||
|
nodeId: "n-revenue-2",
|
||||||
|
previousStatus: "supported",
|
||||||
|
newStatus: "resolved",
|
||||||
|
previousValue: null,
|
||||||
|
newValue: "Revenue doubled confirmed by accounts.",
|
||||||
|
reason: "Regression test update.",
|
||||||
|
},
|
||||||
|
],
|
||||||
|
addedEdges: [],
|
||||||
|
removedEdgeIds: [],
|
||||||
|
resolvedUnknownNodeIds: [],
|
||||||
|
affectedNodeIds: [],
|
||||||
|
selectedQuestion: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(result.success).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("preserves contradiction with questionRequired=true for genuinely opposing observations", () => {
|
||||||
|
const graph = makeGraph({
|
||||||
|
centralStatement:
|
||||||
|
"The service was reported as available throughout the hour and unavailable throughout the same hour.",
|
||||||
|
nodes: [
|
||||||
|
makeNode({
|
||||||
|
id: "n-available",
|
||||||
|
label: "The service was available throughout the hour.",
|
||||||
|
description: "The service was available throughout the hour.",
|
||||||
|
kind: "observation",
|
||||||
|
status: "supported",
|
||||||
|
confidence: "high",
|
||||||
|
}),
|
||||||
|
makeNode({
|
||||||
|
id: "n-unavailable",
|
||||||
|
label: "The service was unavailable throughout the same hour.",
|
||||||
|
description: "The service was unavailable throughout the same hour.",
|
||||||
|
kind: "observation",
|
||||||
|
status: "supported",
|
||||||
|
confidence: "high",
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
edges: [],
|
||||||
|
activeUnknownNodeId: null,
|
||||||
|
resolvedNodeIds: [],
|
||||||
|
currentSummary: "Contradiction regression fixture",
|
||||||
|
reasoningState: {
|
||||||
|
comparabilityStatus: "confirmed",
|
||||||
|
comparabilityReason: "Stored from earlier assessment.",
|
||||||
|
comparabilityEvidence: [],
|
||||||
|
relationshipStatus: "contradictory",
|
||||||
|
relationshipReason: "The observations assert mutually incompatible states about the same subject.",
|
||||||
|
relationshipAssessed: true,
|
||||||
|
contradictionReasoningAllowed: true,
|
||||||
|
reasoningStages: [
|
||||||
|
{ stage: "comparability", status: "confirmed", outcome: "Stored." },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const relationship = classifyObservationRelationship(graph);
|
||||||
|
|
||||||
|
expect(relationship.relationshipStatus).toBe("contradictory");
|
||||||
|
expect(relationship.questionRequired).toBe(true);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user