Archived
fix(w05): 两颗料不能是同一颗 —— 起单这一刻立墙,因为路只在这里
用户:「创建活动的启动参数里面不应该能选到同样的两个芯片」。 查下来这不只是没意义,是**把单子做死**:sub_eval.part 的主键是 eval_ref+internal_pn (role 不在主键里),S1 配方铸的两行撞成同一个主键、后一笔覆盖前一笔,两行收成一行 —— sub_eval_part_exists_status_found = 2 永不成立,S1 收不了步,而件上那两行人加不出来 (行源 mine:,没有「+加一行」),唯一出路是终止重开。与「两格留空」是同一条链。 平台加互斥声明 x-distinct(契约 distinctGroup)——与 x-link 正相反:那个是引导,这个是墙。 · 前端:别的格占着的候选这一格不列(自己填着的那个永远留着,否则 select 当场变空白), 并说清是谁占了哪个;走「新增」自己写一个同样的 → 小红字 + 启动按不下去; · 服务端 validateLaunchParams 独立拦(脚本 / API 绕不过),400 点名后填的那格; · 「算不算同一个」= 去空白 + 不分大小写(launchDistinctKey,前后端同一把尺)—— 只挡精确相等的话 lm2596s-5.0 照样进去,混一颗垃圾主数据出来。 W05 两格挂 x-distinct: 'part',2.14.0 已装库核过。 测:服务端 6 条 + 前端 8 条(含联动与互斥合起来的真形状)+ 包内 1 条,三处变异验证过; 四道门禁绿(2548 测)。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
This commit is contained in:
@@ -309,6 +309,20 @@ describe('契约', () => {
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
* 两格不能是同一颗料(2026-08-31 用户定:「不应该能选到同样的两个芯片」)—— 与联动不同,
|
||||
* 这一条**是墙**,且理由与上面「留空会卡死」那条是同一条链:同一个料号 = 同一个主键
|
||||
* (`eval_ref + internal_pn`,`role` 不在主键里),两行撞成一行,`exists_status_found = 2`
|
||||
* 永不成立,而件上那两行人加不出来 —— 唯一出路是终止重开。**墙立在起单这一刻,因为路只在这里。**
|
||||
*/
|
||||
it('两格互斥:同一颗料不能填两遍(x-distinct 同名 = 一组,服务端真拦)', () => {
|
||||
const props = manifest.contract.input.data['properties'] as Record<string, Record<string, unknown>>;
|
||||
for (const key of ['originalInternalPn', 'candidateInternalPn']) expect(props[key]?.['x-distinct']).toBe('part');
|
||||
/* 主键真是「案号 + 料号」——「同一个料号 = 同一个主键」这条链的第一环,它变了这道墙就该重新论证 */
|
||||
const part = manifest.declarations.ledger.find((l) => `${l.domain}.${l.object}` === 'sub_eval.part');
|
||||
expect(part?.fields.filter((f) => f.primaryKey).map((f) => f.name)).toEqual(['eval_ref', 'internal_pn']);
|
||||
});
|
||||
|
||||
it('零工具 —— 这是这次重写的立场,不是疏漏', () => {
|
||||
expect(manifest.contract.resources.tools).toEqual([]);
|
||||
expect(manifest.declarations.tools).toEqual([]);
|
||||
|
||||
@@ -54,7 +54,7 @@ export const manifest: ActivityManifest = {
|
||||
activityId: ACTIVITY_ID,
|
||||
name: 'ACT-WORK-05 · 差异评估',
|
||||
/* 重写不是改 —— 同版重装是 no-op(静默丢失,踩过) */
|
||||
packageVersion: '2.13.0',
|
||||
packageVersion: '2.14.0',
|
||||
category: '需求分析与方案匹配',
|
||||
sdkVersion: '0.1.0-m5',
|
||||
checksum: 'dev-checksum-part-substitution-assessment',
|
||||
@@ -96,7 +96,17 @@ export const manifest: ActivityManifest = {
|
||||
* 组内**先填的那格是锚**(摆全量),另一格只列同类型的料 + 库里未标类型的(殿后一组)+「新增」。
|
||||
* 锚没有类型、或锚填的是库里没有的新料号 → 不收窄(两颗都还没建档时不该拦着人)。
|
||||
* **这只是表单的引导,不是墙**:服务端照收两格不同类型的组合(`launch-params.ts` 头注),
|
||||
* 类型一致由 S1 的收步判据 `sub_eval_part_distinct_chip_type_id = 1` 管 —— 那才是数得出来的门。requestDescription / candidateInternalPns(数组)/
|
||||
* 类型一致由 S1 的收步判据 `sub_eval_part_distinct_chip_type_id = 1` 管 —— 那才是数得出来的门。
|
||||
*
|
||||
* **两格不能是同一颗料**(`x-distinct: 'part'`,2026-08-31 用户定:「不应该能选到同样的两个芯片」)——
|
||||
* 这一条**是墙**,不是引导,理由与上面「留空」那段是同一条链:两格同一个料号 → 上面那笔 `project`
|
||||
* 铸的两行撞上同一个主键(`eval_ref + internal_pn`,`role` 不在主键里)→ 后一笔覆盖前一笔 →
|
||||
* `sub_eval.part` 收成一行 → `sub_eval_part_exists_status_found = 2` 永不成立,S1 收不了步;
|
||||
* 而件上那两行人加不出来(块① 行源 `mine:parts.profile`,没有「+加一行」),**唯一出路是终止重开**。
|
||||
* 墙立在起单这一刻,是因为**路只在这里** —— 那时换一格就好了。运营端表单据此不把另一格已经选走的
|
||||
* 料号列出来;自己写一个同样的、或脚本 / API 直接起单,由服务端 `validateLaunchParams` 拒。
|
||||
*
|
||||
* requestDescription / candidateInternalPns(数组)/
|
||||
* datasheets 三键已随重写撤下 —— 这一版没有「需求主记录」「N 候选并行」「预填
|
||||
* datasheet」这几件事。
|
||||
*/
|
||||
@@ -113,6 +123,7 @@ export const manifest: ActivityManifest = {
|
||||
'x-options': { ledger: 'parts.profile', value: 'internal_pn', label: 'internal_pn', group: { column: 'chip_type_id', ledger: 'parts.chip_type', value: 'type_id', label: 'type_name' } },
|
||||
'x-order': 1,
|
||||
'x-link': 'chip-type',
|
||||
'x-distinct': 'part',
|
||||
},
|
||||
candidateInternalPn: {
|
||||
type: 'string',
|
||||
@@ -123,6 +134,7 @@ export const manifest: ActivityManifest = {
|
||||
'x-options': { ledger: 'parts.profile', value: 'internal_pn', label: 'internal_pn', group: { column: 'chip_type_id', ledger: 'parts.chip_type', value: 'type_id', label: 'type_name' } },
|
||||
'x-order': 2,
|
||||
'x-link': 'chip-type',
|
||||
'x-distinct': 'part',
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user