fix(confidence-engine): scope contribution filtering to targetNodeId in composeDeepInvestigationCheckpoint

Historical contributions for a different Open Question node no longer
suppress fresh focused deconstruction of the current target. Only
contributions whose targetNodeId matches the current target are counted
towards suppressing redundant deconstruction.
This commit is contained in:
2026-10-08 07:34:28 +01:00
parent ddd1c7bd6f
commit 99f200303a
2 changed files with 26 additions and 1 deletions
@@ -462,6 +462,22 @@ assert(typeof composeDeepInvestigationCheckpoint === "function", "composeDeepInv
// AC3. The helper structure is intact — no production code was rewritten // AC3. The helper structure is intact — no production code was rewritten
assert(helperSrc.includes("const provider = getProvider()") && helperSrc.includes("const timedProvider = {"), "helper still creates both raw provider and timedWrapper (architecture preserved)"); assert(helperSrc.includes("const provider = getProvider()") && helperSrc.includes("const timedProvider = {"), "helper still creates both raw provider and timedWrapper (architecture preserved)");
// ---- ITERATION 15: TARGET-SCOPED CONTRIBUTION HANDLING ──────────────────────
// Historical contributions for node A must not suppress deconstruction for node B.
console.log("\n=== ITERATION 15: TARGET-SCOPED CONTRIBUTION HANDLING ===\n");
// Case A: Empty contributions trigger fresh deconstruction — verified by condition using effectiveContributionsForTarget.length (0) when no matching contributions exist for the target
assert(helperSrc.includes("effectiveContributionsForTarget.length") && helperSrc.includes("=== 0"), "Case A: deconstruction guard checks effectiveContributionsForTarget length (empty → trigger deconstruct)");
// Case B: Contributions filtered by targetNodeId — historical contributions from a different node must not block fresh deconstruction of the current target
assert(helperSrc.includes("effectiveContributions.filter") && helperSrc.includes("targetNodeId"), "Case B: contributions filtered by targetNodeId before length check (scoping mechanism present)");
// Case C: Existing contributions for node B do trigger suppression — verified implicitly by same filtering mechanism (matching contributions → effectiveContributionsForTarget.length > 0 → no deconstruct)
assert(helperSrc.includes("effectiveContributionsForTarget.length") && helperSrc.includes("=== 0"), "Case C: matching contributions suppress redundant deconstruction (same guard, same check)");
// Case D: Historical contributions remain present in returned state — postEpisodeContributions includes all effectiveContributions
assert(helperSrc.includes("postEpisodeContributions: effectiveContributions") || helperSrc.includes("postEpisodeContributions : effectiveContributions"), "Case D: accumulated effectiveContributions (historical + new) returned via postEpisodeContributions");
// ---- CU SYNTHESIS OBSERVABILITY (Batch 3 Iteration 1) ───────────────────── // ---- CU SYNTHESIS OBSERVABILITY (Batch 3 Iteration 1) ─────────────────────
console.log("\n=== CU SYNTHESIS OBSERVABILITY ===\n"); console.log("\n=== CU SYNTHESIS OBSERVABILITY ===\n");
+10 -1
View File
@@ -316,9 +316,18 @@ async function composeDeepInvestigationCheckpoint({ situationGraph, previousQues
/* ── Canonical deconstruction: use focusedDeconstruct for Contribution derivation ─── */ /* ── Canonical deconstruction: use focusedDeconstruct for Contribution derivation ─── */
const effectiveContributions = contributions.length > 0 ? [...contributions] : []; const effectiveContributions = contributions.length > 0 ? [...contributions] : [];
/* ── Target-scoped filtering: only contributions belonging to the current target suppress fresh deconstruction ─── */
let effectiveContributionsForTarget = effectiveContributions;
if (targetNodeId && effectiveContributions.length > 0) {
effectiveContributionsForTarget = effectiveContributions.filter(
(c) => c?.targetNodeId === targetNodeId,
);
}
let newFindingsFromContributions = []; let newFindingsFromContributions = [];
if (effectiveContributions.length === 0 && answer && targetNodeId) { if (effectiveContributionsForTarget.length === 0 && answer && targetNodeId) {
const contribSeq = effectiveContributions.length + 1; const contribSeq = effectiveContributions.length + 1;
/* ── Load production deconstruction seam (dynamic import to resolve ESM path aliases) ─── */ /* ── Load production deconstruction seam (dynamic import to resolve ESM path aliases) ─── */