From 100dfa2be50477326719de2b66b10ab051c6bc15 Mon Sep 17 00:00:00 2001 From: robbond Date: Fri, 14 Aug 2026 13:31:30 +0100 Subject: [PATCH] docs: record decision factor detection --- docs/current-handoff.md | 31 ++++++++++++++++ docs/experiment-60b61.md | 80 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 docs/experiment-60b61.md diff --git a/docs/current-handoff.md b/docs/current-handoff.md index 101c1c1..3ba4e7e 100644 --- a/docs/current-handoff.md +++ b/docs/current-handoff.md @@ -3064,3 +3064,34 @@ Schema changed: NO Ollama calls: 0 Live API calls: 0 Vitest run: NO + +--- + +### 60B.61 — Decision Remaining-Material-Factor Detection + +**Status:** PASSED +**Type:** Helper detection experiment (bounded) + +**Question answered:** Does the dedicated remaining-material-factor helper work correctly once malformed tests are repaired, without any broader applyValidatedProposal integration? **Answer: YES.** + +**Production additions:** +- `hasRemainingMaterialFactors(decisionNodeId, graph)` — boolean public helper +- `countRemainingMaterialFactors(decisionNodeId, graph)` — count variant (internal/helper support) +- `TERMINAL_STATUSES` and `isUnresolvedUnknown(node)` — internal helpers + +**Routes supported:** A (hierarchy), B (direct dependency), C (consequence via may_cause/affects/causes), D (containment via option) +**Excluded:** known/resolved/contradicted statuses, supports/measures weak links, arbitrary connectivity, decision self-count + +**Test cases:** 14 in 60B.61 block — all passed +**Regression preservation:** 60B.43 PASSED, 60B.11 PASSED, pricing prerequisite-first PASSED + +**Out-of-scope removed:** +- `remainingMaterialFactorCount` integration hook from applyValidatedProposal return (integration rejected per scope) +- Extra "countRemainingMaterialFactor counting" test block (out of bounded scope) +- `makeProductLaunchClosureFixture()` dependency in 60B.61 tests (replaced with local graphs) + +**Committed:** +- Production/tests: `feat(reasoning): detect remaining decision factors` +- Docs: `docs: record decision factor detection` + +**Next step:** Decision-sufficiency closure integration remains a separate next experiment. diff --git a/docs/experiment-60b61.md b/docs/experiment-60b61.md new file mode 100644 index 0000000..bdee8fd --- /dev/null +++ b/docs/experiment-60b61.md @@ -0,0 +1,80 @@ +# Experiment 60B.61 — Decision Remaining-Material-Factor Detection + +## Status: PASSED + +### Objective +Answer: *Does the dedicated remaining-material-factor helper work correctly once malformed tests are repaired, without any broader applyValidatedProposal integration?* + +**Answer: YES.** + +### Scope (bounded) +Helper detection experiment only. No closure integration. + +### Production code added (2 helpers + internal support) + +| Export | Role | +|--------|------| +| `hasRemainingMaterialFactors(decisionNodeId, graph)` | Public boolean — `true` if any unresolved unknown remains material to the decision | +| `countRemainingMaterialFactors(decisionNodeId, graph)` | Count variant — used internally by `hasRemainingMaterialFactors`; kept as exported for potential future use | + +- **Set-based deduplication** of factor IDs across routes (no double-count) +- **Decision self-count excluded** (`node.id === decisionNodeId`) +- **Terminal statuses excluded**: `known`, `resolved`, `contradicted` +- **Helper-only**. No integration into `applyValidatedProposal` return, no closure logic change. + +### Supported Routes + +| Route | Relationship Path | +|-------|-------------------| +| A — hierarchy | `parentId` chain or `childIds` membership | +| B — direct dependency | `depends_on` edge to decision | +| C — consequence | unknown → `{affects,may_cause,causes}` → option → `contained_in` → decision | +| D — containment | unknown → `contained_in` → option → `contained_in` → decision | + +### Excluded (returns false) + +- Known / resolved / contraduted statuses +- `supports` / `measures` weak links +- Arbitrary non-approved connectivity (`other`) +- The decision node itself +- Non-unknown kind nodes (e.g., observations) + +### Test Suite (14 cases in 60B.61 block) + +1. Containment-only unresolved factor → **true** +2. Same factor resolved → **false** +3. `may_cause` option-linked factor → **true** +4. Valid direct `depends_on` factor → **true**; resolved → **false** +5. Hierarchy child factor → **true** +6. Supports / measures weak link → **false** +7. Decision node alone does not self-count → **false** +8. Another genuine unresolved hierarchy child remains → **true** +9. Status = known excluded → **false** +10. Status = contradicted excluded → **false** +11. Non-unknown kinds excluded → **false** +12. 60B.56 sufficiency (all factors resolved) → **false** +13. Arbitrary connectivity via `other` edge → **false** +14. Additional resolution state within Route B test → **false** + +### Regression Preservation + +- **60B.43**: PASSED +- **60B.11**: PASSED +- **Pricing prerequisite-first**: PASSED + +### Git Commits + +``` +feat(reasoning): detect remaining decision factors +docs: record decision factor detection +``` + +WHAT IS NOW GUARANTEED +--- + +The helper `hasRemainingMaterialFactors(decisionNodeId, graph)` correctly identifies unresolved material factors for a decision node across all four approved routes (A–D), with Set-based deduplication and proper terminal-status exclusion. No production behaviour outside the helper itself was changed. + +WHAT REMAINS OPEN +--- + +Decision-sufficiency closure integration remains a separate next experiment. The helper detects but does not influence any decision-closure logic at this time.