fix(rectification): stop stamping pending receipts and document aggregate blocker
Implement BUG-984 F2 option A and reproduce mixed completed identities through real tools. Stop at the required SQL authorization boundary; F1/F3/F4 remain pending. Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
@@ -109,7 +109,11 @@ test("unreachable versions retain the existing unknown-identity cache fallback,
|
||||
assert.equal(cachedEngineScoreIsReusable({ ...fingerprints, algorithmVersion: PREVIOUS }, fingerprints, live), true);
|
||||
});
|
||||
|
||||
test("new Case scoring writes the new version on both started and completed receipts", async (t) => {
|
||||
async function runGoldenToolSequence(t: test.TestContext, options: {
|
||||
compareVersion?: string;
|
||||
diagnosticsVersion?: string;
|
||||
diagnosticsFailure?: boolean;
|
||||
} = {}) {
|
||||
isolateIdentityEnv(t);
|
||||
const request = golden.request;
|
||||
const candidateRange = { start_time: request.start_time, end_time: request.end_time };
|
||||
@@ -123,7 +127,13 @@ test("new Case scoring writes the new version on both started and completed rece
|
||||
const path = new URL(String(url)).pathname;
|
||||
calls.push(path);
|
||||
if (path.endsWith("/versions")) return Response.json(golden.versions);
|
||||
if (path.endsWith("/score") || path.endsWith("/diagnostics")) return Response.json(golden.score);
|
||||
if (path.endsWith("/score")) {
|
||||
return Response.json({ ...golden.score, algorithm_version: options.compareVersion ?? CURRENT });
|
||||
}
|
||||
if (path.endsWith("/diagnostics")) {
|
||||
if (options.diagnosticsFailure) return Response.json({ error: "fixture_unavailable" }, { status: 503 });
|
||||
return Response.json({ ...golden.score, algorithm_version: options.diagnosticsVersion ?? CURRENT });
|
||||
}
|
||||
throw new Error(`unexpected engine request ${path}`);
|
||||
});
|
||||
const accounting = fakeAccounting({
|
||||
@@ -152,15 +162,44 @@ test("new Case scoring writes the new version on both started and completed rece
|
||||
});
|
||||
const tools = createRectificationV9Tools({ userId: USER_ID, caseId: CASE_ID, turnId: TURN_ID, accounting: accounting.client as never });
|
||||
for (const name of ["rectification-compare-candidates", "rectification-read-diagnostics"] as const) {
|
||||
await (tools[name] as unknown as { execute(input: unknown): Promise<unknown> }).execute({ caseId: CASE_ID });
|
||||
const receipts = accounting.calls.filter((call) => call.fn === "insert_agentic_rectification_tool_receipt" && call.args.p_tool_name === name);
|
||||
assert.deepEqual(receipts.map((call) => [call.args.p_status, call.args.p_engine_version]), [
|
||||
["started", CURRENT], ["completed", CURRENT],
|
||||
]);
|
||||
const execute = () => (tools[name] as unknown as { execute(input: unknown): Promise<unknown> }).execute({ caseId: CASE_ID });
|
||||
if (options.diagnosticsFailure && name === "rectification-read-diagnostics") await assert.rejects(execute);
|
||||
else await execute();
|
||||
}
|
||||
assert.ok(calls.includes("/api/rectification/v5/score"));
|
||||
const persisted = accounting.calls.find((call) => call.fn === "persist_agentic_rectification_candidate_v2");
|
||||
assert.equal(persisted?.args.p_algorithm_version, CURRENT);
|
||||
assert.equal(persisted?.args.p_algorithm_version, options.compareVersion ?? CURRENT);
|
||||
return accounting.calls.filter((call) => call.fn === "insert_agentic_rectification_tool_receipt");
|
||||
}
|
||||
|
||||
test("new Case scoring writes actual identity only on completed receipts", async (t) => {
|
||||
const receipts = await runGoldenToolSequence(t);
|
||||
assert.deepEqual(receipts.map((call) => [call.args.p_status, call.args.p_engine_version]), [
|
||||
// 原值: started=CURRENT;新值: null;原因: BUG-984,开始不是成功结果身份。
|
||||
["started", null], ["completed", CURRENT], ["started", null], ["completed", CURRENT],
|
||||
]);
|
||||
});
|
||||
|
||||
test("failed diagnostics do not claim an engine result identity", async (t) => {
|
||||
const receipts = await runGoldenToolSequence(t, { diagnosticsFailure: true });
|
||||
assert.deepEqual(receipts.map((call) => [call.args.p_status, call.args.p_engine_version]), [
|
||||
["started", null], ["completed", CURRENT], ["started", null], ["failed", null],
|
||||
]);
|
||||
});
|
||||
|
||||
test("BUG-984 blocker: real tool sequence permits mixed completed identities in one turn", async (t) => {
|
||||
// Identity-only mutation models rolling backend versions; all response shape and values
|
||||
// remain the real native golden. This is not a claim to have run future algorithms.
|
||||
const version9 = "rectification-v5-matrix-scoring-9";
|
||||
const version10 = "rectification-v5-matrix-scoring-10";
|
||||
const receipts = await runGoldenToolSequence(t, { compareVersion: version9, diagnosticsVersion: version10 });
|
||||
const completed = receipts.filter((call) => call.args.p_status === "completed");
|
||||
assert.equal(new Set(completed.map((call) => call.args.p_turn_id)).size, 1);
|
||||
assert.deepEqual(completed.map((call) => call.args.p_engine_version), [version9, version10]);
|
||||
// Preserve the blocker as positive evidence, not a false passing acceptance test.
|
||||
// F2 acceptance must replace this diagnostic once the approved aggregate fix lands.
|
||||
assert.equal([version9, version10].sort().at(-1), version9);
|
||||
assert.notEqual([version9, version10].sort().at(-1), completed.at(-1)?.args.p_engine_version);
|
||||
});
|
||||
|
||||
test("history opens with its bound Skill and reads old engine receipt values unchanged", async (t) => {
|
||||
|
||||
Reference in New Issue
Block a user