Archived
三面拆分⑮:对齐 Mastra 数据流 —— 边只表达顺序,数据按输入/输出字段名流动
用户定的机制对齐:Mastra 的边不传数据,所有约束力靠输入/输出字段(schema 咬合)完成。
照此把「边映射」整个退役:
· 契约:edge 去 mapping,审批 reject 去 mapping —— 边只剩 顺序 + 条件(读上游
输出字段)+ 标签/回边。fieldMapping 只留给触发器的起单装配(系统边界)。
存量包无需迁移:zod 解析时把旧 jsonb 里的 mapping 静默剥掉,图照常有效。
· 运行时:assemble(边装配)→ flatScope(铺平作用域)——
起单入参垫底 ← 沿途各输出口字段依次盖上 ← 刚发射的载荷(Mastra 语义:
下一步的 input 首先是上一步的 output)。下游按自己的契约取字段;
「__」前缀是运行时自留地,不入业务作用域。审批驳回重开、失败改道同一条路。
· 闭合校验:边未映射/必填未映射/容忍依赖三条映射类检查退役
(宽进之下必填有没有着落是运行时补全单的事,不拦激活);
激活闸只留一条硬伤 —— **同名不同型**:名字即管道,名同型异必坏,
容忍依赖改按名判。改名映射不存在:名不对改契约,不是加映射。
· 种子:A2 的入参 material 更名 pn(它就是 PN;上游 A1 发的名就得是它收的名),
契约 0.3.0、槽位 0.8.0;流程种子边全部去映射。
· 前端:边属性卡砍掉「映射 · 载荷装配」整节,只剩 E号/方向/条件/标签;
节点属性卡新增「数据接口 · 按字段名流动」——每个输入字段标出运行时从哪来
(起单入参 / 上游 X / 补全单),输出口列出发什么名;沿边回溯推导,设计期看得见。
画布保存与依赖文件导出同步去映射。
E2E 顺带把宽进接进真流:快速归档流的 A3 要 outcome 而流里没人产 ——
测试如实走补全路(等人 → 答卡 outcome=won → 开跑 → completed)。
实测走查:A2 节点卡上 pn←上游A1、rfqRef←起单入参、scenario←补全单,推导全对。
五闸绿;契约快照随本提交入库。
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
This commit is contained in:
@@ -42,8 +42,9 @@ export type OwnerSpec = z.infer<typeof ownerSpecSchema>;
|
||||
/* ── 边与载荷映射 ────────────────────────────────────────────────────── */
|
||||
|
||||
/**
|
||||
* 映射来源四类:上游输出口载荷字段 / 流程变量 / 起单载荷 / 常量;
|
||||
* 允许 S-FEEL 表达式做转换(与触发器字段映射同一形式)。
|
||||
* 字段映射 —— **只用于触发器的起单装配**(外界事件字段 → 调用接口字段,系统边界)。
|
||||
* 流程内部**不用它**(2026-07-30,对齐 Mastra):边只表达顺序,
|
||||
* 数据靠输入/输出字段名流动,约束力在两端活动契约的 schema 上。
|
||||
*/
|
||||
export const mappingSourceSchema = z.discriminatedUnion('from', [
|
||||
z.object({ from: z.literal('output-port'), port: z.string().min(1), path: z.string().min(1) }),
|
||||
@@ -65,10 +66,12 @@ export const edgeSchema = z.object({
|
||||
id: z.string().min(1),
|
||||
from: nodeIdSchema,
|
||||
to: nodeIdSchema,
|
||||
/** XOR 网关出边的条件(S-FEEL);AND 出边留空 */
|
||||
/**
|
||||
* XOR 出边的条件(S-FEEL),读上游节点的输出字段;无条件即默认兜底。
|
||||
* 边**只表达顺序与条件**(对齐 Mastra):不带映射 —— 数据靠字段名流动,
|
||||
* 下游拿什么由它自己的输入契约声明,约束力在两端 schema 上。
|
||||
*/
|
||||
condition: z.string().optional(),
|
||||
/** 连一条边即须完成该边映射 —— 必填未映射 = 边未完成 */
|
||||
mapping: z.array(fieldMappingSchema).default([]),
|
||||
/** 边标签:画布上的出口名(如「TYPE-A」「通过」) */
|
||||
label: z.string().optional(),
|
||||
/** 边标签色调(呈现):ok = 绿(通过类) / bad = 红(驳回类) */
|
||||
@@ -172,7 +175,7 @@ export const processNodeSchema = z.discriminatedUnion('kind', [
|
||||
*/
|
||||
/** 驳回走向:声明式,不由临场决定 */
|
||||
reject: z.discriminatedUnion('kind', [
|
||||
z.object({ kind: z.literal('reopen'), nodeId: nodeIdSchema, mapping: z.array(fieldMappingSchema).default([]) }),
|
||||
z.object({ kind: z.literal('reopen'), nodeId: nodeIdSchema }),
|
||||
z.object({ kind: z.literal('terminate') }),
|
||||
]),
|
||||
nudge: nudgeLadderSchema.optional(),
|
||||
@@ -230,12 +233,12 @@ export type ProcessPackage = z.infer<typeof processPackageSchema>;
|
||||
/* ── 编排校验的报告形状(前端画布即时预览与后端裁决同源) ───────────── */
|
||||
|
||||
export const CLOSURE_VIOLATION_KINDS = [
|
||||
'edge-unmapped',
|
||||
'required-unmapped',
|
||||
/** 相邻两活动同名字段类型相抵 —— schema 咬合是唯一的数据约束,名同型异必坏 */
|
||||
'type-conflict',
|
||||
'dangling-node',
|
||||
/** 多出边的无条件默认兜底超过一条 —— 第二条默认永远走不到 */
|
||||
'multi-default-edge',
|
||||
/** 容忍分支的产出被下游必填依赖 —— 分支可空,依赖它的必填就会空 */
|
||||
'tolerate-required-dependency',
|
||||
'unknown-activity',
|
||||
] as const;
|
||||
|
||||
Reference in New Issue
Block a user