feat(rectification): the server writes the evidence recap — 「记下了 N 件事」 with the ledger list collapsed under it (BUG-1136)

- Evidence turns whose batch accepted items: the body is the server recap
  built from those items (two or fewer listed inline, more as a count);
  the model no longer restates them (both prompt sets updated).
- The case snapshot carries each assistant turn's recorded evidence from
  the ledger (rejected/superseded excluded); the message shows it in a
  collapsed <details> list when more than two.
- Chinese date labels read straight into the event phrase (2016年入学);
  ISO labels keep their space.
- Assertions updated with original/new/reason notes.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017eEAG8HD3mm8gsKXgk8uU8
This commit is contained in:
Jesse_Chen
2026-10-01 10:40:29 +08:00
co-authored by Claude Opus 5.5
parent 408b22749e
commit 9d302e515c
21 changed files with 244 additions and 27 deletions
@@ -896,7 +896,8 @@ test("host fallback after a completed batch recaps the returned events", async (
});
const result = await runV9AgentTurn(options);
assert.equal(result.ok, true);
assert.equal(result.answerText, "记下了:2016年9月 入学、2020年6月 毕业。");
// 原值: 中文日期标签与事件之间有空格(记下了:2016年9月 入学、2020年6月 毕业。)。新值: 记下了:2016年9月入学、2020年6月毕业。。原因: BUG-1136——复述每轮由服务器写,中文日期标签直接接事件;ISO 标签保留空格。
assert.equal(result.answerText, "记下了:2016年9月入学、2020年6月毕业。");
assert.ok(result.phases.includes("answer.host_fallback"));
assert.equal(emitted.some((event) => event.type === "run.completed"), true);
assert.deepEqual(billing, { reserved: 1, completed: 1, released: 0 });
@@ -965,7 +966,8 @@ test("length finish after a completed batch with no text uses the host fallback"
});
const result = await runV9AgentTurn(options);
assert.equal(result.ok, true);
assert.equal(result.answerText, "记下了:2018年7月 入职。");
// 原值: 中文日期标签与事件之间有空格(记下了:2018年7月 入职。)。新值: 记下了:2018年7月入职。。原因: BUG-1136——复述每轮由服务器写,中文日期标签直接接事件;ISO 标签保留空格。
assert.equal(result.answerText, "记下了:2018年7月入职。");
assert.ok(result.phases.includes("answer.host_fallback"));
assert.equal(emitted.some((event) => event.type === "run.failed"), false);
assert.deepEqual(billing, { reserved: 1, completed: 1, released: 0 });