Files
confidence-engine/docs/experiment-60b32.md
T

7.6 KiB

Experiment 60B.32 — Runtime Question Formulation Path Diagnosis

Branch: feature/proposition-prefix-over-v0.32
Starting HEAD: clean (after 60B.31)
Date: 2026-08-14
Status: COMPLETE — Classification: D — ACTIVE CONTEXT DRIFT

Objective

Answer exactly:

Where does the full runtime diverge from the deterministic question-formulator path, causing the correct selected node to end with a generic decision-justification question?

Fixed Input (60B.31)

The revenue and launch-cost estimates are good enough for the decision. The remaining issue is one prospective enterprise customer. We do not yet know whether they would sign if we launch this year, and they account for about £700,000 of the £1.2 million expected annual revenue.

Live node added:

  • id: n_enterprise_customer_signing
  • label: Enterprise customer signing decision (or variant with "decision" at end)
  • description: Whether the prospective enterprise customer will commit this year, because resolving this uncertainty is needed to decide if launching this year provides superior net value over waiting twelve months.

60B.32 Findings

Root Cause: extractMeaning proposition detection depends on label keywords

In question-formulator.js line 120-127 of extractMeaning:

if (
  /\b(status|likelihood|probability|chance|risk|uncertainty)\b/i.test(
    String(node?.label || ""),
  ) &&
  /^whether\s+/i.test(strippedDescription)
) {
  return sentenceCase(extractWhetherProposition(strippedDescription));
}

The proposition-extraction path requires the label to contain one of: status, likelihood, probability, chance, risk, uncertainty.

The focused test (line 896-914) uses label "Supplier renewal likelihood" — contains "likelihood" ✓ → meaning starts with "Whether..." → isWhetherPropositionMeaning(meaning) = true.

The live 60B.31 node uses label "Enterprise customer signing decision" — contains none of those keywords ✗ → falls through to line 129-136 which strips "Whether" → meaning does NOT start with "Whether..." → isWhetherPropositionMeaning(meaning) = false.

Root Cause: Parent context bleeds into child formulation via extractActionPhrase

In selectInvestigationStrategy (line 1593):

const actionPhrase = extractActionPhrase([
  ...resolvedValues,
  ...relatedNodes.map((relatedNode) => relatedNode.value),
  ...relatedNodes.map((relatedNode) => relatedNode.label),
  ...relatedNodes.map((relatedNode) => relatedNode.description),
  graph?.centralStatement,
]);

extractActionPhrase iterates over ALL related nodes including the parent n_product_launch_decision. The regex \b(build|launch|adopt|buy|continue|proceed|invest in|fund)\s+([^.,;:]+)/i matches words like "launch" in the parent's label/description, returning an action phrase from the parent node.

This means the child node's question text embeds the parent's decision vocabulary ("launching"), not the child's own proposition.

Root Cause: hasDecisionValueLanguage wins over proposition semantics

At line 1680-1695:

if (
  !selectedStrategy &&
  (hasCriteriaLanguage ||
    (hasDecisionValueLanguage && !isWhetherPropositionMeaning(meaning)))
) {
  selectedStrategy = buildInvestigationStrategy({
    key: "decision_threshold",
    ...
  });
}

Three conditions conspire:

  1. hasDecisionContext is true (parent product-launch node exists)
  2. hasDecisionValueLanguage is true ("value" in description text within decision context)
  3. !isWhetherPropositionMeaning(meaning) is true (extractMeaning stripped "Whether")

All three are true → selects decision_threshold strategy over evidence gathering.

Generic question origin

Function: buildQuestionFromStrategy at line 1759 of question-formulator.js Pattern: "decision_threshold" Family: "decision_threshold" Template: Uses strategy.actionPhrase from parent node's "launch" keyword Trigger: actionPhrase != null (from parent context) → interpolates gerund form

return strategy.actionPhrase
  ? `What outcome would demonstrate enough value to justify ${toGerundPhrase(strategy.actionPhrase)}?`
  : "What outcome would be sufficient to justify this decision?";

Why it wins: The decision_threshold condition (line 1680-1695) fires before evidence_gathering conditions (line 1726-1742). hasDecisionValueLanguage combines with !isWhetherPropositionMeaning(meaning) as a gate — and because extractMeaning didn't produce a "Whether..." meaning for this node, the gate passes.

Critical distinction between test and live

The focused test's graph (via makeGraphFor) contains ONLY the single unknown node. No parent nodes exist. Therefore:

  • collectRelatedNodes returns no ancestors with decision keywords
  • hasDecisionContext checks only the single node + centralStatement → false (centralStatement defaults to "Decision context" which doesn't match \b(whether to|build|launch|continue...))
  • actionPhrase scans nothing relevant → null

The live graph contains: parent product-launch decision node + child customer-signing unknown node. The parent provides both hasDecisionContext and actionPhrase via collectRelatedNodes.

Context comparison

Input Focused deterministic test Live runtime (60B.31)
node label "Supplier renewal likelihood" "Enterprise customer signing decision"
node description "Whether the supplier will renew the contract." "Whether the prospective enterprise customer will commit this year, because resolving this uncertainty is needed to decide if launching this year provides superior net value over waiting twelve months."
label keywords match YES ("likelihood") NO (none of status/likelihood/probability/chance/risk/uncertainty)
extracted meaning starts with "Whether" YES NO
isWhetherPropositionMeaning true false
parent node exists NO YES (n_product_launch_decision)
hasDecisionContext false true
decisionContext flag in selectInvestigationStrategy false true
actionPhrase source null (nothing to scan) parent node's "launch" keyword
hasDecisionValueLanguage false ("value"/"justify" not in text) true (description contains "value", context is decision)
selectedStrategy key evidence_gathering decision_threshold
reasoningPattern diagnosis (default, no decision context) decision (parent triggers it)

Minimum corrective boundary

Choice: D — REMOVE/CHANGE POST-FORMULATION OVERRIDE (more precisely: make proposition semantics override decision-context heuristics)

The fix must ensure that when a node description starts with "Whether..." (bare proposition), the proposition extraction in extractMeaning does NOT depend on label keywords. The description-level "Whether" itself is sufficient evidence of an unresolved proposition.

Specifically, line 120-127 of question-formulator.js should be augmented:

  • Either remove the label keyword requirement when description starts with "Whether..."
  • Or add a separate extraction path that checks bare "Whether..." in description regardless of label

Would this preserve generic decision questions when the decision node itself is selected?

YES — because only nodes whose description starts with "Whether" (not just any node with "decision" in its label) would get the proposition extraction boost. A product launch decision node has a different description format.

Would it preserve 60B.20 direct interrogative behaviour?

LIKELY — because isDirectInterrogativeMeaning is checked at line 92 first, before any "Whether" handling. Direct interrogatives already bypass all the Whether-stripping logic.