` 折叠条(零脚本);页高 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`
(全仓按钮类没有一条定义过伪元素,审过)。**`