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
@@ -1,6 +1,13 @@
import { formulateQuestionForTarget } from "@/lib/graph/focused-investigation";
import { getProvider, getProviderModelName } from "@/lib/llm/provider";
import {
assessStrategyCompatibility,
formulateQuestionForTarget,
isStrategyQuestionTemplateCompatible,
} from "@/lib/graph/focused-investigation";
import { withAuthenticatedApi } from "@/lib/supabase/api-auth.js";
const STRATEGY_ASSESSMENT_TIMEOUT_MS = 10000;
async function post(request) {
try {
const body = await request.json();
@@ -19,18 +26,59 @@ async function post(request) {
);
}
const result = formulateQuestionForTarget({
const proposed = formulateQuestionForTarget({
situationGraph: body.situationGraph,
targetNodeId: body.targetNodeId,
});
if (!result.success) {
if (!proposed.success) {
return Response.json(
{ success: false, error: result.error },
{ success: false, error: proposed.error },
{ status: 400 },
);
}
let result = proposed;
if (proposed.investigationStrategy) {
const controller = new AbortController();
const timeout = setTimeout(
() => controller.abort(),
STRATEGY_ASSESSMENT_TIMEOUT_MS,
);
let strategyCompatibilityVerdict = {
strategyKey: proposed.investigationStrategy.key,
relevance: "unavailable",
};
try {
const assessment = await assessStrategyCompatibility({
provider: getProvider(),
modelName: getProviderModelName(),
targetLabel: body.situationGraph.nodes.find((node) => node.id === body.targetNodeId)?.label,
targetDescription: body.situationGraph.nodes.find((node) => node.id === body.targetNodeId)?.description,
centralStatement: body.situationGraph.centralStatement,
proposedStrategy: proposed.investigationStrategy,
signal: controller.signal,
});
if (assessment.success) strategyCompatibilityVerdict = assessment.verdict;
} catch {
// A timed-out or unavailable assessment is explicitly non-authorizing.
} finally {
clearTimeout(timeout);
}
result = formulateQuestionForTarget({
situationGraph: body.situationGraph,
targetNodeId: body.targetNodeId,
strategyCompatibilityVerdict,
strategyTemplateCompatibility:
strategyCompatibilityVerdict.relevance === "compatible" &&
!isStrategyQuestionTemplateCompatible(proposed.investigationStrategy)
? "incompatible"
: undefined,
});
}
return Response.json({
success: true,
targetNodeId: result.targetNodeId,