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 Opus 5 eb80876554 走查逼出的六条:发卡前清单要有行 · 在库要拿得出依据 · 数据工单只建缺的那颗 · 录入卡自带 basis
ACT-WORK-05 差异评估的浏览器全流程走查(六轮六条路径,全部 released),
逐条治了实跑里现形的缺陷。活动包 1.2.2 → 1.2.6:

- H(1.2.3):模型压拍把执行工单发了、清单一行没写,人对着空表 ——
  「先写清单再发卡」只在剧本里,压过拍就只有说明书还在;规矩搬进说明书。
- I(1.2.4,结构治):原 PN 根本不在库,模型两颗都判「在库」,硬阻塞整条路被跳过。
  剧本已写到头 → pn_check 加 found_pn_ref(refersTo + requiredWhen):
  判在库就必须填一个基座查得到的料号,查无此值当场拒、填不出则收不了步。
  这是「机检只读基座数」第六次现形,前五次都是计数,这次是存在性。
- J(1.2.5):数据工单派给了在库的那颗,缺的那颗没人建 ——
  剧本把「建哪几颗」和「要不要问人」写在同一串分岔里,从没写过「found 的不建」;拆成两问。
- K(1.2.6):数据录入卡的参考信息栏摆着引擎内部家具(九个计划项全名)——
  entryCard.basis 契约里可选,活动没声明,基座就兜了内部事实;卡骨架补三行人话。

包内自测 56 → 61 条;门禁 typecheck / lint / depcruise / test(2071)全绿
(api:check 的差异全在 org/* 与 api/*,是工作树里先前那批鉴权改动,本轮未添)。

docs/ACT-WORK-05-端到端测试记录.md:六轮走查的逐轮结论与 A–K 十一条发现总表。
docs/debt.md:四条平台欠账(disable 无路可走 · 前一项不收后一项的件推不出来 ·
拒回数不出缺的是工具调用 · 零行台账的提交闸无牙)。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01FJcX8A6TWp4GRs41TYryEh
2026-08-27 04:29:40 +08:00

225 lines
17 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`。
> 全部走查在**浏览器**里做(测试台起单 → 工作台真人点),不是脚本代答。
## 一、这个活动是什么
原 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 条**。
## 三、走查发现总表
| # | 现象 | 病根 | 治法 | 层 |
|---|---|---|---|---|
| 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` 三行,并写明不给的后果 | 活动 |
**可推广的三条**(已记 `docs/debt.md`):
1. 凡「同一条路上前后两个人环项」,前一项不收掉,后一项的件就推不出来(发现 F);
2. 拒回文案只谈行与列,数不出「缺的是一次工具调用」(发现 G);
3. 执行工单绑的必交付台账**一行都没有**时提交闸无牙 —— 回落只数「已有行缺不缺必填」,零行 = 零缺(发现 H)。
**还有一条**(平台侧,已记 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`,每单都真发射了。