Archived
Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7ed997187e |
@@ -2026,6 +2026,22 @@
|
||||
**副产**:e2e 样例 3「原PN缺库」的前提已被污染(`LM2596S-3.3` 现在真在库里,多半是白天 ops 起单
|
||||
落的主数据),那一例实际走的也是验收工单那条路 —— 名字与实测不符,清库存那件事记在这儿。
|
||||
|
||||
- **「类型不一致还能点下一步」的病根:确认闸条件在发卡装配被丢 —— 手写字段清单第四次丢值**
|
||||
(2026-09-01 用户:「两个芯片类型不一样,页面上方有红色提示,右边派发的卡片还可以点击下一步」):
|
||||
活动白纸黑字声明了 `gateWhen`(2026-08-31 加的确认闸条件档),而**发卡装配那段手写清单**
|
||||
(engines.ts 的 human 口 —— `variant` 上次被丢的同一段)逐项点名转交 `gateLedgers`/`variant`,
|
||||
没点 `gateWhen`/`gateWhenSay` 的名:落库工单载荷里它是 undefined(稳定库任务 43 法证),
|
||||
按钮禁用与服务端拒收读的都是它,**一起无声失效**;红带是视图画的所以照亮 ——
|
||||
屏上两处说着相反的话。此前 fields / blocks / redoable 三次同款,这次的教训:
|
||||
**中段是不可信卡骨架的缝,不能整包 spread,那就抽纯函数校验着转交并在 variant 的
|
||||
测试位旁边钉死**(`cardConditionGate`,5 测:转交原样 / 不发明键 / 脏值不端 /
|
||||
say 单独无意义 / when 可无 say)。**末端断言照 redoable 那课补上**:e2e w05 数据卡
|
||||
阶段 `expectCardGateWhen` —— 卡一到手查 desk 载荷,丢了当场判失败。
|
||||
活体验证(测试台真单):载荷带 `gateWhen` → detail 闸 `ready:false` 带活动那句话 →
|
||||
API 强行确认 **400**;e2e w05 案例 0 全绿(released、被拒 0、模型 2 次)。
|
||||
活动侧零改动(`GATE_OPEN_WHEN` 含类型不一致,mismatch 时发的必是带闸的数据卡;
|
||||
⑧ 验收卡的件只读、碰不上这形)。门禁 exit 0(2595 测)。
|
||||
|
||||
- **「终止活动」接口被蒸馏吊 13–45 秒到报错:收尾不等模型**(2026-09-01 用户:「点击终止后
|
||||
接口迟迟不返回,还会报错,但实例确实终止了」):法证在库里 —— 四单被终止的任务,
|
||||
`finished_at` 与蒸馏条目 `created_at` 差 13.2 / 36.3 / 43.4 / 44.6 秒:`finish` 把终态
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* **确认闸的条件档要在真发卡那条路上转交**(2026-09-01 用户实测:「两个芯片类型不一样,
|
||||
* 页面上方有红色提示,右边派发的卡片还可以点击下一步」)。
|
||||
*
|
||||
* 病:发卡装配那段手写清单逐项点名转交 `gateLedgers`/`variant`,而 `gateWhen`/`gateWhenSay`
|
||||
* 没被点名 —— 配方白纸黑字声明了「类型不一致不许确认」,落库的工单载荷里那两个字段是
|
||||
* undefined(任务 43 法证)。红带是视图画的所以照亮;按钮禁用与服务端拒收读的都是
|
||||
* 存下的 `order.gateWhen`,一起无声失效。**手写字段清单第四次丢值**(fields / blocks /
|
||||
* redoable 之后),而且丢在 `variant` 上次被丢的同一段。
|
||||
*
|
||||
* 这个缝取的是模型也会路过的不可信卡骨架,逐项校验转交是设计 —— 所以治法不是整包 spread,
|
||||
* 是把这两项的取用抽成纯函数、在 variant 的测试位旁边钉死。
|
||||
*/
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { cardConditionGate } from '../wiring/engines.ts';
|
||||
|
||||
describe('cardConditionGate —— 条件档从卡骨架到工单载荷', () => {
|
||||
it('声明了就转交,一个字不改', () => {
|
||||
expect(cardConditionGate({ gateWhen: 'parts_profile_distinct_chip_type_id <= 1', gateWhenSay: '两颗料不是同一个芯片类型' })).toEqual({
|
||||
gateWhen: 'parts_profile_distinct_chip_type_id <= 1',
|
||||
gateWhenSay: '两颗料不是同一个芯片类型',
|
||||
});
|
||||
});
|
||||
|
||||
it('没声明就什么都不带 —— 不发明键', () => {
|
||||
expect(cardConditionGate({})).toEqual({});
|
||||
expect(cardConditionGate({ gateLedgers: ['parts.profile'] })).toEqual({});
|
||||
});
|
||||
|
||||
it('脏值不端下去:非字符串 / 空白串一律丢', () => {
|
||||
expect(cardConditionGate({ gateWhen: 42, gateWhenSay: '话' })).toEqual({});
|
||||
expect(cardConditionGate({ gateWhen: ' ', gateWhenSay: '话' })).toEqual({});
|
||||
expect(cardConditionGate({ gateWhen: null })).toEqual({});
|
||||
});
|
||||
|
||||
it('只有那句话没有条件 = 什么都不带(say 单独存在没有意义,评估端只认 when)', () => {
|
||||
expect(cardConditionGate({ gateWhenSay: '两颗料不是同一个芯片类型' })).toEqual({});
|
||||
});
|
||||
|
||||
it('条件在、话没写:条件照转交,拒回用兜底话术', () => {
|
||||
expect(cardConditionGate({ gateWhen: 'a > 1' })).toEqual({ gateWhen: 'a > 1' });
|
||||
expect(cardConditionGate({ gateWhen: 'a > 1', gateWhenSay: '' })).toEqual({ gateWhen: 'a > 1' });
|
||||
});
|
||||
});
|
||||
@@ -279,6 +279,24 @@ export function executionCardVariant(fromCard: unknown, fromStep: unknown): 'dat
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* **确认闸的条件档从卡骨架到工单载荷**(2026-09-01 用户实测:「两个芯片类型不一样…
|
||||
* 右边派发的卡片还可以点击下一步」)。配方声明了 `gateWhen`/`gateWhenSay`,发卡装配的
|
||||
* 手写清单没点它们的名 —— 落库的工单载荷里两个字段是 undefined,按钮禁用与服务端拒收
|
||||
* 读的都是它,一起无声失效(**手写字段清单第四次丢值**,且丢在 `variant` 上次被丢的同一段)。
|
||||
* 这个缝取的是模型也会路过的不可信卡骨架,不能整包 spread —— 校验着转交:
|
||||
* 条件必须是非空字符串;那句话只在有条件时才有意义(评估端只认 `when`)。
|
||||
*/
|
||||
export function cardConditionGate(card: Readonly<Record<string, unknown>>): { gateWhen?: string; gateWhenSay?: string } {
|
||||
const when = card['gateWhen'];
|
||||
if (typeof when !== 'string' || when.trim() === '') return {};
|
||||
const say = card['gateWhenSay'];
|
||||
return {
|
||||
gateWhen: when,
|
||||
...(typeof say === 'string' && say.trim() !== '' ? { gateWhenSay: say } : {}),
|
||||
};
|
||||
}
|
||||
|
||||
export function decisionCardFace(
|
||||
input: { readonly variant?: 'review' | undefined; readonly checklist?: ReadonlyArray<string> | undefined },
|
||||
step: { readonly cardVariant?: string | undefined; readonly acceptanceChecklist?: ReadonlyArray<string> | undefined } | undefined,
|
||||
@@ -1974,6 +1992,8 @@ export function wireEngines(deps: EngineWiringDeps): EngineWiring {
|
||||
...(blocks === undefined ? {} : { blocks: blocks as ExecutionWorkOrderDraft['blocks'] }),
|
||||
...(gateLedgers.length === 0 ? {} : { gateLedgers }),
|
||||
...(variant === undefined ? {} : { variant }),
|
||||
/* 条件档(gateWhen/gateWhenSay)—— 校验着转交,见 cardConditionGate 的账 */
|
||||
...cardConditionGate(input.card),
|
||||
});
|
||||
// 打扰率的计量对象:每发一张卡就是调了一次人 —— 不计就等于没有上限
|
||||
await taskStore.addConsumption(input.taskId, { humanCalls: 1 });
|
||||
|
||||
@@ -615,6 +615,13 @@ const SUITES = {
|
||||
rowKey: 'internal_pn',
|
||||
blankCol: 'brand_name',
|
||||
expectGateBlock: true,
|
||||
/*
|
||||
* **确认闸的条件档必须跟到工单载荷上**(2026-09-01 用户实测:「两个芯片类型不一样…
|
||||
* 卡片还可以点击下一步」)。配方声明了 `gateWhen`,发卡装配的手写清单没点它的名 ——
|
||||
* 落库载荷里是 undefined,按钮禁用与服务端拒收一起无声失效(手写字段清单第四次丢值,
|
||||
* 与 variant 上次被丢的是同一段)。这类丢值只有末端断言拦得住:卡一到手就查载荷。
|
||||
*/
|
||||
expectCardGateWhen: true,
|
||||
edits: [],
|
||||
extraTables: [
|
||||
/*
|
||||
@@ -1340,6 +1347,9 @@ async function runCase(suite, kase) {
|
||||
let fileCheck;
|
||||
let gateLeaked = false;
|
||||
const gateChecked = new Set();
|
||||
/** 确认闸的条件档(gateWhen)没跟到工单载荷上 —— 类型不一致将拦不住(末端断言,见 w05 数据卡阶段) */
|
||||
let gateWhenMissing = false;
|
||||
let gateWhenChecked = false;
|
||||
let decisions = 0;
|
||||
missedRows.clear();
|
||||
asked.length = 0;
|
||||
@@ -1540,6 +1550,15 @@ async function runCase(suite, kase) {
|
||||
: ` ⚠️ 缺着必填还放过去了:提交闸失效`,
|
||||
);
|
||||
}
|
||||
if (stage.expectCardGateWhen === true && !gateWhenChecked) {
|
||||
gateWhenChecked = true;
|
||||
const { body: det } = await api(`/api/desk/tasks/${taskId}`);
|
||||
const wo = (det?.workOrders ?? []).find((o) => o.id === card.id);
|
||||
if (wo?.gateWhen === undefined) {
|
||||
gateWhenMissing = true;
|
||||
console.log(' ⚠️ 确认闸的条件档(gateWhen)没跟到工单载荷上 —— 类型不一致将拦不住,判失败');
|
||||
} else console.log(' 确认闸条件已随卡落库(gateWhen 在载荷上)');
|
||||
}
|
||||
/*
|
||||
* **两阶段自定义填表**(w05「候选缺库·新建类型」专用)—— 在空手交卷的闸测过**之后**、
|
||||
* 常规 `buildEdits` 之前跑一次:先铸 `parts.chip_type` 的自增 `type_id`,读回来才知道
|
||||
@@ -1675,6 +1694,10 @@ async function runCase(suite, kase) {
|
||||
console.log(' ⚠️ 数据工单确认即入库那道门没兑现 —— 判失败');
|
||||
ok = false;
|
||||
}
|
||||
if (gateWhenMissing) {
|
||||
console.log(' ⚠️ 确认闸条件(gateWhen)被链上丢掉 —— 判失败');
|
||||
ok = false;
|
||||
}
|
||||
// 「超限才叫人」是 A4 的要害:该叫的那一单没叫,等于底价门禁是摆设
|
||||
if (missedRows.size > 0) {
|
||||
console.log(` ⚠️ 案例点名要填的行,整例跑完也没在件上出现过(${missedRows.size} 处:${[...missedRows].slice(0, 3).join('、')}…)—— 判失败`);
|
||||
|
||||
Reference in New Issue
Block a user