LeapWorld PlayBook · 仓库导读与地图

一页看懂 LeapWorld:怎么组织、怎么运转、怎么改、怎么交付

对应版本:v2.2.0(冻结前第一遍) main 提交:659eee02c5 生成日期:2026-10-20

LeapWorld 一句话

LeapWorld 是 Agent 时代对「软件怎么被生产、交付、演化」的范式重定义。本仓是它的工程形态(底座),十个应用是第一个实例。

底座维护者先看这三节

  1. 仓库地图
  2. 一个改动怎么进 main
  3. 发版与下游

FDE 先看这三节

  1. FDE 定制指南
  2. 业务流驱动(v2)
  3. Agent CLI 与 API

1LeapWorld 是什么

LeapWorld 赌的是:Agent 时代稀缺的不是写代码,而是让机器速度的迭代保持安全,并且对人完全可读。

五大支柱与三层工程形态 LeapWorld:Agent 时代「软件怎么生产、交付、演化」的范式 ① 极度原子化每个 SaaS 独立部署断网断厂商照常营业又能拼成大生态 ② Agent 原生操作CLI + SKILL人能做的操作Agent 都能做 ③ Agent 原生迭代任何模型都能改约束本身是产品闸门+破坏验证+分级 ④ 极度语义化上层是 World Version工单、版本、文档直达用户 ⑤ 能力原子化通用能力可回流按能力目录选装运行期零依赖底座 工程形态(顺序别搞反) 1 底座(本仓)模板 + 共享包 + 闸门 + 统一 Agent API 2 模板 APP(apps/*)各自带库、各自 compose、独立部署 3 我们自用的业财实例第一个实例,不是底座本身 终局:把这套体系复用给所有公司(服务对象是中小企业),不是把业财软件卖给所有公司。
图 1 五大支柱(信条正本)与三层工程形态。第 ④ 条就是 World Version。

要点

  • 信条正本只有一处:21-consensus.md §1。START-HERE.md 等其他文档只放指向它的链接,不再逐字复制;tests/vision-creed.test.ts 守正本存在、关键词齐全。
  • World Version 是交付给客户的、完全可读的版本对象:语义化的工单、版本叙事、文档与用户手册。客户不必懂 git。实例级投影在导出包根的 world-version.json。
  • 卖的是三层能力:一,客户的 AI 直接调 operation 读写业务;二,AI 能按企业需求安全地改这份实例;三,交付的是语义化的工单、版本和文档。第一层是护城河,第二层是成交理由。
  • 服务对象是中小企业。往多服务拆分、复杂编排、重型中间件走的提案默认不采纳。
  • LeapCore 是另一条产品线(Agent 工作站)。LeapWorld 可以跑在它上面,但能单独部署;能和它的 Agent 打通,也支持其他品牌的 Agent。

详细见:21-consensus.md §1(信条正本)· START-HERE.md §1 · 19-concepts.md §7(World Version 词条)· 17-north-star.md(北极星指标)

2仓库地图

一个 monorepo:应用在 apps/,共享包在 packages/,新应用从 templates/saas-app 复制;其余目录是生成、检查、文档和工单。

仓库顶层目录及依赖关系 templates/saas-app新应用的可执行基线 apps/(10 个应用)各自带库、compose,独立部署应用之间不许 import packages/(18 个包)共享源码,不读环境变量 new-app 复制 workspace 依赖 deploy/跨应用的部署编排 plugins/(6 个插件)选装后落进应用目录 选装时复制进应用目录 开发与交付期的工具和记录:不进客户实例的运行路径 scripts/生成、检查、导出、发布 tests/仓根检查:静态档与行为档 docs/规范、操作手册、决策、版本志 tasks/工单、交接卡、候选池
图 2 顶层目录。箭头是代码级的复制或依赖关系,不是线上服务互调。

apps:每个应用一句话

目录做什么给谁用
crm销售从线索到回款、费用、采购、考核销售、经理、财务、管理员
score内部积分激励与考核:申报、评议、入账、兑换员工、评议人、部门负责人、管理员
foodbuy公司内部零食选购、采购、报销员工、行政、财务
marketLeapCore 渠道商:报备、下单、交付、充值、分润与结算渠道、IT、软件实施、财务、管理员
prm客户项目谁负责、开到哪一阶段、会议与工时技术负责人、管理员
tickets交付运营中枢:需求和故障从提单到发版、批准、装机回执;也接业务方的流程修改意见FDE、工程师、管理员、业务方
pms绩效考核:目标、自评与上级评、校准档位、公布与申诉员工、直属上级、部门负责人、HR
cms合同台账、两级审批、收付款登记、到期待办员工、部门负责人、财务、管理员
center统一入口:一个账号登录各应用,跨应用待办汇总、管理员摘要员工、管理员、FDE
itamIT 资产入库、领用、借用、归还、调拨、报废管理员、资产管理员、审计员、员工

packages:每个包一句话

包做什么
@bf/contracts跨应用 schema 的唯一事实源:Agent 协议信封、业务事实信封、组织、派生待办契约。只有 schema 与类型,没有行为代码
@bf/loggerJSONL 日志,按天切分,自动带 traceId
@bf/feishu飞书 OAuth、通讯录、机器人消息、审批
@bf/auth统一认证:Cookie 与 Bearer 通道、CSRF、只读 Key 拒写、身份源接口;2.2 起另收 API 密钥有效期换算、签发服务 Key 的流程、统一登录旧密码绑定接口(1059、1062、1063)
@bf/authz统一授权:权限点声明、判定引擎(给出允许与否和数据范围)、委托代办计算
@bf/audit审计写入的统一写法,动作名一律 <domain>.<verb>
@bf/agent-server统一 Agent API 的协议引擎:读请求体、信封、幂等、限流、simulate;高风险方案确认的共用判断与方案落库(plan-store.ts,1061);Agent 引擎装配 createAgentEngineAssembly(模板已用,十个应用另单迁移,1106)
@bf/agent-cliAgent API 的薄 CLI 内核:capabilities、invoke、退出码 0/1/2/3
@bf/tutorial-kit可执行用户手册:/help、PDF、飞书版;流程章由流程定义生成
@bf/telemetry拆售实例回传:错误摘要、心跳、用量。应用侧接线已删,现在没有应用使用,包保留
@bf/runtime运行时基建:可写目录探测、迁移执行、实例身份、登录尝试次数限额。500 错误只写日志,不再落表
@bf/ui前端基础组件与 lark / linear / techblue 三套主题;平台功能页「接入 Agent」(AgentAccessPage,十个应用共用,1058、1060)
@bf/format金额(分与元)和上海时间的展示与解析
@bf/flow流程定义、静态检查、服务端流转与纠正/导入/迁移、到点由系统执行(1069)、手册与流程图和路径测试的生成器
@bf/events进程内领域事件总线:emit 与 subscribe
@bf/notifications站内通知、升级通知、可插拔的外发通知端口
@bf/testkit测试期共享断言:一次性库校验、并发请求
@bf/seed-org固定种子的示例组织(80 人、6 个部门)

其余目录

  • templates/saas-app:规范的可执行形态。模板与规范不一致时以规范为准,再修模板。部署脚本只改模板 deploy/ 里的一份,应用里的副本由 bun scripts/template-derived-sync.ts --write 生成,不手改(1064、1065)。
  • plugins/:存储、通知、审批等插件母本。选装后复制进应用目录,下游可以改。
  • scripts/:顶层脚本逐个登记在 scripts/README.md;scripts/hooks/ 放常驻破坏脚本。
  • tests/:仓根检查,分静态档和行为档,由 scripts/check.ts 编排。
  • docs/:architecture/ 是必须遵守的规范;runbooks/ 是操作手册;decisions/ 是决策记录;history/ 与 archive/ 是史料,不要照着做。
  • tasks/:一张工单一个 tasks/<id>-<slug>.md;证据放 tasks/appendix/<id>/;新冒出的想法登记 tasks/_candidates.md。

详细见:START-HERE.md §3–§4(应用与包,受闸门守护)· 08-packages.md §2(包职责与边界)· 25-repo-map.md(谁依赖谁、改 X 波及 Y)· scripts/README.md · docs/README.md

3分层与依赖方向

六层回答「一个客户实例怎么堆起来」;发布面回答「东西怎么送到客户手上」。上层依赖下层,客户定制层不能被反向依赖,中央服务不在任何一层。

六层、发布面与依赖规则 六 外部系统LeapCore 云端 · 其他品牌 Agent · 飞书/钉钉(可关) 五 开发面 = 客户定制层从某个 tag 导出的仓,只改 L0–L2 四 默认企业应用层apps/ 十个 + templates/saas-app 三 Infra 层3.1 packages 编译期复用 · 3.2 工程基建 二 运行时依赖PG · 对象存储 · 镜像 · 备份,每个实例自带 一 承载(可选)LeapCore 工作站,或任意能跑容器的机器 发布面(我方持有,单向)tag 与镜像补丁包与包快照License 凭据签发、安全通告永不进运行路径输出物可离线验签 单向 依赖规则:四条不许1 app 不许 import app2 packages 不许读 env、连库3 实例之间不共享运行时依赖4 上层不许感知承载层 数据面不是第三个面:它是统一 Agent API 的子协议(market 与 LeapCore 云端),走第六层。
图 3 六层(纵向,运行时)与发布面(横向,交付)。开发面要尽量小,发布面要尽量全,两者不合并。

要点

  • 判断有没有长出中心节点,只问一句:客户不连它,已购模块还有哪个 operation 或页面不能用?有一个就是中心节点,不许做。
  • 跨应用取数走 facts.*(与 Agent API 同端点、同认证),不共享数据库,不跨应用 import。
  • 四条不许里,前两条由 scripts/arch-check.ts 的机械规则挡在提交时。
  • 本仓是底座:业务实现的真相源在下游发包,本仓只管底座与高复用部分(2026-08-19 裁决)。

详细见:20-layers.md §2–§5 · 22-instance-constraints.md(实例约束)· 07-cross-app-data.md(跨应用数据)· 19-concepts.md §7

4业务流驱动(v2)

每条业务流只写一份流程定义。待办、表单、权限、手册流程章、流程图、测试路径、每步的 Agent 写操作都从它生成。这不是工作流引擎:状态仍在业务表的状态列,运行时只多一张流转记录表和一个事务函数。

从流程定义到生成物与运行时 流程定义(一份)defineFlow({ … })apps/<app>/shared/flows/流程 › 阶段 › 步骤 › 表单 流程静态检查八类,失败时点名 手册流程章:大白话说明 + 静态流程图(给业务方) 给定-当-则规格(开发用)与接口级路径测试(进门禁) 派生待办:单据停在哪步,就给该步角色一条(不落库) 表单:表单里的字段,就是该步角色能改的字段 每步一个 Agent 写 operation(与页面同一入口) 流程改动时生成业务语言的版本志条目 运行时读同一份定义 运行时:页面按钮与 Agent 写 operation 调同一个流转函数,一次流转 = 一个 PG 事务① 校验角色与条件 → ② 按表单过滤可写字段 → ③ 条件更新状态列(AND status = 旧状态)→ ④ 写流转记录
图 4 一份定义,多种生成物;人与 Agent 走同一个流转函数。

特殊流转:普通流转之外的四个正式入口

普通、纠正、导入、迁移四类流转与委托代办 上线时已经走到一半的单据 步骤 甲 步骤 乙 步骤 丙 结局 普通(命令) 纠正(correction):指定角色把单据挪到合法步骤,必须写理由 导入(import):只能是第一条历史,必须写理由 迁移(migration):步骤改名或删除时按改名对照把在途单据挪到新步骤 委托代办不在流程定义里:@bf/authz 统一计算,数据边界取委托人与被委托人的交集
图 5 四类流转都写进流转记录并标出类型;普通流转的理由可空,其余三类必须写非空理由。
类型什么时候用入口限制
普通 normal按定义里的命令推进@bf/flow/server/transition表单即权限;条件更新失败整笔回滚
纠正 correction办理中由指定角色人工改状态@bf/flow/server/correction定义里先声明角色与目标;每个目标在服务端登记处理函数;不提交表单字段
导入 import上线时录入已在途的单据@bf/flow/server/import只能是该单据第一条历史;目标必须是在途步骤;应用在同一事务插入业务行后调用
迁移 migration步骤改名或删除@bf/flow/server/migration定义里写「旧步骤 → 新步骤」对照;不做流程多版本并存
到点由系统执行定义里给已有命令写了 auto(到哪个时间点),到点由系统替人办理(1069、1070)@bf/flow/server/auto只执行定义里已有的命令,记录人记 system:auto;内核不带定时器,由应用在已有入口调用;失败时单据留在原步,下次再试;超过 30 分钟仍在原步,管理员收到「到点未自动办理」待办
委托代办有效期内由他人代办@bf/authz 的委托计算数据边界取委托人和被委托人自己边界的交集,两边都有边界且不同则这份委托不生效;不能再转委托;执行人记实际办理人;委托记录存在各应用自己的库。审批人委托:审批模块决议时认「本人或委托人」,ITAM 领用审批已接入(908 并入 922)

要点

  • 三方各看自己那部分:员工看自己的几步和待办;业务负责人看手册流程章并点「提修改」;FDE 改定义本身,其余跟着重新生成。
  • 现状:market 订单交付、itam 资产领用与归还、foodbuy 月度采购的流程定义已接入 @bf/flow。foodbuy 采购是 2.2 迁的(1071、1072):月份状态写入全部改走流转函数,锁单到点由系统执行。dzy 10-07 定:所有有状态、多人经手的业务流程都要迁到流程定义;其余流程从 2.3 起逐条迁(28 §23)。
  • 纠正统计每周提醒:market 每周一给能看纠正统计页的角色派生一条待办,写上周纠正次数和最多的一种纠正,经 center 汇总发飞书;上周 0 次不派生(1074)。
  • 审批:申请人正好是审批人时不审自己的单,由同层其他人审(ITAM 826、cms 932、tickets 发布单 931);ITAM 的审批人在工作台收到「待审批」,在网页办理(913、916)。
  • 某一步没有任何在职的人有资格办理时,给应用管理员派生一条待办;资格恢复后自动消失。
  • 跨应用的一步叫交接步:主人应用带幂等键同步调用对方一个已注册的写 operation;对方失败,本步流转不发生。2.0 只立规则、不写代码。
  • 明确不做:工作流引擎、定时器与 SLA 计时、失败补偿、流程多版本并存、拖拽式编辑器。「到点由系统执行定义里已有的命令」不算这里的定时器(dzy 10-07):内核只给服务端入口,何时触发由应用决定。

详细见:28-flow-driven.md(§2 定义形态、§3 静态检查、§4 生成物、§5 运行时、§10 变更、§21–§22 2.1 方向、§23 2.2 范围)· 19-concepts.md §10 · D39 · packages/flow/ · 示例 market 订单交付定义 · 14-user-manual.md §5(流程章与流程图)

5登录与权限

center 只管两件事:认证,以及「能不能进某个应用」。角色和权限点留在各应用;Agent 用各应用自己签发的 Key,权限跟着 Key 绑定的用户走。

统一登录、应用权限与 Agent Key 员工 / 业务方浏览器 center(统一登录)认证:OIDC 身份提供方应用级准入:能不能进某应用不管应用内的角色 各应用(接入方)本地会话不超过 12 小时角色与权限点留在应用判定给出允许与数据范围 ① 跳转登录 ② 下发身份 ④ 只读拉待办 ③ 在应用里办事(用应用自己的会话) Agent / CLI代表某个用户 Bearer Key:权限继承 Key 绑定的用户;scope 为 read 或 read_write 人用的 Key:在应用网页签发、吊销(只认网页会话)center 用的 Key:服务账号名下只读,部署管理员用命令签发只展示一次;只存哈希;默认永久,可选 365 或 90 天到期 高风险操作四个应用:先提方案再确认 center 挂了:已登录会话照常;会话到期后管理员用各应用本地密码登录。所以 center 不是中心节点。
图 6 人走统一登录,Agent 走 Bearer Key;两条路最后都落到同一套应用内权限判定。虚线:人用的 Key 在各应用网页签发,center 用的服务账号只读 Key 由部署管理员在应用容器里用命令签发;高风险方案在各自应用的网页确认(market、score、cms、crm),见第 6 节。

要点

  • center 用 OIDC 授权码流程,各应用经 @bf/auth 的 oidc 身份源接入;不做单点登出,停用当天内失效。
  • center 下发给各应用的统一 ID 是 center 的账号编号。882(10-10)之前,挂了目录人员的账号下发的是人员标识(p_ 开头)。
  • 应用里按旧值存的 center 绑定,用户下次登录时自动改成新编号,再照常直接登录。下发身份里的 legacy_ids 只用来找旧绑定,不当身份用。
  • 不等每个人登录,可以批量更正:center 容器跑 bun run center-subject:map,输出作为标准输入交给每个应用的 bun run center-subject:migrate -- --dry-run 看条数,再去掉 --dry-run 正式跑。可以重复跑,只改 provider=center 的绑定。新旧值都有绑定的不自动合并,命令按 CENTER_SUBJECT_CONFLICT 点名,交管理员处理。
  • 各应用 /api 默认要登录:没有登录会话、也没带 API Key 的请求,进处理函数前回 401。不登录也能访问的路径登记在各应用 server/security.ts(score 在 server/index.ts)。新增公开路径要在工单写明路径和原因,经调度者或 dzy 逐条批准。
  • 应用级准入粒度只到「整个应用」,默认全员可进,可改为指定组;授权上级部门即放行整条子树。「全员可进」只放行内部账号;外部账号(渠道商)默认只进 market,进别的应用要管理员显式授予。
  • 应用内权限由 @bf/authz 判定:权限点在各应用 shared/authz.ts 声明,判定同时给出允许与否和数据范围。
  • Agent 通道的写 operation 必须与网页共用同一个权限判定函数;注册表里的 roles 只用于能力列表展示,不是放行依据。
  • 高风险操作「先提方案、网页确认」:资金确认、结算打款、账号与凭据管理等,Agent 调用只生成待确认的计划(planRef),由有权限的人在网页里用登录会话确认后才执行,Bearer Key 调不到确认接口。
  • 已接入的应用:market;2.1 起加上 score 的 claims.book(积分入账,894、909)、cms 的 payments.record(登记收付款)与 contracts.transition 的终止合同(896、910)、crm 的 contracts.void(作废合同,897)。
  • 审批决议(通过、驳回)只认网页会话:Agent 和 API Key 调 ITAM 的 approvals.decide 返回 403,提示请审批人在网页上处理;Agent 仍可列出待审、读审批状态。
  • 各应用另有一张 Bearer 拒绝表(SENSITIVE_FOR_BEARER),表里的权限点对任何 Key 都拒绝。
  • center 拉各应用待办时,用各应用里一个不可登录的服务账号(<应用名>-service)名下的只读 Key,不新增凭据类型。
  • center 默认调各应用的 todos.list 拉待办;cms 例外,调 workbench.list。cms 的 todos.list 是更早的合同与款项清单,改它不会进 center 首页和飞书。
  • 这把 Key 由目标应用的部署管理员在应用容器里运行 bun run service-key:issue -- --name center-panel 签发,明文只输出一次,交给部署配置保管;网页入口待 2.2。同名重跑会先吊销旧 Key 再签新的;foodbuy 每个账号只能有一把有效 Key。2.2 起这套签发流程收进 @bf/auth,各应用只留自己的建号语句;模板新建的应用自带这条命令(1062)。
  • 登录限流和接口限流按来源地址分桶,只认反向代理传的 X-Real-IP,不读客户端能伪造的 X-Forwarded-For。反代没传 X-Real-IP 时,整个实例挤进同一个桶,任何人输错几次就能锁住所有人的登录;部署时反代要补这一项(1027)。
  • API 密钥默认永久有效;网页签发和下载 SKILL 时可选 365 天或 90 天到期,到期的和吊销的一样被拒绝。crm 例外,仍默认 90 天。

详细见:26-center-panel.md(§0 边界、§1 身份、§1.6 统一 ID 的旧值、§3.1 待办、§3.3 服务间鉴权)· 02-backend.md §3(/api 默认要登录)、§5(限流来源)· 05-agent-api.md §3–§4 · 12-customization-playbook.md §8(统一登录接入清单)· packages/authz/ · market AGENT-API.md §3.11、§4(高风险提案与确认)

6Agent CLI 与 API

每个应用只有一个机器入口 POST /api/agent/v1。CLI 只是协议的薄包装;能做什么以 capabilities.list 为准,多数应用的注册表在 catalog.ts(market 在 operations.ts)。

一次 Agent 调用从 CLI 到服务端的路径 Agent(模型) 应用 CLI 应用服务端 @bf/agent-server 注册表与 handler capabilities / invoke POST /api/agent/v1 dispatchAgentRequest 1 限流,确认身份2 Content-Type 与 64 KiB3 解析信封,查 operation4 authorize:同网页权限5 只读 Key 调写 → 4036 按 schema 校验 input7 写操作:模拟或幂等键 执行 handler { ok, data | error, meta },带 requestId 退出码 0 / 1 / 2 / 3 Authorization: Bearer 写操作带 Idempotency-Key
图 7 协议接线(第 1–7 步)在共享包里,应用只注入注册表、授权模型、handler 与存储。2.2 起模板改用 @bf/agent-server 的 createAgentEngineAssembly 连接主体、写事务、幂等和请求日志;十个应用仍用原接线,按应用另单迁移(1106)。

高风险操作:先提方案、网页确认

高风险操作的提案与网页确认 ① Agent 发起调用高风险 operationsettlements.pay ② 只生成计划写入 agent_plans返回 planRef,待确认 ③ 人打开确认页显示要执行的操作、对象和关键参数 ④ 网页确认只认登录会话Bearer Key 调不到 ⑤ 校验后执行提案人仍有权限对象版本没变 计划状态 待确认(submitted) 已确认:执行动作,重复确认按幂等返回 已取消:这个 planRef 不能再确认 已过期:24 小时未确认(409) market 已上线充值到账、退款与结算打款客户改判渠道、账号与 Key 管理订单收款:确认时恒被拒绝 2.1 起 score、cms、crm 已接入入账、登记款项、终止或作废合同
图 8 高风险操作:Agent 的调用只生成计划;有权限的人在网页确认后,服务端重新校验提案人权限和对象版本才执行。
  • 提案入口:apps/market/server/modules/admin/agent-high-risk.ts 的 proposeHighRiskPlan,经 server/modules/agent/domain-ops.ts 的 proposeFromCtx 接线;调用返回 { planRef, status: "submitted" }。
  • 确认页:apps/market/src/features/agent-plans/AgentPlanPage.tsx(路由 /agent/plans/:planRef);确认与取消走 POST /api/admin/agent-plans/:planRef/confirm 与 /cancel,只接受网页登录会话。
  • 确认页显示要执行的操作、对象和关键参数:提案时把它们写进步骤(907)。步骤为空的方案不能确认,页面写清原因和下一步。
  • 确认时重新核对当初的提案人:账号停用或权限收回就拒绝执行,确认人自己有权限也不能代为执行。
  • score 的 claims.book、cms 的 payments.record 与 contracts.transition(终止)、crm 的 contracts.void 在 2.1 改成先提方案、网页确认(894、896、897)。确认页分别在 apps/score/src/features/agent-plans/、apps/cms/src/features/agent-plans/AgentPlanPage.tsx、apps/crm/src/features/agent-plans/AgentPlansPage.tsx;确认期限等共用判断在 packages/agent-server/src/plan-confirm.ts;这三个应用的方案落库和状态流转 2.2 起也收进 packages/agent-server/src/plan-store.ts,应用只留执行动作、行级判断和审计写法(1061)。market 仍用自己的实现。

普通写操作的确认顺序

  1. 先读能力capabilities 看 operation 的 mode 与 supportsSimulation
  2. 模拟invoke <op> --write --simulate,在真实事务里跑完再回滚,不带幂等键
  3. 可选:提交方案plan.submit 换一个 planRef,只做审计关联
  4. 用户确认删除、状态跨越、批量写,真实执行前必须取得用户明确确认
  5. 真实写入--write --idempotency-key,重试复用同一个键

要点

  • 接入形态只有 CLI + SKILL,一律不用 MCP(D21)。每个应用提供预配置的 SKILL 包下载。
  • Key 不进命令行参数,不进脚本、日志或仓库;CLI 只从标准输入或交互读取。
  • Key 在各应用「工具 → 接入 Agent」页签发、吊销和下载预配置 SKILL 包(原名「API 密钥」页)。
  • CLI 退出码:0 成功,1 平台拒绝,2 本地参数或配置错,3 网络或上游失败。
  • 普通写操作的确认在用户与 Agent 的对话里完成;plan.submit 返回的 planRef 只是审计关联。高风险操作的 planRef 不同:它是待网页确认的计划,确认前什么都不执行。
  • SKILL 表:各应用 skills/**/SKILL.md 的 operation 表(三列 operation / mode / 说明)是生成区块,和同目录的 manifest.json 清单一起由 bun run agent:manifest -- --write 从注册表生成;--check 点名过期的应用。区块外的手写句子原样保留。
  • 注册表位置:多数应用在 apps/<app>/server/agent/catalog.ts;market 在 apps/market/server/modules/agent/operations.ts。

详细见:05-agent-api.md(§1 单入口、§2 信封、§3 注册表、§4 Key、§5 幂等与 simulate、§9 CLI 与 SKILL、§11.6 加 operation 要同步改什么)· dispatch.ts · packages/agent-cli/ · 示例 cms SKILL.md · agent-client-integration.md · 高风险提案 market AGENT-API.md §3.11 · agent-high-risk.ts · AgentPlanPage.tsx

7一个改动怎么进 main

一张工单一个交付单元。执行者在自己的工作树里改并自检,审查者独立验收,调度者确认规模后排进串行合并队列,门禁机跑全量门禁,绿了按工单压成一笔推上 main。历史必须线性。

工单到合入 main 的泳道图 调度者 执行者 审查者 门禁机 ① 创建工单判据与可写清单 ② 修改并提交独立工作树 ③ 自检三条自检命令 ④ 初审只读,盲评三步 ⑤ 规模确认超线签 Size-Ack ⑥ 全量门禁在门禁机上跑 ⑦ 合入 main按工单压成一笔 打回:返工 四道闸门(会挡住流程的检查) 提交时 pre-commit 推送时 pre-push 开发内环 bun run check 合并总门禁 check:merge
图 9 执行者不推送、不跑合并总门禁;整台机器同一时刻只跑一趟整套检查。
环节做什么关键命令或文件
① 创建工单写已核实的事实、要做什么、验收判据、可写清单;frontmatter 声明 change_paths 与 verify。新功能单的第 1 步写「先打通的那条路」:一条从入口到落库再回到页面的最细真实路径,不按前后端分层拆单tasks/<id>-<slug>.md
② 修改并提交先单独提交认领;只改 change_paths;每次提交带 Task: 尾注独立 worktree,需要时设 WORKTREE_SLOT
③ 自检三条末行原文写进交接卡;再核对改动没有超出声明。真实 PG 等重测试经 sh.ts remote-test.sh 在门禁机跑;交出前跑 pretrain-check.sh,末行要 PRETRAIN okbun run ticket:preflight / ticket:verify / ticket:affected;bun scripts/change-impact.ts --task <id>
④ 初审审查者只读、在隔离副本里复跑;先复述问题、不看实现自己设计、再对比结论:通过 / 有条件放行 / 打回
⑤ 规模确认相对 origin/main,推送碰到 800 行,或生产代码文件达到 15 个时,由调度者签 Size-Ack,执行者不自签;生产代码实际超过工单首估三倍,或碰到 800 行 / 15 个生产代码文件,执行者补 size_ack_overrun 停下等确认,都没超就在交接卡写实际数和首估工单 frontmatter 的 size_ack_*
⑥ 全量门禁串行合并队列按依赖顺序变基、--ff-only,终点在门禁机跑一次合并总门禁;红了按单二分定位tmp/dispatch/v2/pretrain-check.sh → verify-train.sh;这些脚本不进 git,由调度者维护
⑦ 合入门禁绿后按工单压成一笔再推;原分支留档见 dispatch 技能 §6.0

检查与破坏验证(反向证明)

测试证明「对的时候是绿的」,破坏验证证明「错的时候会红」。改了运行或检查行为的工单,要提交一个 scripts/hooks/break-<名称>.ts 并在附录登记。

  1. 基线绿先确认检查现在通过
  2. 破坏落盘故意改坏目标文件并核验
  3. 点名红检查必须因为被点名的原因失败
  4. 逐字节还原finally 里还原并比较字节
  5. 复绿再跑一次通过,核对工作树干净
  • 闸门是会挡住流程的检查;只报告、不挡的叫「检查」。闸门必须能红,否则只是装饰。
  • 合并总门禁里的 jscpd-new-clones 只拦新增的重复代码;确需保留的重复登记进 tests/jscpd-exceptions.json,写明理由、出处和到期日。
  • 「读代码觉得没问题」不能写成「验证通过」;没跑过的写「未验证」和原因。
  • 冲突由写这段代码的人解;只有两边都只往同一份登记表加新行时,调度者可以代解。

详细见:tasks/README.md(§完工规则)· _preamble-hard-rules.md · 根 AGENTS.md §2.1–§2.2 · 19-concepts.md §3、§6 · 检查总览(需要时用 bun scripts/gen-checks-map.ts 生成到 tmp/,不入库)· break-scripts.md · 15-agent-collaboration.md §3.10 · dispatch 技能

8发版与下游

本仓不直接部署任何对外实例(D28)。发版 = 定稿版本志并打附注 tag;下游通过导出、发布包或企业仓拿到新版本,再由下游部署。2.0 起下游主路径是企业仓。

从打 tag 到下游部署 main(底座仓)本仓不直接部署 打版本 tag定稿版本志history.ts --cutdzy 确认后打附注 tag 单应用导出(export-plane)源码 + vendor 包快照 + 文档子集包根带 world-version.json 发布包(release-plane)补丁 + 整文件替换 + 包快照upgrade.sh + 签名 license + 清单 企业仓(enterprise-repo.ts)create:生成企业仓upgrade --commit:按固定提交升级 单应用客户仓在仓里跑 upgrade.sh 收发布包冲突停下,等人工解 企业仓(2.0 起的主路径)选中的应用 + center + tickets一份共享底座包,整仓一个版本多应用默认共用一个 PG 实例检查:check / check:push镜像:check:image 部署由下游仓执行,不从本仓推 版本志干完一件事就往 unreleased.md 追一条;打 tag 时一条命令定稿,同时导出给客户看的 whats-new(World Version 的叙事部分)
图 10 发布面只单向输出;客户实例不连它也照常营业。

要点

  • 打 tag 前先 bun scripts/history.ts --cut <version> --dry-run 看预检;正式运行时定稿版本志、重开 unreleased.md 并导出给客户看的版本说明。v2.0.0 起打附注 tag。预检共四项,第四项查手册截图:哪个应用缺图就拒切,先把当天门禁机手册重拍的提交收进 main 再切(1025)。
  • 每次打 tag 前,按 playbook-update.md 更新本页。
  • 单应用导出:bun scripts/export-plane.ts --app <app> --out <dir>,带走该应用实际消费的包(只读)和规范子集;新导出还带打包脚本 scripts/build-images.ts 及其依赖,单应用发布包暂不送达这几个文件,旧仓要人工补。
  • 发布包:bun scripts/release-plane.ts --app <app> --from <tag> --to <tag> --out <dir>;交给下游前要在生产形态下真起来一次(--smoke)。
  • 企业仓升级:在上游跑 bun scripts/enterprise-repo.ts upgrade --repo <企业仓> --name <代号> --commit <完整 SHA>;不用移动的 main 代替固定提交。命令不跑迁移、不推送、不部署。目标提交正好是 v* tag 时,企业仓 UPSTREAM.md 的底座版本写 tag 名(1085)。部署后,实例在 10-10 之前就有 center 绑定的,再跑一次统一 ID 批量更正,见企业仓升级手册「部署后:统一 ID 批量更正」。
  • 下游单仓逐仓同步(scripts/sync-downstream.ts)是 2.0 之前的路径;v2.0.0 起不再单独同步各单仓,改走企业仓。
  • 导出面的文档子集由 scripts/lib/export-plane-docs.ts 登记:每份 docs/ 文件都要裁决带或不带。本页属于母仓导读,不随单应用导出;企业仓由 create / upgrade 带一份只读副本(911),页头写明来源提交,企业仓里改过副本时同步会停下。

一个实例怎么跑、怎么运维

项现在的做法正本
部署形态一个应用一个镜像 + 外部 PG:工作站提供与业务库隔离的 PG 实例,对外 compose 多一个 PG 容器;新部署用 PG 18,已部署的不强制升级。企业仓多应用部署默认共用一个 PG 实例,每个应用一个库一个账号(deploy/shared-pg/,944);只买一个应用时用该应用自带的 PGD40;D41;13 §12
备份备份在镜像里:每日 pg_dump 写挂载卷,保留 7 份日备份与 4 份周备份,每次用 pg_restore --list 校验D40;restore-drill.md
部署脚本只有模板 templates/saas-app/deploy/ 里的一份手改;备份、恢复、发布、安装等八种脚本的应用副本由 template-derived-sync.ts --write 照模板生成,检查守住一致(1064、1065)deploy.md
数据库角色密码deploy/db-ops.sh roles 遇到环境文件里没填的角色密码时,三个角色各自随机生成 32 位,不再从主密码派生;已有的值不动(1129)02 §3.3;db-performance.md §1
健康检查/api/health 报数据库与迁移是否就绪及 baseVersion;安装脚本核对镜像、胶囊与运行中的版本一致后才写「就绪」回执13 §6
License发布包里的 license.json 离线验签、零外呼;过期即拒绝,没有宽限期;发布包交出前要验证缺 license 时拒绝启动19-concepts §3.1(license-offline);12 §1
部署来源本仓不部署;现在只有 preview 环境。八个单应用仓已并入 mtyq-enterprise 企业仓;企业仓已在本地升到 v2.1.1(1024),推送由调度者做。preview 上九个应用的部署来源由公司 FDE 基于企业仓切换,底座侧不触发部署。v2.1 冻结时还没切完(dzy 10-13);切换进度由公司 FDE 掌握,不算 2.2 的判据。全部切完 7 天没有回退,再归档单仓(856)。2.2 发版后企业仓升到 2.2(28 §23)D28;28 §22;deploy.md §3

详细见:D28 · docs/history/README.md(版本志与打 tag)· 13-deployment.md §6、§11–§12 · 10-customization.md §1.3、§3 · enterprise-upgrade.md · downstream-sync.md · D41 · 28-flow-driven.md §22–§23(下游路径)· D40(单镜像与外部 PG)· deploy.md · restore-drill.md

9FDE 定制指南

先看代码里的 [CUSTOM:Lx] 标记再动手:L0–L2 能改,L3 禁止改。判定口诀:这条改动客户 B 也要吗?要,就回上游改。

定制点分级与判定口诀 L0 品牌 / 部署配置shared/branding.ts、.env;页面只消费品牌对象 L1 数据字典角色显示名、状态文案、下拉字典、UI_THEME L2 业务规则(客户真正买的东西)域模块、前端 feature、迁移(9000 起)、Agent 注册表、事件订阅 L3 协议与基建(禁止改)vendor 包、engine.ts、idempotency.ts、security.ts plugins:下游可改改过的文件升级时停下等人工 事件订阅:新增文件不改发事件的一方,升级零冲突 判定口诀这条改动客户 B 也要吗?要 → 回上游改,再合新 tag不要 → 在客户仓 L0–L2 改动手前rg 找 [CUSTOM:L] 标记l3-check(上游仓运行)判 L3不改名、不挪目录发现通用 bug必须回流底座修,再发新版本
图 11 等级越高越不许改。改名是升级期最贵的操作。

拿到企业仓后怎么跑起来

  1. 先读企业仓根的 AGENTS.md 与 README.md,再读要改的那个应用的 apps/<app>/AGENTS.md。
  2. 仓根 bun install --frozen-lockfile,再 bun run hooks:install 装上推送前检查。
  3. 日常检查:bun run check;推送前:bun run check:push;镜像:bun run check:image(真实 docker 构建,手动跑)。
  4. 企业仓结构:apps/<app>/、共享底座包 packages/(只读)、企业公共代码 common/、全仓一处的 docs/data-exchange.md、UPSTREAM.md、多应用共用的 PG 部署 deploy/shared-pg/、上游 PlayBook 只读副本 docs/playbook/index.html。
  5. 客户要开飞书通知时,再读飞书通知接入手册。验收前先跑统一 ID 批量更正;不跑的话,10-10 之前从 center 绑定应用的人收不到汇总和紧急推送。

能改

  • L0 品牌(含登录页左栏文字)、端口、身份源、飞书开关
  • L1 角色显示名、状态文案、主题
  • L2 域模块、页面、迁移、Agent operation、事件订阅
  • L2 流程定义(按业务方确认的修改)
  • 插件目录里的代码(fork 语义)

不能改

  • L3 vendor 或仓根 packages/ 下的共享包
  • L3 Agent 协议接线:engine.ts、idempotency.ts
  • L3 server/security.ts 与数据库基建。不登录也能访问的 /api 路径名单也在这个文件里;要加这类路径(如第三方回调),回上游提单,经调度者或 dzy 批准。
  • 不改文件名和目录结构
  • 不直接 merge 上游 tag(没有共同祖先)

定制一条业务流程

  1. 收意见业务方在手册流程章点「提修改」,或在 market、itam 的待办卡和单据详情页点「这里不对」(带上单号,843),意见进 tickets;意见类型除了流程修改,还可以是新看板、改指标口径(968)
  2. 起草FDE 的 Agent 经 tickets 的 Agent API 读原文和流程定义,写回结构化草稿;带单号的意见可经主人应用的只读操作取这张单的流转记录
  3. 确认业务方本人在 tickets 网页上确认草稿;业务方的 Agent 可以代提意见,但不能代确认。执行者 Agent 写的进度记录,业务方在自己那条意见页上能看到(964)
  4. 改定义改 shared/flows/*.ts;改名或删步骤写 renamed 对照
  5. 重新生成并检查静态检查、路径测试、手册流程章跟着变

加页面、加 Agent 操作

  • 加页面:放 src/features/<domain>/(L2),用 @bf/ui 组件,不新增自定义基础组件;页面有且只有一个主动作,列表要分页。表单默认提交成功后可以再点;新建类、成功后不离开页面的表单要声明 lockAfterSuccess,或用 idempotencyKey="auto"(1046)。「接入 Agent」页用 @bf/ui 的 AgentAccessPage,应用只传读写函数,不另写一份(1058、1060)。
  • 加 Agent 操作:属 L2。注册 operation(name、mode、严格的输入输出 schema),接 handler 与 simulate,授权与网页同源,补拒绝测试,跑 bun run agent:manifest -- --write 重新生成清单和 SKILL 表;写操作一律接幂等。完整 13 项清单见 05 §11.6。
  • 改登录页文字:属 L0。应用名、一句业务说明、「这里能做什么」(最多三条)、「登录遇到问题」都在 shared/branding.ts 里改;登录页本身用 @bf/ui 的 LoginLayout,不散改页面(1000)。
  • 挂副作用:优先新增 subscribers.ts 订阅事件,不改核心模块,升级时零冲突。要提醒某个人,就产生一条待办,由 center 统一推飞书;应用里不再自己直连飞书发消息。
  • 大改动:相对基线碰到 800 行,或生产代码文件达到 15 个,提交要带 Size-Ack;新增 lib / patterns 导出要带 Reuse-Check。

升级时冲突怎么办

  • 企业仓:升级在副本里做三方合并。失败先读回执,副本保留冲突标记,原仓不动;按回执点名的文件处理后重跑。不要 reset 原仓。
  • 单应用客户仓:upgrade.sh 停住后不要 reset --hard;先 git fetch upstream --tags,再按 10 §3.2 分步处理。确实要整包重来,reset 后再跑 upgrade.sh --clean-round,不要 git clean -fd。
  • 客户改过的整文件、插件文件,升级会停下等人工,不覆盖客户的字节。
  • SKILL.md 走三方合并:生成区块由上游重生成,客户只改区块外的手写句子。企业仓里的 PlayBook 副本不要改,改过会让升级停在「同步上游 PlayBook」。

发现通用问题怎么回流

  • 通用 bug:走缺陷回流——开 downstream-defect 工单、在底座写回归测试、核对守护检查、关单;底座修好后发新版本,下游升级拿到。见 defect-backflow.md。
  • 可复用的能力:走能力回流七步——判可复用、逐案人批授权、去客户化、红线自查、补五件套、定落点、收录进能力目录;只回流代码,不回流数据。见 capability-backflow.md。

详细见:12-customization-playbook.md(操作正本:§1 交付流程、§2 Prompt 包、§3 验收命令、§4 定制点速查)· 10-customization.md(§1.3 企业仓、§2 L0–L3、§3 升级、§4 回流)· 28-flow-driven.md §10–§11 · 05-agent-api.md §11.6 · 03-frontend.md · 11-ui-kit.md · enterprise-upgrade.md · FDE 学习路径

10本地开发与常见问题

本地从零到能登录只要六步;排障时始终用同一个 requestId 横着串日志。

本地起步六步与 requestId 排障链 ① 对齐 BunGit Bash 补 PATH ② bun install装依赖与钩子 ③ 领 slotworktree-slot.ts ④ 起一次性 PGdocker run ⑤ 起 API 登录health 为 ready ⑥ 用完拆掉删自己起的 PG 排障:始终用同一个 requestId 横着串 x-request-id或用户给的八位编号 运行日志第一站 audit_logs登录与写操作 未捕获的 500也在运行日志里 agent_request_logsAgent 调用
图 12 上排:本地起步(以 tickets 为例,身份固定 local)。第 ① 步对齐到根 package.json 写的 Bun 版本(2.2 起是 1.4.3,1122)。第 ⑥ 步只删自己用 docker run 起的那个 PG 容器;用 compose 起的才用 down -v 删整个项目。下排:排障按 requestId 串联。未捕获的 500 在同一份运行日志里找 Unhandled request error 那一行,不再落 request_errors 表。

常见问题

现象原因与处理
Git Bash 里找不到 bun 或 dockerGit Bash 默认 PATH 不含两者,开工先补 PATH;PowerShell 里敲 bash 会进 WSL。
登录后其它接口都返回 403「请先设置新密码」首次引导的管理员 mustChangePassword=true,改密前只有豁免接口可用。复现 404 要带一个已改过密码的账号的登录 cookie:不带 cookie 回 401,带首次引导管理员的 cookie 回 403。
并行测试撞端口或撞库每个工作树设自己的 WORKTREE_SLOT;端口由 scripts/worktree-slot.ts 计算,不要写死。
机器变慢、内存吃紧先跑 bun run orphans 看 Agent 遗留的孤儿进程;只杀脚本判定为 kill 的,不要按名字批量杀。
Agent 写操作返回 400 MISSING_IDEMPOTENCY_KEY真实写入必须带 Idempotency-Key;simulate 反过来不许带。
网页写接口返回 409 REQUEST_OUTCOME_UNKNOWN同一个幂等键的上一次请求结果不明(处理中超过 10 分钟)。服务端不自动重跑:先按业务编号核对是否已经生效,没生效再换新键重试(1026)。
有人输错几次密码后,所有人都登录不上反向代理没传 X-Real-IP,整个实例的请求挤进同一个限流桶。在反代配置里补上这个头(1027)。
Agent 写操作返回 403 READONLY_KEYKey 的 scope 是 read;需要写就让管理员在应用网页签一把 read_write 的 Key。
用户报来一个八位排查编号它是 requestId 的前八位。先按前缀搜应用日志,再用命中的完整 requestId 查审计和错误记录;命中多条时用复制信息里的时间、页面和操作区分。
数据库慢先看脱敏慢 SQL 快照,再按只读边界做 EXPLAIN。

详细见:local-dev.md · troubleshooting.md · db-performance.md · 05-agent-api.md §5.3、§6(结果不明)· 02-backend.md §5(限流来源)· 根 AGENTS.md §2.1(并行与测试隔离)· testing/README.md

11术语表

只收读者会碰到的词。定义取自正本原句,括号里是出处;拿不准某个词时以出处为准。

术语分三组 仓库与协作工单 · 调度者 · 执行者 · 审查者闸门 · 破坏验证 · 未验证worktree · 先打通的那条路 业务流与 Agent流程定义 · 步骤 · 流转 · 流转记录表单即权限 · 主人应用 · 交接步委托代办 · operation · scope 交付与定制开发面 · 发布面 · 企业仓L0–L3 · World Version派生待办
图 13 下表按这三组排列。
工单
tasks/<id>-<slug>.md,一个语义交付单元。commit 是它的物化,不是反过来。19-concepts §1
调度者
拆工单、定边界、裁决争议、验收合入、清理资源。只做判断不做执行试错。19-concepts §6
执行者
领一张工单,在自己的 worktree 里修改、验证并提交,按硬规则交接本地分支,不推送。19-concepts §6
审查者
独立验证一张已就绪的工单。只读、不进别人的 worktree、在隔离副本里跑。19-concepts §6
dzy
本仓唯一的人类负责人与最终裁决人;其余角色都由 AI Agent 担任。19-concepts §6
闸门
会挡住流程的检查:pre-commit、pre-push、bun run check(开发内环)与 bun run check:merge(合并总门禁)。只报告不挡的叫检查。19-concepts §3
破坏验证
故意违规一次,证明闸门真的会红。常驻闸门脚本放 scripts/hooks/。19-concepts §3
未验证
声明没跑过的部分及原因。把「读代码觉得没问题」写成「验证通过」是本仓最不能接受的一件事。19-concepts §6
worktree
一个 Agent 的独占工作树;一个 worktree 同时只能有一个 Agent 在写。19-concepts §1
先打通的那条路
新功能单先做的一条最细真实路径:从用户入口经接口、落库再回到页面,端到端跑通并有测试守住,再往宽里补权限、异常和细节。用来避免按层拆单后在接缝处出错。19-concepts §6
流程定义
一条业务流的唯一正本:一个 TypeScript 数据对象,声明主人应用、角色、字段、阶段、步骤、流转条件与步骤改名对照;带格式校验与流程静态检查。已在 market 订单交付、ITAM 资产领用和归还、foodbuy 月度采购(2.2,1072)接入,其余流程按 28 的迁移方法逐条迁。19-concepts §10;28 §23
步骤
阶段里的一个可执行节点:映射业务表状态列的一个或几个取值,有一个执行角色、一张表单、一个 Agent 写 operation。19-concepts §10
流转
从一个步骤到另一个步骤的一次推进。一次流转 = 一个 PG 事务。19-concepts §10
流转记录
每个应用一张的追加表:每次流转一行,记录流程、业务对象、前后步骤与状态、命令、记录人、执行角色、时间,另记流转类型与理由。别当待办表。19-concepts §10
表单即权限
每一步表单里列出的字段,就是该步角色能改的字段;服务端强制,前端只是展示。19-concepts §10
主人应用
一条流程只归一个应用,流程状态只存在它那里。19-concepts §10
交接步
流程走到别的应用负责的步骤时的那一步:主人应用经对方统一 Agent API 同步调用对方一个已注册的写 operation。19-concepts §10
委托代办
有效期内,被委托人代办委托人的角色;数据边界取双方自己边界的交集,两边都有且不同则这份委托不生效。每份委托绑定委托人身份,不能再转委托,执行人仍记实际办理人。19-concepts §10
operation
Agent API 的一个可调用动作,注册表里的一条。不是 REST endpoint。19-concepts §2
scope
API Key 能调哪些 mode:read 只能调读操作,read_write 都能调。19-concepts §2
开发面
从本仓某个 tag 导出的一个应用提升为根 + vendor 包快照 + 文档子集。给 FDE / Agent 开工用,目的是降低理解面。它和「客户定制版」是同一个东西。19-concepts §7
发布面
我方持有、唯一、单向输出、客户侧离线可消费的交付通道:tag 与镜像、补丁包与包快照、参考实现库、License 凭据、安全通告。19-concepts §7
企业仓
一个企业一个仓:选中的应用 + center(应用 ≥2 个时必带)+ tickets(标配)+ 一份共享底座包 + 企业自己的公共代码目录 + 全仓一处的企业级数据交换约定。共享代码与身份,不共享数据库;多应用部署默认共用一个 PG 实例,每个应用仍是自己的库和账号。19-concepts §10;D41(共用 PG 实例,944)
L0–L3
定制点分级:L0 品牌/部署配置、L1 数据字典、L2 业务规则、L3 协议与基建(禁止改)。19-concepts §4
World Version
交付给客户的完全可读的版本对象:语义化的工单、版本叙事、文档与用户手册组成的整体。客户无需理解任何底层技术。19-concepts §7
派生待办
角色工作台首屏的待办队列;单条待办由业务表查询派生,不落库、不建手工待办表。19-concepts §2「workbench-todo」

详细见:19-concepts.md(工程与协作概念)· 16-glossary.md(业务名词)· 29-plain-writing.md(写作规范)