Archived
fix(engine): 人点「重做」不是「办完了」—— 打回即重开一轮,不再一路推到放行
用户实测:「我重做后怎么直接推进了?不应该是重做刚才那一步吗?」那一单的轨迹逐条对得上: 审核卡发出 → 人带意见交回 →「这一步已经发过卡,不再发第二张」→「自动收步:S3_review」 → 下一拍发出落账放行的验收卡。意见落进了轨迹(还被 note-anchors 逐行对上了), 而再没有任何东西会去读它。 这条缺陷 2026-08-30 全分支终审已记录成 Important 2、并留着一条坐实病灶的测试, 连「半个修法会把单子卡死」都预判对了。照那个方向修完,两半缺一不可: ① 收步那道门认答复(answerSettlesStep:custom:(人没选任何选项、写了自己的话)与 约定的 reject 都不算办完;空答复照旧算「照原样确认」); ② 同一句判断也让 carded 让位 —— 幂等挡的是「同一问被重复发出去」,而人点重做正是说 「这一轮不算,改了再问我一遍」:配方重跑(该重算的重算)再发一张,日志里说一句 「人把这一步打回重做:<意见>」。 测:坐实那条改写成钉死修复后的行为(历史诊断原样留着);新增「重做但发不出新卡也不收步」 (这一条专管收步门那一半)与「通过照旧收步」;3 条纯函数测。两半各自变异验证。 e2e w05 5/5 released —— 案例 0 现在真的发出两张审核卡(先带意见驳回、再确认通过)。 顺带撞见一条独立的老毛病,已记 debt 未修:人答得比发卡那一拍收尾还快时,回传被判 stale、 wake 又被那一拍的 park 覆盖,单子停在 awaiting-event 再没人叫醒(手工拨回 running 立刻走完)。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
This commit is contained in:
@@ -1718,3 +1718,40 @@ B 表却**不在**同一份 `only` 名单里——B 表对应的那一行仍留
|
||||
**排查法留一条**:「配方办不下去」类的 `AutoRecipeError`,若原文提到「已入库/已落地…撤不掉」,
|
||||
先看是不是这条——尤其当那一步的 `project` 动作带 `prune: true`、且它写向的表**也**在
|
||||
某张数据工单的 `gateLedgers` 上时,概率最高。
|
||||
|
||||
---
|
||||
|
||||
## 人答得太快,那条回传被判 `stale`,单子就此没人叫醒(2026-08-31 夜,未修)
|
||||
|
||||
**实测指纹**(e2e w05 案例 0,ACT-WORK-05):
|
||||
|
||||
```
|
||||
23:53:39.778 card-sent 逐条差异结论已备好…(S3 审核卡)
|
||||
23:53:40.048 card-reply 人答了(重做,带意见) ← 卡发出去 270ms 后
|
||||
23:53:40.274 last_progress_at 被更新 ← **发卡那一拍自己**跑完了
|
||||
此后 4 分钟一拍没跑,
|
||||
runtime 停在 awaiting-event
|
||||
```
|
||||
|
||||
后来手工把 `runtime` 拨回 `running`,同一份代码立刻把该走的三拍走完(重做那一轮的新卡也发了)
|
||||
—— 也就是说**逻辑是对的,只是没有任何东西再叫醒它**。
|
||||
|
||||
**病根**:2026-08-27 那条 stale 守卫的前提是
|
||||
「`lastProgressAt > occurredAt` ⇒ 这条回传一定已被那一拍消费(留痕先于事件落)」。
|
||||
人答得比发卡那一拍收尾还快时,这个前提就不成立:**把 `lastProgressAt` 往前挪的那一拍,
|
||||
正是发出这张卡的那一拍** —— 它不可能消费一条当时还不存在的回传。
|
||||
于是两件事叠在一起把单子锁死:
|
||||
- 回传路由的 `wake`(2026-08-25)先把任务拨成 `running`,可**发卡那一拍随后收尾时又把它
|
||||
park 回 `awaiting-event`**(晚到的写覆盖了早到的 wake);
|
||||
- 人事件随后到达,`deliver` 按 `lastProgressAt > occurredAt` 判 stale,「只记到达痕不推」。
|
||||
再没有第三样东西会叫醒它。
|
||||
|
||||
**为什么少见**:真人点一张卡至少要几秒,发卡那一拍早收尾了;e2e 是 3 秒轮询 + 秒答,
|
||||
才把这条窗口撞得出来。但 CLAUDE.md 里几次「怎么推不动了」的报告有可能是同一条。
|
||||
|
||||
**要治**(方向,未验证):park 那一下要认「这一拍开跑之后有没有人叫醒过我」——
|
||||
比如 `wake` 记一个时刻/世代号,tick 收尾时的 `update` 带上 `where last_wake_at <= <本拍开跑时刻>`;
|
||||
或者 tick 收尾前再看一眼「有没有新的未消费回传」,有就留在 `running`。
|
||||
**别去放宽 stale 守卫本身** —— 它治的是另一个真病(晚到十几秒的事件把没人答的卡收掉,
|
||||
2026-08-27 实测),两件事不要混。
|
||||
|
||||
|
||||
Reference in New Issue
Block a user