test(confidence-engine): preserve deep investigation episode state
This commit is contained in:
@@ -170,7 +170,7 @@ function _extractReasoningState(result) {
|
||||
/**
|
||||
* Run one live experiment through the real updateCase() production path.
|
||||
*/
|
||||
async function runLiveExperiment({ graph, previousQuestion, answer }) {
|
||||
async function runLiveExperiment({ graph, previousQuestion, answer, findings = [] }) {
|
||||
const baseUrl = assertRequiredEnv("OLLAMA_BASE_URL");
|
||||
const model = assertRequiredEnv("OLLAMA_MODEL");
|
||||
|
||||
@@ -207,7 +207,50 @@ async function runLiveExperiment({ graph, previousQuestion, answer }) {
|
||||
);
|
||||
const endToEndElapsedMs = Date.now() - endToEndStartedAt;
|
||||
|
||||
return extractLiveExperimentCheckpoint(result, { graph, answer });
|
||||
// ── accumulated state for longitudinal multi-episode use ───
|
||||
const updatedGraph = result?.updatedSituationGraph ?? null;
|
||||
const postEpisodeFs = Array.isArray(result?.findings) ? [...result.findings] : [];
|
||||
|
||||
return {
|
||||
/* ── CU narrative (UNAVAILABLE — synthesis is a separate seam from updateCase()) ─── */
|
||||
currentUnderstanding: "UNAVAILABLE",
|
||||
|
||||
/* ── updatedSituationGraph (NEW for longitudinal state feeding) ─── */
|
||||
updatedSituationGraph: updatedGraph,
|
||||
|
||||
/* ── postEpisodeFindings (NEW — accumulated Findings exposed for Episode N+1) ─── */
|
||||
postEpisodeFindings: postEpisodeFs,
|
||||
|
||||
/* ── graph checkpoint (from production result) ─── */
|
||||
graphCheckpoint: updatedGraph
|
||||
? {
|
||||
nodeCount: updatedGraph.nodes?.length ?? 0,
|
||||
edgeCount: updatedGraph.edges?.length ?? 0,
|
||||
resolvedNodeIds: updatedGraph.resolvedNodeIds ?? [],
|
||||
}
|
||||
: { nodeCount: 0, edgeCount: 0, resolvedNodeIds: [] },
|
||||
|
||||
/* ── findings checkpoint (count from accumulated Findings) ─── */
|
||||
findingsCheckpoint: {
|
||||
total: postEpisodeFs.length,
|
||||
eligible: "UNAVAILABLE",
|
||||
},
|
||||
|
||||
/* ── Timing ─── */
|
||||
modelElapsedMs: result?.modelElapsedMs !== undefined ? result.modelElapsedMs : null,
|
||||
endToEndElapsedMs: result?.endToEndElapsedMs !== undefined ? result.endToEndElapsedMs : null,
|
||||
providerGenerateCalls: result != null && result.providerGenerateCalls != null ? result.providerGenerateCalls : 0,
|
||||
modelName: result?.modelName || null,
|
||||
|
||||
/* ── answer meaning (from production result) ─── */
|
||||
userSupportedMeaning: result?.proposal?.answerMeaning?.userSupportedMeaning ?? null,
|
||||
possibleInference: result?.proposal?.answerMeaning?.possibleInference ?? null,
|
||||
|
||||
/* ── helper internals (for diagnostic / test verification) ─── */
|
||||
selectedQuestion: result?.proposal?.selectedQuestion ?? null,
|
||||
behaviourSelection: result?.behaviourSelection ?? null,
|
||||
reasoningState: _extractReasoningState(result),
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -225,7 +268,7 @@ async function runLiveExperiment({ graph, previousQuestion, answer }) {
|
||||
* - currentUnderstanding from the synthesis result
|
||||
* - findingsCheckpoint with accurate post-episode accumulated findings count
|
||||
*/
|
||||
async function composeDeepInvestigationCheckpoint({ situationGraph, previousQuestion, answer }) {
|
||||
async function composeDeepInvestigationCheckpoint({ situationGraph, previousQuestion, answer, findings = [] }) {
|
||||
dotenv.config({ path: ".env.local" });
|
||||
|
||||
const baseUrl = assertRequiredEnv("OLLAMA_BASE_URL");
|
||||
@@ -267,16 +310,11 @@ async function composeDeepInvestigationCheckpoint({ situationGraph, previousQues
|
||||
|
||||
/* ── Step 2: Current Understanding synthesis (mirrors production synthesizeFn) ─── */
|
||||
const updatedGraph = episodeResult.updatedSituationGraph;
|
||||
const accumulatedFindings = episodeResult.appendedFindings ?? [];
|
||||
|
||||
// Collect accumulated findings from the episode result for accurate counting
|
||||
let postEpisodeFindings = Array.isArray(accumulatedFindings) ? [...accumulatedFindings] : [];
|
||||
|
||||
// Derive eligible count via the same filter the production seam uses
|
||||
const { filterEligibleFindings } = await import("../../lib/graph/current-understanding-synthesis.js");
|
||||
const eligibleCount = postEpisodeFindings.length > 0
|
||||
? filterEligibleFindings(postEpisodeFindings).length
|
||||
: 0;
|
||||
// Accumulate prior findings + newly appended Findings for CU synthesis
|
||||
const priorFindings = Array.isArray(findings) ? [...findings] : [];
|
||||
const accumulatedEpisodes = episodeResult.appendedFindings ?? [];
|
||||
const postEpisodeFindings = [...priorFindings, ...accumulatedEpisodes];
|
||||
|
||||
let currentUnderstanding = null;
|
||||
if (episodeResult.success && updatedGraph) {
|
||||
@@ -291,31 +329,46 @@ async function composeDeepInvestigationCheckpoint({ situationGraph, previousQues
|
||||
currentUnderstanding = synthesized?.currentUnderstanding ?? null;
|
||||
}
|
||||
|
||||
// Consistent graphCheckpoint for both success and failure paths
|
||||
const graphCheckpoint = updatedGraph
|
||||
? {
|
||||
nodeCount: updatedGraph.nodes?.length ?? 0,
|
||||
edgeCount: updatedGraph.edges?.length ?? 0,
|
||||
resolvedNodeIds: updatedGraph.resolvedNodeIds ?? [],
|
||||
}
|
||||
: { nodeCount: 0, edgeCount: 0, resolvedNodeIds: [] };
|
||||
|
||||
// Accurate post-episode accumulated findings count
|
||||
const { filterEligibleFindings } = await import("../../lib/graph/current-understanding-synthesis.js");
|
||||
const eligibleCount = postEpisodeFindings.length > 0
|
||||
? filterEligibleFindings(postEpisodeFindings).length
|
||||
: 0;
|
||||
|
||||
return {
|
||||
/* ── CU synthesis result (NEW — mirrors production synthesizeFn) ─── */
|
||||
/* ── CU synthesis result (mirrors production synthesizeFn) ─── */
|
||||
currentUnderstanding,
|
||||
|
||||
/* ── Accurate post-episode findings count (FIX — uses actual accumulated Findings, not graph nodes) ─── */
|
||||
/* ── updatedSituationGraph (NEW — for longitudinal Episode N+1 state feeding) ─── */
|
||||
updatedSituationGraph: updatedGraph,
|
||||
|
||||
/* ── postEpisodeFindings (NEW — accumulated Findings for Episode N+1) ─── */
|
||||
postEpisodeFindings: postEpisodeFindings,
|
||||
|
||||
/* ── Accurate post-episode accumulated findings count ─── */
|
||||
findingsCheckpoint: {
|
||||
total: postEpisodeFindings.length,
|
||||
eligible: eligibleCount,
|
||||
},
|
||||
|
||||
/* ── Timing (mirrors extractLiveExperimentCheckpoint) ─── */
|
||||
/* ── graph checkpoint (from production result) ─── */
|
||||
graphCheckpoint,
|
||||
|
||||
/* ── Timing ─── */
|
||||
modelElapsedMs,
|
||||
endToEndElapsedMs,
|
||||
providerGenerateCalls,
|
||||
modelName: episodeResult.modelName ?? null,
|
||||
|
||||
/* ── Graph checkpoint (from production result) ─── */
|
||||
graphCheckpoint: updatedGraph
|
||||
? {
|
||||
nodeCount: updatedGraph.nodes?.length ?? 0,
|
||||
edgeCount: updatedGraph.edges?.length ?? 0,
|
||||
resolvedNodeIds: updatedGraph.resolvedNodeIds ?? [],
|
||||
}
|
||||
: null,
|
||||
|
||||
/* ── Answer meaning (from production result) ─── */
|
||||
userSupportedMeaning: episodeResult?.proposal?.answerMeaning?.userSupportedMeaning ?? null,
|
||||
possibleInference: episodeResult?.proposal?.answerMeaning?.possibleInference ?? null,
|
||||
|
||||
Reference in New Issue
Block a user