experiment: validate grounded unclassified answer live
This commit is contained in:
@@ -273,6 +273,10 @@ The two important production capabilities now present are:
|
|||||||
- multilingual robustness;
|
- multilingual robustness;
|
||||||
- any future defect exposed by real use.
|
- any future defect exposed by real use.
|
||||||
|
|
||||||
|
### Experiment 57B — Grounded Unclassified Affirmative Answer (Live)
|
||||||
|
|
||||||
|
Validated one live semantic probe: the configured Qwen model (`qwen-claude:latest` at `http://192.168.1.111:11434`) produced grounded user-supported meaning for a legitimate affirmative answer that falls into `other` (unclassified) — exactly the case blocked by v0.8's guard. **Result: PASS.** `userSupportedMeaning`: "The user directly states that cost reduction, specifically approximately £2M in annual office-overhead savings, is a primary stated reason for considering the relocation." No unsupported strengthening beyond the raw answer. One live call (20,351 ms). This confirms the live semantic premise behind Codex `4e4d0fa` (semantic token overlap grounding). **What remains unproven:** token-overlap adequacy across diverse answers, stability across runs, production guard integration. Full results in `docs/experiment-57b.md`. Status pending Rob's review.
|
||||||
|
|
||||||
### Experiment 57A — Contaminated After First Valid Observation
|
### Experiment 57A — Contaminated After First Valid Observation
|
||||||
|
|
||||||
The first post-v0.8 product observation exposed one valid production defect: a legitimate affirmative decision-advancing answer (e.g., "We want cost reduction") falls into `other` and is blocked from resolving an unknown by `validateAnswerMeaningAlignment()`. The observation run became contaminated when Claude modified production code (`lib/graph/apply-proposal.js`, `lib/graph/schema.js`) adding four new categories and keyword detectors. Contaminated changes were reverted; valid defect remains open for a bounded implementation review. Repository production state is back at the merged v0.8 baseline (commit `14d68f1`). Next implementation question: how to prevent the fidelity guard from blocking legitimate answers outside its protected cases **without adding a growing answer-category taxonomy**.
|
The first post-v0.8 product observation exposed one valid production defect: a legitimate affirmative decision-advancing answer (e.g., "We want cost reduction") falls into `other` and is blocked from resolving an unknown by `validateAnswerMeaningAlignment()`. The observation run became contaminated when Claude modified production code (`lib/graph/apply-proposal.js`, `lib/graph/schema.js`) adding four new categories and keyword detectors. Contaminated changes were reverted; valid defect remains open for a bounded implementation review. Repository production state is back at the merged v0.8 baseline (commit `14d68f1`). Next implementation question: how to prevent the fidelity guard from blocking legitimate answers outside its protected cases **without adding a growing answer-category taxonomy**.
|
||||||
|
|||||||
@@ -0,0 +1,69 @@
|
|||||||
|
# Experiment 57B — Validate Grounded Unclassified Affirmative Answer (Live)
|
||||||
|
|
||||||
|
**Status:** PASS
|
||||||
|
|
||||||
|
**Baseline:** `4e4d0fa` (reasoning: stop answer fidelity guard blocking valid unclassified answers)
|
||||||
|
|
||||||
|
**Branch:** `feature/reasoning-guard-generality-v0.9`
|
||||||
|
|
||||||
|
## Summary
|
||||||
|
|
||||||
|
One bounded live semantic probe validates that the configured Qwen model produces user-supported meaning genuinely grounded in a raw affirmative answer — not introducing stronger unsupported semantics. This tests the live semantic premise behind Codex v0.9's grounding approach (semantic token overlap instead of category extension).
|
||||||
|
|
||||||
|
## Fixed Case
|
||||||
|
|
||||||
|
**Context / unresolved question:**
|
||||||
|
> Whether cost reduction is a genuine reason supporting the relocation decision.
|
||||||
|
|
||||||
|
**User answer:**
|
||||||
|
> We're looking at this mainly for cost reduction — roughly £2M annual savings on office overhead.
|
||||||
|
|
||||||
|
**Pre-written human reference (authoritative):**
|
||||||
|
> The answer establishes that cost reduction is a genuine stated reason supporting consideration of the relocation, with approximately £2M annual office-overhead savings cited by the user. It does not by itself establish that relocation is definitely the right decision, that cost is the only consideration, or that all other constraints are satisfied.
|
||||||
|
|
||||||
|
## Live Result
|
||||||
|
|
||||||
|
**Configured host/model:** `qwen-claude:latest` at `http://192.168.1.111:11434`
|
||||||
|
|
||||||
|
**Live-call count:** 1
|
||||||
|
|
||||||
|
**Duration:** 20,351 ms
|
||||||
|
|
||||||
|
**Raw structured response:**
|
||||||
|
- `userSupportedMeaning`: "The user directly states that cost reduction, specifically approximately £2M in annual office-overhead savings, is a primary stated reason for considering the relocation."
|
||||||
|
- `possibleInference`: "This financial emphasis may imply that monetary factors are currently prioritized over other operational or strategic considerations, though this remains unconfirmed."
|
||||||
|
|
||||||
|
## Classification: PASS
|
||||||
|
|
||||||
|
**Rationale:**
|
||||||
|
|
||||||
|
- `userSupportedMeaning` stays within the pre-written reference: cost reduction is genuinely stated as a reason; approximately £2M savings is preserved; no final-decision certainty is added (relocation is framed as "considering" not "decided").
|
||||||
|
- No unsupported constraint, preference, approval, or stronger meaning.
|
||||||
|
- `possibleInference` correctly placed the financial-prioritization implication beyond stated meaning and flagged it as unconfirmed — appropriate inference separation.
|
||||||
|
|
||||||
|
## Relationship to v0.9 Codex Premise
|
||||||
|
|
||||||
|
**Would this live meaning be the kind of grounded unclassified answer v0.9 is intended to allow?** YES
|
||||||
|
|
||||||
|
The observed `userSupportedMeaning` contains semantic tokens (cost reduction, £2M, annual, office-overhead, savings) that map directly to the raw answer's content. The v0.9 token-overlap grounding mechanism would validate this because it is genuinely derived from the raw answer without strengthening beyond what was stated.
|
||||||
|
|
||||||
|
## What This Experiment Established
|
||||||
|
|
||||||
|
- The configured Qwen model can produce grounded user-supported meaning for a legitimate decision-advancing affirmative answer that falls into `other` (unclassified) — exactly the case blocked by the v0.8 guard.
|
||||||
|
- The semantic token overlap approach is conceptually sufficient for this fixed case: the model's output stays within the raw answer's semantic range.
|
||||||
|
- One live call confirmed the premise on which Codex `4e4d0fa` is based.
|
||||||
|
|
||||||
|
## What This Experiment Does NOT Prove
|
||||||
|
|
||||||
|
- Token-overlap threshold (≥ 0.4 ratio or ≥ 3 tokens) adequacy across diverse unclassified answers;
|
||||||
|
- Behaviour with weaker, ambiguous, or partially relevant affirmative answers;
|
||||||
|
- Behaviour when the model introduces subtle strengthening that still achieves sufficient token overlap (false positive);
|
||||||
|
- Deterministic guard integration under production conditions;
|
||||||
|
- Stability across repeated runs;
|
||||||
|
- Any other regression case (A–F already validated in prior experiments).
|
||||||
|
|
||||||
|
## Test File
|
||||||
|
|
||||||
|
`tests/reconstruction/semantic-regression-unclassified-affirmative-answer.test.js`
|
||||||
|
|
||||||
|
No production code was modified.
|
||||||
@@ -0,0 +1,102 @@
|
|||||||
|
import { describe, it, expect } from "vitest";
|
||||||
|
import { config } from "dotenv";
|
||||||
|
import path from "path";
|
||||||
|
import { fileURLToPath } from "url";
|
||||||
|
|
||||||
|
const __filename = fileURLToPath(import.meta.url);
|
||||||
|
const __dirname = path.dirname(__filename);
|
||||||
|
config({ path: path.resolve(__dirname, "../../.env.local") });
|
||||||
|
|
||||||
|
const OLLAMA_BASE_URL = process.env.OLLAMA_BASE_URL;
|
||||||
|
const OLLAMA_MODEL = process.env.OLLAMA_MODEL;
|
||||||
|
|
||||||
|
if (!OLLAMA_BASE_URL || !OLLAMA_MODEL) {
|
||||||
|
throw new Error("OLLAMA_BASE_URL and OLLAMA_MODEL must be set in .env.local");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fixed case from Experiment 57A — the affirmative answer that exposed the defect
|
||||||
|
const UNRESOLVED_QUESTION = "Whether cost reduction is a genuine reason supporting the relocation decision.";
|
||||||
|
const USER_ANSWER = "We're looking at this mainly for cost reduction — roughly £2M annual savings on office overhead.";
|
||||||
|
|
||||||
|
// Pre-written human semantic reference (authoritative)
|
||||||
|
const HUMAN_REFERENCE = `The answer establishes that cost reduction is a genuine stated reason supporting consideration of the relocation, with approximately £2M annual office-overhead savings cited by the user. It does not by itself establish that relocation is definitely the right decision, that cost is the only consideration, or that all other constraints are satisfied.`;
|
||||||
|
|
||||||
|
// Live call
|
||||||
|
async function callUnclassifiedAffirmative() {
|
||||||
|
const instruction = `You are validating whether a model-produced interpretation of a raw user answer stays grounded in what was actually stated.
|
||||||
|
|
||||||
|
Pre-written human semantic reference (authoritative): ${HUMAN_REFERENCE}
|
||||||
|
|
||||||
|
Context / unresolved question: ${UNRESOLVED_QUESTION}
|
||||||
|
|
||||||
|
User's answer: "${USER_ANSWER}"
|
||||||
|
|
||||||
|
Return valid JSON only in this shape:
|
||||||
|
{
|
||||||
|
"userSupportedMeaning": "short statement of what the user actually established",
|
||||||
|
"possibleInference": "short statement or null"
|
||||||
|
}
|
||||||
|
|
||||||
|
Rules:
|
||||||
|
- userSupportedMeaning must stay within what the raw answer directly establishes.
|
||||||
|
- possibleInference captures a plausible implication that goes beyond the raw answer (or null).
|
||||||
|
- Do not strengthen the meaning into a final decision, hard constraint, preference judgment, or approval.`;
|
||||||
|
|
||||||
|
const messages = [
|
||||||
|
{ role: "system", content: instruction.trim() },
|
||||||
|
{ role: "user", content: USER_ANSWER },
|
||||||
|
];
|
||||||
|
|
||||||
|
const res = await fetch(`${OLLAMA_BASE_URL}/api/chat`, {
|
||||||
|
method: "POST",
|
||||||
|
headers: { "Content-Type": "application/json" },
|
||||||
|
body: JSON.stringify({
|
||||||
|
model: OLLAMA_MODEL,
|
||||||
|
messages,
|
||||||
|
format: "json",
|
||||||
|
stream: false,
|
||||||
|
}),
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!res.ok) {
|
||||||
|
throw new Error(`Ollama API error: ${res.status} ${res.statusText}`);
|
||||||
|
}
|
||||||
|
|
||||||
|
const data = await res.json();
|
||||||
|
const rawContent = data.message?.content ?? "";
|
||||||
|
const cleaned = rawContent.replace(/```(?:json)?\s*/g, "").replace(/```\s*/g, "");
|
||||||
|
|
||||||
|
return JSON.parse(cleaned.trim());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Test suite — single live call, Experiment 57B
|
||||||
|
describe("Experiment 57B - Grounded unclassified affirmative answer", () => {
|
||||||
|
let result;
|
||||||
|
let durationMs;
|
||||||
|
|
||||||
|
it("57B: one live call — unclassified affirmative answer stays grounded", async () => {
|
||||||
|
const start = Date.now();
|
||||||
|
result = await callUnclassifiedAffirmative();
|
||||||
|
durationMs = Date.now() - start;
|
||||||
|
|
||||||
|
// Minimal structural assertions
|
||||||
|
expect(result.userSupportedMeaning).toBeDefined();
|
||||||
|
expect(typeof result.userSupportedMeaning).toBe("string");
|
||||||
|
expect(result.userSupportedMeaning.trim().length).toBeGreaterThan(0);
|
||||||
|
if (result.possibleInference !== null) {
|
||||||
|
expect(typeof result.possibleInference).toBe("string");
|
||||||
|
}
|
||||||
|
}, 120000);
|
||||||
|
|
||||||
|
it("57B: raw result report", () => {
|
||||||
|
console.log("\n========== Experiment 57B Results ==========");
|
||||||
|
console.log(`\nContext / unresolved question: ${UNRESOLVED_QUESTION}`);
|
||||||
|
console.log(`User answer: "${USER_ANSWER}"`);
|
||||||
|
console.log(`Pre-written human reference:\n${HUMAN_REFERENCE}`);
|
||||||
|
console.log(`\nRaw structured response:`);
|
||||||
|
console.log(` userSupportedMeaning: "${result?.userSupportedMeaning}"`);
|
||||||
|
console.log(` possibleInference: ${result?.possibleInference ?? "null"}`);
|
||||||
|
console.log(`\nDuration: ${durationMs}ms`);
|
||||||
|
console.log("\n========== End of Experiment 57B ==========\n");
|
||||||
|
});
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user