fix(focused-investigation): suppress incompatible question strategies

This commit is contained in:
2026-10-08 17:48:53 +01:00
parent 92ae463d10
commit f74fe6de10
6 changed files with 672 additions and 16 deletions
+48 -9
View File
@@ -1198,6 +1198,37 @@ function constrainStrategyToReasoningPattern(strategy, reasoningPattern) {
return allowedStrategies.includes(strategy.key) ? strategy : null;
}
function applyStrategyCompatibilityVerdict(proposedStrategy, verdict) {
// No verdict is the backward-compatible path. A supplied verdict can only
// preserve this exact proposal or suppress it; it cannot select a substitute.
if (verdict === undefined) return proposedStrategy;
if (!proposedStrategy || !verdict || typeof verdict !== "object" || Array.isArray(verdict)) {
return null;
}
const keys = Object.keys(verdict);
if (
keys.length !== 2 ||
!keys.includes("strategyKey") ||
!keys.includes("relevance") ||
typeof verdict.strategyKey !== "string" ||
(verdict.relevance !== "compatible" && verdict.relevance !== "incompatible") ||
verdict.strategyKey !== proposedStrategy.key
) {
return null;
}
return verdict.relevance === "compatible" ? proposedStrategy : null;
}
export function isStrategyQuestionTemplateCompatible(strategy) {
if (!strategy) return true;
return !(
strategy.key === "baseline_reconstruction" &&
isWhetherPropositionMeaning(strategy.meaning)
);
}
function selectQuestionFamily({
node,
graph,
@@ -2047,7 +2078,7 @@ export function formulateQuestion({ node, graph, context = {} }) {
}
}
const investigationStrategy = selectInvestigationStrategy({
const proposedInvestigationStrategy = selectInvestigationStrategy({
node,
graph,
context: {
@@ -2055,12 +2086,20 @@ export function formulateQuestion({ node, graph, context = {} }) {
reasoningPattern: reasoningPatternSelection.pattern,
},
});
const investigationStrategy = applyStrategyCompatibilityVerdict(
proposedInvestigationStrategy,
context.strategyCompatibilityVerdict,
);
const templateCompatibleStrategy =
context.strategyTemplateCompatibility === "incompatible"
? null
: investigationStrategy;
const questionFamilySelection = selectQuestionFamily({
node,
graph,
reasoningPattern: reasoningPatternSelection.pattern,
investigationStrategy,
investigationStrategy: templateCompatibleStrategy,
});
let question = buildQuestionFromFamily({
@@ -2069,7 +2108,7 @@ export function formulateQuestion({ node, graph, context = {} }) {
reasoningPattern: reasoningPatternSelection.pattern,
questionFamily: questionFamilySelection.family,
selectedQuestionTemplate: questionFamilySelection.template,
investigationStrategy,
investigationStrategy: templateCompatibleStrategy,
});
question = sanitizeQuestionText(question);
@@ -2080,11 +2119,11 @@ export function formulateQuestion({ node, graph, context = {} }) {
if (
!validateFormulatedQuestion(
question,
investigationStrategy?.meaning || fallbackMeaning,
templateCompatibleStrategy?.meaning || fallbackMeaning,
)
) {
question = sanitizeQuestionText(
(investigationStrategy &&
(templateCompatibleStrategy &&
isClaimLikeUnknown(
node,
normaliseText(
@@ -2112,11 +2151,11 @@ export function formulateQuestion({ node, graph, context = {} }) {
return {
question,
reason: investigationStrategy
? `Formulated from graph context using the ${investigationStrategy.key} investigation strategy.`
reason: templateCompatibleStrategy
? `Formulated from graph context using the ${templateCompatibleStrategy.key} investigation strategy.`
: "Formulated as a neutral clarification question because no narrower investigation strategy clearly applied.",
strategy: investigationStrategy?.key ?? null,
investigationStrategy,
strategy: templateCompatibleStrategy?.key ?? null,
investigationStrategy: templateCompatibleStrategy,
reasoningPattern: reasoningPatternSelection.pattern,
reasoningPatternReason: reasoningPatternSelection.reason,
questionFamily: questionFamilySelection.family,