fix(rectification): give persist-first-sentence fixture a completed batch (BUG-635)
Independent Staging Quality Gate / validate (push) Successful in 9m47s
Independent Staging Quality Gate / publish (push) Successful in 8m55s

The staging gate failed because that case claimed 记下了 without a write tool, which the unwritten-evidence guard now rejects.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-09-10 18:11:25 +08:00
co-authored by Cursor
parent a1db6fe550
commit 8f9eb58738
3 changed files with 18 additions and 2 deletions
+1 -1
View File
@@ -9871,7 +9871,7 @@
- 触发条件:collect 焦点下用户提供带年月经历,模型只调 `rectification-read-case` 后按格式写「记下了」,不调 `rectification-record-evidence-batch` / `rectification-set-focus`
- 根因:路由分类结果没传给运行器,收尾只要正文非空就 `completeAttempt`,不看有没有公开写工具。客户端把旧消息上的同 `focus_id` 当成问题仍在显示,缺口不补主持人问题行。
- 修复:路由把 `expectedWrite` 设为 `"evidence" | "none" | "unknown"` 传进运行器;`provide_new_evidence``answer_current_focus` + `has_new_dated_event``"evidence"`。分类器 null/出错重试一次,仍失败则 `"unknown"` 且守卫 fail-open,**不用年份正则或关键词兜底**。无焦点的 `message` 路径也跑同一分类器。无写入的「记下了」第一次 `evidence_not_written` 可重试(零写工具,不进 `RETRYABLE_ERROR_CODES`);第二次主持人正文「这件我还没记上。请再说一次大概年月和发生的事。」,`answer.host_fallback`,不结算计费。`liveQuestionOnMessages` 只认最后一条 settled 助手消息。
- 验证:`frontend/tests/rectification-unwritten-evidence.test.ts`,以及 host-fallback / spoken-collect / agentic-entry / turn-intent-classifier / agent-voice-copy-contract。
- 验证:`frontend/tests/rectification-unwritten-evidence.test.ts`,以及 host-fallback / spoken-collect / agentic-entry / turn-intent-classifier / agent-voice-copy-contract。`rectification-v9-agent.test.ts` 的 persist 三句夹具必须带 completed batch,否则 635 会把它收成未写入(Gitea run 2545)。
- 防复发:有公开写工具 completed 不得重试(BUG-186);兜底正文不得由宿主复述用户原话冒充「记下了」;旧消息同 `focus_id` 不得挡住主持人问题行。
- 相关记录:BUG-186、BUG-278、BUG-359、BUG-449、BUG-633
- 复发自:BUG-633(只补了 batch 已完成且无正文,没补正文声称记下了但 batch 没跑)
@@ -62,6 +62,7 @@
### 既有断言改动
- `rectification-v9-stream.test.ts` empty_stream 二次成功正文:原值「记下了这件事。」/ 新值「先继续核对。」;原因:BUG-635 把无写入的「记下了」收口成 `evidence_not_written`,该用例只锁 empty_stream 重试。
- `rectification-v9-agent.test.ts` `evidence persist keeps the first sentence when the model writes three`:断言未改。原夹具 read-case 后直接写三句「记下了」、无 batch / 新夹具 batch + set-focus completed 后再写那三句 / 原因:Gitea `Independent Staging Quality Gate` run 2545 全文套件 3082/3083,该条被 635 收口成「这件我还没记上」;用例名是 persist,夹具必须真写入。
## 环境缺口
+16 -1
View File
@@ -158,7 +158,7 @@ test("no tool accepts event arrays, birth data or candidate ranges as input", ()
type StreamChunk = {
type: string;
payload?: { toolName?: unknown; text?: unknown; args?: unknown; error?: unknown };
payload?: { toolName?: unknown; text?: unknown; args?: unknown; error?: unknown; result?: unknown };
};
type FakeStreamResult = {
@@ -834,6 +834,9 @@ test("evidence persist keeps the first sentence when the model writes three", as
append_agentic_rectification_turn: () => ({ turn_id: TURN_ID }),
finalize_agentic_rectification_turn: () => ({ turn_id: TURN_ID, status: "completed", idempotent: false }),
});
// 原夹具:read-case 后直接写三句「记下了」,无 batch。
// 新夹具:batch completed 后再写那三句。
// 原因:BUG-635 把无写入的「记下了」收口成「这件我还没记上」;本用例锁的是已 persist 后只留第一句。
const { options } = runOptions({
action: "evidence",
accounting: accounting.client,
@@ -841,6 +844,18 @@ test("evidence persist keeps the first sentence when the model writes three", as
chunk("start"),
chunk("tool-call", { toolName: "rectification-read-case", args: { caseId: CASE_ID } }),
chunk("tool-result", { toolName: "rectification-read-case" }),
chunk("tool-call", { toolName: "rectification-record-evidence-batch", args: { caseId: CASE_ID } }),
chunk("tool-result", {
toolName: "rectification-record-evidence-batch",
result: {
accepted_recaps: [
{ display_date_label: "2016 年 9 月", event_phrase: "入学" },
{ display_date_label: "2020 年 6 月", event_phrase: "毕业" },
],
},
}),
chunk("tool-call", { toolName: "rectification-set-focus", args: { caseId: CASE_ID } }),
chunk("tool-result", { toolName: "rectification-set-focus" }),
chunk("text-delta", {
text: "记下了:2016 年 9 月入学、2020 年 6 月毕业。这对校正很有帮助。接下来我们继续。",
}),