4.3 KiB
v0.6 Atomicity Experiment
Hypothesis
After deterministic unknown selection, the engine should assess whether the selected unknown is already atomic or is still too composite to ask directly.
If the unknown is atomic, the engine should proceed exactly as before.
If the unknown is composite, the engine should not ask that parent unknown directly. Instead, it should decompose it into a small set of explicit child unknowns representing broad, independent candidate dimensions that a non-expert could understand.
Constraints
- No graph redesign
- No persistence
- No UI redesign
- No selection-weight tuning
- No Ollama calls in unit tests
Deterministic rule introduced
Atomicity assessment is not a new investigation strategy.
It runs in the graph update path at this seam:
unknown selection -> atomicity assessment -> optional decomposition -> deterministic reselection -> question formulation
The implementation uses deterministic text and graph-shape checks:
- focused unknowns like denominator / threshold / definition / baseline / evidence remain atomic
- broad relationship-explanation unknowns and broad “possible causes / what changed / explanation for why X but Y” unknowns become composite
Decomposition behavior
When a selected unknown is composite:
- The parent unknown remains unresolved.
- Between 2 and 5 child unknowns are created or reused deterministically.
- Children become explicit graph nodes.
- Children link back to the parent with existing
depends_onedges. - Children inherit the same “why it matters” discipline in their descriptions.
- Deterministic selection reruns across the updated graph.
For the current relationship-explanation experiment, the broad child dimensions are:
- Whether the two observations reflect different timing
- How the two observations were measured
- Change affecting signal A more than signal B
- Change affecting signal B more than signal A
- One-off event during the period
These are intentionally non-jargon and broad enough to generalise across scenarios like:
- Revenue up / Cash down
- Customer satisfaction up / Complaints up
- Delivery time down / Cancellations up
- Traffic up / Sales flat
- Production up / Defects up
Diagnostics added
The orchestrator now reports:
atomicityAssessmentatomicityDecisionReasondecompositionDepthdecompositionAttempteddecompositionAccepteddecompositionStoppedReasonproposedChildCountacceptedChildCountrejectedChildrenselectedChildNodeIdchildQualitySummarydecompositionPerformedchildUnknownCountchildNodeIdsatomicityReason
This sits alongside the existing explicit-emergent-unknown diagnostics.
Observed outcome
The experiment was useful.
Before this change, the engine could select a broad explanation unknown and ask it directly.
After this change:
- the broad explanation parent remains explicit in the graph
- the engine decomposes it into child unknowns first
- the next asked question is backed by a more focused child unknown
- repeated updates reuse the same decomposition children deterministically
- child-quality checks reject compound or duplicate children before they enter the graph
- decomposition stops deterministically once a selected child is directly answerable
In the revenue-versus-cash case, the selected next question becomes:
What evidence would clarify how the two observations were measured?
rather than asking the full broad explanation node directly.
Interpretation
This supports the idea that recursive decomposition is a fundamental part of graph-backed questioning, not just a prompt refinement.
The main remaining limitation is that some decompositions can still produce equally justified child candidates. The current implementation handles that deterministically by exposing the ambiguity in diagnostics and, when possible, reusing the existing selector to pick a specific atomic child. That is still preferable to hiding the ambiguity inside one broad parent question.
Validation run
Covered by:
tests/graph/atomicity-assessment.test.jstests/graph/decomposition-quality.test.jstests/graph/apply-proposal.test.jstests/graph/orchestrator.test.jstests/graph/question-formulator.test.jstests/ui/scenario-form.test.jsx
And then by the broader requested validation pass with lint and build.