reasoning: require corroboration for conjunction compoundness

This commit is contained in:
2026-08-10 14:53:57 +01:00
parent dcefb36f4d
commit 60048a5636
2 changed files with 182 additions and 1 deletions
+3 -1
View File
@@ -671,7 +671,9 @@ function countIndependentAnswerDimensions(node, graph) {
conjunctionCount,
implicitConclusion,
multipleEvidenceDimensions:
prerequisiteConceptCount >= 2 || conjunctionCount >= 2,
prerequisiteConceptCount >= 2 ||
(conjunctionCount >= 2 &&
unresolvedDependencies > 0),
};
}
+179
View File
@@ -136,3 +136,182 @@ describe("answerability-triggered decomposition", () => {
expect(selectedChild.status).toBe("unknown");
});
});
describe("conjunction corroboration — Option C", () => {
it(
"Case 1: alternative labels for one concept with surface 'or' tokens stays answerable",
() => {
const unknown = makeNode({
id: "n-case1",
label:
"The actual scenario, problem description, or data set intended for analysis.",
description:
"The actual scenario, problem description, or data set intended for analysis.",
kind: "unknown",
status: "unknown",
confidence: "low",
});
const graph = makeGraph({
centralStatement: "test",
nodes: [unknown],
edges: [],
activeUnknownNodeId: unknown.id,
resolvedNodeIds: [],
currentSummary: "Minimal clarification fixture",
});
const answerability = assessUnknownAnswerability({
node: unknown,
graph,
});
expect(answerability.independentlyAnswerable).toBe(true);
expect(answerability.decompositionRequired).toBe(false);
},
);
it(
"Case 2: surface conjunctions alone cannot make composite without corroborating signal — this is the correct trade-off of Option C",
() => {
const unknown = makeNode({
id: "n-case2",
label:
"What evidence supports the savings estimate and what evidence supports the retention assumption?",
description:
"Determine what data validates both the projected savings and the customer retention figures before making a decision.",
kind: "unknown",
status: "unknown",
confidence: "medium",
});
const graph = makeGraph({
centralStatement:
"Evaluate whether the expansion plan is viable based on financial projections.",
nodes: [unknown],
edges: [],
activeUnknownNodeId: unknown.id,
resolvedNodeIds: [],
currentSummary: "Surface conjunction fixture — no deps",
});
const answerability = assessUnknownAnswerability({
node: unknown,
graph,
});
// Option C trade-off: surface 'and/or' without corroborating signal
// (unresolvedDependencies > 0 or prereqConcept >= 2) stays answerable.
// This is the correct behaviour — conjunctionCount alone must not make composite.
expect(answerability.independentlyAnswerable).toBe(true);
expect(answerability.decompositionRequired).toBe(false);
},
);
it(
"Case 2b: same text WITH unresolved dependencies stays composite via corroboration",
() => {
const prereq = makeNode({
id: "n-case2-dep",
label: "What is the savings estimate?",
description:
"Determine the projected savings figure to use as a reference.",
kind: "unknown",
status: "unknown",
confidence: "medium",
});
const unknown = makeNode({
id: "n-case2-dep-unknown",
label:
"What evidence supports the savings estimate and what evidence supports the retention assumption?",
description:
"Determine what data validates both the projected savings and the customer retention figures before making a decision.",
kind: "unknown",
status: "unknown",
confidence: "medium",
dependsOn: ["n-case2-dep"],
});
const graph = makeGraph({
centralStatement:
"Evaluate whether the expansion plan is viable based on financial projections.",
nodes: [prereq, unknown],
edges: [],
activeUnknownNodeId: unknown.id,
resolvedNodeIds: [],
currentSummary: "Corroborated conjunction fixture",
});
const answerability = assessUnknownAnswerability({
node: unknown,
graph,
});
// With unresolvedDependencies > 0 as corroborating signal,
// conjunctionCount >= 2 now correctly flags composite.
expect(answerability.independentlyAnswerable).toBe(false);
expect(answerability.decompositionRequired).toBe(true);
},
);
it(
"Case 3: commercial-validation container unknowns stay composite",
() => {
const graph = makeCommercialContainerGraph();
const unknown = graph.nodes[0];
const answerability = assessUnknownAnswerability({
node: unknown,
graph,
});
expect(answerability.independentlyAnswerable).toBe(false);
expect(answerability.decompositionRequired).toBe(true);
},
);
it(
"Case 4: explicit unresolved dependencies stay composite even without conjunctions",
() => {
const prereq = makeNode({
id: "n-prereq",
label: "What is the current baseline measurement?",
description:
"Need the baseline to determine the starting point for comparison.",
kind: "unknown",
status: "unknown",
confidence: "medium",
});
const unknown = makeNode({
id: "n-case4",
label: "What is the current state of the primary metric?",
description:
"Determine the current value before comparing against targets.",
kind: "unknown",
status: "unknown",
confidence: "high",
dependsOn: ["n-prereq"],
});
const graph = makeGraph({
centralStatement:
"Evaluate whether the expansion plan is viable based on financial projections.",
nodes: [prereq, unknown],
edges: [],
activeUnknownNodeId: unknown.id,
resolvedNodeIds: [],
currentSummary: "Explicit prerequisite fixture",
});
const answerability = assessUnknownAnswerability({
node: unknown,
graph,
});
expect(answerability.independentlyAnswerable).toBe(false);
expect(answerability.decompositionRequired).toBe(true);
},
);
});