Archived
fix(loop-engine): 配方失败给人一条真的路;幂等在「反复进入」下也成立
**I1 · 失败不再伪装成「等外部回音」**:从前配方办不下去只 `status:'awaiting'` 就走了 —— 映射成 `awaiting-event`,而推进器只捡 `running` 的单:卡已答完、 没立监听、没有时限,**再没有任何东西会叫醒它**。人在工作台上看到「等外部回音」, 而外面没有任何回音会来。现照熔断兜底卡的成例:发一张卡把办不下去那一笔的原话 摆给负责人 + 立人事件监听。走到那儿时这一单没有未答的卡(runTurn 开头 `cards.unanswered` 把住),所以不会堆卡。不补 narration —— 那句话 auto-runner 已落成系统观察进了对话区,而且停下来的是系统不是 AI(narration 是 AI 蓝)。 **I2 · 重投不许把已落地的行 un-land**:`DraftStore.put` 的 upsert 尾巴上有 `landed_at = null`,而配方每一拍都把同一张表重投一遍 —— 数据工单确认入库之后 那些行的「已落地」记号被悄悄擦掉,整单放行会再写一遍正式表、再抛一遍 data 事件。 新增两个**配方专用**旗(模型那一路一个字不变):`skipUnchanged`(值没变就不落笔)、 `skipExisting`(「只建不改」的表碰到已在库的键当「不用建」跳过并留痕,不抛 —— 那句拒回是写给模型看的,配方抛出去就是永久停单)。已在库的行也进 `kept`, prune 不许撤它。 M4 一并做了:auto-runner 的假 `draftWrite` 从**覆盖**改成生产的**合并**语义 (`patch || excluded.patch`),并补上 landed / createOnly 两件生产真有的事 —— 「重投不会擦掉人填的格子」这条结论在覆盖语义下根本不成立,旧替身证明不了它。 I1 2 测、I2 5 测、M4 使既有 20 测在真语义下重跑。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
This commit is contained in:
@@ -59,7 +59,21 @@ export type TaskDataGateway = {
|
||||
object: string;
|
||||
key: Record<string, string | number>;
|
||||
patch: Record<string, unknown>;
|
||||
}): Promise<{ changed: boolean }>;
|
||||
/**
|
||||
* **值没变就别落笔**(2026-08-29 终审 I2)—— 配方每一拍都把同一张表重投一遍,
|
||||
* 而草稿层的 upsert 尾巴上有 `landed_at = null`(「再写一笔就不再是已落地」)。
|
||||
* 照写的话:数据工单确认入库之后,下一拍配方一重跑,那些行的「已落地」记号就被**悄悄擦掉**,
|
||||
* 整单放行时会被再写一遍正式表、再抛一遍 data 事件 —— 而承诺是「整单放行不再写它、不抛事件」。
|
||||
* 模型那一路不传这个旗:它的「空转写」要被看见(如实回 `changed:false`),行为一个字不变。
|
||||
*/
|
||||
skipUnchanged?: boolean | undefined;
|
||||
/**
|
||||
* **「只建不改」的表碰到已在库的键:跳过,不拒**(2026-08-29 终审 I2)。
|
||||
* 那句拒回是写给模型看的(「别再写它,用 drop 把骨架撤掉」)—— 摆到人面前毫无意义,
|
||||
* 而配方抛出去就是永久停单。对配方来说「这颗料已经在库了」是**常态**,不是错。
|
||||
*/
|
||||
skipExisting?: boolean | undefined;
|
||||
}): Promise<{ changed: boolean; skipped?: boolean }>;
|
||||
/**
|
||||
* **撤掉本单草稿层的一行** —— 写错了得有退路。
|
||||
*
|
||||
|
||||
Reference in New Issue
Block a user