Archived
feat(w05): 数据齐了也叫人一次 —— S1 改派只读的验收工单,件同一份、编辑钮收起
用户:「就算数据是足的也进入这个数据工单,就派发一个验收工单,界面和数据要和现在的 第一个数据工单一致,只不过把芯片卡片上的编辑按钮去掉,只展示不能编辑,然后把标题旁边的 数据工单改成验收工单」。 病根在引擎拍首那道 doneWhen 扫描:输入本来就齐的单,S1 的 doneWhen 第一拍就为真, 配方一笔都还没跑,这一步当场被收掉 —— 卡永远发不出去,人一眼没看过就进了 S2。 治法:CMMN 给 S1 标 manualActivation,那道扫描多一个门槛(worldTouched),次序变成 「配方发卡 → 人答 → 下一拍 doneWhen 为真才收」;doneWhen 仍是真门,只是不抢在人前面。 平台:执行工单第三副面孔 variant:'accept'(件只读、人只确认「确认无误」)—— 与 mode:'acceptance'(submit 抬起来的收口验收,带打回重做)分清;三副面孔的判断 抽成纯函数 order-face.ts(有测),chat-bubbles 只摆。 活动:S1 两笔互斥的 card(carded 幂等保证一步只发一张)+ 案卷粘着的旗 order_kind; 一张件两副面孔 —— 题头/标题/页脚三处名字与卡角编辑钮按 v-data / v-accept 由样式表挑 (藏的是容器 .fabs,逐枚去盖打不完)。 测:引擎测钉死那一对(标了人工激活 → 卡发得出去、步不收;没标 → 步当场被收、卡发不出); auto-runner variant 透传;order-face 4 条;包内 2 条(两笔卡 + 粘旗)、view 1 条; 两处变异验证。e2e w05 5/5 released、被拒 0、模型调用恰 1 次 —— 都在库那例摆的正是验收工单。 2558 测、四门禁绿;2.15.0 装库核过。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
This commit is contained in:
@@ -146,13 +146,47 @@ describe('S1 配方', () => {
|
||||
* 变成空字符串)见 `apps/api/src/modules/loop-engine/__tests__/w05-gate-reason-order.test.ts`
|
||||
* ——这份文件只做结构断言,不跑引擎(活动包不许 import apps/*)。
|
||||
*/
|
||||
it('六笔,次序是:两颗料 → 主数据骨架 → 参数骨架 → 案卷 → 卡 → 交代(类型字典/字段清单两笔自投影已随「只选不建」退役)', () => {
|
||||
expect(kinds).toEqual(['project', 'project', 'project', 'project', 'card', 'say']);
|
||||
it('七笔,次序是:两颗料 → 主数据骨架 → 参数骨架 → 案卷 → 数据工单 → 验收工单 → 交代', () => {
|
||||
expect(kinds).toEqual(['project', 'project', 'project', 'project', 'card', 'card', 'say']);
|
||||
expect(acts.map((a) => (a.kind === 'project' ? a.into : undefined)).filter(Boolean)).toEqual([
|
||||
'sub_eval.part', 'parts.profile', 'parts.parameter', 'sub_eval.case',
|
||||
]);
|
||||
});
|
||||
|
||||
/*
|
||||
* **数据齐了也叫人一次**(2026-08-31 用户定:「就算数据是足的也进入这个数据工单,就派发一个
|
||||
* 验收工单…把芯片卡片上的编辑按钮去掉,只展示不能编辑」)。两张卡是互斥的两条路,不是先后:
|
||||
* 引擎的 `carded` 幂等保证一步只发一张 —— 数据工单发过之后,验收工单这一笔永远轮不到
|
||||
* (补完数据不会再被叫第二次)。
|
||||
*/
|
||||
it('两张卡:缺东西派数据工单(读闸)· 都齐了派只读验收工单(读上一笔刚写下的粘旗)', () => {
|
||||
const cards = acts.filter((a) => a.kind === 'card');
|
||||
expect(cards.map((c) => (c.kind === 'card' ? c.variant : undefined))).toEqual(['data', 'accept']);
|
||||
/* 验收工单不重算一遍闸 —— 读的是案卷刚写下的旗,同一件事只许有一处判定 */
|
||||
expect(cards[1]?.kind === 'card' && cards[1].when).toBe('sub_eval_case_order_kind_accept > 0');
|
||||
/* 两张都是执行工单(验收工单是它的变体,不是第三种 mode);零输入,填报/核对都在件上 */
|
||||
for (const c of cards) expect(c.kind === 'card' && c.as).toBe('execution');
|
||||
/* 闸同一份:件只读也要在确认那一刻再数一遍「数据是齐的」 */
|
||||
for (const c of cards) expect(c.kind === 'card' && c.gateLedgers).toEqual(['parts.profile', 'parts.parameter']);
|
||||
});
|
||||
|
||||
/*
|
||||
* 旗**粘着**:第一档读的是上一拍写下的自己(tally 读数)。不粘着的后果实打实 ——
|
||||
* 人在数据工单上把最后一格填上、还没点确认,闸当场变 clear,件的题头会当场改名叫
|
||||
* 「验收工单」、卡角的笔也没了,而他手里那张卡还开着。
|
||||
*/
|
||||
it('order_kind 粘着:已经是 data 就一直是 data,否则按此刻的闸决定(与发卡条件同一句)', () => {
|
||||
const caseAct = acts.find((a) => a.kind === 'project' && a.into === 'sub_eval.case');
|
||||
const kind = caseAct?.kind === 'project' ? caseAct.fields['order_kind'] : undefined;
|
||||
const gate = acts[4]?.kind === 'card' ? acts[4].when : undefined;
|
||||
expect(kind).toEqual({
|
||||
when: 'sub_eval_case_order_kind_data > 0',
|
||||
then: 'data',
|
||||
/* 第二档与数据工单那张卡读的是同一句闸(一处真源) */
|
||||
else: { when: gate, then: 'data', else: 'accept' },
|
||||
});
|
||||
});
|
||||
|
||||
/*
|
||||
* 2026-08-30,Ruling H35:`parts.chip_type`/`parts.type_param` 各自把「选中类型的那一行」
|
||||
* 原样投一遍(值不变,幂等)——目的不是产出新数据,是让 `mine:` 这两张表不再天然为零行,
|
||||
|
||||
Reference in New Issue
Block a user