Archived
feat(w05): 案例模型换成四步 —— 零 guide、零工具、零记账旗
九步砍成四步:校验入参 / 差异分析 / 结论审核 / 落账放行。 三道入场哨兵全读基座数,caseFileModel 里一面记账旗都没有 —— 旗是活动自己写的数,而「机检只读基座数」这条在本仓被违反过六次。 审核与放行触达的是人:标人工激活、不给 doneWhen。 说明书瘦成「整单的事」,示例一律占位形 —— 模型会把示例当成这一单的值。 manualActivation 未照 brief 给的 planItem+definitionRef 写法(与本仓 cmmn-parse.ts 不兼容,会解析出错误的计划项 id):改用本仓既有的单元素写法 —— <humanTask id="..." manualActivation="true">,与 steps.test.ts 给定的 RED 测试、 E04/I01/旧九步 W05 的既有约定一致。 顺带恢复 Task 2 遗留的两条「Task 3 补回」skip(读写面 ⊆ 台账声明 / 工具 ⊆ 声明工具, 后者按零工具的新立场做了修正而非照抄旧断言);第三条(T_release judge criterion 逐字对应 acceptanceCriteria label)调查后判定为结构性不可恢复 —— 它检查的「guide 散文里嵌 judge criterion 给模型执行」这套机制随零 guide 重写整体撤掉,继续保留 skip 并订正注释说明原因。 四步重写让 activity.test.ts 的「案例模型与清单的对齐」组里 7 条既有(未 skip)断言 硬编码了旧九步结构,不改不可能 pnpm gates 绿:仍然成立的按新模型更新数字/名单 (四计划项 / 两处不给 doneWhen / 三段阶段);检查对象已被撤掉机制的转 skip 并写明 原因(P-08/P-10 双视图已合并进单一 S1_inputs;决策卡 JSON 骨架已从说明书散文挪进 配方的结构化 card 声明)。 Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
This commit is contained in:
@@ -12,12 +12,20 @@ import { createMockHost } from '@sdk';
|
||||
import { manifest, D } from '../src/manifest.ts';
|
||||
import activity from '../src/index.ts';
|
||||
|
||||
const ITEMS = ['S0_bind', 'S0d_p08_master', 'S0d_p10_document', 'S1_input_confirm', 'S2_normalize', 'S3_assess', 'S4_review', 'S5_prepare_landing', 'T_release'];
|
||||
/*
|
||||
* 2026-08-27 晚:两张数据工单改成**给 doneWhen**(只读入库事实)—— 引擎只在人答过卡之后求它,
|
||||
* 不再靠模型记得 finish。仍不给的三处:输入确认(交人补缺口)/ 审核循环 / 放行。
|
||||
* 2026-08-29 Task 3 整体重写(spec §4):九步砍成四步,案例模型换成 CMMN + `case-model.ts` 里的
|
||||
* `ASSESSMENT_STEPS` 四条剧本。这份包内自测原是照旧九步写的,`案例模型与清单的对齐` 这组的多数
|
||||
* 断言在结构上仍然成立(CMMN humanTask id 与剧本 item 一一对应、除放行外每项恰属一个阶段…),
|
||||
* 只是数字与名单要随新模型换 —— 下面这几处常量与断言标题已按 `case-model.ts` 的新四步同步更新。
|
||||
*/
|
||||
const NO_DONE_WHEN = new Set(['S1_input_confirm', 'S4_review', 'T_release']);
|
||||
const ITEMS = ['S1_inputs', 'S2_assess', 'S3_review', 'T_release'];
|
||||
/*
|
||||
* 2026-08-29 Task 3:四步里只有 `S3_review`(审核,可循环)与 `T_release`(放行)不给
|
||||
* `doneWhen`——判据不许摆在还欠一张卡的那一步眼前(2026-08-28 用户实测逼出的立墙,
|
||||
* `humanWrites`/`acceptanceChecklist` 同一课)。`S1_inputs` / `S2_assess` 全 auto,
|
||||
* 入库事实 / 分析结论一落地引擎就自己收步,不再需要人工激活等待。
|
||||
*/
|
||||
const NO_DONE_WHEN = new Set(['S3_review', 'T_release']);
|
||||
const VIEWS = ['p08-master-create', 'p10-document-create', 'eval-input-list', 'difference-review', 'landing-confirm'];
|
||||
/** 运营中心 L2 沙箱里那张关键台账数据看板 —— 不是工单件,只在「都声明了」这一条里出现;自己那组断言在文件尾 */
|
||||
const BOARD_VIEW = 'activity-ledger';
|
||||
@@ -222,35 +230,43 @@ describe('契约', () => {
|
||||
});
|
||||
|
||||
describe('案例模型与清单的对齐', () => {
|
||||
it('九个计划项,剧本 item 与 CMMN humanTask id 一一对应', () => {
|
||||
it('四个计划项,剧本 item 与 CMMN humanTask id 一一对应', () => {
|
||||
const cmmnIds = [...manifest.assets.businessModel.cmmnXml.matchAll(/<humanTask id="([^"]+)"/g)].map((m) => m[1] ?? '');
|
||||
expect(cmmnIds).toEqual(ITEMS);
|
||||
expect((manifest.assets.businessModel.steps as ReadonlyArray<{ item: string }>).map((s) => s.item)).toEqual(ITEMS);
|
||||
});
|
||||
|
||||
it('三处不给 doneWhen(输入确认 / 审核 / 放行),其余六处都给 —— 两张数据工单的只读入库事实', () => {
|
||||
it('两处不给 doneWhen(审核 / 放行),其余两处都给 —— 校验入参与逐项分析全 auto、入库/结论事实一落地就收步', () => {
|
||||
for (const s of manifest.assets.businessModel.steps as ReadonlyArray<{ item: string; doneWhen?: string }>) {
|
||||
if (NO_DONE_WHEN.has(s.item)) expect(s.doneWhen, s.item).toBeUndefined();
|
||||
else expect(s.doneWhen, s.item).toBeDefined();
|
||||
}
|
||||
});
|
||||
|
||||
it('两张数据工单件各自绑自己的 view(P-08 与 P-10 不共用同一份画面)', () => {
|
||||
/*
|
||||
* SKIP(2026-08-29,Task 3):`S0d_p08_master` / `S0d_p10_document` 两个计划项已随四步重写撤下 ——
|
||||
* 「补芯片主数据」与「补原厂技术资料」不再是两张各自的数据工单,统一并入 `S1_inputs`
|
||||
* (校验入参与补数据)一步之内。Task 3 的 brief 明写这一步不设 `view`(它是可选的,
|
||||
* Task 7–9 各自补上自己那一张),所以这条「两张数据工单件各自绑自己的 view」眼下没有对应的
|
||||
* 断言对象可钉 —— 不是「暂时还没做」,是这个二选一视图的设计前提本身已经不存在了。
|
||||
*/
|
||||
it.skip('两张数据工单件各自绑自己的 view(P-08 与 P-10 不共用同一份画面)', () => {
|
||||
const steps = manifest.assets.businessModel.steps as ReadonlyArray<{ item: string; view?: string }>;
|
||||
expect(steps.find((s) => s.item === 'S0d_p08_master')?.view).toBe('p08-master-create');
|
||||
expect(steps.find((s) => s.item === 'S0d_p10_document')?.view).toBe('p10-document-create');
|
||||
});
|
||||
|
||||
it('那五项在 CMMN 里都标了人工激活', () => {
|
||||
it('那两项在 CMMN 里都标了人工激活', () => {
|
||||
for (const id of NO_DONE_WHEN) {
|
||||
const block = new RegExp(`<humanTask id="${id}"[\\s\\S]*?</humanTask>`).exec(manifest.assets.businessModel.cmmnXml)?.[0] ?? '';
|
||||
expect(block, id).toContain('manualActivationRule');
|
||||
/* Task 3 起改用 `manualActivation="true"` 属性直接标在 humanTask 元素上(与 CMMN 解析器的两种认法之一同款),不再嵌套 <manualActivationRule> */
|
||||
expect(block, id).toContain('manualActivation="true"');
|
||||
}
|
||||
});
|
||||
|
||||
it('除放行外每一项恰好属于一个阶段;5 段 + 放行 = x/6,与文档 0.5/1/2/3/4/5 六步对齐', () => {
|
||||
it('除放行外每一项恰好属于一个阶段;3 段 + 放行 = x/4', () => {
|
||||
const phases = manifest.assets.businessModel.phases ?? [];
|
||||
expect(phases).toHaveLength(5);
|
||||
expect(phases).toHaveLength(3);
|
||||
const phaseItems = phases.flatMap((p) => p.items);
|
||||
expect([...phaseItems].sort()).toEqual([...ITEMS.filter((i) => i !== 'T_release')].sort());
|
||||
expect(new Set(phaseItems).size).toBe(phaseItems.length);
|
||||
@@ -261,7 +277,14 @@ describe('案例模型与清单的对齐', () => {
|
||||
for (const name of mentioned) expect(ITEMS, `说明书提到但不存在的计划项: ${name}`).toContain(name);
|
||||
});
|
||||
|
||||
it('说明书里只剩审核那一种决策卡(approve/reject/custom:);候选放弃/创建那张已退役 —— 缺库一律自动派数据工单(2026-08-27 用户定)', () => {
|
||||
/*
|
||||
* SKIP(2026-08-29,Task 3):这条测的是「决策卡骨架住在说明书的散文里,模型抄卡骨架时照读」——
|
||||
* 那正是**零 `guide`**重写要撤掉的机制本身(卡骨架挪进配方 `auto.do[].kind:'card'` 的结构化
|
||||
* `options` 字段,由引擎按声明发卡,不再靠模型从说明书里抄 JSON 片段)。新版 `NARRATIVE`
|
||||
* 因此不再嵌任何 `"value":"..."` 这类卡面 JSON —— 不是「还没写全」,是这条断言检查的机制
|
||||
* 在四步全 auto 的设计里已经不存在了(决策卡的选项由 Task 4–6 的配方声明,不由说明书文本决定)。
|
||||
*/
|
||||
it.skip('说明书里只剩审核那一种决策卡(approve/reject/custom:);候选放弃/创建那张已退役 —— 缺库一律自动派数据工单(2026-08-27 用户定)', () => {
|
||||
const n = manifest.assets.businessModel.narrative;
|
||||
expect(n).not.toContain('"value":"create"');
|
||||
expect(n).not.toContain('"value":"abandon"');
|
||||
@@ -271,10 +294,13 @@ describe('案例模型与清单的对齐', () => {
|
||||
});
|
||||
|
||||
/*
|
||||
* SKIP(2026-08-29,Task 2 →Task 3 补回):`contract.acceptanceCriteria` 已按 spec §7 整体重写,
|
||||
* 旧的九步 T_release 剧本(`case-model.ts`,本任务不动)引的还是旧的三条 L4 label
|
||||
* (「本单数据工单的创建记录」等旧措辞)。Task 3 整体重写四步案例模型时,新 T_release 会照新的
|
||||
* 两条 L4 判据重新引用,那时再放开这条断言。
|
||||
* SKIP(2026-08-29,Task 2 → Task 3 补回,复核后维持 skip):原计划这条断言的是
|
||||
* 「T_release 剧本里 `judge criterion="..."` 的原文逐字对得上 acceptanceCriteria 的 label」——
|
||||
* 而 Task 3 的四步重写是**全程零 guide**:`T_release` 的 `guide` 现在是 `''`,
|
||||
* 「prose guide 里嵌 `judge criterion="..."` 给模型执行」这套机制随零 guide 重写整体撤掉了
|
||||
* (裁量判据改由人工验收清单 `acceptanceChecklist` 让人亲自核,不再靠模型在 guide 里自判)。
|
||||
* 这不是「Task 3 会把断言点的字符串换成新的两条」——是断言检查的机制本身不复存在,
|
||||
* 无法在不改变检查对象的前提下让它变绿,继续保留跳过并记录清楚原因。
|
||||
*/
|
||||
it.skip('T_release 剧本里 judge criterion 的原文逐字对得上 acceptanceCriteria 的 label', () => {
|
||||
const tRelease = (manifest.assets.businessModel.steps as ReadonlyArray<{ item: string; guide?: string }>).find((s) => s.item === 'T_release');
|
||||
|
||||
Reference in New Issue
Block a user