This repository has been archived on 2026-09-13. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
BPOS-TMP-REPO/activities/part-substitution-assessment/src/manifest.ts
T
xcsandClaude Opus 5 d244864317 feat(w05): 清单重写 —— 九张台账、两个启动参数、零工具
台账:两张类型字典 + P-08 主/参数(撤 createOnly、封装工艺归字典)+ 案卷两张 + P-11 主/明细 + P-06。
契约:启动只剩原 PN 与候选 PN 两格且都选填(缺了由第一步派工单补);tools 清空 —— 这是立场不是疏漏。
判据全读基座数;明细加合成列 judgement_class,因为「硬约束不符有几条」不是单列 tally 数得出来的。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01LKMZDwMbyKzjw6Hembwvet
2026-08-29 12:39:45 +08:00

512 lines
31 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 活动包清单 —— ACT-WORK-05 差异评估(案例活动)。
*
* **2026-08-29 整体重写(@2.0.0)**:从「九步、两枚工具、全程 agent 驱动」改成「四步、零工具、
* 零 `guide`、AI 出场恰好一次」。设计权威:
* `docs/superpowers/specs/2026-08-29-act-work-05-rewrite-design.md`(下称「spec」)。
* 用户原话立的场:「不是把所有东西都丢给 ai 来处理…一定是系统先确定性的从数据库中取出数据后交给
* ai 分析」——`docs/ACT-WORK-05-端到端测试记录.md` 的 A–AE 发现表里,八条事故都落在
* 「本来就该是确定的」那几步(编号抄别单、判在库判错、数据工单派给在库的料…),
* 真正需要判断的只有一件事:**这一条参数,候选跟原厂比算不算事**。
*
* 这份清单是 Task 2 的产物,只动 `declarations.ledger` 与 `contract` 两段,以及 `assets`
* 里已经不自洽的那几处(spec §8 的退役清单前移到这一步,见「计划裁定 G3」)。**案例模型
* (`case-model.ts`)还是旧的九步、旧的 `guide` 文本** —— 下一个任务(Task 3)才整体重写成
* spec §4 的四步(`S1_inputs` / `S2_assess` / `S3_review` / `T_release`)+ 四道哨兵 + 零 `guide`
* (行为改由 `PlanStep.auto` 声明式配方接管)。旧剧本引用本次删掉的台账地址而导致的包内自测红,
* 已按台账逐条 `it.skip` 并注明「Task 3 会补回」,不删测试(§12.5 铁律)。
*
* ## 九张台账声明(spec §3)
* 两张新字典(`parts.chip_type` / `parts.type_param`,Task 1 已物化 + 播种)承接「约束类型按类型
* 标一次」;P-08 主记录 `parts.profile` 撤 `createOnly`(在库老料要能补上 `chip_type_id` 这一格)、
* 封装与工艺退休(它们本来就是「核心参数」,该以类型字段的身份出现在字典里);P-08 子表
* `parts.parameter` 撤 `constraint_type` 与参数名自指引用(名字对不对由 S1 配方铺格子这件事本身
* 保证,不必再靠一堵测三次都没拦住的墙)。原来的三张单据(`pn_check` / `input_gap` / `verdict`)
* 由两张顶掉:`sub_eval.part`(**一单恰两行** —— 配方 `each` 遍历「哪几颗料要建」的唯一数据源,
* 拆成两行的理由见 spec §3.3「为什么非拆成两张不可」)与 `sub_eval.case`(一单一行的案卷,
* 挂入参未就绪的原因与结论摘要)。P-11 明细加合成列 `judgement_class`(约束类型 × 四态的合成,
* 因为「硬约束不符有几条」不是任何单列 `tally` 数得出来的数)。P-01 需求主记录 / P-10 原厂资料 /
* 客户档案**本活动不碰**(它们的存在性核对与录入不再是这个活动的事)。
*
* ## 契约(spec §4.1/§4.5/§7)
* 启动只剩 `originalInternalPn` / `candidateInternalPn` 两格(单数,一次评估恰一对一候选),
* 都选填 —— 缺了由第一步的配方派数据工单补。零工具:`contract.resources.tools` 与
* `declarations.tools` 都是 `[]`,这是这次重写的立场,不是疏漏(四态改 S2 唯一一次 `analyze`
* 判定,推荐等级改配方按 spec §3.5 的规则算)。判据全部改读基座数(`域_对象_rows` / `_missing` /
* `_distinct_列` / tally 计数),没有一条读活动自己写的汇总列。
*/
import type { ActivityManifest } from '@contracts';
import { activityIdSchema } from '@contracts';
import { CMMN_XML, NARRATIVE, ASSESSMENT_PHASES, ASSESSMENT_STEPS } from './case-model.ts';
import { LEDGER_BOARD, LEDGER_BOARD_DATA } from './views/ledger-board.ts';
import { ACTIVITY_ID_TEXT, D } from './constants.ts';
export { D, RULE_VERSION } from './constants.ts';
const ACTIVITY_ID = activityIdSchema.parse(ACTIVITY_ID_TEXT);
/** 字段声明的短写(与 E04 同一套写法:显式 primaryKey / masked,其余按需) */
type F = { name: string; type: 'text' | 'number' | 'integer' | 'boolean' | 'date' | 'timestamp' | 'json'; label: string; primaryKey?: boolean; required?: boolean; expect?: boolean; tally?: string[]; auto?: boolean; distinct?: boolean; refersTo?: string; requiredWhen?: { column: string; value: string } };
const col = (f: F) => ({ primaryKey: false, masked: false, ...f });
export const manifest: ActivityManifest = {
identity: {
activityId: ACTIVITY_ID,
name: 'ACT-WORK-05 · 差异评估',
/* 重写不是改 —— 同版重装是 no-op(静默丢失,踩过) */
packageVersion: '2.0.0',
category: '需求分析与方案匹配',
sdkVersion: '0.1.0-m5',
checksum: 'dev-checksum-part-substitution-assessment',
},
/* ── 契约七件 ────────────────────────────────────────────────── */
contract: {
activityId: ACTIVITY_ID,
version: '1.0.0',
input: {
/*
* 两格,都选填(spec §4.1):库里有就选,没有就自己写一个新的 —— 启动后由第一步的
* 配方核对存在性、缺了就派数据工单补齐。运营端启动表单渲染这两格为
* 「选择 + 新增」下拉(`x-control: combo`),候选从 `parts.profile.internal_pn`
* 现读(`x-options`);`x-order` 定表单次序(清单存在 jsonb 里,书写顺序到不了运营端)。
* requestDescription / candidateInternalPns(数组)/ datasheets 三键已随重写撤下 ——
* 这一版没有「需求主记录」「N 候选并行」「预填 datasheet」这几件事。
*/
data: {
type: 'object',
required: [],
properties: {
originalInternalPn: {
type: 'string',
title: '原内部料号',
description: '差异评估基准料号;库里有就选,没有就自己写一个新的,启动后由第一步派数据工单补齐。',
examples: ['LM2596S-5.0'],
'x-control': 'combo',
'x-options': { ledger: 'parts.profile', value: 'internal_pn', label: 'internal_pn' },
'x-order': 1,
},
candidateInternalPn: {
type: 'string',
title: '候选内部料号',
description: '被评估的候选料号;库里有就选,没有就自己写一个新的,启动后由第一步派数据工单补齐。',
examples: ['XL2596S-5.0'],
'x-control': 'combo',
'x-options': { ledger: 'parts.profile', value: 'internal_pn', label: 'internal_pn' },
'x-order': 2,
},
},
},
messageAllowed: true,
messageHint: 'FAE 可在此说明客户的应用边界或验证条件',
},
output: {
/* 单一必发口:签下去 P-11 落账、P-06 落账;载荷是已落地的事实,不是待办 */
mandatory: [
{
name: 'assessment-released',
description: '差异评估结论已落账(P-11 替代关系主记录 + 差异明细、P-06 验证记录)—— 载荷即已落地的事实',
payload: {
type: 'object',
required: ['evalRef', 'relationId', 'originalPn', 'candidatePn', 'recommendationLevel', 'matchTotal', 'mismatchTotal', 'unknownTotal', 'conditionalTotal', 'validationId'],
properties: {
evalRef: { type: 'string', title: '评估案号' },
relationId: { type: 'string', title: '替代关系ID' },
originalPn: { type: 'string', title: '原内部料号' },
candidatePn: { type: 'string', title: '候选内部料号' },
recommendationLevel: { type: 'string', title: '推荐等级' },
matchTotal: { type: 'integer', title: 'MATCH 条数' },
mismatchTotal: { type: 'integer', title: 'MISMATCH 条数' },
unknownTotal: { type: 'integer', title: 'UNKNOWN 条数' },
conditionalTotal: { type: 'integer', title: 'CONDITIONAL 条数' },
validationId: { type: 'string', title: '关联验证ID' },
},
},
},
],
selective: [],
},
/* 一份成果常不止一张表:差异评估结论由明细 + 关系两张共同承载,落账内容由关系 + 验证记录承载 */
requiredDeliverables: [
{ key: 'difference-items', label: '差异评估结论', ledger: 'substitution.difference_item', ledgers: ['substitution.difference_item', 'substitution.relation'], editableAtRelease: [] },
{ key: 'landing', label: '落账内容', ledger: 'substitution.relation', ledgers: ['substitution.relation', 'validation.record'], editableAtRelease: [] },
],
/*
* 验收判据(spec §7)—— 五条机检 L1/L2 全读基座数,两条 L4 裁量,一条 L5 责任关(不上卡)。
* `input-ready` 的谓词与 S1(Task 3 待写)的 `doneWhen` 同构:两颗都在库、类型一致、参数不缺 ——
* **不写「参数行数 = 字段数×2」**,那不是基座数得出来的数(`parts_type_param_rows` 数的是
* 本单写下的字段行,不是整本字典;给判据编一个数不出来的数,是这个仓踩过六次的同一个坑)。
*/
acceptanceCriteria: [
{
key: 'input-ready',
label: '评估输入已就绪:原 PN 与候选都在库、归了同一个芯片类型、主数据与参数值都不缺必填',
level: 'L1',
predicate:
'sub_eval_part_exists_status_found = 2 and sub_eval_part_missing = 0 and sub_eval_part_distinct_chip_type_id = 1 and ' +
'parts_profile_missing = 0 and parts_parameter_missing = 0',
},
{
key: 'every-param-judged',
label: '每条核心参数都有明确状态:每条差异明细都是 MATCH / MISMATCH / UNKNOWN / CONDITIONAL 之一,没有一条缺必填',
level: 'L2',
predicate:
'substitution_difference_item_missing = 0 and ' +
'substitution_difference_item_difference_status_match + substitution_difference_item_difference_status_mismatch + ' +
'substitution_difference_item_difference_status_unknown + substitution_difference_item_difference_status_conditional = substitution_difference_item_rows',
},
{
key: 'level-by-rule',
/* §3.5 的规则原样译成析取式:推荐等级只有一种取值能配上当前的 judgement_class 分布,规则说了算不是话术说了算 */
label: '推荐等级与判定分类一致:有硬约束不符的候选不能是「推荐」,等级由规则算,不由措辞改判',
level: 'L2',
predicate:
'(substitution_relation_recommendation_level_not_recommended = 1 and substitution_difference_item_judgement_class_hard_mismatch > 0) or ' +
'(substitution_relation_recommendation_level_conditional = 1 and substitution_difference_item_judgement_class_hard_mismatch = 0 and ' +
'(substitution_difference_item_judgement_class_unknown > 0 or substitution_difference_item_judgement_class_conditional > 0 or substitution_difference_item_judgement_class_soft_mismatch > 0)) or ' +
'(substitution_relation_recommendation_level_recommended = 1 and substitution_difference_item_judgement_class_hard_mismatch = 0 and ' +
'substitution_difference_item_judgement_class_unknown = 0 and substitution_difference_item_judgement_class_conditional = 0 and substitution_difference_item_judgement_class_soft_mismatch = 0)',
},
{
key: 'unknown-has-disposition',
label: '每个 UNKNOWN 都有去向:去向、影响说明、判断依据没有一条缺',
level: 'L2',
predicate: 'substitution_difference_item_missing = 0',
},
{
key: 'validation-landed',
label: '验证记录已落账:P-06 恰有一行且不缺必填(全推荐也要写「本轮无待验项」)',
level: 'L2',
predicate: 'validation_record_rows = 1 and validation_record_missing = 0',
},
{ key: 'evidence-credible', label: '证据链可信:每条差异的影响说明与判断依据站得住', level: 'L4' },
{ key: 'values-traceable', label: '参数值与原厂资料对得上:候选与原 PN 的取值来源可追溯', level: 'L4' },
/* L5 是责任关:那张卡本身就是这道关,卡面上不摆它(基座统一滤) */
{ key: 'gate03-release', label: 'ACT-GATE-03 评审放行:签下去 P-11 落账、P-06 落账,结论供下游消费', level: 'L5' },
],
revisableAtRelease: [],
prohibitions: [
{ key: 'no-fabricated-parameter', statement: 'UNKNOWN 是一等公民:查不到的参数值必须显式写「未披露」并记去向,不得伪造、不得用估计值或空串冒充' },
{ key: 'no-override-hard-mismatch', statement: '硬约束 MISMATCH 不得被任何措辞改判 MATCH;要改只能补证据后重比' },
{ key: 'no-customer-approval-write', statement: '客户批准状态由独立审批流维护,本活动不写 customer_approval_status(没有这一列的写权)' },
{ key: 'no-commercial-judgement', statement: '本活动只答技术可替代性:不做数量、价格、交期、采购判断' },
],
authorization: {
discretion: [],
preauthorizedActions: [],
/* 调人三次(补数据 / 审核 / 放行);零工具、AI 只出场一次 —— 预算随之从 16/90 步收紧到 8/40 步 */
humanCallBudget: 8,
},
resources: {
tools: [],
skills: [],
models: ['deepseek-v4-flash'],
roles: ['FAE/RI'],
budget: { steps: 40, tokens: 300_000, activeMinutes: 60, humanCalls: 8 },
},
},
/* ── 声明 ────────────────────────────────────────────────────── */
declarations: {
models: ['deepseek-v4-flash'],
/* 零工具 —— 这是这次重写的立场,不是疏漏(见头注) */
tools: [],
ledger: [
/* ── 两张类型字典(parts 域,与 P-08 同域;Task 1 已物化 + 播种)── */
{
domain: 'parts',
object: 'chip_type',
kind: 'master',
label: '芯片类型字典',
fields: [
col({ name: 'type_id', type: 'integer', label: '类型编号', primaryKey: true, auto: true }),
col({ name: 'type_name', type: 'text', label: '类型名称', required: true }),
col({ name: 'description', type: 'text', label: '类型说明', expect: true }),
],
},
{
domain: 'parts',
object: 'type_param',
kind: 'master',
label: '芯片类型核心参数字段',
fields: [
col({ name: 'type_id', type: 'integer', label: '所属类型', primaryKey: true, refersTo: 'parts.chip_type.type_id' }),
col({ name: 'param_name', type: 'text', label: '参数名', primaryKey: true }),
/* AI 分析时读它 —— 这一格说清「这个参数是什么意思」,是 S2 唯一一次 analyze 出场的入参之一 */
col({ name: 'param_desc', type: 'text', label: '参数说明', required: true }),
/* 约束类型按类型标一次,长在这里(不在每颗料的 `parts.parameter` 上)—— 见该表的头注 */
col({ name: 'constraint_type', type: 'text', label: '约束类型', required: true, tally: ['hard', 'soft'] }),
col({ name: 'param_unit', type: 'text', label: '参考单位', expect: true }),
],
},
/*
* P-08 芯片主数据 —— 声明后为八列,物理表其余列本活动不碰。`createOnly` 撤掉
* (spec §3.2):它当初是为了拦模型凭空建料,而配方现在按本单两颗料铺行,
* 凭空建在结构上已不可能;撤掉它换来一件必需的事 —— 给在库的老料补上
* `chip_type_id` 这一格(迁移前建的行没有类型,不许改就永远补不了)。
* package / process_technology / eol_pcn_status / application_scenarios 不声明:
* 封装和工艺本来就是「核心参数」,该以类型字段的身份出现在字典里,不在主记录上另开一列。
*/
{
domain: 'parts',
object: 'profile',
kind: 'master',
label: '芯片主数据(P-08)',
fields: [
col({ name: 'internal_pn', type: 'text', label: '内部料号', primaryKey: true }),
col({ name: 'chip_type_id', type: 'integer', label: '芯片类型', required: true, refersTo: 'parts.chip_type.type_id' }),
col({ name: 'brand_name', type: 'text', label: '品牌名称', required: true }),
col({ name: 'lifecycle_status', type: 'text', label: '生命周期状态', required: true, tally: ['active', 'nrnd', 'eol', 'discontinued', 'risk'] }),
col({ name: 'specification_description', type: 'text', label: '规格描述', expect: true }),
col({ name: 'manufacturer_name', type: 'text', label: '制造商名称', expect: true }),
col({ name: 'datasheet_ref', type: 'text', label: 'Datasheet 引用', expect: true }),
col({ name: 'datasheet_version', type: 'text', label: 'Datasheet 版本', expect: true }),
],
},
/*
* P-08 子表:标准化参数集,一行一参数。`createOnly` 撤掉(理由同上一张:在库那颗料的
* 现值要能回填进草稿层,只许建新就写不进去)。两处退休(spec §3.2):
* `constraint_type` 搬去 `parts.type_param`(同一个参数在两颗料上标法不一致这件事从结构上
* 消失);`param_name` 的自指引用墙与 `distinct` 一并退休 —— 它当初是为了硬逼两颗料用同一套
* 参数名,而字段清单现在由类型字典给、行由配方按字典铺,名字对不上根本不可能发生。
*/
{
domain: 'parts',
object: 'parameter',
kind: 'master',
label: '标准化参数集(P-08 子表)',
fields: [
col({ name: 'internal_pn', type: 'text', label: '所属料号', primaryKey: true, refersTo: 'parts.profile.internal_pn' }),
col({ name: 'param_name', type: 'text', label: '参数名', primaryKey: true }),
col({ name: 'param_value', type: 'text', label: '值', required: true }),
col({ name: 'param_unit', type: 'text', label: '单位', expect: true }),
/* 值说明,AI 也读它(spec §3.2) */
col({ name: 'param_note', type: 'text', label: '说明', expect: true }),
/*
* **约束类型不在这里** —— 它长在 `parts.type_param`(按类型标一次)。
* 从前每颗料各标一次,同一个参数在两颗料上标法不一致就成了可能;
* 而比对是逐参数对着比的,两边约束档不同,判出来的四态就没有意义。
*/
],
},
/*
* ── 活动自持两张(spec §3.3,顶掉退休的 pn_check / input_gap / verdict 三张)──
* `sub_eval.part` 是配方唯一能拿来遍历「哪几颗料要建」的数据源(`each: 'mine:sub_eval.part'
* where exists_status = absent`)—— 挤进一行案卷里就没法 `where` 过滤,而不能过滤就会给
* 已经在库的那颗料也铺一遍空参数行,这是非拆成两张不可的理由。
*/
{
domain: D,
object: 'part',
kind: 'record',
caseKey: 'eval_ref',
label: '本单两颗料(存在性与类型核对)',
fields: [
col({ name: 'eval_ref', type: 'text', label: '评估案号', primaryKey: true }),
col({ name: 'internal_pn', type: 'text', label: '内部料号', primaryKey: true }),
col({ name: 'role', type: 'text', label: '角色', required: true, tally: ['original', 'candidate'] }),
/*
* **「在库」是一次 lookup 的结果,不是一句断言**(spec §3.3):判 found 就必须拿得出
* 一个基座查得到的料号,`refersTo` 让查无此值当场拒。`exists_status` 与这一列**每一拍
* 由配方重算**(不设 created 档、不靠谁记账)—— 人把料建好之后自己变 found。
*/
col({ name: 'found_pn_ref', type: 'text', label: '在库核对依据', refersTo: 'parts.profile.internal_pn', requiredWhen: { column: 'exists_status', value: 'found' } }),
col({ name: 'exists_status', type: 'text', label: '在库状态', required: true, tally: ['found', 'absent'] }),
col({
name: 'chip_type_id',
type: 'integer',
label: '芯片类型',
required: true,
/*
* **`distinct`**:「两颗料是不是同一个类型」从此是基座数得出来的数
* (`sub_eval_part_distinct_chip_type_id`)—— 不同取值恰好 1 种才算一致。
* 这一条是 S1 收步与 S2 入场的硬门:两边字段清单不是同一套,逐项比对无从谈起。
*/
distinct: true,
}),
],
},
{
domain: D,
object: 'case',
kind: 'record',
caseKey: 'eval_ref',
label: '本单案卷',
fields: [
col({ name: 'eval_ref', type: 'text', label: '评估案号', primaryKey: true }),
col({ name: 'chip_type_id', type: 'integer', label: '本单锁定的芯片类型' }),
col({ name: 'gate_reason', type: 'text', label: '入参未就绪原因(件上摆的就是它)' }),
col({ name: 'summary', type: 'text', label: '结论摘要' }),
],
},
/*
* P-11 替代关系主记录 —— 一单一行。退休三列(spec §3.4):`substitution_type`(新流程里没有
* 它的定夺人)、`confidence_score`、`analysis_report_ref`;`recommendation_level` 的
* `alternate` 档一并退休(原 D02 的 configurable 来路已不存在,只剩三档)。
*/
{
domain: 'substitution',
object: 'relation',
kind: 'master',
label: '替代关系主记录(P-11)',
fields: [
col({ name: 'substitution_relation_id', type: 'text', label: '替代关系ID', primaryKey: true }),
col({ name: 'eval_ref', type: 'text', label: '评估案号', required: true }),
col({ name: 'original_internal_pn', type: 'text', label: '原内部料号', required: true, refersTo: 'parts.profile.internal_pn' }),
col({ name: 'candidate_internal_pn', type: 'text', label: '候选内部料号', required: true, refersTo: 'parts.profile.internal_pn' }),
col({ name: 'chip_type_id', type: 'integer', label: '芯片类型', required: true }),
col({ name: 'recommendation_level', type: 'text', label: '推荐等级', required: true, tally: ['recommended', 'conditional', 'not_recommended'] }),
col({ name: 'recommendation_reason', type: 'text', label: '推荐理由', required: true }),
col({ name: 'difference_summary', type: 'text', label: '差异摘要', required: true }),
col({ name: 'risk_level', type: 'text', label: '替代风险等级', required: true, tally: ['low', 'medium', 'high'] }),
col({ name: 'verification_requirement', type: 'text', label: '验证要求', requiredWhen: { column: 'recommendation_level', value: 'conditional' } }),
col({ name: 'validation_id', type: 'text', label: '关联验证ID' }),
/* 固定 fae_confirmed —— 分析状态与客户批准状态分离,本活动只写这一层 */
col({ name: 'analysis_status', type: 'text', label: '分析状态', required: true }),
col({ name: 'rule_version', type: 'text', label: '差异规则版本', required: true }),
],
},
/*
* P-11 差异明细子表 —— 一参数一行。`evidence_ref` 改名 `evidence_note`「判断依据」:
* 不写 P-10 了,AI 能给的就是依据不是文件引用,名字得说实话(spec §3.4)。
*/
{
domain: 'substitution',
object: 'difference_item',
kind: 'master',
label: '差异明细(P-11 子表)',
fields: [
col({ name: 'substitution_relation_id', type: 'text', label: '替代关系ID', primaryKey: true, distinct: true, refersTo: 'substitution.relation.substitution_relation_id' }),
col({ name: 'difference_item_id', type: 'text', label: '差异明细ID', primaryKey: true }),
col({ name: 'parameter_name', type: 'text', label: '标准参数名', required: true }),
/* 字段说明快照,归档件不必 join 回字典 */
col({ name: 'parameter_desc', type: 'text', label: '参数说明', expect: true }),
col({ name: 'constraint_type', type: 'text', label: '约束类型', required: true, tally: ['hard', 'soft'] }),
col({ name: 'original_value', type: 'text', label: '原物料参数值', required: true }),
col({ name: 'candidate_value', type: 'text', label: '候选物料参数值', required: true }),
col({ name: 'parameter_unit', type: 'text', label: '参数单位', expect: true }),
/* AI 判:逐参数比对,S2 唯一一次 analyze 出场的出参之一 */
col({ name: 'difference_status', type: 'text', label: '差异状态', required: true, tally: ['match', 'mismatch', 'unknown', 'conditional'] }),
/*
* **`judgement_class` 是合成列**:推荐等级要数的是「**硬约束**不符有几条」,
* 而基座读数只会数单列 —— 把「约束类型 × 四态」先合成一列,规则才算得出来。
* 由配方按 §3.5 的 when 链算,不是 AI 出的。
*/
col({ name: 'judgement_class', type: 'text', label: '判定分类', required: true, tally: ['match', 'soft_mismatch', 'hard_mismatch', 'unknown', 'conditional'] }),
col({ name: 'impact_statement', type: 'text', label: '影响说明(MATCH 写「无」)', required: true }),
col({ name: 'evidence_note', type: 'text', label: '判断依据', required: true }),
col({ name: 'unknown_disposition', type: 'text', label: 'UNKNOWN 去向(验证任务号 / 补来源动作)', requiredWhen: { column: 'difference_status', value: 'unknown' } }),
col({ name: 'risk_level', type: 'text', label: '风险等级', required: true, tally: ['low', 'medium', 'high'] }),
col({ name: 'rule_version', type: 'text', label: '差异规则版本', required: true }),
],
},
/* P-06 验证记录:一单一行,关联的是本单案号(P-01 不在本活动里,顶掉 request_id) */
{
domain: 'validation',
object: 'record',
kind: 'master',
label: '芯片验证记录(P-06)',
fields: [
col({ name: 'validation_id', type: 'text', label: '验证ID', primaryKey: true }),
col({ name: 'eval_ref', type: 'text', label: '评估案号', required: true }),
col({ name: 'validation_internal_pn', type: 'text', label: '验证内部料号', required: true, refersTo: 'parts.profile.internal_pn' }),
col({ name: 'validation_type', type: 'text', label: '验证类型', required: true, tally: ['pin_to_pin', 'functional', 'reliability', 'certification', 'retest', 'parametric'] }),
/* 固定 not_started */
col({ name: 'validation_status', type: 'text', label: '验证状态', required: true }),
col({ name: 'test_condition', type: 'text', label: '测试条件', expect: true }),
col({ name: 'next_validation_action', type: 'text', label: '后续验证动作', required: true }),
],
},
],
listeners: [],
harness: {
memoryWindow: 24,
stallAfter: 'PT4H',
nudge: [{ after: 'PT2H', action: 'nudge' }],
retry: { times: 2, backoff: 'PT30S' },
},
},
/* ── 资产初始版 ──────────────────────────────────────────────── */
assets: {
/*
* DMN 判定表已退役:D01(逐参数四态)改由 S2 唯一一次 analyze 判定;D02(推荐等级)的规则
* 搬进配方的 when 链(spec §3.5)—— 规则只许有一处真源,再留一份 DMN 就是同一件事两处
* 各存一份。Task 3 会把 `steps` 换成四步、`guide` 全部清空(auto 配方接管行为)。
*/
businessModel: { cmmnXml: CMMN_XML, narrative: NARRATIVE, dmn: { drd: [], tables: [] }, steps: ASSESSMENT_STEPS, phases: ASSESSMENT_PHASES },
/* 三条技能已随重写退役(全程无 agent,没有临场编排可言);skills.ts 的删除排在 Task 10 */
skills: [],
/*
* 五张旧局面全部作废(它们绑的九步与旧台账地址已经不存在),**暂时只留运营中心那张看板** ——
* 三张新件(`input-supplement` / `difference-review` / `landing-confirm`)由 Task 7–9 各自加回;
* 中途(Task 2–Task 9 之间)包不装,不会被静态审拦下。看板自己的 `data` 声明现在也引着已经
* 不存在的台账地址(`sub_eval.pn_check` 等)——Task 9「运营中心看板重绑」会把它换成新九张表。
*/
viewTemplates: [{ name: 'activity-ledger', html: LEDGER_BOARD, data: LEDGER_BOARD_DATA }],
cardSchemas: {},
/* 蒸馏钩子撤空:它是给 agent 在终态回看轨迹用的,而这个活动全程无 agent(AI 只出场一次、答一份结构化判断,没有可供归纳的多轮轨迹) */
distillHooks: [],
},
/*
* ── 样例集:五条形状真不同(常备案例即验收案例)──
* 本任务不改样例(它们仍是旧九步 / 旧入参形状的素材,Task 3 重写案例模型时一并核对)。
* 库里只播了 LM2596S-5.0 / LM2596S-ADJ 两颗(见 seed-mvp-data.ts),XL2596S-5.0 / CN-DCDC-32V / LM2596S-3.3 刻意不在库。
*/
samples: [
{
name: '候选缺库·派数据工单',
input: {
customerCode: 'CU-0142',
requestDescription: '工业电源项目在用 LM2596S-5.0(TI,12V→5V),原厂 PCN 转 NRND,客户要求验证替代料;应用 12V→5V、工业温域、输入上限 40V',
originalInternalPn: 'LM2596S-5.0',
candidateInternalPns: ['XL2596S-5.0', 'LM2596S-ADJ'],
},
expect: { ports: ['assessment-released'] },
},
{
name: '都在库·常路',
input: {
customerCode: 'CU-0142',
requestDescription: 'LM2596S-5.0 转 NRND,客户先评估同族可调版 LM2596S-ADJ 能否替代(愿意改外围);应用 12V→5V、工业温域',
originalInternalPn: 'LM2596S-5.0',
candidateInternalPns: ['LM2596S-ADJ'],
},
expect: { ports: ['assessment-released'] },
},
{
name: '原PN缺库·硬阻塞',
input: {
customerCode: 'CU-0142',
requestDescription: '客户另一块板在用 LM2596S-3.3(3.3V 固定版),同批 PCN,要求评估 LM2596S-ADJ 替代;应用 12V→3.3V',
originalInternalPn: 'LM2596S-3.3',
candidateInternalPns: ['LM2596S-ADJ'],
},
expect: { ports: ['assessment-released'] },
},
{
name: '三候选·含硬约束不推荐',
input: {
customerCode: 'CU-0142',
requestDescription: '工业电源 12V→5V,输入上限 40V,工业温域;三个候选:XL2596S-5.0、LM2596S-ADJ、国产 CN-DCDC-32V(输入上限只有 32V)',
originalInternalPn: 'LM2596S-5.0',
candidateInternalPns: ['XL2596S-5.0', 'LM2596S-ADJ', 'CN-DCDC-32V'],
},
expect: { ports: ['assessment-released'] },
},
{
name: '新客户·先建档',
input: {
customerCode: 'CU-9001',
customerName: '深圳恒星电源有限公司',
requestDescription: '新客户口述:工业电源 12V→5V 在用 LM2596S-5.0,想评估 LM2596S-ADJ',
originalInternalPn: 'LM2596S-5.0',
candidateInternalPns: ['LM2596S-ADJ'],
},
expect: { ports: ['assessment-released'] },
},
],
entry: { file: 'index.js', checksum: 'dev-entry-part-substitution-assessment' },
};