Files
confidence-engine/docs/archive/experiments/decision-closure-integration/experiment-60b75.md
T

2.8 KiB

Experiment 60B.75 — Fix Decision Node Detection for Sufficiency Question

Date: 2026-08-14 Branch: feature/sufficiency-decision-detection-v0.46 Preceded by: Experiment 60B.74 (BLOCKED — State B detection bug)

Objective

Fix the deterministic bug in State B detection so that real kind="unknown" decision nodes can reach the sufficiency confirmation question path, without changing target selection, closure semantics, schema, or prompt behaviour.

Root Cause (confirmed by 60B.74)

The condition node.kind !== "unknown" at line 2010 of question-formulator.js excludes ALL nodes from State B, including parent decisions, because all decisions have kind === "unknown".

The reasoningPattern check at the same conditional's first clause (reasoningPatternSelection.pattern === "decision") already uses hasDecisionContext() — a text-pattern predicate that identifies decision context via ancestry chain and keywords like "whether to", "launch", "build", etc. The kind gate was redundant but harmful.

Fix Applied

Removed node.kind !== "unknown" from the State B conditional at line 2010 of question-formulator.js. The reasoningPattern check already provides canonical decision identification via hasDecisionContext().

Files Changed

  • lib/graph/question-formulator.js — removed broken kind gate (line 2010)
  • tests/graph/question-formulator.test.js — updated 60B.73 tests to use production-shaped kind: "unknown" for decisions; added new 60B.75 describe block with 6 focused tests

Production/tests Commit

fix(reasoning): recognise decision in sufficiency question

Documentation Commit

docs: record sufficiency decision detection fix

Why It Works

hasDecisionContext(node, graph, relatedNodes) at line 972 of question-formulator.js examines the parent chain and context text for decision keywords. When selectReasoningPattern() returns pattern: "decision", it has already confirmed this node sits in a build/continue/invest/commercial-justification decision context via that predicate.

Removing node.kind !== "unknown" exposes the State B branch to all nodes where reasoningPattern === "decision", including kind="unknown" decisions — which is exactly what was intended.

Test Gap (identified and closed)

The existing 60B.73 tests used kind: "state" for decision nodes, which passed the broken gate ("state" !== "unknown" = true). Production decisions use kind: "unknown". Tests were corrected to match production shape, so they now fail against the old condition and pass after this fix.

Focused Verification

npx vitest run tests/graph/question-formulator.test.js tests/graph/apply-proposal.test.js -t "60B.75|60B.73|60B.64|decision_threshold"

Result: 22 tests pass (0 failures). No Jest, no Watchman, no Ollama calls, no live API calls.