experiment: define decision sufficiency module boundary
This commit is contained in:
@@ -3295,3 +3295,97 @@ One unresolved question at implementation layer only: precise phrase family brea
|
||||
### VITEST RUN: NO
|
||||
### JEST RUN: NO
|
||||
### WATCHMAN USED: NO
|
||||
|
||||
## Experiment 60B.65 — Decision-sufficiency module boundary audit (read-only structural analysis)
|
||||
|
||||
**Type:** Structural audit of decision-sufficiency implementation scale and extractability
|
||||
**Purpose:** Determine whether the 60B.64 closure implementation added ~210 lines to apply-proposal.js is carrying too many responsibilities, and identify the smallest safe module boundary for future zero-semantic-change extraction.
|
||||
|
||||
### LINE FOOTPRINT (lib/graph/apply-proposal.js — 4730 lines)
|
||||
|
||||
| Unit | Lines | Approx count |
|
||||
|---|---|---|
|
||||
| Confirmation helper (`isUserConfirmationOfNoRemainingUncertainty`) + constants | 61–117 | ~57 |
|
||||
| Remaining-factor helpers (`isUnresolvedUnknown`, `hasRemainingMaterialFactors`, `countRemainingMaterialFactors`) + TERMINAL_STATUSES | 4615–4730 | ~111 |
|
||||
| Closure integration block (inside applyValidatedProposal) | 3835–3984 | ~149 |
|
||||
| **Total decision-sufficiency production lines** | — | **~317** |
|
||||
|
||||
The closure integration block (~149 lines) is the largest single unit. It contains three responsibilities: virtual resolution set construction, decision-sufficiency evaluation (predicate), and graph mutation (status update). The virtual helper `checkRemainingFactorsVirtual` duplicates ~55 lines of traversal logic from `countRemainingMaterialFactors`.
|
||||
|
||||
### RESPONSIBILITY CLASSIFICATION
|
||||
|
||||
| Unit | Classification | Mixed? |
|
||||
|---|---|---|
|
||||
| Confirmation helper | TEXT CONFIRMATION | NO — pure text predicate |
|
||||
| `isUnresolvedUnknown` | GRAPH QUERY | NO |
|
||||
| `hasRemainingMaterialFactors` | GRAPH QUERY | NO |
|
||||
| `countRemainingMaterialFactors` | GRAPH QUERY | NO |
|
||||
| Closure integration block | ORCHESTRATION + MUTATION | YES — 3 responsibilities in one inline block |
|
||||
|
||||
### DATA DEPENDENCIES
|
||||
|
||||
- **Confirmation:** needs only `answer` string. Zero accidental coupling. Pure function.
|
||||
- **Remaining-factor detection:** needs `(decisionNodeId, graph)`. Zero accidental coupling. Pure function.
|
||||
- **Closure application:** reads `updatedSituationGraph`, `proposalSnapshot`, `answer`. All PASSABLE ARGUMENTS — no deep local-variable dependency. The virtual helper's duplication of graph traversal is latent code smell, not accidental coupling.
|
||||
|
||||
### CANDIDATE ASSESSMENT SUMMARY
|
||||
|
||||
| Candidate | Semantic risk | Coupling reduction | Testability | Complexity reduction | Schema change? |
|
||||
|---|---|---|---|---|---|
|
||||
| A (no extract) | N/A | NONE | NONE | NONE | NO |
|
||||
| B (query only) | LOW | MEDIUM | MEDIUM | MEDIUM | NO |
|
||||
| C (query+confirm) | LOW | HIGH | HIGH | MEDIUM | NO |
|
||||
| **D (pure sufficiency unit)** ★ | **LOW** | **HIGH** | **HIGH** | **HIGH** | **NO** |
|
||||
| E (query+mutation) | HIGH | MEDIUM | MEDIUM | LOW-MED | YES/NO |
|
||||
|
||||
### PREDICATE BOUNDARY
|
||||
|
||||
**Pure-function boundary possible: YES**
|
||||
|
||||
```js
|
||||
shouldCloseDecision({ decisionNodeId, graph, answer }) -> boolean
|
||||
```
|
||||
|
||||
Derived from two existing pure functions + one boolean combine. Zero mutation, zero state change. All inputs naturally available at the closure-evaluation point.
|
||||
|
||||
### MINIMUM ORCHESTRATION REMAINING AFTER EXTRACTION
|
||||
|
||||
~40 lines (reduced from ~150):
|
||||
```js
|
||||
iterate parent unknown nodes → call shouldCloseDecision() → apply mutation if true → set closureApplied = true
|
||||
```
|
||||
|
||||
### TEST MIGRATION
|
||||
|
||||
- 60B.61 tests (9 cases, 353 lines): **YES** — all test pure `hasRemainingMaterialFactors`
|
||||
- Confirmation subtests: **PARTIAL** — mixed with integration fixtures
|
||||
- 60B.64 full integration tests: **STAY in apply-proposal.test.js**
|
||||
|
||||
### RUNTIME / TOOLING IMPACT
|
||||
|
||||
| Question | Answer |
|
||||
|---|---|
|
||||
| Runtime performance improvement? | NEGLIGIBLE |
|
||||
| Claude/Codex edit reliability? | LIKELY YES |
|
||||
| Future context reduction? | LIKELY YES |
|
||||
|
||||
### CRITICAL DISTINCTION: D — EXTRACT PURE DECISION-SUFFICIENCY UNIT
|
||||
### MINIMUM REFACTOR BOUNDARY: B — ONE NEW decision-sufficiency.js MODULE
|
||||
### REFACTOR TIMING: B — RUN LIVE REGRESSION FIRST, THEN REFACTOR
|
||||
### IMPLEMENTATION READINESS: A — READY FOR ZERO-SEMANTIC-CHANGE REFACTOR
|
||||
|
||||
The evaluation logic (confirmation detection + remaining-factor counting + closure predicate) is entirely pure and self-contained. One `decision-sufficiency.js` module with 5 exports achieves all seven criteria: zero semantic change, identical 60B.64 behaviour, visible orchestration (~40 lines), mutation ownership in apply-proposal, independently testable pure logic, no schema/prompt changes, less future context.
|
||||
|
||||
**One unresolved question at implementation layer only:** Should `shouldCloseDecision` return just `boolean` or a richer shape `{ hasRemainingFactors, userConfirmedNoRemainingUncertainty, shouldClose }` for diagnostic logging? This does not affect extraction correctness — only post-refactor API surface.
|
||||
|
||||
Smallest zero-semantic-change refactor: extract all decision-sufficiency evaluation logic to one module with 5 exports, replace inline closure evaluation in apply-proposal.js with call to `shouldCloseDecision`, keep mutation code in apply-proposal.js.
|
||||
|
||||
### PRODUCTION CODE CHANGED: NO
|
||||
### TESTS CHANGED: NO
|
||||
### PROMPT CHANGED: NO
|
||||
### SCHEMA CHANGED: NO
|
||||
### OLLAMA CALLS: 0
|
||||
### LIVE API CALLS: 0
|
||||
### VITEST RUN: NO
|
||||
### JEST RUN: NO
|
||||
### WATCHMAN USED: NO
|
||||
|
||||
Reference in New Issue
Block a user