Files
JX-BPOS/apps/web/src/shared/gov/gov-route.ts
T
ChaiHaoandClaude Fable 5 6854524784 三面拆分⑫:网关去节点化 —— 分支即条件出边,汇合即多入边异或
模型(与 Mastra .branch 同构,条件挂在步与步之间):
- routing.selectEdges:多出边一律异或,不分节点种类 —— 条件命中优先(按声明序),
  无条件边作默认兜底,恰取一条;单出边直通保留(历史并行网关的遗留通道)
- closure:含网关即 gateway-deprecated(历史版本仅可读、不可激活);
  「隐式合并」禁令删除(多入边=异或汇合,上游互斥无歧义);
  新规:多出边节点的无条件边至多一条,超出报 multi-default-edge
- contracts:CLOSURE_VIOLATION_KINDS 去 gateway-unbalanced/join-ambiguous-source,
  进 multi-default-edge/gateway-deprecated(下游零引用,api-report 随行)

种子(按用户要求:只留一条流一个版本,图/节点/边全部对账):
- MVP_PACKAGE 重写:10 节点 14 边零网关 —— G1/G2 展开为 A1 的三条出边
  (选型/直接寻源/默认直接定价)+ A2 的两条,G2J/G3 整颗删除,
  A5 审批点的两个去向就是自己的两条 verdict 条件出边(驳回边与 reject 声明字字对齐)
- 手绘图:顶车道 y30 补画 A1→A3「直接寻源」—— 画布保存只认画出来的边,
  不画这条语义边会在首次存盘被静默丢掉(新增图边对账测试卡死这类漏画);
  「供应商底价表」标注钉进 y190 车道空档,不再被卡点压住
- 开发库外科手术:清运行数据 + 删 v1–v4,重种为唯一生效版 v1(闭合过闸)

UI 与文案同步:
- 元素盘/追加盘不再有网关件(画布仍认得历史图);图例删「判断/并行网关」「菱形=网关」
- 新建流程补激活一跳(保存不生效模型下,不激活「建出来就能起单」就是谎言)
- 总览四种编排要素、「画图不检查,激活才查完整」贯穿 blueprint/memory/process 文案

测试:closure 43 通过(gateway-deprecated + multi-default-edge 两用例),
seed-mvp-flow 8 通过(含图边对账),端到端八例真库全绿(网关从不建实例,断言原样存活);
五闸 typecheck/lint/depcruise/api:check/test 全过(退出码验)。

债:M5-4 AND 并行待「并行组」声明(Mastra .parallel);M5-5 网关运行时兼容三处,
含网关在途流清零后随 schema 一并摘除。

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01KeDBx2PHLavbURXB8LJJ7m
2026-07-28 17:56:20 +08:00

213 lines
9.2 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.
/**
* 治理台的分级页面路由 —— 自原型 `Governance.tsx` 第 25–90 行平移。
*
* 「**不用抽屉、不用弹窗**:每一层内容都有自己的页面。」
* 区 → 对象 → 子维度 → 元素,顶部面包屑可回跳任意一级,Esc / 返回退一级。
*/
export type Route =
| { k: 'wf'; id: string }
| { k: 'task'; id: string }
| { k: 'tasklog'; id: string }
| { k: 'apr'; id: string }
| { k: 'emp'; id: string }
| { k: 'role'; id: string }
| { k: 'pkg'; id: string }
| { k: 'trigger'; id: string }
| { k: 'act'; id: string }
| { k: 'tool'; id: string }
| { k: 'obj'; id: string }
| { k: 'mem'; id: string }
| { k: 'llm'; id: string }
| { k: 'chan'; id: string };
/**
* 十一区 —— 分属两个台面(见 `surfaces.ts`):
* 设计中心定义企业(战略 → 方法 → 能力 → 对象),运营中心看企业跑。
* 触发器不再独立成区:定义并入 workflows,启停并入 tasks;
* 记忆一分为二:度量升为 cockpit 首页,活动记忆归 knowledge。
*/
export const GOV_ZONES = [
// 设计中心
'blueprint',
'workflows',
'library',
'tools',
'data',
'testbed',
// 运营中心
'cockpit',
'tasks',
'people',
'ledgers',
'knowledge',
'system',
] as const;
export type GovZone = (typeof GOV_ZONES)[number];
export const ZONES: ReadonlyArray<{ key: GovZone; label: string; icon: string }> = [
{ key: 'blueprint', label: '蓝图', icon: 'route' },
{ key: 'workflows', label: '流程包', icon: 'workflow' },
{ key: 'library', label: '活动库', icon: 'boxes' },
{ key: 'tools', label: '工具箱', icon: 'wrench' },
{ key: 'data', label: '数据域', icon: 'database' },
{ key: 'testbed', label: '测试台', icon: 'flask-conical' },
{ key: 'cockpit', label: '驾驶舱', icon: 'gauge' },
{ key: 'tasks', label: '任务', icon: 'activity' },
{ key: 'people', label: '员工', icon: 'users' },
{ key: 'ledgers', label: '台账', icon: 'table' },
{ key: 'knowledge', label: '知识库', icon: 'layers' },
{ key: 'system', label: '系统', icon: 'settings' },
];
/** 区元信息:标题 / 定位说明 / 主色 —— 说明文取自两卷规范,不是装饰 */
export const ZM: Readonly<Record<GovZone, { title: string; desc: string; accent: string; icon: string }>> = {
blueprint: {
title: '企业蓝图',
icon: 'route',
accent: 'linear-gradient(140deg,#4954e6,#232b6e)',
desc: '战略 → 方法 → 能力 → 对象:流程包决定企业以哪些流转运转,活动库决定每件事怎么干,工具箱决定系统能对世界做什么,数据域决定企业运营什么。四库的健康度与待补清单聚在这一屏——设计者看的是定义完不完整,不是今天忙不忙。',
},
cockpit: {
title: '经营驾驶舱',
icon: 'gauge',
accent: 'linear-gradient(140deg,#12b886,#0b7a5c)',
desc: '看企业今天跑得怎样:度量八指标(自主率与纠正率成对读,复合为有效自主率)+ 异常面(异常工作流、需处置件数)。指标零埋点——全部由留痕投影而来,点数字直达处置页。',
},
ledgers: {
title: '台账管理',
icon: 'table',
accent: 'linear-gradient(140deg,#245bdb,#16307a)',
desc: '行数据 · 版本 · 引用——域的结构在设计中心改,这里做运营动作。域即页签,随数据域发布生长:设计侧一发布新域,台账里自动多一个域页签。',
},
knowledge: {
title: '知识库',
icon: 'layers',
accent: 'linear-gradient(140deg,#f14ba9,#c92d86)',
desc: '活动记忆四层 + 技能资产 + 候选增量的回放与放行。记忆的终点是成为模型——候选增量必经回放与人放行,这里是那道人工放行口。',
},
tasks: {
title: '任务管理',
icon: 'activity',
accent: 'linear-gradient(140deg,#3370ff,#245bdb)',
desc: '运行态:任务与工作流两级运行时实例的在途监控、干预与控制——任务 = 活动被调起的一次运行,恰有一名负责人;工作流 = 流程包的一次运行,状态由流内各任务聚合投影而来。审批点卡到审批人工位,是流程层的人裁节点、不是任务。控制事件三种语义:暂停可恢复、叫停归负责人、终止级联作废。治理不改定义。',
},
people: {
title: '员工管理',
icon: 'users',
accent: 'linear-gradient(140deg,#2bc7d4,#0e9fd8)',
desc: '员工负载、岗位与授权。权限按岗位授予:客体三类 × 动作三种;停用前置检查——在途任务与待答卡须先改派完毕。',
},
workflows: {
title: '流程包管理',
icon: 'workflow',
accent: 'linear-gradient(140deg,#4954e6,#3a44c9)',
desc: '战略——企业以哪些流转运转。一条流一个包,版本收在包内部:画图不检查、激活才查完整,恰一个生效版本、在途按启动版本跑完。编排即定契约:连线即映射,分支就是条件出边。触发器(谁调起这条流)也在本区定义;启停在运营中心。',
},
library: {
title: '活动库',
icon: 'boxes',
accent: 'linear-gradient(140deg,#0aa294,#0a6a64)',
desc: '已安装活动的资产货架:活动是任务的定义——编排引用一个活动,运行时就长出一个任务。审批点与网关是系统内置要素,零开发、不入库。业务分类 × 活动类型两维,每活动两条版本序列。',
},
tools: {
title: '工具箱',
icon: 'wrench',
accent: 'linear-gradient(140deg,#7f3bf5,#5b21cf)',
desc: '能力——系统能对世界做什么。一件事能交给谁办的全集:功能工具(交给系统)、LLM 工具(交给模型)、人类工具(交给人)。读类过程中自由调用,写类只登记动作意向、放行后落地;密钥只存治理台,不入包、不入活动。',
},
data: {
title: '数据域',
icon: 'database',
accent: 'linear-gradient(140deg,#0e9fd8,#245bdb)',
desc: '对象——企业运营什么。域 × 对象的结构定义:声明物化(最大化合并、只增不破坏)与调用接入(事实源在外)。数据可以自生长,权力不可以自生长。行数据不在这里看——那在运营中心的台账。',
},
testbed: {
title: '联调测试台',
icon: 'flask-conical',
accent: 'linear-gradient(140deg,#e8833a,#c25f1a)',
desc: '把定义**试着跑一遍**:造一封入站邮件(可带附件)投进通道,看归属解析怎么判、哪个触发器命中、有没有起单。邮件通道是外界,模拟通道是允许的;系统内部机制一律真跑 —— 这里投出去的信走的是与真通道同一条入站归一链路。',
},
system: {
title: '系统管理',
icon: 'settings',
accent: 'linear-gradient(140deg,#46586a,#2b3644)',
desc: '系统边界的配置面:LLM 实例(名称间接层)、通道实例(归属键规则与默认认领岗位)、系统用途模型绑定。',
},
};
/**
* 区内页签:一页一个维度 —— 不把四种维度摞在同一屏。
*
* `ledgers` 的页签是**数据域**,随发布动态生成(壳层运行时铺开),故此表留空。
*/
export const TABS: Readonly<Record<GovZone, ReadonlyArray<{ key: string; label: string; ico: string }>>> = {
blueprint: [{ key: 'map', label: '企业蓝图', ico: 'route' }],
testbed: [{ key: 'inbound', label: '入站邮件', ico: 'mail' }],
workflows: [
{ key: 'overview', label: '总览', ico: 'gauge' },
{ key: 'pkgs', label: '流程包', ico: 'boxes' },
{ key: 'rules', label: '触发器', ico: 'zap' },
],
library: [{ key: 'shelf', label: '活动货架', ico: 'boxes' }],
tools: [{ key: 'catalog', label: '能力目录', ico: 'wrench' }],
data: [{ key: 'domains', label: '数据对象', ico: 'database' }],
cockpit: [{ key: 'dash', label: '驾驶舱', ico: 'gauge' }],
tasks: [
{ key: 'board', label: '运行看板', ico: 'activity' },
{ key: 'list', label: '任务', ico: 'list-checks' },
{ key: 'apr', label: '审批单', ico: 'shield-check' },
{ key: 'trg', label: '起单开关', ico: 'zap' },
{ key: 'todo', label: '需处置', ico: 'flag' },
],
people: [
{ key: 'emp', label: '员工', ico: 'users' },
{ key: 'roles', label: '岗位授权', ico: 'key' },
{ key: 'groups', label: '工作组', ico: 'users' },
],
ledgers: [], // 动态:页签即数据域(短名呈现),由壳层按已发布域生成
knowledge: [{ key: 'layers', label: '活动记忆', ico: 'layers' }],
system: [
{ key: 'llm', label: 'LLM 实例', ico: 'cpu' },
{ key: 'chan', label: '通道实例', ico: 'mail' },
],
};
export function routeLabel(r: Route): string {
switch (r.k) {
case 'wf':
return '工作流';
case 'task':
return '任务';
case 'tasklog':
return '任务日志';
case 'apr':
return '审批单';
case 'emp':
return '员工';
case 'role':
return '岗位授权';
case 'pkg':
return '流程包';
case 'trigger':
return '触发器';
case 'act':
return '活动';
case 'tool':
return '工具';
case 'obj':
return '数据对象';
case 'mem':
return '活动记忆';
case 'llm':
return 'LLM 实例';
case 'chan':
return '通道实例';
}
}
export type Nav = {
push: (r: Route) => void;
jump: (z: GovZone, tab: string, r?: Route) => void;
};