编排层①:改图入口下沉画布 + 活动契约面全链打通

① 已发布包就地给「起草新版本并去编辑」,不用去页头找;
② 修一个我自己引入的 bug:卡点还原把审批点的「退回调整」牌子当成边,凭空造出 e-A5-A4 ——
   卡点只认亲、不新建(旧包有这条边才认);实测编辑器往返 16 边 14 节点无损;
③ 活动契约面接进治理台:列表出参带必填入参/输出口/声明依赖,活动详情摆成一屏,
   导出依赖文件一并带上 —— 开发一个活动要照着的东西,现在有一处能看全。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
This commit is contained in:
2026-07-28 03:02:44 +08:00
co-authored by Claude Fable 5
parent af789f546c
commit 9de641459e
8 changed files with 200 additions and 6 deletions
@@ -77,6 +77,19 @@ describe('mergeGraphIntoPackage', () => {
expect(diagram.nodes.map((n) => n.id)).toContain('c1');
});
it('卡点只认亲、不新建 —— 审批点的驳回牌子不该被当成一条边', () => {
// 「审批点 → 退回卡点(to: A)」在旧包里没有对应的边:它是 reject 声明的呈现
const withReject: FlowGraph = {
...graph,
nodes: [...graph.nodes, { id: 'AP', kind: 'activity', label: '审批', flavor: 'approval' }],
edges: [...graph.edges, { from: 'AP', to: 'c1', label: '不通过' }],
};
const merged = mergeGraphIntoPackage(basePkg, withReject);
expect(merged.edges.some((e) => e.from === 'AP' && e.to === 'A')).toBe(false);
// 旧包里有的回边照旧认得出来
expect(merged.edges.some((e) => e.from === 'G' && e.to === 'A')).toBe(true);
});
it('画布装不下的声明原样保留:边映射与负责人策略', () => {
const merged = mergeGraphIntoPackage(basePkg, graph);
expect(merged.edges.find((e) => e.id === 'e-s-a')?.mapping).toHaveLength(1);
+9 -3
View File
@@ -112,8 +112,13 @@ export function mergeGraphIntoPackage(
/*
* 卡点是**回跳的呈现**:图上不画长线,画一枚「返回调整→A4」的小牌子。
* 所以「X → 卡点(to: Y)」就是语义边 X→Y —— 落包时把它还原回去,
* 否则一存盘回边就没了(卡点不入语义,这条边两端有一端不在 semanticIds 里,会被滤掉)。
* 「X → 卡点(to: Y)」要还原成语义边 X→Y,否则一存盘回边就没了
* (卡点不入语义,这条边有一端不在 semanticIds 里,会被滤掉)。
*
* 但还原只用于**认亲**,不用于**新建**:只有旧包里确有 X→Y 这条边才认。
* 不设这道闸,审批点的「退回调整→A4」卡点(它是 `reject` 声明的呈现、不是边)
* 会被当成 A5→A4 凭空造出一条边来 —— 实测就多出过一条 `e-A5-A4`。
* 真要新连一条边,画一条线;卡点只是牌子。
*/
const calloutTarget = new Map(
graph.nodes
@@ -122,7 +127,8 @@ export function mergeGraphIntoPackage(
);
const resolved = graph.edges.map((e) => {
const via = calloutTarget.get(e.to);
return via === undefined ? e : { ...e, to: via };
if (via === undefined) return e;
return priorEdge.has(`${e.from}→${via}`) ? { ...e, to: via } : e;
});
const edges: Edge[] = resolved