人手改的那一手真正落得下去;界面不撒谎那几处补齐

手改是**兜 AI 的错**的那一手 —— 这一轮把它从「摆在那儿但落不了地」做成真的:

件上就地改
· 保存**按地址收**,不看当下那张卡:载荷从前借道工单的 `blocks[i]` 取列名,
  于是熔断卡(没有 blocks)在屏上时,人补的那一格一个字都送不出去 ——
  而他要补的恰恰是把这一单卡住的那个必填格。授权面改由活动清单的台账声明把关。
· **能增删行**:错不止「这一格填错了」,还有「这一行不该在」与「漏了一行」。
  删挂记号不当场抹掉(看得见、可后悔),且**删要说出来**(`drops`)——
  「没回传就是删了」会把一次不完整的回传变成一次删表。
· **必填没填按不下提交**:与放行门 L1 同一个数同一套算法;闸上摆出差在哪一行哪一格。
· 只写真改了的那几行 —— 改一格却留「修订 4 行」的痕,那句话是假的。

判据与门
· 裁量判据带谓词时**谓词说了算**:「选填缺口已补齐」基座数得出来,
  人填好的目标价它照样判「客户未提供」的毛病由此消掉。
· 验收卡判据**读时现算** —— 人在成果件上补一格,判据跟着变。
· 放行门认「**办完了没有**」不认「有人写过」:从前写个 `false` 就把门推开,
  于是一单没打标就进了放行门。三个数全由基座现数。
· 拒回把「活没干完」说成「数或行对不上」的毛病:判据点名的表一行都没写时直说那一步没办。
  **指向两扇打不开的门,比不指还糟。**

界面不撒谎
· 日志只有三色:负责人绿 · 智能体蓝 · 系统灰(归侧五种是度量的分法,不是给人看的)。
· 验收收口答两件事:落了什么(按**交付物**点名,一份成果的几张表并成一行)、
  往哪儿去(转出哪一口、带过去哪些字段);一个口都没发就直说到此为止。
· 签完到收尾之间那一段有自己的话「字已签下,正在落地」—— 中间态本来就该说出来,只是要说对。
· 消息不再被内部事件刷屏:只有从通道进来的件才谈得上「无人认领」。
· 建客户公司与联系人**一次确认落两行**;联系人编码自增不问人;卡面摆表的人读名。

A1 三案例端到端全 released:全 A 类直通 12 拍 / 客户点名跳一条 10 拍 / 新客户缺必填 14 拍。
五道门禁全绿(971 passed)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JsTDjoHovERXyy6Wmw1ALp
This commit is contained in:
2026-08-02 13:41:44 +08:00
co-authored by Claude Opus 5
parent 94f1c7a4ef
commit 259192f736
228 changed files with 27850 additions and 2847 deletions
+60 -2
View File
@@ -11,11 +11,11 @@
`TurnOutcome` `DecisionResult` `DecisionTrace` `Gap` `ItemState` `CaseState`
- 错误:`CmmnParseError` `IllegalTransitionError` `ForbiddenTerminalError`
`AutomaticOnWorldTouchingError`
- 端口类型:`LoopStateStore` `Sfeel` `TaskDataGateway` `AgentPort` `ToolGateway`
- 端口类型:`LoopStateStore` `Sfeel` `TaskDataGateway`(含 `writable` 授权面)`AgentPort` `ToolGateway`
`CardGateway` `ListenerRegistrar` `MemoryRecorder` `TaskContext`
- 用例工厂:`createTurnRunner(deps): LoopEngineService`
- 纯函数:`parseCmmn` `parseXml` `publishEnabled` `navigate` `evaluateCriterion`
`transitionItem` `occur` `reenter` `autoCompleteReady` `canTransitionItem`
`transitionItem` `occur` `achieveMilestones` `reenter` `autoCompleteReady` `canTransitionItem`
`mayCompleteCase` `mayTerminateCase` `evaluateTable` `evaluationOrder` `deduceGaps`
- adapter:`createLoopStateStore`;Drizzle 表:`loopStateTable`
@@ -36,6 +36,64 @@
- **结论不可静默覆写**:`isBindingConclusion` 标出约束性输入
- **三型行动**:每步行动属于且仅属于「调工具 / 调人 / 立监听」之一;
调人 = 立监听听人;AI 对世界只有触达(动作,落在放行)与等待(监听)两种姿势
- **一拍一串行动**(2026-07-30,`AgentTurn.actions`,封顶 `TURN_ACTION_CAP` = 6):
拍是按模型调用计费的 —— 一拍只许一个行动时,每个 write / finish / start 都单烧一遍
完整上下文,实测 A1 六步的活恰好 21 拍(其中 19 拍是该约束下的最短路径)。
收成一串后同一单 8 拍收口、token 减半。执行纪律引擎强制:按序执行,谁被拒停在谁那儿
(**前缀已生效不回滚**,理由喂回下一拍);`tool` 之后截断(出参没看见,后面的行动是
闭着眼计划的);挂起型(ask/human/listen/submit)落地即收拍;超封顶丢弃并留痕。
- **写台账草稿是过程写的唯一形态**(2026-07-30 新增 `write` 行动,铁律②)。
从前这条路**根本不存在**:`TaskDataGateway.draftWrite` 有端口无调用方,
Agent 干出来的结论一处也放不下 —— 后果不是少个功能,而是必交付物恒零行、
验收判据求值取不到值、出口载荷推不出字段:跑得再热闹,放行那刻什么也交不出。
- 一拍可写**多行**:一份 BOM 一次写完,不一行一拍各烧一次模型;
- 地址与列名的把关在装配层(它认识活动清单)—— 未声明的地址与列一律拒写,
越域写与越权调工具同罪;拒了抛错,由回合收成「行动被拒」喂回下一拍,引擎不崩;
- **写的授权面是台账声明,不是计划项**(2026-07-30):`itemId` 只是记账,
挂得上就挂(项活性化),挂不上(已完成 / 人工激活未 start / 阶段 / 不存在)照写不拦,
留痕注明「未挂到计划项」。从前绑死在项生命周期上,死锁过一单:S5 收完才发现打标
没写全,所有能挂的项都 Completed —— 每拍补写都被拒,连拒五拍熔断,而数据本身合规;
- 写完把该项收了(未 Active 的就地过一下 Active)。**这不是绕开「Enabled ≠ Active」**:
那条纪律管的是触达世界的项,而草稿写触达不到任何东西 —— 为它单烧一次模型去按那一下是纯仪式。
- **里程碑前提达成即达成**(2026-07-30,`achieveMilestones`):CMMN 的里程碑没有执行体,
也没有谁去按它。从前只有 `onEvent(ref = 里程碑 id)` 会 occur,而系统里没有任何东西
发这种事件 —— 于是里程碑永远 `Available`:既是必做项(堵死 autoComplete),
又常驻「当下可为」与「目标缺口」,让 Agent 每拍都看见自己按不动的东西。
现在引擎在发布前自己收(达成留痕);**无前提的里程碑不自达成** —— 那是建模漏了前提。
- **事件监听器不是交付物,是等待岗**(2026-07-30):不进 `gaps`,也不算 autoComplete 的必做项
(从前只排除 `timerEventListener`,一个 `userEventListener` 就让案子永远判不齐)。
- **一拍 = 一个行动 + 一句交代**(2026-07-30 `AgentTurn`)。Agent 从前**不会说话** ——
会写台账、调工具、调人、立监听,但没有一型行动是「对人说一句」。
实测:A1 跑十几拍、写七行台账、调两次工具,负责人的对话区从头到尾空白,
他只看得见「多了一个任务」。「人只在责任点与放行点出现」不等于「过程中人什么都看不见」。
- 交代落 `narration`(它进对话区),与 `thought`(给自己留的痕)分开;
- **不是一型行动,是每一拍的附带**:先做成 `kind:'say'` 试过 —— 它占一整拍又不推进局面,
预算下的 Agent 理所当然跳过它,对话区照旧空白。让说话与干活抢拍,
等于把「必须说」设计成了「有空才说」;
- **先交代再动手**:人看到的是「我要去查这三个 PN 的历史价」,紧接着才是结果;
- `say.view` 可顺手换局面模版 —— 局面变了,人既要听到为什么,也要看到新画面。
- **卡死了交回给人**(2026-07-30 `stalledTurns` + `STALL_LIMIT=5`)。预算会烧完,
但那是二三十万 token 之后的事;这期间界面上只是「进行中」一动不动 —— 那不是在办,是卡死了。
连续 5 拍行动被拒就不再问模型(再问也是同一个答案),发执行卡把**拒绝理由原话**摆给人:
是它跑偏、是行动型少了一种、还是案例模型建得不对 —— 三种处置完全不同,人得看得见证据。
- **补全卡是对话卡,不是执行工单**(`ask` 行动 / `CardGateway.ask`)。
「按缺口清单追问补全」要的是:缺口清单摆在对话区、带一张表单,人就地填齐。
从前 Agent **发不出对话卡**(只能选执行 / 验收两种工单),SOP 上画着补全卡的那一步
只能拿执行工单顶 —— 形似而神非:派一张工单去问几个字段,收卡的人得进待处理、
办完再回来,重得不成比例。一个格子都没有即拒发(空表单等于没问)。
- **决策卡也是对话卡**(2026-07-31 `decide` 行动 / `CardGateway.decide`)。
与补全卡的分工:补全卡问**事实**(缺哪几个字段,你填);决策卡问**处置**(往哪走,你选)。
从前决策卡**只有 UI 没有 Agent 侧** —— 卡面在对话区画得出来,行动型里却发不出它,
于是所有岔路口都被写成补全卡:人拿到一张要自己敲字的表单,而不是两个可点的选项。
少于两个选项即拒发(一个选项的「选择题」是通知,不是决策)。
- **视图推送回报推没推上**(`ViewGateway.push` → `{pushed, templates}`)。
从前引擎每拍推一个**硬编码**的 `case-overview`,而活动声明的模版未必叫这个名字
(A1 的四张一个都不叫)—— 模版查不到就静默 return,**每一帧都被悄悄丢掉**,
工作区从头到尾空白,日志里连一个字都没有。静默失败让「没画面」看起来像「没产出」。
现在:要的那张没有就退到活动声明的第一张,换不上则如实记痕。
- **人答了什么要看得见**:`MemoryRecorder.window` 带回 `detail`,回传值(`detail.values`)
随轨迹进叙事面。不给的话「执行工单回传」这一行读起来像事情办完了,而人填了哪几个值
Agent 一个字看不见 —— 既写不进台账,也只能再问一遍。
- **终局唯放行与 Harness**:引擎不把案计划置 Completed —— 那是 release 的事;
`mayCompleteCase` 只对 release 为真,`mayTerminateCase` 只对 harness / owner / governance 为真
- **提交放行 = 发验收卡**(2026-07-28 三修①):submit / 判齐(autoCompleteReady)