This repository has been archived on 2026-09-13. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
BPOS-TMP-REPO/docs/ACT-WORK-05-端到端测试记录.md
T
xcsandClaude Fable 5 88f2149d12 差异比对三刀:客户约束不再一票否决 · 入参由基座从台账取 · 「下限~上限」一律读成范围
①**两颗一模一样的输入电压范围判成 MISMATCH**(用户送来 0bddd862):客户写「45V 以内」→ requirement `>= 45`,
而原 PN 与候选上限都是 40V;`judgePair` 只看候选过不过客户线、不看原 PN 自己过不过 ——
需求边界与在用料的差距记在了候选头上,硬约束 MISMATCH → 整颗不推荐。差异评估比的是「换上去会不会比现在差」:
候选与原 PN 相等 / 盖住、且客户线原 PN 也过不去 → 仍按比对结果判(MATCH,风险中),备注点名
「需求边界,请回头核对需求」;候选更窄且过不了线仍 MISMATCH(3 形有测)。
②**入参由基座从台账取,模型只报料号与客户约束**(用户:「这个做差异评估比对的 harness 肯定有问题」):
同一单痕里模型念出「输入上限 32V 低于客户 40V」—— 那是 S3 剧本示例的原话、不是这单的数;
工具入参只存哈希,喂了哪几对值事后查不到;写回时还把工具的 `equal` 改成 `less`。两头都靠模型抄、两头都没有基座核。
改三层:工具运行时把 `taskId / activityId` 交给处理器(`ToolHandler` 入参加两个可选键);
`compare-parameters` 给 `originalInternalPn + candidates[].candidateInternalPn(+ requirements)`,
参数行从 `parts.parameter`、封装 / 生命周期从 `parts.profile`、证据引用从 `parts.document` 由工具现读任务视图
(本单草稿也算),出参每项带原值与证据,写盘照抄;老形状(自带 pairs)照接,试运行走它;
container 用 `compareParametersWith(ledger)` 顶掉静态名单那份;≤800 字的工具入参整份进 `result` 痕(审得了才谈得上认真)。
**基座能读到的事实,不让模型转述给工具。**
③**「下限~上限」一律是范围**(用户:「4.5~40 / -40~+85 这种我怕模型搞不清楚」):实测解析器真有洞 ——
单位写进值里(`4.5V~40V` / `-40℃~+85℃`)被读成单个数,Unicode 减号、`…`、`≥45 / 40 以内` 读成文本。
分隔符认 ~ ~ - – — … 至 到 to、单位可夹在值里、单边界读成半开范围;出参每项 `readAs:{original,candidate}`
写明「范围 4.5~40 / 定值 5 / 下界 ≥ 45 / 文本」—— 比对依据可见,模型照它写影响、不自己重新解释值;
契约描述与 S3 / P-08 剧本明写读法(示例用中性数 1~10,不用真数据里的 4.5~40 —— 模型会把示例当这单的值)。
工具 1.0.0 → 1.3.0(注册一名一行、upsert 换版本,handler 在进程内按名绑,装完稳定版重建即生效);
W05 包 1.6.2 → 1.6.4:S3 第一拍只报料号与约束、示例只留占位形,第三拍 compare_result 照抄,S4 重比只改 requirements。
13 工具测 + 包内 89。在途单要人在审核卡上「重做」并写明意见才会重比。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_0167qWjeyBwvfdGovd7FWbCu
2026-08-28 01:13:07 +08:00

293 lines
29 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# ACT-WORK-05 差异评估 —— 端到端测试记录
> 这份文档记的是**每一轮实跑逼出了什么、改了什么、怎么验证的**。
> 活动包:`activities/part-substitution-assessment`;业务出处 `docs/SS02-ACT-WORK-05-html/`。
> 台账字段口径见 `docs/数据域字段说明-W05.md`。
> 走查分两条线:**浏览器**(测试台起单 → 工作台真人点,六轮)与**脚本 e2e**
> (`node tools/e2e-a2.mjs w05`,五案例代答,可一键复跑)。两条线逮到的缺陷不重合 ——
> 浏览器逮呈现与交互(件、闸、徽标、翻页、画面切换),脚本逮机制(空手交卷、循环、崩、归属)。
## 一、这个活动是什么
原 PN 与候选替代料之间**逐项差异评估**:比参数、判四态(MATCH / MISMATCH / UNKNOWN / CONDITIONAL)、
定推荐等级(preferred / alternate / conditional / not_recommended)、留证据与验证任务,
最后把结论落进 P-11(替代关系 + 差异明细)并回写 P-01 需求,发射 `assessment-released` 交 ACT-GATE-03 评审。
**九个计划项**(五处不给 doneWhen —— 触达人的一律交人收):
| 项 | 谁办 | 卡 / 件 | doneWhen |
|---|---|---|---|
| `S0_bind` | AI | —— | 有 |
| `S0d_p08_master` | 人 · 数据工单 | `p08-master-create`(表1 芯片主数据 + 表2 标准化参数集) | 无 |
| `S0d_p10_document` | 人 · 数据工单 | `p10-document-create`(原厂技术资料) | 无 |
| `S1_input_confirm` | 人 · 执行工单 | `eval-input-list`(评估输入清单) | 无 |
| `S2_normalize` | AI | —— | 有 |
| `S3_assess` | AI + 两枚工具 | —— | 有 |
| `S4_review` | 人 · 决策卡(可循环) | `difference-review` | 无 |
| `S5_prepare_landing` | AI | —— | 有 |
| `T_release` | 人 · 终局验收 | `landing-confirm` | 无 |
## 二、逐轮走查
### R1 · 样例「都在库·常路」
**第 1 次 —— 熔断**,逮到两条真缺陷:
- 轨迹里 `S0_bind` 写完三张表后连续 5 拍只做一件事「弃用计划项 `S0d_p08_master`」,每拍被拒
「生命周期迁移非法:Available → Disabled」→ 熔断交人;工作区还摆着一张「待建 0 条记录」的空数据工单件。
- **根因一(平台事实,本轮不改)**:`lifecycle.ts` 里 `Disabled` 只能从 `Enabled` 来,而 `Enabled` 只由
`plan` 动作写;普通计划项一直停在 `Available`。全仓只有本活动用过 `disable` —— **这条路从没人走通过**。
- **根因二(活动缺陷,已修)**:哨兵 `s_bound` 只看「需求写了 + 核对表写了」,而 `S0_bind` 在**每条路**上都写这两张表,
于是都在库时数据工单那两项照样进「当下可为」,剧本就让模型去 disable。
- 修:哨兵加 `sub_eval_pn_check_exists_status_absent > 0`;全包清 `disable`;两条回归测试。**v1.0.1**。
**第 2 次 —— 通了**:两拍写完 `demand.request` / `pn_check` / `verdict`,直接派出执行工单;
提交闸如实拦住空手交卷并点名三条缺项(与件上红带同名同数);填三格保存 → 闸自收 → 提交。
**收工:`released` · 12 拍 · 人环 3 · 行动被拒 0**。落账逐条 SQL 核过:
- P-11 主记录 1 条:`pin_to_pin | alternate | fae_confirmed | 客批=(空) | R-2026.07` —— **客户批准状态确实留空**(只读边界守住),规则版本随结论落账;
- P-11 差异明细 9 条(8 MATCH / 1 CONDITIONAL);P-01 回写五项齐;出口 `assessment-released` 已发射;
- 验收卡 11 条判据全部达标(L1×2 / L2×6 / L4×3),一次通过。
### R2 · 样例「候选缺库·派数据工单」
四次开跑,逼出四条缺陷(E / F / G / H),逐条治了再跑;第 4 次(v1.2.3)全绿。
| 次 | 版本 | 结果 | 逼出什么 |
|---|---|---|---|
| 1 | 1.2.0 | 中途停 | E(决策卡被跳过)已在本次前修好并当场验证;F 现形 |
| 2 | 1.2.1 | 熔断 | F 修复通过;**G 现形**(`recommend` 工具被跳过 → S3 收步恒假) |
| 3 | 1.2.2 | 中途停 | G 修复通过;**H 现形**(压拍发卡,清单一行没有) |
| 4 | 1.2.3 | **`released` · 被拒 0 · 人环 5** | 四条修复全部实测通过 |
第 4 次逐段实证:
- 决策卡按规格出现(候选总数 2 ≥ 2)→ 答「创建主数据」;
- P-08 数据工单**一件两表**(主数据 1 行 + 参数 6 行),两张表各有自己的编辑闸与缺项红带;
填好保存 → 提交 → **画面自己切到 P-10**(发现 F 的修复稳定);
- **执行工单出来时清单已有 12 行**(上一轮是 0)—— 发现 H 的修复见效;提交闸如实拦住剩下那条
「未披露」缺口,补上才放行 —— 闸与件同源;
- **S3 两枚工具都真调了**(轨迹里 `compare-parameters 返回` / `recommend 返回` 各一条),自动收步,没有熔断;
- **审核驳回循环**(本轮顺带覆盖):在「写下你的口径」里写两条具体意见 → 模型改台账 → **换问法重发**新卡。
逐条核过落点:XL2596S-5.0 降 `conditional`、两条 UNKNOWN 明细写明处置(挂 `VAL-…` 验证任务、
「闭环前不升级推荐等级」)、LM2596S-ADJ 的推荐理由点名「R1/R2 分压电阻」—— **意见落在被点名的那两处**;
- 终局验收 11 条判据全部达标 → 确认通过 → `released`。
落账 SQL 复核:P-11 两条关系(`pin_to_pin | conditional | fae_confirmed` / `pin_to_pin | alternate | fae_confirmed`,
客批均空、规则版本 `R-2026.07`)· 差异明细 18 条(15 MATCH / 2 UNKNOWN / 1 CONDITIONAL)·
验证任务 1 条(`not_started`)· P-01 回写五项齐 · **XL2596S-5.0 真进了主数据**(`XLSEMI | active`,6 行参数 + 1 份资料)。
### R3 · 样例「三候选·含硬约束不推荐」—— `released` · 被拒 0
一次跑通,验的是**硬约束这条路**:
- 决策卡按规格出现(3 颗候选,只有 CN-DCDC-32V 缺库)→ 建主数据 → P-08 填
**输入电压范围 4.5~32(hard)**、工作温度 -20~+85(hard);
- 清单 13 行、三行 default 的 detail 写对了默认值本身;缺口里把客户约束写成可解析式「输入上限硬指标 >= 40(V)」;
- S2 铺 3 条关系 + 27 条明细;S3 两枚工具都调过;
- **CN-DCDC-32V = `not_recommended` / high**(两条硬约束 MISMATCH:输入 4.5~32 vs 4.5~40、温域 -20 vs -40),
XL2596S-5.0 `conditional`、LM2596S-ADJ `alternate`;
- 验收件上三颗候选各一份「拟写 P-11」字段表,徽标逐个核过(不推荐/高 · 条件推荐/中 · 备选/中 · Pin-to-Pin · FAE确认)。
**一次自纠**:我先按 `innerText` 判定「四个枚举列是空的」,险些记成缺陷 ——
徽标文字是 CSS `::after` 生成的,`innerText` 读不到。**验证呈现要看 computed style,不看 innerText**。
### R4 · 样例「原PN缺库·硬阻塞」
三次开跑,逼出两条**同族**的真缺陷:
**第 1 次(v1.2.3)—— 发现 I:「在库」是模型自报的一句话**
原 PN `LM2596S-3.3` 主数据里**一行都没有**(SQL 复核 count = 0),模型把原 PN 与候选**两颗都写成 `found`**,
交代里还写「原 PN 与候选都在库」—— 数据工单一张没派,直接把评估输入执行工单发给了人。
剧本早写着「`parts.profile` 整表在你的作用域里,按 internal_pn 逐个核对」——**措辞已到头**。
**结构治**:`sub_eval.pn_check` 加一列 `found_pn_ref`,
`refersTo: parts.profile.internal_pn` + `requiredWhen: {exists_status: found}`。
于是「判在库」这句话必须配一个**基座拿去主数据里查得到**的料号:
- 查无此值 → `draftWrite` 当场拒;
- 填不出 → `pn_check_missing > 0` → `S0_bind` 的 `doneWhen` 收不掉。
两条路都堵死,唯一走得通的就是如实写 `absent`。**这是「机检只读基座数」第六次现形**
(前五次是 missing_key_total / missing_minor_total / untyped_total / draft_total / 哨兵读 line_total),
这次的形状不是计数,是**存在性**。
**第 2 次(v1.2.4)—— 墙生效了,但逮出发现 J:数据工单派给了在库的那颗**
核对表这次写对了(`LM2596S-3.3 = absent`、`LM2596S-ADJ = found` 且依据经基座查过),
可数据工单派给了 **LM2596S-ADJ**(它在库、参数资料齐全),真正缺的那颗没人建。
交代原话:「候选只有 LM2596S-ADJ 一颗,按规则直接建主数据」——
它把「候选总数 = 1 → 不问人」这条**关于问不问**的规则,读成了**关于建哪颗**的规则。
病根:剧本把两个问题写在同一串项目符号里,三档分岔每档都以「→ 直接进入建的名单」收尾,
而**从没写过「found 的不建」**。与发现 E 同形。
**治法(措辞,精准化)**:拆成「**问题一 · 建哪几颗**」(名单 = `absent` 的每一行,`found` 的一行都不建,并写明后果)
与「**问题二 · 建之前要不要先问人**」(只有 absent 的候选才谈得上问)。这一处不上结构 ——
系统其实兜得住(原 PN 还 absent → S1 哨兵不开 → 依赖断点),只是要白烧一次人环;
而这一刀是**补上从没写过的那句话**,不是把已经写过的话再说一遍。
**第 3 次(v1.2.5)—— `released`**:数据工单派给了 `LM2596S-3.3`,**没发决策卡**(硬阻塞不问人),两条修复都实测通过。
这一轮还留下了**发现 I 那道墙开火的现场证据**(轨迹 seq 6):
> 行动被拒:在库核对依据「LM2596S-3.3」在芯片主数据(P-08)里不存在 —— 这一列只许引用台账里真实存在的值……
模型确实又想判「在库」,基座当场拒回并点名;它随后如实写了 `absent`,硬阻塞照规格走了下去。
**终局「重做」分支也在这一轮验了**(本活动此前未验):在验收卡上写明两条意见后点「重做」——
模型没有原样再递一次,而是**真去改了台账**(`demand.request.verification_requirement` 重写、
5 行 `difference_item.evidence_ref` 从「只写文件名」改成指到 `Rev H (2023-09) §6.5 Electrical Characteristics`),
再重新裁量 + 提交;第二张验收卡确认通过 → `released`。
整单 2 次被拒:一次是上面那道墙(它该拒),一次是 S3 的「先 finish 后调工具」——
拒回文案照旧只谈「行与列」(平台欠账已记),但模型下一拍自己去调了 `recommend`、随即自动收步,没有熔断。
落账:`parts.profile.LM2596S-3.3`(TI / nrnd,7 行参数)真进了主数据;
P-11 一条(`LM2596S-3.3 → LM2596S-ADJ | alternate | fae_confirmed`);P-01 回写齐。
### R5 · 样例「新客户·先建档」
验的是**数据录入卡**这条路(客户不在档案里,先收人、再评估):
- 卡按规格出现:「客户 CU-9001 不在客户档案里,请核对建档信息后确认」,客户名称已从入参带出、行业与区域留白给人补;
- 补两格 → 确认写入 → 客户档案落草稿层(`深圳恒星电源有限公司 / 工业电源 / 华南`)→ 流程直奔 S1(两颗料都在库);
- 缺口补齐 → 审核通过 → 终局确认 → `released`。
**发现 K**:那张录入卡的「参考信息」栏摆的是引擎兜底的**内部家具** ——
「这一步 / 当下可为 / 目标缺口」,后面跟着**九个计划项的全名**,人一个字用不上。
病根:`entryCard.basis` 在契约里是**可选**的,活动的卡骨架没声明,基座就把内部事实兜了上去。
与 A1 2026-08-03 那次同族(那次是执行卡的 steps/standard 没进说明书)。
治法:说明书里的录入卡骨架补 `basis` 三行(触发原因 / 这一单要评估的 / 确认之后会发生什么),
并在骨架下写明「不给基座会兜内部家具」。配一条测试。
**一处操作教训(不是缺陷)**:测试台在「清场」之后会回落到样例 0 ——
选样例与「起单试跑」必须在同一次操作里完成,否则起的是上一个默认样例。
## 二·五、六轮走查一览
| 轮 | 样例 | 结果 | 这一轮覆盖的分支 |
|---|---|---|---|
| R1 | 都在库·常路 | `released` · 12 拍 · 人环 3 · 被拒 0 | 无数据工单直通;验收判据 11/11 |
| R2 | 候选缺库·派数据工单 | `released` · 被拒 0 · 人环 5 | 决策卡(创建)· P-08 一件两表 · P-10 · **审核驳回循环** |
| R3 | 三候选·含硬约束不推荐 | `released` · 被拒 0 | 三候选并行 · **硬约束 MISMATCH → `not_recommended`** |
| R4 | 原PN缺库·硬阻塞 | `released` · 被拒 2(其中一次是墙该拒) | **硬阻塞不问人** · **终局「重做」循环** |
| R5 | 新客户·先建档 | `released` · 被拒 1 | **数据录入卡建档** |
| R5b | 新客户(v1.2.6) | 验完即停 | 录入卡 `basis` 呈现 |
版本轨迹:1.0.0 → 1.0.1(A)→ 1.1.0/1.1.1(B·C·D)→ 1.2.0(参数子表)→ 1.2.1(F)→ 1.2.2(G)
→ 1.2.3(H)→ 1.2.4(I)→ 1.2.5(J)→ **1.2.6(K)**。包内自测 16 → **61 条**。
## 二·六、脚本 e2e 的六轮(2026-08-27)
浏览器那六轮之后,凭证到位、`w05` 套件跑起来,又逼出六条 —— **全是浏览器逮不到的那一类**
(脚本每张卡都先空手交一次、每个岔路口都按序代答,人手点的时候会先把格子填好再按提交):
| 轮 | 结果 | 这一轮逼出什么 |
|---|---|---|
| 1 | 1 通过 | **L 数据工单的提交闸没牙** |
| 2 | 3 通过 | **M 拒回数不出「缺的是一次工具调用」· N 决策卡拒回只给指针** |
| 3 | 1 通过 | N 的措辞版没用 → **改结构**;**O 工具被 null 打崩** · P `count` 假线索 |
| 4 | 2 通过 | **H 的残留面:零行同时骗过闸与哨兵** |
| 5 | 4 通过 | **created 逐颗对账太松 · S1 卡的前提没写在说明书** |
| 6 | 跑到的 4 例全 released,3 例被拒 0 | 案例 4 停在 `Insufficient Balance`(大模型余额) |
| 7 | 前 3 例 released | 充值后:先撞上我自己拉起的旧稳定实例抢单(`recommend` 无可用实现);**T** P-10 骨架零行 · **U** 脚本一例翻车整套退出 |
| 8 | **5 例全 released,4 例被拒 0** | 案例 3 被拒 6:**V** 建完第一颗就收掉数据工单那一项 |
| 9 | 案例 3 单跑 | 用户纠正「别每次全跑」;逮到一次**假绿**:**W** 参数名写成英文 key · **X** 两颗缺库只问一次 —— 断言收紧 |
| 10–11 | 案例 0/1 被拒 0 | **W 的乘法对账只在 ≥2 颗时咬得住**,单颗照漏 → 自指 `refersTo`;**Y** 脚本按闸的指示「加一行」;案例 2 撞 **Z** |
| 12 | 案例 2 · 4 各单跑 | **Z** 修后 released · 被拒 0 · 卡先发人再答 |
**最终状态(收紧断言下)**:五例全部 `released` · 全部被拒 0。
案例 0/1 验于 1.3.5、案例 3 验于 1.3.4、案例 2/4 验于 1.3.6 —— 1.3.6 只改了 S0d 剧本里「何时标 created」那一句,
案例 0/3 走过那一步、未在最终文本上复验(如实记)。
第 6 轮逐条实证:早收容忍让案例 1/2 的最后 1 次被拒消失(轨迹里是**观察**不是拒回);
三候选那例**第一次跑通**(前三轮:超时 / 超时 / 烧穿预算),两颗缺库一起办、三条结论全对。
## 三、走查发现总表
| # | 现象 | 病根 | 治法 | 层 |
|---|---|---|---|---|
| A | 缺口表**每一行**都摆红「必填」,而闸只认 3 条 | 那一格用静态 `req` class,`supplement` 的声明是 `requiredWhen:{status:'gap'}` | 按行投影 `data-class-of="status"`,判断留样式表 | 活动 |
| B | 五张模版是 E04/I01 的 `jc-rp-*` 外壳,不是目标件的版面 | 计划文本自相矛盾(一边说逐字量自目标件,一边让用 `prd-style.ts`) | 目标件 `<style>` 逐字节抽成 `target-style.ts`,标记逐块搬,删 `prd-style.ts` | 活动 |
| C | 带下划线的 tally 值一律显示「待定」(`pin_to_pin` 等 14 个值) | **两套消毒规则打架**:`view-render.classToken` 只留 `[a-z0-9-]`(吃下划线),而基座读数 slug 只留 `[a-z0-9_]`(吃连字符) | 徽标 CSS 选择器改由 `vtok()` 从 tally 值算,永不漂移;平台那两套规则不一致记欠账 | 活动(平台记账) |
| D | 主键列 `item_key` 丢了 `data-col`;`status` 降成只读徽标而它是必填 | 模版重做时的回归 | 补回主键 `data-col`;`status` 改混排(只读徽标 + 编辑态下拉);**两条回归测试**(主键列必有钥匙 / 必填列必有可填控件) | 活动 |
| E | 候选 ≥2 时该问的决策卡被跳过 | guide 写的是复合条件「候选 absent 且候选数 ≥2」,模型读成「absent 的候选 ≥2 颗」 | 改两步式:先数两个数各给名字,再按三档分岔;显式写「不在库的只有一颗不是跳过的理由」 | 活动 |
| F | P-10 的卡发出来了,工作区还停在 P-08 的件 | 模型没先 `finish` 上一项就发下一项的卡;引擎按「当下还没干完的第一步」取 view | guide 把动作串写死「恰好两个、顺序不能反:①先 finish ②再发卡」 | 活动(平台记账) |
| G | `S3_assess` 熔断:`recommend` 工具从没被调用,推荐等级是模型自己拍的 | doneWhen 里 `tool_..._recommend_calls > 0` 恒假;而拒回文案只谈「行与列」,把模型指向错方向 | guide 写盘前自检「两个 tool_*_calls 都必须 > 0」+ 写明「自己填看着对、机制上是你拍的」 | 活动(平台记账) |
| H | 执行工单发出来了,清单一行都没有 —— 人对着空表 | 「先写清单再发卡」只写在 S1 剧本里,而那一拍模型**压拍**,摊开的是上一项的剧本 | 规矩搬进**说明书**(每拍都在);包内自测钉死 | 活动(平台记账) |
| I | 原 PN 根本不在库,模型两颗都判「在库」,硬阻塞整条路被跳过 | 存在性核对是模型自报的一句话,基座数不出来;剧本已写到头 | 加 `found_pn_ref`(`refersTo` + `requiredWhen`):判在库就必须填一个基座查得到的料号,查无此值当场拒、填不出则收不了步 | 活动(结构) |
| J | 数据工单派给了在库的那颗,缺的那颗没人建 | 剧本把「建哪几颗」与「要不要问人」写在同一串分岔里,从没写过「found 的不建」 | 拆成两个问题分别作答,并写明后果 | 活动 |
| K | 数据录入卡的「参考信息」栏摆着引擎内部家具(九个计划项全名) | `entryCard.basis` 契约里可选,活动没声明,基座兜底把内部事实摆了上去 | 卡骨架补 `basis` 三行,并写明不给的后果 | 活动 |
| L | **数据工单的提交闸没牙**:件上红带点着「缺品牌名称」,提交钮却是绿的,空手交卷一路放行 | `gateAddressesOf` 只有两级 —— 没绑表就回落到**必交付物**,而数据工单要人补的是 `parts.*` 主数据,不在交付物名单里:闸盯着一堆与这张卡无关的表,一格不缺 | 契约新增 `ExecutionWorkOrder.gateLedgers`(**这张卡该拦哪几张表,发卡的人说了算**),闸改三级取一:绑的表 > 卡自报 > 交付物 | **平台**(结构) |
| M | `finish` 撞 doneWhen 为假时,拒回只谈「行与列」,而缺的是一次**工具调用** | 拒回从不摆判据本身,更不摆读数 | 拒回摆出**判据原文 + 那几个名字此刻的读数**;`tool_*_calls` 读到 0 的单独点名 | **平台** |
| N | 人点了决策卡,模型每拍再发一张,连拒五拍熔断 | 剧本让模型「去轨迹里找 card-reply」,而那条痕会被挤走 —— 拒回把「他选的是 approve」写明白也没用,**下一拍它又从头翻一次** | `answeredCardFact`:把「这张卡已答过 → 他选的是什么」做成**每拍都在的事实行** | **平台**(结构) |
| O | 模型传 `requirement: null`,工具 `null.trim()` 当场崩,整次调用记成「行动被拒」 | 工具入参是宽松描述式 schema,null 一路落到处理器;处理器只判了 `undefined` | 边界上一律经 `text()` 归一,类型如实写成可空 | **平台**(我写的工具) |
| P | 拒回里摆着 `count=(没写过)` —— 那是 S-FEEL 的函数名,不是谁忘了记的账 | `readingsOf` 把内建函数当台账名 | `SFEEL_WORDS` 补上 count/sum/min/max/all/any | 平台 |
| Q | 模型压拍没写骨架就发数据工单,人打开是空表,而**零行 = 零缺**,闸与哨兵一起放过 | 「缺必填」只数已有行;`_missing = 0` 在零行时恒真 | 平台 `emptyGate`(**卡自报的表一行都没有 = 没完成**)+ 说明书③「发卡前骨架必须先有行」+ 哨兵 `profile_rows >= created` 逐颗对账 | 平台 + 活动 |
| R | 两颗缺库只办了第一颗,第二颗还 absent 就把 S1 的卡发了出去 | **发卡的授权面是调人预算,不是计划项** —— 它绕得过哨兵;而 S1 那张卡的**前提**只写在剧本里 | 前提写进说明书的卡骨架(「一颗 absent 都不剩」「有几颗 absent 就要办几颗」) | 活动 |
| S | 每例白吃一次的「早收」:工具还没轮到调,`finish` 先到了 | 那是**计划次序**的小错,却被记成「行动被拒」去喂熔断计数 | 与「重发已答过的卡」同一把尺:**头一次只落观察,第二次起才算被拒** | **平台** |
| T | P-10 数据工单发出来时 `parts.document` 一行都没有 | 说明书③给 P-08 补了「发卡前骨架必须先有行」,④(P-10)没补 | ④ 补同款前提 | 活动 |
| U | 一例卡住,脚本整套抛出退出,后面两例连跑都没跑 | `main` 逐例调用没兜 | 一例翻车判失败、接着跑下一例 —— 一套五例的价值在「哪几例过、哪几例没过」 | 脚本 |
| V | 建完第一颗料就把数据工单那一项收掉,再给第二颗发卡撞「这一步已经办完」 | 剧本【P-08 确认回来了】没分岔「还有没有 absent」 | absent 没清零不许 finish;写明「收掉了就回不去了」 | 活动 |
| W | 参数名写成英文 key(`input_voltage_range`),与库里中文行**不是同一行** → 27 条里 14 条 UNKNOWN | `param_name` 是主键的一半;措辞两遍 + 乘法对账(行数 = 不同名字数 × 料数)都拦不住**单颗**那一路 | **自指 `refersTo: parts.parameter.param_name`** —— 一颗料时也咬得住 | 活动(结构) |
| X | 两颗缺库只问了一次;`expectDecision` 只看张数,审核卡就把它喂饱 | 剧本「还有 absent → 写骨架再发卡」把「先问」压掉;断言太宽 | 剧本补「第二颗也要先问」;脚本新增 `expectAsks`(按问法数) | 活动 + 脚本 |
| Y | 模型漏铺骨架 → 闸如实拦「一行都没有」→ 脚本只会填已有行,连吃 400 抛出 | 脚本没有「加一行」这条路,而人在浏览器里正是这么做的 | 主键齐了就加一行(与件上「加一行」同一条路) | 脚本 |
| Z | 铺完骨架就标 `created`、直接 finish,撞「从没给它发过卡」连拒五拍 | 我 1.3.1 的措辞「表里真有一行才标 created」—— 而骨架是模型自己铺的 | 「created 认的是卡交回来了」;顺序写死:骨架 → 发卡 → 拍结束 → 人交回 → 才标 | 活动 |
| AB | **库里有值的参数被 S1 清单当成缺口再问一遍**(三次复现):人在 P-08 填了使能阈值 2.5,清单上仍有「使能阈值 · 原厂未披露」;第三次连数据工单都没派(料号已在库、21 个参数全有值)照样出现 | S1 的「待确认」行是模型对参数表的断言,基座无读数核它;说明书里「使能阈值」与「未披露」同句三处(含 1.4.10 我写的反例原话);S-FEEL 无列表过滤写不出判据 | S1 一行参数都不写;件上加「候选参数现值」只读块(嵌套 `data-by` 现读台账);未披露归 S3 判 UNKNOWN;说明书全文去掉「使能阈值」 | 活动(结构)+ 平台(渲染器嵌套行) |
| AA | **数据工单确认了,数据没入库**:卡上写着「确认后这批主数据即入库」,人建好的 P-08/P-10 记录要等整条评估放行才进正式表;试跑单(不落主数据)永远不进(2026-08-27 用户指出) | 草稿层通往正式表只有整单放行一道口子(`releaseWrite(taskId)`),回传路由只记办结 + 抛人事件;而引擎的 `mine:` / `_rows` / 哨兵全靠草稿层认「本单写下的行」,清掉就断 | `releaseWrite(taskId, {only, cause})` 范围放行:只并这张卡 `gateLedgers` 那几张表,并过的行**留在草稿层打 `landed` 记号**(读面不变,整单放行不再写);回传路由在保存与回传落定后调它,痕点名几张表各几行;`createOnly` / `drop` 对已落地行改口(别 drop,撤了读面少一行);活动 1.4.8 剧本改口「已入正式表」 | **平台**(结构)+ 活动 |
| AC | **两颗输入电压范围一模一样却判 MISMATCH、整颗不推荐**(2026-08-27 用户送来 0bddd862):客户写「输入电压在 45V 以内」,模型译成 requirement `>= 45`,原 PN 与候选上限都是 40V | `judgePair` 客户约束一票否决:候选过不了客户线就 mismatch,不看原 PN 自己过不过得了 —— 需求边界与在用料的差距被记在候选头上 | 工具 1.1.0:候选与原 PN 相等 / 盖住且原 PN 也不满足客户线 → 仍按比对结果判(MATCH,风险中),备注点名「需求边界,请回头核对需求」;候选更窄且过不了线仍 MISMATCH | **平台**(工具) |
| AD | **比对没有「认真比每一条」的机制**(2026-08-27 用户:「这个做差异评估比对的 harness 肯定有问题」):模型交代里念出「输入上限 32V 低于客户 40V」—— 这两个数不是这单的,是 S3 剧本示例的原话;工具入参只存哈希,喂了哪 9 对值事后查不到;写回台账时还把工具的 `equal` 改成了 `less` | 比对入参由模型从台账抄给工具(抄错 / 抄示例都拦不住),出参再由模型抄回台账,两头都没有基座核;示例引了具体值 | 工具 1.2.0:只报原 PN + 候选料号 + 客户约束,参数 / 封装 / 生命周期 / 证据引用由工具从 parts.* 现读(taskId 经运行时交给处理器,读任务视图);出参带原值,写盘照抄;≤800 字的工具入参整份留痕;剧本示例只留占位形 | **平台**(工具运行时 + 工具)+ 活动 |
**可推广的三条**(已记 `docs/debt.md`):
1. 凡「同一条路上前后两个人环项」,前一项不收掉,后一项的件就推不出来(发现 F);
2. 拒回文案只谈行与列,数不出「缺的是一次工具调用」(发现 G);
3. 执行工单绑的必交付台账**一行都没有**时提交闸无牙 —— 回落只数「已有行缺不缺必填」,零行 = 零缺(发现 H)。
发现 L 是这三条里**唯一当场治了平台的**:闸看的表与件上摆的表不是同一张,闸就等于没有 ——
而这件事只有脚本 e2e 逮得到(它每张卡都先空手交一次;人手点的时候会先把格子填好再按提交)。
**还有一条**(平台侧,已记 debt):`disable` 这条路从来没通过(发现 A)——
`Disabled` 只能从 `Enabled` 来,而 `Enabled` 只由 `plan` 动作写。
## 四、这一轮沉淀下来的三条方法
1. **措辞治不了的结构治,但要先分清「已经说过」和「从没说过」。**
发现 I 是措辞已到头(剧本白纸黑字写着「整表在你的作用域里逐个核对」),该上结构;
发现 J 是**从没写过那句话**(「found 的不建」),补一句话就够 —— 两者形状像,处方不同。
2. **「机检只读基座数」这条纪律,第六次以新形状现形。**
前五次都是**计数**(missing_key_total / missing_minor_total / untyped_total / draft_total / line_total),
这次是**存在性**。凡是「模型说了算、基座数不出来」的判断,迟早会在某一单里说反。
本活动的解法是 `refersTo` + `requiredWhen` 组合成一道「说了就得拿出依据」的门。
3. **验证呈现要看 computed style,不看 `innerText`。**
徽标文字是 CSS `::after` 生成的 —— 用 `innerText` 判空,会把好端端的页面判成缺陷(R3 差点误报)。
## 五、活动侧的验收口径
- 六条路径全部 `released`;三条零被拒,另三条的被拒各有交代(一次是墙该拒,两次是同一处平台缺口且模型自行恢复);
- 落账逐单 SQL 复核:P-11 主记录 / 差异明细 / P-01 回写 / 验证任务 / 主数据 P-08 与 P-10,值与业务一致;
- **只读边界守住**:`customer_approval_status` 每单都留空(本活动不产生),`rule_version` 随结论落账;
- 出口只有一口 `assessment-released`,每单都真发射了。
4. **两条线逮到的缺陷不重合,缺一条就漏一半。**
浏览器逮的是**人看见什么、点得动什么**(件、闸、徽标、翻页、画面切换、快照 1:1);
脚本逮的是**机制**(空手交卷、循环、崩、归属)。发现 L–S 八条没有一条是浏览器走查逮到的 ——
因为人手点的时候会先把格子填好再按提交,永远不会去试「空着交上去会怎样」。
5. **断言报的通过是假的,比报的失败是假的更糟。**
第 9 轮案例 3 报「1/1 通过」,而参数名全是英文、两颗缺库只问了一次 —— 脚本只把它们记成 ⚠️ 就放过。
假失败还有人去查;假通过没有人会看第二眼。此后:点名的行整例跑完仍没出现 = 失败;决策卡按**问的是哪件事**数。
6. **只跑受影响的那一例;改了平台共享面才全跑回归。**
前八轮每次把已绿的四例重跑一遍 —— 每轮多烧一百多万 token,而且什么新东西都测不出。
脚本本来就支持 `w05 N`。
7. **拒回喂事实,不喂指针。**
发现 N 那一轮把「他选的是 approve、下一步写哪面旗」写进拒回,日志里逐字可见,模型照发不误 ——
因为**下一拍它又从头翻一次会滚走的窗口**。把同一件事做成「每拍都在的事实行」之后,一次就好了。
同一条道理已经在 worldTouched(2026-08-21)、E04 的 worldTouched 事实行(2026-08-24)上各现过一次。