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.
This commit is contained in:
2026-08-11 08:33:36 +01:00
parent 79377670e2
commit 0348921542
4 changed files with 444 additions and 0 deletions
+57
View File
@@ -3208,4 +3208,61 @@ describe("applyValidatedProposal", () => {
}
expect(result.success).toBe(true);
});
// ── Experiment 57J.31 — diagnostics integration tests (rejecting fixture unchanged) ──
it("identical rejected fixture still rejects (same stage, no new mutations)", () => {
const { graph, proposal } = makeApplicationFixture();
const result = applyValidatedProposal({
situationGraph: graph,
proposal: {
...proposal,
addedNodes: [
makeNode({
id: "n-ghost",
label: "Ghost unknown",
description: "An unknown not grounded in any existing node.",
kind: "unknown",
status: "unknown",
confidence: "medium",
}),
],
addedEdges: [
makeEdge({
id: "e-ghost-edge",
fromNodeId: "n-ghost",
toNodeId: "neb1bz2",
relationship: "depends_on",
confidence: "medium",
description: "Ghost edge.",
}),
],
},
});
expect(result.success).toBe(false);
expect(result.stage).toBe("proposal_compatibility");
expect(result.updatedSituationGraph).toBeUndefined();
expect(result.changesApplied).toBeUndefined();
});
it("successful proposal behaviour unchanged (same pass result, same applied mutations)", () => {
const fixture = makeComparabilityUpdateFixture();
const result = applyValidatedProposal({
situationGraph: fixture.graph,
proposal: fixture.proposal,
});
expect(result.success).toBe(true);
// applyValidatedProposal does NOT return a stage field on success — only on failure.
// The comparability unknown should be resolved with the answer-provided value.
const resolvedNode = result.updatedSituationGraph.nodes.find(
(n) => n.id === fixture.comparabilityUnknownId,
);
expect(resolvedNode.status).toBe("resolved");
expect(resolvedNode.value).toBe(
"Both figures cover the same accounting period and are taken from the same management accounts.",
);
});
});