# JCAI-WOS —— 企业级 AI Native 任务操作系统 > 一句话:组织的工作定义为可编排的工作流,工作流由**活动**编排而成;活动是完成一项任务的 > Agent 机制,系统外开发、安装即用。人只在责任点与放行点出现 —— 确定交系统,临场交 AI,落地交人。 ## 现状快照(2026-08-22) - **三面一体**:设计中心 `/design`(九区:蓝图/触发器/流程包/活动库/工具箱/数据域/知识库/ 大模型/**测试台:三格 —— 流程(投一封信)/ 活动(按契约填入参)/ 日志(历次试跑存档)**)· 运营中心 `/ops`(六区:驾驶舱/工作流/任务/员工/台账/系统)· 工作台 `/`。 `/gov` 302 → `/ops`。 - **编排层与流程引擎已跑通并测死**:起单宽进(门口不拒缺项)、数据按字段名流动(无强制 类型)、边只表达顺序与条件(对齐 Mastra)、闭合校验只查结构闭合 + 活动装载、一条流恰一个 生效版本、在途按启动版本跑完、版本号与名归设计人员自己定。 - **活动一律案例模型**(2026-07-29 范式退役):flow-engine 已删,业务模型只有 CMMN + 说明书 + DMN 一形;`defineActivity` 已去 `paradigm`,`run` 改为可选 —— 行为全在清单里。`turn-runner` 每拍要 `agent.decide` —— **环境无模型密钥时 案例活动一步走不动**,三套端到端(unified-quote-flow / new-package-flow / testbed-trace) 整套跳过,恢复条件写在各文件头。 - **A1 客户RFQ受理已是真活动包**(2026-07-30):`activities/quote-intake@2.0.0` 经**安装通道 读文件**装入(`seed-activities.ts` 读 `dist/{manifest.json,index.js}`,不经 import —— 与 activities 之间只有安装通道)。五对象台账(record / type_table / verdict / alt_request / rfq_request)、两张判定表(F-01 完整度 · P-03 三分类)、三条技能、四张 HTML 报告模版; **案例模型照 SOP 图一步一项**(S1…S6 + 放行,7 项,扁平无阶段)—— v2.0.0 重写: 上一版 12 项(擅自加阶段/里程碑/裁量项)让 Agent 全程跟 harness 较劲,实测无限死循环; 流程包 A1 节点已指向它。其余**五**槽位照旧占位。 - **模型实例**:只留 `deepseek-v4-flash` / `deepseek-v4-pro` 两条;种子读不到 `JCAI_DEEPSEEK_API_KEY` 就**不绑密钥**(卡上如实显示不可用),去治理台大模型区补。 - **A1 已真跑通**(2026-07-30):起单 → Loop 逐拍 → 写台账草稿 → 提交放行 → 人签 → releaseWrite 合并进正式版 → 发射 intake 口 → `released`。三分类与双去向旗业务正确 (A 直通 / B 寻源 / C 选型)。为跑通它补了 Loop 的七个洞:`write` 行动 · `finish` 宣告完成 · 进行中的项进局面 · 工具清单进单拍提示词 · 里程碑自达成 · 在途验收不被兜底 save 擦掉 · 必交付物只数本单草稿。**A1 的槽位 `rfq-intake` 已退役卸载**(库里两个同名活动会骗人)。 - **A1 两条路径都跑通并零卡壳**(2026-07-30):常路五步与最长路径(含 S2 补全卡来回) 各跑一遍 `released`,**行动被拒 0 次**。补全卡走对话卡族(`ask` 行动); 连续 5 拍被拒即熔断交人(`stalledTurns`)。 - **一拍一串行动**(2026-07-30,`AgentTurn.actions`,封顶 6):从前一拍只许一个行动, 每个 write/finish/start 都单烧一遍完整上下文 —— A1 六步恰花 21 拍(19 拍是该约束下的 最短路径)。收成串后 **7 拍 released、56k token**(自 21 拍 173k);纪律引擎强制: 被拒停在谁那儿(前缀生效)、tool 后截断、挂起型收拍。浏览器 UI 点「确认通过」→ released 全链亦验证过。 - **写的授权面是台账声明,不是计划项**(2026-07-30 修死锁):`write` 的 itemId 降为记账, 挂不上(项已完成/人工激活未 start/阶段/不存在)照写不拦、留痕注明。此前绑死在项生命周期上, 实测死锁:S5 收完才发现打标没写全,能挂的项全 Completed,每拍补写被「要先 start T_release」 拒回,连拒五拍熔断 —— 而数据本身合规。台账声明与空转检查仍是硬门。 同批修:`finish` 对非人工激活的项就地过 Active 再收(白按一下省一拍); 事件到达痕**只记 task 层一条**(此前 task 与 loop 各记一条,同一次回传日志三行像结巴)。 最长路径(含补全卡人环)复测:**8 拍 released、64k token、行动被拒 0 次**。 - **每拍时延 20-56s → 1.5-4.9s**(2026-07-30):trace 拆出 tokIn/tokOut/reasonChars 实证 —— 慢全在**隐藏推理解码**(最慢拍可见 1538 字、推理 9808 字)。`ModelCall.reasoning: 'off'` 经 provider-profile 的 `reasoningControl` 译成 DeepSeek `thinking:{type:'disabled'}` (探针核过;`low` 在该厂无效)。配套:write patch 只带有值列、scope 摊平字段前置整表殿后 (rest 3000→1800)、轨迹剔除装配技能戳、旧出参截 120 字、技能戳版本不变不重写、温度 0.2。 off 档一次误判(缺目标价当关键字段)以**说明书写死规则**治(「关键字段只有 PN/EAU/交期」), 不给思考额度 —— 判断归判定表与说明书,模型只做编排。复测:7 拍 49k token released、零被拒。 - **工作台交互按 PRD 补全**(2026-07-30):①对话区点卡 → 视图区 locate 跳转(待办跳页位、 办结跳成果详情);②工作成果页签真实现(一行一份 → 定稿报告[印章+verdict+嵌 HTML 汇报] → 返回列表);③执行工单挂作业指导书卡组二;④工单办结回执以人事件进对话流,引擎内部观察 (internal 标)与裸「事件到达(human)」不再污染对话区;⑤空待处理四态分明(推进中动画 / 等外部回音 / 都办完了 / 已收尾)。 - **AI 工作中动画**(2026-07-30):对话区**办事条**(均衡条,语义「在办事」不是「在打字」; 三点气泡仍留给回话中)+ 头像呼吸环;空工作区**推进场景**(涟漪 + 微光工作线)。 纯 CSS、只动 transform/opacity、prefers-reduced-motion 全静止; 状态源自任务投影 `runtime === 'running'`,等人/等外部/已收尾不亮 —— 界面不撒谎。 - **活动开发规范已重写为开发手册**(2026-07-30 第二版):销账史砍掉(在 git), 精华收进建模八纪律与排障速查表;余账在 §15(④受理分支误吞验收裁决 · ⑤治理台白名单授权口 · ⑦dist 真编译 · ⑧单拍工具缝 · ⑨⑩死代码 · ⑪评价卡暂不做)。 语义源两卷(操作系统/活动模型)已归档 `docs/archive/`。 - **实时同步补齐五处**(2026-07-30 第二轮,测试台为引子):①订阅层不失效 `['gov','testbed',*]` —— 测试台全靠 2s 轮询而轮询到终态即停,一单跑完那屏就此定格; ②`testCurrentRoute` 把已终结的试跑单当成「在跑」,旋钮永久锁死(现返回 `live` 分开 「摆出来」与「占着仪器」);③试跑起单/销毁不广播 —— 销毁掉的真任务还挂在别人工作台上; ④**`kind:'system'` 声明了却全仓从未发布** —— 治理台所有配置面(活动/工具/模型/流程包/ 数据域/驾驶舱)永不实时刷新;现由 `/api/gov/*` 写路由中间件统一发(一处拦住,新路由自动生效), 任务走到终态也补发一次(台账与指标不以任务为轴);⑤本地 id 活过服务端事实 —— 别处销毁后面板还钉着旧号,显示「取数失败」的鬼卡片(渲染期对齐,服务端说没了就松手)。 订阅映射已抽成纯函数 `invalidateFor` 并按「哪一屏靠什么刷新」逐屏断言(8 条)。 - **MVP 工作流第一轮跨节点跑通 A1→A2**(2026-07-31),并挖出**七个编排缺陷**(全已修): ①六节点绑的是退役槽位 id ②流程包入参还是 `customerCode`+`rfqRef` ③**触发器装配映射是空的** —— 事件触发的 scope **不打底**(只有 registration 才铺 scope), 「同名会自动带过去」是错觉,`subject`/`body` 同名照样缺 ④E5 读 `needSourcing` 而 A2 出口不发 ⑤E10/E11/E12 读 `outcome` 而 A6 三口载荷是空对象 ⑥A2 要 `originalPn` 而 A1 发的是 `altRequests`(上游发一批、下游要一个) ⑦**自动收步与行动串并行** —— 引擎在拍首收了 T_select,而模型这一拍原本就打算 write 完再 finish, `Completed → Active` 当场抛非法迁移,连拒五拍熔断;现与 `start` 同款:收过了就当已完成。 ④⑤⑥ 同一类:**边读什么 / 下游要什么,上游就得发什么** —— 光测单活动测不出来,只有真跑跨节点才现形。 - **六个活动全部转正为真活动包**(2026-07-31):`REAL_PACKAGES` 六件齐,经安装通道读 `dist/` 装入 —— 治理台里不再有 `viewTemplates: []` 的占位槽。六份案例模型统一到 A1 的 状态机模式(剧本 `steps`:intent / guide / writes / tools / doneWhen): **A2/A3 各只有「派一张执行单 + 放行」两项**(专家判断,建细了只是跟 harness 较劲); **A4 定价**三项(算价归判定表 · **超限才叫人**的决策卡 · 放行); **A6 议价**三项(落单 · **发出去人工激活 + 立监听等回音** · 放行); **A7 归档**两项(一步落三张表 —— 它们互不依赖,分开只多两次 finish)。 凡触达世界的项一律不给 `doneWhen`(给了等于给引擎一把替人签字的钥匙)。 - **A2/A3 的简化口径**(同日):案例模型从九个 humanTask 砍成**两项** —— `T_select`/`T_source`(派**一张执行单**,卡面两张可编辑表)+ `T_release`(人工激活)。 上一版把「FAE/采购脑子里怎么想」当成了「系统要管几步」;而那一整段在业务上是**一件事**。 剧本与 A1 同一套(`doneWhen` 真了引擎自己收步)。`REAL_PACKAGES` 已含这两个, 不再是治理台里 `viewTemplates: []` 的占位槽。 - **判据三态 + 表格默认锁着**(2026-08-01,`quote-intake@20.0.0`,用户两问): ①「这条未达标为啥还在」—— `acceptanceCriterionCheckSchema` 只有 `{label,level,pass}`, **裁断与理由传不到卡面**,于是「裁了但裁成不满足」与「压根没裁」都是一个红叉。 补 `settled` + `rationale`,卡面变三态:达标(绿)/ **AI 判为不满足 · 交你定** (琥珀 + 左侧色条 + 理由)/ 未达标(红)。更早的注释写着「理由随卡交给人」—— **那句话描述的行为从来没实现过**,因为契约里没有那两个字段。 ②**表格默认锁着**:每张可改的表各带一道闸(`[data-edit-for]`),锁着只出「编辑」, 开了换「取消 / 保存」;取消还原成按下那一刻的值,保存才交给外层缓冲。 **看与改是两件事** —— 从前一进屏 54 个输入框一起亮着。 途中踩了跨 realm 陷阱:`event.target instanceof Element` 在 iframe 元素上**恒为 false** (`Element` 是父文档的构造器),症状是点「编辑」毫无反应而 class/CSS/选择器逐个查都对。 **认能力不认血统**;监听挂载也改成幂等的(srcdoc 换文档时机抓不准,每次有机会就挂一遍)。 验收:6/6 released;浏览器里走完「编辑→改→取消还原→再改→保存→提交」,落草稿层。 - **A1 连跑 10/10 全 released、行动被拒 0 次**(2026-08-01,`quote-intake@19.0.0`, 10-11 拍 / 99-112k token)。基线是 5 轮熔断 1(其中一轮 13 次拒回、23 拍、234k token)—— 五处 harness 改动逐轮逼出来的(见下两条与 `docs/debt.md`)。 - **最后一条自报的机检判据也交给基座数**(2026-08-01):台账字段声明加 `required`(可选, 不建 NOT NULL —— 草稿层的本分就是过程中允许缺),基座据此出 `域_对象_missing` 与 `_missing_keys`(缺在哪几行、缺哪一列)。A1 的「必填齐(PN/年用量)」原读活动自写的 `missing_key_total` —— 人在卡上补了年用量、基座已写回草稿层,而那个数要模型自己重算, **漏算一次这道门就再也开不了**:十轮里三轮死在这。这是「机检只许读基座数得出来的数」 这条纪律第二次被违反,第一次是 missing_minor_total 被改小那次。 - **Harness 三条死胡同已通**(2026-08-01,连跑 A1 摸底逼出来的:5 轮熔断 1、再 6 轮熔断 2)。 三条全是同一个病 —— **判据正确地拦住一件办错的事,而模型没有一个动作能把它办对**: ①**写错一行没有退路** → 加 `drop` 行动(`ledger.draftDrop` → `DraftStore.drop`): 只撤本单草稿层那一笔,正式版一个字都动不了、不抛事件,**不是第四种写**。 起因:客户明说本轮跳过的那颗料被写进有效清单,数全对(9 有效/1 跳过)而表里 10 行, `record_rows = line_total` 拦住 —— 模型唯一能改的是那个数(改了 skipped_total 又不对), 13 次拒回、23 拍、234k token; ②**拒回只给数字** → 读数连**主键名单**一起摆(`域_对象_keys`,封顶 12 行): 两份名单一比,多的那个 PN 就在里面对着,一句话能办的事; ③**拒回把模型指上死路** —— 「要先 start,当下是 Completed」,而 start 一个 Completed 项同样被拒,两堵墙对着撞;现按状态分开说,且 start 已收的项改为无事发生。 **拒回的话是模型下一拍的行动指南,指错方向比不给指引更糟** —— 同一条也改了提交门的 结尾建议:先分清差的是**数**还是**行**,行不对就 drop,别去改数。 顺带:**收步判据与验收判据同源**(S2/S5/S6 都改读基座的 `_rows`)—— 松出来的那一截就是返工;S2 那条把「多写一行」的发现点从第 10 拍提前到**第 2 拍**。 还删了孤儿模版 `intake-gaps`(7 处 `view:` 无一指向它)。 - **对话区一轮一句(不是一拍一句)**(2026-08-01,用户:「太密集了」):形状是 **设定目标 →(分析现状 → 规划 → 执行)× N 轮 → 一个气泡**,气泡可以是仅结论, 也可以是**结论 + 功能卡两部分**。三处:①`turn-runner` 的 `handsOff` —— 只有交出控制权那一拍(ask/human/decide/listen/submit)的交代进对话区, 别的拍留进工作日志(`internal`);②提示词与 say 字段说明明写这条规矩, 否则模型照旧每拍写播报、只是被默默丢掉(白烧 token 还写不好总结); ③`chat-projection` 把交代与卡**并成一个气泡**,并把收尾三条引擎回声 (裁决 / 发口 / 终态)收成一条。并卡的判断按**来路**认(只有 terminal 不认领卡)—— 一度写成 `tag !== 'conclusion'`,而交代本身常是结论口吻,于是第一轮并对、第二轮没并。 账:同一条 11 拍的 A1,对话区 **9 条 → 5 条**;压下的 8 条交代一条不少留在工作日志。 - **放行卡不摆 L5、去向不再有 L4 裁量**(2026-08-01,用户当场指出): L5「BD 放行」是**责任关**,而那张卡本身就是这道关 —— 列进判据表等于摆一条恒为 「未达标」的项,「n/m 达标」永远差一条;声明留着、呈现去掉(滤在基座组卡处,六活动通用)。 L4「去向判断合乎业务常理」删掉 —— 去向已由出口谓词算出,再让模型裁一次是**给自己 没做的决定盖章**:裁「满足」是废话,裁「不满足」也改不动什么(能改的是三类条数, 那已由 route-alt / route-rfq 两条机检看着)。**判据得能指向一个可做的动作。** - **三个区各归各位:件归工作区,判据与指导书归对话区**(2026-08-01,`quote-intake@14.0.0`, 用户指出「你用你自己的报告格式嵌套了一层我要的报告格式」):工单报告组件自带一整套外壳 (题头/编号带/依据带/判据表/章节头),又把活动推的那一屏包在里面 —— 两套版面语言叠着。 现在 **待处理与工作成果只放那份 HTML 模版**;作业指导书 · 依据 · 判据 · 填报表单 · **提交与裁决**全在对话区的卡上。**待处理是可编辑态**:可改的格子在模版里挂 `data-col`、 行容器挂 `data-edit="域.对象"`,渲染时每格多渲一个 `` 孪生件, 只读那份与输入那份**由样式表按根节点的 `editing` 二选一** —— 同一份 HTML 两处用,不存两份。 收值在外层(`allow-same-origin` 读得到 DOM),**iframe 里仍然一行脚本都没有**; 收上来按台账地址对上工单 `blocks[i]` 的 `ledger`/`fields`,仍走老的 `table:N` 回传。 同批修两个只在真人点的那条路上现形的洞:①**监听挂在 about:blank 上** —— `srcDoc` 异步换文档,渲染那刻挂的监听随旧文档作废,人改了两格提交时载荷一个字都没有; ②**算出来的去向没交回去** —— `routedPort` 那一路 `selectedPorts` 恒空,按「确认通过」 当场判「选择组未选出口」,台账都合并进正式表了单子却死在最后一步(`blocked`)。 验收:浏览器里走完两道人环 —— 件上改两格 → 提交 → 落草稿层 → 放行 → **released**, 九行数据(含人补的 eau/brand)落进正式表;工作成果那一屏零输入框、零外壳。 - **阶段2 补回成一项:受理需求交人审定**(2026-08-01,`quote-intake@13.0.0`,用户指出 「我都没确认需求 它就让我验收了」):「经过人」从前不是一项,而是归一那步收步条件里的半句 `missing_minor_total = 0 or answered_total > 0` —— **只在缺东西的时候才叫人**。 一封字段齐全的询价进来,这半句在拆完那一刻就为真,引擎自己把那步收了, 人一眼没看过受理需求,下一次被叫到已是终局验收。现在 `S3_confirm` 是独立一项: **人工激活 + 不给 doneWhen**(与放行同款),`view: intake-overview`,一单必发一张; S4 的入场前提改读 `confirmed_total`(只有人回卡才产生的数)。 规范 §7.1 立纪律 3.5:**判据是「这件事办完了没有」,不是「要不要办」**。 连带修掉一个零条死锁:**没写过 ≠ 写了 0 行** —— 全 A 类那条路上替代请求表一行没写, `quote_intake_alt_request_rows` 整个键不存在,而判据 `= type_c_total`(0=0)本该成立, 未绑定的名字比较为假 → 永远过不去、连撞五拍熔断;现按 `declarations.ledger` 先铺 0。 验收:常路 **11 拍 released、被拒 0**;全齐无 C 类那条 **10 拍 released**、去向 `to-sourcing`。 - **A1 两份报告改为从 PRD 目标件整份搬过来**(2026-08-01,`quote-intake@12.0.0`): `views/prd-style.ts` 是机械抽取的整段样式表 + 图标精灵(`PRD_CSS`/`PRD_SPRITE`,数值未改), `views/report.ts` 逐块搬标记、只把写死的数据换成绑定 —— **不再用 `@sdk` 拼装件复述** (那套外壳有自己的版面语言,「照着做」出来的是第二种版面;前三轮报「25 块到位」都是 结构断言,对版面零约束)。规范 §10.3.1 立此法:**视觉目标件只能看,不能用 DOM 断言验收**。 连带三件:①**`data-class-of` 不再以 `data-slot` 为前提** —— 纯色块(格里不写字、只按值上色) 从前整条静默失色,屏上一排灰格子看着像「还没算出来」(补 4 条用例); ②**去向进视图**:`case:routeKey/routePort/routeTo/routeWhy` 由基座按出口谓词求值后注入, 与放行发口是同一次判定,报告只摆不算(分布条按条数分宽也走同一招:条数投影成 class + 宽度梯子); ③`contact_name` 落进 `verdict` —— 老客户不重写主数据,联系人卡从前会显示公司名。 端到端复跑:**10 拍 released、96k token、行动被拒 0 次**,去向 `to-alternative(type_c_total > 0)`。 - **A1 五轮端到端全部 released**(2026-07-31):行动被拒 **0** 次,判据 7/8(只剩 L5 人放行)。 跑测逼出并修掉两个「人答了什么 Agent 看不见」:①可编辑表的修改只活在组件局部 state, 回传载荷一个格子都没有(加 `onTableChange` 链,键 `table:N`、首行列名); ②决策卡选了哪个不进轨迹(`payloadOf` 只认 values/output/error,补 `detail.value`)。 两者都会让 Agent 重发同一张卡 —— 人以为自己白填/白点了一次。 - **工作台空占位统一**(2026-07-31):任务那一栏的空态从裸 `execution-panel` 改挂 `jc-panel-card`(其余四模块一直有,只它是画布上飘着的一段文字); `.jc-empty` 由固定内边距改 `margin:auto` + `justify-content:center`,在栏内真居中。 - **活动状态机:每步一条剧本,成果已在就自己收**(2026-07-31,治 A1 空转)。 `LoopModel.steps` 一个计划项一条:`intent` / `guide` / `writes` / `tools` / `doneWhen`。 引擎每拍开头先对任务视图求 `doneWhen`,**真了就自己 finish 那一项,不问模型** (人工激活的项不自动收 —— T_release 触达世界,不给它 doneWhen); 上下文按状态组织:只摊开当前这一步的做法与它该用的东西,其余步骤各留一行。 起因是实测死循环:S1 一次写齐八字段后 S3「补齐八字段」已无活可干,而每拍喂整本说明书, 模型只能把同样三行再写一遍 → 「写了等于没写」被拒 → 下一拍再来一遍,连拒到熔断。 **`doneWhen` 的坑**:S-FEEL 里未绑定的名字 `!= null` 求值为 **true**,写它等于那一步开局即收; 布尔列也不能当判据(分不清「没写」与「写了 false」)—— 一律取同步写下的计数列(测里拦下过)。 实测三连:**A1 三次端到端全部 `released`,行动被拒 0 次,S3 每次自动收步**; 8 拍 / 58k token(状态机之前是 11 拍 / 82-90k)。 - **决策卡 Agent 侧接通**(2026-07-31):新增 `decide` 行动(contract / port / turn-runner / engines / 提示词 / 解析)。此前决策卡**只有 UI 没有 Agent 侧**,岔路口只能写成补全卡 —— 人拿到一张要敲字的表单而不是两个可点的选项。少于两个选项拒发。 - **真实文件进得了活动**(2026-07-31):`sys.upload`(迁移 0024)存原字节 + 读出来的文本; `POST /api/gov/upload`(base64,8MB 封顶)/ `GET /api/gov/upload/:id`; xlsx **不引依赖**自己读(ZIP 中央目录 + `inflateRawSync` + XML,13 条测试); 契约字段标 `format:'file'` → 测试台出文件选择器。读不出文本的类型如实说读不出。 - **沟通记录接通**(2026-07-31):`sys.task_comm`(迁移 0025);活动清单声明 `contract.input.inboundComm`(哪几个入参字段合起来是那封来件),基座**起单那一刻**归档 —— 人一点开这单,沟通记录里就已经躺着那封信,不必等模型跑几拍。附件那一行照抄基座的读取说明。 - **测试台改三格 + 试跑日志**(2026-07-30):两档旋钮长在内容里(别处跳不进来、刷新记不住 试的是哪一台,第三样东西也塞不进二档),提到页签 —— **流程 / 活动 / 日志**;单在另一台上 不抢页签,只挂一句「它在那边」。日志是**拔之前先存一份**:停止仿真照旧连根拔掉,拔前 `archiveRun` 存一条(逐拍轨迹 + 台账草稿 + 发出去的人卡 + 读数),**一次试跑一条** (流程包把名下节点任务合成一条,痕带节点名前缀、按时刻排);可单删可清空,`reset-runs` 一并清。 库表 `sys.testbed_run`(迁移 0023),路由四条挂 `/api/gov/testbed/logs`(写路由中间件自动广播)。 顺手修:单活动那一台的负责人下拉掉进 `.tb-asn-r` 的 40px 那一格(它比流程那台少一列), 现给 `.solo` 四列版 + 插座列加宽到 184–238px。 - **台账列归型前移到写入那一刻**(2026-07-30):模型用 `""` 表示「原文没给」,草稿层照收, 到 `releaseWrite` 才被 PG 掀桌(`invalid input syntax for type double precision: ""`)—— **而那是人签完字之后**,整单落 `blocked`。现在 `draftWrite` 按声明列型归:空值=不写这一列、 数值/布尔字符串转真类型、归不了当场拒(理由喂回下一拍)。台账字典也带上列型给 Agent 看。 - **前端实时刷新已通**(2026-07-30):前端那一侧一直是好的(单条 SSE + 按前缀失效缓存), 三处**后端没广播**:①`task-advancer` 只在 runtime/terminal **换名字**时广播,而案例活动 连跑十几拍全程 `running`(改为 `progressed` 即广播);②`interaction` 的推送一个订阅者都没有 (加 `onPush` 系统级转接);③发消息不经事件投递,收件人的消息气泡不动(outbox 处补广播)。 - **四类人类工具:前三类已通**(2026-07-30):执行(工单 · 报告页填报提交)、 **补全**(对话卡 · `ask` 行动,两条路必走其一)、验收(工单 · 判据表 + AI 已填好可编辑 + 裁决在对话区)。决策卡(第四类)UI 已在、Agent 侧未接。 验收修订链原来断在五处「声明了没接线」——契约 `revisableAtRelease` 定死哪几个值可改、 改完落哪儿;拟值放行前从台账现读,不让模型重述。 - **A1 的两份执行页照 PRD 目标件重做并跑实**(2026-07-31,`quote-intake@9.5.0`): `~/coding/JCAI_PRD/docs/活动执行页/` 的两份 HTML 是「办完该长什么样」的答案 —— **询价受理需求**(来件原文 → 受理要素四卡 → 指标带 → PN 清单 → 本轮不报)与 **统一受理记录**(要素 → 逐条记录带标 → 分级依据 → 分流去向 → 两类请求 → 结论 → 这一签下去会发生什么)。`@sdk` 补 `letter` / `factCards` / `actionList` 与列样式 `req`/`opt`/`num`/`pill`;`data-blank` 让空值真的留空,必填/选填胶囊与缺项标底 由模版自己的 CSS 出 —— **模版仍不许算**(分布条宽度、命中高亮这类算出来的画面一律不做假)。 顺手删掉 `@sdk` 里五个零调用方的拼装件(kvCard/tableCard/noteCard/stagesCard/critList)。 - **A1 六轮端到端,末轮九行数据全对**(2026-07-31):每轮 `released`、**行动被拒 0 次**, 9-10 拍 / 76-89k token。逐轮逼出并修掉五个洞: ①**机检判据两边都由活动自报** —— 条数报 9 而表里 10 行、三类条数报 7A/2B 而判定器给 5A/3B,派单数同源同错于是「2 = 2」顺利过关;现加基座读数 `域_对象_rows`(本单写下几行), 判据必有一边不是自报,`classify` 出参也带 `counts` 供照抄; ②**问过 ≠ 答过** —— 收步判据写 `asked_total`(卡一发就为真),人填完提交这一步当场被收, 答案没轮到写回台账;改等 `answered_total`; ③**归档件被冲掉** —— 收口后引擎再跑一拍,推固定的 `case-overview` 退到「声明的第一张」, 把人刚签过的放行页冲成阶段二的执行件;现按剧本 `view` 推、活步收完不推; ④**说明书与剧本各写一份六步**,分叉出三个案例模型里不存在的计划项名(S1_register 等), 模型照它报 itemId 一报一个被拒;说明书现在只讲整单的事,逐步做法归剧本(有测试钉死); ⑤三类数据失真(PN 抄漏后缀→同一料两行、数值缺失写成 0、制表符 BOM 拆错列)—— 逐条在说明书里写死实测账。 - **Harness 可靠性:三处「门本身教模型撒谎」已修**(2026-08-01,两条样例路径连跑逼出来的): ①**机检判据读活动自报的数** —— 一颗料只缺目标价,模型如实记 1、被连拒四次, 第五拍把那个数**改回 0** 就绿了(台账从此写着「缺选填 0 条」); **机检只许读基座数得出来的数**,数不出来的别假装机器判得了 —— 该条已降 L4 交人; ②**裁量判据也被要求「为真」** —— 它如实裁「未满足」并写了理由,提交照样被拒, 判-提-拒十二轮 21 拍 187k token,最后把裁断翻成「满足」才过去; 提交门已改:机检必须为真、**裁量裁过即可**,裁断连理由随卡交给签字的人; ③**熔断数不出「同一堵墙」** —— 拒回标题带着串位(「第 2 个」),整条一比成了 N 堵墙, 叙事窗 20 条也装不下几次撞墙;一单被同一条判据拒回 **33 次**、40 万 token 烧到 `exhausted`。已修:削掉串位前缀比对 + 熔断另开 60 条窗。 顺带:计划项号认唯一前缀简写(`S4` → `S4_history`)。 **验收**:Itelma 与新客户两条路径各三轮全部 `released` —— 10 拍 / 88-90k / 被拒 0 与 9-11 拍 / 71-88k / 被拒 0-1,数据逐轮对得上。 - **执行页补到「能做的极限」**(2026-08-01):新增 `data-class-of`(把值消毒成 class 后缀, 仍只是取值,判断留在样式表)—— 于是类标 A/B/C 三色、两枚旗的是/否、**一条料一格的刻度条** 都真做得出来;要素卡补方/圆标(方=组织、圆=人,里面放图标不放算出来的首字母)与大号计数; G2 那段改成**三条规则连着本单计数**的规则表 —— 命中由编排层求值,这份件不画对勾替它宣布。 仍不做的只剩两类:按条数分宽的分布条(宽度得算)、编辑态(沙箱无脚本,改数走执行卡)。 - **试跑日志吞主键已修**(2026-08-01):存档那一屏只渲染 `patch`,`key` 整个不显示 —— 三行受理记录屏上只剩「eau / lead_time」,看的人据此判「PN 没提取到」,而 PN 一条不少。 两处观测面已合并到 `gov-testbed/internal/drafts.tsx` 一份实现。 - **就地改的三处不老实已修**(2026-08-02,同一单实测逼出来的): ①**保存按地址走,不看当下那张卡** —— 载荷从前是 `{workOrderId, values:{'table:0':…}}`, 列名由那张工单的 `blocks[0]` 给出,于是「这份件能不能改」被绑在了「此刻开着的那张卡 长什么样」上。一单在放行门连拒五拍熔断,引擎发的是**没有 blocks 的熔断卡**,而屏上摆着的 正是受理记录那份件 —— 闸在、编辑进得去、保存按得下,前端找不到匹配的块,**一格都没往下送**; 人要补的恰恰是把这一单卡在那儿的那个必填格。现在收件自己说的话(`data-edit` 地址 + `data-col` 列名),授权面改由**活动清单的台账声明**把关。 ②**必填还空着就按不下提交**(`ExecutionWorkOrder.gate`,基座按声明现算, 与放行门 L1 `域_对象_missing = 0` **同一个数同一套算法**);闸上摆出差在哪一行哪一格, 人在件上补齐、保存,闸自己开。算不出来(卡上没绑表)就不给闸 —— 没有依据的时候不拦人。 ③**只写真改了的那几行**:件上按一次保存整张表都回传,照单全写会留「就地修订成果:4 行」 的痕而人只改了一格。 端到端:12/12 判据、`released`、被拒 0(另一轮 3 次、亦 released)。 - **日志只有三色**(2026-08-02 用户定):负责人绿 · 智能体蓝 · 系统灰(`LogLine.who`)。 从前按归侧上五色 —— 那是**度量**的分法(自主率要把「等外面」与「机器干的」分开), 对读日志的人不构成区别。连带两件:放行那一刻四条痕说的是同一件事(合并 / 发口 / 流转 / 终态), 日志只留说得出实情的那一条(带「几行没进正式表」);台账写入认 `by` 定主语 —— 放行合并归系统,人工修订归人。 - **件上的表能增删行**(2026-08-02 用户:「编辑列表应该还能增删行」):手改本来就是 **兜 AI 的错**那一手,而错不止「这一格填错了」——「这一行根本不该在」(客户点名跳过的料 被写进了有效清单)与「漏了一行」是同一类错,只给改格子就没有出口。 序号那一格编辑态换成 ×(一列两用),表尾一条「加一行」;删是**挂记号不当场抹掉** (看得见、可后悔),「取消」把加的撤掉、把记号摘掉、把值放回去,三样一起才叫还原。 **删要说出来**(载荷 `drops`),不靠「没回传就是删了」—— 那种口径会把一次不完整的回传 变成一次删表。撤的只是本单草稿层那一笔(`draftDrop`),正式版一个字不动。 痕里点名撤了哪几行并写「别再写回去、条目数跟着改对」—— 那条痕是**下一拍模型的行动指南**, 不说清它会照「条目数 9 而表里 8 行」判成少写了一行,把人刚删的写回去。 实测:删一行 + 加一行 + 补必填 → **released、11 拍、被拒 0**。 - **裁量判据带谓词时谓词说了算**(2026-08-02 用户:「这个价格是我填写的,但是它判错了」): 「选填缺口:已补齐,或由你放行时确认可以先受理」是复合命题 —— 前半句基座数得出来 (`域_对象_gaps`),后半句才需要人。从前整条只读裁断,于是模型凭记忆写理由, 人填好的目标价它照样判「客户未提供」(复现的那单更离谱:两行年用量都填着, 它写「共 4 处选填缺口」,而 EAU 压根是必填)。现在谓词为真即达标、**那句相反的话一并丢掉**; 谓词为假才轮到裁量。同批:验收卡的判据改为**读时现算**(`container.checks.of`, 与提交门同一段 `criterionCheck`)—— 人在成果件上补一格,判据跟着变; `remark` 不再算选填缺口(它是我方写的注,不是客户该给而没给的)。 - **作业指导书与验收判据同一套版面**(2026-08-02 用户定):从前指导书是一串松散的圆点、 判据是一摞带章的行,同一张卡上两套版面语言。差别只留一处:**指导书不画对勾** —— 它是要办的事,系统并不知道人做没做。执行卡那一钮也改称「查看工单」。 连带挖出:**引擎压根不往下传 `steps` / `standard`** —— 活动照骨架写了,发卡时一个字 都没到卡面,人拿到的只有一句「请核对确认」。空着不是简洁,是把交代省掉了。 - **建客户要公司与联系人都经人确认**(2026-08-02 用户定):录入卡加 `also` 段 —— 一张卡两段(公司档 + 联系人档),确认一次落两行,值按 `段号.列名` 隔开 (两张表都有 `name`,平铺会互相盖掉而没人看得出来)。从前联系人由 AI 自己写, 而 `contact_code` 恰是它编出来的那一个。 - **该问人的问人,人答不上来的别摆到他面前**(2026-08-02 用户两条): ①卡面摆的是台账登记的**表人读名**(「客户档案」),不是 `customer.profile`; 主键行只摆表单里没有的那几格、用中文列名 —— 从前一句「主键 customer_code=待定」 既是英文列名,又在替一件他马上就要做的事做旁白。 ②**自增列不问人**:声明加 `FieldDeclaration.auto`,标了的列压根不进表单, 写入那一刻由基座按「同组其余主键值-两位序号」生成(`CU-9001-01`,序号数正式版 + 本单草稿, 同一单连加两位也不撞);卡上另摆一句「由系统按顺序生成,不用你填」—— **不能一声不吭地拿掉**,那样人会以为这张档少了一格。 - **放行卡砍掉四条判据,办结后换成落地结果**(2026-08-02 用户定): `downgrade-safe` · `route-alt` · `route-rfq` · `typed-on-record` 四条都是**内部一致性** (打标依据对不对、几类料开了几张单、两张表行数齐不齐)—— 该由引擎自己看住, 而放行卡是给签字的人看的:一屏九条,真正要他过目的那几条反而淹了。 落地那一侧不因此变松:同一批基座读数仍在 S5/S6 的收步判据里。 **办结之后那一屏换成「这一签下去发生了什么」**:进了哪几张表各几行(摆表的人读名)、 转去哪儿了(摆出口的 description)、试跑挡下几行 —— 判据说的是签之前要核什么, 签完再回看,那一摞对勾答不了这个问题。事实取自放行那一刻的**结构化留痕** (`ledger-write` / `release-verdict` 的 detail),不解析日志句子。 - **判据措辞写全,两张卡的按钮统一**(2026-08-02 用户定): 「客户已确认(认出或已建档)」→「客户已确认:发件邮箱认出为老客户,或已为新客户建好档」, 五条同批改写;执行卡与验收卡那一钮改成同一形状 —— 图标一格、**四字粗体** (执行工单 / 验收工单)、小字说明、右侧箭头,且四字在上小字在下(从前是反的)。 - **执行工单说的是「哪几格必须有、哪几格值得追」**(2026-08-02 用户定): A1 的作业指导书从「怎么核表」改成逐项建议 —— PN/年用量必须有(缺一条走不到放行)、 目标价尽量试探出来、客户料号对齐回价单、品类与制造商能填就填; 收口标准写明「问不到的留空并在备注里写明,放行时由你决定先受理还是退回」。 - **A1 不再开请求单**(2026-08-02 用户当场定):`alt_request` / `rfq_request` 两张表 连同 S6 的开单动作、两个派单计数列、报告里那两张明细表一并退休。原话: 「这两项数据不在这里产出;随令牌流向下一个节点的只有工作成果验收内的内容; 进入选型替代后,活动会自己归一需要的数据」。从前 A1 逐条开单交给 A2/A3 —— 那是**替下游把它的输入先摆好**,而下游本来就要照自己口径归一一遍: 同一份事实两处各存一份,改一处就分叉而没人看得出以哪份为准。 S6 的收步判据改读 `route_decided_total`(旗是布尔,分不清「没写」与「写了 false」)。 报告同批瘦身三处:两张请求单表 + 那条对账说明、「受理结论」四格表、 「本轮不报 0 行」横幅 —— 后两者要么与别处重复,要么九成时候在说「没有」。 - **消息不再被内部事件刷屏**(2026-08-02 用户:「消息怎么总莫名其妙的出内容」): 「无主入站待认领」从前只看「有没有主 + 有没有人接住」,于是**台账写一行发的 `data` 事件**也进兜底 —— 装一次活动包就往三个人收件箱塞十几条 「无主入站待认领:(无主题) … 原件:无」。判据加一刀认**来源**不认类型: 同样是 `data`,从通道进来的是件、台账写出来的是事实;只有 `source.kind === 'channel'` 才谈得上「无人认领」。顺带:顺利收尾那条 `终态:released` 不再进对话区 (落地结果那一屏已经说全了,且它摆的是英文状态名);没顺利收尾的仍出声,措辞取 `TERMINAL_STATE_LABEL`。 - **一道只认「有人写过」的门等于没有门**(2026-08-02,用户送来一单熔断的实测): 那一单跳过 S4/S5/S6 直接提交放行 —— 受理记录三行一个标没打、分类表一行没写, 却进得了放行门。查出来三个洞: ①**放行门的入场哨兵 `s_routed` 只有 onPart 没有 ifPart** —— 「往 need_sourcing 写过一笔 就开门」,模型顺手写了个 `false` 就把门推开了。现在认**办完了没有**, 且三个数全由基座现数(打了标的条数 = 记录行数、去向定过了)。 ②「每条都已打标」这条 L2 读的还是活动自报的 `untyped_total` —— 「机检只许读基座数得出来的数」**第三次**被违反(前两次:missing_key_total / missing_minor_total)。改读 `_type_tag_a + _b + _c = _rows`,两边都是基座出的数。 ③**拒回把「活没干完」说成了「数或行对不上」** —— 那一单数是对的(诚实报了 3 条没打标)、 行也是对的,而话术只给「改数 / 改行」两条路,还明写「别为了过判据去改那个数」, 正好堵死它唯一想走的门,于是原样重提五拍熔断。现在判据点名的表若**这一单一行都没写** (基座 `_rows` = 0),就直说「那一步还没办,回去办了再来」。 **指向两扇打不开的门,比不指还糟。** - **验收那一屏是活动的收口,答两件事**(2026-08-02 用户定):①落了什么 —— 按**交付物**点名 (`RequiredDeliverable.ledgers` 说清一份成果由哪几张表承载:A1 的受理记录 / 分类表 / 结论 是**同一份**询价受理记录的内部结构,从前各占一条,人在成果面上看到三样东西); ②往哪儿去 —— 转出哪一口、**带过去哪些字段**(载荷即已落地的事实,摆列名不摆值), 一个口都没发就直说「到此为止」。同批:`统一受理记录` 全仓改称 `询价受理记录`; 成果列表执行蓝 / 验收绿两色;办结卡那一钮改称「打开报告」。 - **签完到收尾之间有自己的话**(2026-08-02 用户:「点完验收按钮后会闪一下中间态」): 那不是渲染毛病,是**真的中间态**(合并 / 发口 / 落终态还在跑)。从前它落在通用四态里 —— 待办清零先闪一句「都办完了」再跳「已收尾」;那句话在那一刻是对的,可它说的是另一件事。 现在这一段说「字已签下,正在落地」。**中间态本来就该说出来,只是要说对。** - **进度条漏了一格,和一条已经不存在的路**(2026-08-02 用户送来一条实测日志): ①`INTAKE_PHASES` 漏了 `S3_confirm`(它是 08-01 才补回成一项的)—— 计划项六个、名单里五个, 于是 S2 一收进度条当场跳到「判定去向」,而人这会儿正对着受理需求审定那张卡: **他手上办的那件事在条上没有格子**,条却已经走过去了。补成四格 (定位客户 / 归一受理 / 交你审定 / 判定去向 + 基座统一加的放行收口), 包内自测钉死「除放行外每一项恰好属于一个阶段」。 ②说明书里还留着「人交回来还缺必填,就再发一张卡」—— **提交闸上线后那条路已经不存在** (缺必填按不下提交),模型照它办,每次都撞在「这件事刚问过,人也答过了」上,连烧四拍。 改成「这张卡一单只发一次」;同时把提交闸补到**服务端**(收下回传之前把住)—— 说明书向模型承诺「卡回来时必填一定是齐的」,那句承诺只有服务端拦得住才算数。 - **话说的范围要盖住门拦的范围**(2026-08-02 用户问「为什么会少了 start」查出来的): 提示词那条规矩写的是「标了『须你启动』的项要先 start **再调工具**」——只说了调工具; 而拦截那一侧(`readyToWork`)管的是 tool / ask / human / decide / entry / finish 一整片。 模型那一拍要发的是 `human`(派工单),照字面读这条规矩管不着它,于是漏了 start, 撞上「S3_confirm 标了人工激活,要先 start 再干活」白烧一拍。**话窄一格,模型就正好漏在那一格上。** 写全之后三案例复跑 **全部被拒 0**(案例三从 14 拍 126k / 被拒 2 → 11 拍 97k / 被拒 0)。 同批两处呈现:目标价改左对齐(右对齐是给要竖着相加的数用的,这张表一行一个料、彼此不相加); 待处理那一屏表上方加**缺项红带**,点名还差几格、差在哪一行哪一列 —— 两个数由基座现算 (`_missing` / `_missing_keys`,与提交闸、放行门 L1 同源),「一格不缺就别出这条带」 交给样式表(`data-class-of` → `v-0` 那档 display:none),模版仍不算也不判。 - **A1 三案例常备**(2026-08-02):全 A 类直通 / 客户点名跳一条 / 新客户中文正文列料缺必填 —— 三条来件形状真不同(俄文 BOM 附件、正文点名跳料、中文正文列料无附件), 末次复跑 **3/3 released、全部被拒 0**(11 / 10 / 11 拍)。 - **A2/A3 按复杂活动 MVP 简化形完整重写**(2026-08-02 用户改盘:「MVP 期间只做精美验收报告 + 一张执行单,提交就是输出」):`quote-alternative@3.0.0` / `quote-sourcing@3.0.0`,各四项扁平 (归一 → 一张执行单交人 → AI 判稳/齐检 → 放行)。**A2**:挑 C 类组单交 FAE 系统外选型填回, 替代料查库行情**判稳定标**(≤90 天且稳转 A,否则转 B;尺与 P-03 的 A/B 行同一把), 询价受理记录就此转成**询价受理清单**;出口 `alt-route` 两口带 when(还有 B → to-sourcing, 全 A → to-pricing),verdict 落 `need_sourcing` —— **E5 自此第一次真正成立**(从前 A2 台账 没有承载列,那条边恒假)。**A3**:归一**目标报价清单**、A 类行按库内历史价预填 (`price_basis` tally HIST/SOURCED)、PRM 执行单补货源价 —— `base_price` 标 `required`, 件上红带 / 执行卡提交闸 / 放行门 L1 三处同源,实测闸真拦(单飞两颗料只填一颗, 交卷被点名「缺底价」)。判据全读基座读数(旧版两活动各两条 L2 读自报数,全部置换); GRADE_DMN / STRATEGY_DMN 两张零求值器判定表、shortlist/benchmark/supplier_quote/compare_table 四张不再产出的表、两个死 `run()` 全部退役留墓志铭。报告各一张件贯穿在办与归档 (`alt-roster` / `sourcing-roster`,PRD 版面语言拷自 A1;A2/A3 无 PRD 目标件,用户定沿用自造)。 **验收:A2 3/3、A3 3/3 全部 `released`、行动被拒 0**(6-7 拍 / 38-47k token), 三案例形状真不同(流内混行载荷 / 免寻源转 A / 单飞宽进自造案号)。 `contract.input.required` 一律空(用户定:宽进严出,输入契约在活动内归一+补全)。 同批:A1@43 出口撤空壳 `altRequests`/`rfqRequests`(表已退休,数组通配让它装的与 records 完全相同);e2e 脚本落成 `tools/e2e-a2.mjs`(登录 AI → testbed 起单 → 件上按地址保存 → 答卡 → 断言 released/被拒 0/发口)。 - **「算出来的口」改为服务端算数**(2026-08-02,A2 e2e 逼出来的 harness 修死):放行卡的 `routedPort` 从前只在**前端回传**时顶上 `selectedPorts`(chat-bubbles 里那段),而放行落地 读的是**人事件载荷**(原始 reply)—— 换个客户端(脚本/API)就死在「选择组未选出口」, 台账已合并、单落 `blocked`。现 `human-tool-service.replyWorkOrder` 在发事件前算好**有效口** (routedPort 优先,算不出才认人选),事件与返回值同一份 —— 服务端说了算的事, 不靠每个客户端自觉。顺带:执行卡 `fields` 缺席时基座兜底加必填「结果」回执字段, 代答脚本交卷要带 `values.result`。 - **A2 浏览器真人路走查通过并逮住一个洞**(2026-08-02):锁定 → 编辑 → 填错取消(还原)→ 重填 → 保存(痕「改了 1 行」不撒谎)→ 交执行卡 → AI 判稳(原标 C 现标 B,依据逐行留痕)→ 验收签字 → **released、7 拍/51k、被拒 0**;归档件零输入框、闸与红带都收、去向命中留在定稿。 逮住的洞:**模版主键格没挂 `data-col`,人保存的行没有钥匙**,服务端按「全表一致列」补键, 两行对到同一行上、后者盖前者(BBPY 的 C 标被隔壁行的 A 盖掉)—— e2e 走 API 自带主键测不出, 只有件上真按保存才现形。修:主键列必挂 `data-col`(它不是编辑面,是行的钥匙;A1 从头就带), 两包自测钉死,`quote-alternative@3.1.0` / `quote-sourcing@3.2.0`。 A3 另修一处时序:第一拍禁写 verdict(凭据列提前落会让引擎提前收步,预填从此不发生 —— 实测嘴上说预填了、台账里没有)。 - **A2 执行件重做成替代选型工作单**(2026-08-02 用户:「执行工单的 HTML 怎么是按验收单做的? 替代选型要为选型高度定制一个模版」):`quote-alternative@3.4.0` 两个局面各一张 —— `alt-worksheet` 选型工作单(S1/S2 摆):逐颗料一张**选型档案卡**(题面:要素/为什么要替代/ 客户约束与预授权;定案回显带待填胶囊;A/B 行收成「原样承继」一行)+ **替代等级判据表** (P2P 直换 / FUNC 功能兼容 / OTHER 须验证,附 pin-to-pin 五项核对与「同封装不等于同引脚」警示)+ 三层筛指引(参数硬指标 → 认证合规 → 供应价格)+ 填回工作表;`alt-roster` 清单(S3/放行/归档)。 台账补齐**对标维度**:`alt_grade`(tally P2P/FUNC/OTHER)/`alt_diff`/`alt_risk`/`alt_verify` + 承继 `remark`(预授权/约束);执行卡指导书按等级写死核对深度。复跑 3/3 released、被拒 0。 连带逮住一个渲染器约束并记进陷阱表:**行展开按第一个同名闭合标签截行内容** —— `
` 的行模版里嵌 `
` 会把行截成套娃(第二张卡长进第一张的表头里), 行容器要用行内不会再出现的标签(`
`/``)。 - **A2 选型工作单精专一颗 + 逐颗按序派单**(2026-08-02 用户两条:「选型 HTML 里为啥出现 ABC 类描述的表?这个报告就精专一个芯片的选型」「多个芯片按顺序派选型单」): `quote-alternative@3.8.0`。台账加**排程列 `sel_stage`(tally NOW/WAIT/DONE)**: S1 给每颗待选型料标 WAIT;S2 只 start 一次、一串卡都发在它名下 —— 每轮把一颗置 NOW、 发**这一颗**的选型单(标题带 PN 与第 k/n 颗,互不撞「一单一卡」闸;卡=七格表单, 选填显式 `required:false` 留「替代未果」通道),人交回 → 定案照抄落行、置 DONE → 下一颗; 全部 DONE 记 filled_total 才 finish。工作单随排程列演**当前这一颗**:顶部选型队列丸 (当前蓝/办结绿/排队灰,非选型行一枚不出)、替代关系图(芯片→芯片内联 SVG,未定案「待选定」红)、 题面/定案两栏档案、等级判据三档配示意图(P2P 引脚一一对应/FUNC 芯片+外围件/OTHER 打样烧瓶)、 pin-to-pin 五项核对图标带(封装尺寸/引脚/电气/温度/认证)、三层筛漏斗;填回表只显当前行; 已定案收一行摘要 —— **ABC 分类语言全部归收口清单**(自测钉死工作单正文不含原标/分布条/判稳)。 验收:3/3 released、被拒 0(双卡案例 8 拍/69k,第 1/2 → 第 2/2 依序)。 路上逼掉三类抢跑(guide 写死):S2/S3 收步后「这一拍到此为止」、第一轮 start 提成显式第一步、 被拒重试不重写已生效的值(空转写也是拒)。 - **A3 执行件同款重做成寻源询价工作单**(2026-08-02 用户定,素材取 MVP 示例工作流 §1.7 **只作文字参考、不作实现逻辑参照**):`quote-sourcing@3.4.0` 两个局面各一张 —— `sourcing-worksheet`(S1/S2 摆):逐颗待询料一张**询价档案卡**(题面含**取价对象** 「替代料有值取替代料」/客户约束;A 类收成「已按历史价预填 · 可校可改」一行)+ **按场景圈渠道**规则(BOM早期可放宽 / 后期主→备选→贸易商圈两三家贸易商尽量不用 / 现货只认库存实拍无库存转单商不可选 / 样品量小求快)+ **价格验证的尺**(早期首报即用 / 后期按历史最低降两成两轮核 / 现货多重校验 / 样品低于线上即用)+ 发询纪律与时限带 + 填回工作表(缺价红带与提交闸同源);`sourcing-roster`(S3/放行/归档)。 `quote_list` 补承继列 `remark`(认证/预授权/急料)。复跑 3/3 released、被拒 0。 同批堵一条自造案号的口子(A2@3.5.0 同款):单飞造号**只从本单来件取材, 不许从台账里已有的别单单号里挑** —— 实测一轮借走了正式表里的 MD14.1。 - **执行卡零输入**(2026-08-02 用户定:「执行卡片不要有任何填写的了,填写全去工作区, 包括A1的补全信息,那个『结果』输入框没任何作用」):基座兜底的必填「结果」textarea 删掉 (`fields = declaredFields ?? []`);三活动卡骨架撤 `blocks`/`fields` —— 填报全在 工作区的件上(editGate + 孪生件,保存即落草稿层,模型**不许再 write 一遍**)。 **提交闸回落**:卡不绑表时改看必交付物声明的 `ledgers`/`ledger`(纯函数 `gateAddressesOf`,有测),与放行门 L1 仍同一个数;服务端收回传前同一段把关。 连带删「执行工单 = 指导书 + 空表单,表单不得为空」的拒发 —— 通道换到件上之后, 那道机检让活动照新规矩发卡、基座按旧规矩连拒到熔断(实测 A1 五拍)。 - **A2 选型件升格「一页汇报」**(2026-08-02 用户:「还是不够华丽,要设计成强交互的 汇报形式,直接拿去当一页 PPT 的程度」):深空电路底 hero(队列信标呼吸 / 原厂芯片 → 流光走线 → 替代定案 / 四格账)+ 编号 slide 小节推进(题面七格 · 等级三卡悬停展开口径 · 五项核对徽章 · 三层筛 · 填回表 · 已定案摘要,空节 `:has` 自折)。 「强交互」全是纯 CSS(hover 浮起 / focus 展开 / reduced-motion 全静),沙箱仍零脚本、 模版仍不算不判。规范新增 §8.5 立此语言;踩了「媒体查询写在基础规则之前被盖掉」 的层叠坑(竖排下走线该藏未藏,排障入册)。 - **start 墙拆除 + JSON 括号栈 + 空转拒回带指南**(2026-08-02,零输入改造连跑逼出): ①**人工激活「先 start」不再是墙**(`readyToWork`):措辞写全(话与门同宽)之后 A1 仍连拒五拍熔断,五次全是「要先 start」—— 那墙保护不了任何东西(start 是模型自己的 动作,同一串连发即过),学不稳的礼仪就是死法;现在**动它就算启动**,人工激活真正 要保的两条(引擎不因哨兵替启、不给 doneWhen 替收)原样有测。三活动剧本的 start 礼仪同批删除。②关思考的模型偶发多吐一个 `}`,单数花括号的配平切出半截非法片段, 整拍六个动作全对却退化成「需要你判断下一步」兜底卡;`parseJsonLoose` 改**括号栈**、 不配对的闭括号当噪声丢(7 测)。③「写了等于没写」拒回补行动指南(值已在台账 → 该办下一件事),治 A2 收步时连拒四拍的重写循环;A2 判稳同批堵死「拿上游原 PN 的 9999 顶替、不亲查 alt_pn」的近路(实测走岔过一单去向)。 **e2e 三套七案例 7/7 released、全部被拒 0**(6-11 拍):a1 闸拦空手交卷→件补年用量; a2 to-sourcing / to-pricing / to-sourcing;a3 quotation×3(案例 3 闸拦真拦)。 浏览器全链走查:hero 呈现、编辑→保存→落草稿→队列推进(办结绿/当前信标)→ 零输入卡提交→released。A1@45.0.0 / A2@4.5.0 / A3@3.6.0。 - **一天里连挨三炸后的返工账**(2026-08-02 下午,全部用户实测逼出): ①**工作区滚轴拉不到填写区** —— ViewContainer 量高在 `editable` class 落下**之前** (闸/红带现身把内容撑高 122px 没人再量),且 ResizeObserver 挂在 srcdoc 之前那份 空白文档的 body 上(盯着一具尸体);修:先 bind 再量 + observer 每次有机会重挂真 body。 ②**「稳定的活动又开始出错」** —— 零输入改造时我往**全局提示词**塞了一句 「执行工单…别再 write 一遍」,把 A1 说明书「人交回确认卡后写 confirmed_total 记账」 顶翻:模型收到答复不记账不收步、把确认卡当没答成,重发同一张卡连拒五拍熔断。 改回通用真理(「人答回的东西在轨迹里,照说明书处理,别当没答过再发一张」); **全局提示词只说通用真理,活动级细节归说明书** —— 此为铁训。 同批把「重发已答过的卡」从拒改为**头两次无事发生 + 观察指路**(第三次起才算被拒, 熔断兜底仍在),空答复落痕带「人已办完并交回」一句(空 values 在模型眼里像没答)。 ③**「啥都没干就能提交」** —— A2 定案列当时全标选填(想保「未果留空」通道), 闸回落后成了没牙的闸。新增**行级必填 `requiredWhen`**(`{column:'sel_stage', value:'NOW'}`:该轮到的那一行才算必填,排队的颗不拦当前的卡 —— 表级 required 在逐颗派单下会被第二颗的空格拦死成死锁);未果通道改「备注写缘由 + 行首 × 撤行」。 `_missing`/红带/提交闸/放行门同源生效,e2e 三案例空手交卷全部 400 真拦。 ④**「输入区和汇报内容为啥分开?一屏都看不完算什么一页 PPT」** —— A2 工作单改 **看与改同一块**:01 区平时是汇报稿(题面七格+定案摘要+档案行),按「编辑」同一块 换成表单(`:has` 切换),保存/取消回稿;方法论(等级三卡/五项核对/三层筛)收进 原生 `
` 折叠条(零脚本);页高 2528 → 1285。A2@4.7.0。 ⑤**遗留(记 debt):A2 单飞判稳连续两轮「不查工具直接编」**转 A 走岔去向 —— 说明书措辞已到头,结构性根治 = 判稳 decisionTask 化 / 工具出参带标(见 debt.md); 现状兜底:验收页 type_tag 可改、去向跟着变。 ⑥契约变更:`FieldDeclaration.requiredWhen`(api-report 已刷新,随本轮一并提交后 api:check 门才绿 —— 它拦的就是「契约变了没入库」)。 - **A1「又出补全卡」的病根:入场哨兵读自报列**(2026-08-02 用户送来 exhausted 单): `s_parsed` 读模型自报的 `line_total`,模型把 record 三行在 S1 拍写完、没记这个数, S2 空手收步 —— 门永不开,引擎报「依赖断点」,提示词「断点请调人」把模型推去发 补全卡绕路(两张标题只差尾巴的卡把 humanCalls 4/4 烧光)。 **「机检只读基座数」第四次违反现形,这次是哨兵**。修:s_parsed 改读 `quote_intake_record_rows > 0`(行落了门就开,不等模型记账);`sameQuestion` 补前缀比对(≥6 字前缀 = 同一问)。复跑新客户空手确认路:**released、被拒 0、 断点 0、补全卡 0**(11 拍,回稳定基线)。A2/A3 哨兵同缝记 debt。 - **补全卡(ask)全局退役**(2026-08-02 用户定:「彻底全局退役补全卡,执行卡完全 就是包含补全语义的人类工具」):缺信息 = 发**零输入执行工单**(指导书写清缺什么, 人在工作区的件上补)。归一层把旧输出的 `ask` **原地转成执行工单**(字段名并进 指导书;拒回只会让模型换花样再发,归一才是铺路);引擎侧直发 `ask` 如实拒并指路; 提示词④段改写、handsOff 去 ask;A2/A3 剧本里「未果问人」改用决策卡(二选本就是 处置);规范 §3.4 五类卡 → 四类。历史卡回放兼容件(契约类型/前端渲染/起单老路) 留着,清理记 debt。A1@47.0.0 / A2@4.8.0 / A3@3.7.0。 - **A2 工作单第三版:对决卡 + 一张贯穿 + 占位三级**(2026-08-02 用户四条连发): ①「01 重构成渲染态就是结构,编辑就是写组件内的值;顶栏与 01 合并:左静态原厂 SVG 卡、右替换卡、等级直接选择(正确性全由人控)」→ **对决区**:深空 hero 里 左卡(原厂题面规格)→ 流光走线 → 右卡(替代定案就地编辑);**等级 = 三枚自绘 radio**(不写 checked,当前值 data-class-of 投影描虚线;基座 collect 对未选中 radio 整列不交 ——「没点」是「不改」;快照/取消按 checked 存取)。 收值铁律:**一张卡里所有输入格的祖父必须同一元素**(collect 按祖父归行)。 ②02 指引铺开、不写类型(口径贴在三枚选择钮上);③**空占位三级全局统一**: 必填红 / 建议填橘 / 选填灰 = required / expect / 其余(A2 已上,A1/A3 记 debt); ④**一张模版贯穿到底**:「待处理的 HTML 报告完成后直接转变为静态的工作成果」—— alt-roster 退役,收口内容(清单总览三态丸、去向判定)长在同一张尾部有值才现身; 规范 §1 硬规矩收紧,A1/A3 旧制记 debt。基座陪三小刀:`setOpen` 对非表格容器把 `.on` 落在 `data-edit` 元素自身;collect/快照/取消的 radio 特判。 验收:e2e 3/3 released 被拒 0(闸拦三案例全 400);浏览器实证 radio 选 P2P → 保存落草稿 → 徽变绿 → 取消还原(含 radio uncheck)。A2@4.9.0。 - **A2 工作单定稿为 One Pager + 单卡多页 + 成果 1:1 快照**(2026-08-02/03 用户连定): ①「这份报告就是一颗芯片的替代选型」—— 队列丸/清单总览/去向段全撤(收口整合的 东西不在这份),版面 = 深空 hero 对决卡(左原厂静态 SVG 卡 · 流光 · 右替换卡)+ 选型指引(不分段);「待选定」与必填同风格红胶囊左对齐;编辑钮做进替换卡右上角 (cardbtn 三件套仍是 data-edit-open/cancel/save);等级口径贴在三枚选择钮上。 ②「一个执行单可以派多个 HTML 待执行报告,合理利用右上角的翻页」—— **逐颗派单退役**:一张执行单,件里一颗待选型芯片一页(行挂 `data-page`, orig_type=C 成页),右上角箭头翻页;`sel_stage` 排程列整个退休; requiredWhen 改钉 `orig_type=C`;双 C 案例 7 拍(比逐颗省)。 基座配套:渲染器**行内表单组名唯一化**(radio 组按行号缀名,页间不互斥); ViewContainer 通用分页(`[data-page]` 可见段,`page`/`onPages`,不传 page 不分页)。 ③「工作成果要 HTML/UI/数据/内容/布局 1:1 从待处理转成静态报告」(反复强调)—— 病根:执行单定稿走 WorkOrderReport 卡壳、验收单渲「当下」视图,都不是办结时那份。 修:**回执收下那一刻把渲好的件存进工单**(`WorkOrder.finalHtml`),成果页 1:1 静态渲快照(零编辑钮、数据定格);旧单无快照退最近视图再退卡壳(历史兼容)。 e2e 3/3 released 被拒 0;浏览器实证:1/2↔2/2 翻页、两页一次保存全落库、 成果点开即对决卡静态版。A2@4.10.0。 - **A2 逻辑收口:两件各归各位**(2026-08-03 用户:「验收工单怎么又变成选型了?」): 「一张贯穿」被我执行过头 —— 验收阶段摆的还是选型 One Pager。校准后的口径 (规范 §1 已改):**「1:1」的落点是每份件与它的办结快照**(在办可编辑 ↔ finalHtml 静态归档),**不同工作各有各的件** —— 选型 One Pager 归执行单(S1/S2), **收口整合清单归验收**(S3/放行/归档,`alt-roster` 恢复:整份清单 原标/替代/等级/现标/依据 + 按分类算出的去向判定,只读 —— 就地改走验收卡的 editableAtRelease 表)。浏览器全链实证:验收阶段工作区 = 收口清单(判稳这轮 也真查了工具:43 天·稳 → 转 A);成果两份定稿各是各的快照(执行单=One Pager 静态、验收单=清单静态)。e2e released 被拒 0。A2@4.11.0。 同批沉淀:活动开发规范新增 **§6.5 设计律八条**(墙要配路 / 学不稳的礼仪就是死法 / 拒回喂对抗观察喂事实 / 机检只读基座数管一整片 / 提示词分层 / 措辞治不了的结构治 / 改共享面全量回归 / 用户重复提的要求说明没打中病根);HTML 规范补「概念图形是 第一语言」与「收值三铁律」。 - **A2 两张报告第四版(用户 /brand 推倒重设计)**(2026-08-03): ①**选型执行工单**重单颗芯片:白纸文件基底 + 身份条(眉头式,客户在条内不占右上角), 深空只留「对决 Stage」(原厂芯片 →流光→ 替代芯片,PN 大字,**编辑钮组在 Stage 右上**); 定案面板白纸双栏(左题面灰底/右定案,输入全在右栏);指引脚注化(五徽一行+三层筛横条)。 ②**选型验收报告**重列表与落边:汇总带(条数/A/B/C)→ 受理记录大表 → **落边图**(SVG 流程:清单 → 菱形「还有 B 类?」→ A3 寻源/A4 定价,命中边实线亮+流光、 未命中灰虚,`case:routeKey` 投影 —— 不冒充判过)。 ③占位三种定稿:**必填(红)/选填(灰)/建议(橘)**(`ph-req/ph-opt/ph-sug`); **等级空位归「必填」**(不再写「待选定」),打开编辑即三枚选择。 e2e released 被拒 0;浏览器实证:Stage 空位红胶囊呼吸、落边图 v-r1 命中亮线带真实计数。 A2@4.12.0。 - **兜底卡不再摆模型原话:输出不成形先就地重问**(2026-08-03,用户送来一单: 「正常派工单为啥不是作业指导书,卡片里又是乱七八糟的东西」):关思考的模型偶发把 整拍输出写坏(一串行动一个都不认识 —— 多闭括号那形已由括号栈自修,这次是另一形), 从前一次没认出就发「需要你判断下一步」兜底卡,还把 JSON 原话整段摆卡面。 现在 `normalizeTurn` 标 `unrecognized` → decide **就地重问一次**(原文经 `note` 存工作日志内部痕,附「只输出 JSON」硬提示);第二次仍不成形才交人,卡面只说人话 (原话在日志,不上卡)。假网关三测钉死:重问只一次、原文进痕、好拍不白重问。 复测 e2e a1:released、被拒 0(11 拍/102k)。 - **提交钮靠右 + A1 占位补齐三级**(2026-08-03 用户两条):①执行工单的提交钮从卡脚 左侧移到右侧(`jc-fc-ft` 加 flex-end;验收卡「重做|通过」有 `jc-fc-sp` 撑着不受影响; 旧版报告页脚 space-between 同批)。②A1 报告里品类/制造商/目标价三列的空占位从灰 「选填」改橘「**建议**」(用户点的是目标价)—— 档位跟台账声明走:required→必填红、 expect→建议橘、其余→选填灰,颜色与 A2 同套;备注仍选填;「分级依据」那段话同步改口。 跟着一条(用户:「没有和数字对齐」):裸 inline-flex 胶囊按 baseline 挂,盒子比字的 基线深几像素,整枚往下坠、行高忽高忽低 —— 空格子(`:empty`)转 flex 居中 + `min-height` 撑住文字那份盒高,胶囊中线对数字中线(陷阱表入册)。 再跟一条(用户:「编辑态太拥挤」):那条 flex 规则比「编辑态藏只读份」的 display:none **更特异**,编辑态里胶囊盖过隐藏冒了出来,54 个输入框旁边各站一枚 —— 圈上 `:not(.on)`:胶囊只属于看的那份,编辑态里该不该填由闸与红带说。 quote-intake@48.2.0 已装,62 测绿。A3 的占位三级仍欠着(debt)。 - **保存不再闪:就地换内容的第二层是逐节点 morph**(2026-08-03 用户:「保存的时候 HTML 会闪一下,之前都修过怎么又来了」):08-02 那刀把 srcDoc 重载换成 `body.innerHTML`,文档不再重载 —— 可整树仍是**推倒重建**:47KB 样式表在 body 再解析一遍(head 那份还在,从此一文档两份同文样式,实测拿探针在真单上量出来的)、 二十来个 SVG 全部重建、CSS 动画回第 0 帧重起跳 —— 同一个症状,病根在下一层。 现 `ViewContainer.replaceInPlace`:顶层样式归位 head 去重(注意 `:scope > style` 在 DocumentFragment 上**实测不命中**,要用 children 过滤 —— 不然新旧顶层错一位 全树失配,浏览器独立三轮验证逮出来的)+ `morphNode` 新旧逐节点对齐,一样的不碰, 输入件活值只在拟值真变时跟上(人敲了一半的字不因无关重推被擦);任何一步栽了 退回整树重建(闪但不错)。验证:浏览器独立三轮(改值保identity/加行保敲字/ 遗留双样式自愈)全过;1103 测、typecheck/lint 绿。真单上的探针账:save 后 probe alive、loads 0、无 remount —— 闪的确不是重载,是重建。 - **「保存后旧值还持续一会儿」才是人看见的那件事**(2026-08-03 用户第三次指出同一处): 上面两刀治的都是**重绘**,而人说的是**内容**:保存要跑个来回(POST 落草稿 → 失效缓存 → 重取详情 → 新件推回),闸却在按下那一刻就关了 —— 这几百毫秒里屏上摆的是只读那份的 **旧值**,人刚敲完的数当场消失,看着像这一下没生效(会再改一遍、再按一次)。 值本来就在手上,不必等服务端告诉我们:按下保存**先把新值写进只读孪生件**再关闸 (`mirrorTwins`),回声到达时 morph 一比已经一样,一次重绘都没有。 只镜像格子自己的值 —— 红带缺几格 / 分布条 / 去向是**基座算的数**,一律等回声(界面不撒谎)。 途中逮住一条会让这一段静默失效的事实:**渲染那一遍把 `data-slot` 连同槽位一起消费掉**, 活 DOM 里只读那份与 input 都没有这个属性;认孪生件要**按位置**(`previousElementSibling`)。 第一版按 `data-slot` 找,在我自己搭的合成 fixture 上全绿、在真单上一格都不动 —— **验证要在真单的 DOM 上做**。实测:显示 1ms(点击同步内完成)、20 秒 663 帧零抖动、 值真落库(服务端详情里就是新值)。 - **A4 成本定价补齐到验收线**(2026-08-03,`quote-pricing@3.5.0`):契约宽进(input.required 清空, 原本 required `customerCode`+`records` 而上游 A3 发的是 `rows` —— 这条边真跑会断)、 `draft` 口载荷对齐 A6、哨兵与判据全改基座读数(`draft_total` 自报数是第 5 类同款违反)、 两份件(pricing-worksheet / pricing-roster)、78 条包内自测、e2e 加 `a4` 套件 (含**决策卡代答** answerDecisions / expectDecision)。**e2e a4 3/3 released、被拒 0** (7-9 拍 / 54-74k),闸每单真拦,超限那单真发决策卡。三处踩坑各留一条账: ①**只有一列价时 AI 会编价**(库里查不到的料它照样填一个,交代还说「价空着等你定」)—— 结构治:拆 `suggested_price`(AI 算)/ `quoted_price`(人填,`required`), 闸从此每单有牙,不靠模型分辨「这行算得出没有」;②门禁三列没人写、放行门只说 「数不对/行不对」→ 底价自检独立成项 `S3_gate`,`doneWhen` = 三档守恒(与验收 L2 同源); ③人点完决策卡后那一步被重念、guide 头一段写着「发一张决策卡」→ 连发四张烧光调人预算, 改成**先分岔(轨迹里人选了没有)再谈动作**。 - **决策卡也有了幂等兜底**(2026-08-03,A4 逼出):`resendVerdict` 抽成纯函数, 执行工单与决策卡**同一把尺** —— 人已答过的同一问,头两次「无事发生」(卡不真发、 humanCalls 不烧,只把事实摆回轨迹),第三次起才算被拒(熔断仍看得见)。 从前只有执行工单那一路有,决策卡一道都没有:同一个岔路口连发四张,四次调人预算 烧光落 `exhausted`。**按钮按两下不该变成墙,也不该变成四张卡**;6 测钉死三档。 - **重发判断要走在站上场之前**(2026-08-03,**A1 基线当场熔断**逼出来的顺序): 人答完之后那一步常常已经收掉,而 `readyToWork` 走在前面 —— 对 Completed 项直接抛 「这一步已经办完,不能再往它上面挂活」,于是「重发已答过的卡 = 无事发生」这条**唯一的活路 在最需要它的时候够不着**:同一条拒回重复五遍熔断(实测 13 拍 124k、发口一个都没有, 而数据本身合规)。重发一张已答过的卡本就不需要那一项在场 —— 它什么也不做。 两族(human / decide)同批换序,无事发生那一路**原样交回局面**(不顺手把项推上场)。 这是设计律第一条「墙要配路」的第三次现形。复跑 A1 四轮:三轮 released 被拒 0、 一轮 released 被拒 4,**熔断不再出现**。 同批修 e2e 脚本一处误判:**「已回传」不是「闸拦着」** —— 两种 400 长得一样而处置正相反, 当成闸拦着就原样再交一遍、三次判失败,把一单 released 的 A1 记成了失败。 - **A6 报价议价补齐到验收线**(2026-08-03,`quote-negotiate@3.5.0`):五项 (排版报价函 → 交人发出并落客户回音 → 逐条定案 → **还价才叫人拍板** → 放行), 四道哨兵全读基座读数,两张判定表(N-01 议价结果 / N-02 让步梯度),三口带 `when` (won / revise / lost),两份件(negotiate-worksheet 可编辑 + negotiate-roster 收口含落边图), 90 条包内自测,e2e 加 `a6` 套件。**连跑两轮 3/3 released、被拒 0**(6-8 拍 / 44-65k), 三口各覆盖一条,闸每单真拦,还价那单真发决策卡。三个结构账各修死并有测: ①**同一张决策卡连发六次** —— `revise` 那条路原写「定案不动」,人点完哨兵照旧成立; 改:`deal_status` 加第四档 `REVISE`,拍板三条路都必须动它,「办完了」在数上看得见。 ②**模型自己写 REVISE 绕过拍板**(一轮 released 而决策卡 0 张,让步梯度成摆设)—— 病根:哨兵读模型判出来的 `deal_status`;改读**客户自己填的那一格**(`_reply_type_counter`, 基座现数)。**「该不该叫人」不能由被叫的那一方说了算**。 ③断点那几拍模型自编决策卡(拿计划项中文名当 itemId / 换问法发出两张)—— itemId / ask / 选项值写进**说明书**(说明书每拍都在提示词里,而 step guide 在断点时没摊开)。 **等外部回音落在执行工单上**(人收到信把回音填进件里),不用 `listen` —— 引擎的 `listen` 恒挂起而 desk 侧没有投递 data 事件的入口(记 debt)。 - **五套十三案例一次全绿**(2026-08-03,第三阶段主体达成):A1 1 + A2 3 + A3 3 + A4 3 + A6 3 = **13/13 released、行动被拒 0、发口全对、提交闸每单真拦**(6-11 拍 / 45-108k token; 两张决策卡分别落在 A4 超限拍板与 A6 让幅超授权)。门禁 1278 测、typecheck / lint 全绿。 这一轮同时是**共享面改动的回归证据**(agent-runner 重问 / turn-runner 重发换序 + 决策卡幂等 / ViewContainer morph 与保存镜像)。A7 归档同法补齐中。 - **「机检只读基座数」第一次覆盖到工具**(2026-08-03,治 A2 判稳偶发走岔): 新读数 `tool_<工具名去符号>_calls`(`toolCallReadings` 按留痕数**成功返回**的次数, 声明过的工具一律先铺 0;调失败不算查过 —— 调不通等于没拿到行情)。 病根:判稳的行情只有 `crm.history-price-read` 一条来路,而模型偶发压根没调工具 就把料判成「稳」转 A,**自报的依据列写得漂漂亮亮**,去向从寻源走成定价(约十次一次)。 说明书已写到头,**措辞治不了的结构治**(设计律第六条)。A2@4.14.0 立 L2: `quote_alternative_list_type_tag_a = 0 or tool_crm_history_price_read_calls > 0` —— **写成析取**:一颗都没转 A 就无需查行情(全 B 那条路合法),有 A 才必须亲查过。 静态审(`static-audit.boundNames`)与包内自测的「谓词绑得上」名单同批扩到这一类 (`declarations.tools` 在审计入参里做可选 —— 老调用方只传 ledger,别掀翻整份审计)。 判据锚在 `orig_type_c`(原标)而非现标 `type_tag_a`:清单里的 A 多半是**上游原样承继**的, 拿现标当锚会把「全是承继的 A、一颗 C 都没有」这条合法路径也拦下。 - **「闸没拦」与「压根没东西可拦」是两件事**(2026-08-03,一次假失败逼出来的): `expectGateBlock` 从前写成「空手交卷必须吃 400」,于是模型碰巧把该填的格子全填上的那些轮 (A1 补齐了缺的年用量、A2 客户点名的替代料型号本来就在来件里)一律被判成「提交闸失效」。 **而闸好端端的** —— 拿一单直接空手交卷实测吃的就是 400,还点名了缺哪一行哪一格。 现在断言分三档:blocked / nothing-missing(该填的全填上了,闸无需出手)/ leaked(缺着还放过去,真失效), 用**与 buildEdits 同一份草稿、同一个列名**去数。断言报的失败是假的,真失效那天反而没人信它。 - **A7 情报归档补齐到验收线**(2026-08-03,`quote-archive@3.0.0`):归一情报卡 → 一张零输入执行单(逐条落**输赢归因** + 竞对价)→ 按败价幅度算档 → **入库口径决策卡** 拍板(全量/脱敏/仅内部)→ 放行,一口 `archived`。哨兵读**人填的那一格**、 6 条 L1/L2 全读基座数、`competitor_price` 用 `requiredWhen{cause_tag:PRICE}` (交期/认证败的行不被拦成死锁)、82 条包内自测。**e2e a7 3/3 released、被拒 0**(各 7 拍/54k)。 同批退役三张共享域表并留墓志铭(单案例算不出月度落地率、客户档案 A1 已持有、 行情历史与情报卡是同一份事实)。 - **A2 常路会跳过派给 FAE 那一步**(2026-08-03 发现,**未修**,已写 debt): 案例①连续三轮 6 拍收口、一张执行工单都没发 —— 模型自己把替代料填了, 而 S2 的 `doneWhen` 认的正是那几格填没填,于是收步条件当场成立、**人环整个消失**。 这是「触达世界的项不给 doneWhen」的反面教材:「把清单交给 FAE 选型」触达的是人, 完成与否不该由数据形状推出来。治法与 T_release 同款(人工激活 + 不给 doneWhen)。 **排除项**:撤掉当日新加的工具留痕判据(@4.15.0)后原样复现 —— 不是它引起的。 - **A1 的话与工单说的不是一回事**(2026-08-03 用户四连指出:「这个工单是让员工填必填, 建议追问目标价,其他选填,你这条日志的表述就完全变了」):件与卡早已是**三档** (必填红 / 建议橘 / 选填灰),而 A1 的说明书还在教**两档** —— 目标价被明写成「选填」, 于是交代里说成「缺的选填项你看着补」;更糟的是同一句里「NE555P 我先照历史价估」: **它把 S4 查来的历史价当成了客户的目标价填进去** —— 那是替客户表了态, 下游定价议价全建在这个假数上。三处同批改齐(`quote-intake@49.2.0`): ①说明书「两种分量」改「三种分量」,逐列点名哪几格是建议档,并写死 **目标价客户没给就留空、不许用历史价或经验价估**;②say 口径写明「用件上那三个词、 只说事实」;③S3 卡骨架的 steps/standard/basis 与验收判据 label 一并换成「建议追问」 (judge 按整句对名,说明书那一处同字改)。实测交代已改成 「DAG… 缺年用量(必填),UMW… 缺制造商、NE555P 客户没给目标价(这两条建议追问,不拦单)」。 - **反例引了原话,模型照抄反例**(2026-08-03 用户送来 10:40 的单:「还是老样子啊, 派工单的时候为什么会查历史价?」):上一轮治措辞时,我把那句错话**原文**引进说明书 当反例(「别说『我先照历史价估』」)—— 关思考的模型不读「别说」的否定框, 只认框里现成的句子,又原样说了一遍。台账数据其实全对(信里给了 8.0/22,NE555P 留空, 一个假数没写),错的只有这句被我喂进去的叙事 —— 且它谈的历史价那一拍**根本还没查** (S4 未跑,轨迹里零工具调用):纯编造。治法(`quote-intake@49.3.0`): ①**反例一律不引原话**(描述失败,不给可照抄的句子),A1 三处清扫,其余五包 grep 无同类; ②**要引原话就引正例** —— S3 派卡拍给了一句完整交代模版(三档词 + 只说事实); ③叙事纪律:历史价/分类/去向是审定之后那几步的事,派卡拍一个字不提。 验证:同一封信两轮 —— 一轮平实无编造、一轮逐字命中正例模版,台账两轮全对。 **提示词里唯一该出现的原话,是你想听到的那句。** 连带一笔:复现时我起的试跑单把用户 10:40 那单顶掉了(试跑台一次只挂一单,已有 debt)—— **用户正在测试台上测的时候,别起自己的试跑单**。 - **执行卡的指导书空了:卡骨架住错了地方**(2026-08-03 用户:「作业指导书展示不对了」): 受理需求审定卡的骨架(steps/standard/basis)写在 S3 那一步的**剧本**里,而模型把 「建档→落表→收步→派卡」压成一拍连做(被鼓励的省拍打法)—— 那一拍摊开的是 S1 的剧本, S3 的骨架看不见,模型凭记忆拼出一张裸卡,基座兜底 basis 又摆上「当下可为(空)/目标缺口」 这类内部家具。**卡内容不该取决于它在哪一拍被发出**。两处修: ①骨架搬进**说明书**(每拍都在;A6 决策卡先立此法 —— 断点拍自编决策卡同一个坑), 剧本留一句指路;第一版误插进 S1 剧本(录入卡骨架就住在那儿,被我当成了说明书), 测试逮住后挪进 NARRATIVE 本体。②`steps`/`standard` **补进出参 schema** —— 它们从前不在 schema 里,能到卡面纯靠厂商 JSON 模式宽松放行,而本仓早有纪律 「结构化出参只吐 schema 里声明过的键」(ai/ledger 当年就是这么丢的)。 `quote-intake@49.5.0` 已装;1366 测、typecheck/lint/depcruise 绿。 用户在途那单已见到全指导书;e2e 复跑等测试台空出来再补(他的单还开着,不顶)。 - **工作日志:一行摆首句,展开才看细节**(2026-08-03 用户:「细节展开不够好」): 从前一条只有一行标题,而留痕里那些人真想回看的东西 —— 凭什么算这一步办完了 (`rationale`)、那一笔写了哪几行(主键名单)、被拒到底拒在哪儿(`reason`+`hint`)、 发的是哪种卡送到哪儿 —— **一个字都没露过面**。现在 `detailOf` 把它们摘成 **人读键值对**(与 title 同一条纪律:不摆内部英文名、认不出的不摆), 折叠不占地方、展开才现身;**摘不出就是空数组,前端据此不给展开钮** —— 点开是空的抽屉比不给还糟。 连带修一处**文档与实现不符**:「一轮一句」口径说埋头办事那几拍的交代 「留进工作日志」,而实现把 `internal` 整类滤掉了 —— 那几句**哪儿都看不到**。 现在带 `say` 的放行(它是人话),章写「交代进展」、记在 AI 名下; 排障用的内部痕(重问原文)照旧不摆。 两种交代统一「首句上行、全文进抽屉」(一句话说完的不重复摆,免得点开发现一模一样); 截了才加省略号 —— 加了等于说「后面还有」。 实测:一单 8 行、6 行有抽屉、行高 34-36px 齐平,展开那两行 141/103px。 14 条新测(detailOf 五类 + 压下交代放行 + 首句去重)。 - **E04 关系覆盖与关键人经营修到验收线并全流程跑通**(2026-08-22, `crm-relationship-coverage@2.0.5`,用户:「实现完成了但做的不好」)。接手时两天 18 次 试跑只 2 次 released、活单正熔断;收尾:**e2e 三案例(点名/月度/驳回循环)+ 浏览器 新客户建档路全部 released**,新客户路被拒 0(18 拍/216k/5 人环)。修死的账,harness 四刀: ①**finish 的 doneWhen 按写完后的草稿算**(从前拍首快照,「先写后 finish」这个被鼓励的 省拍打法被误拒,下一拍引擎又用同一份数据自动收步 —— 同一份数据两个裁决); ②**空转写身后还有行动就不废串**(「被拒停在谁那儿」把「写记账旗+发卡」整串弃权, 排在后面的发卡从没执行过,连拒五拍熔断 —— 值没变的写什么也没改,后面行动不该陪葬; 串尾/独苗仍拒,熔断检测靠它);③**调工具挂不上项不拦调**(授权面是工具白名单, 与「写的授权面是台账声明」同款);④**读工具同一份入参重调:第 2 次起出参标题带点名 警告(不算被拒),期间没写过东西的第 5 次才拒**(实测模型把 recompute-score 连调 10 次 赌分数变卦 —— 26 次调用烧穿预算的前科在案而 stalledTurns 只数被拒,成功的重调无兜底)。 活动包三处结构治:⑤**S5 记账旗退役**(receipt_confirmed_total 是模型写的「人环凭据」, S4 一过它顺手写旗就坚信 S5 办完,[写旗+finish 被拒]×5 熔断两轮;门改读基座数 receipt _rows/_missing —— 回执四列全是人在件上填的,被叫的那一方无账可记); ⑥**收口拆两项**(S6_writeback 写回主数据 / S6_ledger_update 只写明细+结论 —— 三拍纪律写得再明白,模型照样把四张表挤一串,串尾最费字数的明细表被截成空数组; 拆开后剧本只摊自己那几张表,串想长也长不起来);⑦**case:openedAt 真的进 Agent 作用域** (说明书让拿它铸 round_ref 而这个键从前只注给视图渲染 —— 模型只能编,正式表里一有旧号 就照抄,测试台里所有单共用同一个案号、跨单主键相撞;现注真实开案时刻含年秒,跨单唯一)。 S5 指南改「唯引擎 worldTouched 事实行是从,别自己数 card-reply」——轨迹里躺着 S2/S4 的 card-reply,模型对不准归属,连续三拍幻觉「回执已交回」(措辞治不了的结构治第 N 课: **指南让模型判的事,引擎已有现成事实的,一律改成读事实**)。视图照目标件 §6.2 补齐: 关联任务(engines 注入 case:taskId)、步骤行、页脚案号、执行工单1 编辑闸措辞 「AI 已识别 N 个客户」(绑基座读数)、计划表补时间点列(判据③指向的东西must在卡面)、 回执对象列「客户 · 关键人」、结果摘要/客户反馈照目标件换 **textarea**(渲染器补 textarea 孪生:值进正文、collect/镜像/增删行全链)、台账更新确认补「依据/编码」次行 (三条 L4 从前让人判他看不见的东西)。verdict.trigger 改名 trigger_label(与入参同名, 首帧摆英文码);plan.status 死列退役;建档卡写的六列补进声明(授权面);两条 L1 谓词 各钉一半基座数(旗单独成谓词是「机检只读基座数」的伪装形)。e2e 加 `e04` 套件 (`stages` 按卡名对号 —— 一单两张不同表的执行单;`fillAllBlank` 整行扫空; `decideSeq` 驳回→通过按张走;buildEdits 泛化 rowKey,不再钉死 pn)。 新测:turn-runner +6、包内 76(补 steps.test.ts:count(customers) 三形状真 @sfeel 钉死 —— 未绑定名 flatten 成 [undefined] 长度 1 不是 0)、view-render textarea 3、ui-kit 2。 - **验收「重做」第一次真的能退回重做**(2026-08-22,柴浩实测:点了重做,单子卡死): 从前非 pass 裁决也走 `finished` 分支 —— runTurn 把在途验收消费成 null、返回 「finished 未放行」,task 层把它重新挂成 awaiting-human;**人已经说了话,却再没有 任何事件会叫醒它**(A 系列 e2e 从来只点通过,这条路第一次被真人踩到)。 修死(turn-runner + port.ts + CONTRACT.md,3 测):非 pass = **打回重做,不是终局** —— 意见(`PendingAcceptance.comment`,onEvent 从裁决载荷捕入信封)以 「验收被打回重做:<意见>」进轨迹(没写意见就明说「自己复核一遍」),在途验收清掉, **同一拍照常问模型**;刚被打回的那一拍不走判齐快道(判齐恒真的活动会在意见没人读时 原样再发一张卡)。模型修订后重新 submit,新发的验收卡才是下一次裁决的对象。 卡死的那单以「把消费掉的在途验收原样放回信封 + 拨回 running」救活 (不手插记忆行 —— task_memory 有封链,留痕必须走正规通道),实测:重做意见进轨迹 → 模型复核三条裁量 → 重新提交 → 新验收卡已回到负责人工作台。 - **「重做」得真的退回去改,不是原样再递一次**(2026-08-23,柴浩连点两次重做的实测账): 上一条修好了「重做后单子卡死」,但没治**空转重做** —— 打回那一刻案例模型的项全是 `Completed`,模型除了重新 submit 无事可做:两次都是 6 秒内把三条裁量判据重判一遍、 台账一个字没动就把同一份成果递回来,人看见的是「我说了重做,它当没听见」。两手一起治: ①**基座侧结构闸**(`raiseAcceptance` 一个出口管住模型 submit 与判齐快道两条路,6 测): 打回之后台账没动过(写/撤都算)就不许再提交;软硬两段 —— 头一次拒并指路 (改台账 / 或发卡问清楚要改什么),已因此拒过一次再提交就放行(墙要配路,不锁死单子)。 ②**活动侧指路**(`quote-…` 同理,E04@2.0.7 的 T_release 剧本加「被打回重做」分支): 闸只知道「没改」,**改哪一张表是活动自己的知识** —— 理由空改 `plan.rationale`、 依据虚改 `ledger_update.evidence_ref`、结论糊改 `verdict.summary`;没写具体意见就 自己挑最站不住的那处改实,一律同 PK 覆盖写(新开行会把收步判据弄假)。 T_release 的 `writes` 同批补上这三张表 —— 不声明就写不进去(写的授权面是台账声明)。 - **「取不到」不是「还活着」:测试台钉着死号说在跑**(2026-08-23 用户:「推进完成了, 但测试台还在运行中,没有停下来」—— 当场复现):面板钉着一个**已被别处清掉**的任务 (reset-runs / 另一台起单会先销毁上一单),屏上同时说两句相反的话 —— 上面「AWAITING-EVENT · 自动刷新 2s」灯亮着、钮写「停止仿真」,下面一条橙带 「取数失败 —— 任务不存在」。两处一起修: ①**后端状态码说错了一格**:「任务不存在」抛的是普通 Error → 兜底成 `500 internal`, 而 500 的意思是「服务器出毛病了,等会儿再来」—— 面板据此举着上一次的状态每 2 秒重试。 现在这条路由如实回 **404 not-found**(「这一单已经不在了」); ②**前端把「取不到」当成了「在跑」**:`q.data` 在取数失败后保留上一次成功的那份、 其 `terminal` 恒 undefined → `live` 恒真;`s === undefined ? 'live'` 那个兜底更是直接 在撒谎。抽出纯函数 `observeFace`(6 测)分三种局面说话:**没了**(404 → 停轮询、 灯灭、说「这一单已不在了」、当场松手回装配台)、**取数失败**(断网/500 → 不说在跑, 轮询留着等它回来)、**取到了**(照实说)。浏览器实证:起单 → 面板盯着 → 别处清掉 → 6 秒内自己回到装配台,鬼卡片不再出现。 - **立监听的授权面是清单声明 —— 立了没人叫醒的监听不是等待,是失联**(2026-08-23, 验重做那一单当场撞出来的第三个洞):S4 审批过后模型**漏写了 `plan_approved_total` 那面旗** (人工激活的项没有 doneWhen 兜底,finish 拦不住),S5 的入场哨兵永不成立 → 依赖断点 → 它临场「立一个 data 监听等执行回执」,而 E04 的 `declarations.listeners` 是**空的**、 这一单也不会有任何 data 事件进来(全仓没有一处消费静态监听声明,desk 侧更没有投递 data 的入口 —— 老 debt),单子就此挂在 `awaiting-event` 15 分钟一动不动。 修:`ListenerRegistrar` 补 `declared(taskId)`(engines 从清单取),`listen` 只放行 **声明过的那几种**,没声明的当场拒;拒回把两条真路一起指出来 —— 「要等人办事就发执行工单(人在件上把回音填回来);卡在断点多半是某个入场前提的数 还没写(常见是某面记账旗漏了),回去补那一笔,门自己就开」。3 测 + CONTRACT.md 已记。 - **步数是活动自己声明的预算,记的是 tick 不是模型拍**(2026-08-23 用户问): 测试台那三格读的是 `task.caps` ← 清单 `contract.resources.budget`(E04 声明 80 步 / 50 万 token / 12 次调人,A 系列 50-60 步 —— E04 高是因为四道人环 + 审批循环)。 **一步 = 一次 `task.tick()`**,而不是一次模型决策:实测一单 19 步里只有 12 拍真跑了模型, 另外 7 次是人回卡后「看一眼在途验收就返回」的空转 tick。挂起等人期间不烧步数 (推进器只捡 `runtime='running'` 的单),所以这笔账不会随人拖延而涨。 - **起单入参要预填满**(2026-08-23 用户:「询价受理起单时左边都有预填好的输入,E04 也要」): 测试台落到一个活动上自动铺的是 `samples[0]`,而 E04 的第一条样例只有 `{trigger:'monthly'}` 一个键 —— 表单除了那个下拉全空,看着像没预填(A1 两条样例都是 满载的一封信,所以那边没问题)。E04@2.0.6 把**满载的那条**(重大商机 · 点名 CU-0142, 四字段全有值)挪到第一位、月度例行补上真实背景说明,并把五条样例名收到 **≤14 字** —— 超过 14 字测试台只显示「样例 N」(activity-run.tsx),那等于没名字。 包内测试钉死这三条;e2e 的 e04 套件样例序号同批对调。 - **I01 品牌形象与销售工具包管理按 E04 标准审完并全流程跑通**(2026-08-23, `brand-content-toolkit@1.1.1`):**e2e 三案例 3/3 released、被拒 0**(9-10 拍 / 66-82k), 浏览器真人路(件上加一行 → 提交 → 初稿审核 → 发布放行)**released、被拒 0**。 审出并修死的问题,与 E04 那一轮同族: ①**两条 L1 只读模型自写旗**(`requirement_confirmed_total`/`draft_approved_total`)—— 各钉一半基座数(`_rows > 0 and _missing = 0`); ②**判据指向的东西不在卡面上**:L4「场景与 BT 标签是否登记完整」而 `content.asset` 压根没有 BT 列(剧本拿 `brand_tone` 顶替)—— 补 `bt_tag`(**人读值不带 tally**: 件上是普通格子、没有翻译层,存 ASCII 人看到的就是 ASCII,这是 `scene` 踩过的坑), 两份验收件都摆出来; ③**「发布前场景必须登记」只写在剧本里、机器数不出来** —— `scene`/`bt_tag` 加 `requiredWhen: {content_status: published}`,红带/提交闸/放行门 L2 三处同源; ④卡头/页脚缺说明书 §6.2 的四个共用动态位 —— 补关联任务(`case:taskId`)、步骤行、 页脚单号(最迟交回无真数据源,照 E04 口径不摆);编辑闸措辞改回目标件 「AI 已识别 N 个内容需求」(N 绑基座读数);触发口径并进【做什么】; ⑤样例名超 14 字全退成「样例 N」+ 样例 0 只有两个键 —— 收短名、把满载的那条挪到第一位; ⑥e2e 加 `i01` 套件(一张执行单 + 初稿审核决策卡 + 发布放行,含驳回循环案例)。 包内测试 29 → 44(补 steps.test.ts,把上面每条口径钉死)。 - **人在件上「加一行」会被静默丢掉:序号型主键没人给它续号**(2026-08-23,审 I01 时 逮到、浏览器实测复现):`content_brand.requirement` 的主键是 `round_ref + req_seq`, 而「加一行」那一下所有 `data-col` 都被清空(`ViewContainer.addRow` 如此)—— `req_seq` 空着,而各行序号本就互不相同,「全表一致」那条补法永远取不出 → `writeEditedRows` 一 continue 就没了:**屏上两行、库里一行,还不报错**。 修:凑主键那一段抽成纯函数 `resolveRowKey`(9 测),三类主键三种凑法 —— 件上给了的用他填的 / 件上没摆的按行认或全表一致 / **整数型主键由基座续号(现有最大 + 1)**。 途中自己踩了一脚并当场修回:一度把序号列的 `data-col` 拿掉「让它只读」, 结果**老行也没了钥匙**,服务端把它当新增行、又拿「只有一行时的全表一致」猜出个 1, **当场覆盖掉原来那一行** —— **主键列必挂 `data-col`**(它不是编辑面,是行的钥匙), 且序号型主键不走「全表一致」那条路(一致只是行数太少的假象)。 - **兜底卡自己被门拦住:最后的活路砌了墙**(2026-08-23,E04 回归实测):依赖断点那一拍 「当下可为」是空的,归一层给兜底卡兜出来的 `itemId` 就是空串,于是引擎自己造的那张 「需要你判断下一步」被 `readyToWork` 拒 —— 人连被问一句的机会都没有。 修两处:①归一层的项号兜底连**进行中**的项一起看;②**发卡的授权面是调人预算,不是计划项** ——项号挂不上照发、留痕注明(与「写看台账声明」「调工具看白名单」同族); 「这一步已经办完/停用」仍是真墙(既有测钉着),用 `ItemUnattachableError` 把两件事分开。 - **枚举列上下两态得说同一个字**(2026-08-23 用户:「BT 层级下拉框显示不全, 都看不到具体选了哪个」,`quote-…` E04@2.0.8):覆盖范围确认那张件的 BT 层级一格两处错 —— ①**列宽只有 80px**,而选项文字是「BT-01 · 采购/供应链」,下拉被挤扁,选了什么看不见 (覆盖深度那列因为选项只有两个字,同样的窄列一直没暴露); ②**只读那一份是 `data-slot` 直显**,存的是 ASCII `bt-02`,人看到的就是 `bt-02` —— 与编辑态下拉里的「BT-02 · 技术」对不上。**覆盖深度当初专门修过这个坑,BT 层级漏了**。 改:列宽 80 → 150,只读态换成 `data-class-of` 徽标、人读名由样式表出(值仍是 ASCII —— 台账与 recompute-score 的 `btLevel` 入参认它),选项文字统一成人读大写。 两条包内测试钉死:枚举列不许 `data-slot` 直显机器码、BT 列宽 ≥140px。 - **画面挑的是拍首那一步,而卡发的是下一步的**(2026-08-23,走查 E04 S4→S5 撞上): 那一拍收掉 S4(经营计划审批)、当场发出 S5 的回执执行卡,而工作区推的仍是 S4 声明的 **只读审批件** —— 人拿到的卡写着「把回执填到件上」,屏上一个可填的格子都没有; 提交闸如实拦住「缺完成状态、结果摘要、关键人变动」,他无处可填,整单挂死在那儿。 病根与 `liveScope` 那条同源:**拿拍首的局面去决定拍尾的事**(`liveStep` 在行动串跑完 之前就算好了)。修:推帧前按 `currentRuntime` 重算一次在办的那一步,算得出就以它为准; 算不出(活步都收完)照旧走老路,免得把人刚签过的放行页冲掉。设计律第一条 「墙要配路」的第四次现形。测钉死(拿掉修复就退回推 step1)。 - **表宽超出就得能横着滑**(2026-08-23 用户:「覆盖范围确认这个表格显示不全, 不能左右滑动」):E04/I01 抄 quote-* 版式时把 `.jc-tbl-wrap` 的 `overflow-x: auto` 抄成了 `overflow: hidden`(本意是圆角裁表头)—— 列一多、或某列为放下 BT 下拉框加宽, 右边那几列**直接被裁掉且滑不动**。两包改回 `overflow-x: auto; overflow-y: hidden` (竖向仍关:件是整篇跟着外层滚的)。实证:950px 的表在 586px 容器里滑得动, 编辑态(958px)同样。E04@2.0.9 / I01@1.1.2。 - **翻件与翻页各归各位,没得翻就别摆数字**(2026-08-23 用户两条:「一次叫人不一定只有 一个 HTML 模板所以需要翻页,现在这个 0/0 显示的不正常」「工作成果点进一个工作成果 也需要这个东西」):右上角那对箭头从前**三处各写一遍、两组二选一** (`docPages > 1 && openList.length <= 1`)—— 多张卡各自多页时**页就翻不动了**, 人只看得见每张卡的第一页。三处收成一个 `Pager`,两组同时在场时各带一个字(件/页)。 0/0 有两个来源,都治了:①`ViewContainer.paginate` 对没写 `data-page` 的件如实回报 0 页 —— **件在手上,再少也是一页**,改 `Math.max(1, …)`;②一件都没有时(在跑 / 等对话区那张卡 / 已收尾)摆的是 `0/0`,**0 分之 0 不是一个数**,改写「—」并禁用两枚箭头。 成果详情补**翻份**:一单常有三五份定稿(执行单快照 / 验收单快照 / 决策卡快照), 从前想看下一份得退出去再点一次;换份时页码归零(上一份翻到第 3 页,下一份可能只有一页)。 判断抽成纯函数 `pagerFace`/`pagerText`(9 测)。浏览器实证:决策卡那一屏「—」、 回执卡「1/1」、办结后四份成果 1/4→4/4 逐份翻过、末份下一枚变灰。 改共享面照例全量回归:1573 测 / typecheck / lint / depcruise 绿, **e2e e04 三案例全部 released、发口 coverage-map 全对**(16-20 拍); 两案例各有 1-2 次被拒,都是既有的模型空转被墙拦住(recompute-score 同参连调第 5 次、 S6_writeback 少写一行就 finish),非本轮改动引入 —— E04 的 `被拒 0` 仍欠着。 - **I01 的「审核资料」第一次真产出资料文件**(2026-08-23 用户定:「格式可以是 word、excel、 md、html,文件需要能在前端渲染,在表格中点击资料名可以跳转到一个新的页面来渲染这些文件」): 接手时这一步**一个文件都产不出来** —— S3 的剧本白纸黑字写着「file_ref 选填,本 MVP 阶段 可留空」,台账里只有一行标题,人要审的那份初稿根本不在系统里(点不开、下不来)。 **文件是台账那一行的投影,不另存一份**(另存 = 同一份事实两处各存一份,改一处就分叉): ①**声明**:台账对象声明加 `file: {titleColumn, bodyColumn, formatColumn}`(契约变更), 它同时是授权面 —— 没声明的表点不开(403),与「写看台账声明」「立监听看清单声明」同款; ②**现造**:`file-compose.ts` 进「标题 + Markdown 正文 + 格式」出真字节 —— docx / xlsx 是**自己打的 OOXML 包**(`zip-write.ts`:store + CRC32,不引依赖, 与 `upload-extract.ts` 读 xlsx 同一条路);md 出原文、html 出整份自带样式的文档; ③**读回来渲**:`file-doc.ts` 解**造出来的那份字节** → `FileDoc`(docx→段落 / xlsx→行列) —— 屏上渲的与下载到的是同一份东西,渲得出来才证明文件是真的; ④**点得开**:视图新增绑定 `data-file-of="主键列"` → 渲成 `data-file="域.对象/主键值"`, ViewContainer 接住 → 工作区二级界面 `FileViewer`(Excel 网格 / Word 纸面 / 渲好的 Markdown / 沙箱 HTML)+「下载原件」(`?raw=1`,RFC 5987 中文名)。 **Markdown 富文本渲染顺带销账**:`markdownBody` 一个依赖都没引(标题/列表/GFM 表格/ 分隔线/粗体/行内码),全程转义、走同一个沙箱 —— 与下载到的 .html 是同一段函数出的。 I01 侧:`content.asset` 加 `body_md`(正文,必填)+ `file_format`(tally 四档,必填), S3 剧本教它按内容形态挑格式(表→xlsx / 正式文档→docx / 网页→html / 短要点→md), 新增 L2 判据「每份内容都产出了资料文件」(四档计数之和 = 行数,两边都是基座数), 两份验收件的资料名都挂上链接 + 格式徽;新增第 4 条样例「对照表与落地页」—— 一封需求里三种形态,专治「一律 docx」那条走不到的路。 **验收**:e2e i01 四案例(含驳回循环)**4/4 released、被拒 0**(8-9 拍 / 68-89k), 资料文件逐份取得回渲得出,末条实测 `xlsx / html / md` 三种格式各出各的;浏览器在**审核那一屏**逐份点开 (Word 纸面出四节标题与要点 / Excel 网格出参数对照表 / md 渲成标题+要点 / html 出纸面), 「下载原件」拿到的 .docx 落盘后 `file` 认作 **Microsoft Word 2007+**、 macOS `textutil` 逐段读得出正文。新测 47 条(现造+读回 22 · `data-file-of` 绑定 4 · fileRefOf 4 · 主键解析 6 · 包内 11);全仓 1573 → 1620。I01@1.2.2。 连带治掉一处每单白吃一次的被拒:**「提交前先裁三条 L4」原本只写在 T_release 的剧本里**, 而拟发布与提交常被模型压成同一拍 —— 那一拍摊开的是拟发布那一步的做法,T_release 的 剧本这时**根本不在上下文里**,于是照着 S5 写完就 submit,被门点名「三条还没裁过」。 规矩搬进**说明书**(每拍都在),与 A1 的卡骨架、A6 的决策卡同一课: **模型会压拍,压过之后只有说明书还在**。 改了共享面(view-render / ViewContainer / desk 路由)照例全量回归:**e2e e04 3/3 released**、 发口全对(两例被拒 0,余一例是 E04 既有的模型空转)。 一处边界记进 debt:资料这一行落在**主数据**上,而试跑单放行时主数据只留在活动缓存、 不落正式表 —— 于是**试跑单放行之后**那份资料点不开(正式单不受此限); 404 的话已分两种说法,不拿「可能已被撤掉」把人支去翻一行根本不会在的东西。 - **产出的资料存了档,工作成果里点得开;查看面的灰底不再半路变白**(2026-08-23 用户两条): ①「渲染页面向下翻的时候背景的灰色在下半截会变成白色」—— **修了两刀,第一刀没打中**。 第一刀治的是走沙箱那两档(markdown / html):外层 `.fileview-body` 在 markdown 那一档 写死 `background:#fff`(它还是一整块 `
` 铺满时的写法),与里面那份自带灰底的文档
  不同色;改成同色 `#f4f5f7` + 去内边距,html 那一档一并(它套的是「渐变书桌 + 26px 边距」,
  而那份文档自带书桌)。**但用户报的不是这两档** —— 他截图里那份是 docx,
  走的是 word / excel 那条**父文档直接渲**的路(不进 iframe)。
  真病根:`.fileview-body` 是 `.fileview`(`height:100%`)的弹性子项,默认 `flex:0 1 auto`
  **不长个** —— 盒子高度被「看得见的那一屏」封住,而里面那张纸比一屏长时溢出盒子继续排,
  **背景只画在盒子里**:滚过一屏,纸两侧的灰书桌就没了,底下是面板自己的白。
  改 `flex: 1 0 auto`(不许被压 → 盒子至少和纸一样高;内容短时又能长满 → 下方不留白边)。
  实证(同一单来回切):撤掉这一改盒子 529px、屏底取到 `rgb(255,255,255)`;改在盒子 1399px、
  屏底取到书桌渐变。四种格式滚到底逐一取色:docx/xlsx 两侧是书桌灰,md/html 纸铺满且外层同色、
  无空隙。**教训:同一个症状可能有两条独立的路,治完一条要把另一条也走一遍**。
  ②「检查当前产出的附件是否存档,在工作成果里也需要有产出的附件,点击后可以预览」——
  **查出来的实情是没存**:文件一直是台账那一行**现造**的,而资料落在**主数据**上,
  试跑单放行时主数据只留在活动缓存、不落正式表 ——「放行之后再点开」实测 404,
  而工作成果恰恰是收工才去看的地方。现在**放行落地之前**(人的修订刚落回草稿层)
  把每一份造成字节冻进 `sys.task_asset_file`(迁移 0029,一单一行一份、重复放行覆盖);
  取文件那条路**存档优先** —— 归档件上点开的必须是他签字那一刻的那一份,
  不是台账后来被下一单改成的样子。工作成果里「产出的资料」自成一摞(与定稿报告分开:
  报告是「叫人办的那件事办完长什么样」,资料是**办出来的东西本身**),按格式上色、
  带存档时刻,点开即预览、可下载原件;件上与归档报告里的资料名照旧点得开(同一条路)。
  路上逮住一个只在存档那条路上出现的坑:**pg 取回来的 `Buffer` 挂在共享的 64KB 内存池上**,
  `buf.slice().buffer` 是视图不是拷贝 —— 三份资料下载下来都是 65536 字节
  (后面全是别人的残渣);改 `Uint8Array.from` 按元素拷。
  验收:e2e i01 断言加了「放行之后逐份仍取得回、原件仍是 ZIP」这一条,
  **四案例 4/4 released、被拒 0,每单都是「在办中渲得出 + 放行后存了档点得开」**;
  浏览器实证两屏(审核那一屏、工作成果那一屏)都点得开,归档件里的资料名同样点得开,
  归档的 .xlsx 落盘后 `file` 认作 **Microsoft Excel 2007+**、python `zipfile` 读得出
  整张对照表。新测 8 条(存哪些不存哪些 + 主键拼法);`reset-runs` 一并清这张表。

- **两个后端连同一个库,把同一张单推坏了**(2026-08-24 柴浩实测:E04 一单五拍熔断;
  用户中途提示「本机和局域网另一台机器的同一个后端都连着这个库」——最后一块拼图):
  症状是**两堵墙对着撞** —— `finish S2` 被拒「从没给它发过卡」,而重发那张卡又被拒
  「这件事刚问过,人也答过了」。查下来:卡确实发过(11:17:53 发、11:18:01 人答的),
  可局面里 **8 个计划项的 `worldTouched` 全是空**;同一步 S1 被收了两遍
  (两条 rationale 只差一个标点 —— 是两次独立采样,不是重放)。
  根因:两边的推进器各自 2 秒扫一次「running 的单」,**同时推同一张**,
  两拍并发写同一份 `sys.loop_state`,**后写的整份覆盖先写的** —— 发过卡这个事实就此消失。
  而互斥只在进程内(`task-lock.ts` 开头自己写着「MVP 单进程…多进程部署时再叠一层」)。
  **修**:`workers/task-claim.ts` —— 库里一列 `advancing_until`(迁移 0030)当跨进程租约,
  推之前一条 SQL 判+占(判与占分两句写就是经典竞态),推完就还,带 5 分钟过期
  (进程崩了不锁死);推进器与派发器两条推进路径都接上。
  实测:两条真连接对着真库抢 20 轮,**每轮恰好一个赢**;租约过期后另一方接得上。
  **还欠**(记 debt):`loop_state` 本身没有乐观并发(版本号 / CAS)——
  租约挡住了主路,但绕过它的第三条路仍会**悄无声息**地整份覆盖。
  排查法留一条:`worldTouched` 全空 + 同一步收两遍 = 并发覆盖的指纹。

- **点了要有反应,在办事要说出来**(2026-08-24 用户:「点击了都不知道点没点上」):
  两件事各缺一半。①**键感**:治理台整套 `g-*` 控件一条 `:active` 都没有,工作台只有零星几个;
  更糟的是有 `:active` 的那几个把 transform 一起塞进了 0.16s 的过渡里 ——
  一次点击常常比这还短,手抬起来时键帽才刚下去一半。新增 `styles/press.css`
  (三面共用、**装在最后**):按下 `scale(.97)`(整行整卡这类大件收到 `.995`,同样幅度会晃)、
  **按下这一刻不过渡**(松开仍走控件自己的过渡,回弹是软的)、`:focus-visible` 描圈。
  ②**在办**:请求在路上的那几百毫秒屏上从前一动不动 —— 新增 `shared/Btn.tsx`,
  `busy`(递 `mutation.isPending`)或 `onClick` 返回的 Promise 一亮,按钮脚下走一道
  不定长进度条。**不给 `disabled`**:那会把按钮画成灰的,而它此刻正在**做**这件事,
  不是做不了(界面不撒谎)。全仓 40 余处会去请求服务端的钮都换成了它;
  勾选与下拉给不了键感,改成把**那一行**点亮(认 `mutation.variables`,只亮真正在路上的那一条)。
  途中两个坑各留一条账:**条不能画进按钮自己的 background** —— 第一版用 background-image,
  在真页面上量出来根本不存在:`.tbtn` 这类皮肤用 `background:` 简写上色,
  特异度压过 `[aria-busy]`,图片当场被顶回 none(动画照跑,条却没有);改用 `::after`
  (全仓按钮类没有一条定义过伪元素,审过)。**``,渲染器只给自动孪生件(`data-slot`+
  `data-col` 空 span)填值,手写的一开编辑就是白框。修(E04@2.1.5 + 基座):
  ①新数据源 `touched:域.对象` = 正式现值 + 本单草稿叠加、按草稿键只取本轮碰过的行
  (engines `touchedRows` 纯函数;不进提示词,restPart 滤掉);②预览两表改绑 touched、
  文本格全部换自动孪生(select/textarea 本就有 current 填值);③**保存的「真改了吗」
  也对着叠加行比**(从前只对草稿:回显值一保存全算「改了」,痕写「改了 2 行」而人
  一格没动,日志撒谎)——「是不是新增」同理改判。
  连带逮出并修死一个**新增变覆盖**:人在确认屏加联系人,编码空着(自增列本分),
  而 `resolveRowKey` 的 findKnownRow 拿半把钥匙(只有 customer_code)把新行错配到
  该客户已有的草稿联系人行上 —— 编码从那行借来,模型刚建的那位被顶掉,痕还写
  「改了 1 行」。立规:**空着的自增列不是身份线索,是「给我续个号」**——声明 auto
  的列件上摆着却空着,一律不走 findKnownRow/全表一致,直进续号(2 测钉死);
  e2e 断言同批收紧(按填的姓名找行,防覆盖冒充新增再骗过一次)。
  **验收**:案例 0 released、被拒 0;定格的确认屏 HTML 六探针全中(Tier1 OEM /
  车规电子 / value="Itelma" / value="Ekaterina Volkova" / 测试CTO王工 /
  CU-E2E-ADD-01);痕三条全部老实(新增记新增)。1676 测 / 五门禁绿。

- **括号少一个,一拍全对也白跑:括号栈补上「补」这一档**(2026-08-24 柴浩:「怎么又
  推不动了」):卡在 S6 收口拍 —— 全流程括号最深的输出(decision_chain +
  interaction_timeline 两个嵌套 JSON 列),关思考的模型在 profile 行上**少吐一个 `}`**;
  drop 档(08-02 治「多括号」)把后面本该关 rows 的 `]` 当噪声丢掉,整段错位到尾,
  重问一次(温度 0.2)几乎原样复现,两连败 → 兜底卡「需要你判断下一步」交人,
  单子看着像卡死。修:`parseJsonLoose` 两档**有序**修复 —— 先 drop(多括号当噪声),
  失败再 close(闭括号对不上但栈更深处有它 → 把欠的补上;文本截断收尾 → 全补)。
  顺序不能反:close 先跑会把多括号那形的外层提前关掉、行动串截半(测钉死)。
  仍只合成闭括号,不发明内容。事故原文实测:三个 write 全解出。1679 测绿。
  **同夜第二形**(e2e 逼出):行对象没关、后面直接跟 `,{"key":…`(下一行)——括号到尾
  能配平、strict 与两档全看不出;close 档补第三条:**对象里逗号后面冒出 `{`/`[`,就是
  上一个对象没关**,把欠的 `}` 补在那个逗号之前(逗号其实属于外层数组)。两起原文
  全解出(11 测)。e2e 同批:认出「需要你判断下一步」兜底卡当场判失败收工,
  不再空转到 20 分钟超时。

- **数据域记录浏览的 JSON 列不再是 `[object Object]`**(2026-08-24 用户报):
  格子文本 `String(row[col])` 对对象一律糊成那七个字 —— 决策链地图 / 互动时间线两列
  整列不可读。补 `cellText`:对象/数组 stringify 原样摆,超 120 字截断加省略号、
  全文进 title(悬停可读)。别处早就对了(试跑草稿面 JSON.stringify、视图 displayValue),
  只有这张表漏了。浏览器实证:决策链格摆出 `{"nodes":[…` 真内容,全页无 [object Object]。

- **「关键人待识别」从计划渗进主数据又渗回来:占位句式全链退役 + 引用墙**(2026-08-24
  柴浩:「审批里怎么会有关键人待识别的项目」):三层病 ——
  ①模型把 2.1.1 的占位句式(查无联系人客户的 -00 行)**泛化到缺口节点**,给 Itelma
  编 CU-0142-02/03 引用码 + 占位人名(措辞三连拦不住:反例描述/说明书纪律/禁令);
  ②某单落库后这些占位行**以「关键人待识别」为姓名进了 customer.contact 主数据**,
  下一单从主数据读到它们照常规划 —— 污染自我强化;③一次 e2e 集合共用 bug
  (录入卡与决策卡共用已答名单,decideSeq 序号被顶,点名驳回被跳过)。
  修四层(E04@2.1.7 + 基座):①**占位句式全链退役** —— 查无联系人的候选客户改走
  **数据录入卡**先收第一位关键人(该问人的问人;骨架进 S3 剧本),真人建档后再排计划;
  一位联系人一行,缺口节点动作并进已知联系人那一行;②**契约新增 `refersTo`**
  ('域.对象.列'):声明引用关系,基座 draftWrite 那一刻查引用表(正式+草稿叠加),
  查无此值当场拒、拒回指路;安装静态审核 refersTo 目标真实存在
  (`reference-target-unbound`,写错地址=永远查无此值的死墙);plan/receipt 的
  contact_code 都钉上;③主数据两次清污(占位联系人删除);④e2e:录入卡代答
  (entryValues)+ 计划违禁字样断言(forbidInPlan)+ 已答名单分家。
  **验收(@2.1.7,主数据清污后)**:三案例 3/3 released、全部被拒 0(16-18 拍);
  案例 0 计划恰 2 行全是真人(Ekaterina 那行把两个缺口节点的动作并进她名下、
  王工按点名改成约见CTO),录入卡先收人 → 确认屏再补一位续号 -02;案例 2 单人单行。
  注意:refersTo 墙在这轮从没响 —— 主数据干净时模型照 2.1.7 的「一位联系人一行」
  就不再编码了;墙是备份,不是主路。**清污是前提**:主数据里躺着占位联系人时,
  引用检查会「合法」放行它们(引用的确存在),病就从主数据渗回来。

- **报价链 A1–A7 从系统卸载,只留 E04 / I01**(2026-08-24 用户定,**只卸不删源码**):
  六个 quote-* 包在库里置 `uninstalled` + 禁用(registry.uninstall),两个 RFQ 触发器
  (trg-rfq / trg-rfq-manual)停用 —— 触发器对着已卸载的活动起单只会生出坏任务;
  种子同步:`REAL_PACKAGES` 只剩 E04/I01,`seedMvpFlow` 以 `SEED_QUOTE_FLOW=false`
  整段不播(统一报价流程包 / 触发器 / 询价邮箱 —— 装不上的活动激活流程包会被闭合
  校验拦下)。源码、e2e 套件、包内测试原样保留;`MVP_PACKAGE` 常量仍是流程编译与
  触发装配那几组测试的夹具。**库里 `unified-quote` 流程包仍在**(active,节点指向已卸载
  的活动 —— 蓝图待补清单会点它),等用户定要不要连流程包一起退。要装回:名字加回
  `REAL_PACKAGES` + 拨回 `SEED_QUOTE_FLOW`,跑 activities:install。

- **台账更新确认四件小账**(2026-08-24 柴浩连报,E04@2.1.8):①**重做后旧明细留在表里**
  (SQ-0031 的覆盖度同时挂着 50→50 与 50→100):主键是序号,重做时模型新开一行而不是
  同 seq 覆盖。结构治:明细表加 `update_key`(台账地址|客户|联系人|字段,必填,
  `distinct`),S6 收步 + 新 L2「同一处字段只留一条更新」钉 distinct = rows;
  T_release 重做分支写明过期行 `drop` 撤掉。②**依据列带机器键前缀**
  (「回执 contact_code=CU-0087-02:…」):说明书与技能改教人话(客户名·人名的回执:…),
  不写编码、不带前缀。③**标题旁的单号不摆**:`doc()` 的 `titleRef` 改可选,四份件全去掉
  (页脚单号仍在)。④**验收判据与「AI 已完成」文案夹着 `coverage_score`/`decision_chain`**
  → 全改人读名。当前那单的草稿当场手术:删过期行、去六条前缀。包内测试 91 条钉死四条口径。

- **计划 7 行回执 6 行照样交卷、两堵墙对撞熔断、对话区偶发乱序**(2026-08-24 柴浩三连):
  ①**多行 write 不是原子的** —— 第 2 行撞 refersTo 墙被拒时第 1 行已落草稿,轨迹只记
  「被拒」,模型与人都以为一行没写,回执骨架从此少一行;提交闸只数已有行缺不缺必填,
  数不出「少了一行」;放行门「每条计划都有回执」拒 → 模型删计划凑数 → 「每家候选都进了
  计划」拒 → 加回来 → 循环五拍熔断,而缺的那行回执只有人能填。修:loop 的 write
  **整批先验后写**(`draftWrite` 加 `dryRun`,两遍),被拒 = 一行都没落;E04@2.1.9
  把「回执行数 = 计划行数」钉进 S3 收步与 S4 入场哨兵(派回执单前就得齐),S4 剧本
  加/撤计划行同步骨架,T_release 写明回执少行 → 补骨架重派执行单、**不许删计划凑数**;
  e2e 回执单派出那一刻断言骨架 = 计划。②**对话区按任务内序号排,不按墙上时钟**
  (`chat-order.ts`):合并从前按 `at` 字符串排,两台后端交替推同一单、时钟一偏,
  上一拍的话就排到下一拍后面;记忆 `seq` 与时钟无关,AI/系统项本身是记忆条目、
  卡对 card-sent、自由输入对 human-input(`say` 现在把消息 id 记进 detail),
  找不到落点的老数据按时刻插位。3 测。
  **验收**:脚本 e2e 案例 0 released、被拒 0、回执骨架 = 计划;浏览器全链(AI 账号,
  不落主数据):件上加客户 → 录入卡收 CTO → 点名驳回改对行 → 回执单待回执 2/2、
  闸拦空手交卷、件上填两行保存即落库 → 验收判据全中文、落库预览回显 → **released**
  (17 拍、被拒 1 —— 模型在 S3 先写了计划再写回执骨架、中间撞了一次 doneWhen 收步,
  下一拍补齐);对话区 AI 气泡 23:52 → 23:55 → 23:57 单调;更新明细依据人话、位置键唯一。

- **摆给人看的行标识去掉单号那一段**(2026-08-25 柴浩:「COV-…/CU-0142-01 只保留斜杠右边」):
  缺项红带 / 执行卡提交闸 / 拒回主键名单 / 就地修订痕从前把主键各列全拼上 ——
  可人正在这一单里看件,单号是脚下的地面,不是区分行的信息。基座 `rowLabel(id, caseKey)`
  按声明的单标识(`caseKey`)去掉那一段,四处同源同改;去完一段都不剩(主键只有单号)
  退回整段。`missingReadings` 入参补 `caseKey`。4 测;在途单 `views.repush` 一帧即见。

- **点击后两块同一帧变脸:「在办事」写在回传返回之前**(2026-08-25 柴浩:「右边聊天框
  先有反应,中间的 html 过一会儿才变成 AI 正在推进中,看上去很不流畅」):人回传落库后
  runtime 要等派发器投递、推进器抢到租约、开跑前那一刻才翻成 `running` ——
  前端 onSuccess 那一次重取抓到的还是 `awaiting-event`:对话区(卡状态已落)先变,
  工作区(读 runtime)要等下一次推送。修:`TaskService.wake(taskId)` —— 只对
  awaiting-event / awaiting-human 翻 running 并 setPhase('active')(顺带广播),
  两条回传路由(工单 / 对话卡)在返回之前调它。浏览器探针实测(100ms 采样):
  点「通过」后 **401ms** 中间已是「AI 正在推进这单」、对话区同帧「你选了:通过 ·
  持续推进中」;8.2s 推进完成两块同帧换成回执件 + 下一张卡。3 测;CONTRACT.md 已记。

- **对话区「上一步的卡跑到这一步下面」的真病根:并卡判紧邻只看对话项**(2026-08-25
  柴浩第二次报):08-24 那刀(按记忆 seq 排序)治的是**跨机器时钟偏**,而这次时钟没偏 ——
  I01 一单:「两份初稿…请审核」→ 发决策卡 → 人答 → 收口 → 发验收卡;`projectChat`
  的「一个气泡 = 交代 + 卡」只看 `out` 末项是不是还没挂卡的 AI 发言,而决策卡 / 录入卡
  的 card-sent、人的答复、内部观察都**不进 out**,那句话在它眼里一直「空着」——
  41 秒后的验收卡被挂到了上一步那句话上,以它的时刻排到决策卡前面。修:「刚说过话」
  按**记忆序列**判(话与工单之间不许隔任何条目;装配戳这类信封件除外;跨人卡 / 决策卡
  的 card-sent 也算隔开),一句话只领一张卡。3 测(26 → 全绿)。**同一症状两条独立的路**
  (时钟偏 / 并卡误认),治完一条要把另一条也走一遍 —— 这是 08-23 灰底那课的第二次。

- **工作成果里摆着别单的资料:「这一单产出的」被算成了「这张表里所有的行」**(2026-08-25
  柴浩:「这个工作成果怎么有 4 个资料,这单的需求只会产出一个」):那一单只写了
  `CT-2026-0004` 一行(三笔留痕全指着它、放行合并 3 行),而工作成果里摆着四份 ——
  另外三份是**品牌内容库里历次跑出来的资产**。病根一处、抄了两遍:放行存档
  (`archiveAssetFiles`)与在办列单(`assetFilesOf`)取行都用 `taskView(where:{})` ——
  那是「正式版全表 + 本单草稿」的合并视图,而资料常落在**主数据**上(`content.asset`),
  整表里躺着别单放行过的行。台账契约本就把这两件事分得清清楚楚(`taskDrafts` 的注释:
  「引擎求值要区分『这一单的事实』与『别人放行后的事实』」),视图模版也一律绑 `mine:`
  ——只有资料这两处忘了。修:抽一段 `assetRowsOf` 存档与列单同用,认**本单碰过的行**
  (草稿键),值仍取叠加行(改过一格的行按落库后的样子造文件);`touched` 是必填入参 ——
  「哪几行是这一单的」每个调用方都得回答得出来。e2e 补**份数断言**(存档份数 =
  本单写下的资产行数,多一份也判失败 —— 从前只断「取得回、渲得出」,多摆几份照样全绿)。
  用户那一单误存的三份已删,工作成果现摆 1 份、点开即那份 .docx。5 测。
  顺手清两笔:`wake.test.ts` 的 `as unknown as`(§12.5 禁止清单,lint 红)、
  `wake` 契约的 api-report 快照(上一轮没入库,api:check 一直红)。
- **统一鉴权中心(Keycloak)接入,只做后端**(2026-08-25,ADR-012):资源服务器 —— 后端只验 Bearer JWT
  (`jose`,RS256 / iss / aud 本地验,不回源);`Staff.id` = `sub`,首登即建、Admin API 同步名册;
  **权限只到端**:`sys.role_access` 一行一个 realm 角色,运营中心可改(锁死不变量:改完得有人还能进运营中心);
  路由归属写在契约 `access` 上,app 层一处中间件统一判 401/403,治理路由里 59 处守卫整体删除,
  覆盖测试 fail-closed;SSE 与下载走 60 秒票据;口令 / 会话表 / 岗位授权退役(八条路由回 410,契约留一轮)。
  web 待按前端手册接入,接入前登不进。
- **邮件收发模块接上腾讯企业邮箱,两条路**(2026-08-25,ADR-013,`apps/api/src/modules/mail` L1):IMAP/SMTP(任意信箱 + 客户端专用密码)与
  企业微信邮件 API(应用邮箱);腾讯没有带内容的推送,收信是**轮询拉**(每账号自己的间隔,跨进程租约 `polling_until`)→ postal-mime 解析 →
  `sys.mail_inbound` 两把唯一键去重 → 分发给订阅方(`channel` 是第一个:来信归一进事件流,活动经触发器 / `listen` 收到)。
  分发**自动只投一次**(channel → event 按 cause.ref 不幂等,重投会起两单),失败在运营面可见,「重新投递」是人按的钮。
  发信:`mail.send` 工具 2.0.0 真发(放行时经 ToolInvoker;`dryRun` 只校验 —— 注册的试运行会真调处理器)、channel 出站经 `mail.send`、
  运营面试发;先落 `sending` 再发,厂商失败不抛(`state:'failed'` + 原话脱敏);带幂等键的不发两封。凭证密封,视图只回 `secretBound`。
  15 条 `/api/gov/mail/*` 路由**全部归运营中心 `ops`**(读写都不给设计端 —— 邮箱那一屏没有设计端消费方,入站正文是客户来往内容,
  见 ADR-013 决策 10);前端未做,照 `docs/前端对接说明-邮件收发.md`。新依赖 imapflow / nodemailer@8 / postal-mime。
  欠账(debt):event 按 cause.ref 幂等、IDLE、wecom 无 Message-ID、channel 无 upsert 路由(共十五笔见 debt.md)。
- **「工作台疯狂轮询三个接口」= 两台后端互桥回弹的广播风暴**(2026-08-26 用户报):前端没有任何轮询
  (`refetchInterval` 全仓只在测试台),是 SSE 在以每秒几千条的速度推 `system` touch —— 挂在库的
  `jcai_touch` 频道上实测 **45 秒 192,270 条**,全是同一条 `POST /api/gov/process/validate`,
  在 8787 与 8790 两个进程之间严格交替、条数相等。病根 `broadcast-bridge.ts`:收到别人的 NOTIFY 就
  `broadcaster.publish` 到本地,而桥自己也订阅着这个 broadcaster,那条转发被当成「自己推的」再 NOTIFY
  一遍(from 换成自己)→ 对面不是它发的、再转发、再 NOTIFY……「自己发的自己不收」只挡一跳,两台接力
  就是永动机;08-24 验桥时只有一台在跑,没有第二方回弹。修:转发进来的那条打记号(WeakSet,publish
  同步派发),「本地 → 库」那一侧认出记号就不发;`bridgeBroadcaster` 第三参 `self` 可注入(同进程两座桥
  才模拟得出两台机器)。2 测:转发不再 NOTIFY 出去 · 两台互桥一条广播各到一次就停(假频道封顶 50 条,
  让用例失败而不是把测试进程撑爆 —— 第一版真·无限递归 OOM 了)。两侧任一打上补丁回弹即断。
  连带看见但未动:`task-service.tick` 每拍无条件 `setPhase` 广播 + 每拍推帧 + 推进器 `advanced`,一拍
  3-4 条 `task` touch,前端 `invalidateFor` 无合并 —— 推送有多密请求就有多密(记 debt)。
- **工作台任务界面给 SSE 配了 10 秒兜底轮询**(2026-08-28 用户定):`app/fallback-poll.ts` ——
  任务界面开着时每 10 秒把 `desk` 下**在用的**查询(清单 / 这一单 / 角标,`type:'active'`)各重取一次,
  推送漏了画面最多旧 10 秒;**不取消在途**(`cancelRefetch:false`,慢接口不被兜底打成永远取不回)、
  页签藏起不打、回前台先补一趟;壳层 `useEffect` 起停,切模块 / 卸载即 `stop()`(定时器与可见性监听一起摘)。
  `doc` 可注入,4 测钉死(周期 / 停止 / 可见性 / 在途去重,第四条做过变异验证)。
  §9.2「组件禁止自行轮询」照旧:兜底只此一处、由壳层起停。`queryKeys.desk` 新增作整支前缀。
- **录入卡在等人时,工作区摆占位页,不摆件**(2026-08-28 用户看柴浩的差异评估单定的):建档那一步
  (「客户 123 不在客户档案里,请核对建档」)要人做的事全在对话区那张录入卡上,而工作区里躺着的是
  **上一拍**推的 HTML 件,人以为要在那份工单上办点什么。前端判:`pendingCardsOf(detail.chat)`
  (纯函数,5 测)认出未确认的录入卡 → `ViewRegion` 在 running 之后、viewHtml 之前插一支占位
  `EmptyState`(点名那张表的人读名,指向对话区);决策卡**不走**这一支 —— 人要决定的常常就是件上那份稿。

- **第三个活动 ACT-WORK-05 差异评估已入库并全流程走查**(2026-08-27,`part-substitution-assessment@1.2.6`):
  原 PN 与候选替代料**逐项差异评估** —— 比参数、判四态(MATCH / MISMATCH / UNKNOWN / CONDITIONAL)、
  定推荐等级(推荐 / 条件推荐 / 备选 / 不推荐)、留证据与验证任务,落 P-11(替代关系 + 差异明细)、
  回写 P-01,发一口 `assessment-released` 交 ACT-GATE-03。
  **九个计划项**(五处不给 doneWhen):S0_bind → S0d_p08_master / S0d_p10_document(两张数据工单各一份件 ——
  一个计划项只能绑一份画面,不能共用)→ S1_input_confirm(唯一的执行工单,零输入)→ S2_normalize →
  S3_assess(两枚纯函数工具:`compare-parameters` / `recommend`)→ S4_review(决策卡循环)→
  S5_prepare_landing → T_release。
  **新建 4 域 7 张主数据表**(`parts.profile` / **`parts.parameter` 子表** / `parts.document` / `demand.request` /
  `substitution.relation` / `substitution.difference_item` / `validation.record`),主数据域 4 → 8。
  五张模版**逐字节搬自目标件**(`views/target-style.ts` 是抽取的原样式表,不用 E04/I01 的外壳)。
  **六轮浏览器走查全部 `released`**(都在库常路 / 候选缺库 / 三候选含硬约束不推荐 / 原PN缺库硬阻塞 /
  新客户建档 / 录入卡复验),覆盖决策卡、审核驳回循环、终局重做循环、数据录入卡四条人环分支;
  逐单 SQL 复核落账(`customer_approval_status` 每单留空 —— 只读边界守住,`rule_version` 随结论落账)。
  逐轮结论与 A–K 十一条发现见 `docs/ACT-WORK-05-端到端测试记录.md`,字段口径见 `docs/数据域字段说明-W05.md`。
  **三条值得记住的**:①**「机检只读基座数」第六次现形,这次是存在性不是计数** ——
  原 PN 根本不在库而模型判「在库」,剧本已写到头;治法是 `pn_check.found_pn_ref`
  (`refersTo: parts.profile.internal_pn` + `requiredWhen: {exists_status: found}`)——
  **判在库就必须拿得出一个基座查得到的料号**,查无此值当场拒、填不出则收不了步。
  ②**模型会压拍,压过之后只有说明书还在**(第四次):S1 的「先写清单再发卡」只在剧本里,
  压拍那一拍卡发出去而清单一行没有,人对着空表;规矩搬进说明书。
  ③**措辞治不了的结构治,但先分清「已经说过」与「从没说过」**:同一天的发现 I 是前者(该上结构),
  发现 J(数据工单派给了在库的那颗)是后者 —— 剧本从没写过「found 的不建」,补一句话就够。
  平台侧四条欠账已记 debt(`disable` 无路可走 · 前一项不收掉后一项的件推不出来 ·
  拒回数不出「缺的是一次工具调用」· 零行台账的提交闸无牙)。

- **脚本 e2e 逼出的八条:两条线逮到的缺陷不重合**(2026-08-27,`w05` 五案例连跑六轮):
  浏览器走查逮**人看见什么、点得动什么**;脚本逮**机制** —— 它每张卡都先空手交一次、
  每个岔路口按序代答,而人手点的时候永远不会去试「空着交上去会怎样」。**发现 L–S 八条,
  没有一条是浏览器那六轮逮到的**。末轮:跑到的四例全部 released、三例被拒 0
  (第五例停在大模型账户 `Insufficient Balance`,不是代码问题)。
  平台侧六条(全部有测):①**闸看错了表** —— 卡没绑表就回落到必交付物,而数据工单要人补的是
  `parts.*` 主数据、不在交付物名单里:闸盯着一堆无关的表、一格不缺,空手交卷一路放行。
  契约新增 `ExecutionWorkOrder.gateLedgers`(**这张卡该拦哪几张表,发卡的人说了算**),
  `gateAddressesOf` 变三级取一(绑的表 > 卡自报 > 交付物);②**拒回数不出「缺的是一次工具调用」** ——
  `finish` 撞 doneWhen 为假时只谈「行与列」,现在摆判据原文 + 那几个名字此刻的读数,
  `tool_*_calls` 读到 0 的单独点名;③**拒回喂指针没用**:人点了决策卡、模型每拍再发一张,
  把「他选的是 approve」写进拒回**照发不误** —— 下一拍它又从头翻一次会滚走的窗口;
  改结构 `answeredCardFact`,把「这张卡已答过 → 他选的是什么」做成**每拍都在的事实行**
  (worldTouched 2026-08-21、E04 事实行 2026-08-24 之后同一条道理的第三次);
  ④模型传 `requirement: null` 把工具打崩(边界上一律经 `text()` 归一);
  ⑤拒回里的 `count=(没写过)` 是 S-FEEL 函数名被当成台账名 —— **假线索模型会去追**;
  ⑥**零行 = 零缺**:模型压拍没写骨架就发数据工单,人打开是空表,闸与哨兵一起放过
  (`emptyGate`:卡自报的表一行都没有 = 没完成);⑦**「早收」不该算撞墙** ——
  工具还没轮到调 `finish` 先到了,那是计划次序的小错,头一次只落观察、第二次起才算被拒
  (与「重发已答过的卡」同一把尺)。
  活动侧 1.2.9:三张执行工单各自声明 `gateLedgers`;说明书补「发卡前骨架必须先有行」与
  S1 那张卡的前提(一颗 absent 都不剩);哨兵 `parts_profile_rows >= created` 逐颗对账。
  e2e 脚本加 `JCAI_E2E_BEARER` 直供旁路(卡会落到 token 主人的工作台、不续期;
  服务账号 `client_credentials` 仍是正路)。

- **数据工单确认即入库**(2026-08-27 下午,用户:「数据工单里面填的数据应该是确认这个数据工单后
  这些数据就应该入库了」):查下来草稿层通往正式表只有整单放行一道口子(`releaseWrite(taskId)`)——
  W05 的 P-08/P-10 卡上写着「确认后即入库」,而人建好的主数据要等整条评估放行才进表,试跑单
  (不落主数据)永远不进。**不能简单地「确认时 releaseWrite 那几张表再清草稿」**:引擎的 `mine:` /
  `_rows` / 哨兵(`parts_profile_rows >= created`)、视图 `data-rows="mine:parts.profile"` 全靠草稿层
  认「本单写下的行」,清掉就当场断。修法:`releaseWrite(taskId, { only, cause })` **范围放行** ——
  只并这张卡提交闸盯的那几张表(`gateLedgers` / 绑的 `blocks`,与闸同一份名单),并过的行**留在
  草稿层打 `landed` 记号**(`__draft.landed_at`):读面一字不变,整单放行不再写它、不抛事件、不做
  冲突检查(`landedEarlierRows` 分开报);再写一笔记号擦掉、基线换成落地后的值。事件不指回本单
  (它正等自己的人事件)。app 侧 `data-order-landing.ts` 在回传路由里、保存与回传落定后调它;
  失败不拦人(痕上说清,放行时再并)。`createOnly` 与 `drop` 对本单已落地的行改口(别 drop ——
  撤了读面少一行);数据域「在办草稿」不再数已落地的行。活动 1.4.8:两张数据工单的剧本改口
  「已入正式表,别再写、别 drop」。测:ledger IT 3 条(范围/记号/再写/试跑)+ app 7 条 + 域 1 条 +
  活动 1 条;e2e w05 数据工单交卷即验痕(`JCAI_E2E_LAND_MASTER=1` 时连正式表一起验)。

- **验收卡只许有一种样式;验收件题头改验收绿**(2026-08-27 下午,用户:「验收卡怎么有两种样式,
  统一都使用评审放行与落账确认这一步派出的这个验收卡的样式;中央 html 模版区域如果是验收工单
  把标题部分的红色改为和验收卡一样的绿色」):①审核卡(决策卡 `variant:'review'`)从前只换了头上
  的字、身子还是 A/B 选项列表;现在照终局验收卡 `AcceptForm` 那一套摆(`ReviewForm`:请你验收 ·
  验收工单入口 · 理由框 · [重做] … [确认通过]),机制不变 —— 通过交 approve 项,重做写了理由走
  `custom:<理由>`(基座按字面点名对行)、没写走驳回项;判断抽成纯函数 `review-face.ts`(7 测)。
  「验收工单」钮对没有工单行的审核卡也要有反应:`ViewRegion.locate` 找不到那张单就把待处理翻出来
  (件在那一屏)。②W05 两张验收件(ACC1 差异评估结论审核 / ACC2 评审放行与落账确认)的 `--ledger`
  由目标件的 #b23a2e 红改成对话区验收卡同一枚 #0aa294(`--st-collab`),题头渐变与徽章投影同改;
  CONDITIONAL 状态徽标是语义色,保留原红。W05@1.4.9 已装;浏览器走查未做(需登录统一鉴权)。

- **S1 清单把人刚填的参数摆成缺口:示例引了原话,模型照抄示例**(2026-08-27 下午,用户:「第一步已经
  补充了 XL2596S-5.0 使能阈值,当前这一步还要填一次?」):人在 P-08 件上填了使能阈值 2.5(已入库),
  两分钟后 S1 清单上却有一行「XL2596S-5.0 使能阈值 · 原厂未披露」。查下来 S1 剧本写着
  `input_item 如「XL2596S-5.0 使能阈值」`、说明书⑤卡骨架写着「原厂未披露的参数(如使能阈值)」——
  模型按示例造行,不读现值(值就在 mine:/focus 里)。与 08-03「反例引了原话,模型照抄反例」同一课:
  **示例也不引具体料号 + 参数名**。W05@1.4.10:示例改成占位形「<料号> <参数名>」,写明「先读现值,
  人填了值的参数不是缺口、零行合法」;包内测钉死。顺带看见:压拍时 `focus:` 只带拍首那一步的 reads
  (S0d_p10 那一拍连做 S1 的写与发卡,S1 声明的 parts.parameter 不在 focus 段,只靠 3000 字的 mine: 段)。

- **运营中心 · 活动模块接口落地(L1/L2/L3 十一条,全 `ops`)**(2026-08-27,`docs/API文档-活动模块.md` 已按契约回写):
  契约 `packages/contracts/src/{activity-ops,api/activity-ops}.ts`;服务端住 app 层 `apps/api/src/app/activity-ops/*`
  (纯函数:启动参数派生 / 五态映射 / 时间线 / 摘要 / 视图注入;raw SQL 存取;服务编排)+ `routes/activities.ts`,
  写全走既有 port(`task.start` origin=ops / `task.control('terminate')` / `registry.setEnabled`)。
  **设计端两条改名让位**:`GET/POST /api/gov/activities` → `/api/gov/activity-packages`(前端零改动,import 的是路由对象)。
  迁移 0034(`sys.task.seq` 人读实例号 `INS-` + 按活动索引)/ 0035(`sys.activity_launch` 幂等键一句 SQL 判占、
  `sys.activity_profile` 负责人/说明/图标/色相,seed 按岗位填三个真包,取不到留空)。
  五态是对 task 的如实映射(`pending` = 建单未被推进器领到;`rejected` = 打回未重提交那一段)。
  W05@1.5.0:四个启动字段加 `x-control`/`x-options`/`description`(combo 候选从正式台账现读),
  全流程分支图作 `activity-overview` 沙箱视图(模版无脚本,报高脚本由出口注入,协议 `jcai:view-height`)。
  前端 §10 对接另起一轮。测试:契约 7 + app 层 33 + W05 包内 +1。

- **差异评估结论审核件改版:一个候选一张表**(2026-08-27 傍晚,用户改了目标件
  `docs/SS02-ACT-WORK-05-html/ACT-WORK-05-验收工单-01-差异评估结论审核.html`:「存在多个替代 PN 要对比
  差异时看不清楚,现在将每个待选 PN 分开」):渲染器从前只认一层 `data-rows`,做不出「外层按候选复制、
  里层只列它名下的明细」。补**嵌套行模版 + `data-by="子列[=父列]"` 父键过滤**(`view-render.ts`,里层先按
  本行展开再填本行标量;4 测),它也能当查表用 —— 品牌不在 relation 上,`` 从整表挑那一颗料的行。件照目标件重搬:候选 PN 结论汇总
  (一个候选一条;差异统计绑 `difference_summary`,S3 剧本本就让它写成「7 项比对:4 MATCH / …」)+
  `
` 包 `
` 的分组明细(``); 判据四条照目标件改;ACC1_CSS 整段重搬(.cand*/.rec*/.stat*,CONDITIONAL 改蓝),主题色仍取卡的 #0aa294(目标件改版自己写的是 #16a34a)。W05@1.4.11。规范 §4 绑定表补 `data-by` 一行。 - **「库里明明有值,清单还要填一遍」第三次复现:根因不是措辞,是让模型宣布台账事实**(2026-08-27 傍晚,用户:「都已经出现几次这个问题了,自己找到根因并解决」):1.4.10 改了措辞照样复现 —— 这一单 XL2596S-5.0 已在库、三颗料 21 个参数全有值、说明书已是新版,模型仍写出 「使能阈值 · 原厂未披露」并在交代里说「原厂没披露」。三条线索:①S1 的「待确认」行是**模型对参数表 的一句断言**,基座没有任何读数核它;②说明书里「使能阈值」与「未披露 / UNKNOWN」同句出现三处, 其中一处是我 1.4.10 写的反例原话「使能阈值 · 原厂未披露」(08-03「反例一律不引原话」那课又犯一遍); ③S-FEEL 没有列表过滤,想拿判据核「gap 行数 = 未披露参数数」也写不出。修(W05@1.5.1):**S1 一行参数 都不写**(item_key 不许以 unknown_ 开头);件上加「候选参数现值」只读块 —— `
` 逐颗复制,里层 `parts.parameter` 按 `data-by="internal_pn"` 现读,人看得见 每个参数此刻的值;未披露的由 S3 判 UNKNOWN + 验证任务(本来就是它的活)。说明书全文不再出现 「使能阈值」(包内测钉死);S3 示例改「实测<参数名>」。设计律:**台账里有的事实,不许由模型在别处再宣布一遍。** - **「你真的改好了吗」—— 改是改好了,库里没有**(2026-08-27 傍晚):新起的单 `loop_state` 里还是旧说明书。 查下来两条:①`sys.activity_package` 里 1.5.0 / 1.5.1 两行都是**另一个会话**在同一个 checkout 上 改出来的(activity-overview 视图 + 启动表单 x-control),各比我的安装早几分钟占了版本号 —— 我两次 `activities:install`(候选分组件 / S1 参数行退役)全是**同版重装 no-op**,脚本还打印 「活动包已装」;②`manifestOf` 每次读库,不是服务缓存。修:升 1.5.2 重装并**用 SQL 核库里的清单** (查 JSON 文本别用 `\"` 手写转义 —— 第一次核出个假阴性);`InstallVerdict.stored`(契约,默认 true) + 安装脚本同版时改口「已是这一版,未重装」。规矩:**装完看库,不看脚本的话;两个会话同改一个包, 版本号先问库里最高的是几。** - **「验收卡又变成需要你定」「差异明细两张表没渲染出来」—— 同一个根:稳定版后端跑的是早上的代码** (2026-08-27 傍晚):`.stable/RELEASE` 是 `3171d8a`(11:53 构的),早于「审核卡摆成验收工单」那一提交, 更早于当天所有改动;它与开发后端(:8787)抢同一个库的租约,抢到哪一拍就用旧代码发那一拍的卡、 推那一拍的帧 —— 决策卡没 variant、帧里 `data-rows`/`data-by` 原样漏出(旧渲染器不认嵌套)。 修:`./stable.sh update`(稳定版现为 `7555337+未提交改动`,与开发一致);并把审核卡的面孔改成 **引擎按剧本定**(`faceOf`:点名的项优先,挂不到就按当下在办的那一步 → `cards.decide.variant`), 不再只靠模型给对 itemId(2 测)。排查法:先看 `.stable/RELEASE` 的 commit 与 `lsof -iTCP:8790` 的 进程启动时间 —— **两台后端一个库,先问另一台跑的是哪一版。** - **「叫了人我都没填你就直接推进了」—— 两道结构闸**(2026-08-27 傍晚,用户:「不能再有叫了人又继续 自动推进的问题」):实测账 —— S1 的执行卡 17:48:00.2 发出,0.3 秒后投到的是**上一张(P-10)卡回传的 人事件**(回传落库那一刻已 wake、推进器读 card-reply 先跑了那一拍,事件晚 12 秒),`deliver` 照样 tick,再一拍模型读到事实行「这一步已经发过卡,人已经被问过了,照『人交回之后』办」,把没人答的 S1 收掉。①`task.deliver`:人事件带 `occurredAt`,任务在这条回传之后推进过就只记到达痕(stale)不推; ②`runTurn`:`cards.unanswered(taskId)` 非空这一拍不问模型(`human-tool.pendingCards` = 没办结工单 + 没作答且没被顶替的对话卡),谁叫醒都推不动 —— 这一条管住所有多余唤醒(另一台后端 / 手动 wake)。 5 测(task 3 + turn-runner 2)。两台后端都要装上:dev 自动重载,稳定版 `./stable.sh update`。 - **审核卡 = 终局验收卡的结构:判据表,不是参考信息**(2026-08-27 傍晚,用户:「给你说了要最后一个 评审放行与落账确认这个验收卡的样式和结构,没有参考信息这个东西,变成 L1、L2 这种东西」): `decisionCardSchema.criteria`(可选)—— 任务详情读时对**没作答的 review 卡**现算同一摞判据 (`checks.of`,L5 不上卡,过契约 schema 归型),与终局验收卡同一段算法同一份读数;`ReviewForm` 摆 `Crit` 判据表 + 头上「n/m 达标」,卡上不再有参考信息 / AI 建议。答过的卡不带判据。 - **验收卡的条目 = 人工验收清单,人点「达标 / 不达标」,点全才能通过**(2026-08-27 傍晚,用户定,先只做 ACT-WORK-05):从前卡上摆的是系统判的判据(L1/L2…)让人签;用户定「不是系统判断的条目,是人要对这个 验收工单的内容进行审核需要的步骤,每份验收工单固定」。契约:`PlanStep.acceptanceChecklist`(剧本声明)→ `AcceptanceWorkOrder.checklist` / `DecisionCard.checklist`;回传 `checked`(落 `done.checked` / `chosen.checked`);human-tool 回传校验:通过必须 `checked ⊇ checklist`(`checklist-incomplete`),审核卡只拦 「通过」选项。引擎:审核卡随面孔带清单(`faceOf`),终局验收卡在 submit 时从剧本取(声明了清单且不是审核步)。 前端 `Checklist`:序号格 + 右侧开关(**待确认灰 ↔ 已确认绿**,用户定;不叫「不达标」—— 没点过不是判了不合格), 头上「已确认 n/m」,确认通过灰到点全;答过的只读摆当时点的。W05@1.5.3: S4_review 4 条、T_release 5 条(按两份目标件的【验收判据】写成人眼能核的动作)。E04 / I01 未动(用户定先不管)。 `decisionCardSchema.criteria`(上一轮加的)撤掉。测:card-rules 2 + turn-runner + review-face + 包内 1。 - **「标红的填了还是不让推进」:红带点的是「缺输入项」,不是补充内容**(2026-08-27 晚,用户实测):S1 清单 11 行全没有 `input_item`(必填的人读名列),模型这一拍只写了 status/detail/origin;件上红带的固定前缀写死 「补充内容没填」,人于是把 11 行的补充内容全填成「1」,闸照拦(它拦的是输入项)。病根:剧本只在括号里提过 一次「input_item 用人读名」,逐行做法里从没再说 —— 措辞的「从没说过」那一档。修(W05@1.5.5):剧本逐行写死 六列与每行的人读名(客户 / 客户需求 / 原 PN / 候选 N / 应用场景 / BOM 位 / 替代类型 / 规则版本 / 负责人期限 / 原 PN 资料版本)+ 发卡前自核 `_input_gap_missing = 0`;红带前缀改「必填格」不写死列名;包内测钉死。 顺带答用户「这些输入项库里拿不到吗」:输入项只是每行的名字(AI 该写),不是库里的数据;真要人填的只有 应用场景 / BOM 位两格 —— 它们不在任何表里(P-01 是本单新建的、P-09 BOM 没建模)。 - **进度条钉在 1/6 · 重做意见变成「驳回(不写具体意见)」**(2026-08-27 晚,用户实测两条):①`phaseProgress` 从前「一段里的项全收完才算过」,都在库时数据工单两项永远 Available,条钉死在第一段;改成「案子走到了哪一段」—— 最后一个有项动过(Active / Completed / Terminated)的阶段,全收完就进下一段,没收完停那一段;一项没动过才退回 老规矩(3 测)。②模型把审核卡骨架里的 `allowCustom` 抄丢,引擎默认 false,前端写了意见的重做只能退回驳回项, 卡面摆的是选项原标签;现在审核卡一律收自定义意见(`allowCustom ?? reviewFace`),答过的卡摆**验收的话** (确认通过 / 重做:<意见> / 重做(未写意见)),不摆选项标签。 - **「评审放行与落账确认」派了两次:先一张执行单,人答完才 submit 又一张验收单**(2026-08-27 晚,用户送来 5616e13d 那单):S5 在同一拍里被自动收步后模型接着被问,读到人工激活步的事实行「唯一合法的动作是先发那一张卡 (human/entry/decide)或立监听」,就给 T_release 发了一张执行工单;下一拍才 judge + submit。修三处: ①`isReleaseStep`(剧本声明了人工验收清单且不是审核步)—— `human` 挂到放行步当场拒并指向 submit; ②放行步的事实行只指向 submit(不再套执行步那句);③验收卡题目取案例模型里那一项的名字 (「评审放行与落账确认(ACT-GATE-03)」),「收口验收」只是兜底。W05@1.5.6 剧本补一句「不发执行工单」。 2 测 + 包内 1 测。 - **工作成果详情右上角只翻页,不翻份**(2026-08-27 晚,用户:「这个东西不是让你在整个工作成果里面切换, 是让你在单个工单有多个页面的情况下切换的」):08-23 加的「翻份」撤掉;右上角那对箭头只在这一份件里翻页 (一页也摆 1/1),换一份成果回列表点。 - **验收卡「又变成老的」:投影按标题里有没有「验收」二字挑面孔**(2026-08-27 晚,用户实测): `chat-projection` 从前拿 `title.includes('验收')` 决定 card-sent 是判据卡(`criterion` → `AcceptForm`) 还是执行卡(`guidance` → 通用「派出工单」气泡),而同晚验收卡题目改成了案例模型项名 「评审放行与落账确认(ACT-GATE-03)」—— 四个字不在了,人工验收清单整张不见,摆出的是 11 条判据 + 「打开报告」。同文件上面几行早写过「标题措辞是给人看的、随时会改」。改认痕里的结构化键 `mode` (发卡时随 payload 入痕),老痕没有它才退回标题。2 测;读时投影,在途单刷新即好;稳定版已更新。 - **「字已签下,正在落地」停住不动:迟到守卫把放行裁决也丢了**(2026-08-27 晚,用户送来 317c9124): 同晚加的「迟到的人事件不再推」(`lastProgressAt > occurredAt` → 只记痕不投)前提是**那一拍能从 留痕 / 卡库读到答复**(执行单填报、决策卡选项都如此);而放行裁决只走事件这一条路 —— loop 的 `onEvent` 把 verdict 落进在途验收信封。实测账:签字 04.129 落库 → `wake` → 推进器抢先一拍 (在途验收没裁决原地返回,但 lastProgressAt 挪到 04.483)→ 事件 05.774 才到 → 判 stale 丢掉, 再没有任何事件叫醒它。修:`payload.mode === 'acceptance'` 的人事件不进迟到守卫(认结构化键); 1 测。那一单以「删 event_consumption 行 + 投递行翻回 pending」让派发器按新路重投 → released、 合并 24 行、发口 assessment-released。**两台后端都装上再重投** —— 稳定版的派发器同样会抢这条。 - **P-10 的卡对着 P-08 的件:画面跟着这一拍发出去的卡走**(2026-08-27 晚,用户送来 3ef3fc3e: 「当前这一步不是应该给我推 P-10 的数据工单吗?怎么还是推送的芯片主数据创建」):模型没收掉 S0d_p08_master(剧本两处白纸黑字「先 finish 再发下一张」,措辞治不了)就发了 S0d_p10 的数据工单, 两步同时 Active,推帧按「第一步没干完的」取了 P-08 的件 —— 人拿着 P-10 的卡,屏上没有资料表可填, 提交闸拦「缺资料」。08-23 那刀(按 currentRuntime 重算)治不了两人环项相邻的形状(debt 早记了)。 结构治:`applyAction` 的 human / entry / decide 三条路把 `issuedFor`(卡是哪一步的)交回拍内, 推帧时那一步声明了画面就推它,压过别的规则;没发卡的拍照旧。1 测;debt 销账。 在途那单以「task_view.template 改成 p10-document-create + `views.repush`」救活(tsx 起容器跑脚本, `-e` 不支持顶层 await,要写成 .mts 文件)。 **根治**(用户:「根因修了吗?不要只修表象」):病根是**这一步办完没办完是引擎手里现成的事实 (卡答了、数据入库了),却让模型去记得 finish**。①引擎:人工激活的项在 `worldTouched` 之后照常求 doneWhen(此前一律跳过,怕替人签字 —— 门槛保留:卡没发过不收),拍首扫一遍、**拍尾再扫一遍** (人答卡那一拍模型写完东西 doneWhen 才真;刚发卡的项排除;submit 拍不扫免擦信封); ②W05@1.5.8:P-08 / P-10 各给一条只读入库事实的 doneWhen(要建的每颗料 = absent + created, 主数据/参数/资料都落了、必填不缺、逐颗对账),S1 哨兵不再等模型写 `created` 旗(那是「机检只读 基座数」的哨兵形);剧本里「顺序不能反」改口「引擎也会自己收」。现有 E04 / I01 / W05 没有任何 人工激活项声明过 doneWhen → 零回归。3 引擎测 + 包内 220 测;规范 §4.4 / 建模纪律 3、4 改口。 e2e w05 这轮没跑(用户的测试台占着,起单会顶掉他的单)。 - **工作区正文里的占位上下居中**(2026-08-27 晚,用户:「AI 推进中 / 这单已收尾 / 还没有往来记录 …居中显示」): `.jc-empty` 早写了 `margin:auto`,可它住在自绘滚动区的视口 `.wf-body`(块级)里,纵向 auto 边距算 0, 全贴顶边。与 08-x 治五模块空态同一招:`.wf-body:has(> .jc-empty / > .jc-working)` 才切成纵向 flex, 件 / 日志 / 往来记录这些正文照旧从顶往下排。浏览器实证「这单已收尾」「还没有往来记录」两屏居中。 - **两颗一模一样的输入电压范围判成 MISMATCH:客户约束一票否决**(2026-08-27 晚,用户送来 0bddd862): 客户写「输入电压在 45V 以内」→ 模型译成 requirement `>= 45`,原 PN 与候选上限都是 40V;`judgePair` 只看候选 过不过客户线,不看原 PN 自己过不过 —— 需求边界与在用料的差距记在候选头上,硬约束 MISMATCH → 整颗不推荐。 差异评估比的是「换上去会不会比现在差」:工具 `compare-parameters` 升 1.1.0 —— 候选与原 PN 相等 / 盖住、 且客户线原 PN 也过不去 → 仍按比对结果判(MATCH,风险中),备注点名「需求边界,请回头核对需求」; 候选更窄且过不了线仍 MISMATCH(3 形有测)。工具注册一名一行、upsert 换版本,handler 在进程内按名绑, 装完稳定版重建即生效;在途单要人在审核卡上「重做」并写明意见才会重比。 - **差异比对的入参由基座从台账取,模型只报料号与客户约束**(2026-08-27 晚,用户:「这个做差异评估比对的 harness 肯定有问题,要让它认真比对每一条,然后再输出结论」):同一单痕里模型念出「输入上限 32V 低于客户 40V」—— 那是 S3 剧本示例的原话,不是这单的数;工具入参只存哈希,喂了哪几对值事后查不到;写回时还把工具的 `equal` 改成 `less`。两头都靠模型抄、两头都没有基座核。改三层:①工具运行时把 `taskId / activityId` 交给处理器 (`ToolHandler` 入参加两个可选键);②`compare-parameters` 1.2.0:给 `originalInternalPn + candidates[]. candidateInternalPn(+ requirements)`,参数行从 `parts.parameter`、封装 / 生命周期从 `parts.profile`、证据引用从 `parts.document` 由工具现读任务视图(本单草稿也算),出参每项带原值与证据,写盘照抄;老形状(自带 pairs)照接, 试运行走它;container 用 `compareParametersWith(ledger)` 顶掉静态名单那份;③≤800 字的工具入参整份进 `result` 痕(审得了才谈得上认真);W05 S3 第一拍只报料号与约束、示例只留占位形,第三拍 compare_result 也照抄; S4 重比只改 requirements。13 工具测 + 包内 89。**基座能读到的事实,不让模型转述给工具。** - **「下限~上限」一律是范围:解析器补齐写法、出参摆出读法**(2026-08-28 用户:「4.5~40 / -40~+85 这种我怕模型 搞不清楚,harness 里强调一下是范围值」):实测解析器真有洞 —— 单位写进值里(`4.5V~40V` / `-40℃~+85℃`)被读成 单个数,Unicode 减号、`…`、`≥45 / 40 以内` 读成文本。工具 1.3.0:分隔符认 ~ ~ - – — … 至 到 to、单位可夹在值里、 单边界读成半开范围;出参每项 `readAs:{original,candidate}` 写明「范围 4.5~40 / 定值 5 / 下界 ≥ 45 / 文本」—— 比对依据可见,模型照它写影响、不自己重新解释值;契约描述与 S3 / P-08 剧本明写读法(示例用中性数 1~10, 不用真数据里的 4.5~40 —— 模型会把示例当这单的值)。W05 升版装上。3 测(11+7 种写法)。 - **AI 把原 PN 的规格书填到了候选料号头上:人填的表要声明,判据不摆给还欠卡的那一步**(2026-08-28 柴浩实测单 6ddcecf8,连撞五拍熔断):P-10 资料记录的标题 / 版本 / 链接与台账里 `LM2596S-5.0` 那一行**逐字相同** —— 不是幻觉,是「手边有一行看着对的就拿来用」(那一步 reads 摊开了 `parts.document`,视野里唯一一份真资料 就是原 PN 的)。三层合谋:①把 P-08 的回卡认成 P-10 的(P-10 的卡从没发过);②我 08-27 给这一步加的 doneWhen 把「资料必填不缺」摆成目标、后面还跟「成立了就 finish」,**与同一份提示词里「唯一合法的动作是先发那一张卡」 直接打架**;③它顺手把 `exists_status` 改成 created,按剧本发卡名单自己空了 —— 一个合法动作都不剩。 止血两刀:**①`PlanStep.humanWrites`**(契约)—— 声明的台账 `write` 当场拒并指路「去发那张卡,值由人填」, `drop` 不拦(写错了得撤得掉);判法认点名的项、点不出退回当下在办的那一步(压拍时骨架写在上一步名下正好放行)。 **②还欠一张卡的那一步不摆 doneWhen** —— 判据同时是摆在模型眼前的目标,而它此刻只许发卡。 W05@1.6.5 声明 `humanWrites: ['parts.document']` 并从 writes 去掉。4 测(墙 / 放行 / drop / 声明)。 **一个闲着的模型 + 一个它够得着的判据 = 它一定会去凑那个判据。** 用户同时点出更大的一条(记 debt,未做):**存在性核对 + 派数据工单是确定性流程,根本不该交给模型** —— 平台缺「确定性步骤」(纯工具只读、判定表不写台账、doneWhen 只收步),所以只能写进 guide; 引擎三样能力都有(taskView / draftWrite / issueExecution),缺的只是声明面。 - **确定性步骤已出设计,未动代码**(2026-08-28,ADR-014):盘完 W05 九步 —— **三步整个确定**(S0_bind / S0d_p10 / S5)、四步八成确定、只有 S3 是 agent 主场;一单十来拍里七八拍在做确定的活。 agent 真正不可替代的只有四类:自然语言→结构化 · 读人的意见落到具体行 · 写给人看的话 · 非结构化抽取(实跑中一次没发生)。 设计要点:**声明式配方进 manifest,不执行包代码**(ADR-004「不执行代码即知包为何物」;artifact 至今零执行, 不为这个功能开沙箱面);三个动词 `project` / `card` / `say`,条件复用 S-FEEL、聚合复用基座读数,不发明第二套求值; `auto` 是「问模型之前先把确定的事做了」,作用域到交出控制权为止;**一步要么确定要么不是**(判断点先切出去, 不做「一半 auto」);出错交人不重试不退回模型;静态审把地址/列名/S-FEEL 在装的时候审死。 **回溯验算:已记录的八条事故落在会被 auto 掉的三步半上**(编号抄别单 / 判在库判错 / 派给在库的料 / 没写骨架就发卡 / 清单漏列 / 库里有值当缺口 / 抄别的料的资料 / 撞墙五拍熔断)。 立场要改口:**agent 只在真需要判断的地方出现,与「人只在责任点与放行点出现」是同一条原则。** 五条待定见 ADR §11(决策卡给不给配方 / 工具串接 / humanWrites 细到列 / S2 与比对工具的 join 重复 / T_release 第三条裁量该删)。 - **运营中心活动详情沙箱换成「关键台账数据」看板,数据接真台账**(2026-08-27 晚,用户定:只摆最近一次已放行 实例、替换掉全流程分支图):模版搬自 `docs/ss02-act-05/ACT-WORK-05-关键台账数据.html`(P-01 KV / P-08 逐颗 + 参数瓷贴 / P-11 主记录 + 差异明细 / P-10 / P-06 本单 + 同料号历史),徽标文案全由 `data-class-of` 投影。 **取数归活动声明、执行归基座**:契约新增 `viewTemplates[].data`(`case{ledger,key,prefix}` + `rows[{as,ledger,by,not,orderBy}]`, `from` 只能指 `case` 或前面的 `.<列>`),`view-scope.ts` 按声明逐表等值读正式表、摊成扁平作用域 (`` / `.<列>` / `_rows` / tally 计数 / `case:*` / `board:state` 三态)交 `renderView`,`/view` 出口照旧注入报高脚本。 案号 = 前缀 + 开案时刻 14 位(`case-stamp.ts`,与引擎注给模型铸主键的 `case:openedAt` 同一函数 —— 实测 INS-20 `13:51:03Z` ↔ `W05-20260827215103` 一字不差);放行后草稿层已清空,所以只能这么圈。`store.latestReleased`。 W05@1.6.0(库里核过带 `data` 11 条);`views/overview.ts` 删除(docs 里的源文件不动)。测:契约 3 + view-scope 9 + service 3 + store 1 + 包内 4;真库渲染 `v-ready`、INS-21 / `W05-20260827215148`。欠账见 debt(挑单 / 行级来源 / `vtok` 三份 / `data` 装包静态审)。 - **确定性步骤已落地**(2026-08-29,ADR-014):`PlanStep.auto` 声明式配方,五个动词 (`project` / `analyze` / `card` / `submit` / `say`)、四种地址、嵌套两层封顶;引擎在拍首跑, **发了卡就收拍(零 token)**,有 `guide` 的照常问模型。`analyze` 是**一次结构化 AI 调用** —— 系统组装入参、声明出参 schema、系统落表,**不给工具不给记忆不多轮**。 三条纪律进了规范 §4.6:**行由确定的那一侧决定不由 AI 决定** / 判据不许编数不出来的数 / 每一笔之前刷读数。静态审在装包时把地址、列名、模型名、视图、submit 的验收清单逐条核死。 配套四件:`data-options`(下拉选项从台账现读)· 件上保存后 `wake`(「保存即铺格」)· 审核卡放宽到单选项 · 卡答复即收步。**E04 / I01 / W05 一个字没改** —— 它们的剧本里没有 `auto`。 - **ACT-WORK-05 从『什么都丢给 AI』重写成『系统确定性取数 → AI 只在真需要判断处出场一次』** (2026-08-29/30,`part-substitution-assessment@2.1.6`,design spec `docs/superpowers/specs/2026-08-29-act-work-05-rewrite-design.md`,用户原话立场:「不是把 所有东西都丢给 ai 来处理…一定是系统先确定性的从数据库中取出数据后交给 ai 分析」)。 九步砍成**四步**(S1_inputs 核对入参与补数据 → S2_assess **整个活动唯一一次** `analyze` → S3_review 结论审核 → T_release 落账放行),**全程零 `guide`**,行为整体搬进 `PlanStep.auto` 声明式配方(ADR-014 第一个真实用户);零工具、零技能,两枚旧工具与两张 DMN 一并退役 —— 规则只许有一处真源,活在配方的 `when` 链里。新建两张类型字典 (`parts.chip_type`/`parts.type_param`):按芯片类型(不是按料号)标一次核心参数字段与 硬软约束,「两颗料必须用同一套参数名」从此是**结构保证**,原先靠测三次都没拦住的 自指引用墙退休。三张件(数据工单 · 结论审核 · 落账确认),数据工单按缺口条件发卡, 零卡直通是常态路径之一。 **e2e 五案例的真实战果**(2026-08-30,连续多轮真跑,详见 `.superpowers/sdd/2026-08-29-act-work-05-rewrite/task-11-report.md`):候选缺库·新建类型 / 都在库·零卡直分析 / 原PN缺库三例 `released`、**被拒 0**、**模型调用恰 1 次**、发口 `assessment-released` 全对——**「候选缺库·新建类型」这条记录后来被全分支终审推翻** (见下方「全分支终审」条):那次 `released` 靠脚本走 API **显式传 `type_id:'90'`**, 没有走真人在浏览器里点「新建类型」那条路;`e2e-a2.mjs` 自己的注释原话是 「这条路径连真人在浏览器里都走不通」。**该走的那条路当时藏着 Critical 1**(见下方条目), 这里的「released」只证明了 API 直传能通,不证明「新建类型端到端通了」。 类型不一致·硬拦那例撞上**已记入 `docs/debt.md`** 的平台死锁 (`prune` 与「数据工单确认即入库」的架构性冲突:人先交一次、字段已落地,再改类型选择, `prune` 想撤已落地的陈旧行被显式挡住,两条机制各自都对、合起来死锁);两颗都缺库那例 卡在「决策卡答完之后不再推进」,`advancing_until` 反复核过是空、租约与陈旧进程两种假说 均已排除,**真因未定位**,如实记录未解决,不强装成功。**`judgement_class` 逐行核对通过** (7/7:使能阈值 / 工作温度 / 开关频率 / 输入电压范围 / 输出电压 / 输出电流 / 静态电流, AI 判的 `difference_status` 与规则链算出的 `judgement_class` 逐行对上,`risk_level` 联动也对)—— 这条验证之所以要点名贴出来,是因为它曾经**逐行全错**。 **地基缺陷**:活动清单存进 `sys.activity_package.manifest` 这个 jsonb 列后,PostgreSQL 按「先短后长、同长字典序」重排了所有嵌套对象的键,而 `project`/`analyze` 的 `fields` 原来靠 `Object.entries` **声明顺序**求值(后一字段靠 `ctx.computed` 看前一字段已算出的 值)——「声明序 = 依赖序」这条从没写下来的假设一进数据库就被打破,且**不报错**、 隔离测试也复现不出来(它直接读 `dist/manifest.json`,不经数据库往返),只有真跑 e2e 才现形。W05 实证:合成列 `judgement_class` 被排到它依赖的 `difference_status` 前面, 读到 `undefined`,七行**全部**误判(`difference_status` 本身走 `lookup` 不依赖字段序, 所以是对的 ——「一个对一个全错」的怪现象由此而来)。**修法是把字段求值从『声明序』 改成『依赖拓扑排序』**(Kahn 算法,新增 `packages/utils` 的 `topoOrder`,契约纯新增); 真正的环在装包静态审当场拒装,不兜底、不静默放行。四条新纪律入规范 §4.6(六条→十条): `fields` 顺序不可依赖拓扑排序之外的任何假设 / 跨笔顺序仍要人自己排(一笔读的是另一笔 写出来的数就得排在后面)/ 方向相反的依赖拆两笔写、中间夹子表 / `gateLedgers` 同时管 「闸要求非空」与「确认时并进正式表」两件事,漏想一半就会悬空引用或永久卡死。 `pnpm gates` 退出码 0(2447 passed | 34 skipped)。 - **W05 数据工单换版面已退回**(2026-08-31 用户:「改了 ui 之后这个版本我感觉有点问题」): `report.ts` / `target-style.ts` / `activity.test.ts` 三个文件**逐字节恢复**到换版面之前 (45cec82 的样子),包版本 **2.3.0**(内容是旧版面 —— `store.manifest` 不传版本时取 **最近安装**的那一条,不是版本号最大的,所以退源码必须配一个新号装进去才真生效)。 **换版面那一版原样活在分支 `feat/w05-view-swap`**(HEAD `1373eb4`),随时切得回去; 下面这条记的是它的账,留着当索引 —— 里面三条渲染机制的实锚(宿主闭合标签 / 行内 class-of 只认行作用域 / data-by 回落)与平台侧探针测试**不随退回作废**,它们钉的是 平台行为,测试与目标件 html 都还在主支上。 - **(已退回,见上条)W05 数据工单换版面 + 两条渲染机制的实锚**(2026-08-30,`part-substitution-assessment@2.2.2`, 用户给了新目标件 `docs/ss02-act-05-new/ACT-WORK-05-数据工单-PN主数据创建.html`): `input-supplement` 整张照它重排 —— **两条并列轨道**(每颗料一条:档案卡 + 主数据 + 类型选择) + `
` 新增类型面板(chip_type / type_param 两张表原样搬入,独立「核心参数字段」区退役) + 核心参数值**瓷贴单块平铺**;绑定面一列不差(四张台账 / 四道闸 / 两处加行 / 终审 C1 的 disabled type_id / 主键钥匙)。目标件脚本驱动的状态全部无脚本翻译:保存即铺格顶掉「选类型 即时加载」、details 顶掉 `.newtype.show`、步骤圆点按基座数点亮、gateprog 进度条如实退掉 (分母不是基座现有的数)。**三条机制账**,全有测钉死: ①**`data-rows` 宿主的闭合标签就是行模版的截刀** —— ROWS 正则按宿主自己的闭合标签非贪婪 截取,`
` 被行模版里第一个 `
` 截半,第二行嵌进第一行没闭合的标签里 档案卡当场串行(A2 立的「行容器用行内不会再出现的标签」说的正是**宿主**,它自己就是 `
` 包 `
`);防再犯钉用**配平判法**(「不含闭合标签」是空话 —— 非贪婪截取 本来就停在闭合标签之前,那条断言永远不会红); ②**行内 `data-class-of` 只认行作用域**(renderRows 末段 renderTemplate 拿的是行对象), 作用域级读数在行内投不出 —— 圆点的投影挂在行外的 `.pj` 包裹层,后代选择器点亮; ③**`data-by` 行缺键落回外层同名字段**(终审 I3)真咬人:XL 没选类型,`sub_eval.case` 摊平的 `chip_type_id` 顶进来,查名 pill 摆出它没有的类型 —— 守卫认 `selectCurrent` 按 **这一行自己的值**写下的 `option[selected]`,行里没真选上名字不摆(判断全在样式表)。 同批逮到并修死:profile 的编辑闸在第一版 body 里**整个漏掉**(宿主在而闸不在,XL 必填 永远补不上 —— 「四道闸」旧断言只查 data-edit 宿主没查 [data-edit-for] 闸,补强)。 另一半探针钉进平台测试:嵌套 data-rows 在唯一 data-edit 宿主里**必然把一颗料的格子并成 一条记录**(rowOf 认宿主直接子元素;真实 renderView+collect 实测, `view-container-collect-div-rows.test.ts`)—— 步骤③不按轨道分两栏是机制不是偏好。 **验收**:活动自测 62 → 74(新钉逐条变异验证);`pnpm gates` 退出码 0(2497 测); 2.2.0/2.2.1/2.2.2 三连装库 SQL 逐次核过;浏览器全流程真人路 —— 起单 → 两轨道核对 → 保存即铺格(XL 七格当场铺出)→ 填参数 → 确认写入办结 → S2 分析推进;新建类型走种子行 续号 `03`、DC-DC 原行未被覆盖、下拉即时长出;类型不一致护栏真亮 v-2 再熄灭。 终审评审 0 Critical / 0 Important / 1 Minor(注释漂移,已修)。跑完 reset-runs, 主数据与活动缓存零残留。 - **W05 三张工单件视图层按 C 端重设计**(2026-08-31 用户定:「不要后台管理端的样子, 要给客户用的 C 端界面;可加主题 SVG 与动画;只保留功能,视图层可以推翻重新设计」, `part-substitution-assessment@2.6.0`):「精密检测报告」语言 —— 深色电路板夜景 hero 三张各一幕(建档台:两颗料的芯片铭牌由 `mine:sub_eval.part` 铺行、不在库虚线描边 / 对决量尺:原 PN→候选 PN + 推荐等级徽章 / 落账席:慢转印章环 + 一句话结论),正文瓷白 报告版面(丝印小标 / 比对光谱分布带 / 落账三卡大数);动画全 transform/opacity、 reduced-motion 全静;验收两件仍是验收绿 #0aa294。**功能绑定逐项保留**:可编辑表 DOM 结构逐字节不动(收值链路按结构认元素),机制规则(计数器/种子行显隐/gate-bar :has/ overflow-x)逐字保留仍被测试钉着。设计系统收进 `views/style.ts`,`target-style.ts` 退役(目标件时代的锚),report.ts 的 vtok/badgeCss 收归 badge.ts(销一笔 debt)。 离线预览自审(真 renderView + 造景数据,不碰测试台)逮到并修掉三洞:kv 占位破折号 连嵌套徽标一起吃(改只认直接子级)、光谱条里渗计数字、加行钮没 base display:none。 104 包内测 + 2516 全仓绿,两条新锚变异验证过,2.6.0 装库 SQL 核过。 (2.5.0 是同日另一会话的启动表单芯片类型联动 —— 两会话同 checkout,版本号先问库。) - **W05 数据工单三病一改:档案卡上桌,prune 跳过已落地**(2026-08-31 用户实测三连 + 「设计只是头上加了动画」,`part-substitution-assessment@2.7.0`): ①「类型自己给上了」= data-by 行缺键落回外层(debt I3 原样咬人)—— 查名 pill 摆出案卷锚 (原 PN)的类型;治:守卫认 `selectCurrent` 按**行作用域**写的 `option[selected]`, 真选上才摆名、没选摆「待选择」胶囊。**守卫必须单层 `:has`** —— `:has()` 里嵌 `:has()` 是非法选择器,整条被浏览器静默丢弃(第一版就栽在这,预览截图逮回),挂共同祖先上写。 ②「品牌…点保存根本不会保存」= 块① 行源是 `sub_eval.part` 而那张案卷表没有主数据列, `renderTemplate` 只认行作用域 —— 保存真落草稿、显示与孪生件永远空白(四步重写后的潜伏缺陷, 真人一填才现形;e2e 走 API、旧浏览器走查在 swap 版上,两条线都照不到)。治:行源改 `mine:parts.profile` 本身(S1 ④ prune:true 恒有两行),行里天生有全部列。 ③「改回同一类型,下面还是两个类型」= ②③ 自投影为绕「已落地行撤不掉」的死锁特意不带 prune,没落地的陈旧行也跟着积。治在平台:`draftDrop` 加配方专用旗 `skipLanded` (跳过并出声「N 行已随数据工单入库、这一笔不清它」,不炸),②③ 恢复 prune:true —— H35 案例 2 不再死锁,debt「prune 与确认即入库的架构性冲突」销账。quiet 拍仍不撤行(F3), 清理落在每次确认工单那一拍。 ④设计:块① 从 11 列横滑表推翻成**电路板工作台** —— 深色板底上两张可就地编辑的芯片 档案卡(SOIC 封装 SVG + 角色/在库徽 + 类型选择行 + 双栏主数据格),编辑态整卡变表单; 三级占位(必填红/建议橘)上卡与参数值表(徽标包装的必填格用单层 `:has` 认裸 class 补胶囊); 参数值表所属料号列加角色徽。测:107 包内(守卫/行源/嵌套零 data-col 三锚变异验证)+ auto-runner skipLanded(变异验证)+ 2520 全仓;2.7.0 装库 SQL 核过。 另:1838474「在库」是真的 —— 用户此前某单 land_master 落过它(正式表 chip_type_id 为空)。 - **W05 第二轮:比对基准合一卡 + `prune:'live'` + 蓝图板底**(2026-08-31 用户:「类型和字段 合并成一个卡…两个芯片同类型就只显示一种,现在只变多不变少」「卡片容器黑色和页面不搭」, `part-substitution-assessment@2.8.1`):①类型+字段并成**比对基准卡**(只读、跟手)—— 不列 mine: 镜像(积旧选择,撤行只在确认拍跑),按案卷锚嵌套查字典,保存即换脸、同类型 恰显一种;新建类型收进 details 抽屉(零脚本),编辑表原样在抽屉里。②契约新增 `prune:'live'`(quiet 拍也撤,**只给人加不了行的表**用 —— F3 防「人刚加的行被撤」, 这种表没有该风险;有加行钮的表永远不许用):W05 参数骨架改 'live',改类型参数行跟手换; static-audit 盖住 'live',规范 §4.6 纪律 5 补反面特例。③档案卡板底深色→**浅色蓝图** (强调色晕染+淡格线),整页只剩 hero 一处深色。锚测各变异验证;2.8.1 装库核过; :8787 watcher 又断,应急手起 node dist/main.js(14:41)。 - **W05 第三轮:数据工单去表格化 —— 翻面芯片卡 + 平台多宿主收值**(2026-08-31 用户: 「界面东西太多做成几个区域;类型与字段做成和芯片卡差不多的卡片;芯片卡与核心参数值 合并,点击翻转、背面写参数、悬浮看得出能翻;这个界面都不再需要表格展示数据」, `part-substitution-assessment@2.9.0`):主画面零表格 —— 基准卡瓷贴化(类型丸+字段 瓷贴),芯片卡纯 CSS 翻面(checkbox+:has 零脚本,悬浮提示丸+侧倾;主数据编辑锁正面、 参数编辑自动翻背面),背面参数瓷贴就地可改;说明四条收折叠;表格只剩新建类型抽屉 (加行机制认 tr)。**平台扩面:ui-kit ViewContainer 多宿主收值** —— 同一地址 querySelectorAll 全数进来,**格子只归最近的 data-edit 祖先**(嵌套异地址排除;不带 data-edit 的嵌套 data-rows 行为原样,两条 collect 旧钉测不动);addRow 仍单宿主。 三脚各留一条:CSS 注释写「data-col=」原文会踩翻别件的字面断言(选择器与注释都不许); `.flip-cue i` 特异度压过 `.cue-back{display:none}`;host 计数断言别拿渲染后的数去数 模版源码。ui-kit multihost 3 测(变异验证)+ 包内 110 + 2528 全仓;2.9.0 装库核过; 浏览器实测点卡真翻、参数编辑双卡自动翻背成表单。 - **W05 第四轮九连改:笔↔软盘卡角编辑 + 只选不建**(2026-08-31 用户一次点齐九件, `part-substitution-assessment@2.10.0`):①编辑闸两行退役 → 卡右上角笔(开当前面)↔ 软盘(存)+叉(弃),按钮即 data-edit-open/save/cancel 触发器,按面显隐全在样式表; ②ui-kit `mirrorTwins` 修「保存一瞬间下拉变数字」—— 镜选项文案不镜 value,顺手把 selected 拨到人选项(守卫 CSS 认它);③渲染器 twinInputs 认 `data-ph` 落 placeholder; ④参数说明空着什么都不摆;⑤芯片档案区提到比对基准前;⑥**新建芯片类型整条路移除** (只选已有):抽屉/种子行/Critical-1 修法/thead 回归网退役,S1 配方八笔→六笔(②③ 自投影删),gateLedgers 收窄 profile+parameter,e2e 案例 0 改选既有 type_1,七条退役 钉测 it.skip 留墓志铭;⑦题头回原目标件浅蓝渐变(hd-light,夜景只留验收两件); ⑧对话区执行卡不摆「参考信息」(basis 随卡数据照旧);⑨比对基准降噪:字段丸 + 说明悬浮气泡。2525 全仓四门绿,2.10.0 装库六探针核过,:8787 重启载入新渲染器。 - **W05 第五轮:按卡独立编辑 + 顶条合并点名**(2026-08-31 用户四连, `part-substitution-assessment@2.11.0`):①「不要做联动」—— ui-kit 新增 `scopedTargets`: 开合作用域跟着触发钮走(钮在本地址宿主的行里→只这一行;钮在别的宿主行里→行内的 本地址宿主;外部闸→全宿主老行为),收值仍按地址全量、「只写真改了的行」服务端把关; 编辑态 CSS 全改按卡(.dossier.on),同地址同时只开一张卡(快照键按地址,双开互踩)。 ②逐块「还差 N 行必填」红带撤下,_missing/_missing_keys 并进顶条「还差什么」两行子行 (v-0 自收)。③比对基准/芯片档案区序换回(基准在前)。④比对基准换层叠双封装 SVG (t-ghost 淡剪影 —— 一类而非一颗)。ui-kit 35 测 + 包内 105 + 2528 全仓;2.11.0 装库 五探针核过;浏览器实证单卡独立翻背编辑。 - **W05 第六轮:确认闸条件档 + 量高可缩 + 互换动画**(2026-08-31 用户三连, `part-substitution-assessment@2.12.0`):①「类型不一致还能确认」—— 平台加**确认闸 条件档**:配方 card 声明 `gateWhen`(S-FEEL 只读基座读数)+`gateWhenSay`,受理回传前 `submitGate` 按声明表现读 rows/missing/tally/distinct 现算,为假 400 用发卡人那句话; 静态审同 when 一套;评估不出的条件不成墙。W05 钉 `parts_profile_distinct_chip_type_id <= 1`(钉 profile 本表零滞后 —— 钉 sub_eval.part 要等配方 tick 会误拦刚存完就确认的人), profile.chip_type_id 加 distinct。②「底部没东西还能滑一截」—— ViewContainer 量高 documentElement.scrollHeight 以 iframe 高为下限,**只涨不缩**;改 body 优先(margin 0 的 body 才是内容自己的高)。③卡间动画换「可替换」语义:对向双信号点互穿(卡后走、 缝里现身)+ 中央 ⇄ 徽呼吸。2531 全仓;2.12.0 装库核过;:8787 重建重启。 - **W05 互换动画第二稿:与卡同级的实体动画道**(2026-08-31 用户:「不要做到背景板上会被 卡片覆盖,和卡片做到一级,压缩一点卡片」,`part-substitution-assessment@2.12.1`): .dossiers 三列网格(1fr·76px·1fr),中间列是实体动画道 —— ⇄ 徽呼吸 + 双点绕徽轨道 对转(sw-orbit),总线虚线在道里连两卡;窄屏单列收道。浏览器两帧相位实证。 ## 文档权威地图 | 层 | 文件 | 说明 | |---|---|---| | **活文档**(冲突时以代码现状为准) | `docs/编码规范.md` | 工程结构权威:模块层级 L1-L8、依赖门禁、AI 协作协议 §12 | | | `docs/产品设计.md` | 三面一体的产品形态与决策记录 | | | `docs/活动开发规范.md` | **开发活动照这份**(2026-08-02 第三版,按四轴重组:解耦机制/Harness 契约/Loop/活动怎么写):基座读数与机检纪律、门与闸、五类卡、剧本 steps、建模十纪律、三常备案例与验收口径(released+被拒0)、**排障速查表**;§8 = 待实现 | | | `docs/HTML报告生成规范.md` | **报告模版照这份**(2026-08-02 从开发规范拆出):一份 HTML 三个身份(件/表单/归档件)、**报告与卡的关系与同源纪律**、绑定语言全表、编辑态(闸/孪生件/增删行/红带)、PRD 平移法、陷阱表 | | | `docs/前端对接说明-统一鉴权中心.md` | **前端接统一鉴权中心照这份**(ADR-012):要改哪些文件、`/api/me` 与端、401/403/410、SSE 与下载的票据 | | | `docs/前端对接说明-邮件收发.md` | **前端接邮箱配置 / 来信 / 发信记录照这份**(ADR-013):账号表单两形、四个动作、投递状态、附件与原件的票据下载、SSE 失效、腾讯侧前置 | | | `docs/API文档-邮件收发.md` | 邮件收发 15 条接口的人话版 + schema 附录 + curl;活动怎么收(事件链)怎么发(`mail.send` 2.0.0) | | | `docs/API文档-鉴权与人员.md` | 鉴权 / 人员 / 角色→端接口的人话版 + 全部路由归属总表;契约不一致时以 `packages/contracts` 为准 | | | `docs/ACT-WORK-05-端到端测试记录.md` | **历史记录,已停止更新**(2026-08-30 标注):旧九步设计从零到 released 的走查账,六轮逐轮结论 + A–Z 二十六条发现总表(现象 / 病根 / 治法 / 层);四步重写(2026-08-29)之后的发现不再往里追加,散落在源码注释与 `docs/debt.md` | | | `docs/数据域字段说明-W05.md` | ACT-WORK-05 重写后九张台账 / 66 列 / 人填列 20 —— 建活动时照它对字段 | | | `docs/adr/ADR-014-deterministic-steps.md` | **确定性步骤(已实现,2026-08-29)**:W05 九步的确定/判断盘点、`PlanStep.auto` 声明式配方(五动词:`project`/`analyze`/`card`/`submit`/`say`)、引擎拍内次序、回溯验算、迁移次序、§11 待定前两条已定(决策卡给了 / 工具串接换成 `analyze`) | | | `docs/debt.md` | 欠账台账(只增,销账划线) | | | `docs/adr/` · 各模块 `CONTRACT.md` | 架构决策与模块级不变量 | | 业务样例(活) | `docs/MVP示例工作流.html` | 七节点 SOP + 判定表 + 台账域 —— 开发活动的业务素材 | | 前端语义权威 | `~/coding/JCAI_PRD/workbench` `~/coding/JCAI_PRD/governance` | 原型 1:1 平移(只平移不 import);工作台视图逻辑以 `workbench/.../\_data/model.ts` 统一建模为准 | | 归档 | `docs/archive/` | 已完成使命的文档(**操作系统/活动模型两卷语义源**、旧 README 规格包、PROGRESS、旧计划),只读;代码注释里的 OS x.x / AM x.x 编号指向归档卷章节 | ## 铁规矩(违者返工) 1. **五道门禁以退出码验**,不许以 echo 验:`pnpm -s typecheck && pnpm -s lint && pnpm -s depcruise && pnpm -s api:check && pnpm -s test`(或 `pnpm gates`)。 2. **契约变更四步**(§12.4):depcruise 反查下游 → 同步 CONTRACT.md → `pnpm api:check --update && git add api-report` → 破坏性走三步弃用。 3. **§12.5 禁止清单**:no `any` / `as unknown as` / `@ts-ignore`;domain 零 IO; 不删测试;不动门禁配置;不绕写三分/两缝。 4. **mock 只许出现在外界**(邮件通道、外部系统的录制回放替身);系统内部机制不得 mock。 5. **密钥只从环境读**:`JCAI_DEEPSEEK_API_KEY`(模型)、`JCAI_SECRET_KEY`(凭证密封 + 票据派生)、 `KEYCLOAK_URL` / `KEYCLOAK_REALM` / `KEYCLOAK_CLIENT_ID`(启动必填)、`KEYCLOAK_PROVISIONING_CLIENT_*`(名册同步,可选); 不入源码、不入包、不入留痕;E2E 永不回退开发库。 6. **试跑一律用 AI 服务账号**(Keycloak 里 `bpos-e2e` 的服务账号,client_credentials 拿 token;`JCAI_TEST_ACCOUNTS` 列上它的用户名), 绝不派到用户工作台;测完 `pnpm --filter @app/api reset-runs` 清运行数据(清跑出来的,留配置好的)。 7. **安装恒新增**:活动/工具改了内容必须升版本号,同版重装是 no-op(静默丢失,踩过)。 8. **界面不撒谎**:状态如实(未绑就写未绑)、错误带厂商原话、不可用不摆假数字。 ## 常用命令 ```bash pnpm gates # 五道门禁(gen:tiers → typecheck → lint → depcruise → api:check → test) pnpm db:up # docker compose 起 PG16 pnpm db:migrate # 应用迁移(新迁移写 db/migrations/ 并登记 meta/_journal.json) pnpm db:seed # 播种(五员工 + AI 账号;登录者 = 冯兵) pnpm dev:api # :8787 pnpm dev:web # :5173(/api 反代) pnpm --filter @app/api reset-runs # 清运行数据,留配置 pnpm activities:install # 只装活动包(不碰治理台配置)—— 开发活动时用这个,别用 db:seed ``` ## 结构速查 ``` apps/api/src/modules//{index,contract,port,CONTRACT.md,internal/{domain,usecase,adapter}} apps/api/src/app/ # 唯一组装层:container / wiring/engines / routes / workers / seed apps/web/src/features/ # desk-*(工作台)· gov-*(设计+运营)· auth packages/{contracts,activity-sdk,sfeel,ui-kit,testing} activities//src/{index,manifest,case-model,skills,views/} # 活动包(只准 import @sdk/@contracts) ```