Archived
W05 收口:五例在收紧断言下全 released · 全被拒 0(活动 1.2.9 → 1.3.6)
第 7–12 轮逼出七条(T–Z),两条是脚本自己的、五条是活动的,其中一条上结构: - W 参数名写成英文 key,与库里中文行不是同一行 → 27 条里 14 条 UNKNOWN。措辞两遍 + 乘法对账都拦不住单颗料那一路(5 = 5×1 恒成立),改自指 refersTo:param_name 只能用台账里已经在用的名字,一颗料时也咬得住。 - V/Z 数据工单那一项的两个方向:建完第一颗就收掉(再给第二颗发卡撞「已办完」)、 铺完骨架就标 created 直接 finish(撞「从没发过卡」)—— 顺序写死:骨架 → 发卡 → 拍结束 → 人交回 → 才标 created;absent 没清零不许 finish。 - T P-10 也要「发卡前骨架先有行」;X 第二颗缺库也要先问。 - 脚本:U 一例翻车不拖垮整套;Y 按闸的指示「加一行」;断言收紧 —— 点名的行整例跑完 仍没出现 = 失败,决策卡按「问的是哪件事」数(第 9 轮逮到一次假绿)。 流程上两条纪律(用户当场纠正):只跑受影响的那一例,改了平台共享面才全跑;先说计划再动手。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01FJcX8A6TWp4GRs41TYryEh
This commit is contained in:
@@ -84,6 +84,13 @@ describe('台账声明:授权面与《统一方案》口径', () => {
|
||||
expect(param?.kind).toBe('master');
|
||||
expect(param?.fields.filter((f) => f.primaryKey).map((f) => f.name)).toEqual(['internal_pn', 'param_name']);
|
||||
expect(param?.fields.find((f) => f.name === 'internal_pn')?.refersTo).toBe('parts.profile.internal_pn');
|
||||
/*
|
||||
* 参数名自指引用:只能用台账里已经在用的那几个 —— 2026-08-27 实测三次,
|
||||
* 模型给新料写英文 key,剧本写过两遍 + 一条乘法对账都拦不住「只建一颗」那一路。
|
||||
*/
|
||||
const pn = param?.fields.find((f) => f.name === 'param_name');
|
||||
expect(pn?.refersTo).toBe('parts.parameter.param_name');
|
||||
expect(pn?.distinct).toBe(true);
|
||||
expect(param?.fields.find((f) => f.name === 'param_value')?.required).toBe(true);
|
||||
expect(param?.fields.find((f) => f.name === 'constraint_type')?.tally).toEqual(['hard', 'soft']);
|
||||
expect(param?.fields.find((f) => f.name === 'constraint_type')?.required).toBe(true);
|
||||
|
||||
@@ -263,7 +263,9 @@ describe('说明书与剧本的骨架', () => {
|
||||
});
|
||||
|
||||
it('数据工单也要「先写骨架再发卡」写进说明书,且哨兵不认零行主数据(2026-08-27 e2e:模型压拍没写骨架就发卡,人打开是空表,零行同时骗过闸与哨兵,一路走到 S2 才被引用检查拦下)', () => {
|
||||
expect(NARRATIVE).toContain('必须先有骨架行');
|
||||
// 两张数据工单各要一条(P-08 的 profile/parameter、P-10 的 document)
|
||||
expect(NARRATIVE.match(/必须先有骨架行/g)?.length ?? 0).toBeGreaterThanOrEqual(2);
|
||||
expect(NARRATIVE).toContain('parts.document` 必须先有骨架行');
|
||||
expect(NARRATIVE).toMatch(/压拍/);
|
||||
// 标了几颗建好,主数据就得有几行 —— 逐颗对账(第一刀写成「≥1 行就算数」太松,三候选那单从缝里过去了)
|
||||
expect(CMMN_XML).toContain('parts_profile_rows >= sub_eval_pn_check_exists_status_created');
|
||||
@@ -280,6 +282,35 @@ describe('说明书与剧本的骨架', () => {
|
||||
expect(g).toContain('引用检查');
|
||||
});
|
||||
|
||||
it('absent 没清零之前不许收掉数据工单那一项(2026-08-27 e2e:建完第一颗就 finish,再想给第二颗发卡撞上「这一步已经办完收掉了」,连拒四次)', () => {
|
||||
const g = ASSESSMENT_STEPS.find((s) => s.item === 'S0d_p08_master')?.guide ?? '';
|
||||
expect(g).toMatch(/还有没有 absent 的料号/);
|
||||
expect(g).toMatch(/这一项千万别 finish/);
|
||||
expect(g).toMatch(/收掉了就回不去了/);
|
||||
});
|
||||
|
||||
it('参数名一律中文、与库里既有行同名(2026-08-27 e2e:模型写成 input_voltage_range,而原 PN 是「输入电压范围」—— 主键的一半对不上,27 条里 14 条判成 UNKNOWN)', () => {
|
||||
const g = ASSESSMENT_STEPS.find((s) => s.item === 'S0d_p08_master')?.guide ?? '';
|
||||
expect(g).toMatch(/参数名一律用中文/);
|
||||
// 措辞写过两遍都没拦住 → 上结构:把「同一套名字」变成基座算得出的数
|
||||
expect(CMMN_XML).toContain('parts_parameter_rows = parts_parameter_distinct_param_name * sub_eval_pn_check_exists_status_created');
|
||||
expect(g).toContain('input_voltage_range');
|
||||
expect(g).toMatch(/不是同一行/);
|
||||
});
|
||||
|
||||
it('第二颗缺库的候选也要先问(每一颗都有被放弃的权利)', () => {
|
||||
const g = ASSESSMENT_STEPS.find((s) => s.item === 'S0d_p08_master')?.guide ?? '';
|
||||
expect(g).toMatch(/这一颗也要先发一张决策卡问人/);
|
||||
expect(g).toMatch(/第一颗问过了不代表第二颗也问过/);
|
||||
});
|
||||
|
||||
it('created 认的是「卡交回来了」,不是「表里有行」—— 写骨架 ≠ 建好了(2026-08-27 e2e:模型铺完骨架就标 created、直接 finish,撞「从没给它发过卡」连拒五拍)', () => {
|
||||
const g = ASSESSMENT_STEPS.find((s) => s.item === 'S0d_p08_master')?.guide ?? '';
|
||||
expect(g).toMatch(/写骨架 ≠ 建好了/);
|
||||
expect(g).toMatch(/写骨架 → \*\*发卡\*\* → 这一拍结束 → 人交回/);
|
||||
expect(g).not.toMatch(/只有它在 \\`parts\.profile\\` 里真有一行/);
|
||||
});
|
||||
|
||||
it('五段进度,每段名 ≤10 字;除放行外每项恰属一段', () => {
|
||||
expect(ASSESSMENT_PHASES).toHaveLength(5);
|
||||
for (const p of ASSESSMENT_PHASES) expect(p.name.length, p.name).toBeLessThanOrEqual(10);
|
||||
|
||||
@@ -45,6 +45,9 @@ export const CMMN_XML = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
<caseFileItem id="parts_profile_missing" name="本单建的芯片主数据缺必填的行数(基座现数)"/>
|
||||
<caseFileItem id="parts_parameter_missing" name="本单建的标准化参数集缺必填的行数(基座现数)"/>
|
||||
<caseFileItem id="parts_document_missing" name="本单建的资料记录缺必填的行数(基座现数)"/>
|
||||
<caseFileItem id="parts_document_rows" name="本单建的资料记录行数(基座现数)"/>
|
||||
<caseFileItem id="parts_parameter_rows" name="本单建的参数行数(基座现数)"/>
|
||||
<caseFileItem id="parts_parameter_distinct_param_name" name="本单用到的不同参数名个数(基座现数不同值)"/>
|
||||
<caseFileItem id="input_confirmed_total" name="评估输入已确认(人环凭据)"/>
|
||||
<caseFileItem id="sub_eval_input_gap_rows" name="评估输入清单行数(基座现数)"/>
|
||||
<caseFileItem id="sub_eval_input_gap_missing" name="评估输入清单缺必填的行数(基座现数)"/>
|
||||
@@ -90,7 +93,7 @@ export const CMMN_XML = `<?xml version="1.0" encoding="UTF-8"?>
|
||||
却只建了第一颗,一行足以让门开着,直到 S2 写关系时才被引用检查拦下。
|
||||
改成**逐颗对账**:\`parts_profile_rows >= created\` —— 标了几颗建好,就得有几行。
|
||||
-->
|
||||
<ifPart id="if_pr"><condition>sub_eval_pn_check_rows = count(candidateInternalPns) + 1 and sub_eval_pn_check_missing = 0 and sub_eval_pn_check_exists_status_absent = 0 and sub_eval_pn_check_exists_status_abandoned < count(candidateInternalPns) and parts_profile_missing = 0 and parts_parameter_missing = 0 and parts_document_missing = 0 and parts_profile_rows >= sub_eval_pn_check_exists_status_created</condition></ifPart>
|
||||
<ifPart id="if_pr"><condition>sub_eval_pn_check_rows = count(candidateInternalPns) + 1 and sub_eval_pn_check_missing = 0 and sub_eval_pn_check_exists_status_absent = 0 and sub_eval_pn_check_exists_status_abandoned < count(candidateInternalPns) and parts_profile_missing = 0 and parts_parameter_missing = 0 and parts_document_missing = 0 and parts_profile_rows >= sub_eval_pn_check_exists_status_created and parts_document_rows >= sub_eval_pn_check_exists_status_created and parts_parameter_rows = parts_parameter_distinct_param_name * sub_eval_pn_check_exists_status_created</condition></ifPart>
|
||||
</sentry>
|
||||
<!-- ③ 评估输入已确认(旗 + 清单有行且必填齐)—— 标准化那一步的入场前提 -->
|
||||
<sentry id="s_input_confirmed">
|
||||
@@ -244,7 +247,10 @@ PN 在库但个别字段缺 = 「有而不全」,归执行工单 01 补。**该
|
||||
不给它就回落到必交付物那几张(与这张卡无关),于是件上红带点着「缺品牌名称」而提交钮照样绿,
|
||||
空手交卷一路放行(2026-08-27 实测)。给了之后,闸与红带、放行门读的是同一个数。
|
||||
|
||||
④ 数据工单 · P-10(同一批料号的资料记录,一张单;在 P-08 那张确认之后再发):
|
||||
④ 数据工单 · P-10(同一批料号的资料记录,一张单;在 P-08 那张确认之后再发)——
|
||||
**与③同一条:发这张卡之前 \`parts.document\` 必须先有骨架行**(名单里每颗料至少一行,
|
||||
key 是 {internal_pn, doc_seq:"01"});一行都没有的话人打开是空表、什么也补不了,
|
||||
提交闸会如实拦住(「这一单还一行都没有」),这一单就卡在这儿了(2026-08-27 实测)。
|
||||
{"kind":"human","itemId":"S0d_p10_document","workOrder":"execution","card":{
|
||||
"title":"数据工单 · 原厂技术资料创建(P-10):<料号列表>",
|
||||
"ask":"请把这些料号的 datasheet / 承诺函等资料记录补进原厂技术资料库(一份资料一行,可加行)。",
|
||||
@@ -383,20 +389,41 @@ current_stage = "assessing"。application_scenario / bom_position **这一步不
|
||||
1. 给名单里每颗料写一行 \`parts.profile\` 骨架(表 1):key {internal_pn},patch 只带你确有依据的列 —— 有 \`datasheets[].text\` 就从里面读
|
||||
brand_name / specification_description / package / lifecycle_status(active/nrnd/eol/discontinued/risk 之一)/ datasheet_ref + datasheet_version;
|
||||
没有 datasheet 就只写 internal_pn 这一列(其余留给人填,**别编**)。
|
||||
2. 同一拍给每颗料写标准化参数集骨架(表 2,\`parts.parameter\`,一行一参数):有 \`datasheets[].text\` 就从里面读出典型参数
|
||||
2. 同一拍给每颗料写标准化参数集骨架(表 2,\`parts.parameter\`,一行一参数):
|
||||
**参数名一律用中文,与库里既有料号的那几行同名**(输入电压范围 / 输出电压 / 输出电流 / 开关频率 /
|
||||
静态电流 / 工作温度 / 使能阈值…)—— \`param_name\` 是主键的一半,写成 \`input_voltage_range\`
|
||||
与写成「输入电压范围」**不是同一行**:原 PN 那边是中文、候选这边是英文,比对时两套名字对不上,
|
||||
逐条判成 UNKNOWN,结论就废了(2026-08-27 实测:27 条里 14 条 UNKNOWN)。
|
||||
封装、工艺、生命周期这些**不是参数**,它们在表 1,别往表 2 里塞。
|
||||
**建几颗料就用同一套名字**:门上有一条对账 —— 参数行数 = 不同参数名数 × 建过的料数,
|
||||
只有每颗料的名字集合一模一样时才成立;混着写(这颗中文那颗英文、或同一颗写两套)这一步就过不去。有 \`datasheets[].text\` 就从里面读出典型参数
|
||||
(如输入电压范围 / 输出电压 / 输出电流 / 开关频率 / 静态电流 / 工作温度 / 使能阈值等,按品类而定)各写一行,
|
||||
key {internal_pn, param_name},patch 带 param_value / param_unit / constraint_type(hard/soft)/ param_note(一句话说清这项为什么要卡,
|
||||
如「须覆盖客户输入上限」);原厂没写的值写「未披露」(它会进入 UNKNOWN 并挂验证任务)。没有 datasheet 就只写
|
||||
internal_pn + param_name 骨架(把你判断这颗料该评估的参数名列出来,**param_value 留空给人填,别编**)。
|
||||
3. 同一拍给每颗料写一行 \`parts.document\` 骨架:key {internal_pn, doc_seq: "01"},patch {document_type: "datasheet", document_status: "pending",
|
||||
3. 同一拍**给名单里每一颗料各写一行** \`parts.document\` 骨架(两颗就两行,别只写一行 ——
|
||||
门上有一条对账:建好几颗就得有几行资料记录;少一行,那颗料的资料工单人打开是空的):key {internal_pn, doc_seq: "01"},patch {document_type: "datasheet", document_status: "pending",
|
||||
brand_name 有就写}(这一行是骨架,下一项 S0d_p10_document 会把它填成正式记录)。
|
||||
4. 同一拍发说明书③那张 P-08 数据工单(title 里列全料号),发完这一拍结束(挂起)。
|
||||
|
||||
**\`created\` 是「这颗料真的建好了」,不是「我打算建」**:只有它在 \`parts.profile\` 里真有一行(件上填好交回来了)
|
||||
才改成 created —— 门上有一条逐颗对账(建好几颗就得有几行主数据),标了却没建,这一步过不去,
|
||||
到 S2 写关系时还会被引用检查再拦一次。
|
||||
**\`created\` 认的是「那张卡交回来了」,不是「表里有行」** —— **写骨架 ≠ 建好了**:
|
||||
骨架是**你**铺的(只有料号和参数名),值是**人**在件上填的。骨架一铺就把 pn_check 改成 created,
|
||||
等于替人宣布他已经办完了:接着你会以为数据工单收工、去 finish 这一项,而卡根本没发出去 ——
|
||||
撞上「这一单里从没给它发过卡」,连撞五拍熔断(2026-08-27 实测,整单白跑)。
|
||||
**顺序只有一个**:写骨架 → **发卡** → 这一拍结束 → 人交回 → 这时才把那几颗改成 created。
|
||||
门上还有一条逐颗对账(建好几颗就得有几行主数据、几行资料),标了却没建,这一步照样过不去。
|
||||
|
||||
【P-08 那张确认回来了】这一拍的动作串**恰好两个,顺序不能反**:
|
||||
【P-08 那张确认回来了】**先看名单里还有没有 absent 的料号**(\`${D}.pn_check\` 现读):
|
||||
· **还有** → **这一项千万别 finish**。先回到上面【问题二】那一档:候选总数 ≥2 的话,
|
||||
**这一颗也要先发一张决策卡问人**(照说明书②,人选 create 才建 —— 每一颗 absent 的候选都有被放弃的权利,
|
||||
第一颗问过了不代表第二颗也问过);人选 create 之后再把它的骨架写好(profile + parameter,有 datasheet 就预填),
|
||||
发一张 P-08 卡(标题带那一颗的料号)—— 同一个计划项可以先后发好几张卡,一颗一张也行。
|
||||
原 PN 与「候选总数 = 1」那两档不问,直接建。
|
||||
**收掉了就回不去了**:这一项一旦 Completed,再想给它挂第二张卡会被拒「这一步已经办完收掉了」,
|
||||
而那颗料从此没人建,后面写替代关系时被引用检查逐颗拦下(2026-08-27 实测,一单连拒四次)。
|
||||
· **一颗都不剩了** → 才走下面这两步。
|
||||
|
||||
这一拍的动作串**恰好两个,顺序不能反**:
|
||||
① 先 \`finish S0d_p08_master\` —— **必须先把这一项收掉**。不收掉,引擎挑工作区画面时按
|
||||
「当下还没干完的第一步」取 view,S0d_p08_master 只要还 Active,画面就一直停在
|
||||
\`p08-master-create\`(P-08 那两张表);下一拍就算发出了 P-10 的卡,人的工作区也看不见
|
||||
|
||||
@@ -89,7 +89,7 @@ export const manifest: ActivityManifest = {
|
||||
identity: {
|
||||
activityId: ACTIVITY_ID,
|
||||
name: 'ACT-WORK-05 · 差异评估',
|
||||
packageVersion: '1.2.9',
|
||||
packageVersion: '1.3.6',
|
||||
category: '需求分析与方案匹配',
|
||||
sdkVersion: '0.1.0-m5',
|
||||
checksum: 'dev-checksum-part-substitution-assessment',
|
||||
@@ -309,7 +309,32 @@ export const manifest: ActivityManifest = {
|
||||
label: '标准化参数集(P-08 子表)',
|
||||
fields: [
|
||||
col({ name: 'internal_pn', type: 'text', label: '所属料号', primaryKey: true, refersTo: 'parts.profile.internal_pn' }),
|
||||
col({ name: 'param_name', type: 'text', label: '参数名', primaryKey: true }),
|
||||
/*
|
||||
* `distinct` 是为了让「两颗料是不是用同一套参数名」变成**基座算得出的数**
|
||||
* (`parts_parameter_distinct_param_name`)—— 见 CMMN 的 s_pns_resolved:
|
||||
* 参数行数 = 不同参数名数 × 建过的料数,只有每颗料的名字集合一模一样时才成立。
|
||||
* 2026-08-27 实测:模型给第二颗料写英文 key(`input_voltage_range`),
|
||||
* 而原 PN 在库里是中文「输入电压范围」—— 名字是主键的一半,对不上就没法逐项比。
|
||||
* 措辞写过两遍都没拦住(设计律第六条:措辞治不了的结构治)。
|
||||
*/
|
||||
col({
|
||||
name: 'param_name',
|
||||
type: 'text',
|
||||
label: '参数名',
|
||||
primaryKey: true,
|
||||
distinct: true,
|
||||
/*
|
||||
* **参数名只能用台账里已经在用的那几个**(自指引用)—— 比对是逐参数对着比的,
|
||||
* 候选身上有一个原 PN 没有的维度,本来也无从比起;名字对不上更是直接判成 UNKNOWN。
|
||||
* 2026-08-27 实测三次:模型给新料写英文 key(`input_voltage_range`),
|
||||
* 而库里既有行是中文「输入电压范围」—— 剧本写过两遍、又加了一条乘法对账
|
||||
* (行数 = 不同名字数 × 建过的料数)仍拦不住**只建一颗**的那一路(5 = 5×1 恒成立)。
|
||||
* 自指是唯一在一颗料时也咬得住的:写下去那一刻基座去这一列里查,查无此值当场拒。
|
||||
* 代价(已知约束):真要引入一个全新的参数维度,得先有一颗料用过它 ——
|
||||
* MVP 的品类词汇表是固定的七项,够用;将来要放开,改成引用一张参数字典表。
|
||||
*/
|
||||
refersTo: 'parts.parameter.param_name',
|
||||
}),
|
||||
col({ name: 'param_value', type: 'text', label: '值', required: true }),
|
||||
col({ name: 'param_unit', type: 'text', label: '单位', expect: true }),
|
||||
col({ name: 'constraint_type', type: 'text', label: '约束类型', required: true, tally: ['hard', 'soft'] }),
|
||||
|
||||
Reference in New Issue
Block a user