fix(reasoning): preserve investigation ownership across selection and question rejection
This commit is contained in:
+13
-12
@@ -2871,6 +2871,9 @@ function reseatSelectionAfterQuestionRejection({
|
||||
: { status: "none", nodeId: null };
|
||||
}
|
||||
|
||||
const QUESTION_FORMULATION_REJECTION_NO_QUESTION_REASON =
|
||||
"The selected investigation target remains active, but its current graph-backed question formulation was rejected as too complex.";
|
||||
|
||||
export function determineGraphBackedQuestion({ situationGraph }) {
|
||||
const graphSnapshot = cloneJsonSafe(situationGraph);
|
||||
let updatedSituationGraph = cloneJsonSafe(situationGraph);
|
||||
@@ -2937,15 +2940,12 @@ export function determineGraphBackedQuestion({ situationGraph }) {
|
||||
initialQuestionRejected &&
|
||||
deterministicSelection?.status === "selected"
|
||||
) {
|
||||
deterministicSelection = reseatSelectionAfterQuestionRejection({
|
||||
graph: updatedSituationGraph,
|
||||
deterministicSelection,
|
||||
excludedNodeIds: [deterministicSelection.nodeId],
|
||||
});
|
||||
questionResult = buildSelectedQuestionResult({
|
||||
updatedSituationGraph,
|
||||
deterministicSelection,
|
||||
});
|
||||
questionResult = {
|
||||
...questionResult,
|
||||
selectedQuestion: null,
|
||||
questionSuppressedReason:
|
||||
QUESTION_FORMULATION_REJECTION_NO_QUESTION_REASON,
|
||||
};
|
||||
}
|
||||
|
||||
if (
|
||||
@@ -2971,14 +2971,15 @@ export function determineGraphBackedQuestion({ situationGraph }) {
|
||||
? questionResult.selectedQuestion?.questionSuppressedReason ||
|
||||
questionResult.selectedQuestion?.reason ||
|
||||
"Eligible unresolved candidates remain tied after initial graph-backed selection."
|
||||
: (updatedSituationGraph.nodes || []).some(
|
||||
: questionResult.questionSuppressedReason ||
|
||||
((updatedSituationGraph.nodes || []).some(
|
||||
(node) =>
|
||||
node.kind === "unknown" &&
|
||||
!["resolved", "contradicted"].includes(node.status) &&
|
||||
!(updatedSituationGraph.resolvedNodeIds || []).includes(node.id),
|
||||
)
|
||||
? "Compatible unresolved candidates remain, but none produced a valid graph-backed question."
|
||||
: "No unresolved unknown candidates remain after initial graph construction.";
|
||||
? "Compatible unresolved candidates remain, but none produced a valid graph-backed question."
|
||||
: "No unresolved unknown candidates remain after initial graph construction.");
|
||||
|
||||
return {
|
||||
success: true,
|
||||
|
||||
+15
-5
@@ -249,7 +249,7 @@ function semanticSignature(candidate) {
|
||||
);
|
||||
}
|
||||
|
||||
function classifyCandidateOrdering(candidates) {
|
||||
function classifyCandidateOrdering(candidates, activeNodeId = null) {
|
||||
const displayOrder = buildCandidateDisplayOrder(candidates);
|
||||
const best = displayOrder[0] ?? null;
|
||||
if (!best) {
|
||||
@@ -319,15 +319,21 @@ function classifyCandidateOrdering(candidates) {
|
||||
}
|
||||
|
||||
if (topStructuralCandidates.length > 0) {
|
||||
const activeTiedCandidate = activeNodeId
|
||||
? topStructuralCandidates.find((candidate) => candidate.nodeId === activeNodeId)
|
||||
: null;
|
||||
|
||||
return {
|
||||
displayOrder,
|
||||
best,
|
||||
best: activeTiedCandidate || best,
|
||||
leadingCandidates: topStructuralCandidates,
|
||||
status: "selected",
|
||||
tieType: "complete_unresolved_tie",
|
||||
usedAlphabeticalOrdering: true,
|
||||
usedAlphabeticalOrdering: activeTiedCandidate ? false : true,
|
||||
reason:
|
||||
"Leading candidates remained tied after score, structural, and semantic checks, so the stable deterministic display order was used as the final fallback.",
|
||||
activeTiedCandidate
|
||||
? "Leading candidates remained tied after score, structural, and semantic checks, so existing active investigation ownership was preserved."
|
||||
: "Leading candidates remained tied after score, structural, and semantic checks, so the stable deterministic display order was used as the final fallback.",
|
||||
};
|
||||
}
|
||||
|
||||
@@ -624,6 +630,7 @@ export function selectActiveUnknownCandidate(graph, resolvedNodeIds) {
|
||||
...candidate,
|
||||
node,
|
||||
})),
|
||||
graph?.activeUnknownNodeId ?? null,
|
||||
);
|
||||
|
||||
if (selection.status === "ambiguous") {
|
||||
@@ -690,7 +697,10 @@ export function explainUnknownSelection(graph, resolvedNodeIds = []) {
|
||||
...scoreUnknownCandidate(graph, node, resolvedNodeIds),
|
||||
}));
|
||||
|
||||
const selection = classifyCandidateOrdering(candidates);
|
||||
const selection = classifyCandidateOrdering(
|
||||
candidates,
|
||||
graph?.activeUnknownNodeId ?? null,
|
||||
);
|
||||
const orderedCandidates = selection.displayOrder;
|
||||
const selected = selection.best;
|
||||
const competitors = orderedCandidates
|
||||
|
||||
Reference in New Issue
Block a user