Archived
docs(w05): S1 配方次序改对 —— 案卷排到骨架两笔之后
gate_reason 引的 parts_profile_missing / parts_parameter_missing 要等 ②③ 把骨架行铺出来才有值。排在前面时引擎给它读到 0,卡照样正确发出, 但卡上那句「还差什么」是空白的 —— 恰在人最想要一句解释的时候。 计划与 spec 两处都写着旧次序,不改则下游任务照抄同一个错。 S2/S3/S4 已核,次序都对(投影在前、读它的排在后),病只在 S1 一处。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
This commit is contained in:
@@ -850,10 +850,11 @@ describe('S1 配方', () => {
|
|||||||
const acts = recipe?.do ?? [];
|
const acts = recipe?.do ?? [];
|
||||||
const kinds = acts.map((a) => a.kind);
|
const kinds = acts.map((a) => a.kind);
|
||||||
|
|
||||||
it('六笔,次序是:两颗料 → 案卷 → 主数据骨架 → 参数骨架 → 卡 → 交代', () => {
|
it('六笔,次序是:两颗料 → 主数据骨架 → 参数骨架 → 案卷 → 卡 → 交代', () => {
|
||||||
expect(kinds).toEqual(['project', 'project', 'project', 'project', 'card', 'say']);
|
expect(kinds).toEqual(['project', 'project', 'project', 'project', 'card', 'say']);
|
||||||
|
/* 案卷排在骨架两笔之后 —— gate_reason 引的 _missing 要等骨架铺出来才有值,提前算它那句话是空的 */
|
||||||
expect(acts.map((a) => (a.kind === 'project' ? a.into : undefined)).filter(Boolean)).toEqual([
|
expect(acts.map((a) => (a.kind === 'project' ? a.into : undefined)).filter(Boolean)).toEqual([
|
||||||
'sub_eval.part', 'sub_eval.case', 'parts.profile', 'parts.parameter',
|
'sub_eval.part', 'parts.profile', 'parts.parameter', 'sub_eval.case',
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -871,7 +872,7 @@ describe('S1 配方', () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
it('参数骨架:两颗料都铺、值回填现值 —— 「在库但当年参数没录全」也要被拦住', () => {
|
it('参数骨架:两颗料都铺、值回填现值 —— 「在库但当年参数没录全」也要被拦住', () => {
|
||||||
const params = acts[3];
|
const params = acts[2];
|
||||||
expect(params?.kind === 'project' && params.prune).toBe(true);
|
expect(params?.kind === 'project' && params.prune).toBe(true);
|
||||||
const from = params?.kind === 'project' ? params.from : undefined;
|
const from = params?.kind === 'project' ? params.from : undefined;
|
||||||
/* 外层是本单两颗料,里层是该类型的字段清单 —— 人没挑类型时 where 一行不命中,什么也不铺 */
|
/* 外层是本单两颗料,里层是该类型的字段清单 —— 人没挑类型时 where 一行不命中,什么也不铺 */
|
||||||
@@ -951,39 +952,8 @@ Expected: FAIL(现在只有一笔 `say`)。**整份贴进报告。**
|
|||||||
chip_type_id: { lookup: 'parts.profile', by: { internal_pn: { col: 'pn' } }, take: 'chip_type_id', else: '' },
|
chip_type_id: { lookup: 'parts.profile', by: { internal_pn: { col: 'pn' } }, take: 'chip_type_id', else: '' },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
/* ② 案卷一行:`gate_reason` 是**摆在件上给人看**的那句话(条件判断另用基座读数,见 ⑤) */
|
|
||||||
{
|
|
||||||
kind: 'project',
|
|
||||||
into: 'sub_eval.case',
|
|
||||||
from: { once: true },
|
|
||||||
fields: {
|
|
||||||
eval_ref: { in: 'evalRef' },
|
|
||||||
chip_type_id: { lookup: 'mine:sub_eval.part', by: { role: 'original' }, take: 'chip_type_id', else: '' },
|
|
||||||
gate_reason: {
|
|
||||||
when: 'sub_eval_part_rows < 2',
|
|
||||||
then: '原料号与候选料号还没填全 —— 在下面把两格补上。',
|
|
||||||
else: {
|
|
||||||
when: 'sub_eval_part_exists_status_absent > 0',
|
|
||||||
then: '有料号库里查不到 —— 在下面把它的主数据建起来。',
|
|
||||||
else: {
|
|
||||||
when: 'sub_eval_part_missing > 0',
|
|
||||||
then: '有料号还没归芯片类型 —— 在下面给它选一个;没有合适的就新建一个,并把它的核心参数字段一并定下来。',
|
|
||||||
else: {
|
|
||||||
when: 'sub_eval_part_distinct_chip_type_id > 1',
|
|
||||||
then: '两颗料不是同一个芯片类型,逐项比对无从谈起 —— 换一颗料,或者把归错的那颗类型改对。',
|
|
||||||
else: {
|
|
||||||
when: 'parts_profile_missing + parts_parameter_missing > 0',
|
|
||||||
then: '还有必填格空着 —— 红带点名的那几格填上就能提交。',
|
|
||||||
else: '',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
/*
|
/*
|
||||||
* ③ 主数据骨架:**两颗料都铺、值回填现值**。
|
* ② 主数据骨架:**两颗料都铺、值回填现值**。
|
||||||
* 在库那颗回填出它此刻的样子(人不必重填);要建那颗全空等人填。
|
* 在库那颗回填出它此刻的样子(人不必重填);要建那颗全空等人填。
|
||||||
* **「在库的老料还没归类型」于是也被拦住** —— 那一格回填出来是空的,而 `chip_type_id` 必填。
|
* **「在库的老料还没归类型」于是也被拦住** —— 那一格回填出来是空的,而 `chip_type_id` 必填。
|
||||||
* 人不必在件上「加一行」:要建哪颗料是启动参数就定死的事,行由系统摆好,他只填格子。
|
* 人不必在件上「加一行」:要建哪颗料是启动参数就定死的事,行由系统摆好,他只填格子。
|
||||||
@@ -1005,7 +975,7 @@ Expected: FAIL(现在只有一笔 `say`)。**整份贴进报告。**
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
/*
|
/*
|
||||||
* ④ 参数骨架 —— 三件事一笔办完:
|
* ③ 参数骨架 —— 三件事一笔办完:
|
||||||
* · 人还没挑类型 → `{outer:'chip_type_id'}` 是空串,`where` 一行不命中,**什么也不铺**;
|
* · 人还没挑类型 → `{outer:'chip_type_id'}` 是空串,`where` 一行不命中,**什么也不铺**;
|
||||||
* 他挑了、按了保存,行就出来 —— **「保存即铺格」不是特判,是这一笔的自然结果**;
|
* 他挑了、按了保存,行就出来 —— **「保存即铺格」不是特判,是这一笔的自然结果**;
|
||||||
* · 在库那颗料**也**铺,值回填现值 → 屏上是它此刻的样子,`_missing` 不会误报;
|
* · 在库那颗料**也**铺,值回填现值 → 屏上是它此刻的样子,`_missing` 不会误报;
|
||||||
@@ -1037,6 +1007,44 @@ Expected: FAIL(现在只有一笔 `say`)。**整份贴进报告。**
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
/*
|
||||||
|
* ④ 案卷一行:`gate_reason` 是**摆在件上给人看**的那句话(条件判断另用基座读数,见 ⑤)。
|
||||||
|
* **这一笔必须排在②③之后,不许提前**(2026-08-29 走查实测,评审用活探针复现):
|
||||||
|
* 它引的 `parts_profile_missing` / `parts_parameter_missing` 要等②③把骨架行铺出来才有值。
|
||||||
|
* 排在前面时,引擎在②③写入**之前**给它读到 0 —— 卡照样正确发出(⑤ 的 `when` 排在更后面,
|
||||||
|
* 读到的是刷新后的真缺口),但卡上那句「还差什么」是**空白的**,恰在人最想要一句解释的时候。
|
||||||
|
* **一笔读的是另一笔写出来的数,它就得排在那一笔后面。**
|
||||||
|
*/
|
||||||
|
{
|
||||||
|
kind: 'project',
|
||||||
|
into: 'sub_eval.case',
|
||||||
|
from: { once: true },
|
||||||
|
fields: {
|
||||||
|
eval_ref: { in: 'evalRef' },
|
||||||
|
chip_type_id: { lookup: 'mine:sub_eval.part', by: { role: 'original' }, take: 'chip_type_id', else: '' },
|
||||||
|
gate_reason: {
|
||||||
|
when: 'sub_eval_part_rows < 2',
|
||||||
|
then: '原料号与候选料号还没填全 —— 在下面把两格补上。',
|
||||||
|
else: {
|
||||||
|
when: 'sub_eval_part_exists_status_absent > 0',
|
||||||
|
then: '有料号库里查不到 —— 在下面把它的主数据建起来。',
|
||||||
|
else: {
|
||||||
|
when: 'sub_eval_part_missing > 0',
|
||||||
|
then: '有料号还没归芯片类型 —— 在下面给它选一个;没有合适的就新建一个,并把它的核心参数字段一并定下来。',
|
||||||
|
else: {
|
||||||
|
when: 'sub_eval_part_distinct_chip_type_id > 1',
|
||||||
|
then: '两颗料不是同一个芯片类型,逐项比对无从谈起 —— 换一颗料,或者把归错的那颗类型改对。',
|
||||||
|
else: {
|
||||||
|
when: 'parts_profile_missing + parts_parameter_missing > 0',
|
||||||
|
then: '还有必填格空着 —— 红带点名的那几格填上就能提交。',
|
||||||
|
else: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
/*
|
/*
|
||||||
* ⑤ 缺什么就派一张数据工单。
|
* ⑤ 缺什么就派一张数据工单。
|
||||||
* **条件只用基座读数**:`gate_reason` 为空串时那一列压根不写、于是未绑定,
|
* **条件只用基座读数**:`gate_reason` 为空串时那一列压根不写、于是未绑定,
|
||||||
|
|||||||
@@ -200,26 +200,16 @@ let evalRef = cat('W05-', fmt(case:openedAt, digits))
|
|||||||
then 'found' else 'absent'
|
then 'found' else 'absent'
|
||||||
chip_type_id = lookup('parts.profile' by internal_pn={col:'pn'} take chip_type_id, else '')
|
chip_type_id = lookup('parts.profile' by internal_pn={col:'pn'} take chip_type_id, else '')
|
||||||
|
|
||||||
② project sub_eval.case from once
|
② project parts.profile prune from each('mine:sub_eval.part') ← **两颗料都铺**
|
||||||
eval_ref = {in:'evalRef'}
|
|
||||||
chip_type_id = lookup('mine:sub_eval.part' by role='original' take chip_type_id, else '')
|
|
||||||
gate_reason = when 链(**全读基座数**):
|
|
||||||
两颗 PN 有一格为空 → 「原 / 候选料号还没填」
|
|
||||||
sub_eval_part_exists_status_absent > 0 → 「<PN> 库里没有,请在下面建」
|
|
||||||
sub_eval_part_distinct_chip_type_id > 1 → 「两颗料类型不一致,换一颗或把类型改对」
|
|
||||||
parts_profile_missing + parts_parameter_missing > 0 → 「还差 n 格没填」
|
|
||||||
其余 → ''
|
|
||||||
|
|
||||||
③ project parts.profile prune from each('mine:sub_eval.part') ← **两颗料都铺**
|
|
||||||
internal_pn = {col:'internal_pn'}
|
internal_pn = {col:'internal_pn'}
|
||||||
chip_type_id / brand_name / lifecycle_status / specification_description /
|
chip_type_id / brand_name / lifecycle_status / specification_description /
|
||||||
manufacturer_name / datasheet_ref / datasheet_version
|
manufacturer_name / datasheet_ref / datasheet_version
|
||||||
= lookup('parts.profile' by internal_pn={col:'internal_pn'} take 同名列, else '') ← 回填现值
|
= lookup('parts.profile' by internal_pn={col:'internal_pn'} take 同名列, else '') ← 回填现值
|
||||||
↑ 与④同构。在库那颗回填出它此刻的样子;要建那颗全空等人填。
|
↑ 与③同构。在库那颗回填出它此刻的样子;要建那颗全空等人填。
|
||||||
**「在库的老料还没归类型」于是也被拦住** —— 那一格回填出来是空的,而 chip_type_id 必填。
|
**「在库的老料还没归类型」于是也被拦住** —— 那一格回填出来是空的,而 chip_type_id 必填。
|
||||||
人不必在件上「加一行」:要建哪颗料是启动参数就定死的事,行由系统摆好,他只填格子。
|
人不必在件上「加一行」:要建哪颗料是启动参数就定死的事,行由系统摆好,他只填格子。
|
||||||
|
|
||||||
④ project parts.parameter prune
|
③ project parts.parameter prune
|
||||||
from each('mine:sub_eval.part') ← **两颗料都铺,不只是缺库那颗**
|
from each('mine:sub_eval.part') ← **两颗料都铺,不只是缺库那颗**
|
||||||
then each('parts.type_param' where type_id={outer:'chip_type_id'})
|
then each('parts.type_param' where type_id={outer:'chip_type_id'})
|
||||||
internal_pn = {outer:'internal_pn'};param_name / param_unit ← {col:…}
|
internal_pn = {outer:'internal_pn'};param_name / param_unit ← {col:…}
|
||||||
@@ -232,6 +222,21 @@ let evalRef = cat('W05-', fmt(case:openedAt, digits))
|
|||||||
· 在库那颗料**也**铺,值回填现值 → 屏上是它此刻的样子,`_missing` 不会误报;
|
· 在库那颗料**也**铺,值回填现值 → 屏上是它此刻的样子,`_missing` 不会误报;
|
||||||
· **「在库但参数没录全」于是自动被拦住** —— 那一格回填出来是空的,红带点名、闸按不下。
|
· **「在库但参数没录全」于是自动被拦住** —— 那一格回填出来是空的,红带点名、闸按不下。
|
||||||
|
|
||||||
|
④ project sub_eval.case from once
|
||||||
|
eval_ref = {in:'evalRef'}
|
||||||
|
chip_type_id = lookup('mine:sub_eval.part' by role='original' take chip_type_id, else '')
|
||||||
|
gate_reason = when 链(**全读基座数**):
|
||||||
|
两颗 PN 有一格为空 → 「原 / 候选料号还没填」
|
||||||
|
sub_eval_part_exists_status_absent > 0 → 「<PN> 库里没有,请在下面建」
|
||||||
|
sub_eval_part_distinct_chip_type_id > 1 → 「两颗料类型不一致,换一颗或把类型改对」
|
||||||
|
parts_profile_missing + parts_parameter_missing > 0 → 「还差 n 格没填」
|
||||||
|
其余 → ''
|
||||||
|
↑ **这一笔必须排在②③之后,不许提前**(2026-08-29 走查实测):`gate_reason` 是**摆给人看的那句解释**,
|
||||||
|
而它引的 `parts_profile_missing` / `parts_parameter_missing` 要等②③把骨架行铺出来才有值。
|
||||||
|
排在前面时,引擎在②③写入**之前**给它读到 0 —— 卡照样正确发出(`card.when` 排在更后面,读到的是真缺口),
|
||||||
|
但卡上那句「还差什么」是**空白的**,恰在人最想要一句解释的时候。
|
||||||
|
**一笔读的是另一笔写出来的数,它就得排在那一笔后面。**
|
||||||
|
|
||||||
⑤ card 执行工单 · variant data · view 'input-supplement' when gate_reason != ''
|
⑤ card 执行工单 · variant data · view 'input-supplement' when gate_reason != ''
|
||||||
gateLedgers = [parts.chip_type, parts.type_param, parts.profile, parts.parameter]
|
gateLedgers = [parts.chip_type, parts.type_param, parts.profile, parts.parameter]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user