diff --git a/docs/MVP示例工作流.html b/docs/MVP示例工作流.html index 7394070..460b84b 100644 --- a/docs/MVP示例工作流.html +++ b/docs/MVP示例工作流.html @@ -333,7 +333,7 @@ table.ct td{border:1px solid var(--line);padding:7px 9px;vertical-align:top;font

业务流程 · 统一报价

会话「芯片业务」沉淀的业务流程「统一报价」单章报告:流程描述 · 流程图 · 动态数据 · 静态底座 · 规则 · 活动(SOP 节点 = 任务定义卡 · 作业指导书;Case 节点 = 案例·定义卡 · CMMN 案例图 · 案例说明书)。

-

EXPORTED 2026/7/27 15:58:24 · 1 条流程 · 5 个下钻节点 · 47 张单据 · MIND-TINKER

+

EXPORTED 2026/7/27 22:04:53 · 1 条流程 · 4 个下钻节点 · 47 张单据 · MIND-TINKER

@@ -355,7 +355,7 @@ table.ct td{border:1px solid var(--line);padding:7px 9px;vertical-align:top;font
流程图 · 顺序
FIG. 1 — 统一报价流程从收到报价请求到发出标准报价书
- 通过成交不通过有异议拒绝/超时不需要选型需要选型需要寻源不需要寻源下钻小节:A1 · 客户RFQ受理客户RFQ受理A1BD下钻小节:A4 · 成本定价成本定价A4BD下钻小节:A5 · 定价审批定价审批A5PM×下钻小节:A6 · 报价议价报价议价A6BD×下钻小节:A2 · 替代选型替代选型A2FAE退回调整→A4下钻小节:A7 · 情报归档情报归档A7BD返回调整→A4下钻小节:A3 · 寻源询价寻源询价A3PRM××客户RFQ询价审批结果议价结果转订单履约归档闭环是否需要选型是否需要寻源 + 通过成交不通过有异议拒绝/超时不需要选型需要选型需要寻源不需要寻源下钻小节:A1 · 客户RFQ受理客户RFQ受理A1BD下钻小节:A4 · 成本定价成本定价A4BD下钻小节:A5 · 定价审批定价审批A5PM×下钻小节:A6 · 报价议价报价议价A6BD×下钻小节:A2 · 替代选型替代选型A2FAE退回调整→A4下钻小节:A7 · 情报归档情报归档A7BD返回调整→A4下钻小节:A3 · 寻源询价寻源询价A3PRM××客户RFQ询价审批结果议价结果转订单履约归档闭环是否需要选型是否需要寻源
图例 起始 结束 SOP 活动 Case 活动 判断网关 并行网关 卡点 顺序流 @@ -696,7 +696,7 @@ table.ct td{border:1px solid var(--line);padding:7px 9px;vertical-align:top;font
步骤流程 — 客户RFQ受理客户RFQ受理
- 不完整不需要选型完整需要选型接收登记S1×追问补全信息S2逐条解析归一S3查历史价S4逐条定状况标S5定去向与派单S6×接流程起点D1 · 判断完整度G1 · 是否需要选型下接 G2·是否需要寻源转 A2·替代选型 + 不完整不需要选型完整需要选型接收登记S1×追问补全信息S2逐条解析归一S3查历史价S4逐条定状况标S5定去向与派单S6×接流程起点D1 · 判断完整度G1 · 是否需要选型下接 A3·寻源询价转 A2·替代选型

谁做、何时做:BD 受理<15分钟、判定<45分钟。真实 RFQ 五花八门(俄文BOM/内部码/字段常缺)——先归一成台账化的 统一受理记录,再逐条查历史价与供货状况;去向由两道判断定:要不要选型、要不要寻源,两者可同时成立(先选替代料,再为替代料寻价)。判错状况,快单变慢单。

@@ -751,27 +751,124 @@ table.ct td{border:1px solid var(--line);padding:7px 9px;vertical-align:top;font
留痕 · SLA留痕:报价草案(已批准,含策略与批注);SLA 每单<30min,审批通过目标 >90%。
- 1.4统一报价-A6 · 报价议价 + 1.4统一报价-A6 · 报价议价CASE
-
任务定义卡
+ +
案例 · 定义卡
统一报价 A6 · 报价议价
-
执行
BD·商务
触发
报价草案(已批准)
目标
发出 正式报价单,同步留档并建立跟进
+
执行
BD·商务
触发
报价草案(已批准) 就绪,待发客户并跟谈
输入
输出
正式报价单(已送出)
-
作业指导书
+ +
案例图 · 结构(CMMN)
+
+
CASE PLAN · 报价议价
+
● 上接 G3·审批结果(通过 进入) ─→ ◎ 办结经 G4·议价结果 定去向
+ 正式报价单正式报价单D+3/D+7跟进提醒D+3/D+7跟进提醒历史价格情报历史价格情报统一受理记录统一受理记录S1发报留档◇何时进入 报价草案(已批准) 就绪 ◆何时算完 正式报价单…◇ 何时进入:报价草案(已批准) 就绪◆ 何时算完:正式报价单 已送出且跟进已建立齐了即收(阶段级 AutoComplete):必做项齐即收束本阶段怎么办:排版为 正式报价单:中英双语,单价CNY/交期/SPQ/MOQ/贸易条款;依 报价有效期P-04 注明 7 日历天有效。人工任务(Human Task)人工生成发出!必做◇ 何时能做:报价草案(已批准) 就绪◇ 报价草案(已批准) 就绪怎么办:回写 历史价格情报:报价日期/单价/交期/MOQ/备注——下次判定不必寻源的资本。人工任务(Human Task)人工逐条留档!必做怎么办:设 D+3/D+7跟进提醒,到点必催;发出即建,不等客户先回。人工任务(Human Task)人工建立跟进!必做◇ 达成标志:正式报价单 发出并留档报价已送出达成:正式报价单 发出并留档S2跟进议价◇何时进入 正式报价单 已送出 ◆何时算完 客户明确接受/拒…◇ 何时进入:正式报价单 已送出◆ 何时算完:客户明确接受/拒绝,或有效期已过⊞ 规划表:本阶段含「看情况」裁量项怎么办:催问结果记回 统一受理记录;客户不回不是结论,催到表态或有效期过。人工任务(Human Task)人工按节奏催问#可反复◇ 何时能做:D+3/D+7 到点或客户久未回◇ D+3/D+7 到点或客户久未回怎么办:分清争的是价格、交期、MOQ,还是走过场压价——对症再谈,不上来就让。人工任务(Human Task)人工弄清异议看情况◇ 何时能做:客户有异议时◇ 客户有异议时怎么办:授权范围内回旋;要破 底价门禁P-02 红线的,交回发起流程重批,不私自破线。人工任务(Human Task)人工让价核线▶需拍板◇ 何时能做:需要让价时◇ 需要让价时怎么办:每轮谈判的客户反馈与口头承诺当天记回 统一受理记录,不留脑子里。人工任务(Human Task)人工记录反馈#可反复◇ 达成标志:接受/拒绝/异议已明确客户表态达成:接受/拒绝/异议已明确S3定案交接◇何时进入 客户表态,或 D+7 已过 ◆何时算完 结果定案,去…◇ 何时进入:客户表态,或 D+7 已过◆ 何时算完:结果定案,去向已交接怎么办:核对最终成交条件与 正式报价单 一致;移交订单履约,差异写清再交。人工任务(Human Task)人工成交交接◇ 何时能做:客户接受报价◇ 客户接受报价怎么办:登记拒绝原因/无回复,更新 统一受理记录 状态;后续归档由发起流程接续。人工任务(Human Task)人工关单定案◇ 何时能做:拒绝或 D+7 无回复◇ 拒绝或 D+7 无回复◇ 达成标志:成交移交或关单定案完成结果定案达成:成交移交或关单定案完成怎么办:客户价格敏感度、竞品报价、行情反应随手记 客户资料库 与 历史价格情报——每谈一单,底账厚一层。人工任务(Human Task)人工情报沉淀!必做D+3 未回:第一轮催问:确认收到、探态度。⏱ D+3 未回第一轮催问:确认收到、探态度。D+7 未回:最后一催,仍无回复按超时定案。⏱ D+7 未回最后一催,仍无回复按超时定案。客户还价:随时可来:进入议价,弄清异议再回。✋ 客户还价随时可来:进入议价,弄清异议再回。要留的材料(CASEFILE)全程随时可做(不属于任何阶段)要盯的事(EVENT LISTENER)
记号:图标井=任务四型(人工/按流程办/另立一案/拍板决策) · !必做 · #可反复 · ▶需拍板 · 虚线=看情况 · ◇何时能做/进入 · ◆何时算完 · ▣齐了即收 · ⊞含裁量项 · ⏱定时监听 · ✋人为触发
+
CMMN · CASE MANAGEMENT MODEL AND NOTATION
+
+ +
案例说明书
-
-
步骤流程 — 报价议价报价议价
- 成交有异议拒绝/超时生成发出S1CRM留档S2建立跟进S3×上接 A5·定价审批G4 · 议价结果转订单履约返回调整→A4转 A7·情报归档 -
-

谁做、何时做:BD 在审批通过后 15 分钟内发出报价并留档。发出的同时必须建立 D+3/D+7 跟进——没有跟进的报价等于没报。

-
● 上接 A5·定价审批
-
  1. S1生成发出把 报价草案(已批准) 排版为 正式报价单(PDF·中英双语:单价CNY/交期/SPQ/MOQ/贸易条款);依据 报价有效期P-04 注明 7 日历天有效。
  2. S2CRM留档逐条录入 CRM,回写 历史价格情报(报价日期/单价/交期/MOQ/备注)——这是下次判定不必寻源的资本。
  3. S3建立跟进设 D+3/D+7跟进提醒;客户议价在授权范围内回旋,超出授权回 A5 重批,不私自破线。
  4. G4议价结果判断 × · 出口固定客户是否接受报价?成交→转订单履约(ORM);拒绝/无回复→情报库归档闭环(D+3/D+7跟进,落地率目标>25%,7天闭环)
    ↳ 成交 → 转订单履约
    ↳ 有异议 → 返回调整→A4
    ↳ 拒绝/超时 → 转 A7·情报归档
+

§0 开案:一单一谈:收到 报价草案(已批准) 即开案。先发报留档建跟进(15 分钟内),再按 D+3/D+7 节奏催问跟谈——客户的异议五花八门,价格、交期、MOQ 各有谈法;让价守 底价门禁P-02 红线,要破线的交回发起流程重批。谈到客户明确接受或拒绝、或有效期过就定案:成交移交订单履约,不成交也把情报沉进底账。

+
  1. S1发报留档审批通过后 15 分钟内发出:把 报价草案(已批准) 排版为 正式报价单(PDF·中英双语:单价CNY/交期/SPQ/MOQ/贸易条款),依 报价有效期P-04 注明 7 日历天有效。发出的同时做两件事——逐条回写 历史价格情报(报价日期/单价/交期/MOQ/备注),设 D+3/D+7跟进提醒;没有跟进的报价等于没报。
    ↳ 生成发出:排版为 正式报价单:中英双语,单价CNY/交期/SPQ/MOQ/贸易条款;依 报价有效期P-04 注明 7 日历天有效。
    ↳ 逐条留档:回写 历史价格情报:报价日期/单价/交期/MOQ/备注——下次判定不必寻源的资本。
    ↳ 建立跟进:设 D+3/D+7跟进提醒,到点必催;发出即建,不等客户先回。
  2. S2跟进议价按 D+3/D+7 节奏催问——客户不回不是结论,催到表态或有效期过。客户有异议先弄清争的是价格、交期还是MOQ,每轮反馈当天记回 统一受理记录;让价在授权范围内回旋,要破 底价门禁P-02 红线的交回发起流程重批,不私自破线。临近 报价有效期P-04 到期客户仍在犹豫的,主动催一轮再定去留。
    ↳ 按节奏催问:催问结果记回 统一受理记录;客户不回不是结论,催到表态或有效期过。
    ↳ 弄清异议:分清争的是价格、交期、MOQ,还是走过场压价——对症再谈,不上来就让。
    ↳ 让价核线:授权范围内回旋;要破 底价门禁P-02 红线的,交回发起流程重批,不私自破线。
    ↳ 记录反馈:每轮谈判的客户反馈与口头承诺当天记回 统一受理记录,不留脑子里。
  3. S3定案交接成交的按最终成交条件移交订单履约,成交价与条款记实再交;拒绝或超时的按期定案,交回发起流程归档闭环——不成交也是情报,别让单子烂尾挂着。
    ↳ 成交交接:核对最终成交条件与 正式报价单 一致;移交订单履约,差异写清再交。
    ↳ 关单定案:登记拒绝原因/无回复,更新 统一受理记录 状态;后续归档由发起流程接续。
+
全程随时可做:
↳ 情报沉淀:客户价格敏感度、竞品报价、行情反应随手记 客户资料库 与 历史价格情报——每谈一单,底账厚一层。
+

§Z 结案:人工结案——由主办人确认满足结案标准后宣布。 成交的移交订单履约;拒绝或 D+7 无回复的按超时定案,交回发起流程归档闭环(7 天不挂单,报价落地率目标 >25%)。每谈一单,客户画像与行情底账厚一层。

+
+
+
动态数据 · 流转
+
+
+
报价草案输入
+

逐条定价的待审报价

+
+
载体数据表格
+
+
+ 字段 · 4 +
PN拟报单价毛利率偏离度
+
-
留痕 · SLA留痕:正式报价单、历史价格情报(记录)、D+3/D+7跟进提醒;系统:CRM;SLA <15min。
-
+
+
定价审批表输入
+

定价审批记录

+
+
载体审批流
+
+
+ 字段 · 4 +
报价单号批复审批人时间
+
+ +
+
+
正式报价单输出
+

对外发出的标准报价

+
+
载体PDF文件
+
+
+ 字段 · 7 +
PN单价CNY交期SPQMOQ贸易条款有效期
+
+ +
+
+
D+3/D+7跟进提醒过程
+

发出后的跟进任务

+
+
载体数据表格
+
+
+ 字段 · 5 +
客户报价单号D+3D+7回复状态
+
+ +
+
+
统一受理记录过程
+

归一后的逐条需求台账

+
+
载体数据表格
+
+
+ 字段 · 7 +
客户码PN厂牌EAUType标目标价状态
+
+ +
+
静态数据 · 底座
+
+
+
历史价格情报外部情报
+

历次报价与成交价情报

+
+
载体数据表格
+
来源内部沉淀
+
维护随单归档
+
+
+ 字段 · 7 +
PN厂牌单价CNY交期MOQ报价日期有效期
+
+ +
+
+
客户资料库主数据
+

客户等级与画像档案

+
+
载体数据表格
+
来源内部沉淀
+
维护随交易更新
+
+
+ 字段 · 7 +
客户码客户等级画像标签付款条款行业属性风险等级年采购额
+
+ +
1.5统一报价-A2 · 替代选型CASE
@@ -785,7 +882,7 @@ table.ct td{border:1px solid var(--line);padding:7px 9px;vertical-align:top;font
案例图 · 结构(CMMN)
CASE PLAN · 替代选型
-
● 上接 A1·客户RFQ受理(需要选型 进入) ─→ ◎ 办结转 A3·寻源询价
+
● 上接 G1·是否需要选型(需要选型 进入) ─→ ◎ 办结经 G2·是否需要寻源 定去向
齐了即收(AutoComplete):必做项完成且无进行中项即结案替代对标表替代对标表初筛清单初筛清单替代评估请求替代评估请求芯片规格书芯片规格书替代料库替代料库S1初选核险◇何时进入 收到技术选型需求 ◆何时算完 初选风险与主推定…◇ 何时进入:收到技术选型需求◆ 何时算完:初选风险与主推定性⊞ 规划表:本阶段含「看情况」裁量项怎么办:一手以原厂官网为准:产品页/规格书/PCN·EOL 公告;查 芯片规格书,生命周期对照 PN物料主库。人工任务(Human Task)人工查规格核险!必做◇ 何时能做:入案即可做◇ 入案即可做怎么办:对 品牌原厂字典 判初选品牌是否我司主推;无风险且主推→采信初选,直接办结交回。人工任务(Human Task)人工判主推品牌!必做怎么办:查 替代料库 有现成方案直接复用并注明来源;技术问题案例库 有坑先避。人工任务(Human Task)人工查沉淀避坑看情况◇ 何时能做:同类需求出现过◇ 同类需求出现过◇ 达成标志:风险与主推与否有结论初选定性达成:风险与主推与否有结论S2圈选替代◇何时进入 初选有风险/非主推,或只给类型参数 ◆何时算完 …◇ 何时进入:初选有风险/非主推,或只给类型参数◆ 何时算完:候选替代圈定并确认怎么办:AI 检索/选型聚合平台/芯片采购网拉 初筛清单:候选型号、品牌、替代关系、封装、生命周期、货态。人工任务(Human Task)人工撒网拉初筛!必做 · #可反复◇ 何时能做:入案即可做◇ 入案即可做怎么办:每颗先明确数据来源(以原厂官网 芯片规格书 为准,记版本),再仔细通读规格书做全面参数对比:封装/引脚/电气/温度/认证逐项过;定 替代等级,不合格剔除。人工任务(Human Task)人工逐条核验分级!必做 · #可反复◇ 何时能做:初筛清单到手◇ 初筛清单到手怎么办:过 客户技术画像 禁用清单;同原厂(查 原厂技术支持库)或我司采购确认候选为主推型号;供应顺带核(查 供应商渠道目录)。人工任务(Human Task)人工确认主推型号!必做◇ 达成标志:2~3颗分级候选经确认候选圈定达成:2~3颗分级候选经确认S3对比评估交付◇何时进入 候选替代确认 ◆何时算完 报告签字交回发起方◇ 何时进入:候选替代确认◆ 何时算完:报告签字交回发起方怎么办:收齐候选 芯片规格书(官网版),版本与日期记录在案。人工任务(Human Task)人工收集规格书!必做怎么办:关键参数逐项对比写进 替代对标表,标出差异项与 替代等级,写明差异带来的风险。人工任务(Human Task)人工参数对比表!必做怎么办:P2P 核确免改动;功能兼容/其他评软件开发/外围电路/layout 改动;关键差异给验证建议,对照 验证记录库。人工任务(Human Task)人工替代风险评估!必做怎么办:FAE 签字,替代对标表(已签字) 交回发起方——输入技术需求的客户/PM。人工任务(Human Task)人工签字交出!必做 · ▶需拍板◇ 达成标志:替代对标表带FAE签字签字放行达成:替代对标表带FAE签字怎么办:官网查到的规格书随手入 芯片规格书;确认的替代关系回填 替代料库 与 PN物料主库(内部推荐替代料);踩到的坑记 技术问题案例库。人工任务(Human Task)人工知识入库!必做时限过半:向 BD 与 PM 同步进度与风险,必要时协商只报有把握的部分。⏱ 时限过半向 BD 与 PM 同步进度与风险,必要时协商只报有把握的部分。客户改需求:应用条件/参数变更→回初选核险与圈选复核,必要时重圈候选。✋ 客户改需求应用条件/参数变更→回初选核险与圈选复核,必要时重圈候选。要留的材料(CASEFILE)全程随时可做(不属于任何阶段)要盯的事(EVENT LISTENER)
记号:图标井=任务四型(人工/按流程办/另立一案/拍板决策) · !必做 · #可反复 · ▶需拍板 · 虚线=看情况 · ◇何时能做/进入 · ◆何时算完 · ▣齐了即收 · ⊞含裁量项 · ⏱定时监听 · ✋人为触发
CMMN · CASE MANAGEMENT MODEL AND NOTATION
@@ -793,10 +890,10 @@ table.ct td{border:1px solid var(--line);padding:7px 9px;vertical-align:top;font
案例说明书
-

§0 开案:替代选型一事一议:收到 替代评估请求 即开案——客户/PM 给出初选物料,或芯片类型与大致参数;先核初选(EOL 等风险提示 + 是否我司主推品牌),无风险且主推直接采信初选办结;需要替代的,先撒网(AI 检索/聚合平台拉 初筛清单)后逐条人工核验,常要两三轮,存活候选按 替代等级 分级(P2P/功能兼容/其他)圈 2~3 颗,做参数对比与风险评估成报告交回。任何替代必须把差异与风险写清——差异没核清的不放行。

-
  1. S1初选核险接 替代评估请求 立案——客户/PM 给出初选物料,或只给芯片类型与大致参数;一手资料以原厂官网为准(产品页/规格书/PCN·EOL 公告):查 芯片规格书 确认初选料有无 EOL/停产等风险提示,生命周期对照 PN物料主库;对 品牌原厂字典 判初选品牌是否我司主推——无风险且主推,直接采信初选、免替代办结;顺手查 替代料库 与 技术问题案例库,有沉淀方案或已知坑先亮出来。
    ↳ 查规格核险:一手以原厂官网为准:产品页/规格书/PCN·EOL 公告;查 芯片规格书,生命周期对照 PN物料主库。
    ↳ 判主推品牌:对 品牌原厂字典 判初选品牌是否我司主推;无风险且主推→采信初选,直接办结交回。
    ↳ 查沉淀避坑:查 替代料库 有现成方案直接复用并注明来源;技术问题案例库 有坑先避。
  2. S2圈选替代先撒网后核验,常要两三轮:用 AI 检索、选型聚合平台与芯片采购网(线索归 公网选型库)拉 初筛清单——带替代关系标注的一堆候选,快而不可靠;再逐条人工核验做全面参数对比——先明确每项数据的来源(一律以原厂官网 芯片规格书 为准),再仔细通读规格书逐项对标(Pin-to-Pin),存活者按 替代等级 分级——P2P(同封装同引脚可直换)/功能兼容(需外围或 layout 调整)/其他(部分兼容须验证);候选过 客户技术画像 禁用清单、优先同品类我司主推品牌(对照 产品线能力档案),不足 2~3 颗就放宽参数或换角度重新撒网;定型前同原厂(按 原厂技术支持库 找窗口)或我司采购确认主推型号。
    ↳ 撒网拉初筛:AI 检索/选型聚合平台/芯片采购网拉 初筛清单:候选型号、品牌、替代关系、封装、生命周期、货态。
    ↳ 逐条核验分级:每颗先明确数据来源(以原厂官网 芯片规格书 为准,记版本),再仔细通读规格书做全面参数对比:封装/引脚/电气/温度/认证逐项过;定 替代等级,不合格剔除。
    ↳ 确认主推型号:过 客户技术画像 禁用清单;同原厂(查 原厂技术支持库)或我司采购确认候选为主推型号;供应顺带核(查 供应商渠道目录)。
  3. S3对比评估交付收齐候选 芯片规格书,整理关键参数对比表:逐项标出差异项并分析差异风险;按 替代等级 定评估深度——P2P 核确免改动即可,功能兼容/其他逐项评软件开发、外围电路与 layout 改动,认证差异对照 行业标准库,已有 验证记录库 结论直接采信;成稿 替代对标表(推荐报告,同颗芯片 2 页:等级+参数对比+风险评估),FAE 签字后交回发起方——输入技术需求的客户/PM。
    ↳ 收集规格书:收齐候选 芯片规格书(官网版),版本与日期记录在案。
    ↳ 参数对比表:关键参数逐项对比写进 替代对标表,标出差异项与 替代等级,写明差异带来的风险。
    ↳ 替代风险评估:P2P 核确免改动;功能兼容/其他评软件开发/外围电路/layout 改动;关键差异给验证建议,对照 验证记录库。
    ↳ 签字交出:FAE 签字,替代对标表(已签字) 交回发起方——输入技术需求的客户/PM。
-
全程随时可做:
↳ 知识入库:官网查到的规格书随手入 芯片规格书;确认的替代关系回填 替代料库 与 PN物料主库(内部推荐替代料);踩到的坑记 技术问题案例库。
-

§Z 结案:必做的事都办完、没有进行中的事,自动算结案(CMMN AutoComplete)。 无需替代的,确认初选可用即结案;需要替代的,推荐报告 替代对标表(已签字) 交回发起方——输入技术需求的客户/PM 即结案;替代关系回填 替代料库 与 PN物料主库,规格书与报告入库——每办一案,知识库厚一层。

+

§0 开案:替代选型一事一议:收到 替代评估请求 即开案——客户/PM 给出初选物料,或芯片类型与大致参数;先核初选(EOL 等风险提示 + 是否我司主推品牌),无风险且主推直接采信初选办结;需要替代的,先撒网(AI 检索/聚合平台拉 初筛清单)后逐条人工核验,常要两三轮,存活候选按 替代等级 分级(P2P/功能兼容/其他)圈 2~3 颗,做参数对比与风险评估成报告交回。任何替代必须把差异与风险写清——差异没核清的不放行。

+
  1. S1初选核险接 替代评估请求 立案——客户/PM 给出初选物料,或只给芯片类型与大致参数;一手资料以原厂官网为准(产品页/规格书/PCN·EOL 公告):查 芯片规格书 确认初选料有无 EOL/停产等风险提示,生命周期对照 PN物料主库;对 品牌原厂字典 判初选品牌是否我司主推——无风险且主推,直接采信初选、免替代办结;顺手查 替代料库 与 技术问题案例库,有沉淀方案或已知坑先亮出来。
    ↳ 查规格核险:一手以原厂官网为准:产品页/规格书/PCN·EOL 公告;查 芯片规格书,生命周期对照 PN物料主库。
    ↳ 判主推品牌:对 品牌原厂字典 判初选品牌是否我司主推;无风险且主推→采信初选,直接办结交回。
    ↳ 查沉淀避坑:查 替代料库 有现成方案直接复用并注明来源;技术问题案例库 有坑先避。
  2. S2圈选替代先撒网后核验,常要两三轮:用 AI 检索、选型聚合平台与芯片采购网(线索归 公网选型库)拉 初筛清单——带替代关系标注的一堆候选,快而不可靠;再逐条人工核验做全面参数对比——先明确每项数据的来源(一律以原厂官网 芯片规格书 为准),再仔细通读规格书逐项对标(Pin-to-Pin),存活者按 替代等级 分级——P2P(同封装同引脚可直换)/功能兼容(需外围或 layout 调整)/其他(部分兼容须验证);候选过 客户技术画像 禁用清单、优先同品类我司主推品牌(对照 产品线能力档案),不足 2~3 颗就放宽参数或换角度重新撒网;定型前同原厂(按 原厂技术支持库 找窗口)或我司采购确认主推型号。
    ↳ 撒网拉初筛:AI 检索/选型聚合平台/芯片采购网拉 初筛清单:候选型号、品牌、替代关系、封装、生命周期、货态。
    ↳ 逐条核验分级:每颗先明确数据来源(以原厂官网 芯片规格书 为准,记版本),再仔细通读规格书做全面参数对比:封装/引脚/电气/温度/认证逐项过;定 替代等级,不合格剔除。
    ↳ 确认主推型号:过 客户技术画像 禁用清单;同原厂(查 原厂技术支持库)或我司采购确认候选为主推型号;供应顺带核(查 供应商渠道目录)。
  3. S3对比评估交付收齐候选 芯片规格书,整理关键参数对比表:逐项标出差异项并分析差异风险;按 替代等级 定评估深度——P2P 核确免改动即可,功能兼容/其他逐项评软件开发、外围电路与 layout 改动,认证差异对照 行业标准库,已有 验证记录库 结论直接采信;成稿 替代对标表(推荐报告,同颗芯片 2 页:等级+参数对比+风险评估),FAE 签字后交回发起方——输入技术需求的客户/PM。
    ↳ 收集规格书:收齐候选 芯片规格书(官网版),版本与日期记录在案。
    ↳ 参数对比表:关键参数逐项对比写进 替代对标表,标出差异项与 替代等级,写明差异带来的风险。
    ↳ 替代风险评估:P2P 核确免改动;功能兼容/其他评软件开发/外围电路/layout 改动;关键差异给验证建议,对照 验证记录库。
    ↳ 签字交出:FAE 签字,替代对标表(已签字) 交回发起方——输入技术需求的客户/PM。
+
全程随时可做:
↳ 知识入库:官网查到的规格书随手入 芯片规格书;确认的替代关系回填 替代料库 与 PN物料主库(内部推荐替代料);踩到的坑记 技术问题案例库。
+

§Z 结案:必做的事都办完、没有进行中的事,自动算结案(CMMN AutoComplete)。 无需替代的,确认初选可用即结案;需要替代的,推荐报告 替代对标表(已签字) 交回发起方——输入技术需求的客户/PM 即结案;替代关系回填 替代料库 与 PN物料主库,规格书与报告入库——每办一案,知识库厚一层。

动态数据 · 流转
@@ -1042,7 +1139,7 @@ table.ct td{border:1px solid var(--line);padding:7px 9px;vertical-align:top;font
案例图 · 结构(CMMN)
CASE PLAN · 寻源询价
-
● 上接 A2·替代选型(需要寻源 进入) ─→ ◎ 办结转 A4·成本定价
+
● 上接 G2·是否需要寻源(需要寻源 进入) ─→ ◎ 办结转 A4·成本定价
齐了即收(AutoComplete):必做项完成且无进行中项即结案寻源比价表寻源比价表供应商回价单供应商回价单正式报价单正式报价单询价请求询价请求S1接需核史◇何时进入 收到询价请求 ◆何时算完 历史核价完成,采用策…◇ 何时进入:收到询价请求◆ 何时算完:历史核价完成,采用策略已定怎么办:系统带出在供供应商及历史报价,逐PN核对有效期与历次价格。未达3次询价但有效期已过的,标记须重询。人工任务(Human Task)人工查历史报价!必做怎么办:BOM早期:有效期内直采;过期浮动≤10%直采、10-20%取均價、>20%重询。BOM后期:历史最低(≥3次)直采,否则降20%谈。现货/样品:一律重询。决策任务(Decision Task)拍板决策判定采用策略!必做◇ 达成标志:每PN明确直采或须询价策略已定达成:每PN明确直采或须询价S2选渠定策◇何时进入 须执行新询价 ◆何时算完 每料圈定渠道◇ 何时进入:须执行新询价◆ 何时算完:每料圈定渠道⊞ 规划表:本阶段含「看情况」裁量项怎么办:BOM早期/样品:系统带出即可圈入,可放宽。BOM后期:主→备选→贸易商顺序圈2~3家,贸易商尽量不用。现货:仅选有库存/实拍的供应商,无库存转单商不可选。人工任务(Human Task)人工按场景圈渠道!必做怎么办:核实授权代理资质与授权期限;贸易商核查货源链可靠性。人工任务(Human Task)人工渠道资质核实看情况◇ 何时能做:BOM后期场景◇ BOM后期场景◇ 达成标志:每料有2~3家渠道清单渠道圈定达成:每料有2~3家渠道清单S3发询比价◇何时进入 渠道已圈定 ◆何时算完 有效报价确认或时限到◇ 何时进入:渠道已圈定◆ 何时算完:有效报价确认或时限到⊞ 规划表:本阶段含「看情况」裁量项齐了即收(阶段级 AutoComplete):必做项齐即收束本阶段怎么办:同一料所有渠道一次发齐;PN/数量/目标价/回价时限写死在询价里。BOM后期默认两轮,首轮后内部review再发次轮。人工任务(Human Task)人工批量发询!必做 · #可反复怎么办:供应商回价单逐单登记:价格/MOQ/交期/有效期/批次DC/成色/渠道等级,一一对应不可缺项。人工任务(Human Task)人工登记回价!必做 · #可反复◇ 何时能做:收到回价◇ 收到回价怎么办:BOM早期:首个报价即用,品牌价差≤20%正常。BOM后期:按历史最低降20%谈,两轮review。现货:低于线上商城+比区域市场+比订货价(>20%可接受)。样品:低于线上商城即用,库内不足线上补。人工任务(Human Task)人工价格验证!必做 · #可反复◇ 何时能做:回价入册后◇ 回价入册后怎么办:电话催回未应答渠道;不实回价或远低行情则换渠道补询,每轮记录追价次数与结果。人工任务(Human Task)人工追价补询#可反复 · 看情况◇ 何时能做:回价异常或截止未应答◇ 回价异常或截止未应答◇ 达成标志:每料有有效报价或明确无货报价确认达成:每料有有效报价或明确无货S4反馈交付◇何时进入 报价已就绪(历史直采或新询完成) ◆何时算完 …◇ 何时进入:报价已就绪(历史直采或新询完成)◆ 何时算完:寻源比价表交付PM⊞ 规划表:本阶段含「看情况」裁量项怎么办:将确认报价/LT/SPQ/价格有效期等逐项填入寻源比价表,供PM直接查阅。人工任务(Human Task)人工填寻源比价表!必做怎么办:PM向客户反馈→确认下单出具正式报价单→填入采购申请表。采购接申请后向供应商下单,填写下单价格/交期/物流单号,跟踪到货。人工任务(Human Task)人工下单与跟踪看情况◇ 何时能做:现货或样品场景且PM确认下单◇ 现货或样品场景且PM确认下单◇ 达成标志:寻源比价表已提交,现货/样品下单已启动交付完成达成:寻源比价表已提交,现货/样品下单已启动怎么办:回价与成交沉淀历史价格情报;渠道表现与配合度回写供应商渠道目录与供应商档案库;新渠道收编。人工任务(Human Task)人工知识入库!必做◇ 何时能做:寻源比价表已交付◇ 寻源比价表已交付时限预警:按场景时限过半提醒:BOM早期/现货1~4日、样品1~3日、BOM后期3~9日。急料电话催办。⏱ 时限预警按场景时限过半提醒:BOM早期/现货1~4日、样品1~3日、BOM后期3~9日。急料电话催办。回价到期:回价临过期提醒复核确认,过期触发重询。⏱ 回价到期回价临过期提醒复核确认,过期触发重询。要留的材料(CASEFILE)全程随时可做(不属于任何阶段)要盯的事(EVENT LISTENER)
记号:图标井=任务四型(人工/按流程办/另立一案/拍板决策) · !必做 · #可反复 · ▶需拍板 · 虚线=看情况 · ◇何时能做/进入 · ◆何时算完 · ▣齐了即收 · ⊞含裁量项 · ⏱定时监听 · ✋人为触发
CMMN · CASE MANAGEMENT MODEL AND NOTATION
@@ -1051,8 +1148,8 @@ table.ct td{border:1px solid var(--line);padding:7px 9px;vertical-align:top;font

§0 开案:本案例覆盖四种询价场景——BOM早期、BOM后期、现货询价、样品询价。场景不同,供应商选择尺度与价格验证规则各异,但都遵循同一主线:PM提交询价请求→查历史报价判定可否直采→(须询价时)按场景圈渠道→发询验证→填入寻源比价表反馈。BOM早期/样品渠道可放宽、价格验证宽松;BOM后期必须靠谱渠道、两轮谈价、按历史最低降20%谈;现货仅选库存实拍供应商、多重价格校验。

-
  1. S1接需核史PM在需求库填写项目/PN/数量/场景类型/紧急度后,触发询价任务给采购。系统自动带出在供供应商与历史报价。先核历史:按场景规则逐PN判定是否可直接采用——可直接采用则跳过询价、直接进入反馈交付;须新询价则进入选渠阶段。
    ↳ 查历史报价:系统带出在供供应商及历史报价,逐PN核对有效期与历次价格。未达3次询价但有效期已过的,标记须重询。
    ↳ 判定采用策略:BOM早期:有效期内直采;过期浮动≤10%直采、10-20%取均價、>20%重询。BOM后期:历史最低(≥3次)直采,否则降20%谈。现货/样品:一律重询。
  2. S2选渠定策须新询价的料号,按场景确定渠道策略。BOM早期/样品:渠道可放宽,系统带出的供应商直接圈入。BOM后期:必须靠谱——按主供应商→备选供应商→贸易商顺序,圈2~3家,贸易商尽量不采用。现货:仅选有库存且可提供仓库实拍的供应商,不可选无库存转单商。
    ↳ 按场景圈渠道:BOM早期/样品:系统带出即可圈入,可放宽。BOM后期:主→备选→贸易商顺序圈2~3家,贸易商尽量不用。现货:仅选有库存/实拍的供应商,无库存转单商不可选。
    ↳ 渠道资质核实:核实授权代理资质与授权期限;贸易商核查货源链可靠性。
  3. S3发询比价按渠道批量发询,PN/数量/时限一次带足。回价逐单登记供应商回价单。验证规则因场景而异:BOM早期第一个报价即可;BOM后期两轮谈价、按历史最低降20%谈;现货多重校验(低于线上商城、比区域市场价、比订货价);样品低于线上商城即可。回价异常或未应答则追价补询。
    ↳ 批量发询:同一料所有渠道一次发齐;PN/数量/目标价/回价时限写死在询价里。BOM后期默认两轮,首轮后内部review再发次轮。
    ↳ 登记回价:供应商回价单逐单登记:价格/MOQ/交期/有效期/批次DC/成色/渠道等级,一一对应不可缺项。
    ↳ 价格验证:BOM早期:首个报价即用,品牌价差≤20%正常。BOM后期:按历史最低降20%谈,两轮review。现货:低于线上商城+比区域市场+比订货价(>20%可接受)。样品:低于线上商城即用,库内不足线上补。
    ↳ 追价补询:电话催回未应答渠道;不实回价或远低行情则换渠道补询,每轮记录追价次数与结果。
  4. S4反馈交付将确认报价/LT/SPQ/有效期填入寻源比价表,供PM查阅。现货/样品场景多一步:PM向客户反馈→确认下单出具正式报价单→填采购申请表→采购下单(填价格/交期/物流单号)→跟踪到货。
    ↳ 填寻源比价表:将确认报价/LT/SPQ/价格有效期等逐项填入寻源比价表,供PM直接查阅。
    ↳ 下单与跟踪:PM向客户反馈→确认下单出具正式报价单→填入采购申请表。采购接申请后向供应商下单,填写下单价格/交期/物流单号,跟踪到货。
-
全程随时可做:
↳ 知识入库:回价与成交沉淀历史价格情报;渠道表现与配合度回写供应商渠道目录与供应商档案库;新渠道收编。
+
  1. S1接需核史PM在需求库填写项目/PN/数量/场景类型/紧急度后,触发询价任务给采购。系统自动带出在供供应商与历史报价。先核历史:按场景规则逐PN判定是否可直接采用——可直接采用则跳过询价、直接进入反馈交付;须新询价则进入选渠阶段。
    ↳ 查历史报价:系统带出在供供应商及历史报价,逐PN核对有效期与历次价格。未达3次询价但有效期已过的,标记须重询。
    ↳ 判定采用策略:BOM早期:有效期内直采;过期浮动≤10%直采、10-20%取均價、>20%重询。BOM后期:历史最低(≥3次)直采,否则降20%谈。现货/样品:一律重询。
  2. S2选渠定策须新询价的料号,按场景确定渠道策略。BOM早期/样品:渠道可放宽,系统带出的供应商直接圈入。BOM后期:必须靠谱——按主供应商→备选供应商→贸易商顺序,圈2~3家,贸易商尽量不采用。现货:仅选有库存且可提供仓库实拍的供应商,不可选无库存转单商。
    ↳ 按场景圈渠道:BOM早期/样品:系统带出即可圈入,可放宽。BOM后期:主→备选→贸易商顺序圈2~3家,贸易商尽量不用。现货:仅选有库存/实拍的供应商,无库存转单商不可选。
    ↳ 渠道资质核实:核实授权代理资质与授权期限;贸易商核查货源链可靠性。
  3. S3发询比价按渠道批量发询,PN/数量/时限一次带足。回价逐单登记供应商回价单。验证规则因场景而异:BOM早期第一个报价即可;BOM后期两轮谈价、按历史最低降20%谈;现货多重校验(低于线上商城、比区域市场价、比订货价);样品低于线上商城即可。回价异常或未应答则追价补询。
    ↳ 批量发询:同一料所有渠道一次发齐;PN/数量/目标价/回价时限写死在询价里。BOM后期默认两轮,首轮后内部review再发次轮。
    ↳ 登记回价:供应商回价单逐单登记:价格/MOQ/交期/有效期/批次DC/成色/渠道等级,一一对应不可缺项。
    ↳ 价格验证:BOM早期:首个报价即用,品牌价差≤20%正常。BOM后期:按历史最低降20%谈,两轮review。现货:低于线上商城+比区域市场+比订货价(>20%可接受)。样品:低于线上商城即用,库内不足线上补。
    ↳ 追价补询:电话催回未应答渠道;不实回价或远低行情则换渠道补询,每轮记录追价次数与结果。
  4. S4反馈交付将确认报价/LT/SPQ/有效期填入寻源比价表,供PM查阅。现货/样品场景多一步:PM向客户反馈→确认下单出具正式报价单→填采购申请表→采购下单(填价格/交期/物流单号)→跟踪到货。
    ↳ 填寻源比价表:将确认报价/LT/SPQ/价格有效期等逐项填入寻源比价表,供PM直接查阅。
    ↳ 下单与跟踪:PM向客户反馈→确认下单出具正式报价单→填入采购申请表。采购接申请后向供应商下单,填写下单价格/交期/物流单号,跟踪到货。
+
全程随时可做:
↳ 知识入库:回价与成交沉淀历史价格情报;渠道表现与配合度回写供应商渠道目录与供应商档案库;新渠道收编。

§Z 结案:必做的事都办完、没有进行中的事,自动算结案(CMMN AutoComplete)。 寻源比价表交付PM即结案。现货/样品场景还需PM确认下单,之后由发起方继续报价与下单跟踪。回价与成交沉淀历史价格情报,渠道表现回写供应商渠道目录——每询一轮,行情底账厚一层。

@@ -1164,6 +1261,6 @@ table.ct td{border:1px solid var(--line);padding:7px 9px;vertical-align:top;font
- + \ No newline at end of file diff --git a/docs/superpowers/plans/2026-07-27-mvp-foundation.md b/docs/superpowers/plans/2026-07-27-mvp-foundation.md new file mode 100644 index 0000000..152b44c --- /dev/null +++ b/docs/superpowers/plans/2026-07-27-mvp-foundation.md @@ -0,0 +1,975 @@ +# MVP 底座(四域数据 · 1:1 流程包 · 三类工具 · 卡片设计台)实施计划 + +> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking. + +**Goal:** 按 `docs/MVP示例工作流.html` 一比一落一个流程包实例(统一报价:6 活动槽位 + 1 审批点 + 3 网关 + 双终点),数据按 客户/情报/供应商/项目 四域重划,工具箱呈现 功能/LLM/人类 三类已有工具与 自定义导入/MCP 接入,设计台四库全部卡片化;活动只落**槽位契约**,不刻画实现。 + +**Architecture:** 种子重写为三件套(`seed-mvp-data` 四域对象声明 / `seed-mvp-slots` 六槽位清单经安装通道装入 / `seed-mvp-flow` 流程包 v1 + 手绘图坐标 1:1 + 触发器与通道),声明物化自动建四域十八对象;活动与工具靠**声明名**解耦(`declarations.tools` 只写名字,白名单在治理台)。前端:`domains.ts` 换四域短名,设计台四页换 `g-tile`/卡片网格,工具箱一页四段。 + +**Tech Stack:** 既有栈零新增 —— zod 契约 + 安装通道(`registry.install` 顺带声明物化)、diagram-js 手绘图存证(`pkg.diagram`)、React + `g-*` 皮肤(console.css 已有类 + 既有「三面补充」节)。 + +## Global Constraints + +- 五门全绿才算一个任务完成:`pnpm typecheck && pnpm lint && pnpm depcruise && pnpm api:check && pnpm test`(契约变更:同步 CONTRACT.md → `pnpm api:check --update` → `git add api-report`)。 +- §12.5 禁用:`any`、`as unknown as`、`@ts-ignore`、domain 层 IO、全局可变状态、删测试、改门禁配置。 +- **mock 只允许出现在外界**:槽位活动**不得**内置假执行(不发既定载荷、不装作跑过);未实现就是未实现,起单后任务停在那里是诚实状态。 +- **流程包只落一个实例**:种子只产出 `unified-quote` v1(published),不再产出多版本;验收含「库里恰一行」。 +- **活动与工具完全解耦**:槽位清单 `declarations.tools` 只引用工具**名**;工具注册、连接值、白名单全在治理侧(seed 的 toolbox 段),槽位不含任何工具实现或 import。 +- 活动细节不刻画:槽位的 `assets.businessModel` 只携 MVP 文档里的步骤/里程碑**骨架**(标题级),入口产物为注释性占位 JS(不可执行语义,运行时如实报「未实现」)。 +- 密钥只从环境读(`JCAI_DEEPSEEK_API_KEY`);种子口令走 `JCAI_SEED_PASSWORD`。 +- 提交信息中文一句话,结尾两行: + `Co-Authored-By: Claude Fable 5 ` 与 `Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m`。 +- 服务:API `:8787`、Web `:5273`;账号 `Chaihao` / `ch19900614`;curl 先 `POST /api/login` 拿 cookie。 +- 本计划会**整库重建**(`docker compose down -v`)—— 现有运行数据(在途单/消息)全部清掉,这是四域重划的必然代价,执行前无需再确认(用户已在需求 2 中决定重划)。 + +--- + +## 版图(先读懂再动手) + +### 四域十九对象(需求 2 的落法) + +划分原则:**流转单据(过程)归项目域;沉淀资产按内容归 客户/情报/供应商**。 +定价审批表不入台账:MVP 标其载体为「审批流」—— 它就是审批点的审批单记录,落在审批机制里(sys 侧),不物化为数据对象。 + +| 域 | 键 | 短名 | 对象(object 键 · 中文名) | +|---|---|---|---| +| 项目 | `project` | 项目 | `rfq_file` RFQ/BOM文件 · `intake_record` 统一受理记录 · `pn_class` 料号分类表 · `alt_request` 替代评估请求 · `inquiry_request` 询价请求 · `supplier_floor` 供应商底价表 · `alt_benchmark` 替代对标表 · `sourcing_compare` 寻源比价表 · `quote_draft` 报价草案 · `formal_quote` 正式报价单 · `followup` 跟进提醒 · `landing_stats` 报价落地率统计 | +| 客户信息 | `customer` | 客户 | `profile` 客户资料库 | +| 市场与销售情报 | `intel` | 情报 | `history_price` 历史价格情报 · `chip_spec` 芯片规格书 · `public_select` 公网选型库 | +| 供应商信息 | `supplier` | 供应商 | `channel_dir` 供应商渠道目录 · `dead_stock` 呆滞库存表 | + +字段全表(name:type,`*`=主键;type ∈ text/number/boolean/date/timestamp/json,label 用 MVP 中文名): + +``` +project.rfq_file RFQ/BOM文件 *rfq_ref:text *pn:text qty_eau:text brand:text analog_flag:boolean aec_cert:text target_price:number lead_time:text +project.intake_record 统一受理记录 *customer_code:text *pn:text brand:text eau:text type_tag:text target_price:number status:text +project.pn_class 料号分类表 *pn:text type_tag:text basis:text history_hit:boolean review_note:text +project.alt_request 替代评估请求 *material:text chip_type:text spec_params:text scenario:text requester:text +project.inquiry_request 询价请求 *pn:text brand:text era:text project_stage:text accept_alt:boolean unit_usage:text tp:number scenario:text +project.supplier_floor 供应商底价表 *pn:text *supplier:text floor_price:number moq:text lead_time:text +project.alt_benchmark 替代对标表 *original_pn:text *candidate_pn:text alt_grade:text param_diff:text diff_risk:text mod_eval:text verify_advice:text +project.sourcing_compare 寻源比价表 *pn:text *supplier:text quote_price:number moq:text lead_time:text channel_grade:text condition:text verdict:text +project.quote_draft 报价草案 *pn:text proposed_price:number margin:number deviation:number +project.formal_quote 正式报价单 *pn:text unit_price_cny:number lead_time:text spq:text moq:text trade_terms:text valid_until:date +project.followup 跟进提醒 *quote_no:text customer_code:text d3:date d7:date reply_status:text +project.landing_stats 报价落地率统计 *period:text landing_rate:number type_a_hit:number d3_reply_rate:number return_rate:number +customer.profile 客户资料库 *customer_code:text grade:text tags:text payment_terms:text industry:text risk_level:text annual_purchase:number +intel.history_price 历史价格情报 *pn:text *quoted_at:timestamp brand:text unit_price_cny:number lead_time:text moq:text valid_until:date +intel.chip_spec 芯片规格书 *pn:text key_params:text package:text version_date:date +intel.public_select 公网选型库 *alt_relation:text param_compare:text spec_ref:text lifecycle:text price_ref:text +supplier.channel_dir 供应商渠道目录 *supplier:text channel_type:text brand_lines:text contact:text +supplier.dead_stock 呆滞库存表 *pn:text stock_qty:number stock_age:text cost_price:number +``` + +### 六个活动槽位 + 一个审批点(契约面;MVP §1.1–1.7 一比一) + +| 槽位 id | 节点 | 名 | 范式 | 岗位 | 入(契约 input) | 出口(output.mandatory) | 声明的域对象(reads→writes) | +|---|---|---|---|---|---|---|---| +| `rfq-intake` | A1 | 客户RFQ受理 | flow | BD | subject/body/customerCode/rfqRef | `intake`:统一受理记录(records)+ `needAlternative:boolean` + `needSourcing:boolean` | 读 intel.history_price · customer.profile → 写 project.rfq_file · intake_record · pn_class · alt_request · inquiry_request | +| `alt-selection` | A2 | 替代选型 | loop | FAE | 替代评估请求(material/chip_type/spec_params/scenario)+ needSourcing 透传 | `benchmark`:替代对标表 + `needSourcing:boolean`(原样带出) | 读 intel.chip_spec · intel.public_select → 写 project.alt_benchmark | +| `sourcing-inquiry` | A3 | 寻源询价 | loop | PRM | 询价请求(pn/brand/era/…) | `compare`:寻源比价表 + 供应商底价表 | 读 supplier.channel_dir · supplier.dead_stock → 写 project.sourcing_compare · project.supplier_floor | +| `cost-pricing` | A4 | 成本定价 | flow | BD | 受理记录 + 底价/对标(可空) | `draft`:报价草案 | 读 intel.history_price · customer.profile → 写 project.quote_draft | +| `quote-negotiation` | A6 | 报价议价 | loop | BD | 报价草案(已批准)+ 定价审批表 | `formal`:正式报价单 + 跟进提醒 + `outcome:"won"\|"revise"\|"lost"` | 写 project.formal_quote · project.followup | +| `intel-archive` | A7 | 情报归档 | flow | BD | 议价结果与单据 | `stats`:落地率统计 | 写 intel.history_price · customer.profile · project.landing_stats | + +> **A5 定价审批 = 内置审批点**(教义:审批点与网关是系统内置要素,零开发、不入库;审批不是任务)。 +> 审批点自带 通过/驳回 两出口:通过走 A5→A6 边;驳回走 `reject: { kind:'reopen', nodeId:'A4', mapping }` +> 声明(v1 旧包的 AP 节点即此范式,mapping 照抄其式样)。**G3「审批结果」被审批点吸收** —— +> 判据就是审批结果本身,不另立网关;图上以琥珀审批框 + 通过边(ok)+ 底部「退回调整→A4」卡点呈现, +> 与 MVP 图差一颗菱形,语义同构(此取舍已与用户确认:A5 必须是审批点)。 + +### 流程包 1:1(节点 · 坐标取自 MVP SVG,已取整到 10px 珊格) + +语义节点 13 + 图上卡点 2(卡点只入 `diagram`,不入语义): + +| id | kind | label | x,y(w×h) | 备注 | +|---|---|---|---|---| +| start | start | 客户RFQ询价 | 30,62(36×36) | | +| A1 | activity | 客户RFQ受理 | 150,60(100×40) | sub:BD | +| G1 | gateway(exclusive/fork) | 是否需要选型 | 293,58(44×44) | basis:受理判定 needAlternative | +| A2 | activity | 替代选型 | 390,60(100×40) | sub:FAE | +| G2 | gateway(exclusive/fork) | 是否需要寻源 | 553,58(44×44) | basis:受理判定 needSourcing | +| A3 | activity | 寻源询价 | 660,60(100×40) | sub:PRM | +| A4 | activity | 成本定价 | 810,60(100×40) | sub:BD | +| A5 | approval | 定价审批 | 810,260(100×40) | sub:PM · 审批点(琥珀) | +| A6 | activity | 报价议价 | 370,260(100×40) | sub:BD | +| G4 | gateway(exclusive/fork) | 议价结果 | 183,258(44×44) | basis:A6 outcome(G3 已被审批点吸收,G4 保留) | +| A7 | activity | 情报归档 | 150,170(100×40) | sub:BD | +| end_won | end | 转订单履约 | 30,262(36×36) | 图上 end(绿) | +| end_arch | end | 归档闭环 | 30,172(36×36) | 图上 end-bad(红) | +| (callout) | callout | 退回调整→A4 | 590,370(100×30) | 仅 diagram | +| (callout) | callout | 返回调整→A4 | 150,370(100×30) | 仅 diagram | + +边 15(label/tone 按图;条件按上表出参;mapping 见 Task 4 代码)。 +A5 的**驳回不是边**:走审批点 reject 声明(reopen A4),图上由「退回调整→A4」卡点呈现: + +``` +start→A1 (起单五映射:customerCode/rfqRef/subject/body/quotedAt) +A1→G1 +G1→A2 label 需要选型 cond: needAlternative = true +G1→G2 label 不需要选型 cond: needAlternative = false (走图顶部旁路) +A2→G2 +G2→A3 label 需要寻源 cond: needSourcing = true +G2→A4 label 不需要寻源 cond: needSourcing = false +A3→A4 +A4→A5 label 报价草案提审 +A5→A6 label 通过 tone ok (审批点通过出口;驳回走 reject 声明,非边) +A6→G4 +G4→end_won label 成交 tone ok cond: outcome = "won" +G4→A4 label 有异议 tone bad cond: outcome = "revise" reopen: true +G4→A7 label 拒绝/超时 tone bad cond: outcome = "lost" +A7→end_arch label 归档闭环 +``` + +> 网关条件的求值作用域是 `{...initiation, ...vars, ...payload}`(process-service.ts:184), +> payload 是**上一发射节点**的出口载荷 —— 所以 G2 在「A2 路径」上读的是 A2 的载荷, +> A2 契约必须把 `needSourcing` 原样带出(上表已列)。G1 旁路(G1→G2)时载荷穿网关不换, +> G2 读到的仍是 A1 的载荷,两条入路都取到 needSourcing。 + +### 工具箱四段(需求 4) + +| 段 | 内容 | 来源 | 状态 | +|---|---|---|---| +| 功能工具 | `crm.history-price-read`(读)· `mail.send`(写) | toolbox 目录(种子注册,两审) | 实装,白名单按槽位授 | +| LLM 工具 | deepseek-v4-flash / deepseek-v4-pro / quote-extractor | llm 模块实例(`listLlmInstancesRoute`) | 实装(调模型经 ModelGateway 一缝) | +| 人类工具 | 执行工单 · 验收工单 · 决策卡 · 补全卡 · 评价卡 | human-tool 模块(card.ts 五形态) | 实装(调人经工单/卡族),目录静态呈现 | +| 接入 | 导入自定义工具(表单→`toolbox.register` 两审入目录)· 连接 MCP(说明卡) | 新路由 `registerToolRoute`;MCP 无运行时 | 导入实装;MCP 仅呈现+记 debt | + +--- + +### Task 1: 四域短名与业务序(前端命名层) + +**Files:** +- Modify: `apps/web/src/shared/gov/domains.ts` +- Modify: `apps/web/src/shared/gov/__tests__/domains.test.ts` + +**Interfaces:** +- Produces: `DOMAIN_SHORT` 含 `customer:'客户' intel:'情报' supplier:'供应商' project:'项目'`;`DOMAIN_ORDER = ['project','customer','intel','supplier']`(项目是每天看的,排第一);`domainShort`/`sortDomains` 签名不变。 + +- [ ] **Step 1: 改测试(先红)** + +`domains.test.ts` 整段替换两个用例的期望: + +```ts + it('已知域给 2-3 字人读名', () => { + expect(domainShort('project')).toBe('项目'); + expect(domainShort('customer')).toBe('客户'); + expect(domainShort('intel')).toBe('情报'); + expect(domainShort('supplier')).toBe('供应商'); + }); +``` + +`sortDomains` 用例期望改为: + +```ts + expect(sortDomains(['supplier', 'intel', 'zzz_custom', 'project'])).toEqual([ + 'project', + 'intel', + 'supplier', + 'zzz_custom', + ]); +``` + +- [ ] **Step 2: 跑测试确认失败** + +Run: `pnpm exec vitest run apps/web/src/shared/gov 2>&1 | tail -5` +Expected: FAIL(旧字典是 quote_* 键)。 + +- [ ] **Step 3: 改实现** + +`domains.ts` 的字典与序换成: + +```ts +export const DOMAIN_SHORT: Readonly> = { + project: '项目', + customer: '客户', + intel: '情报', + supplier: '供应商', +}; + +/** 业务序:项目(每天看的)→ 客户 → 情报 → 供应商;字典外的域殿后 */ +const DOMAIN_ORDER = ['project', 'customer', 'intel', 'supplier']; +``` + +(`domainShort` 回落逻辑与 `sortDomains` 本体不动。) + +- [ ] **Step 4: 测试过 + 提交** + +Run: `pnpm exec vitest run apps/web/src/shared/gov 2>&1 | tail -4` → PASS。 + +```bash +git add apps/web/src/shared/gov/domains.ts apps/web/src/shared/gov/__tests__/domains.test.ts +git commit -m "MVP底座①:数据四域命名 —— 项目/客户/情报/供应商" +``` + +--- + +### Task 2: 四域对象声明(seed 数据件) + +**Files:** +- Create: `apps/api/src/app/seed-mvp-data.ts` +- Test: `apps/api/src/app/__tests__/seed-mvp-data.test.ts` + +**Interfaces:** +- Consumes: `objectDeclarationSchema`(@contracts:domain/object/label/fields[{name,type,label,primaryKey}])。 +- Produces: + ```ts + export const MVP_OBJECTS: readonly ObjectDeclaration[]; // 19 个,即版图字段全表 + export function declarationsFor(objects: readonly `${string}.${string}`[]): ObjectDeclaration[]; + ``` + `declarationsFor(['project.intake_record', ...])` 供槽位清单按名取声明子集。 + +- [ ] **Step 1: 写失败测试** + +```ts +/** + * 四域十九对象 —— 声明即物化的输入。守三件事:数量与域别齐、主键齐、按名可取。 + */ +import { describe, expect, it } from 'vitest'; +import { MVP_OBJECTS, declarationsFor } from '../seed-mvp-data.ts'; + +describe('MVP_OBJECTS', () => { + it('四域十八对象,不多不少 —— 定价审批表载体是审批流,不入台账', () => { + expect(MVP_OBJECTS).toHaveLength(18); + const byDomain = Object.groupBy(MVP_OBJECTS, (o) => o.domain); + expect(byDomain['project']).toHaveLength(12); + expect(byDomain['customer']).toHaveLength(1); + expect(byDomain['intel']).toHaveLength(3); + expect(byDomain['supplier']).toHaveLength(2); + }); + + it('每个对象至少一个主键字段 —— 只增不破坏靠主键立身', () => { + for (const o of MVP_OBJECTS) { + expect(o.fields.some((f) => f.primaryKey), `${o.domain}.${o.object}`).toBe(true); + } + }); + + it('declarationsFor 按名取子集,名不存在即抛', () => { + expect(declarationsFor(['project.intake_record', 'intel.history_price'])).toHaveLength(2); + expect(() => declarationsFor(['project.nope'])).toThrow('未知对象'); + }); +}); +``` + +- [ ] **Step 2: 跑测试确认失败** + +Run: `pnpm exec vitest run apps/api/src/app/__tests__/seed-mvp-data.test.ts 2>&1 | tail -4` → FAIL。 + +- [ ] **Step 3: 写实现** + +按「版图 · 字段全表」逐对象转录(`objectDeclarationSchema.parse` 包住,label 用中文名)。骨架 + 一个完整示例,其余 18 个照表机械展开: + +```ts +/** + * 四域十八对象(docs/MVP示例工作流.html · 动态数据 + 静态底座;定价审批表落审批机制,不入台账)。 + * 划分原则:流转单据归 project;沉淀资产按内容归 customer / intel / supplier。 + * 声明只写活动**要用**的字段;物化走安装通道的声明合并(最大化合并、只增不破坏)。 + */ +import { objectDeclarationSchema } from '@contracts'; +import type { ObjectDeclaration } from '@contracts'; + +const f = (name: string, type: 'text' | 'number' | 'boolean' | 'date' | 'timestamp', label: string, primaryKey = false) => + ({ name, type, label, primaryKey, masked: false }); + +export const MVP_OBJECTS: readonly ObjectDeclaration[] = [ + objectDeclarationSchema.parse({ + domain: 'project', + object: 'intake_record', + label: '统一受理记录', + fields: [ + f('customer_code', 'text', '客户码', true), + f('pn', 'text', 'PN', true), + f('brand', 'text', '厂牌'), + f('eau', 'text', 'EAU'), + f('type_tag', 'text', 'Type标'), + f('target_price', 'number', '目标价'), + f('status', 'text', '状态'), + ], + }), + // …其余 18 个:严格照「版图 · 字段全表」,*号列 primaryKey=true +]; + +export function declarationsFor(objects: readonly `${string}.${string}`[]): ObjectDeclaration[] { + return objects.map((key) => { + const [domain, object] = key.split('.'); + const hit = MVP_OBJECTS.find((o) => o.domain === domain && o.object === object); + if (hit === undefined) throw new Error(`未知对象:${key} —— 先在 MVP_OBJECTS 登记`); + return hit; + }); +} +``` + +- [ ] **Step 4: 测试过 + 提交** + +Run: `pnpm exec vitest run apps/api/src/app/__tests__ 2>&1 | tail -4` → PASS;`pnpm typecheck` 归零。 + +```bash +git add apps/api/src/app/seed-mvp-data.ts apps/api/src/app/__tests__/seed-mvp-data.test.ts +git commit -m "MVP底座②:四域十八对象声明 —— 流转归项目,沉淀归客户/情报/供应商" +``` + +--- + +### Task 3: 六槽位清单 + 经安装通道装入 + +**Files:** +- Create: `apps/api/src/app/seed-mvp-slots.ts` +- Test: `apps/api/src/app/__tests__/seed-mvp-slots.test.ts` + +**Interfaces:** +- Consumes: `activityManifestSchema`(identity/contract/declarations/assets/samples/entry)、`declarationsFor`(Task 2)。 +- Produces: + ```ts + export const MVP_SLOTS: readonly ActivityManifest[]; // 6 个,id 见版图槽位表(A5 是审批点,不在其列) + export async function installSlots(container: Container): Promise; // 逐个 registry.install + export const SLOT_ARTIFACT: string; // 占位入口 JS(注释体,不可执行语义) + ``` + +- [ ] **Step 1: 写失败测试** + +```ts +/** + * 六个活动槽位 —— 契约就绪、实现留白。守:范式/岗位/出口与 MVP 一致; + * 声明只有名(工具按名引用、域对象按名取)—— 活动与工具的解耦就靠这一条。 + * A5 定价审批是**内置审批点**,零开发、不入库 —— 不在槽位之列。 + */ +import { describe, expect, it } from 'vitest'; +import { MVP_SLOTS, SLOT_ARTIFACT } from '../seed-mvp-slots.ts'; + +describe('MVP_SLOTS', () => { + it('六槽位,id 与范式如 MVP(A5 审批点内置,不入库)', () => { + const byId = new Map(MVP_SLOTS.map((m) => [m.identity.activityId, m.identity.paradigm])); + expect(MVP_SLOTS).toHaveLength(6); + expect(byId.get('rfq-intake')).toBe('flow'); + expect(byId.get('alt-selection')).toBe('loop'); + expect(byId.get('sourcing-inquiry')).toBe('loop'); + expect(byId.get('cost-pricing')).toBe('flow'); + expect(byId.has('pricing-approval')).toBe(false); + expect(byId.get('quote-negotiation')).toBe('loop'); + expect(byId.get('intel-archive')).toBe('flow'); + }); + + it('A1 出口带两枚去向旗;A2 透传 needSourcing —— 网关条件的数据来源', () => { + const a1 = MVP_SLOTS.find((m) => m.identity.activityId === 'rfq-intake')!; + const props = (a1.contract.output.mandatory[0]!.payload as { properties?: Record }).properties ?? {}; + expect(Object.keys(props)).toEqual(expect.arrayContaining(['needAlternative', 'needSourcing'])); + const a2 = MVP_SLOTS.find((m) => m.identity.activityId === 'alt-selection')!; + const p2 = (a2.contract.output.mandatory[0]!.payload as { properties?: Record }).properties ?? {}; + expect(Object.keys(p2)).toContain('needSourcing'); + }); + + it('槽位不携实现:入口是注释占位,工具声明只有名', () => { + expect(SLOT_ARTIFACT).toContain('槽位'); + for (const m of MVP_SLOTS) { + for (const t of m.declarations.tools) expect(typeof t.name).toBe('string'); + } + }); +}); +``` + +- [ ] **Step 2: 跑测试确认失败** → FAIL(文件不存在)。 + +- [ ] **Step 3: 写实现** + +要点(完整写 A1,其余 6 个按版图槽位表机械展开): + +```ts +import { createHash } from 'node:crypto'; +import { activityManifestSchema } from '@contracts'; +import type { ActivityManifest } from '@contracts'; +import type { Container } from './container.ts'; +import { declarationsFor } from './seed-mvp-data.ts'; + +/** + * 槽位占位入口 —— **不是实现**:运行时装载它只会得到「未实现」的诚实报错。 + * mock 只许在外界:这里绝不发既定载荷装作跑过(README 平移规则)。 + */ +export const SLOT_ARTIFACT = [ + '// 活动槽位:契约已就绪,实现待底座完备后逐个开发。', + "throw new Error('活动尚未实现 —— 这是槽位,契约见治理台活动库');", +].join('\n'); + +const checksum = createHash('sha256').update(SLOT_ARTIFACT).digest('hex'); + +/** flow 槽位的业务模型骨架:MVP 作业指导书的步骤标题,一步一条 human 执行工单 —— 未实现期人工可兜 */ +const flowSkeleton = (steps: readonly string[]) => ({ + paradigm: 'flow' as const, + steps: steps.map((label, i) => ({ + id: `S${i + 1}`, + label, + kind: 'human' as const, + workOrder: 'execution' as const, + card: {}, + deadline: 'P1D', + })), + parallelGroups: [], +}); + +/** loop 槽位:CMMN 骨架(MVP 案例图的项),叙事 = 案例卡原文一句话 */ +const loopSkeleton = (items: readonly string[], narrative: string) => ({ + paradigm: 'loop' as const, + cmmnXml: `${items.map((it) => ``).join('')}`, + narrative, + dmn: { drd: [], tables: [] }, +}); + +const identity = (activityId: string, name: string, paradigm: 'flow' | 'loop') => ({ + activityId, name, packageVersion: '0.1.0', category: '统一报价', paradigm, + sdkVersion: '1.0.0', checksum, +}); + +const harness = { memoryWindow: 20, stallAfter: 'PT30M', nudge: [] }; + +export const MVP_SLOTS: readonly ActivityManifest[] = [ + activityManifestSchema.parse({ + identity: identity('rfq-intake', '客户RFQ受理', 'flow'), + contract: { + activityId: 'rfq-intake', version: '0.1.0', + // contractInputSchema:data 是 JSON schema;message 允许但不得携带扩大授权的效力 + input: { + data: { type: 'object', required: ['customerCode', 'rfqRef'], properties: { + customerCode: { type: 'string' }, rfqRef: { type: 'string' }, + subject: { type: 'string' }, body: { type: 'string' }, quotedAt: { type: 'string' } } }, + messageAllowed: true, + }, + output: { mandatory: [{ name: 'intake', description: '统一受理记录(打标)', payload: { + type: 'object', required: ['records', 'needAlternative', 'needSourcing'], properties: { + records: { type: 'array' }, pn: { type: 'string' }, type_tag: { type: 'string' }, + needAlternative: { type: 'boolean' }, needSourcing: { type: 'boolean' } } } }], selective: [] }, + requiredDeliverables: [], acceptanceCriteria: [], prohibitions: [], + authorization: { discretion: [], preauthorizedActions: [], humanCallBudget: 3 }, + resources: { + tools: [{ name: 'crm.history-price-read' }], skills: [], models: [], roles: ['BD'], + budget: { steps: 40, tokens: 200_000, activeMinutes: 30, humanCalls: 3 }, + }, + }, + declarations: { + models: [], listeners: [], harness, + tools: [{ name: 'crm.history-price-read' }], + ledger: declarationsFor([ + 'project.rfq_file', 'project.intake_record', 'project.pn_class', + 'project.alt_request', 'project.inquiry_request', + 'intel.history_price', 'customer.profile', + ]), + }, + assets: { + businessModel: flowSkeleton(['接收登记', '追问补全信息', '逐条解析归一', '查历史价', '逐条定状况标', '定去向与派单']), + skills: [], viewTemplates: [], cardSchemas: {}, distillHooks: [], + }, + samples: [{ name: '契约样例:受理一单', input: { customerCode: 'C001', rfqRef: 'RFQ-001' }, + expect: { ports: ['intake'] } }], + entry: { file: 'index.js', checksum }, + }), + // …A2/A3/A4/A6/A7 同构:范式/岗位见版图表;out 口 payload 至少含表中出参; + // A6 含 outcome:{enum:['won','revise','lost']}; + // businessModel:A4 flowSkeleton(['取价基准','逐条定价']); + // A7 flowSkeleton(['结果登记','画像更新','落地率统计']); + // A2 loopSkeleton(['替代对标表','初筛清单'], 'MVP §1.5:齐了即收 —— 必做项完成且无进行中项即结案'); + // A3 loopSkeleton(['寻源比价表','供应商回价单'], 'MVP §1.7:齐了即收'); + // A6 loopSkeleton(['正式报价单'], 'MVP §1.4:上接审批通过,办结经议价结果定去向'); +]; + +export async function installSlots(container: Container): Promise { + for (const manifest of MVP_SLOTS) { + const verdict = await container.registry.install(manifest, SLOT_ARTIFACT); + process.stdout.write(` 槽位 ${manifest.identity.name}(${manifest.identity.paradigm})静态审 ${verdict.staticFindings.length} 条\n`); + } +} +``` + +注意两处形状要以真实 schema 为准(写前 grep 校对,发现不合就以 schema 为准调用例): +`contractInputSchema` / `outputPortsSchema`(contract7.ts)与 `authorization`/`resources` 的必填名; +静态审若因「工具契约缺失」报 error,把该工具名先注册(Task 5 先行注册两件功能工具即可覆盖)。 + +- [ ] **Step 4: 测试过 + typecheck + 提交** + +```bash +pnpm exec vitest run apps/api/src/app/__tests__ && pnpm typecheck +git add apps/api/src/app/seed-mvp-slots.ts apps/api/src/app/__tests__/seed-mvp-slots.test.ts +git commit -m "MVP底座③:六活动槽位清单 —— 契约就绪,实现留白,工具按名解耦" +``` + +--- + +### Task 4: 流程包 1:1 + 触发器/通道 + 种子切换 + 整库重建 + +**Files:** +- Create: `apps/api/src/app/seed-mvp-flow.ts` +- Create: `apps/api/src/app/seed-mvp.ts`(编排 ①LLM ②工具 ③槽位 ④流程包+触发器+通道) +- Modify: `apps/api/src/app/seed.ts`(改调 `seedMvp`) +- Delete: `apps/api/src/app/seed-quote.ts` +- Test: `apps/api/src/app/__tests__/seed-mvp-flow.test.ts` + +**Interfaces:** +- Consumes: `processPackageSchema`(nodes/edges/diagram)、`triggerConfigSchema`、Task 3 的槽位 id。 +- Produces: `export const MVP_PACKAGE: ProcessPackage`(id `unified-quote`,version 1,含 `diagram`);`export async function seedMvpFlow(container): Promise`。 + +- [ ] **Step 1: 写失败测试(拓扑即契约)** + +```ts +/** + * 流程包 1:1 —— 守三件事:拓扑与 MVP 图一致;网关条件读得到出参;闭合校验可发布。 + */ +import { describe, expect, it } from 'vitest'; +import { MVP_PACKAGE } from '../seed-mvp-flow.ts'; + +describe('MVP_PACKAGE', () => { + it('13 语义节点 · 15 边 · 三网关一审批点双终点', () => { + expect(MVP_PACKAGE.nodes).toHaveLength(13); + expect(MVP_PACKAGE.edges).toHaveLength(15); + expect(MVP_PACKAGE.nodes.filter((n) => n.kind === 'end')).toHaveLength(2); + expect(MVP_PACKAGE.nodes.filter((n) => n.kind === 'gateway')).toHaveLength(3); + expect(MVP_PACKAGE.nodes.filter((n) => n.kind === 'approval')).toHaveLength(1); + }); + + it('A5 是审批点:PM 审,驳回 reopen 回 A4 —— 驳回不是边', () => { + const a5 = MVP_PACKAGE.nodes.find((n) => n.id === 'A5'); + expect(a5?.kind).toBe('approval'); + if (a5?.kind !== 'approval') return; + expect(a5.approver.position).toBe('PM'); + expect(a5.reject.kind).toBe('reopen'); + if (a5.reject.kind === 'reopen') expect(a5.reject.nodeId).toBe('A4'); + // 唯一的 reopen 边是议价「有异议」回 A4 + expect(MVP_PACKAGE.edges.filter((e) => e.reopen).map((e) => `${e.from}→${e.to}`)).toEqual(['G4→A4']); + }); + + it('网关条件按出参写:G1/G2 读旗,G4 读 outcome', () => { + const cond = (from: string, to: string) => MVP_PACKAGE.edges.find((e) => e.from === from && e.to === to)?.condition; + expect(cond('G1', 'A2')).toBe('needAlternative = true'); + expect(cond('G2', 'A4')).toBe('needSourcing = false'); + expect(cond('G4', 'A7')).toBe('outcome = "lost"'); + }); + + it('手绘图存证在包上 —— 呈现 1:1 的真相', () => { + expect(MVP_PACKAGE.diagram).toBeDefined(); + const nodes = (MVP_PACKAGE.diagram as { nodes: { id: string; kind: string }[] }).nodes; + expect(nodes.filter((n) => n.kind === 'callout')).toHaveLength(2); + }); +}); +``` + +- [ ] **Step 2: 确认失败** → FAIL。 + +- [ ] **Step 3: 写 `seed-mvp-flow.ts`** + +按「版图 · 节点表 + 边表」逐行转录。骨架: + +```ts +export const MVP_PACKAGE = processPackageSchema.parse({ + id: 'unified-quote', + name: '统一报价', + version: 1, + state: 'draft', + callInterface: { input: { type: 'object', required: ['customerCode', 'rfqRef'], properties: { + customerCode: { type: 'string' }, rfqRef: { type: 'string' }, + subject: { type: 'string' }, body: { type: 'string' }, quotedAt: { type: 'string' } } }, + output: { type: 'object', properties: { landingRate: { type: 'number' } } } }, + nodes: [ /* 节点表 13 行:activity 带 owner{position,strategy:'sole'} failure{kind:'terminate'}; + A5 审批点照 v1 的 AP 节点范式: + { id:'A5', kind:'approval', label:'定价审批', + approver:{ position:'PM', strategy:'sole' }, + reject:{ kind:'reopen', nodeId:'A4', mapping:[…照 v1 e-g4-a4 式样,从 intake/draft 口取] }, + nudge:{ steps:[{ after:'PT20M', action:'nudge' }], deadline:'PT30M' }, + layout:{ row:1, col:6, x:810, y:260 } } + gateway 带 gateway:'exclusive' mode:'fork' basis;layout{row,col,x,y} 用坐标表 x,y */ ], + edges: [ /* 边表 15 行:label/tone/condition/reopen 逐字照表;mapping: + start→A1 五条 initiation 映射(customerCode/rfqRef/subject/body/quotedAt) + G1→A2 { target:'material',source:{from:'output-port',port:'intake',path:'pn'} } 等按 A2 入参 + G2→A3 按 A3 入参自 intake 口取 pn/brand + G2→A4 / A3→A4 / A2→G2:A4 入参自 intake 口 + 上游口(supplier_floor/benchmark 可空) + A4→A5 { target:'draft',source:{from:'output-port',port:'draft',path:'rows'} } + A5→A6 通过(审批点唯一出边):draft 口取报价草案,照 v1 e-ap-a6 式样 + G4→A4(reopen) 参照旧 v1 的 reopen 映射式样(定稿于库中 v1:e-g4-a4) + G4→A7 outcome/quote_no/customer_code 自 formal 口 + 末端两边 mapping: [] */ ], + variables: [], + diagram: { /* FlowGraph:节点表全部 15 项(13 语义 + 2 callout)带 x/y/w/h; + edges 带 label/tone 与折点(A4→A5 走右侧 910,80→990,80→990,280→910,280; + G1→G2 顶部旁路经 y≈20;G4→A4 回边走底部 y≈370 过「返回调整→A4」卡点; + 「退回调整→A4」卡点(590,370)是 A5 驳回声明的呈现,不带边) */ }, +}); +``` + +`seed-mvp.ts` 统筹(顺序:LLM → 工具+白名单 → 槽位 → 流程包发布 → 触发器/通道),其中 +LLM 段与通道段**整段沿用** `seed-quote.ts` 现文(deepseek 三实例、`ch-rfq-mail`/`ch-rfq-review`、 +`trg-rfq`(event)与 `trg-rfq-manual`(registration)),白名单换新槽位 id: + +```ts +await container.toolbox.setAllowlist('rfq-intake', ['crm.history-price-read']); +await container.toolbox.setAllowlist('cost-pricing', ['crm.history-price-read']); +await container.toolbox.setAllowlist('quote-negotiation', ['crm.history-price-read', 'mail.send']); +await container.toolbox.setAllowlist('sourcing-inquiry', ['crm.history-price-read', 'mail.send']); +await container.toolbox.setAllowlist('alt-selection', ['crm.history-price-read']); +await container.toolbox.setAllowlist('intel-archive', []); +``` + +功能工具只留 `HISTORY_TOOL` 与 `MAIL_TOOL` 两件(quote-* 私有纯工具随旧活动退场 —— 纯工具属活动实现,槽位期没有实现就没有纯工具)。`seed.ts` 把 `seedQuote` 换成 `seedMvp`;删除 `seed-quote.ts`。 + +- [ ] **Step 4: 整库重建 + 种子** + +```bash +pnpm db:down && docker compose down -v 2>/dev/null; pnpm db:up && sleep 4 && pnpm db:migrate && pnpm db:seed +``` +Expected 种子日志:LLM 三实例;两件功能工具;七槽位装入(静态审无 error); +`流程包「统一报价」v1 已发布 —— 13 节点`;触发器两条 + 通道两条。 + +- [ ] **Step 5: 单实例与物化验收(curl + SQL)** + +```bash +docker exec jcai-pg psql -U jcai -d jcai -tAc "select id, version, state from sys.process_package;" +# 期望:恰一行 unified-quote|1|published +docker exec jcai-pg psql -U jcai -d jcai -tAc "select schemaname, count(*) from pg_tables where schemaname in ('project','customer','intel','supplier') group by 1 order by 1;" +# 期望:customer 1 · intel 3 · project 12 · supplier 2 +``` +再起服务用 Chaihao 登录 → `GET /api/gov/process` 恰一包;`/design` 流程包页恰一张卡, +点开画布 1:1(双终点、四网关、两卡点、边标签齐)。 + +- [ ] **Step 6: 五门 + 提交** + +api:check 若报 seed 相关 d.ts 变化照常 `--update`。 + +```bash +git add -A && git commit -m "MVP底座④:统一报价 1:1 流程包单实例 —— 四域物化,种子整体切换" +``` + +--- + +### Task 5: 自定义工具导入路由(后端) + +**Files:** +- Modify: `packages/contracts/src/api/governance.ts` +- Modify: `apps/api/src/app/routes/governance-ops.ts` +- Modify: `api-report/` + +**Interfaces:** +- Consumes: `container.toolbox.register(input): RegistrationVerdict`(两审:静态 + 样例)。 +- Produces: + ```ts + export const registerToolRoute = { + method: 'POST', + path: '/api/gov/tools', + body: z.object({ + contract: z.object({ + name: z.string().min(1), version: z.string().min(1), description: z.string().min(1), + input: z.record(z.string(), z.unknown()), output: z.record(z.string(), z.unknown()), + effect: z.enum(['read', 'write']), + errors: z.array(z.object({ code: z.string(), retryable: z.boolean(), message: z.string() })).default([]), + idempotent: z.boolean().default(true), + timeoutMs: z.number().int().default(10_000), retries: z.number().int().default(1), + connectionKeys: z.array(z.string()).default([]), + }), + /** 连接值只写不读 —— 键声明在契约,值密封在治理台(OS 7.3) */ + connectionValues: z.record(z.string(), z.string()).optional(), + samples: z.array(z.object({ input: z.record(z.string(), z.unknown()) })).min(1), + }), + output: z.object({ accepted: z.boolean(), findings: z.array(z.object({ severity: z.string(), message: z.string() })) }), + } as const satisfies RouteContract; + ``` + +- [ ] **Step 1: 契约 + handler** + +handler 挨着 `listToolsRoute`,守卫 `guard('tool','govern')`(文件内工厂现成): + +```ts +/** 导入自定义工具 —— 与第一方同一条门:两审(静态 + 样例)过了才入目录 */ +app.post(registerToolRoute.path, async (c) => { + const denied = await governTool(c.get('account')); + if (denied) return c.json(denied, denyStatus(denied)); + const parsed = registerToolRoute.body.safeParse(await c.req.json()); + if (!parsed.success) { + const body: ApiError = { code: 'validation-failed', message: '工具契约不合 schema', detail: parsed.error.issues }; + return c.json(body, 400); + } + const verdict = await container.toolbox.register({ + contract: parsed.data.contract, + samples: parsed.data.samples.map((s) => ({ input: s.input, expectShape: { type: 'object' } })), + ...(parsed.data.connectionValues === undefined ? {} : { connectionValues: parsed.data.connectionValues }), + }); + return c.json({ + accepted: verdict.accepted, + findings: verdict.staticFindings.map((finding) => ({ severity: finding.severity, message: finding.message })), + }); +}); +``` +(`governTool` 若不存在,按文件内 `guard('tool', 'govern')` 补一行; +`toolbox.register` 的入参/回参字段名以 `apps/api/src/modules/toolbox/contract.ts` 实际为准,写前 grep。) + +- [ ] **Step 2: curl 验证** + +```bash +curl -s -b $CLAUDE_JOB_DIR/tmp/ch.cookie -X POST http://localhost:8787/api/gov/tools \ + -H 'content-type: application/json' -d '{ + "contract": { "name": "erp.stock-read", "version": "1.0.0", + "description": "读取 ERP 现货库存:PN → 库存量与库龄", "effect": "read", + "input": { "type": "object", "required": ["pn"], "properties": { "pn": { "type": "string" } } }, + "output": { "type": "object", "properties": { "qty": { "type": "number" } } }, + "connectionKeys": ["endpoint"] }, + "connectionValues": { "endpoint": "replay://erp" }, + "samples": [{ "input": { "pn": "LM358DR" } }] }' +``` +Expected: `{"accepted":true,...}`;随后 `GET /api/gov/tools` 目录多一件;坏 schema 400;无权 403。 + +- [ ] **Step 3: api:check + 提交** + +```bash +pnpm api:check --update && git add api-report +git add packages/contracts apps/api/src/app/routes/governance-ops.ts +git commit -m "MVP底座⑤:自定义工具导入路由 —— 与第一方同门两审" +``` + +--- + +### Task 6: 工具箱一页四段(卡片化 + LLM/人类/接入呈现) + +**Files:** +- Modify: `apps/web/src/features/gov-tool/internal/panel.tsx`(整页重写) +- Modify: `apps/web/src/shared/gov/gov-route.ts`(tools TABS:`catalog 能力目录` 保持单签,页内分段) +- Modify: `docs/debt.md`(MCP 连接:仅呈现) + +**Interfaces:** +- Consumes: `useGovTools`(功能工具)、`useGovLlm`(LLM 实例)、`registerToolRoute`(Task 5)。 +- Produces: `ToolsHome({ tab, nav }: HomeProps)` 四段卡片;`ToolPage` 详情保持。 + +- [ ] **Step 1: 重写 ToolsHome** + +四段,全部用既有类(`g-shelf`/`g-tile` 网格 + `Sec` 分段 + `Prop/Field` 表单): + +```tsx +export function ToolsHome({ nav }: HomeProps) { + const tools = useGovTools(); + const llm = useGovLlm(); + return ( + + <> + +
+ {(tools.data?.tools ?? []).map((t) => ( + + ))} +
+
+ + +
+ {(llm.data?.instances ?? []).map((m) => ( + + ))} +
+
+ + +
+ {HUMAN_TOOLS.map((h) => ( +
+ + + {h.name}{h.mode} + 内置 + + {h.desc} +
+ ))} +
+
+ + + + + + +
+ ); +} +``` + +`HUMAN_TOOLS` 静态目录(五形态,语义出自 `packages/contracts/src/card.ts`): + +```tsx +const HUMAN_TOOLS = [ + { name: '执行工单', mode: 'work-order · execution', ico: 'clipboard-check', desc: '作业指导书 + 空表单,请人把一步做完;落地失败卡是它的系统预置形态' }, + { name: '验收工单', mode: 'work-order · acceptance', ico: 'shield-check', desc: '请人验收产出:通过 / 驳回重做 / 驳回迭代' }, + { name: '决策卡', mode: 'chat-card · decision', ico: 'git-branch', desc: '分支条件选择表,含自定义收尾项 —— 决策是对话区的选择题' }, + { name: '补全卡', mode: 'chat-card · elicitation', ico: 'pen-line', desc: '就地要几个小信息;「没法填」旁路与提交两条路必走其一' }, + { name: '评价卡', mode: 'chat-card · rating', ico: 'star', desc: '任务评价:评分 1–5 + 改进建议,回流度量与蒸馏' }, +] as const; +``` + +`ImportToolCard`:Card + Prop/Field 表单(名称/说明/效应 Seg/入参 schema textarea(JSON)/连接键 ListEdit/连接值(逐键 input)/样例入参 textarea)→ `AskBand` 确认(影响:两审过了即入目录、可入白名单;审不过给 findings)→ `call(registerToolRoute)` → 失效 `['gov','tools']`,失败把 findings 列成 `Note tone="warn"`。 +`McpCard`:呈现卡(St mute「未连接」),正文一句话:「连接 MCP 服务器后,其工具经两审入目录、按白名单授给活动 —— 接入走 ToolInvoker 一缝,底座就绪后开放。」按钮 disabled。 + +- [ ] **Step 2: debt 登记** + +`docs/debt.md` 追加:「工具箱 · MCP 连接(2026-07-27):仅呈现卡。真接入需 MCP 客户端 + 工具目录同步(经 ToolInvoker 一缝、两审入目录),当前无运行时 —— 卡上如实标注未连接,连接按钮不可点。」 + +- [ ] **Step 3: 浏览器验收 + 五门 + 提交** + +`/design` → 工具箱:四段齐;导入 `erp.stock-read`(若 Task 5 已注册过,换名 `erp.po-read`)走完确认带 → 功能工具段多一张卡。五门全绿。 + +```bash +git add apps/web/src/features/gov-tool apps/web/src/shared/gov/gov-route.ts docs/debt.md +git commit -m "MVP底座⑥:工具箱四段卡片 —— 功能/LLM/人类/接入,导入走两审同门" +``` + +--- + +### Task 7: 活动库卡片化(六槽位卡) + +**Files:** +- Modify: `apps/web/src/features/gov-activity/internal/panel.tsx`(LibraryHome 列表→卡片网格) + +**Interfaces:** +- Consumes: `useGovActivities`(activityId/name/category/paradigm/enabled/packageVersions/assetVersions)。 +- Produces: `LibraryHome` 卡网格;`ActPage` 详情保持。 + +- [ ] **Step 1: LibraryHome 重写为 `g-shelf` 卡网格** + +每活动一张 `g-tile`:范式章(标准活动=ok / 案例活动=collab)+ 岗位/分类 chips + 版本徽 + **槽位状态**—— +`packageVersions` 里最新版即契约版;实现是否留白,以「活动分类 `统一报价` + 当前无资产增量」呈现为 +`St tone="warn" ico="square-pen"` 「契约就绪 · 待实现」(判定:`assetVersions.length === 0` 或全部 `effective === false`; +若字段实际形状不同,以 `GovActivitiesOutput` 为准 grep 后调整): + +```tsx + +``` + +- [ ] **Step 2: 验收 + 提交** + +`/design` → 活动库:六张槽位卡(A1/A2/A3/A4/A6/A7,范式两色、全部「契约就绪 · 待实现」;A5 是审批点,不在库中);点卡进详情不回退。五门全绿。 + +```bash +git add apps/web/src/features/gov-activity +git commit -m "MVP底座⑦:活动库卡片化 —— 六槽位卡,契约就绪待实现" +``` + +--- + +### Task 8: 数据域卡片化(四域大卡) + +**Files:** +- Modify: `apps/web/src/features/gov-data/internal/panel.tsx`(DataHome 域分组列表→四域大卡) + +**Interfaces:** +- Consumes: `useGovObjects` / `useGovLedger`(列/主键)、`domainShort`/`sortDomains`(Task 1)。 +- Produces: `DataHome` 四域卡;`LedgersHome`/`ObjPage` 不动(运营台列表为主,按需求 1 保留)。 + +- [ ] **Step 1: DataHome 重写** + +一域一张大卡(`Card`),卡头 = 短名 + 域键 mono + 对象数;卡体 = 对象 chips 网格(`g-entries` 或 chips 流式), +点对象 chip → `nav.push({ k: 'obj', id })`(设计侧详情仍只见结构): + +```tsx +export function DataHome({ nav }: HomeProps) { + const q = useGovObjects(); + const objects = q.data?.objects ?? []; + const domains = sortDomains([...new Set(objects.map((o) => o.domain))]); + return ( + + <> + 数据按经营对象四分:项目(每一单的流转单据)· 客户 · 情报 · 供应商(沉淀资产)。这里改结构;行数据在运营中心 · 台账看。 + {domains.map((d) => ( + {d} · {objects.filter((o) => o.domain === d).length} 对象}> +
+ {objects.filter((o) => o.domain === d).map((o) => ( + nav.push({ k: 'obj', id: `${d}.${o.object}` })} /> + ))} +
+
+ ))} + {objects.length === 0 && 还没有物化的对象 —— 槽位安装时按声明物化,种子跑完就出现在这里。} + +
+ ); +} +``` +(`Entry` 的 desc 想带列数/主键需逐对象再查 —— 设计首屏不发 19 个查询,列数留给点开后的 ObjPage。) + +- [ ] **Step 2: 验收 + 提交** + +`/design` → 数据域:四张大卡(项目 12 · 客户 1 · 情报 3 · 供应商 2);运营台台账页签同步变四域短名(项目/客户/情报/供应商 —— Task 1 字典已生效)。五门全绿。 + +```bash +git add apps/web/src/features/gov-data +git commit -m "MVP底座⑧:数据域四域大卡 —— 项目/客户/情报/供应商" +``` + +--- + +### Task 9: 收口 —— 全链走查 · 文档对账 · 五门 + +**Files:** +- Modify: `docs/产品设计.md`(附录追记:四域划分决策 + 设计台卡片/运营台列表原则) +- Modify: `docs/debt.md`(对账) + +- [ ] **Step 1: 走查清单(浏览器,Chaihao)** + +1. `/design` 蓝图:链上四数 = 流程包 1 · 活动 6 · 工具 ≥3(2 内置 + 导入的)· 数据域 4;待补清单为空(全闭合、全安装、有调起); +2. 流程包卡 → 画布对照 `docs/MVP示例工作流.html` FIG(双终点/三网关/琥珀审批点/两卡点/边标签;G3 被审批点吸收是唯一预期差异);属性卡点 A5 见审批人 PM 与驳回去向 A4; +3. 活动库七卡 / 工具箱四段 / 数据域四卡; +4. `/ops` 台账页签 = 项目/客户/情报/供应商,各域对象行数 0(新库); +5. 起单(登记触发)→ 工作流建单、A1 任务出现;任务如实报未实现(不装作跑过)—— 截图留档; +6. 调起规则页两条(事件 + 登记)。 + +- [ ] **Step 2: 文档** + +`产品设计.md` 附录补一行决策:「数据四域(2026-07-27):项目=流转单据,客户/情报/供应商=沉淀资产;设计台卡片式、运营台列表式为交互基调」。`debt.md` 确认含:MCP 仅呈现、槽位未实现(逐活动开发清单 A1→A7)。 + +- [ ] **Step 3: 五门 + 提交** + +```bash +pnpm gen:tiers && pnpm typecheck && pnpm lint && pnpm depcruise && pnpm api:check && pnpm test +git add docs && git commit -m "MVP底座⑨:收口 —— 走查通过,四域决策入档" +``` + +--- + +## 自审记录 + +- **规格覆盖**:需求 1→Task 6/7/8(+流程包已卡片);需求 2→Task 1/2/4(四域物化与呈现);需求 3→Task 3/4(槽位契约 + 1:1 拓扑与手绘图;A5 审批点、G3 吸收为唯一预期差异);需求 4→Task 5/6(功能/LLM/人类三段 + 导入实装 + MCP 呈现,MCP 无运行时为**已声明偏差**记 debt);需求 5→Global Constraints(工具按名声明、槽位无实现、占位入口不可执行语义)+ Task 3。 +- **占位扫描**:重复结构以「版图数据表 + 单个完整样例」承载,表即内容;两处「以实际 schema 为准 grep 后调整」是形状核对动作,不是留白。 +- **类型一致性**:槽位 id 六处(Task 3 清单 / Task 4 白名单与节点 activityId / Task 7 呈现)统一用 `rfq-intake / alt-selection / sourcing-inquiry / cost-pricing / quote-negotiation / intel-archive`(A5 审批点无 activityId);`declarationsFor` 签名 Task 2 定义、Task 3 消费;`registerToolRoute` Task 5 定义、Task 6 消费。 +- **形状已核**:`contractInputSchema={data,messageAllowed}`、`outputPortSchema={name,payload,description?}`、`authorization={discretion,preauthorizedActions,humanCallBudget}`、`resources={tools,skills,models,roles,budget{steps,tokens,activeMinutes,humanCalls}}` —— Task 3 样例即按此写,A2–A7 展开照抄此形。Node 24,`Object.groupBy` 可用。 +- **已知取舍(执行者与评审须知)**:① **A5 = 内置审批点**(用户确认):驳回走 reject 声明 reopen A4,G3「审批结果」被审批点吸收 —— 图与 MVP 差一颗菱形,语义同构;定价审批表落审批机制不入台账(对象 18);② 槽位 flow 骨架的步骤是 human 执行工单标题级占位,入口 JS 直接抛「未实现」—— 运行不会假装成功;③ 整库重建,旧 quote_* 域与多版本包全部退场,`activities/quote-*` 目录留仓作参考实现、不再安装。