docs: archive historical Confidence Engine evidence
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
# Experiment 56A — Regression B Proposal Validation Enum Mismatch
|
||||
|
||||
**Date:** 2026-08-09
|
||||
**Branch:** `feature/reasoning-fidelity-v0.8`
|
||||
**Status:** observation complete, no fix attempted
|
||||
|
||||
## Hypothesis
|
||||
|
||||
Regression B fails at `proposal_validation` because Qwen returns
|
||||
`supportCategory: "conditional_qualification"` while the production
|
||||
proposal schema accepts only `conditional_tradeoff` among others.
|
||||
|
||||
This is a proposal-contract mismatch — not a pre-mutation guard failure.
|
||||
|
||||
## Fixed Input (Regression B)
|
||||
|
||||
- **Source:** "I want the business to grow, but I don't want to take on more risk."
|
||||
- **Answer:** "I'd normally avoid more risk, but for the right opportunity I might accept some."
|
||||
- **Expected supportCategory:** `conditional_tradeoff`
|
||||
- **SituationGraph:** single unknown node `n-risk-constraint`
|
||||
|
||||
## Configuration
|
||||
|
||||
- **Ollama endpoint:** `http://192.168.1.111:11434` (from `.env.local`)
|
||||
- **Model:** `qwen-claude:latest`
|
||||
|
||||
## Four Checkpoints Observed
|
||||
|
||||
### Checkpoint 1 — answerMeaning in raw structured response
|
||||
|
||||
The model returned an `answerMeaning` object with a non-null `supportCategory`.
|
||||
The parsed proposal was null because Zod validation rejected it (Zod's strict
|
||||
mode rejects the full object when any field is invalid).
|
||||
|
||||
### Checkpoint 2 — supportCategory at schema boundary
|
||||
|
||||
**Observed value:** `conditional_qualification`
|
||||
|
||||
Normalization step (`applyKnownEnumAliases`) does not handle `supportCategory`;
|
||||
it only converts `reported_statement → reported_claim` on added nodes. The value
|
||||
survives unchanged to Zod validation.
|
||||
|
||||
### Checkpoint 3 — Schema-accepted values
|
||||
|
||||
```
|
||||
relative_priority_only
|
||||
conditional_tradeoff
|
||||
uncertain
|
||||
explicit_hard_constraint
|
||||
other
|
||||
```
|
||||
|
||||
**Source:** `lib/graph/schema.js`, lines 147–152 (answerSupportCategory enum).
|
||||
|
||||
`conditional_qualification` is NOT in this list.
|
||||
|
||||
### Checkpoint 4 — Zod validation result
|
||||
|
||||
```
|
||||
path: ["answerMeaning", "supportCategory"]
|
||||
message: "Invalid enum value. Expected 'relative_priority_only' | 'conditional_tradeoff' | 'uncertain' | 'explicit_hard_constraint' | 'other', received 'conditional_qualification'"
|
||||
code: invalid_enum_value
|
||||
stage: proposal_validation
|
||||
```
|
||||
|
||||
## Result
|
||||
|
||||
**Hypothesis confirmed: YES**
|
||||
|
||||
1. Provider output contains `conditional_qualification` — confirmed via Zod error message.
|
||||
2. Value survives normalization unchanged — confirmed by inspection of `applyKnownEnumAliases`.
|
||||
3. Schema does not accept it — confirmed (not in the enum).
|
||||
4. Proposal validation fails for that reason — confirmed (Zod error at path `["answerMeaning", "supportCategory"]`).
|
||||
|
||||
## What Was Not Done
|
||||
|
||||
- No production code was changed.
|
||||
- No fix was attempted.
|
||||
- The pre-mutation guard was not reached because proposal_validation rejects first.
|
||||
- Cases A, C, D, E, F were not tested.
|
||||
- This experiment tested only ONE call; model output may vary across runs.
|
||||
|
||||
## Files
|
||||
|
||||
- Read: `lib/graph/schema.js` (lines 147–165 — answerSupportCategory enum)
|
||||
- Read: `lib/graph/update-proposal.js` (full file — normalization functions)
|
||||
- Read: `lib/llm/provider.js` (full file — Ollama provider)
|
||||
- Read: `lib/graph/orchestrator.js` (lines 580–680 — updateCase flow)
|
||||
- Read: `docs/reasoning-refinement-requirements.md` (Regression B section)
|
||||
- Read: `tests/graph/regression-a-d-v0.8.test.js` (fixed graph + input for Regression B)
|
||||
|
||||
## Git
|
||||
|
||||
- Commit message: `experiment: isolate regression B proposal validation`
|
||||
- Working tree left clean after experiment cleanup.
|
||||
@@ -0,0 +1,103 @@
|
||||
# Experiment 56B — Regression B Live Run After Normalisation
|
||||
|
||||
**Date:** 2026-08-09
|
||||
**Branch:** `feature/reasoning-fidelity-v0.8`
|
||||
**Status:** observation complete, no fix attempted
|
||||
|
||||
## Hypothesis
|
||||
|
||||
Regression B passes proposal validation after the normalisation added in commit `36faf70`, reaches the pre-mutation guard in `applyValidatedProposal()`, and preserves its conditional meaning through the graph outcome.
|
||||
|
||||
## Fixed Input (Regression B)
|
||||
|
||||
- **Source:** "I want the business to grow, but I don't want to take on more risk."
|
||||
- **Answer:** "I'd normally avoid more risk, but for the right opportunity I might accept some."
|
||||
- **Graph state:** Single unknown node `n-risk-constraint` (status: unknown)
|
||||
- **Previous question:** "Is avoiding additional risk a hard constraint or a preference/trade-off?"
|
||||
|
||||
## Configuration
|
||||
|
||||
- **Ollama endpoint:** `http://192.168.1.111:11434` (from `.env.local`)
|
||||
- **Model:** `qwen-claude:latest`
|
||||
|
||||
## Observations
|
||||
|
||||
### 1. Raw answerMeaning
|
||||
|
||||
Inferred from Zod rejection errors (the model did not produce a validated proposal):
|
||||
|
||||
- `supportCategory`: `"conditional_preference"`
|
||||
- `resolutionGuidance`: `"Identify and quantify the threshold conditions that trigger risk acceptance."` (free-text string, not an enum value)
|
||||
|
||||
### 2. Raw supportCategory at schema boundary
|
||||
|
||||
**Observed value:** `conditional_preference`
|
||||
|
||||
### 3. Normalised supportCategory
|
||||
|
||||
**Result:** Unchanged — `conditional_preference`
|
||||
|
||||
The normalisation map in `update-proposal.js` line 15 contains only:
|
||||
|
||||
```js
|
||||
const ANSWER_SUPPORT_CATEGORY_ALIASES = {
|
||||
conditional_qualification: "conditional_tradeoff",
|
||||
};
|
||||
```
|
||||
|
||||
It does **not** handle `conditional_preference`. The value passes through normalization untouched to Zod validation.
|
||||
|
||||
### 4. Proposal validation result
|
||||
|
||||
**FAILED — two errors:**
|
||||
|
||||
1. **supportCategory:** `"conditional_preference"` is not in the Zod enum (`relative_priority_only | conditional_tradeoff | uncertain | explicit_hard_constraint | other`)
|
||||
2. **resolutionGuidance:** Free-text string `"Identify and quantify the threshold conditions that trigger risk acceptance."` is not in the Zod enum (`must_remain_unresolved | may_resolve | must_resolve`)
|
||||
|
||||
### 5. applyValidatedProposal reached?
|
||||
|
||||
**NO.** The failure occurs at `proposal_validation` stage, before the pre-mutation guard in `applyValidatedProposal()` can execute.
|
||||
|
||||
### 6. Guard result
|
||||
|
||||
Not applicable — never reached.
|
||||
|
||||
### 7. Resolution/update intent
|
||||
|
||||
The model's free-text `resolutionGuidance` (`"Identify and quantify the threshold conditions that trigger risk acceptance."`) indicates it was attempting to produce conditional-resolution guidance, but failed the enum contract entirely.
|
||||
|
||||
### 8. Final graph state
|
||||
|
||||
**No mutation.** The proposal was rejected at validation; the SituationGraph remains unchanged (still contains `n-risk-constraint` with status `unknown`).
|
||||
|
||||
## Additional Finding — Run-to-Run Model Variation
|
||||
|
||||
Experiment 56A observed `supportCategory: "conditional_qualification"`. Experiment 56B observed `supportCategory: "conditional_preference"`. The same fixed input and model produce different category strings across runs. This means the normalisation map is incomplete by definition — no finite alias list can cover all possible model-generated variants.
|
||||
|
||||
The two observations confirm the same root cause (model returns a non-enum supportCategory string) but with different values, reinforcing that this is an instability in the model's output contract compliance.
|
||||
|
||||
## Result
|
||||
|
||||
**FAIL — normalization / proposal contract**
|
||||
|
||||
The hypothesis is not confirmed. Regression B fails at `proposal_validation` for the same class of defect as Experiment 56A (non-enum supportCategory), but with a *different* invalid value (`conditional_preference` instead of `conditional_qualification`). The existing normalisation map does not cover this variant.
|
||||
|
||||
## What This Established
|
||||
|
||||
1. Run-to-run model variation confirmed: `conditional_qualification` → `conditional_preference`.
|
||||
2. The normalisation alias list (`ANSWER_SUPPORT_CATEGORY_ALIASES`) is insufficient — it only covers one of at least two observed variants.
|
||||
3. The pre-mutation guard in `applyValidatedProposal()` remains unreachable because proposal_validation rejects first.
|
||||
4. Even if the normalisation map were extended to cover `conditional_preference → conditional_tradeoff`, the `resolutionGuidance` field also failed (free-text instead of enum), indicating a second independent compliance gap.
|
||||
|
||||
## What Remains Untested
|
||||
|
||||
- Cases A, C, D, E, F
|
||||
- Whether the model will consistently return one variant vs the other under repeated identical input
|
||||
- The pre-mutation guard behaviour once a proposal successfully passes validation
|
||||
- Downstream graph mutation consequences
|
||||
- Other models' compliance with the answerMeaning output contract
|
||||
|
||||
## Production reasoning code changed: NO
|
||||
## Temporary instrumentation removed: YES
|
||||
## Documentation updated: experiment-56b.md, current-handoff.md
|
||||
## Git status: clean (pending commit)
|
||||
@@ -0,0 +1,62 @@
|
||||
# Experiment 56D — Regression B via Real Production Path
|
||||
|
||||
**Date**: 2026-08-09
|
||||
**Commit**: 3e78d57 (refine answer meaning derivation for negation and qualification)
|
||||
**Type**: Observation-only — no code changes
|
||||
**Objective**: Verify that deterministic derivation refinement works end-to-end for conditional trade-off scenarios
|
||||
|
||||
---
|
||||
|
||||
## Input (Fixed)
|
||||
|
||||
**Source**: "I want the business to grow, but I don't want to take on more risk."
|
||||
**Answer**: "I'd normally avoid more risk, but for the right opportunity I might accept some."
|
||||
|
||||
## Graph Setup
|
||||
|
||||
Pre-update graph state matched Regression B fixture:
|
||||
- `n-risk-constraint` (unknown/unknown) — active unknown
|
||||
- `obs-source-statement` (observation/supported) — source observation
|
||||
- 1 edge connecting source to risk unknown
|
||||
|
||||
---
|
||||
|
||||
## Results
|
||||
|
||||
| # | Checkpoint | Result |
|
||||
|---|-----------|--------|
|
||||
| 1 | `userSupportedMeaning` extracted | ✅ `"Risk avoidance is a strong default preference that can be overridden for specific opportunities deemed suitable, rather than an absolute hard constraint."` |
|
||||
| 2 | `possibleInference` derived | ✅ `"Growth strategy should focus on identifying and qualifying high-potential opportunities with clearly defined, bounded risk parameters instead of broad or unconditional expansion."` |
|
||||
| 3 | LLM-populated `supportCategory` | null (LLM does not auto-populate; nullable per schema) |
|
||||
| 4 | Derived meaning profile category | **conditional_tradeoff** (derived from userSupportedMeaning via deterministic logic) |
|
||||
| 5 | Guard errors present? | ✅ None — guard passed successfully |
|
||||
| 6 | Risk unknown resolved correctly | `n-risk-constraint`: status→`resolved`, newValue=null, reason=preference vs constraint distinction clarified |
|
||||
| 7 | Proposed graph mutation valid | Updated n-risk-constraint as resolved; created new unknown `n-opportunity-criteria` (unknown/unknown) with dependsOn=[n-risk-constraint] |
|
||||
| 8 | Newly proposed question | `"What specific criteria define an acceptable 'right opportunity' that justifies taking on additional risk?"` targeting the emergent unknown |
|
||||
|
||||
## Key Findings
|
||||
|
||||
1. **Meaning derivation correctly identifies conditional tradeoff**: The `userSupportedMeaning` extraction cleanly separated the default stance (avoid risk) from the qualification (override for right opportunity). This is precisely the Regression B scenario.
|
||||
|
||||
2. **Deterministic profile categorization works end-to-end**: Despite LLM returning null for `supportCategory`, our inline derivation logic (triggered by `hasDefaultPref && hasException` pattern matching on "normally" + "might/accept") correctly derives `conditional_tradeoff`.
|
||||
|
||||
3. **Guard validation passes through**: No guard errors — the resolved node and newly added unknown are both compatible with the source scenario.
|
||||
|
||||
4. **Emergent conditional unknown created successfully**: The system created `n-opportunity-criteria` (kind=unknown, status=unknown) with a description that directly operationalizes the conditional nature: *"Needs explicit criteria to define when additional risk is justified."* This confirms the pipeline correctly recognizes that a conditional tradeoff requires further exploration.
|
||||
|
||||
5. **selectedQuestion targets emergent unknown**: The proposal correctly includes `selectedQuestion` pointing to `n-opportunity-criteria`, maintaining conversation flow toward resolution of the remaining uncertainty.
|
||||
|
||||
6. **LLM does not auto-populate `supportCategory`**: Across runs, `answerMeaning.supportCategory` is consistently null. This confirms the derivation logic in `readDiagnostics` (and the inline pipeline) is the mechanism by which the meaning profile gets determined. This is expected design — the LLM produces the raw meaning; the deterministic layer categorizes it.
|
||||
|
||||
---
|
||||
|
||||
## Verdict
|
||||
|
||||
**Regression B PASSES via real production path.** The full updateCase() pipeline correctly:
|
||||
- Extracts conditional tradeoff semantics from userAnswer
|
||||
- Derives `conditional_tradeoff` category via deterministic profile matching
|
||||
- Resolves the active unknown while creating an emergent conditional/threshold unknown
|
||||
- Passes all guard constraints
|
||||
- Proposes a follow-up question targeting the remaining uncertainty
|
||||
|
||||
No regression detected. The meaning derivation refinement from commit 3e78d57 works as intended for conditional trade-off scenarios.
|
||||
@@ -0,0 +1,102 @@
|
||||
# Experiment 56E — Weak Priority Through Live Production Path
|
||||
|
||||
**Date**: 2026-08-09
|
||||
**Commit**: 3e78d57 (refine answer meaning derivation for negation and qualification)
|
||||
**Type**: Observation-only — no code changes
|
||||
**Objective**: Validate that the production path preserves only what the weak-priority answer establishes (relative importance) without inventing whether risk is or is not a hard constraint.
|
||||
|
||||
---
|
||||
|
||||
## Input (Fixed)
|
||||
|
||||
**Source:** "I want the business to grow, but I don't want to take on more risk."
|
||||
**Answer:** "Risk matters more to me."
|
||||
|
||||
## Graph Setup
|
||||
|
||||
Pre-update graph state matched Regression A fixture:
|
||||
- `n-risk-constraint` (unknown/unknown) — active unknown, status=unknown
|
||||
- No source observation node
|
||||
- 0 edges
|
||||
|
||||
---
|
||||
|
||||
## Results
|
||||
|
||||
| # | Checkpoint | Result |
|
||||
|---|-----------|--------|
|
||||
| 1 | `userSupportedMeaning` extracted | ❌ **"Avoiding additional risk is a preference/trade-off rather than a hard constraint."** — strengthened beyond user input |
|
||||
| 2 | `possibleInference` derived | **"The user prioritizes risk mitigation over aggressive growth strategies."** |
|
||||
| 3 | LLM-populated `supportCategory` | null (LLM does not auto-populate; nullable per schema) |
|
||||
| 4 | Derived meaning profile category | null (LLM returned null; deterministic derivation never triggered because guard passed before derivation step) |
|
||||
| 5 | Guard errors present? | ✅ None — guard passed (it received the already-strengthened userSupportedMeaning, not the raw answer) |
|
||||
| 6 | Risk unknown resolution | `n-risk-constraint`: status→`known`, newValue=`"preference/trade-off"` |
|
||||
| 7 | Guard rejected any node? | No guard errors; proposal accepted |
|
||||
| 8 | New nodes created | None |
|
||||
| 9 | Selected question proposed | null (risk unknown treated as resolved) |
|
||||
|
||||
---
|
||||
|
||||
## Analysis Against Regression A Contract
|
||||
|
||||
### Expected preserved meaning
|
||||
> Risk is of greater relative importance than growth; no hard-constraint or non-hard-constraint boundary established.
|
||||
|
||||
### What the model actually extracted
|
||||
> "Avoiding additional risk is a preference/trade-off **rather than a hard constraint**."
|
||||
|
||||
### Violation
|
||||
The user answered only "Risk matters more to me." — this establishes relative importance only. It says nothing about whether avoiding risk IS or IS NOT a hard constraint.
|
||||
|
||||
The production path's `userSupportedMeaning` field (intended to carry *only* what the user established) now contains a negative assertion: **"rather than a hard constraint"** — an unsupported conclusion that risk is not a hard constraint. This directly violates the Regression A "must not happen" requirement:
|
||||
|
||||
> *Must not happen: Inference that risk avoidance is "not a hard constraint" or equivalent negative assertion.*
|
||||
|
||||
### Failure location
|
||||
The strengthening occurred at the **semantic interpretation layer** (the model's answer-meaning extraction). The deterministic guard saw the already-strengthened meaning and passed it because the proposal was internally consistent. The over-resolution happened before the guard could evaluate it against the original answer.
|
||||
|
||||
This matches the historical finding from Experiment 55A: "Case 2 (weak priority — 'Risk matters more to me.') over-resolved: the model set targetResolved=true and inferred 'not a rigid, non-negotiable constraint' — meaning stronger than the user supplied." The same failure pattern reproduced through the full production path.
|
||||
|
||||
---
|
||||
|
||||
## Verdict
|
||||
|
||||
**FAIL - semantic interpretation**
|
||||
|
||||
For Regression A, the live model and production reasoning path did **not** preserve only what the answer establishes. It invented that risk is "not a hard constraint" from the weak-priority answer alone.
|
||||
|
||||
The PASS requirement is not met:
|
||||
- ❌ `userSupportedMeaning` asserts "rather than a hard constraint" (negative assertion)
|
||||
- ❌ The hard-constraint distinction was resolved to "preference/trade-off" rather than left unresolved
|
||||
- ❌ The deterministic guard could not prevent this because the over-resolution happened before the guard
|
||||
|
||||
---
|
||||
|
||||
## Key Findings
|
||||
|
||||
1. **The strengthening defect persists through commit 3e78d57.** The answer-meaning derivation still converts weak priority ("Risk matters more to me.") into a negative hard-constraint assertion ("rather than a hard constraint"). This is not limited to the resolution layer; it has already leaked into `userSupportedMeaning`.
|
||||
|
||||
2. **The guard cannot catch this because it sees the post-enrichment meaning, not the raw answer.** By the time validation reaches the guard, the strengthening has already been baked into `answerMeaning.userSupportedMeaning`.
|
||||
|
||||
3. **Run-to-run variation in inference field.** Across two identical runs: (a) first run returned possibleInference=null; (b) second run populated it with a derived inference. Both contained the over-resolution in userSupportedMeaning. The enrichment is unstable across runs for the weak-priority case.
|
||||
|
||||
4. **No emergent unknown created.** Unlike Regression B (56D), which correctly created `n-opportunity-criteria` as an emergent unknown, Regression A's graph mutation treated the question as fully resolved — no follow-up needed according to the model's interpretation. This is incorrect: the hard-constraint distinction should remain open.
|
||||
|
||||
---
|
||||
|
||||
## What remains untested
|
||||
|
||||
- Whether separating userSupportedMeaning from inference (as attempted in 55D) actually prevents this strengthening when the contract is enforced end-to-end
|
||||
- Whether the fix from 36faf70 (conditional_qualification normalisation) or 3e78d57 (negation/qualification refinement) addresses weak-priority specifically
|
||||
- Whether adding a post-guard verification layer that compares `userSupportedMeaning` against the original answer text can catch this class of over-resolution
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
- **Host:** http://192.168.1.111:11434
|
||||
- **Model:** qwen-claude:latest
|
||||
- **Branch:** feature/reasoning-fidelity-v0.8
|
||||
- **Production code changed:** NO
|
||||
- **Temporary instrumentation:** minimal Node script only — removed after capture
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
# Experiment 56F — Weak Priority Re-tested with Canonical Live Harness
|
||||
|
||||
**Date**: 2026-08-09
|
||||
**Commit**: 4aa1492 (refine raw-answer boundary for answer meaning)
|
||||
**Type**: Observation-only — no code changes
|
||||
**Objective**: After Codex commit `4aa1492`, does Regression A now leave constraint status unresolved instead of allowing "Risk matters more to me." to become "not a hard constraint" or equivalent?
|
||||
|
||||
---
|
||||
|
||||
## Input (Fixed — Regression A)
|
||||
|
||||
**Source:** "I want the business to grow, but I don't want to take on more risk."
|
||||
**Answer:** "Risk matters more to me."
|
||||
|
||||
## Graph Setup
|
||||
|
||||
Pre-update graph state matched Regression A fixture:
|
||||
- `n-risk-constraint` (unknown/unknown) — active unknown, status=unknown
|
||||
- No source observation node
|
||||
- 0 edges
|
||||
|
||||
---
|
||||
|
||||
## Results
|
||||
|
||||
| # | Checkpoint | Result |
|
||||
|---|-----------|--------|
|
||||
| 1 | `userSupportedMeaning` extracted | **"Avoiding additional risk is a strongly weighted preference/trade-off rather than a hard constraint."** — LLM still strengthens beyond user input |
|
||||
| 2 | `possibleInference` derived | null |
|
||||
| 3 | `rawAnswerCategory` (deterministic) | `relative_importance` |
|
||||
| 4 | `proposedMeaningCategory` (deterministic from userSupportedMeaning) | `hard_constraint` |
|
||||
| 5 | `proposalValidation.success` | **false** — proposal rejected before mutation |
|
||||
| 6 | Pre-mutation guard errors? | Empty array (no traditional guard error messages) |
|
||||
| 7 | Compatibility applied? | **false** — guard did not pass |
|
||||
| 8 | Risk unknown resolution | **No mutation** — `n-risk-constraint` status unchanged |
|
||||
| 9 | Hard-constraint distinction resolved? | **NO** |
|
||||
|
||||
---
|
||||
|
||||
## Analysis Against Regression A Contract
|
||||
|
||||
### Expected preserved meaning
|
||||
> Risk is of greater relative importance than growth; no hard-constraint or non-hard-constraint boundary established.
|
||||
|
||||
### What the model extracted (userSupportedMeaning)
|
||||
> "Avoiding additional risk is a strongly weighted preference/trade-off **rather than a hard constraint**."
|
||||
|
||||
The LLM's `userSupportedMeaning` still contains semantic strengthening — it asserts that risk avoidance is "rather than a hard constraint," which goes beyond what the raw answer establishes. This is the same class of over-resolution observed in Experiment 56E (under commit `3e78d57`).
|
||||
|
||||
### What prevented graph mutation
|
||||
The pre-mutation safeguard chain rejected the proposal:
|
||||
- **Deterministic derivation** produced `proposedMeaningCategory: hard_constraint` from the strengthened meaning.
|
||||
- This created a **mismatch** with the raw answer's category (`relative_importance`).
|
||||
- The mismatch caused `proposalValidation.success: false` and prevented the compatibility guard from passing.
|
||||
- **No graph mutation occurred.** `n-risk-constraint` remained unresolved (status=unknown, value=null).
|
||||
|
||||
The raw-answer compatibility mechanism correctly identified that the LLM-proposed meaning profile was incompatible with the raw answer's category, and blocked the mutation before it reached authoritative state.
|
||||
|
||||
### Verdict
|
||||
|
||||
**PASS - strengthening safely rejected**
|
||||
|
||||
The final authoritative graph state does **not** establish either:
|
||||
- risk is a hard constraint; nor
|
||||
- risk is not a hard constraint;
|
||||
|
||||
from "Risk matters more to me." alone. The pre-mutation safeguard (proposal validation + compatibility guard) correctly rejected the strengthened meaning before mutation.
|
||||
|
||||
---
|
||||
|
||||
## Key Find
|
||||
|
||||
1. **Semantic strengthening in `userSupportedMeaning` persists.** After commit `4aa1492`, the LLM still converts "Risk matters more to me." into language that asserts risk avoidance is "rather than a hard constraint." This means R1 (preserve user-supplied meaning) is not fully met at the semantic interpretation layer.
|
||||
|
||||
2. **Pre-mutation safeguard works.** Despite the strengthened `userSupportedMeaning`, the raw-answer compatibility mechanism correctly blocked the proposal from reaching graph state. The mismatch between `proposedMeaningCategory` (hard_constraint) and `rawAnswerCategory` (relative_importance) was sufficient to reject the mutation.
|
||||
|
||||
3. **No emergent unknown created.** Unlike Regression B (56D), which correctly produced an emergent unknown for conditional trade-off, Regression A's rejection left no follow-up question or unknown — the uncertainty remains in its original unresolved state.
|
||||
|
||||
4. **Deterministic derivation is functional.** The derivation from strengthened meaning to `hard_constraint` category worked correctly: the phrase "rather than a hard constraint" triggered the `qualified_support` pattern which then normalized to `hard_constraint`. This confirms the deterministic layer produces meaningful profiles from free-text input.
|
||||
|
||||
---
|
||||
|
||||
## What this established
|
||||
|
||||
- After commit `4aa1492`, Regression A no longer allows unsupported constraint status to reach graph state via the production path. The raw-answer compatibility safeguard is effective at catching semantic strengthening before mutation.
|
||||
- The LLM still produces strengthened `userSupportedMeaning` (the same strengthening pattern as in 56E), but the pre-mutation guard chain successfully blocks it from becoming authoritative graph state.
|
||||
|
||||
## What remains untested
|
||||
|
||||
- Whether the LLM's tendency to strengthen weak-priority answers can be reduced at the prompt/interpretation layer (this is a question for the semantic interpretation model, not just the guard).
|
||||
- Whether `proposedMeaningCategory` derivation has edge cases where it produces incorrect mismatches (false positive rejections of valid proposals).
|
||||
- Whether the deterministic derivation correctly handles other weak-priority answer patterns beyond this single fixture.
|
||||
- Stability across repeated identical runs — does the safeguard hold consistently or only fortuitously?
|
||||
|
||||
---
|
||||
|
||||
## Configuration
|
||||
|
||||
- **Host:** http://192.168.1.111:11434
|
||||
- **Model:** qwen-claude:latest
|
||||
- **Branch:** feature/reasoning-fidelity-v0.8
|
||||
- **Harness:** tests/graph/live-update-experiment-helper.cjs (canonical)
|
||||
- **Runner:** experiment-56f-runner.mjs (temporary, removed after capture)
|
||||
- **Production code changed:** NO
|
||||
- **Live calls:** 1
|
||||
|
||||
---
|
||||
|
||||
## Regression A Result Summary
|
||||
|
||||
| Aspect | Before 4aa1492 (Exp 56E) | After 4aa1492 (Exp 56F) |
|
||||
|--------|--------------------------|--------------------------|
|
||||
| Semantic strengthening in `userSupportedMeaning` | YES | YES (persisted) |
|
||||
| Pre-mutation safeguard rejection | Not observed / unclear | YES — proposalValidation false, compatibilityGuard false |
|
||||
| Graph mutation for risk-constraint | YES (status→known, value="preference/trade-off") | NO (no mutation) |
|
||||
| Hard-constraint distinction resolved? | YES (to "preference/trade-off") | NO |
|
||||
| Verdict | FAIL - semantic interpretation | PASS - strengthening safely rejected |
|
||||
@@ -0,0 +1,48 @@
|
||||
# Experiment 56G — Validate Unresolved Uncertainty Through Live Production Path
|
||||
|
||||
**Date**: 2026-08-09
|
||||
**Branch**: feature/reasoning-fidelity-v0.8
|
||||
**Type**: Live experiment — BLOCKED by apparatus failure
|
||||
**Status**: BLOCKED - apparatus
|
||||
|
||||
---
|
||||
|
||||
## Objective
|
||||
|
||||
Answer: When the user says "I'm not really sure.", does the production path preserve that uncertainty instead of resolving or strengthening the risk-constraint distinction?
|
||||
|
||||
## Fixed Case — Regression C
|
||||
|
||||
- **Source**: "I want the business to grow, but I don't want to take on more risk."
|
||||
- **Previous question**: "Is avoiding additional risk a hard constraint or a preference/trade-off?"
|
||||
- **Answer**: "I'm not really sure."
|
||||
- **Expected preserved meaning**: User is uncertain about whether avoiding additional risk is a hard constraint or preference/trade-off.
|
||||
- **Expected uncertainty**: Full — no position taken.
|
||||
|
||||
## Apparatus Failure
|
||||
|
||||
The canonical helper (`tests/graph/live-update-experiment-helper.cjs`) contains a broken import path:
|
||||
|
||||
```js
|
||||
const { updateCase } = await import("../lib/graph/orchestrator.js");
|
||||
```
|
||||
|
||||
From its location at `tests/graph/`, this resolves to `tests/lib/graph/orchestrator.js` — which does not exist. The correct relative path is `../../lib/graph/orchestrator.js`.
|
||||
|
||||
The canonical helper cannot invoke the production path without a fix to this import.
|
||||
|
||||
## Result
|
||||
|
||||
**BLOCKED - apparatus**
|
||||
|
||||
No live calls were made. No experiment data captured.
|
||||
|
||||
## Evidence
|
||||
|
||||
- File exists: `./lib/graph/orchestrator.js` (project root)
|
||||
- File missing: `tests/lib/graph/orchestrator.js`
|
||||
- Broken path: `../lib/graph/orchestrator.js` from `tests/graph/live-update-experiment-helper.cjs`
|
||||
|
||||
---
|
||||
|
||||
*Status pending Rob's review. Requires canonical helper import path fix before this experiment can proceed.*
|
||||
@@ -0,0 +1,112 @@
|
||||
# Experiment 56H — Validate Unresolved Uncertainty After Harness Repair
|
||||
|
||||
**Date**: 2026-08-09
|
||||
**Branch**: feature/reasoning-fidelity-v0.8
|
||||
**Starting reasoning commit**: e6f7842 (establish canonical live reasoning experiment harness)
|
||||
**Harness repair commit**: c40d8c6 (fix canonical live experiment harness import)
|
||||
**Type**: Live experiment — observation only
|
||||
**Status**: PASS
|
||||
|
||||
---
|
||||
|
||||
## Objective
|
||||
|
||||
When the user says "I'm not really sure.", does the production path preserve the risk-constraint distinction as unresolved?
|
||||
|
||||
## Hypothesis
|
||||
|
||||
The production path will preserve the user's uncertainty:
|
||||
- `userSupportedMeaning` will not invent a preference or hard-constraint position;
|
||||
- compatibility/guard logic will prevent unsupported resolution;
|
||||
- the risk-constraint unknown will remain unresolved.
|
||||
|
||||
## Fixed Case — Regression C
|
||||
|
||||
- **Source**: "I want the business to grow, but I don't want to take on more risk."
|
||||
- **Previous question**: "Is avoiding additional risk a hard constraint or a preference/trade-off?"
|
||||
- **Answer**: "I'm not really sure."
|
||||
- **Expected preserved meaning**: User is uncertain about whether avoiding additional risk is a hard constraint or preference/trade-off.
|
||||
- **Expected uncertainty**: Full — no position taken.
|
||||
|
||||
## Graph Setup
|
||||
|
||||
Pre-update graph state:
|
||||
- `n-risk-constraint` (unknown/unknown) — active unknown, status=unknown
|
||||
- `obs-source-statement` (observation/supported) — source observation
|
||||
- 1 edge connecting source to risk unknown
|
||||
|
||||
## Results
|
||||
|
||||
| # | Checkpoint | Result |
|
||||
|---|-----------|--------|
|
||||
| 1 | `userSupportedMeaning` extracted | **null** — no semantic content extracted from the non-answer |
|
||||
| 2 | `possibleInference` derived | null |
|
||||
| 3 | `rawAnswerCategory` (deterministic) | `cannot_determine` |
|
||||
| 4 | `proposedMeaningCategory` (from userSupportedMeaning) | `none` |
|
||||
| 5 | `proposalValidation.success` | false (no errors — nothing to validate due to null meaning) |
|
||||
| 6 | Compatibility guard passed? | **false** — guard did not pass |
|
||||
| 7 | Graph mutation applied? | **No** — graphMutation is null |
|
||||
| 8 | Risk unknown status after call | **unknown** (unchanged) |
|
||||
| 9 | Hard-constraint distinction resolved? | **NO** |
|
||||
|
||||
## Verdict
|
||||
|
||||
**PASS - uncertainty preserved**
|
||||
|
||||
The final authoritative graph state does **not** establish either:
|
||||
- risk is a hard constraint; nor
|
||||
- risk is not a hard constraint;
|
||||
|
||||
from "I'm not really sure." alone. The n-risk-constraint unknown remained at status=unknown with value=null. No graph mutation occurred.
|
||||
|
||||
## Analysis Against Regression C Contract
|
||||
|
||||
### What the model extracted (userSupportedMeaning)
|
||||
|
||||
> **null** — no semantic content extracted from a non-answer response ("I'm not really sure.").
|
||||
|
||||
The LLM did not invent any preference, constraint position, or leaning. This is the correct behaviour for a genuine non-answer. The deterministic raw-answer classifier categorised the input as `cannot_determine`.
|
||||
|
||||
### What prevented graph mutation
|
||||
|
||||
The pre-mutation safeguard chain rejected the proposal:
|
||||
- **No meaningful userSupportedMeaning** was extracted from the non-answer (null).
|
||||
- Deterministic derivation produced `proposedMeaningCategory: none` (no meaning to map).
|
||||
- There was nothing substantive for the compatibility guard to validate — no proposed meaning profile existed to match against the raw answer.
|
||||
- **No graph mutation occurred.** `n-risk-constraint` remained unknown with value=null.
|
||||
|
||||
### Key observation
|
||||
|
||||
The non-answer ("I'm not really sure.") is handled correctly by this pipeline: the LLM does not fabricate semantic content where none exists, and the guard chain correctly prevents any resolution attempt when there is no substantive meaning to evaluate. The risk-constraint distinction remains unresolved as expected.
|
||||
|
||||
## What this established
|
||||
|
||||
- After harness repair (commit c40d8c6), Regression C passes through the real production path. A non-answer preserves uncertainty — the LLM does not invent constraint or preference positions from "I'm not really sure."
|
||||
- The safety net (proposal validation + compatibility guard) works as a compound gate: when no meaningful userSupportedMeaning exists, there is nothing to validate and nothing can reach graph state.
|
||||
- The deterministic raw-answer classifier correctly categorises non-answers as `cannot_determine`.
|
||||
|
||||
## What remains untested
|
||||
|
||||
- Whether the LLM's handling of "I'm not really sure." is stable across repeated identical runs.
|
||||
- Whether a near-answer (e.g., "I'm leaning toward..." or "It depends on...") would trigger different behaviour.
|
||||
- Whether Regression C works with a graph that has more complexity (multiple active unknowns, edges from other nodes).
|
||||
- Stability across other models — this test used only qwen-claude:latest.
|
||||
- End-to-end interaction flow: whether the follow-up question correctly reflects the remaining uncertainty in the full investigation context.
|
||||
|
||||
## Configuration
|
||||
|
||||
- **Host**: http://192.168.1.111:11434
|
||||
- **Model**: qwen-claude:latest
|
||||
- **Branch**: feature/reasoning-fidelity-v0.8
|
||||
- **Harness**: tests/graph/live-update-experiment-helper.cjs (canonical)
|
||||
- **Runner**: experiment-56h-runner.mjs (temporary, removed after capture)
|
||||
- **Production code changed**: NO
|
||||
- **Live calls**: 1
|
||||
|
||||
## Previous Attempt
|
||||
|
||||
Experiment 56G was blocked by apparatus failure (broken import path in the canonical helper). This repair was completed by commit c40d8c6. Experiment 56H succeeds where 56G could not.
|
||||
|
||||
---
|
||||
|
||||
*Status pending Rob's review.*
|
||||
@@ -0,0 +1,79 @@
|
||||
# Experiment 56J — Explicit Hard Constraint Semantic Fidelity (Regression D)
|
||||
|
||||
## Purpose
|
||||
Probe whether the configured live Ollama model preserves the user's explicit hard-constraint meaning without weakening it into a preference/trade-off or adding unsupported meaning.
|
||||
|
||||
## Branch / HEAD
|
||||
- **Branch:** `feature/reasoning-fidelity-v0.8`
|
||||
- **HEAD:** at time of run, clean working tree on this branch.
|
||||
|
||||
## Historical Live-Call Pattern Reused
|
||||
Experiment 55D — commit `fcb7218407a2921e9197dbb0a65e4e1282459e4c`
|
||||
File: `tests/reconstruction/semantic-clarification-stated-vs-inferred.test.js`
|
||||
|
||||
The established mechanism was reused:
|
||||
- Vitest ESM test;
|
||||
- `dotenv` loads `.env.local`;
|
||||
- native `fetch` POST to `${OLLAMA_BASE_URL}/api/chat`;
|
||||
- `format: "json"`, `stream: false`;
|
||||
- extract `response.message.content`;
|
||||
- strip JSON markdown fences; parse structured JSON.
|
||||
|
||||
## Configured Ollama Host / Model
|
||||
- **Base URL:** `http://192.168.1.111:11434`
|
||||
- **Model:** `qwen-claude:latest`
|
||||
|
||||
## Call Count
|
||||
**Exactly 1 real Ollama call.** No retries, no voting, no fallback.
|
||||
|
||||
## Duration
|
||||
**19,343 ms** (19.3 seconds)
|
||||
|
||||
## Fixed Case — Regression D
|
||||
|
||||
**Source statement:** "I want the business to grow, but I don't want to take on more risk."
|
||||
|
||||
**Clarification target context:** whether avoiding additional risk is a hard constraint or a preference/trade-off
|
||||
|
||||
**Clarification question:** Do you view avoiding additional risk as a hard constraint, or as a preference or trade-off?
|
||||
|
||||
**User's answer (verbatim):** "It's a hard constraint. I don't want any increase in risk."
|
||||
|
||||
## Pre-Written Human Expectation
|
||||
> Avoiding additional risk is an explicit hard constraint. The user does not accept any increase in risk.
|
||||
|
||||
The answer establishes hard-constraint status. It must **not** be weakened into preference, strong preference, normal tendency, trade-off, or conditionally negotiable language.
|
||||
|
||||
## Raw Parsed Response
|
||||
```json
|
||||
{
|
||||
"userSupportedMeaning": "Avoiding additional risk is a hard constraint, and no increase in risk is acceptable.",
|
||||
"possibleInference": null
|
||||
}
|
||||
```
|
||||
|
||||
- **userSupportedMeaning:** "Avoiding additional risk is a hard constraint, and no increase in risk is acceptable."
|
||||
- **possibleInference:** null (correct — explicit answer does not require inferred implication)
|
||||
|
||||
## Call Duration
|
||||
19,343 ms
|
||||
|
||||
## Human Semantic Classification: PASS
|
||||
|
||||
### Rationale
|
||||
`userSupportedMeaning` clearly preserves that avoiding additional risk is an explicit hard constraint with no accepted increase in risk. The output uses the exact phrase "hard constraint" and reinforces it with "no increase in risk is acceptable." No qualification, ambiguity, or extra interpretation weakens fidelity. `possibleInference` is null, which is appropriate for a direct, unambiguous answer.
|
||||
|
||||
### Specific checks
|
||||
- **Preserves explicit hard-constraint status:** YES — the words "hard constraint" appear directly, reinforced by "no increase in risk is acceptable."
|
||||
- **Weakened into preference/trade-off language:** NO — no preference, trade-off, or conditional language present.
|
||||
- **Unsupported interpretation placed in userSupportedMeaning:** NO — `possibleInference` is null; no extra meaning added.
|
||||
|
||||
## What This Experiment Established
|
||||
For Regression D, the configured live Ollama model (`qwen-claude:latest`) preserves explicit hard-constraint meaning without weakening it. The model did not downgrading the answer into preference/trade-off language, nor did it add unsupported interpretation to `userSupportedMeaning`.
|
||||
|
||||
## What This Experiment Does NOT Prove
|
||||
- Semantic fidelity for other regression cases (E, F, or others).
|
||||
- Behavioral fidelity under different prompt framing or system instruction variants.
|
||||
- Consistency across multiple calls (single-call probe only).
|
||||
- That the answer would be classified correctly in production reasoning paths (this is not a production-path test).
|
||||
- That other models or model versions would behave identically.
|
||||
@@ -0,0 +1,64 @@
|
||||
# Experiment 56K — Evidence-resolvable disagreement must not become user clarification
|
||||
|
||||
**Date:** 2026-08-09
|
||||
**Branch:** `feature/reasoning-fidelity-v0.8`
|
||||
**Type:** Live semantic probe (single call)
|
||||
**Status:** PASS
|
||||
|
||||
## Objective
|
||||
|
||||
Determine whether the configured model can distinguish uncertainty that requires external evidence from uncertainty that requires the user to clarify their own meaning, for **Regression E**.
|
||||
|
||||
## Regression E — Fixed case (exact)
|
||||
|
||||
- **Source:** Delivery delay concern.
|
||||
- **Competing causes:** "Staff capacity may be the issue" / "Supplier lead times are likely responsible."
|
||||
- **Expected preserved meaning:** Two distinct hypotheses about causation.
|
||||
- **Expected uncertainty:** Which hypothesis is correct — resolvable by evidence gathering, not user clarification.
|
||||
- **Must not happen:** Generating a user-facing clarification question when evidence sources can distinguish the hypotheses.
|
||||
|
||||
## Pre-written human reference (before model inspection)
|
||||
|
||||
> The unresolved disagreement can be reduced by obtaining relevant evidence. It must not be treated as missing user-owned meaning merely because the engine does not yet know which interpretation is correct. A correct result should preserve the difference between evidence needed to determine what is true, and clarification needed because only the user can establish what they mean, prefer, intend, define, or constrain.
|
||||
|
||||
Expected correct classification: `evidence_needed`
|
||||
|
||||
## Configuration
|
||||
|
||||
- **Host:** `http://192.168.1.111:11434`
|
||||
- **Model:** `qwen-claude:latest`
|
||||
- **Pattern:** Direct Ollama `/api/chat` call (from Experiment 55D historical test, commit `fcb7218407a2921e9197dbb0a65e4e1282459e4c`)
|
||||
- **Format:** `json`, `stream: false`
|
||||
|
||||
## Live call result
|
||||
|
||||
- **Call count:** 1
|
||||
- **Duration:** 18,580 ms
|
||||
- **uncertaintyType:** `evidence_needed`
|
||||
- **reason:** "The uncertainty involves competing objective causes for a delivery delay, which can be resolved by gathering factual data rather than clarifying user intent."
|
||||
- **evidenceNeeded:** "Current internal staffing capacity levels and external supplier lead time records"
|
||||
- **userClarificationNeeded:** (not included in output contract)
|
||||
|
||||
## Human semantic classification: PASS
|
||||
|
||||
**Rationale:** The model correctly identified the disagreement as `evidence_needed`. It specified concrete evidence that could resolve the competing hypotheses without introducing any user clarification requirement. This matches the pre-written human reference and confirms the model can distinguish evidence-resolvable uncertainty from user-owned ambiguity in this case.
|
||||
|
||||
## What this experiment establishes
|
||||
|
||||
- For Regression E (delivery delay with competing causal hypotheses), the model correctly classifies the uncertainty as requiring evidence, not user clarification.
|
||||
- The model specified concrete, relevant evidence to seek — demonstrating it understood the nature of the disagreement rather than producing a generic or tautological classification.
|
||||
- The evidence-vs-user-meaning distinction was preserved in this single tested case.
|
||||
|
||||
## What this experiment does NOT prove
|
||||
|
||||
- That the same boundary holds for Regression F (user-owned ambiguity: preference vs constraint).
|
||||
- That the model consistently makes this distinction across different domains, phrasings, or weaker prompts.
|
||||
- That downstream reasoning steps (graph update, Behaviour Selection) will preserve this distinction.
|
||||
- That the distinction holds with other models or on this host without network variation.
|
||||
- That end-to-end production flow preserves the classification.
|
||||
|
||||
## Critical rule compliance
|
||||
|
||||
- Production reasoning code changed: **NO**
|
||||
- Generic harness created/modified: **NO**
|
||||
- Retries/additional calls: **0**
|
||||
@@ -0,0 +1,78 @@
|
||||
# Experiment 56L — User-owned ambiguity boundary probe
|
||||
|
||||
## Objective
|
||||
|
||||
Can the configured model recognise that an unresolved distinction belongs to the user's own meaning and therefore requires clarification rather than external evidence gathering?
|
||||
|
||||
## Config
|
||||
|
||||
- **Ollama base URL:** `http://192.168.1.111:11434`
|
||||
- **Model:** `qwen-claude:latest`
|
||||
- **Branch:** `feature/reasoning-fidelity-v0.8`
|
||||
- **Start HEAD:** [current HEAD at time of experiment]
|
||||
|
||||
## Fixed Case (Regression F)
|
||||
|
||||
- **Source:** "I want the business to grow, but I don't want to take on more risk."
|
||||
- **Answer context:** (ambiguous statement about both growth and risk — user has not specified preference/trade-off versus hard constraint)
|
||||
- **Expected preserved meaning:** User has not specified whether avoiding additional risk is a hard constraint or a strong preference/trade-off.
|
||||
- **Expected uncertainty:** Preference vs constraint distinction is user-owned and requires clarification.
|
||||
- **Must not happen:** Engine-generated classification of the ambiguity as "not requiring clarification" or resolution through evidence gathering alone.
|
||||
|
||||
## Pre-written Human Reference (written before model output)
|
||||
|
||||
```json
|
||||
{
|
||||
"uncertaintyType": "user_clarification_needed",
|
||||
"reason": "The unresolved distinction (whether avoiding additional risk is a hard constraint or a strong preference/trade-off) belongs to the user's own meaning. External evidence cannot establish what the user means, prefers, intends, defines, or constrains on their own behalf.",
|
||||
"evidenceNeeded": null,
|
||||
"userClarificationNeeded": "Whether the user treats avoiding additional risk as a hard constraint (non-negotiable boundary) versus a strong preference/trade-off (weighted but potentially overrideable)."
|
||||
}
|
||||
```
|
||||
|
||||
## Live-call Result
|
||||
|
||||
- **Call duration:** 14,032 ms
|
||||
- **Call count:** 1
|
||||
|
||||
### Raw Structured Response
|
||||
|
||||
```json
|
||||
{
|
||||
"uncertaintyType": "user_clarification_needed",
|
||||
"reason": "The ambiguity concerns whether avoiding additional risk is a strict hard constraint or a flexible preference, which reflects the user's private intent and priorities that external data cannot determine.",
|
||||
"evidenceNeeded": null,
|
||||
"userClarificationNeeded": "Whether avoiding additional risk is a non-negotiable hard constraint or a trade-off preference that can be balanced against business growth goals."
|
||||
}
|
||||
```
|
||||
|
||||
## Human Semantic Classification: PASS
|
||||
|
||||
**Rationale:** The model clearly recognises the ambiguity belongs to the user's own meaning and requires user clarification rather than external evidence. It preserved the distinction cleanly: `uncertaintyType` is `user_clarification_needed`, `evidenceNeeded` is null (no spurious evidence target introduced), and `userClarificationNeeded` specifically describes the preference/trade-off versus hard-constraint distinction that only the user can establish.
|
||||
|
||||
## Comparison with Pre-written Human Reference
|
||||
|
||||
- **Expected:** `user_clarification_needed`
|
||||
- **Actual:** `user_clarification_needed`
|
||||
- **Matches:** YES
|
||||
|
||||
The model's answer matches the human reference at the category level and substantively agrees on both what is unclear and why (the distinction is private to user meaning, not externally determinable).
|
||||
|
||||
## What This Experiment Established
|
||||
|
||||
1. The configured model (`qwen-claude:latest`) can distinguish user-owned ambiguity from evidence-resolvable uncertainty for Regression F's canonical case.
|
||||
2. It correctly identified that the preference-vs-constraint distinction is user-owned and requires clarification, not evidence gathering.
|
||||
3. It did not introduce unnecessary evidence targets where none apply.
|
||||
|
||||
## What This Experiment Does NOT Prove
|
||||
|
||||
1. Consistency across repeated runs with this or other models.
|
||||
2. Fidelity for other regression cases (A–E, G+).
|
||||
3. Behavior in production reasoning paths or graph-update contexts.
|
||||
4. Downstream integration with Behaviour Selection, UI, or the SituationGraph.
|
||||
5. Whether clarification targeting is precise enough to generate a useful user-facing question (that was explicitly excluded from this experiment's scope per output contract).
|
||||
|
||||
## Files
|
||||
|
||||
- Test: `tests/reconstruction/semantic-regression-f-user-owned-ambiguity.test.js`
|
||||
- Document: `docs/experiment-56l.md`
|
||||
@@ -0,0 +1,93 @@
|
||||
# Experiment 56M — Validate Evidence vs Clarification Routing
|
||||
|
||||
**Date:** 2026-08-09
|
||||
**Branch:** `feature/reasoning-fidelity-v0.8`
|
||||
**Codex refinement validated:** `f861e2c` (reasoning: preserve evidence versus clarification distinction)
|
||||
**Ollama calls:** 0
|
||||
|
||||
## Objective
|
||||
|
||||
Validate one production claim: after Codex commit `f861e2c`, does the production question-formulation boundary keep Regression E on an evidence route and Regression F on a user-clarification route?
|
||||
|
||||
This experiment isolates whether the deterministic production boundary preserves the distinction. No live model call is required because Codex changed deterministic production logic, not semantic interpretation.
|
||||
|
||||
## Method
|
||||
|
||||
Exercised both regression cases against the real `formulateQuestion()` implementation via an inline Node.js session. Captured full output objects including reasoning pattern, investigation strategy, question family, template, and exact question text.
|
||||
|
||||
No Ollama calls were made. Experiments 56K and 56L already established that the configured model can distinguish evidence-resolvable uncertainty from user-owned ambiguity.
|
||||
|
||||
## Regression E — Evidence-resolvable disagreement
|
||||
|
||||
**Input:**
|
||||
- `label`: "Possible causes of the delivery delay"
|
||||
- `description`: "Need to determine whether staff capacity or supplier lead times are responsible for the delivery delay."
|
||||
- `centralStatement`: "Delivery is delayed and the cause is still unknown."
|
||||
|
||||
**Produced question:** "What evidence would clarify possible causes of the delivery delay?"
|
||||
|
||||
**Reasoning pattern:** diagnosis (reason: "Selected diagnosis as the default because the active unknown needs clarifying evidence or mechanism-level investigation.")
|
||||
|
||||
**Investigation strategy:** `evidence_gathering` (reason: "Selected because evidence about the practical limiting factor is needed before the unknown can be resolved.")
|
||||
|
||||
**Question family:** diagnosis
|
||||
**Template:** diagnosis_evidence
|
||||
|
||||
**Semantic assessment:**
|
||||
- The question clearly seeks evidence capable of distinguishing the competing external hypotheses.
|
||||
- It does NOT ask the user to settle which external cause is true.
|
||||
- Both reasoning pattern (diagnosis) and strategy (evidence_gathering) align with an evidence route.
|
||||
|
||||
**Classification: PASS**
|
||||
|
||||
## Regression F — User-owned ambiguity
|
||||
|
||||
**Input:**
|
||||
- `label`: "Whether avoiding additional risk is a hard constraint"
|
||||
- `description`: "Need to know whether avoiding additional risk is a hard constraint or a preference/trade-off."
|
||||
|
||||
**Produced question:** "Is avoiding additional risk a hard constraint or a preference/trade-off?"
|
||||
|
||||
**Reasoning pattern:** prioritisation (reason: "Selected prioritisation because the active unknown is about ordering options or trade-offs.")
|
||||
- **Note:** This is correct — the `isPrioritisationPatternCandidate` check fires on "preference/trade-off" in the label, producing a valid reasoning pattern even though the question itself bypasses pattern-dependent template logic.
|
||||
|
||||
**Investigation strategy:** null (intentionally — user-meaning boundary triggers early return before strategy selection)
|
||||
|
||||
**Question family:** prioritisation
|
||||
**Template:** user_meaning_clarification
|
||||
|
||||
**Semantic assessment:**
|
||||
- The question explicitly clarifies the hard-constraint versus preference/trade-off boundary.
|
||||
- It does NOT pretend external evidence can establish this distinction.
|
||||
- `rejectedQuestionFamilies` correctly excludes evidence_gathering, diagnosis, explanation, contradiction, and comparison.
|
||||
- `allowedQuestionFamilies` correctly includes only prioritisation variants.
|
||||
|
||||
**Classification: PASS**
|
||||
|
||||
## What This Validation Established
|
||||
|
||||
1. After commit `f861e2c`, the production question-formulation code preserves the E/F distinction in deterministic reasoning:
|
||||
- Regression E (competing causal hypotheses, resolvable by evidence) routes to `diagnosis` pattern + `evidence_gathering` strategy → evidence-seeking question.
|
||||
- Regression F (constraint-versus-preference boundary, user-owned) triggers early-return at `isUserOwnedMeaningBoundaryUnknown()` → user-clarification question with null strategy.
|
||||
|
||||
2. The routing mechanism is the `isUserOwnedMeaningBoundaryUnknown()` guard in `formulateQuestion()` (line ~1773), which fires before any investigation strategy or question family selection for node F inputs.
|
||||
|
||||
3. The rejected/allowed question families confirm no evidence-adjacent families are permitted for user-owned boundary cases.
|
||||
|
||||
4. All 19 existing tests in `tests/graph/question-formulator.test.js` continue to pass — no regression from the E/F routing change.
|
||||
|
||||
## What This Validation Does NOT Prove
|
||||
|
||||
1. Consistency of this behavior across repeated runs (no live model call was made).
|
||||
2. Fidelity for other regression cases (A–D, G+).
|
||||
3. Behavior when external evidence is later added to the graph and both routes remain available.
|
||||
4. Downstream integration with Behaviour Selection or the SituationGraph.
|
||||
5. Whether the wording of the produced questions is optimal for real users (that was covered in earlier experiments).
|
||||
|
||||
## Production Files Modified
|
||||
|
||||
None. This experiment reads production code only — no modification was made to any production file.
|
||||
|
||||
---
|
||||
|
||||
*Experiment 56M. Status: Rob's review.*
|
||||
Reference in New Issue
Block a user