tooling: supply anchored previous question in update-only mode
This commit is contained in:
@@ -239,7 +239,10 @@ async function runUpdateOnlyMode() {
|
||||
|
||||
// Deep-copy so mutation doesn't corrupt the original fixture.
|
||||
const situationGraph = JSON.parse(JSON.stringify(initialGraph));
|
||||
let selectedQuestion = null;
|
||||
|
||||
// Derive previousQuestion from the committed savings-realism anchor so that
|
||||
// update-only mode can reach the production Update path without requiring Start.
|
||||
let selectedQuestion = fixtureData.unresolved_question ?? savingsNode.label;
|
||||
|
||||
// ── Exactly one Update through production route ────────
|
||||
const updateNum = 1;
|
||||
|
||||
@@ -651,15 +651,53 @@ describe("reproduce-multi-turn-investigation harness: one-shot semantics", () =>
|
||||
expect(r.startCalls).toBe(0);
|
||||
expect(r.updateCalls).toBe(1);
|
||||
|
||||
// Direct assertion: exact fixture graph transmitted (57J.81)
|
||||
const updateBody = r.capturedUpdateBody;
|
||||
expect(updateBody.situationGraph).toBeDefined();
|
||||
const fixtureGraph = PRE_ANCHORED_FIXTURE.graph;
|
||||
expect(JSON.parse(JSON.stringify(updateBody.situationGraph.nodes))).toEqual(fixtureGraph.nodes);
|
||||
expect(JSON.parse(JSON.stringify(updateBody.situationGraph.edges))).toEqual(fixtureGraph.edges);
|
||||
|
||||
// Verify the captured graph matches what was sent
|
||||
const { nodes, edges } = r;
|
||||
const fixtureGraph = PRE_ANCHORED_FIXTURE.graph;
|
||||
expect(nodes.length).toBe(fixtureGraph.nodes.length);
|
||||
expect(edges.length).toBe(fixtureGraph.edges.length);
|
||||
expect(nodes[0].id).toBe(fixtureGraph.nodes[0].id);
|
||||
expect(nodes[1].id).toBe(fixtureGraph.nodes[1].id);
|
||||
});
|
||||
|
||||
it("57J.81 update-only previousQuestion is non-empty string and matches the committed savings-realism anchor", () => {
|
||||
const r = runPreAnchoredSimulation();
|
||||
expect(r.startCalls).toBe(0);
|
||||
expect(r.updateCalls).toBe(1);
|
||||
|
||||
const prevQ = r.capturedUpdateBody.previousQuestion;
|
||||
expect(typeof prevQ).toBe("string");
|
||||
expect(prevQ.length).toBeGreaterThan(0);
|
||||
// Must correspond exactly to the anchored savings-realism uncertainty
|
||||
expect(prevQ).toBe(PRE_ANCHORED_FIXTURE.unresolvedQuestion);
|
||||
expect(prevQ).toBe("Are the projected office savings from relocation realistic?");
|
||||
});
|
||||
|
||||
it("57J.81 update-only exact ANSWER_2 sent as request answer", () => {
|
||||
const customAnswer = "The projected savings are based on the current London lease and business rates.";
|
||||
const r = runPreAnchoredSimulation({ answer: customAnswer });
|
||||
expect(r.startCalls).toBe(0);
|
||||
expect(r.updateCalls).toBe(1);
|
||||
|
||||
// Direct assertion of exact ANSWER_2 in request body
|
||||
expect(r.capturedUpdateBody.answer).toBe(customAnswer);
|
||||
});
|
||||
|
||||
it("57J.81 missing ANSWER_2 blocks before any HTTP call", () => {
|
||||
const r = runPreAnchoredSimulationWithBlock();
|
||||
expect(r.startCalls).toBe(0);
|
||||
expect(r.updateCalls).toBe(0);
|
||||
expect(r.type).toBe("blocked_no_answer");
|
||||
expect(r.blockedMessage).toContain("missing ANSWER_2");
|
||||
expect(r.apiLog.length).toBe(0);
|
||||
});
|
||||
|
||||
it("pre-anchored update-only mode does not call Start", () => {
|
||||
const r = runPreAnchoredSimulation();
|
||||
expect(r.startCalls).toBe(0);
|
||||
@@ -1061,7 +1099,14 @@ function runPreAnchoredSimulation(cfg) {
|
||||
|
||||
// Pre-anchored: no Start call — graph is supplied directly.
|
||||
let graph = JSON.parse(JSON.stringify(initialGraph));
|
||||
let question = null; // will be set by the update response (or mock)
|
||||
|
||||
// Derive previousQuestion from the committed savings-realism anchor
|
||||
// (mirrors the harness fix in reproduce-multi-turn-investigation.mjs).
|
||||
const unresolvedQuestion = PRE_ANCHORED_FIXTURE.unresolvedQuestion;
|
||||
let question = unresolvedQuestion; // fixture always has this field for pre-anchored mode
|
||||
|
||||
// Track the exact Update request body for direct assertions.
|
||||
let capturedUpdateBody = null;
|
||||
|
||||
const api = {
|
||||
post(path, body) {
|
||||
@@ -1073,6 +1118,7 @@ function runPreAnchoredSimulation(cfg) {
|
||||
|
||||
if (path === "/api/cases/update") {
|
||||
apiLog.push({ step: "update", answer: body.answer });
|
||||
capturedUpdateBody = body; // capture for direct request-body assertions
|
||||
updateCalls++;
|
||||
|
||||
const resp = typeof C.onResponseUpdate === "function"
|
||||
@@ -1161,6 +1207,7 @@ function runPreAnchoredSimulation(cfg) {
|
||||
selectedQuestion: sq && typeof sq === "object" ? { question: sq.question, nodeId: sq.nodeId } : null,
|
||||
graph: { nodes: uj.updatedSituationGraph?.nodes ?? [], edges: uj.updatedSituationGraph?.edges ?? [] },
|
||||
},
|
||||
capturedUpdateBody,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user