fix(confidence-engine): allow no-op episode reconsideration
This commit is contained in:
@@ -4089,7 +4089,16 @@ export async function applyValidatedProposal({
|
||||
);
|
||||
|
||||
if (!proposalGraphValidation.valid) {
|
||||
proposalCompatibilityErrors.push(...proposalGraphValidation.errors);
|
||||
const acceptsCompletedEpisodeNoOp = evidenceContext?.isCompletedEpisode === true;
|
||||
proposalCompatibilityErrors.push(
|
||||
...proposalGraphValidation.errors.filter(
|
||||
(error) =>
|
||||
!(
|
||||
acceptsCompletedEpisodeNoOp &&
|
||||
error === "Update contains no meaningful change"
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
const existingEdgeIds = new Set(situationGraph.edges.map((edge) => edge.id));
|
||||
|
||||
@@ -706,10 +706,10 @@ describe("applyValidatedProposal", () => {
|
||||
expect(graph).toEqual(originalGraph);
|
||||
});
|
||||
|
||||
it("rejects a proposal with no meaningful change", () => {
|
||||
it("rejects a proposal with no meaningful change", async () => {
|
||||
const { graph } = makeApplicationFixture();
|
||||
|
||||
const result = applyValidatedProposal({
|
||||
const result = await applyValidatedProposal({
|
||||
situationGraph: graph,
|
||||
proposal: {
|
||||
addedNodes: [],
|
||||
@@ -740,6 +740,68 @@ describe("applyValidatedProposal", () => {
|
||||
);
|
||||
});
|
||||
|
||||
it("accepts a completed-episode proposal with no additional graph mutation", async () => {
|
||||
const { graph } = makeApplicationFixture();
|
||||
const originalGraph = JSON.parse(JSON.stringify(graph));
|
||||
const noOpProposal = {
|
||||
addedNodes: [],
|
||||
updatedNodes: [
|
||||
{
|
||||
nodeId: "n-quality-deterioration",
|
||||
previousStatus: null,
|
||||
newStatus: null,
|
||||
previousValue: null,
|
||||
newValue: null,
|
||||
reason: "No further graph change.",
|
||||
},
|
||||
],
|
||||
addedEdges: [],
|
||||
removedEdgeIds: [],
|
||||
resolvedUnknownNodeIds: [],
|
||||
affectedNodeIds: [],
|
||||
selectedQuestion: null,
|
||||
};
|
||||
|
||||
const result = await applyValidatedProposal({
|
||||
situationGraph: graph,
|
||||
proposal: noOpProposal,
|
||||
evidenceContext: {
|
||||
isCompletedEpisode: true,
|
||||
episodeEvidence: {
|
||||
turns: [{ question: "What did you find?", answer: "No further change." }],
|
||||
eligibleCanonicalFindings: [{ proposition: "The episode is preserved." }],
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
expect(result.success).toBe(true);
|
||||
expect(result.updatedSituationGraph.nodes).toEqual(originalGraph.nodes);
|
||||
expect(result.updatedSituationGraph.edges).toEqual(originalGraph.edges);
|
||||
});
|
||||
|
||||
it("still rejects an invalid completed-episode proposal", async () => {
|
||||
const { graph } = makeApplicationFixture();
|
||||
|
||||
const result = await applyValidatedProposal({
|
||||
situationGraph: graph,
|
||||
proposal: {
|
||||
addedNodes: [],
|
||||
updatedNodes: [{ nodeId: "missing-node", reason: "Invalid target." }],
|
||||
addedEdges: [],
|
||||
removedEdgeIds: [],
|
||||
resolvedUnknownNodeIds: [],
|
||||
affectedNodeIds: [],
|
||||
selectedQuestion: null,
|
||||
},
|
||||
evidenceContext: { isCompletedEpisode: true, episodeEvidence: { turns: [] } },
|
||||
});
|
||||
|
||||
expect(result).toMatchObject({ success: false, stage: "proposal_compatibility" });
|
||||
expect(result.errors).toEqual(expect.arrayContaining([
|
||||
expect.stringContaining("Cannot update non-existent node"),
|
||||
]));
|
||||
});
|
||||
|
||||
it("resolves one unknown and adds consequential unknowns with one selected question", () => {
|
||||
const { graph, ids } = makeApplicationFixture();
|
||||
|
||||
|
||||
Reference in New Issue
Block a user