Archived
fix(w05): 验收工单的面孔在装配层被丢掉 —— 两头都有测,中间那一段把值扔了
用户实测:「你怎么给我发成了执行工单,我需要的是验收工单,然后标题那一块需要是 验收卡的那种绿色」。 一、面孔:engines.ts 发执行工单那一处是一句写死只认 'data' 的三目,配方递下来的 'accept' 静默丢掉 —— 对话区照旧摆「执行工单」。**配方那一头有测(variant 原样递出去)、 前端那一头有测(accept 该穿哪副面孔)、e2e 按标题驱动也全绿,唯独中间没有。** 修:抽成纯函数 executionCardVariant(与旁边 decisionCardFace 同一种做法、同一个测试位), 认 data / accept、拒 review、认不出的当没写;4 测变异验证过。 e2e 同批改**认面孔不认标题**(试跑观测面的 cards 补 variant,契约变更)—— 标题是活动自己写的字符串,卡穿哪副面孔由装配层决定,那一次正是两者对不上。 二、颜色:件① 验收工单那一副整套强调色换成验收绿 #0aa294(令牌从 ACCENT_LEDGER 现改选择器得来,与件②③、对话区验收卡一处真源),题头那条写死的浅蓝渐变单独给一条绿的; 数据工单那一副仍是蓝。真渲染核过两副 class 与两套令牌。 验收:e2e w05 5/5 released、被拒 0(面孔断言这一轮真在跑);2563 测、四门禁绿; 2.16.0 装库。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
This commit is contained in:
@@ -0,0 +1,37 @@
|
||||
/**
|
||||
* **执行工单的面孔在装配层这一处定**(2026-08-31,用户实测:「你怎么给我发成了执行工单,
|
||||
* 我需要的是验收工单」)。
|
||||
*
|
||||
* 病:配方递下来 `variant: 'accept'`(验收工单 —— 件只读、人只确认),而装配层这一处
|
||||
* 是一句写死只认 `'data'` 的三目,别的值**静默丢掉** —— 对话区照旧摆「执行工单」。
|
||||
*
|
||||
* 更值得记的是**两头都有测,唯独中间没有**:配方那一头断言了「variant 原样递出去」,
|
||||
* 前端那一头断言了「accept 该穿哪副面孔」,e2e 按卡的**标题**驱动也照样绿 ——
|
||||
* 三处都对,而它们中间这一段把值扔了。**面孔要在真发卡那条路上断言。**
|
||||
*/
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { executionCardVariant } from '../wiring/engines.ts';
|
||||
|
||||
describe('执行工单的两副变体面孔', () => {
|
||||
it('data 数据工单 / accept 验收工单,两个都认', () => {
|
||||
expect(executionCardVariant('data', undefined)).toBe('data');
|
||||
expect(executionCardVariant('accept', undefined)).toBe('accept');
|
||||
});
|
||||
|
||||
it('剧本声明优先于卡骨架 —— 模型抄卡会把 variant 抄丢(2026-08-27 实测)', () => {
|
||||
expect(executionCardVariant(undefined, 'data')).toBe('data');
|
||||
expect(executionCardVariant('data', 'accept')).toBe('accept');
|
||||
});
|
||||
|
||||
it('`review` 是决策卡那一路的面孔,不许串到执行工单上', () => {
|
||||
expect(executionCardVariant('review', undefined)).toBeUndefined();
|
||||
expect(executionCardVariant(undefined, 'review')).toBeUndefined();
|
||||
});
|
||||
|
||||
it('没写 / 认不出的值:普通执行工单,不把脏东西端下去', () => {
|
||||
expect(executionCardVariant(undefined, undefined)).toBeUndefined();
|
||||
expect(executionCardVariant('', undefined)).toBeUndefined();
|
||||
expect(executionCardVariant({ variant: 'accept' }, undefined)).toBeUndefined();
|
||||
expect(executionCardVariant(42, undefined)).toBeUndefined();
|
||||
});
|
||||
});
|
||||
@@ -712,6 +712,7 @@ export function registerGovernanceOpsRoutes(app: Hono<AppEnv>, container: Contai
|
||||
cards: orders.map((o) => ({
|
||||
id: o.id,
|
||||
mode: o.mode,
|
||||
...(o.mode === 'execution' && o.variant !== undefined ? { variant: o.variant } : {}),
|
||||
title: o.title,
|
||||
done: o.done !== undefined,
|
||||
...(o.done?.result === undefined ? {} : { result: String(o.done.result) }),
|
||||
|
||||
@@ -242,6 +242,27 @@ export function createOnlyViolation(
|
||||
* 而 `checkChatCardReply` 又要求 `checked ⊇ checklist`:卡按不下去。**只在 `reviewFace` 为真时**
|
||||
* 才退回剧本声明的清单 —— 非审核面孔的卡,清单就是没有,不发明一条按不下去的。
|
||||
*/
|
||||
/**
|
||||
* **执行工单的面孔** —— 两副变体:`data` 数据工单(件上的表就是要建的记录,确认即入库)/
|
||||
* `accept` 验收工单(件只读,人只核对确认)。`review` 是决策卡那一路的面孔,不许串到这儿来;
|
||||
* 认不出的值一律当没写(普通执行工单),不把脏东西端下去。
|
||||
*
|
||||
* **剧本声明(`PlanStep.cardVariant`)优先于卡骨架**:模型抄卡时会把 `variant` 抄丢
|
||||
* (2026-08-27 实测:同一张卡 gateLedgers 抄到了、variant 没有)。但卡自己带的值同样作数 ——
|
||||
* 配方那一路没有模型可抄丢,而**一个步骤里两笔条件互斥的 card**(缺东西派数据工单 /
|
||||
* 都齐了派验收工单,2026-08-31)本来就不可能由一个 step 级的 `cardVariant` 说清。
|
||||
*
|
||||
* **这一处此前是内联的三目,写死只认 `'data'`**(2026-08-31 用户实测:「你怎么给我发成了
|
||||
* 执行工单」)—— 配方递下来的 `accept` 在这儿被静默丢掉,对话区照旧摆「执行工单」。
|
||||
* 配方那一头与前端那一头都有测,唯独**真发卡这条路**上没有:面孔要在这里断言。
|
||||
*/
|
||||
export function executionCardVariant(fromCard: unknown, fromStep: unknown): 'data' | 'accept' | undefined {
|
||||
for (const value of [fromStep, fromCard]) {
|
||||
if (value === 'data' || value === 'accept') return value;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function decisionCardFace(
|
||||
input: { readonly variant?: 'review' | undefined; readonly checklist?: ReadonlyArray<string> | undefined },
|
||||
step: { readonly cardVariant?: string | undefined; readonly acceptanceChecklist?: ReadonlyArray<string> | undefined } | undefined,
|
||||
@@ -1913,8 +1934,7 @@ export function wireEngines(deps: EngineWiringDeps): EngineWiring {
|
||||
: (await deps.registry.manifestOf((await taskContext.of(input.taskId)).activityId)).assets.businessModel.steps?.find(
|
||||
(s) => s.item === input.itemId,
|
||||
)?.cardVariant;
|
||||
// 执行工单这一路只认 data(review 是决策卡那一路的面孔)
|
||||
const variant = stepVariant === 'data' || input.card['variant'] === 'data' ? ('data' as const) : undefined;
|
||||
const variant = executionCardVariant(input.card['variant'], stepVariant);
|
||||
const issued = await deps.humanTool.issueExecution(context, {
|
||||
title,
|
||||
basis: basis.length > 0 ? basis : [{ k: '来源', v: '案例模型当下局面' }],
|
||||
|
||||
Reference in New Issue
Block a user