Commit Graph
77 Commits
Author SHA1 Message Date
robbond 437aadc587 fix(reasoning): honor explicit whether propositions 2026-08-14 07:01:23 +01:00
robbond d26bbfebdf fix(reasoning): support uncertainty-over propositions 2026-08-14 06:31:33 +01:00
robbond 1f361e2d93 fix(reasoning): preserve explicit uncertainty propositions 2026-08-14 06:16:14 +01:00
robbond f955b875af fix(reasoning): clean proposition question formulation 2026-08-13 17:45:28 +01:00
robbond 8cca70774c fix(reasoning): narrow decision audience question routing 2026-08-13 16:58:32 +01:00
robbond d871a8c5c4 fix(reasoning): scope structural context admission 2026-08-13 12:49:42 +01:00
robbond 54bc48342b fix(reasoning): preserve ready material question target 2026-08-13 09:36:10 +01:00
robbond 5ce5e7349b feat(reasoning): add decision materiality rule 2026-08-13 07:24:16 +01:00
robbond 57c9f2205e feat: add 'option' node kind and 'contained_in' edge — 60A.3
Implementation of Candidate B (unknown+option) from decision architecture
design in 60A.2. Adds two new primitives to the situation graph:

Schema (lib/graph/schema.js):
- SituationKind.option — a choice available within a decision context
- SituationRelationship.contained_in — links option → its parent unknown context

Prompt rules (lib/graph/prompt-builder.js):
- Section added: Decision Option Structure Rules with 5 numbered instructions
  governing when/how to create option nodes, link them via contained_in,
  attach consequences to specific options, and handle do-nothing alternatives.
  Explicitly forbids alternative_to edges and is_baseline/is_default flags.

Tests (446 new lines):
- schema.test.js: +300 — enum completeness updates, option kind validation,
  contained_in edge validation, native two-option graph fixture (~25 new tests)
- prompt-builder.test.js: +133 — focused rules verification for all 5 rule points,
  negative checks (no relocation/savings/example-specific wording, no alternative_to
  requirement, baseline flag prohibition context)

No production code paths affected beyond the two enum additions; existing node and
edge kinds remain unchanged. No Ollama calls, no live API calls.
2026-08-12 19:39:58 +01:00
robbond fa42a2643a fix(graph): preserve grammar for question-like unknown labels 2026-08-12 15:02:56 +01:00
robbond bd3c7d59ae fix(graph): make structural action contract authoritative 2026-08-12 08:15:41 +01:00
robbond 6aef806845 feat(graph): add structuralActionRequired contract (57J.67)
- Add structuralActionRequired field to graphUpdateSchema (optional boolean nullable)
- Validate declaration consistency in validateGraphUpdate():
  - true requires meaningful mutation (addedNodes/updatedNodes/addedEdges)
  - false permits intentional no-op when userSupportedMeaning populated
  - null/absent with meaning → reject
  - true/false mismatch on output shape → reject
  - preserve legacy no-op guard for non-contract paths
- Update prompt-builder: add field to required list, insert contract section between rules and Additional Guidance with two mandatory sentences
- 50 new tests: schema validation (4), prompt builder content checks (10), utils contract matrix (10), plus 26 existing suite migrations

All 197 graph tests pass.
2026-08-12 07:26:26 +01:00
robbond bf1f219256 prompt: require candidate question for new unknowns 2026-08-11 18:51:22 +01:00
robbond b8e6745c15 prompt: distinguish uncertainty identity from topical overlap 2026-08-11 17:47:12 +01:00
robbond 7d06cd3c47 reasoning: use structured semantic fidelity contract 2026-08-11 16:45:00 +01:00
robbond a5dd9d3f1a prompt: add existing-first uncertainty fallback
Add one explicit action-order rule in Additional Guidance for when
rule #6 applies to explicitly unresolved uncertainty:

1. First check whether an existing unresolved node already represents
   the same uncertainty.
2. If so, update/refine that existing structure rather than creating
   a duplicate.
3. If no such node exists, add a new unknown that directly represents
   the unresolved uncertainty.
4. Do not use an edge alone to represent a previously unrepresented
   uncertainty.

14 focused prompt tests verify: existing-first ordering, reuse path,
fallback-to-add, related-node-insufficient, edge-only-prohibited,
possibleInference separation, resolution path preserved, duplicate
contract preserved, scope uncertainty-only, fidelity/traceability
preserved, noop validator untouched, no semantic classifier added.
2026-08-11 14:12:42 +01:00
robbond 359ccc4ba9 prompt: remove semantic-only mutation conflict 2026-08-11 13:22:29 +01:00
robbond 6adcd817e1 reasoning: require structural progress for supported meaning 2026-08-11 12:32:03 +01:00
robbond 0348921542 experiment: add rejected proposal diagnostics to failure path
Adds rejectedProposalSnapshot to orchestrator diagnostics for
proposal_compatibility rejections — exposing answerMeaning (userSupportedMeaning,
possibleInference), addedNodes structural fields, addedEdges structural fields,
updatedNodes summaries, and resolvedUnknownNodeIds. Diagnostic evidence only;
does not alter validation, mutation, or error messages. Stage-gated to
proposal_compatibility only.
2026-08-11 08:33:36 +01:00
robbond 2e20d30890 correction: delegate hasNodeLevelUserSupport to rawAnswerSupportsUnclassifiedMeaning
v0.15 duplicated the overlap helper logic in hasNodeLevelUserSupport with
reversed argument orientation (unknownText as source, userSupportedMeaning
as candidate) compared to rawAnswerSupportsUnclassifiedMeaning (USM as
source, unknownText as candidate). This produced different accept/reject
outcomes when the two texts have very different token counts.

The fix replaces the independent reconstruction with a single call to the
canonical helper, ensuring node-level and answer-meaning alignment use
identical semantics. Four boundary regression tests verify:

- Boundary A: overlap ratio < 0.4 but >= 3 shared tokens → accept (token rule)
- Boundary B: short candidate / long source accepted via structural linkage
- Boundary B control: unrelated unknown rejected with no structural edge
- Boundary C: ratio exactly at 0.4 threshold accepts via ratio rule
2026-08-10 20:09:39 +01:00
robbond 9e869cbcb8 reasoning: admit verified user-supported unknowns without provenance edges 2026-08-10 19:27:54 +01:00
robbond 0d15dd1f42 Revert "reasoning: require corroboration for conjunction compoundness"
This reverts commit 60048a5636.
2026-08-10 15:07:30 +01:00
robbond 60048a5636 reasoning: require corroboration for conjunction compoundness 2026-08-10 14:53:57 +01:00
robbond 4c5666dfb3 reasoning: suppress explanation question without relationship structure 2026-08-10 10:17:35 +01:00
robbond 69efc5d1b9 reasoning: ground unclassified answers without category expansion 2026-08-10 08:20:00 +01:00
robbond 7e4c506614 reasoning: prevent unsupported comparison decomposition 2026-08-10 07:44:40 +01:00
robbond 46503b4507 reasoning: normalise graph relationship contract at proposal boundary 2026-08-10 06:16:47 +01:00
robbond 4e4d0fa732 reasoning: stop answer fidelity guard blocking valid unclassified answers 2026-08-09 19:55:35 +01:00
robbond f861e2cac0 reasoning: preserve evidence versus clarification distinction 2026-08-09 16:20:06 +01:00
robbond 4aa1492c8d refine raw-answer boundary for answer meaning 2026-08-09 11:31:27 +01:00
robbond 3e78d57aca refine answer meaning derivation for negation and qualification 2026-08-09 09:48:08 +01:00
robbond 7965375aff refine answerMeaning contract around user-supported meaning 2026-08-09 08:50:37 +01:00
robbond 36faf70a08 refine answerMeaning support category normalisation 2026-08-09 08:06:38 +01:00
robbond 0d7ad5775c reasoning: add proposal-level answer meaning guard
- Add answerMeaning schema with supportCategory and resolutionGuidance enums
- Add pre-mutation guard that validates proposal alignment with answerMeaning
- Update prompt builder to instruct the model on answerMeaning contract
- Add tests for schema, guard logic, parsing defaults, and regression cases A-D
2026-08-09 07:07:21 +01:00
robbond 0ba927230b fix: commit scope-aware condition status integration 2026-08-06 13:14:03 +01:00
robbond 273f715ae0 fix: complete scope-aware condition status evaluation
Handle the actual long-investigation fixture wording without rewriting conditions or evidence.

Fixes:
- Add 'is achievable' to future-feasibility phrase list so present-state evidence correctly leaves future conditions unresolved (different_timeframe scope)
- Add 'european equivalent' to differentiation related keywords so observation-5 evidence directly shares the differentiation concept with the condition (direct_match scope)

Updates:
- decision-condition-status tests to use present-state condition text where needed, and correct expectations for the two actual fixture cases
- Evidence-condition-scope tests for both actual fixture examples
- Design evolution log with Experiment 25B findings confirming long-investigation statuses
2026-08-06 13:05:29 +01:00
robbond 1a9a9a94fe experiment: compare evidence and condition scope 2026-08-06 11:36:42 +01:00
robbond da291c715b experiment: derive condition status from answer evidence 2026-08-06 11:17:17 +01:00
robbond aabb797e5d experiment: classify answer evidence direction
Move EVIDENCE_DIRECTION_GROUPS out of the mock fixture library into
lib/graph/evidence-direction.js where it belongs. Remove unused
DECISION_CONDITIONS and CONTRADICTION_KEYWORDS exports from scenarios.

Add Experiment 24A entry to the design log.
2026-08-06 10:32:48 +01:00
robbond 3119635211 experiment: assess decision condition status 2026-08-06 09:04:06 +01:00
robbond 32aa3f237a experiment: test questions against decision conditions 2026-08-06 08:36:44 +01:00
robbond 89650b44df experiment: test question relevance against decision target 2026-08-06 06:19:09 +01:00
robbond 445aaa7b37 experiment: add passive question importance test 2026-08-05 19:48:11 +01:00
robbond 1273861f0c exp(18): implement investigation state assessment layer
Implement the three-dimensional assessment (phase, progress, conversation
health) that sits between narrative and behaviour selection.

Key changes:
- lib/assessment/investigation-state-assessor.js: assessor module with
  countObservations, assessPhase, assessProgress, assessConversationHealth,
  assessInvestigationState — deterministic classifiers using known rules
- tests/investigation-state-assessor.test.js: 51 tests covering phase
  classification (orienting→concluding), progress thresholds, health
  conditions, confidence aggregation, edge cases, and observation counting
- lib/graph/orchestrator.js: integration calls passing correctly-shaped input
  to assessInvestigationState() at three call sites (~552, ~904, ~1013)

Design decisions encoded in this iteration:
- countObservations counts nodes with known/resolved status + high-confidence
  non-unknown non-state nodes (not just explicit observation-kind nodes)
- Phase uses seven values including cannot_determine for insufficient data
- Progress uses resolution ratio thresholds: accelerating (>0.6), steady
  (0.2-0.6), stalled (<0.2 with ≥1 resolved)
- Overall confidence = minimum across all three dimensions (conservative)

Also adds investigation-state-assessment-contract.md and updates
design-evolution-log, investigation-state-assessment.md (status header),
and investigation-turn-cycle.md (implementation status table).
2026-08-05 17:52:18 +01:00
robbond fe6a9925cb fix: stabilise multi-turn question progression 2026-08-03 13:55:39 +01:00
robbond 34c25fcb43 fix: reselect after reasoning pattern filtering 2026-08-03 12:39:01 +01:00
robbond c27320984c feat: enforce reasoning pattern consistency 2026-08-03 12:10:57 +01:00
robbond 3e2edd2edc fix: continue question selection after graph updates 2026-08-03 11:28:49 +01:00
robbond b00928d6fb feat: introduce reasoning pattern selection 2026-08-03 10:25:26 +01:00
robbond 42d4da3496 feat: decompose non-answerable unknowns 2026-08-03 09:53:28 +01:00