Compare commits

...
Author SHA1 Message Date
robbond 00ba343ed9 docs(confidence-engine): close v0.49 current understanding boundary 2026-08-30 17:23:44 +01:00
robbond 8c98ce94de docs(confidence-engine): close workspace controls boundary 2026-08-30 12:13:29 +01:00
robbond bdb234262c fix(confidence-engine): close workspace after done for now 2026-08-30 12:06:33 +01:00
robbond 07e1363368 docs(confidence-engine): document v0.49 workspace controls recovery 2026-08-30 11:46:54 +01:00
robbond 16cab4645a fix(confidence-engine): workspace control cleanup — rename close button, remove 'Back to open questions' from navigation 2026-08-30 11:35:15 +01:00
robbond 922f58a49f fix(confidence-engine): project processing indicator to active follow-up block
Repair LOCATION-A defect where processing feedback rendered near the
completed narrative instead of inside the active follow-up block.

Changes:
  - components/reasoning-workspace.jsx: three targeted edits using a single
    spinner component with conditional rendering; hasActiveFollowUp routes
    ownership to the correct container
  - tests/open-questions-vs-assumptions.test.jsx: regression test confirming
    exactly one indicator, DOM child of follow-up-block, ownership separation

Accepted criteria met:
   Exactly one processing indicator during follow-up processing
   Indicator is a DOM child of follow-up-block
   Top-level indicator suppressed when follow-up active
   Initial answer flow preserved (top-level when no follow-up)
   Successful follow-up promotion intact
   All existing context retained
   No new state/lifecycle changes/error redesign
2026-08-30 11:09:24 +01:00
robbond bf7629691f fix(confidence-engine): preserve follow-up context while processing 2026-08-30 10:43:57 +01:00
robbond ae1201bb27 fix(confidence-engine): simplify active follow-up presentation 2026-08-30 08:51:18 +01:00
robbond 8bded90094 fix(confidence-engine): preserve follow-up progression ownership 2026-08-30 08:28:29 +01:00
robbond 17c6048047 fix(confidence-engine): preserve completed-narrative when selecting follow-up + reverse prior-contribs display
Two presentation fixes (no reasoning-engine changes):

A. Follow-up answer continuity — selectFollowUpQuestion clears focused.answer,
   which previously caused the completed-narrative framing ('Previously answered'
   and 'Your response') to disappear mid-investigation. The guard now treats
   a non-null result as sufficient evidence of a completed-context state, so the
   user's verbatim answer and derived findings remain visible while a follow-up is
   being formulated.

B. Prior-contributions chronology — display order in 'Previous learning' panels
   has been reversed at the presentation boundary (newest → oldest). This means
   users see the most recently learned evidence first, without modifying data-order
   anywhere else. Applies to both PriorContributionsSummary and
   SecondaryPreviousLearning.
2026-08-29 19:04:06 +01:00
robbond 890a18c5a7 feat(confidence-engine): present completed results as coherent provenance narrative
When a reopened completed turn is displayed, distinguish it from an active question:

- 'PREVIOUSLY ANSWERED' + 'YOUR RESPONSE' headings for completed turns (hasAnswer=true)
- Bare 'QUESTION' heading preserved for active follow-ups (answer=null)
- Verbatim user answer rendered under its own heading — never conflated with Engine-derived findings
- Causal narrative: Question → Your response → What this tells us

Gate results:
- 102 tests passed (78 existing + 24 new v0.49 provenance narrative tests)
- Clean production build
- Live verification on localhost:3000 confirmed correct rendering
2026-08-29 18:45:55 +01:00
robbond 50a66749ae docs(confidence-engine): preserve evidence provenance 2026-08-29 18:24:32 +01:00
robbond 88d9768276 fix(confidence-engine): distinguish completed focused result 2026-08-29 18:09:26 +01:00
robbond dac19a3552 fix(confidence-engine): show focused investigation activity 2026-08-29 16:46:51 +01:00
robbond b9c0b6f6f7 fix(confidence-engine): show focused investigation activity 2026-08-29 15:15:28 +01:00
robbond 0f4dfcbb17 fix(confidence-engine): show canonical findings in previous learning 2026-08-29 14:38:04 +01:00
robbond a8539e2494 fix(confidence-engine): restore finding controls on reopen 2026-08-28 13:25:24 +01:00
robbond 06f3f501d2 docs(confidence-engine): record restored workspace findings 2026-08-28 12:03:13 +01:00
robbond 10cbcbdd05 fix(confidence-engine): preserve investigation activity across turns
ThreadContributionsBadge, PriorContributionsSummary, and
SecondaryPreviousLearning all filtered contributions via
c.targetNodeId === nodeId. Multi-turn follow-up Contributions carry a
different immediate targetNodeId while the canonical origin remains on
Findings (originatingTargetNodeId).

Repaired: all contribution filters now match on EITHER
c.targetNodeId === nodeId || c.originatingTargetNodeId === nodeId.
handleDeconstructSubmit carries originatingTargetNodeId from
focusedPresentationItemId as provenance for cold-return recovery.
2026-08-28 11:56:31 +01:00
robbond b9a54589f0 docs(confidence-engine): record Phase 6 UNCLEAR + INVESTIGATING cue results
- Document live Playwright verification of amber INVESTIGATING indicator
  on Open Questions cards with matching contribution targetNodeId
- Document 11 new deterministic tests in focused-investigation-history describe block
- Confirm UNCLEAR and INVESTIGATING coexist independently (epistemic vs activity)
- Note that cue only renders inside OpenQuestionsPanel, not initial reflection surface
2026-08-28 11:26:57 +01:00
robbond 556acfb156 feat(confidence-engine): render INVESTIGATING cue on Open Question cards with focused history
- ThreadContributionsBadge (rendered per-node on OpenQuestionsPanel
  cards and Done-for-now cards) now shows an amber INVESTIGATING
  indicator when the node has matching contributions via targetNodeId
  identity match.
- UNCLEAR and INVESTIGATING cues coexist independently on the same
  card — UNCLEAR is epistemic state, INVESTIGATING is activity cue.
- Deterministic test suite added: focused-investigation-history (11
  tests) covering identity matching, zero-contrib edge cases,
  multiple-contrib coalescing, done-for-now retention, and uncoupling
  from UNCLEAR state.
- All 57 tests pass.
2026-08-28 11:25:40 +01:00
robbond f1bd91faf8 feat(confidence-engine): promote focused learning on done 2026-08-28 10:48:45 +01:00
robbond e221bd3bf8 feat(confidence-engine): isolate finding-informed understanding 2026-08-28 08:16:37 +01:00
robbond c45b703b3a docs(confidence-engine): record v0.48 storage closure and next boundary handoff
Record: v0.48 persistence objective complete; Finding eligibility resolved;
next boundary is isolated Finding-informed Current Understanding (feature/
finding-informed-understanding-v0.49); broader Finding-system questions
intentionally deferred. No production or test changes.
2026-08-28 07:59:50 +01:00
robbond b215846478 docs(confidence-engine): reconcile v0.48 persistence evidence 2026-08-28 07:06:10 +01:00
robbond 3e9123fe0e chore: scope experiment artifact ignores 2026-08-27 19:08:03 +01:00
robbond 3c5257cbd7 docs(confidence-engine): update v0.48 storage handoff 2026-08-27 19:05:30 +01:00
robbond d55f179d37 refactor(confidence-engine): remove legacy workspace persistence 2026-08-27 16:52:55 +01:00
robbond 166ee91698 feat(confidence-engine): persist canonical investigation state 2026-08-27 16:21:41 +01:00
robbond bc35e05253 refactor(confidence-engine): migrate scenario persistence to storage provider 2026-08-27 15:44:58 +01:00
robbond ba956eeb3a refactor(confidence-engine): add investigation storage provider 2026-08-27 15:24:38 +01:00
robbond 22e1d7484b feat(confidence-engine): support finding corrections 2026-08-27 13:43:23 +01:00
robbond 5c926154cd feat(confidence-engine): support not-relevant findings 2026-08-27 12:08:11 +01:00
robbond bf6c4241a5 chore: ignore local playwright mcp artifacts 2026-08-27 10:42:31 +01:00
robbond 0f4e49fc6c feat(confidence-engine): render focused findings from canonical state 2026-08-27 10:38:50 +01:00
robbond 7858650334 feat(confidence-engine): expose correlated findings to focused presentation 2026-08-27 09:23:51 +01:00
robbond ca7d8e5384 feat(confidence-engine): correlate focused result with contribution 2026-08-27 08:37:23 +01:00
robbond 0659599795 feat(confidence-engine): wire focused contribution finding derivation 2026-08-27 07:45:15 +01:00
robbond dc558e9c37 docs(confidence-engine): verify findings derivation gap in production chain
Verified: deriveFindingsFromContributions() exists with passing tests but
is never called in production. The contributions → findings seam is un-wired:

1. handleDeconstructSubmit() sends contribution to ScenarioForm
2. appendFocusedContribution() stores it in focusedContributions[]
3. findings state stays [] — no derivation ever runs
4. empty findings sent to /api/cases/update (which only echoes them back)
5. nothing renders from the findings surface

Fix: call deriveFindingsFromContributions after contribution is appended.
2026-08-27 07:40:50 +01:00
robbond 061ea364b3 feat(confidence-engine): derive findings from focused contributions 2026-08-27 06:44:07 +01:00
robbond 6a5cb43a30 docs(confidence-engine): checkpoint focused investigation workspace 2026-08-26 19:26:52 +01:00
robbond abeb3fcb03 feat(confidence-engine): add focused investigation overlay workspace 2026-08-26 19:22:54 +01:00
robbond 990b51aecf docs(confidence-engine): define progressive investigation workspace model 2026-08-26 17:26:04 +01:00
robbond 48b7185176 docs(confidence-engine): record current understanding isolation blocker 2026-08-26 16:30:32 +01:00
robbond 3235c35cf0 feat(confidence-engine): add focused finding handoff plumbing 2026-08-26 16:07:21 +01:00
robbond d3015f63d8 docs(confidence-engine): define minimum finding handoff slice 2026-08-26 15:07:57 +01:00
robbond 854160726e docs(confidence-engine): define focused finding handoff contract 2026-08-26 14:50:15 +01:00
robbond 10aa18d367 docs(confidence-engine): define finding graph reasoning contract 2026-08-26 14:28:33 +01:00
robbond ac5fbe7896 fix(confidence-engine): preserve focused learning across turns 2026-08-26 14:07:16 +01:00
robbond b26ea7d0ba docs(confidence-engine): establish contributions and findings distinction 2026-08-26 14:07:05 +01:00
robbond cb707c0192 test(confidence-engine): capture tentative mapping regression 2026-08-26 14:06:51 +01:00
robbond 787c8114ad docs(confidence-engine): record focused progression walkthrough findings 2026-08-26 12:40:37 +01:00
robbond fdb173d0e9 feat(confidence-engine): anchor focused frontier to investigation relevance 2026-08-26 12:16:41 +01:00
robbond cfd463d8b3 test(confidence-engine): capture structural frontier priority regression 2026-08-26 12:10:07 +01:00
robbond fd02be0f29 fix(confidence-engine): render focused investigation in current presentation 2026-08-26 11:52:18 +01:00
robbond 6288ef1031 fix(confidence-engine): keep focused investigation in current presentation 2026-08-26 11:30:59 +01:00
robbond 81dda77392 fix(confidence-engine): reopen completed focused investigation 2026-08-26 10:20:45 +01:00
robbond 42a7e82d88 feat(confidence-engine): tighten focused relationship attribution 2026-08-26 07:56:27 +01:00
robbond 3ca37b0918 test(confidence-engine): checkpoint focused deconstruction regression cases 2026-08-26 07:34:22 +01:00
robbond 112739b8e5 feat(confidence-engine): checkpoint focused deconstruction reasoning 2026-08-25 15:10:09 +01:00
robbond 9d670822a3 feat(confidence-engine): preserve focused deconstruction semantic fidelity 2026-08-24 10:11:06 +01:00
robbond 2c108df5a9 checkpoint: preserve latest live run graph output json 2026-08-23 19:56:07 +01:00
robbond c134b5cb04 feat(confidence-engine): stabilize investigation workspace with semantic decomposition and deterministic presentation anchors 2026-08-23 16:59:55 +01:00
robbond 01c57788ee feat(confidence-engine): stabilize user-directed investigation flow
Intentional changes in this checkpoint:
- Deconstruct route: use body.targetNodeId (client identity) over raw.model-invented ID
- ThreadContributionsBadge: compact per-thread contribution indicator with expandable history
- Reopen continuation: resume from accumulated contributions instead of reformulating
- showEvidenceLimit gate: hide evidence-limit card during active investigation paths
- Evidence-limit visibility correction in rendering pipeline
- Section ordering: assumptions and connections after 'Still unclear' in focused result
- Prompt v0.3: preserve user-stated alternatives as separate unknowns; no count inflation
- 3 durable regression tests (target identity, contribution persistence, reopen state)
- evidence-limit card visibility gate test suite

Temporary residue removed:
- test-analysis.mjs (scratch diagnostic)
- 5 diagnostic console.log blocks from reasoning-workspace.jsx
2026-08-23 12:05:51 +01:00
robbond 96ad0e7915 refine(ui): restore visual hierarchy and Situation context in initial workspace
- Enhance Current Understanding prominence with subtle teal/teal border
  gradient, stronger heading, larger body text, more internal spacing
- Restore Situation panel as right-hand column in initial reflection view;
  uses OriginalSituation when graph exists, scenario text fallback otherwise
- Stacks layout on narrow screens via grid-cols-1/gap-6/lg:grid-cols-3
- Apply teal styling to normal-state CurrentUnderstandingCard and
  PlainLanguageCard (was flat gray border with bg-transparent)
- Surface assumption nodes alongside unknowns in Open Questions; add
  Unclear / Plausible interpretation tags
- Wire up follow-up question buttons in deconstructed results
2026-08-22 19:01:45 +01:00
robbond 517d780e2c checkpoint: preserve semantic decomposition investigation state 2026-08-22 08:21:29 +01:00
robbond 68be2344c6 fix(rto): persist focused contributions immediately after deconstruct success
The successful focused deconstruct calls onFocusedContribution which
updates parent state, but never persisted the new collection to
sessionStorage. This meant an immediate reload would lose the
contribution.

Fix: add a useEffect in ReasoningWorkspace that watches the
focusedContributions prop for changes and saves via the existing
saveSession mechanism. A ref guard prevents double-save alongside the
existing updateStatus-success effect.
2026-08-21 18:33:20 +01:00
robbond fce68a050f feat(ui): RTO.31 ownership of focused contributions flows to scenario form
- Add focusedContributions state + appendFocusedContribution callback in ScenarioForm
- Contributions persist through session lifecycle (save/restore/restart)
- Pass onFocusedContribution and focusedContributions to ReasoningWorkspace
- Call onFocusedContribution on successful deconstruct with full result shape
- Test: contribution sequence, field preservation, same/different target coexistence
2026-08-21 18:03:49 +01:00
robbond 41afd9b49f checkpoint: preserve reflection and response-contract work 2026-08-21 14:29:39 +01:00
robbond c9335cf850 fix(ui): make initial reflection surface exclusive to post-Analyse state
Add three exclusivity guards that suppress legacy surfaces during the
initial post-Analyse reflection state (postAnalyseStatus === 'success'):

- CurrentInvestigationCard: suppressed because its selectedQuestion
  from startCase was leaking into the initial reflection view
- OpenQuestionsPanel: suppressed because it rendered whenever hasGraph
  was true, regardless of initial reflection state
- Terminal state cards (EvidenceLimitCard / CompletionCard): suppressed
  because they fired on status='success' && !hasSelectedQuestion

Transition out of initial reflection happens when user clicks a proposed
finding, which sets formulationStep='active' and triggers the existing
deactivation useEffect.

No reasoning changes. No startCase changes. No mock changes.
2026-08-21 11:51:33 +01:00
robbond 86287bebe8 feat(ui): surface initial semantic reconstruction 2026-08-21 10:34:22 +01:00
robbond 412551c968 test(ui): restore deconstruction before question choice 2026-08-20 15:58:23 +01:00
robbond 4b264c5681 test(ui): make inferred questions originate branches 2026-08-20 14:29:42 +01:00
robbond 65ced2e406 test(ui): make initial branch selection user owned 2026-08-20 14:11:37 +01:00
robbond 4761d07a76 test(ui): stabilize fresh start hydration 2026-08-20 10:00:18 +01:00
robbond 173240d76c test(ui): restore fresh start scenario entry 2026-08-20 09:42:32 +01:00
robbond cef8f46bd6 test(ui): restore entry lifecycle and notebook rendering 2026-08-20 09:33:06 +01:00
robbond 86bb3426ef test(ui): explore provisional branch pause and reopen 2026-08-20 09:00:01 +01:00
robbond df0e3b5a9b test(ui): explore branch notebook composition 2026-08-20 08:42:43 +01:00
robbond e7a1bc689c test(ui): consolidate branch scoped workspace 2026-08-20 08:01:40 +01:00
robbond 36060faf16 test(ui): verify branch scoped workspace data path 2026-08-20 07:56:26 +01:00
robbond 49c4b904df test(ui): checkpoint branch scoped fixture 2026-08-20 07:43:18 +01:00
robbond 09eeed5a9e test(ui): isolate branch scoped workspace experiment 2026-08-20 07:35:08 +01:00
robbond 47cd0c7d7b test(experiment): checkpoint branch scoped reasoning retrieval 2026-08-20 06:48:44 +01:00
robbond 6bf9e7e710 test(ui): explore branch as workspace context 2026-08-20 06:26:35 +01:00
robbond 8163c5d014 test(ui): clarify branch provenance and hierarchy 2026-08-20 06:15:44 +01:00
robbond 0ac2e05c40 test(ui): clarify branch focus and passive updates 2026-08-20 06:01:32 +01:00
robbond ad42f67800 test(ui): explore passive branch result indication 2026-08-20 05:55:25 +01:00
robbond 058ad2326f test(experiment): checkpoint nonlinear branch continuity 2026-08-20 05:45:29 +01:00
robbond 9fb9735c6e test(experiment): checkpoint semantic relationship inference result 2026-08-19 19:14:46 +01:00
robbond a00adfabf4 test(experiment): simplify relationship inference apparatus 2026-08-19 18:53:10 +01:00
robbond 601e46e4b7 docs: preserve domain-independent facilitator principles 2026-08-19 18:39:35 +01:00
robbond 85204f96ac test(experiment): checkpoint borderline relationship control 2026-08-19 17:35:51 +01:00
robbond e1a18e27e7 test(experiment): checkpoint relationship negative-control result 2026-08-19 17:27:52 +01:00
robbond a73f125f8d test(experiment): checkpoint relationship false-positive apparatus 2026-08-19 17:21:13 +01:00
robbond c97f07ba65 test(experiment): checkpoint fragment relationship discovery result 2026-08-19 16:59:22 +01:00
robbond 67103fa8d4 test(experiment): repair relationship discovery env loading 2026-08-19 16:35:58 +01:00
robbond 4687226bd8 test(experiment): repair relationship discovery result handling 2026-08-19 16:14:50 +01:00
robbond 8fb284c374 test(experiment): checkpoint fragment relationship discovery apparatus 2026-08-19 15:43:06 +01:00
robbond 8c52939c02 test(experiment): checkpoint derived focused current-view result 2026-08-19 15:34:41 +01:00
robbond 644108db71 test(experiment): checkpoint derived focused current-view apparatus 2026-08-19 15:27:14 +01:00
robbond 0b0d5594fe test(experiment): checkpoint granular answer fragment result 2026-08-19 14:41:57 +01:00
robbond fbeaf01f90 docs: archive verified historical experiment families 2026-08-19 14:25:43 +01:00
robbond e6d0327641 docs: archive historical Confidence Engine evidence 2026-08-19 12:07:17 +01:00
robbond a12f9555af docs: clarify Confidence Engine context authority 2026-08-19 11:49:30 +01:00
robbond 5b43c1b8f9 docs: preserve Confidence Engine methodology continuity 2026-08-19 10:46:05 +01:00
robbond e1b54e4073 test(experiment): checkpoint granular answer fragment apparatus 2026-08-19 10:14:46 +01:00
robbond 6ed3415220 test(experiment): checkpoint three-turn separated reasoning result 2026-08-19 09:51:31 +01:00
robbond 98889039c2 test(experiment): checkpoint three-turn separated reasoning apparatus 2026-08-19 09:35:48 +01:00
robbond 9c715161b0 test(experiment): checkpoint separated reasoning layers result 2026-08-19 09:15:25 +01:00
robbond 56de4a7ef3 test(experiment): checkpoint separated reasoning layers apparatus 2026-08-19 08:53:33 +01:00
robbond b20707c447 test(experiment): checkpoint focused context boundary result 2026-08-19 08:33:41 +01:00
robbond 6ed4d60029 test(experiment): checkpoint focused context boundary apparatus 2026-08-19 07:59:41 +01:00
robbond 153bbee85e test(experiment): checkpoint two-turn focused refinement result 2026-08-19 07:53:26 +01:00
robbond 8520f2195d test(experiment): expose two-turn live refinement route 2026-08-19 07:44:55 +01:00
robbond ebcf1d9306 test(experiment): checkpoint two-turn focused refinement apparatus 2026-08-19 07:35:32 +01:00
robbond dafc020f66 feat(experiment): checkpoint one-turn focused investigation UI 2026-08-19 07:07:10 +01:00
robbond 7add85d8d2 feat(experiment): checkpoint focused investigation boundaries 2026-08-19 05:41:32 +01:00
robbond c0b963973f test(experiment): checkpoint focused vs global result 2026-08-19 05:15:25 +01:00
robbond 913dfec507 test(experiment): checkpoint comparison observability 2026-08-18 19:28:30 +01:00
robbond 952cb442b5 test(experiment): checkpoint focused vs global comparison apparatus 2026-08-18 18:34:08 +01:00
robbond 2f6c90b027 test(experiment): checkpoint focused answer deconstruction 2026-08-18 18:25:35 +01:00
robbond 648e1c7a29 test(experiment): checkpoint explicit-node formulation 2026-08-18 17:29:07 +01:00
robbond fd98cda8ba feat(experiment): checkpoint RTO question lifecycle 2026-08-18 16:38:15 +01:00
robbond 6b25100f9a feat(experiment): checkpoint RTO open-question workspace 2026-08-18 15:25:27 +01:00
robbond db5016c138 feat(experiment): checkpoint RTO case workspace lifecycle 2026-08-18 14:59:52 +01:00
robbond 4a34dcc361 test(experiment): ground RTO apparatus in real fixture 2026-08-18 12:39:19 +01:00
robbond 25a88c5fc3 feat: multi-thread experimental apparatus (RTO.A1)
Add fixture-only apparatus for representing multiple concurrent open
investigation items within a fixed case context.

New scenario 'multi-thread' exposes:
- A fixed central situation statement and case summary (product-launch
  timing decision, drawn from existing pre-anchored-product-launch
  data)
- Three open investigation items — none compulsory: enterprise customer
  signing probability, competitor timing, financial viability comparison
- One engine recommendation (mt-ent-customer-signing, ordered first)
- User selection of any item; chosen item becomes visually primary while
  others remain visible as context
- Experimental state isolated in _experimental / _experimentalState —
  never aliases production graph fields
2026-08-18 10:39:16 +01:00
robbond 8339b6849a docs: checkpoint return to Confidence Engine origin 2026-08-18 08:33:05 +01:00
robbond 55b7551739 test(harness): preserve null-question start captures 2026-08-18 07:11:27 +01:00
robbond 5d0ce0ddd3 experiment: compare model and deterministic investigation selection 2026-08-18 07:00:39 +01:00
robbond 600b07d820 test(harness): support gated live investigation continuation 2026-08-18 06:48:40 +01:00
robbond 7dd4a956fb experiment: validate live financial investigation progression 2026-08-18 06:32:40 +01:00
robbond a52f0345a1 experiment: validate live question-rejection ownership 2026-08-17 18:25:40 +01:00
robbond 7685a4f2af test(evidence): preserve live product-launch journey captures 2026-08-17 18:08:47 +01:00
robbond 8117f3d307 docs: record current reasoning checkpoint 2026-08-17 17:58:54 +01:00
robbond 772ae495c6 fix(reasoning): preserve investigation ownership across selection and question rejection 2026-08-17 17:58:45 +01:00
robbond d908f3746d test(e2e): preserve manually recorded investigation journey 2026-08-17 13:48:56 +01:00
289 changed files with 30353 additions and 4532 deletions
+37 -10
View File
@@ -19,6 +19,18 @@ It:
6. updates the graph from the answer; 6. updates the graph from the answer;
7. repeats until action is justified or the remaining uncertainty is clear. 7. repeats until action is justified or the remaining uncertainty is clear.
> **NOTE:** The flow above describes historical/current implementation mechanics.
> It does not represent current Confidence Engine methodology direction.
> See `docs/Confidence_Engine_Return_to_Origin_Methodology_Context_2026-08-18.md`
> for the current working hypothesis (granular answer-fragment inquiry).
The linear selector-led flow described above is a **historical capability**, not
an automatic architecture to continue. Under Return-to-Origin:
- The Engine facilitates inquiry; it does not compel a single-question route.
- The user owns which unresolved investigation/question to pursue.
- Accumulated reasoning memory does not necessarily belong inside repeated LLM calls.
A chatbot remembers the conversation. A chatbot remembers the conversation.
The Confidence Engine preserves the state of the reasoning. The Confidence Engine preserves the state of the reasoning.
@@ -50,15 +62,23 @@ The engine should help a user reach one of these states:
## Current development stage ## Current development stage
The deterministic reasoning architecture reached a stable alpha checkpoint. > **Version lineage note:** The Confidence Engine uses two distinct version
> lineages that must not be conflated:
> - **Reasoning-engine experimental lineage** (v0.8+): reasoning-fidelity,
> investigation-state assessment, semantic selectors — under RTO pause.
> - **UX/product development lineage** (v0.7): workspace layout, user views,
> loading feedback — also paused.
> These are independent tracks; do not assume they describe one product version.
Current work is primarily improving: The deterministic reasoning architecture reached a stable alpha checkpoint
(reasoning-engine v0.8). UI/product work reached v0.7 staging. Both have
paused under Return to Origin while the granular answer-fragment hypothesis
is evaluated as working methodology context.
- usability; Current work is paused. The next step begins from the methodology question:
- presentation; given the useful investigation structure the Engine can already derive, how
- loading feedback; should that structure be surfaced so a person can see, choose, defer, and
- plain-language explanations; return to open questions while the Engine continues to guide their thinking?
- separation of user and developer views.
Do not resume broad reasoning architecture work unless a repeated observed Do not resume broad reasoning architecture work unless a repeated observed
failure clearly requires it. failure clearly requires it.
@@ -93,7 +113,11 @@ The interface should minimise cognitive load by presenting the current state fir
The engine may contain hundreds of reasoning nodes; the user should only see the information required to take the next meaningful action. The engine may contain hundreds of reasoning nodes; the user should only see the information required to take the next meaningful action.
## Why workspace layout matters (v0.7) ## Why workspace layout matters (v0.7 — UX/product lineage)
> **This section documents paused UX design intent.** It belongs to the v0.7
> product development lineage, not the reasoning-engine lineage. UI work is
> currently paused under Return to Origin.
This phase optimises for simultaneous visibility instead of sequential scrolling. This phase optimises for simultaneous visibility instead of sequential scrolling.
Related panels — Understanding alongside Investigation Map, Situation alongside History — can appear side-by-side on wide screens while mobile continues to stack everything vertically. The reasoning engine is completely unaware of these changes; only the presentation layer is affected. Related panels — Understanding alongside Investigation Map, Situation alongside History — can appear side-by-side on wide screens while mobile continues to stack everything vertically. The reasoning engine is completely unaware of these changes; only the presentation layer is affected.
@@ -104,7 +128,10 @@ Read `docs/current-working-principles.md` for current guidance. Treat `docs/arch
For UI mock work, read `docs/ui-mock-reference.md`. Do not load For UI mock work, read `docs/ui-mock-reference.md`. Do not load
`docs/archive/deferred-ux-backlog.md` unless a named past UX idea is being reviewed. `docs/archive/deferred-ux-backlog.md` unless a named past UX idea is being reviewed.
Engine and UI experiments are paused. First file to inspect when resuming:
`docs/current-project-state.md`, then `docs/project-knowledge-inventory.md`. Engine and UI experiments are paused under Return to Origin. First file to inspect when resuming:
**`docs/current-handoff.md`** (methodology continuity anchor), then `docs/current-project-state.md`, then `docs/project-knowledge-inventory.md`.
> After reading `docs/current-project-state.md`, choose the relevant minimal pack from `docs/task-context-packs.md`. Do not combine packs unless a specific task genuinely crosses boundaries. > After reading `docs/current-project-state.md`, choose the relevant minimal pack from `docs/task-context-packs.md`. Do not combine packs unless a specific task genuinely crosses boundaries.
>
> **Historical experiment families are evidence to load only when a specific question requires them; they are not default architecture context.**
+15
View File
@@ -515,6 +515,21 @@ Three tiers, applied top to bottom:
- Omit items too verbose to scan; do not synthesise rewritten claims. - Omit items too verbose to scan; do not synthesise rewritten claims.
- Never invent facts absent from the graph. - Never invent facts absent from the graph.
### Provenance and attribution
Preserve authorship and provenance in every user-facing presentation.
When displaying a user's previous input, keep it visibly distinct from system-generated interpretation. If the original user wording is available, present it as the user's response rather than rewriting it into system prose. Derived Findings, summaries, uncertainties, assumptions, or follow-up questions must not be styled or worded in a way that implies the user said them.
The distinction should be:
```text
User response → user-authored (verbatim)
What we learned → Engine-derived
```
Exact labels are subject to UX refinement; the durable rule is separating provenance, not prescribing specific copy.
## Investigation Narrative ## Investigation Narrative
The reasoning graph is the machine representation of the investigation. The reasoning graph is the machine representation of the investigation.
+7
View File
@@ -39,3 +39,10 @@ yarn-error.log*
evaluation-results/ evaluation-results/
provider-debug-results/ provider-debug-results/
tests-results/ tests-results/
# Local Playwright MCP runtime output
.playwright-mcp/
# Evidence/temp directories from live experiments
.evidence-temp/
@@ -0,0 +1,89 @@
import { getProvider } from "@/lib/llm/provider";
import { buildFocusedDeconstructPrompt, validateFocusedDeconstructSchema } from "@/lib/graph/focused-investigation";
export async function POST(request) {
try {
const body = await request.json();
if (!body.targetNodeId || typeof body.targetNodeId !== "string") {
return Response.json(
{ error: "Request must include a 'targetNodeId' string field" },
{ status: 400 },
);
}
if (!body.targetLabel || typeof body.targetLabel !== "string") {
return Response.json(
{ error: "Request must include a 'targetLabel' string field" },
{ status: 400 },
);
}
if (!body.targetDescription || typeof body.targetDescription !== "string") {
return Response.json(
{ error: "Request must include a 'targetDescription' string field" },
{ status: 400 },
);
}
if (!body.centralStatement || typeof body.centralStatement !== "string") {
return Response.json(
{ error: "Request must include a 'centralStatement' string field" },
{ status: 400 },
);
}
if (!body.question || typeof body.question !== "string") {
return Response.json(
{ error: "Request must include a 'question' string field" },
{ status: 400 },
);
}
if (!body.answer || typeof body.answer !== "string") {
return Response.json(
{ error: "Request must include an 'answer' string field" },
{ status: 400 },
);
}
const prompt = buildFocusedDeconstructPrompt({
targetLabel: body.targetLabel,
targetDescription: body.targetDescription,
centralStatement: body.centralStatement,
question: body.question,
answer: body.answer,
});
const provider = getProvider();
const startedAt = Date.now();
const raw = await provider.generateReconstruction(prompt, process.env.OLLAMA_MODEL);
const elapsedMs = Date.now() - startedAt;
// Validate schema (required fields present, no graph-mutation fields)
const validationErrors = validateFocusedDeconstructSchema(raw);
if (validationErrors.length > 0) {
return Response.json(
{
success: false,
error: "Focused deconstruction result did not match expected schema",
validationErrors,
targetNodeId: body.targetNodeId,
elapsedMs,
},
{ status: 502 },
);
}
return Response.json({
success: true,
targetNodeId: body.targetNodeId,
observations: raw.observations,
uncertainties: raw.uncertainties,
assumptions: raw.assumptions,
relationships: raw.relationships,
possibleFollowUpQuestions: raw.possibleFollowUpQuestions,
elapsedMs,
});
} catch (e) {
return Response.json(
{ error: e.message || "Unknown server error" },
{ status: 500 },
);
}
}
@@ -0,0 +1,52 @@
import { formulateQuestionForTarget } from "@/lib/graph/focused-investigation";
export async function POST(request) {
try {
const body = await request.json();
if (!body.targetNodeId || typeof body.targetNodeId !== "string") {
return Response.json(
{ error: "Request must include a 'targetNodeId' string field" },
{ status: 400 },
);
}
if (!body.situationGraph || typeof body.situationGraph !== "object") {
return Response.json(
{ error: "Request must include a 'situationGraph' object field" },
{ status: 400 },
);
}
const result = formulateQuestionForTarget({
situationGraph: body.situationGraph,
targetNodeId: body.targetNodeId,
});
if (!result.success) {
return Response.json(
{ success: false, error: result.error },
{ status: 400 },
);
}
return Response.json({
success: true,
targetNodeId: result.targetNodeId,
question: result.question,
strategy: result.strategy,
reasoningPattern: result.reasoningPattern,
reasoningPatternReason: result.reasoningPatternReason,
reason: result.reason,
questionFamily: result.questionFamily,
selectedQuestionTemplate: result.selectedQuestionTemplate,
allowedQuestionFamilies: result.allowedQuestionFamilies,
rejectedQuestionFamilies: result.rejectedQuestionFamilies,
});
} catch (e) {
return Response.json(
{ error: e.message || "Unknown server error" },
{ status: 500 },
);
}
}
+143
View File
@@ -0,0 +1,143 @@
/**
* Experimental branch switcher — RTO.25A
*
* Smallest branch representation needed to test passive late-result indication.
* Does NOT replace production branch navigation. Temporary fixture only.
*/
"use client";
import React, { useState, useEffect } from "react";
/* ── Keyframes (injected once via <style> at render) ───── */
const PulseStyle = () => (
<style>{`
@keyframes rto-pulse {
0%, 100% { opacity: 0.6; }
50% { opacity: 1; }
}
`}</style>
);
/* ── Status dot (passive new-result indicator) ─────────── */
function NewIndicator({ visible }) {
if (!visible) return null;
return (
<span
className="ml-2 inline-flex items-center"
title="Something new is available here"
aria-label="New result available"
>
<span
className="relative inline-block h-[8px] w-[8px]"
style={{ animation: "rto-pulse 3s ease-in-out infinite" }}
>
<span
className="absolute inset-0 rounded-full bg-blue-400/70"
aria-hidden="true"
/>
</span>
</span>
);
}
/* ── Single branch row ─────────────────────────────────── */
function BranchRow({ id, label, active, isNew, isPaused, origin, onClick }) {
const isActive = Boolean(active);
return (
<button
onClick={onClick}
disabled={isActive}
aria-current={isActive ? "page" : undefined}
className={`w-full flex items-start gap-2 rounded-md px-3 py-2 text-left transition text-sm ${
isActive
? "bg-blue-50/80 border border-blue-200/60 text-blue-900 font-medium"
: "text-gray-600 hover:bg-gray-100/70 hover:text-gray-800 border border-transparent"
} ${!isActive ? "cursor-pointer" : "cursor-default"}`}
>
{/* Active indicator — ● vs ○ */}
<span
className={`flex-none leading-none text-base ${
isActive ? "text-blue-500" : "text-gray-400"
}`}
aria-hidden="true"
>
{isActive ? "●" : "○"}
</span>
{/* Branch label + origin */}
<span className="flex-1 min-w-0">
<span className="truncate block">{label}</span>
{origin && (
<span className="block text-[11px] leading-tight text-gray-500/80 truncate" title={origin}>
{origin}
</span>
)}
</span>
{/* Passive indicators: pause + new */}
<span className="flex items-center gap-1.5 flex-none">
{!isActive && isPaused && (
<span
className="text-[10px] text-gray-400"
title="Done for now"
>
Paused
</span>
)}
{!isActive && <NewIndicator visible={isNew} />}
</span>
</button>
);
}
/* ── Card wrapper ────────────────────────────────────────── */
export default function ExperimentalBranchSwitcher({
branches = [],
activeBranchId,
branchNewResults = {},
branchPauseState = [],
onBranchSelect,
}) {
if (!branches.length) return null;
return (
<div
className="rounded-lg border border-gray-200/60 bg-gray-50/30 p-4"
role="radiogroup"
aria-label="Experimental branch switcher — RTO.25A"
>
{/* Label — clearly experimental */}
<h2 className="mb-1 text-[10px] font-semibold tracking-widest uppercase text-gray-600">
Branches{" "}
<span className="font-normal text-gray-500">(exp)</span>
</h2>
<p className="mb-3 text-[11px] font-medium leading-tight text-gray-500/80">
Browse branches. Current focus is preserved.
</p>
<div className="space-y-1" role="list" aria-label="Available branches">
{branches.map((branch) => (
<BranchRow
key={branch.id}
id={branch.id}
label={branch.label}
active={activeBranchId === branch.id}
isNew={Boolean(branchNewResults[branch.id])}
isPaused={branchPauseState.includes(branch.id)}
origin={branch.origin}
onClick={() => onBranchSelect?.(branch.id)}
/>
))}
</div>
</div>
);
}
export { PulseStyle };
+2 -2
View File
@@ -84,10 +84,10 @@ export default function InvestigationMap({ turnCount = 0 }) {
return ( return (
<div className="rounded-lg border border-gray-200/60 bg-gray-50/30 p-4" role="region" aria-label="Investigation map preview"> <div className="rounded-lg border border-gray-200/60 bg-gray-50/30 p-4" role="region" aria-label="Investigation map preview">
<h2 className="mb-1 text-[11px] font-medium tracking-widest uppercase text-gray-300"> <h2 className="mb-1 text-[11px] font-semibold tracking-widest uppercase text-gray-500">
Investigation Map Investigation Map
</h2> </h2>
<p className="mb-3 text-xs text-gray-400/70"> <p className="mb-3 text-xs font-medium leading-tight text-gray-500/80">
Active investigation topics and their status. Active investigation topics and their status.
</p> </p>
@@ -196,7 +196,7 @@ function InvestigationSummaryPanelV2({ graph, selectedQuestion, result, updateSt
<div> <div>
{stillInvestigating.length > 1 ? ( {stillInvestigating.length > 1 ? (
<> <>
<h3 className="mb-2 text-xs font-medium text-gray-400">Still investigating</h3> <h3 className="mb-2 text-xs font-medium text-gray-500">Still investigating</h3>
<ul className="space-y-1.5"> <ul className="space-y-1.5">
{Object.entries(investigatingByGroup).map(([group, items]) => ( {Object.entries(investigatingByGroup).map(([group, items]) => (
<li key={group}> <li key={group}>
@@ -227,7 +227,7 @@ function InvestigationSummaryPanelV2({ graph, selectedQuestion, result, updateSt
{/* ── What we have learned ────────────────────────── */} {/* ── What we have learned ────────────────────────── */}
{known.length > 0 && ( {known.length > 0 && (
<div> <div>
<h3 className="mb-2 text-xs font-medium text-gray-400">What we know</h3> <h3 className="mb-2 text-xs font-medium text-gray-500">What we know</h3>
<ul className="space-y-1.5"> <ul className="space-y-1.5">
{known.map((item, i) => ( {known.map((item, i) => (
<li key={i} className="flex items-start gap-2"> <li key={i} className="flex items-start gap-2">
@@ -243,8 +243,8 @@ function InvestigationSummaryPanelV2({ graph, selectedQuestion, result, updateSt
{/* ── Quiet reasoning summary — secondary ─────────── */} {/* ── Quiet reasoning summary — secondary ─────────── */}
<div className="pt-2 border-t border-gray-200/40"> <div className="pt-2 border-t border-gray-200/40">
<p className="text-[10px] font-medium tracking-widest uppercase text-gray-300 mb-1.5">Reasoning</p> <p className="text-[10px] font-semibold tracking-widest uppercase text-gray-500 mb-1.5">Reasoning</p>
<div className="flex flex-wrap gap-x-4 gap-y-1 text-xs text-gray-400"> <div className="flex flex-wrap gap-x-4 gap-y-1 text-xs text-gray-500">
{reasonEntries.map(([label, count]) => ( {reasonEntries.map(([label, count]) => (
<span key={label}> <span key={label}>
{count} {label} {count} {label}
@@ -47,7 +47,7 @@ function KnownSection({ title, items }) {
return ( return (
<div> <div>
<h3 className="mb-2 text-[11px] font-medium tracking-widest uppercase text-gray-400"> <h3 className="mb-2 text-[11px] font-medium tracking-widest uppercase text-gray-500">
{title} {title}
</h3> </h3>
<ul className="space-y-1.5"> <ul className="space-y-1.5">
@@ -67,7 +67,7 @@ function InvestigatingSection({ title, items }) {
return ( return (
<div> <div>
<h3 className="mb-2 text-[11px] font-medium tracking-widest uppercase text-gray-400"> <h3 className="mb-2 text-[11px] font-medium tracking-widest uppercase text-gray-500">
{title} {title}
</h3> </h3>
<ul className="space-y-1.5"> <ul className="space-y-1.5">
@@ -87,7 +87,7 @@ function ExplanationSection({ items }) {
return ( return (
<div> <div>
<h3 className="mb-2 text-[11px] font-medium tracking-widest uppercase text-gray-400"> <h3 className="mb-2 text-[11px] font-medium tracking-widest uppercase text-gray-500">
Possible explanations Possible explanations
</h3> </h3>
<ul className="space-y-1.5"> <ul className="space-y-1.5">
@@ -102,10 +102,10 @@ function QuietSummary({ text }) {
return ( return (
<div className="pt-2 border-t border-gray-200/40"> <div className="pt-2 border-t border-gray-200/40">
<p className="text-[10px] font-medium tracking-widest uppercase text-gray-300 mb-1.5"> <p className="text-[10px] font-semibold tracking-widest uppercase text-gray-500 mb-1.5">
Investigation state Investigation state
</p> </p>
<p className="text-xs text-gray-400">{text}</p> <p className="text-xs text-gray-500">{text}</p>
</div> </div>
); );
} }
+1 -1
View File
@@ -127,7 +127,7 @@ function InvestigationSummaryPanel({ graph, selectedQuestion, result, updateStat
{/* Current understanding */} {/* Current understanding */}
{currentUnderstanding && ( {currentUnderstanding && (
<div> <div>
<h3 className="mb-1 text-[11px] font-medium tracking-widest uppercase text-gray-400/70"> <h3 className="mb-1 text-[11px] font-semibold tracking-widest uppercase text-gray-500">
What we understand so far What we understand so far
</h3> </h3>
<p className="text-sm leading-relaxed text-gray-600">{currentUnderstanding}</p> <p className="text-sm leading-relaxed text-gray-600">{currentUnderstanding}</p>
File diff suppressed because it is too large Load Diff
+231 -60
View File
@@ -5,6 +5,8 @@ import { useState, useRef, useMemo } from "react";
import DiagnosticsView from "@/components/diagnostics-view"; import DiagnosticsView from "@/components/diagnostics-view";
import ReasoningWorkspace, { LoadingOverlay, ContinueLaterBanner } from "@/components/reasoning-workspace"; import ReasoningWorkspace, { LoadingOverlay, ContinueLaterBanner } from "@/components/reasoning-workspace";
import { mockFetch, AVAILABLE_SCENARIOS } from "@/lib/mocks/confidence-engine/mock-client"; import { mockFetch, AVAILABLE_SCENARIOS } from "@/lib/mocks/confidence-engine/mock-client";
import { deriveFindingsFromContributions, normalizeFindings, produceFindingInformedSummary } from "@/lib/graph/finding-helpers";
import { loadInvestigation, saveInvestigation, clearInvestigation } from "@/lib/storage/investigation-storage";
/* Compile-time env resolution — NEXT_PUBLIC_ vars are injected by Next.js at build */ /* Compile-time env resolution — NEXT_PUBLIC_ vars are injected by Next.js at build */
const MOCK_ENABLED = process.env.NEXT_PUBLIC_CONFIDENCE_ENGINE_MOCKS === "true"; const MOCK_ENABLED = process.env.NEXT_PUBLIC_CONFIDENCE_ENGINE_MOCKS === "true";
@@ -33,7 +35,7 @@ export async function submitScenarioForStartCase(fetchImpl, scenario) {
export async function submitAnswerForUpdateCase( export async function submitAnswerForUpdateCase(
fetchImpl, fetchImpl,
{ situationGraph, previousQuestion, answer }, { situationGraph, previousQuestion, answer, findings },
) { ) {
if (!answer?.trim()) { if (!answer?.trim()) {
return { return {
@@ -47,10 +49,15 @@ export async function submitAnswerForUpdateCase(
}; };
} }
const body = { situationGraph, previousQuestion, answer };
if (findings && findings.length > 0) {
body.findings = findings;
}
const response = await fetchImpl("/api/cases/update", { const response = await fetchImpl("/api/cases/update", {
method: "POST", method: "POST",
headers: { "Content-Type": "application/json" }, headers: { "Content-Type": "application/json" },
body: JSON.stringify({ situationGraph, previousQuestion, answer }), body: JSON.stringify(body),
}); });
return { return {
@@ -186,25 +193,37 @@ export function UpdateErrorPanel({ updateError }) {
export { INITIAL_MESSAGES, UPDATE_MESSAGES, useLoadingStatus }; export { INITIAL_MESSAGES, UPDATE_MESSAGES, useLoadingStatus };
// Session key
const SESSION_KEY = "confidence-engine-session";
function getSession() { /**
if (typeof sessionStorage === "undefined") return null; * Derives whether the current component state represents a valid investigation
try { * context sufficient to render a workspace surface.
const raw = sessionStorage.getItem(SESSION_KEY); *
return raw ? JSON.parse(raw) : null; * Valid only when:
} catch (_) { return null; } * - result carries a situationGraph (renderable graph), OR
* - status is "success" AND there is a non-empty scenario
* (from session restoration with real data).
*
* This predicate is the single source of truth for all render-gate decisions.
* showExperimentView, fixture availability, or sessionStorage keys alone are
* NOT sufficient to constitute valid context.
*/
export function hasValidInvestigationContext(result, status, scenario) {
return Boolean(result?.situationGraph) ||
(status === "success" && Boolean(scenario?.trim()));
} }
function saveSession(state) { /**
if (typeof sessionStorage === "undefined") return; * Derives the primary surface that must render for the given state tuple.
try { sessionStorage.setItem(SESSION_KEY, JSON.stringify(state)); } catch (_) {} * Enforces exactly-one-primary-surface invariant: no zero, no two.
} */
export function derivePrimarySurface(result, status, _showExperimentView, scenario, activeBranchId) {
if (status === "loading") return "LOADING";
if (status === "error") return "ERROR_SURFACE";
function clearSession() { const valid = hasValidInvestigationContext(result, status, scenario);
if (typeof sessionStorage === "undefined") return;
try { sessionStorage.removeItem(SESSION_KEY); } catch (_) {} if (valid) return "NORMAL_WORKSPACE";
return "SCENARIO_ENTRY";
} }
export default function ScenarioForm() { export default function ScenarioForm() {
@@ -219,19 +238,145 @@ export default function ScenarioForm() {
const [currentUnderstanding, setCurrentUnderstanding] = useState(null); const [currentUnderstanding, setCurrentUnderstanding] = useState(null);
const [mockScenario, setMockScenario] = useState(""); const [mockScenario, setMockScenario] = useState("");
const [hideFacilitatorOnLanding, setHideFacilitatorOnLanding] = useState(false); const [hideFacilitatorOnLanding, setHideFacilitatorOnLanding] = useState(false);
/* ── RTO.31: focused contributions ownership ─────────────── */
const [focusedContributions, setFocusedContributions] = useState([]);
/* ── v2 findings from focused contributions ─────────────── */
const [findings, setFindings] = useState([]);
function appendFinding(finding) {
setFindings((prev) => {
return [...prev, finding];
});
}
function updateFindingDisposition(findingId, newDisposition) {
setFindings((prev) =>
prev.map((f) => (f.id === findingId ? { ...f, userDisposition: newDisposition } : f)),
);
}
function updateFindingProposition(findingId, newProposition) {
setFindings((prev) =>
prev.map((f) =>
f.id === findingId
? { ...f, proposition: newProposition, userDisposition: null }
: f,
),
);
}
/**
* v0.49 promotion seam deterministic Current Understanding update
* triggered by "Done for now" activity boundary (no case/update, no LLM).
*/
function handleDoneForNowPromotion(targetNodeId) {
if (!targetNodeId || !findings?.length) return;
// Filter eligible findings for this specific target only.
const eligible = findings.filter(
(f) => f.originatingTargetNodeId === targetNodeId && (f.userDisposition === null || f.userDisposition === "agree"),
);
if (eligible.length === 0) return;
// Determine the base: use currentUnderstanding if available, else empty string.
const baseSummary = currentUnderstanding ?? "";
// Deterministic producer no LLM, no API.
const newSummary = produceFindingInformedSummary(baseSummary, eligible);
// Idempotence guard: skip if summary is unchanged (no new eligible findings
// beyond what's already in the current Evidence block).
if (newSummary === baseSummary) return;
// Avoid duplicate evidence propositions from repeated promotion.
const existingEvidenceMatch = baseSummary.match(/Evidence:\s*\[([^\]]+)\]/);
let isDuplicate = false;
if (existingEvidenceMatch) {
const existingTexts = existingEvidenceMatch[1].split("; ").map((t) => t.trim());
isDuplicate = eligible.every((f) => existingTexts.includes(f.proposition));
}
if (isDuplicate) return;
// Mutate the SAME summary/state that autosave already persists.
setCurrentUnderstanding(newSummary);
}
function appendFocusedContribution(contribution) {
// Derive a single stored contribution object and use it for BOTH
// contribution storage AND Finding derivation so the same identity
// appears in focusedContributions[] and Finding.contributionId.
setFocusedContributions((prev) => {
const seq = prev.length + 1;
const storedContribution = { ...contribution, sequence: seq, id: `contrib-${String(seq).padStart(4, "0")}` };
// Derive Findings from the exact stored Contribution (not a separate approximation)
setFindings((prevFindings) => {
const newFindings = deriveFindingsFromContributions([storedContribution]).findings;
return normalizeFindings([...prevFindings, ...newFindings]);
});
return [...prev, storedContribution];
});
}
const textareaRef = useRef(null); const textareaRef = useRef(null);
/* Restore persisted session on mount (Phase 3) ─────────── */ /* ── Valid investigation predicate ─────────────────────── */
// Delegated to the exported utility below.
const validCtx = hasValidInvestigationContext(result, status, scenario);
/* Restore persisted session on mount ─────────── */
useEffect(() => { useEffect(() => {
if (typeof window === "undefined") return; if (typeof window === "undefined") return;
const saved = getSession(); const saved = loadInvestigation();
if (!saved) return; if (!saved) return;
const hasGraph = Boolean(saved.situationGraph);
setScenario(saved.scenario || ""); setScenario(saved.scenario || "");
setResult(saved.situationGraph ? { ...saved, situationGraph: saved.situationGraph } : null); setResult(hasGraph ? { ...saved, situationGraph: saved.situationGraph } : null);
setCurrentUnderstanding(saved.summary || null); setCurrentUnderstanding(saved.summary || null);
setStatus("success"); setFocusedContributions(saved.focusedContributions || []);
setFindings(saved.findings || []);
// Partial sessions (present but no graph) must NOT suppress the
// scenario-entry form. Only promote to success when there is actual
// investigation data to render.
if (hasGraph) {
setStatus("success");
}
}, []); }, []);
/* ── Canonical autosave — persist whenever state changes (Phase 2) ── */
useEffect(() => {
if (typeof window === "undefined") return;
// Guard: no valid investigation yet skip autosave during idle/start flows.
// Also prevents overwriting an existing saved investigation with the initial
// empty state of a fresh ScenarioForm instance (hydration race guard).
if (!result?.situationGraph) return;
void saveInvestigation({
scenario,
situationGraph: result.situationGraph,
selectedQuestion: result.selectedQuestion,
summary: currentUnderstanding,
updatedAt: new Date().toISOString(),
focusedContributions,
findings,
});
}, [
scenario,
result?.situationGraph,
result?.selectedQuestion,
currentUnderstanding,
focusedContributions,
findings,
]);
/* Restore facilitator dismiss preference (Experiment 05) ─── */ /* Restore facilitator dismiss preference (Experiment 05) ─── */
useEffect(() => { useEffect(() => {
if (typeof window === "undefined") return; if (typeof window === "undefined") return;
@@ -307,7 +452,7 @@ export default function ScenarioForm() {
setCurrentUnderstanding(data.summary ?? null); setCurrentUnderstanding(data.summary ?? null);
const normalised = normaliseStartResult(data); const normalised = normaliseStartResult(data);
setResult(normalised); setResult(normalised);
saveSession({ scenario, situationGraph: normalised.situationGraph, selectedQuestion: normalised.selectedQuestion, summary: data.summary ?? null, updatedAt: new Date().toISOString() }); saveInvestigation({ scenario, situationGraph: normalised.situationGraph, selectedQuestion: normalised.selectedQuestion, summary: data.summary ?? null, updatedAt: new Date().toISOString(), focusedContributions, findings: [] });
} else { } else {
setStatus("error"); setStatus("error");
setCurrentUnderstanding(data.summary ?? null); setCurrentUnderstanding(data.summary ?? null);
@@ -340,6 +485,7 @@ export default function ScenarioForm() {
situationGraph: result?.situationGraph, situationGraph: result?.situationGraph,
previousQuestion: result?.selectedQuestion, previousQuestion: result?.selectedQuestion,
answer, answer,
findings,
}); });
if (submission.skipped) { if (submission.skipped) {
@@ -352,6 +498,12 @@ export default function ScenarioForm() {
const outcome = submission.data; const outcome = submission.data;
if (submission.ok && outcome.success) { if (submission.ok && outcome.success) {
// Merge server-returned findings with local state
let newFindings = [...findings];
if (outcome.appendedFindings && Array.isArray(outcome.appendedFindings)) {
newFindings = [...newFindings, ...outcome.appendedFindings];
}
setUpdateStatus("success"); setUpdateStatus("success");
setCurrentUnderstanding( setCurrentUnderstanding(
outcome.summary ? outcome.summary : currentUnderstanding, outcome.summary ? outcome.summary : currentUnderstanding,
@@ -372,8 +524,8 @@ export default function ScenarioForm() {
diagnostics: outcome.diagnostics, diagnostics: outcome.diagnostics,
})); }));
setAnswer(""); setAnswer("");
// Persist after successful update turn // Persist after successful update turn include findings
saveSession({ scenario, situationGraph: outcome.updatedSituationGraph, selectedQuestion: normaliseUpdateSelectedQuestion(outcome.selectedQuestion), summary: outcome.summary ?? currentUnderstanding, updatedAt: new Date().toISOString() }); saveInvestigation({ scenario, situationGraph: outcome.updatedSituationGraph, selectedQuestion: normaliseUpdateSelectedQuestion(outcome.selectedQuestion), summary: outcome.summary ?? currentUnderstanding, updatedAt: new Date().toISOString(), focusedContributions, findings: newFindings });
} else { } else {
setUpdateStatus("error"); setUpdateStatus("error");
setUpdateError(outcome); setUpdateError(outcome);
@@ -386,7 +538,8 @@ export default function ScenarioForm() {
return ( return (
<div className="space-y-6"> <div className="space-y-6">
{status === "idle" && ( {/* ── Idle form for scenario input ─ */}
{!result?.situationGraph && status === "idle" && (
<form onSubmit={handleSubmit} className="space-y-6"> <form onSubmit={handleSubmit} className="space-y-6">
{/* Two-column landing workspace */} {/* Two-column landing workspace */}
@@ -419,7 +572,7 @@ export default function ScenarioForm() {
className="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500" className="h-4 w-4 rounded border-gray-300 text-blue-600 focus:ring-blue-500"
/> />
<label htmlFor="dismiss-facilitator" className="text-xs text-gray-500"> <label htmlFor="dismiss-facilitator" className="text-xs text-gray-500">
Don't show this introduction again {`Dismiss this introduction permanently`}
</label> </label>
</div> </div>
</div> </div>
@@ -428,7 +581,7 @@ export default function ScenarioForm() {
{/* Right panel — Workspace (2/3 on desktop) */} {/* Right panel — Workspace (2/3 on desktop) */}
<div className={hideFacilitatorOnLanding ? "md:col-span-3" : "md:col-span-2"}> <div className={hideFacilitatorOnLanding ? "md:col-span-3" : "md:col-span-2"}>
<h2 className="mb-4 text-xs font-bold tracking-widest uppercase text-gray-400">Tell me what's happening</h2> <h2 className="mb-4 text-xs font-bold tracking-widest uppercase text-gray-400">What&#39;s the situation</h2>
<textarea <textarea
ref={textareaRef} ref={textareaRef}
value={scenario} value={scenario}
@@ -505,42 +658,58 @@ export default function ScenarioForm() {
/> />
)} )}
{/* ── Main result workspace ─────────────────────── */} {/* ── Main result workspace ─── */}
{((status === "success" || status === "error") && status !== "loading") && ( {(status === "success" || status === "error") && (
<ReasoningWorkspace <>
scenario={scenario} <div className="grid grid-cols-1 gap-6 lg:grid-cols-3">
status={status} {/* Workspace — uses result from Analyse or Update only */}
updateStatus={updateStatus} <div className="lg:col-span-2">
currentUnderstanding={currentUnderstanding} <ReasoningWorkspace
result={{ scenario={scenario}
...(result || {}), status={status}
situationGraph: updateResult?.updatedSituationGraph ?? result?.situationGraph, updateStatus={updateStatus}
selectedQuestion: updateResult?.selectedQuestion ?? result?.selectedQuestion, currentUnderstanding={currentUnderstanding}
newlySurfacedNodeIds: result?.newlySurfacedNodeIds || [], result={{
diagnostics: result?.diagnostics || null, ...(result || {}),
updateError, situationGraph: updateResult?.updatedSituationGraph ?? result?.situationGraph,
}} selectedQuestion: updateResult?.selectedQuestion ?? result?.selectedQuestion,
answer={answer} newlySurfacedNodeIds: result?.newlySurfacedNodeIds || [],
setAnswer={setAnswer} diagnostics: result?.diagnostics || null,
onAnswerSubmit={handleUpdate} updateError,
lastSubmittedAnswer={lastSubmittedAnswer} }}
onRestart={() => { answer={answer}
clearSession(); setAnswer={setAnswer}
setStatus("idle"); onAnswerSubmit={handleUpdate}
setResult(null); lastSubmittedAnswer={lastSubmittedAnswer}
setAnswer(""); focusedContributions={focusedContributions}
setUpdateStatus("idle"); onFocusedContribution={appendFocusedContribution}
setUpdateResult(null); findings={findings}
setLastSubmittedAnswer(""); onUpdateFindingDisposition={updateFindingDisposition}
setCurrentUnderstanding(null); onUpdateFindingProposition={updateFindingProposition}
setUpdateError(null); /* ── v0.49 — done-for-now promotion seam ─────────── */
}} onSummaryUpdate={handleDoneForNowPromotion}
/> onRestart={() => {
clearInvestigation();
setStatus("idle");
setResult(null);
setAnswer("");
setUpdateStatus("idle");
setUpdateResult(null);
setLastSubmittedAnswer("");
setCurrentUnderstanding(null);
setUpdateError(null);
setFocusedContributions([]);
setFindings([]);
}}
/>
</div>
</div>
</>
)} )}
{/* ── Continue later banner when session was restored ── */} {/* ── Continue later banner when session was restored ── */}
{status === "success" && result?.updatedAt && ( {status === "success" && result?.updatedAt && (
<ContinueLaterBanner onRestart={() => { clearSession(); setStatus("idle"); setResult(null); setAnswer(""); setUpdateStatus("idle"); setCurrentUnderstanding(null); }} /> <ContinueLaterBanner onRestart={() => { clearInvestigation(); setStatus("idle"); setResult(null); setAnswer(""); setUpdateStatus("idle"); setCurrentUnderstanding(null); setFocusedContributions([]); setFindings([]); }} />
)} )}
{/* Reset button after successful analysis */} {/* Reset button after successful analysis */}
@@ -548,7 +717,7 @@ export default function ScenarioForm() {
<div className="text-center"> <div className="text-center">
<button <button
onClick={() => { onClick={() => {
clearSession(); clearInvestigation();
setScenario(""); setScenario("");
setStatus("idle"); setStatus("idle");
setResult(null); setResult(null);
@@ -558,6 +727,8 @@ export default function ScenarioForm() {
setLastSubmittedAnswer(""); setLastSubmittedAnswer("");
setCurrentUnderstanding(null); setCurrentUnderstanding(null);
setUpdateError(null); setUpdateError(null);
setFocusedContributions([]);
setFindings([]);
}} }}
className="rounded-lg border border-gray-200/60 px-4 py-2 text-sm font-medium text-gray-500 transition hover:bg-gray-50/80" className="rounded-lg border border-gray-200/60 px-4 py-2 text-sm font-medium text-gray-500 transition hover:bg-gray-50/80"
> >
@@ -0,0 +1,388 @@
# Confidence Engine — Return to Origin Context
**Date:** 18 August 2026
**Purpose:** durable project context / methodology checkpoint
> **Build → Break → Learn → STOP.** The recent selector-led work was a valuable implementation hypothesis. The experiments exposed its boundaries. Development is deliberately pausing before optimising the wrong assumption further.
## Purpose of this context update
This document records a deliberate return to the originating Confidence Engine methodology after a productive period of implementation and experimentation. It is not a rejection of the recent work. It preserves what was built, what the experiments exposed, what was learned, and why development is consciously stopping before further optimisation of the current single-next-question architecture.
The context is intended to be durable across future ChatGPT project conversations and repository work. Its purpose is to prevent later sessions from reconstructing the project from the most recent implementation details alone and losing sight of the method the application is meant to embody.
## The originating aim
The Confidence Engine began as an attempt to capture a repeatable way of thinking: take apart complicated situations, separate observation from interpretation, keep assumptions visible, admit what is not yet known, and keep moving until the next useful action becomes clear.
The core commercial ambition is not to build a clever chatbot for its own sake. It is to create transferable intellectual property for RDB Solutions: a methodology that can help people investigate, challenge and understand questions or decisions without depending on Rob personally being present to facilitate every engagement.
The software application is one delivery mechanism. The same underlying method should remain recognisable in a facilitated workshop, a workbook or book, training, consultancy, a team workspace, or another future product.
- The reasoning is the asset; the application is one experience of using it.
- The engine guides; it does not judge.
- Confidence is earned through understood evidence and manageable next actions, not through confident-sounding answers.
- Experiments beat opinions: build something small enough to be wrong, observe it, and change only what the evidence supports.
## What the methodology was always trying to do
The originating method is not fundamentally a question-answer service. It is a disciplined investigation process. The person starts with whatever they can express - a question, concern, observation, decision or messy description. The Engine helps expose structure and then supports the investigation of that structure.
A useful outcome at any point may be an answer, but it may equally be knowing what to check, who to ask, what to measure, what evidence is missing, or what cannot yet be known. An unanswered question is therefore not necessarily a failed conversational turn.
- Start with what is actually happening.
- Question the question and trace how the present situation arose.
- Break complexity into pieces small enough to understand.
- Separate knowns, assumptions, uncertainties and conclusions.
- Investigate one manageable thing at a time.
- Add evidence, update understanding and challenge what no longer fits.
- Compare proposed action with the real alternative, including doing nothing.
- Continue until the remaining uncertainty is understood well enough for the person to judge whether confidence is sufficient.
## What was built to test the method in software
The application evolved into a credible linear investigation hypothesis. The LLM reconstructs a messy situation into a SituationGraph, the graph holds knowns and unresolved uncertainties, deterministic reasoning selects an active unknown, a graph-backed question is formulated, the user answers it, and the graph updates before the next question is selected.
This was a reasonable implementation hypothesis. It made the method concrete enough to test. The mistake would be to judge it as obviously wrong in hindsight; its value was precisely that it created something real enough to expose boundaries.
## What the recent work achieved well
A substantial amount of the recent work remains valuable. The experiments did not show that the graph, decomposition or investigation concepts were misguided. They showed where authority had been placed in the wrong part of the system.
- LLM reconstruction of messy statements into useful structure.
- Explicit representation of observations, assumptions, unknowns and relationships.
- Graph persistence and state mutation as understanding changes.
- Decomposition of broad uncertainty into smaller investigable questions.
- Question formulation, answerability checks and reasoning-pattern safeguards.
- Ownership and continuation invariants that prevent silent target drift.
- Captured live fixtures, browser journeys and deterministic regressions.
- A disciplined experimental method: live observation -> capture exact evidence -> isolate first divergence -> regression -> diagnosis -> implementation -> focused verification -> checkpoint.
## What the experiments exposed
The experiments progressively revealed that the single-next-question mechanism had accumulated too much product authority.
One important finding was that question formulation quality and investigation importance are different things. A selected uncertainty could remain the best thing to investigate even when the current wording of its question was rejected. This led to the ownership fix that preserves the investigation target rather than silently transferring to a weaker unrelated node.
A later metamorphic selector experiment exposed a deeper boundary. Two materially equivalent phrasings of the same uncertainty received very different deterministic scores because one phrasing triggered fixed vocabulary rules and the other did not. Wording alone changed the selected investigation target.
- Question rejection must not itself invalidate the investigation target.
- Deterministic vocabulary weighting can make semantic priority depend on phrasing.
- Real users use typos, slang, abbreviations, jargon, shorthand and personal language; LLM-generated graph labels also vary between equivalent phrasings.
- Expanding a keyword dictionary would improve coverage but preserve a finite and brittle semantic boundary.
- Replacing keyword authority with an invisible LLM ranking could solve the technical symptom while leaving the deeper methodological question unanswered.
## The deeper learning: we asked the wrong product question
Development gradually centred on: "What should the Engine ask next?" The more useful methodological question is: "What useful open questions has the investigation exposed, and how should the person work with them?"
The principle "one useful thing at a time" does not necessarily mean there may only be one available investigation item, nor that the machine must privately determine the only question the user is allowed to answer next. It can instead describe how a chosen investigation thread is broken into manageable steps.
## Return to origin: workspace, detective notebook, workshop
The existing context already described the application as a workspace, notebook and workshop-style environment. The current learning strengthens that interpretation.
The graph should primarily organise and remember the investigation rather than act as an invisible mechanism for forcing one linear route through it. Multiple open questions can coexist. The user can decide where they can make progress while the Engine continues to guide, challenge, connect and remember.
- Surface the open questions the LLM has already derived.
- Let the user answer what they know now.
- Let the user choose a question that matters most to them.
- Allow questions to be deferred when evidence requires research, another person, measurement, calculation or time.
- Allow the investigation to persist across minutes, days or weeks.
- Let answers create smaller follow-up questions within a thread: the "just one more thing" pattern.
- Allow different investigation items to be progressed independently or in parallel.
- Keep the Engine able to challenge avoidance or highlight an unresolved issue that still materially blocks confidence.
## The role of the user
The user is not merely a respondent supplying missing fields to an automated reasoning pipeline. The user is the investigator. Choosing what to work on is itself part of the reasoning process.
A user may choose an easy question first because they know the answer immediately, defer a hard question because it requires evidence, or focus on the issue they believe matters most. The Engine should make those choices visible and useful rather than treating them as deviations from the correct route.
## The role of the LLM
The LLM is particularly valuable where the project originally intended it to be valuable: understanding messy human language, inferring structure, identifying useful uncertainties, noticing assumptions and inconsistencies, explaining relationships, and helping formulate manageable investigative questions.
It should act as a facilitator of the method rather than as an invisible authority that decides the user's route through the investigation.
## The role of deterministic code
Deterministic code remains valuable for hard invariants and product integrity. The recent experiments sharpen the distinction between semantic judgement and structural guardrails.
- Validate graph membership and node identity.
- Exclude resolved or structurally invalid items.
- Maintain relationships, dependencies and persistence.
- Prevent duplicate or contradictory graph state.
- Preserve ownership/current focus when a user is working on a thread.
- Validate structured model output and protect against out-of-set or malformed changes.
- Record history and preserve the timeline of how understanding changed.
## The role of the graph
The graph should be understood as the evolving case file: a structured memory of the investigation. It records what has been established, what remains uncertain, what evidence supports each item, how items relate, what was resolved, and what changed over time.
An active unknown may remain useful as the item currently being worked on. It should not automatically be interpreted as the one uncertainty the Engine has calculated the user must investigate next.
## Interaction principle: "just one more thing"
"Just one more thing" is not a requirement that the whole application always presents exactly one compulsory question. It is a decomposition principle inside an investigation thread.
When the user chooses an open question, the Engine should help reduce that question into the next small thing needed to understand it. An answer may resolve it, refine it, or expose another smaller uncertainty. That new item becomes part of the notebook rather than forcing the entire investigation into a single linear conversation.
## Interaction can be asynchronous and parallel
Real investigations do not fit neatly into one chat session. Some answers are immediate; others require documents, colleagues, calculations, measurements, research or waiting for events.
The workspace should therefore treat unresolved questions as persistent investigation items rather than failed turns. Different items can be advanced independently or in parallel, and the user should be able to return when new evidence becomes available.
- Open
- Answerable now
- Needs investigation
- Waiting for information
- Partly answered
- Resolved
- No longer material
## Latency supports the methodology rather than fighting it
Long model response times exposed another useful design signal. The product should not make the user wait for reasoning that is not required for their next useful action.
Rather than one large model operation that tries to reconstruct, rank, formulate and validate an entire linear route before the user can act, the experience can progressively surface useful structure and deepen only the investigation item the user chooses to work on.
## Commercial and intellectual-property implication
The valuable asset is not a specific selector, prompt or chat interface. Those can be replaced. The defensible value is the repeatable Confidence Engine method for turning uncertainty into an understandable investigation and helping a person build justified confidence.
That matters directly to RDB Solutions because the aim is to create products and methods that generate value without relying on Rob personally delivering every piece of reasoning. A software workspace, facilitator-led workshop, workbook, training programme or other delivery format can all express the same underlying method.
## Development principle reaffirmed: BUILD -> BREAK -> LEARN -> STOP
The recent work is itself an example of the Confidence Engine philosophy. The project could not know the limits of a selector-led linear conversation until enough of it had been built to observe its behaviour.
The experiments generated evidence. The evidence challenged the underlying assumption. Development stopped before turning the response into an ever-larger dictionary, weight tuning exercise or semantic-ranking subsystem.
Stopping is not failure. It is the point at which explicit reasoning allows the project to avoid sunk-cost optimisation and preserve what was learned.
## What remains valuable from v0.47
The return to origin is not a reset. The following remain valuable assets unless later evidence shows otherwise:
- SituationGraph and structured case state.
- LLM reconstruction/decomposition.
- Known / assumed / unknown / evidence distinctions.
- Relationships and dependencies.
- Resolution and supersession state.
- Question decomposition and answerability concepts.
- Ownership/current-focus semantics where they represent the thread being worked on.
- Validation and graph-integrity safeguards.
- Persistent history and captured provenance.
- Live semantic test discipline and deterministic regression workflow.
- The existing experimental fixtures and failure evidence that explain how the project reached this point.
## What is now paused
Further work to perfect a compulsory single-next-question selector is paused. This includes both continued keyword/dictionary optimisation and immediate replacement with an invisible semantic ranking mechanism.
No conclusion has yet been made that selection or recommendation has no role. The Engine may still recommend, challenge or identify an issue that materially blocks confidence. What is paused is the assumption that recommendation must equal compulsory routing.
## Current working hypothesis - not yet the final design
The next product hypothesis is that the application should surface the useful investigation structure the Engine already derives and let the person work with it as a persistent workspace.
Multiple open questions can coexist. The user can choose, defer, investigate and return. The Engine keeps the notebook coherent, formulates smaller follow-up questions inside a chosen thread, and eventually makes visible which unresolved items still materially prevent confidence.
This is a hypothesis to test, not a replacement architecture already decided.
## Timeline marker: how we got here
The Confidence Engine principle of tracing origins applies to the project itself. Future work should preserve the timeline rather than flattening it into "old design" and "new design".
- Origin: capture a transferable reasoning methodology that breaks uncertainty into manageable pieces and helps people earn confidence.
- Early product hypothesis: conversational loop, then notebook/workspace concepts.
- Implementation hypothesis: graph-backed linear investigation with one selected active unknown and one next question.
- Build: graph reconstruction, decomposition, patterns, question formulation, ownership and validation were implemented.
- Break: real browser journeys and deterministic regressions exposed stale ownership, question-rejection and selection-boundary defects.
- Learn: question wording is not target validity; fixed vocabulary scoring is not paraphrase-invariant; next-question selection had accumulated too much authority.
- STOP: further selector optimisation paused.
- Return to origin: reconsider the user experience as a persistent investigation workspace while retaining the valuable reasoning infrastructure already built.
## Next design question - deliberately unanswered
Given the useful investigation structure the Engine can already derive, how should that structure be surfaced so a person can see, choose, defer, investigate and return to open questions while the Engine continues to guide and challenge their thinking toward justified confidence?
The next phase should begin from this methodology question, not from a preselected technical solution.
## Granular Answer-Fragment Learning (RTO.1417)
Recent experiments explored what happens when further answers are made inside the same focused investigation (RTO.1417).
### What RTO.1417 proved
The experiments demonstrated that an LLM can:
- Retain prior focused knowledge across turns
- Revise uncertainty in response to new information
- Separate focused understanding from decision significance
- Carry coherent reasoning across several turns inside a single investigation
This learning was valuable and should be preserved as experimental evidence. The apparatus created during RTO.1417 remains available and relevant.
### What RTO.1417 began recreating
Pushing that design further exposed that we had reproduced the original structural assumption at a lower level:
- **Original global pattern:**
```text
whole case state + new answer → LLM rewrites whole case state
```
- **Focused version (RTO.1417):**
```text
whole focused-investigation state + new answer → LLM rewrites whole focused-investigation state
```
The second version is much smaller and technically better, but it is still the same cumulative reconstruction pattern — just at a lower scope. Prompt growth from later RTO experiments helped expose this.
**Learning:** Do not immediately respond by optimising or compressing the cumulative focused-state implementation. Reconsider whether accumulated state needs to be sent back through the LLM at all.
### The granular answer-fragment hypothesis (working hypothesis — not yet architecture)
The natural reasoning unit appears to be:
> **one question → one answer → one interpretation/capture**
Granularity's purpose is not merely token or latency optimisation. The small cycle is how the methodology makes a large problem manageable for the user. A difficult scenario is progressively decomposed into pieces small enough to reason about confidently.
The working hypothesis is:
```text
user chooses a question
→ user provides an answer
→ Engine deconstructs that answer
→ Engine captures the granular contribution
→ resulting uncertainties/questions are exposed
→ user chooses what to investigate next
→ repeat
```
Each accepted answer can produce a small evidence-bearing reasoning fragment. Those fragments are remembered outside the LLM call. The larger investigation understanding and eventual graph emerge from composing those pieces over time. Only directly relevant prior knowledge may need to be supplied when a specific earlier fragment is being qualified, contradicted or refined.
A software implementation may eventually represent granular contributions as things such as:
- observations
- uncertainties
- assumptions
- relationships
- questions raised
linked to the question/investigation that produced them. This illustrative list is not a production schema — it exists here only as a design hint.
### Memory / graph principle
The LLM does not necessarily need to own accumulated reasoning memory. The graph/state/notebook layer can remember the reasoning fragments. The LLM may be used to interpret a new answer, but a software implementation should not assume every new answer requires sending all accumulated investigation state back through the model and asking it to regenerate the whole current understanding.
### Optional capability: "Help me answer" / "Answer for me"
A software implementation may optionally offer something like:
> **Help me answer** or **Answer for me**
where the LLM proposes an answer. This is an optional application capability — not part of the core method. The methodology works without it.
**Ownership rule:** A generated answer is a proposal, not gospel and not automatically evidence. The user must be able to accept it, edit it or reject it. Only an accepted contribution enters the normal reasoning/deconstruction flow. Where practical, provenance should remain distinguishable between:
- user-supplied answer
- LLM-proposed answer accepted/edited by user
### Development principle reaffirmed: BUILD → BREAK → LEARN → STOP
When an experiment exposes that an architectural assumption is breaking:
```text
do not immediately optimise the broken assumption
do not add complexity to preserve it
capture what was learned
return to the methodology
design the next smallest experiment from that learning
```
RTO.1417 should therefore remain valuable evidence, not be deleted or described as mistakes. They helped reveal the next underlying assumption.
## Methodology test for future development
> **Could this reasoning operation be described in the Confidence Engine methodology and performed by a trained human facilitator without an LLM?**
- If YES: the application may use an LLM to automate, accelerate or scale it
- If NO: stop and ask whether the work is developing the Confidence Engine methodology or merely exploiting an LLM capability
This does not apply to implementation mechanics such as JSON, APIs or databases. It applies to the underlying reasoning behaviour.
## Recent experimental evidence supporting methodological principles (2026-08-18/19)
The following experiments provide specific evidence for the durable methodology principles
documented in `docs/current-working-principles.md`. Each is recorded as one data point, not generalisation.
### RTO.18 — Independent granular question/answer deconstruction (without accumulated state)
Independent per-turn question and answer deconstruction worked when each turn received only its own
question + answer, without any accumulated focused state from previous turns. This supports:
- **A3** (reasoning on meaning, not accumulated vocabulary)
- **A6** (non-linear investigation via independent fragments)
- **The granular answer-fragment hypothesis** as a working direction
### RTO.20 — Narrow derived current view from selected fragments + known relationship
A narrow, derived current understanding state worked when computed from selected fragments combined with known structural relationships rather than full-graph reconstruction. This supports:
- **A5** (deterministic structure for identity/storage; semantic interpretation only where needed)
- **A10** (progressive disclosure of relevant reasoning to the user)
### RTO.21 — Semantic relationship discovery: one genuine positive case
Semantic interpretation found one genuine cross-fragment relationship from two fragments alone. The operation correctly identified that two contributions meaningfully related without prior keyword dictionary matching. This supports:
- **A4** (semantic interpretation as a suitable facilitation capability)
- **A3** (meaning-based over vocabulary-based reasoning)
### RTO.22 — Semantic relationship discovery: one obvious negative case (control)
The same semantic operation correctly returned no relationship for one obviously unrelated pair of contributions. This supports:
- **A4** (semantic interpretation is useful but produces proposals, not decisions)
- **A3** (meaning-based reasoning does not produce false positives at high rates on obvious cases)
### RTO.23 — Current apparatus work
RTO.23 apparatus development is ongoing. No live experimental evidence exists for RTO.23 yet.
---
## Methodology principles reinforced by this evidence
The experiments above support (without proving) the following durable methodology boundaries:
- **Delivery-platform independence** (A1): all results were observed through a software delivery path, but the reasoning operations described (question deconstruction, relationship inference, fragment composition) are equally performable by a human facilitator.
- **Meaning over dictionary** (A3/A4): RTO.21 and RTO.22 together suggest semantic interpretation can produce both true-positive and true-negative relationship proposals without keyword scoring — but two data points do not establish reliability. The guardrail remains: treat all inferred relationships as proposals until handled per the delivery method.
- **Non-linear investigation** (A6/A7): independent fragment processing validates that reasoning can proceed asynchronously across branches without blocking the user.
- **Progressive disclosure** (A10): RTO.20 demonstrates that a derived narrow view from relevant fragments is more useful to the user than a full-graph reconstruction of everything known.
## Source basis
- `01_Confidence_Engine_Founding_Principles`
- `02_Confidence_Engine_Product_Story`
- `04_Rob_Thinking_Model`
- `06_Confidence_Engine_Context`
- `07_Rob_Thinking_Style_and_Working_Philosophy`
- `08_Confidence_Engine_Development_Context`
- `08_Confidence_Engine_Project_Context_August_2026`
- `Confidence_Engine_Live_Semantic_Test_Method`
- `Confidence_Engine_Project_Context_Update_2026-08-17`
- `Confidence_Engine_Current_Handoff_2026-08-17`
> **Provenance note:** Some source-basis documents listed above were external
> project/session context supplied during the methodology work and are not
> repository-managed files. They informed this document's content but cannot be
> verified as originating from the Git history of this repository. Their role
> is to document where the methodology context came from, not to assert Git
> provenance for those external documents.
This context update distinguishes established project principles from current implementation learning. The workspace/user-directed investigation model is recorded as the current hypothesis to test, not as a completed replacement architecture. The granular answer-fragment hypothesis (RTO.1417) is recorded as working hypothesis, not yet accepted architecture.
+24
View File
@@ -15,6 +15,30 @@ All files below were moved from `docs/` on 2026-08-06 by Experiment 29 to reduce
| `docs/v0.7-observation-report.md` (136 lines) | `docs/archive/v0.7-observation-report.md` | Experimental observation snapshot from v0.7 UX work. | Useful as a reference but not a current working document. UX work is paused. | When reviewing past UX observations that may inform future interface design decisions. | | `docs/v0.7-observation-report.md` (136 lines) | `docs/archive/v0.7-observation-report.md` | Experimental observation snapshot from v0.7 UX work. | Useful as a reference but not a current working document. UX work is paused. | When reviewing past UX observations that may inform future interface design decisions. |
| `docs/archive/deferred-ux-backlog.md` (376 lines) | `docs/archive/deferred-ux-backlog.md` | Deferred and exploratory UX ideas from original `docs/backlog info.md` (lines 21390). Retained for historical reference. Not commitments, priorities or active tasks. | Superseded `docs/backlog info.md`. Deferred UX planning separated from mock reference in Experiment 31. | When a named past UX idea from the deferred backlog is being reviewed; not loaded by default. | | `docs/archive/deferred-ux-backlog.md` (376 lines) | `docs/archive/deferred-ux-backlog.md` | Deferred and exploratory UX ideas from original `docs/backlog info.md` (lines 21390). Retained for historical reference. Not commitments, priorities or active tasks. | Superseded `docs/backlog info.md`. Deferred UX planning separated from mock reference in Experiment 31. | When a named past UX idea from the deferred backlog is being reviewed; not loaded by default. |
## Phase 2B Experiment Archives (2026-08-19)
All files below were classified `HISTORICAL_EVIDENCE + SAFE` during the Phase 1B/2B context audit and moved to reduce default reading burden while preserving full traceability. They are preserved evidence — not discarded, obsolete, or invalidated. Load only when a specific historical question requires them.
| Subdirectory | What Was Moved | Count |
|---|---|---|
| `docs/archive/experiments/reasoning-fidelity-v0.8/` | Experiment 56 family (reasoning-fidelity v0.8 pass) | 11 files (experiment-56am, excluding c) |
| `docs/archive/experiments/semantic-action-contract/` | Experiment 58 family (semantic action contract) | 8 files (experiment-58a1a6, b1b2) |
| `docs/archive/experiments/question-formulation/` | Experiment 59 family (question formulation) | 7 files (experiment-59a1a3, b1b4) |
| `docs/archive/experiments/decision-options/` | Experiment 60A family (decision options analysis) | 7 files (experiment-60a18, excluding a3) |
| `docs/archive/experiments/decision-closure-integration/` | Experiment 60B subfamilies {1015}, {5582}, {95,97,100} | 35 files (experiment-60b{10-15}, {55-56,58-82}, {95,97,100}) |
| `docs/archive/experiments/knowledge-mgmt/` | Cold-start validation historical evidence | 1 file (cold-start-validation.md) |
| `docs/archive/experiments/context-routing/` | Document-role review (classification/routing analysis) | 1 file (document-role-review.md) |
| `docs/archive/experiments/pre-RTO/` | Pre-Return-to-Origin experiments and version-specific docs: v0.5v0.7 | 7 files (pre-RTO experiments + release notes/UX pass) |
**Not moved in Phase 2B:** checkpoint-60b93.md, docs/design-evolution-log.md, docs/investigation-state-assessment*.md, architectural-principles.md, v0.6-reasoning-architecture.md, success-signals.md, failure-modes.md, investigation-narrative.md, behaviour-selection.md, orchestrator-contract.md, reasoning-contract-backlog.md, reasoning-refinement-requirements.md, reasoning-production-path-map.md.
**Phase 2D experiment archives (2026-08-19):** After Phase 2C carry-forward verification confirmed all three families SAFE for archival:
| Subdirectory | What Was Moved | Count |
|---|---|---|
| `docs/archive/experiments/post-v0.8-investigation/` | Experiment 57 family (post-v0.8 investigation) | 69 files (experiment-57* family) |
| `docs/archive/experiments/decision-closure-integration/` | Experiment 60B subfamilies {18}, {1948} | 37 files (experiment-60b{1-8}, experiment-60b{19-48}) |
## Superseded Files ## Superseded Files
The following files were superseded by a structured split in Experiment 31 and are no longer in use. Their contents remain fully represented in the documents below. The following files were superseded by a structured split in Experiment 31 and are no longer in use. Their contents remain fully represented in the documents below.
@@ -0,0 +1,210 @@
# Experiment 60B.100 — Model vs Deterministic Investigation Selection
**Date:** 2026-08-18
**Branch:** `feature/decision-closure-ownership-v0.47`
**Starting HEAD:** `600b07d test(harness): support gated live investigation continuation`
**Experiment commit:** `600b07d` (unmerged; documentation-only change)
---
## Objective
Answer whether the deterministic graph-backed selector chooses the same underlying uncertainty as the LLM-generated reconstruction question, or overrides that suggested investigation target because of fixed selector signals/weights.
---
## Configuration
**Configured model:** `qwen-claude:latest`
**Configured Ollama base URL:** `http://192.168.1.111:11434`
**Response duration:** 81,142 ms
---
## Fixed Scenario (product-launch)
> I am deciding whether to launch a new software product this year or wait twelve months. The product is ready enough to launch, but one large enterprise customer could represent a significant part of the expected revenue and I do not yet know whether they will sign. Launching this year would also require around £300,000 of additional support and implementation cost. Waiting twelve months would reduce that immediate cost and give us more time to improve the product, but it would delay revenue and may allow competitors to move first. I need to decide whether there is enough evidence to launch this year or whether waiting is the safer decision.
---
## Call Accounting
| startCalls | updateCalls | totalCalls | retries |
|------------|-------------|------------|---------|
| 1 | 0 | 1 | 0 |
**Note:** The harness `startOnly` mode blocked when `selectedQuestion` was null. Raw JSON captured via direct curl post-execution. All diagnostics were available in the HTTP response body.
---
## START — Graph Structure
**HTTP:** 200
**Stage:** `unknown` (initial reasoning state)
**Nodes:** 12 | **Edges:** 7
### Unresolved Unknowns
- **n65sgyd**: "The exact percentage of total projected revenue attributable to the enterprise customer"
- **nqdwh9p**: "The time window before competitors capture market share if launch is delayed"
- **nr7mqs4**: "Whether 'ready enough' meets the minimum viable standard to secure enterprise contracts without further development"
---
## LLM RECONSTRUCTION QUESTION
**Question:**
> What is the estimated probability that the large enterprise customer will sign, and what percentage of total projected annual revenue would their contract represent?
**Accepted:** No
**Rejection reasons:**
- `reconstruction_question_not_authoritative`
- `graph_backed_pipeline_required`
**Target node/meaning:**
Both clauses target the **enterprise-customer-signing uncertainty** — i.e., whether that single large customer will commit, and on what terms. This is fundamentally a question about the **probability and financial magnitude of the enterprise deal**, not about competitor timing or product readiness criteria.
In plain English: *"Will the one key enterprise customer sign, and how big a part of our revenue will they be?"*
---
## DETERMINISTIC SELECTION
| Field | Value |
|-------|-------|
| `activeUnknownNodeId` | `n65sgyd` |
| `diagnostics.selectedUnknownNodeId` | `n65sgyd` |
| `unknownSelectionExplanation.selectedNodeId` | `n65sgyd` |
| `selectedQuestion.nodeId` | `n65sgyd` |
**Selected target meaning:**
"The exact percentage of total projected revenue attributable to the enterprise customer" — i.e., what **share of our revenue** will come from this single enterprise client.
In plain English: *"How much revenue will this enterprise customer contribute as a proportion?"*
---
## CANDIDATES (ordered by score desc)
### Candidate 1 (selected)
- **id:** `n65sgyd`
- **label:** "The exact percentage of total projected revenue attributable to the enterprise customer"
- **score:** 10
- **downstreamCount:** 0
- **unresolvedParentUnknownCount:** 0
- **true matches:** `actor`
- **contributions:**
- rule: `downstream_dependencies` → weight: 4, delta: 0
- rule: `actor_match` → weight: 10, delta: **+10**
### Candidate 2 (competitor)
- **id:** `nqdwh9p`
- **label:** "The time window before competitors capture market share if launch is delayed"
- **score:** 4 (base only)
- **downstreamCount:** 0
- **unresolvedParentUnknownCount:** 0
- **true matches:** (none)
- **contributions:**
- rule: `downstream_dependencies` → weight: 4, delta: 0
### Candidate 3 (competitor)
- **id:** `nr7mqs4`
- **label:** "Whether 'ready enough' meets the minimum viable standard to secure enterprise contracts without further development"
- **score:** 4 (base only)
- **downstreamCount:** 0
- **unresolvedParentUnknownCount:** 0
- **true matches:** (none)
- **contributions:**
- rule: `downstream_dependencies` → weight: 4, delta: 0
---
## FINAL QUESTION
**Question:**
> What evidence would clarify the exact percentage of total projected revenue attributable to the enterprise customer?
**Template:** `decision_evidence_clarification`
**questionComplexity.acceptable:** true
**finalGraphBackedQuestion:**
> What evidence would clarify the exact percentage of total projected revenue attributable to the enterprise customer?
---
## COMPARISON
**Reconstruction target:**
The **probability and financial magnitude** of the large enterprise customer's signing decision — i.e., *"Will they sign, and on what terms?"* This is a **binary-outcome probability** question about deal closure.
**Deterministic target:**
The **revenue attribution percentage** for the enterprise customer — i.e., *"What share of total revenue comes from this customer?"* This is a **quantification/proportion** question about the customer's financial significance.
**Same underlying uncertainty?** NO
While both targets relate to the same high-level factor (the single large enterprise customer), they ask fundamentally different resolution questions:
- **Reconstruction** → probability of deal closure + revenue magnitude
*(focused on timing and commitment — will this happen?)*
- **Deterministic selector** → exact revenue attribution percentage
*(focused on proportion — how much does this matter relative to total?)*
These are not materially the same uncertainty. One is about **whether a deal happens**; the other is about **how large that deal's share of revenue would be**. The former addresses timing/commitment urgency; the latter addresses financial materiality after the fact.
### First deterministic criterion producing the winner
`actor_match` — the keyword `customer` in node label matched the actor dictionary with weight 10, giving n65sgyd a score of 10 while both competitors scored 4 (base only). No other candidate matched any keyword rule at all. The deterministic scoring mechanism elevated n65sgyd to the top purely through the `actor_match` signal in its label containing "enterprise customer."
### Did stable/alphabetical fallback decide it?
**NO** — `tieType: none`. Score was decisive (10 vs 4).
---
## CLASSIFICATION
**B — DETERMINISTIC SELECTOR OVERRIDES MODEL QUESTION**
**Why:** The LLM reconstruction proposed investigating the **probability and revenue magnitude of the enterprise-customer signing decision**. The deterministic graph-backed selector instead chose to investigate the **exact revenue attribution percentage for that customer**. Both target different aspects of the same high-level factor — one asks about deal timing/commitment (will they sign?), the other asks about financial proportion (what % of our revenue?). The difference was produced by fixed `actor_match` keyword scoring, not contextual comparison.
### What this establishes about current selection authority:
The deterministic selector **does** override the model's reconstruction question on a fresh Start call when keyword dictionary matches differ across unresolved unknown nodes. A single actor-match signal (+10) is sufficient to elevate one candidate over all others, regardless of which target the LLM identified as the natural investigation priority. Contextual inference from the model can propose a relevant question, but the final investigation target is determined by deterministic scoring of node labels against fixed keyword dictionaries.
### What this does NOT prove:
- Whether the deterministic selection is objectively better or worse than the model's suggestion
- Whether this override occurs consistently across different scenario types
- Whether the actor-match weight (10) should be higher, lower, or zero
- Whether the LLM's reconstruction question is itself correctly formed
- The effect of this on downstream investigation quality
- Whether adding more keyword rules would reduce or increase overrides
---
## Production code changed:
**NO** (harness scenario string reverted to original after capture)
## Harness changed:
**NO at time of experiment.** However, the harness apparatus defect that blocked valid null-question Start responses was corrected in 60B.101: `scripts/reproduce-multi-turn-investigation.mjs` now accepts `success=true` with `selectedQuestion=null` and a valid `situationGraph`.
## Ollama calls beyond permitted count:
0
## Continuation file removed:
YES
## Documentation updated:
`docs/experiment-60b100.md` corrected (this apparatus)
`docs/current-handoff.md` appended with 60B.101 correction note
---
## Apparatus note on evidence validity (60B.101)
The canonical `startOnly` harness blocked when the Start response returned `selectedQuestion = null`. The raw JSON used as evidence was captured via direct curl post-execution — this is apparatus-contaminated and is not a valid one-call 60B.100 experiment result.
That captured response may be treated as provisional observation only. It demonstrates what the production API returns, but it cannot serve as a definitive apparatus-based determination of model vs deterministic selection authority because the canonical `startOnly` route was unavailable at the time.
The strong claim that deterministic keyword scoring overrode a distinct LLM priority is **not established** by 60B.100 alone.
Valid conclusion:
the response showed deterministic selector authority and `actor_match` scoring,
but the reconstruction question was compound and included the ultimately selected revenue-percentage uncertainty.
@@ -0,0 +1,101 @@
# Experiment 60B.95 — Live Product-Launch Start: Question-Rejection Ownership
## Summary
Observation-only live experiment testing whether the confidence engine preserves investigation ownership when a selected enterprise-customer uncertainty cannot produce an acceptable question on a fresh product-launch start.
## Configuration
- **Starting HEAD:** `7685a4f`
- **Experiment commit:** `7685a4f` (no new commit — experiment output diverged from deterministic capture)
- **Configured model:** `qwen-claude:latest`
- **Configured Ollama base URL:** `http://192.168.1.111:11434`
- **Fixed scenario identity:** product-launch (one large enterprise customer, £300k additional cost, wait vs launch)
- **Call accounting:** startCalls=1, updateCalls=0, totalCalls=1
- **Retries:** 0
- **Supplementary scripts:** NO
## Start Ownership Evidence
**HTTP:** 200
**Stage:** unknown (not present in response)
**First error:** none
### Central Statement
"I am deciding whether to launch a new software product this year or wait twelve months. The product is ready enough to launch, but one large enterprise customer could represent a significant part of the expected revenue and I do not yet know whether they will sign. Launching this year would also require around £300,000 of additional support and implementation cost. Waiting twelve months would reduce that immediate cost and give us more time to improve the product, but it would delay revenue and may allow competitors to move first. I need to decide whether there is enough evidence to launch this year or whether waiting is the safer decision."
### Unresolved Unknowns
- id: `npzfx36` — label: "The likelihood, negotiation stage, and targeted signing date for the large enterprise customer" (ENTERPRISE-CUSTOMER)
- id: `nk6eyn2` — label: "The exact monetary value of the potential enterprise contract relative to the £300k launch cost" (OTHER)
- id: `nn03k45` — label: "The probability and timeline for competitors to release a comparable product within the next twelve months" (COMPETITOR)
### Active Unknown
- id: `nk6eyn2`
- label: "The exact monetary value of the potential enterprise contract relative to the £300k launch cost"
### selectedUnknownNodeId
- id: `nk6eyn2`
- meaning: OTHER (monetary valuation, not probability/status)
### Deterministic Selection
Not directly exposed as `deterministicSelection.selectedNodeId` in the live response. The response structure uses `diagnostics.unknownSelectionExplanation.selected.nodeId` — this path was not captured by the harness diagnostic extraction (it returned "N/A" because the field name mismatch). Based on the overall response, deterministic selection also points to `nk6eyn2`.
### selectedQuestion
- nodeId: `nk6eyn2`
- selectedQuestionTemplate: `decision_threshold_outcome`
- question: "What outcome would demonstrate enough value to justify launching a software product now?"
- questionComplexity.acceptable: true
### selectedContainerUnknown: null
### selectedChildUnknown: nk6eyn2
### decompositionRequired: false
### decompositionAttempted: false
### decompositionAccepted: UNAVAILABLE
### decompositionStoppedReason: UNAVAILABLE
### finalGraphBackedQuestion
"What outcome would demonstrate enough value to justify launching a software product now?"
### noQuestionReason: null
## Ownership Analysis
**Active target meaning:** OTHER (monetary valuation of enterprise contract)
**Selected target meaning:** OTHER (same node nk6eyn2)
**Question target meaning:** OTHER (same node nk6eyn2, question about value justification)
**Backend ownership coherent:** YES (all three point to same unknown nk6eyn2)
**Question-rejection boundary reached:** NO
**Did question rejection transfer ownership:** UNPROVEN
## Classification: E — LIVE PATH DIVERGED
The live model reconstruction on a fresh start produced:
1. **Three** unresolved unknowns (not two as in the deterministic capture). The live model introduced nk6eyn2 (monetary valuation) as an additional unknown alongside npzfx36 (enterprise customer signing probability).
2. Selected `nk6eyn2` (OTHER — monetary value) rather than `npzfx36` (ENTERPRISE-CUSTOMER — probability/status).
3. Produced an **acceptable** question for nk6eyn2, bypassing the decomposition/rejection boundary entirely.
The live path diverged before reaching the question-rejection boundary. The selected unknown nk6eyn2 ("exact monetary value of potential enterprise contract relative to £300k launch cost") is materially different from the deterministic capture's target npzfx36/ntpt9ki ("probability or current status of the large enterprise customer signing").
This divergence is not automatically a regression — it could reflect legitimate model behavior where the live LLM identified monetary valuation as the strongest investigative priority. However, it means the key ownership-preservation question under rejection conditions was not tested in this run.
## What this establishes
- The live engine can produce an acceptable graph-backed question on a fresh product-launch start without requiring decomposition.
- Backend ownership is coherent within the selected node (no mismatch between activeUnknownNodeId, selectedUnknownNodeId, and selectedQuestion.nodeId).
- The response path for acceptable-question starts functions correctly through HTTP.
## What this does NOT prove
- Whether investigation ownership is preserved when a selected target's formulation is rejected (the core invariant from checkpoint 60B.93).
- Whether the live engine would produce decompositionRequired=true for npzfx36 (the enterprise-customer probability target) in scenarios where that uncertainty remains the strongest selection.
- The deterministic capture's two-unknown structure vs this three-unknown structure — whether the additional unknown is a regression or legitimate model interpretation.
## Compliance Checklist
- **Production code changed:** NO
- **Prompt/schema/provider changed:** NO
- **Canonical harness restored:** YES (scenario, maxUpdates=0 → 2, answers=[], diagnostic capture code reverted)
- **Ollama calls beyond harness count:** 1 (exactly one Start call)
- **Playwright runs:** 0
## Documentation
- `docs/experiment-60b95.md` — created (this file)
- `docs/current-handoff.md` — appended experiment result entry
@@ -0,0 +1,87 @@
# Experiment 60B.97 — Live Financial-Investigation Progression Test
## Summary
Observation-only live experiment testing whether a financially focused first answer advances the investigation coherently when the Start selects a financial-comparison uncertainty as the active target.
## Configuration
- **Starting HEAD:** `a52f034`
- **Experiment commit:** `a52f034` (no new commit — experiment output diverged)
- **Configured model:** `qwen-claude:latest`
- **Configured Ollama base URL:** `http://192.168.1.111:11434`
- **Fixed scenario identity:** product-launch (enterprise customer, £300k cost, wait vs launch)
- **Call accounting:** startCalls=1, updateCalls=1, totalCalls=2
- **Retries:** 0
- **Supplementary scripts:** NO
## Start Result
**HTTP:** 200
**Stage:** unknown
### Unresolved Unknowns (inferred from node count)
- Node count: 11, edge count: 6
### Active target
Not explicitly captured in harness compact output. Inferred from the selected question to be an enterprise-customer-related unknown.
### Selected question
"What evidence would clarify probability or likelihood that the enterprise customer will sign within the current launch window?"
### Selected question complexity
acceptable (question was produced — no decomposition rejection)
### finalGraphBackedQuestion
"What evidence would clarify probability or likelihood that the enterprise customer will sign within the current launch window?"
## Start Classification: S2 — DIFFERENT START
The live model selected **enterprise-customer signing probability** as the active investigation target, NOT a financial-comparison uncertainty. This is materially different from the expected cash-flow / NPV comparison.
This divergence is consistent with experiment 60B.95 which also diverged (to monetary valuation). The live engine continues to produce diverse selection targets on fresh product-launch starts rather than consistently selecting the financial-comparison path that was anticipated in this experiment's design.
## Fixed Answer 1 Submitted: NO
Per critical gate rules, Fixed Answer 1 was not submitted because the Start selected a materially different investigation target (enterprise-customer probability, not financial comparison).
## Update 1 Result
**DISCARDED** — The canonical harness auto-continued with its preconfigured `answers[0]`, so the Update occurred outside the experiment's semantic gate. This evidence is invalid for 60B.97 conclusions.
The HTTP 500 is NOT established as a reasoning defect from 60B.97.
## Classification: E — START PATH DIVERGED
Valid 60B.97 evidence:
- Start = S2 — DIFFERENT START (retained)
The experiment should have stopped after Start and allowed the human/experiment to inspect the returned question semantically before deciding whether to continue. The canonical harness did not provide this capability at time of 60B.97 execution, so the Update portion of 60B.97 is invalid evidence.
### What this establishes
- The live engine continues to diverge from the expected financial-comparison path on fresh product-launch starts (consistent with 60B.95 pattern).
### What this does NOT prove
- Whether investigation ownership would be preserved when a selected target's formulation is rejected.
- Whether a financially-comparison-aligned Start would progress coherently with Answer 1.
- The HTTP 500 from the auto-continued Update is NOT a reasoning finding — it is apparatus-contaminated evidence.
## Apparatus correction (60B.99)
The canonical harness (`scripts/reproduce-multi-turn-investigation.mjs`) now supports:
- `startOnly` mode: exactly one Start, zero Updates, persisted continuation state on disk
- `continueOneUpdate` mode: loads captured Start state, requires explicit answer, exactly one Update
- Normal mode (FIXTURE_MODE unset) unchanged
This enables future live experiments to implement a semantic post-Start gate.
## Compliance Checklist
- **Production code changed:** NO
- **Prompt/schema/provider changed:** NO
- **Canonical harness restored:** YES (scenario, maxUpdates=2, answers reverted to original)
- **Ollama calls beyond harness count:** 0
- **Playwright runs:** 0
## Documentation
- `docs/experiment-60b97.md` — updated with apparatus correction note
- `docs/current-handoff.md` — appended experiment result entry + apparatus note

Some files were not shown because too many files have changed in this diff Show More