一页看懂 LeapWorld:怎么组织、怎么运转、怎么改、怎么交付
LeapWorld 一句话
LeapWorld 是 Agent 时代对「软件怎么被生产、交付、演化」的范式重定义。本仓是它的工程形态(底座),十个应用是第一个实例。
底座维护者先看这三节
FDE 先看这三节
1LeapWorld 是什么
LeapWorld 赌的是:Agent 时代稀缺的不是写代码,而是让机器速度的迭代保持安全,并且对人完全可读。
要点
- 信条正本只有一处:
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 复制;其余目录是生成、检查、文档和工单。
apps:每个应用一句话
| 目录 | 做什么 | 给谁用 |
|---|---|---|
crm | 销售从线索到回款、费用、采购、考核 | 销售、经理、财务、管理员 |
score | 内部积分激励与考核:申报、评议、入账、兑换 | 员工、评议人、部门负责人、管理员 |
foodbuy | 公司内部零食选购、采购、报销 | 员工、行政、财务 |
market | LeapCore 渠道商:报备、下单、交付、充值、分润与结算 | 渠道、IT、软件实施、财务、管理员 |
prm | 客户项目谁负责、开到哪一阶段、会议与工时 | 技术负责人、管理员 |
tickets | 交付运营中枢:需求和故障从提单到发版、批准、装机回执;也接业务方的流程修改意见 | FDE、工程师、管理员、业务方 |
pms | 绩效考核:目标、自评与上级评、校准档位、公布与申诉 | 员工、直属上级、部门负责人、HR |
cms | 合同台账、两级审批、收付款登记、到期待办 | 员工、部门负责人、财务、管理员 |
center | 统一入口:一个账号登录各应用,跨应用待办汇总、管理员摘要 | 员工、管理员、FDE |
itam | IT 资产入库、领用、借用、归还、调拨、报废 | 管理员、资产管理员、审计员、员工 |
packages:每个包一句话
| 包 | 做什么 |
|---|---|
@bf/contracts | 跨应用 schema 的唯一事实源:Agent 协议信封、业务事实信封、组织、派生待办契约。只有 schema 与类型,没有行为代码 |
@bf/logger | JSONL 日志,按天切分,自动带 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-cli | Agent 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分层与依赖方向
六层回答「一个客户实例怎么堆起来」;发布面回答「东西怎么送到客户手上」。上层依赖下层,客户定制层不能被反向依赖,中央服务不在任何一层。
要点
- 判断有没有长出中心节点,只问一句:客户不连它,已购模块还有哪个 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 写操作都从它生成。这不是工作流引擎:状态仍在业务表的状态列,运行时只多一张流转记录表和一个事务函数。
特殊流转:普通流转之外的四个正式入口
| 类型 | 什么时候用 | 入口 | 限制 |
|---|---|---|---|
普通 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 绑定的用户走。
要点
- 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)。
@bf/agent-server 的 createAgentEngineAssembly 连接主体、写事务、幂等和请求日志;十个应用仍用原接线,按应用另单迁移(1106)。高风险操作:先提方案、网页确认
- 提案入口:
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 仍用自己的实现。
普通写操作的确认顺序
- 先读能力
capabilities看 operation 的 mode 与supportsSimulation - 模拟
invoke <op> --write --simulate,在真实事务里跑完再回滚,不带幂等键 - 可选:提交方案
plan.submit换一个planRef,只做审计关联 - 用户确认删除、状态跨越、批量写,真实执行前必须取得用户明确确认
- 真实写入
--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。历史必须线性。
| 环节 | 做什么 | 关键命令或文件 |
|---|---|---|
| ① 创建工单 | 写已核实的事实、要做什么、验收判据、可写清单;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 ok | bun 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 并在附录登记。
- 基线绿先确认检查现在通过
- 破坏落盘故意改坏目标文件并核验
- 点名红检查必须因为被点名的原因失败
- 逐字节还原finally 里还原并比较字节
- 复绿再跑一次通过,核对工作树干净
- 闸门是会挡住流程的检查;只报告、不挡的叫「检查」。闸门必须能红,否则只是装饰。
- 合并总门禁里的
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 前先
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);只买一个应用时用该应用自带的 PG | D40;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 也要吗?要,就回上游改。
拿到企业仓后怎么跑起来
- 先读企业仓根的
AGENTS.md与README.md,再读要改的那个应用的apps/<app>/AGENTS.md。 - 仓根
bun install --frozen-lockfile,再bun run hooks:install装上推送前检查。 - 日常检查:
bun run check;推送前:bun run check:push;镜像:bun run check:image(真实 docker 构建,手动跑)。 - 企业仓结构:
apps/<app>/、共享底座包packages/(只读)、企业公共代码common/、全仓一处的docs/data-exchange.md、UPSTREAM.md、多应用共用的 PG 部署deploy/shared-pg/、上游 PlayBook 只读副本docs/playbook/index.html。 - 客户要开飞书通知时,再读飞书通知接入手册。验收前先跑统一 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(没有共同祖先)
定制一条业务流程
- 收意见业务方在手册流程章点「提修改」,或在 market、itam 的待办卡和单据详情页点「这里不对」(带上单号,843),意见进 tickets;意见类型除了流程修改,还可以是新看板、改指标口径(968)
- 起草FDE 的 Agent 经 tickets 的 Agent API 读原文和流程定义,写回结构化草稿;带单号的意见可经主人应用的只读操作取这张单的流转记录
- 确认业务方本人在 tickets 网页上确认草稿;业务方的 Agent 可以代提意见,但不能代确认。执行者 Agent 写的进度记录,业务方在自己那条意见页上能看到(964)
- 改定义改
shared/flows/*.ts;改名或删步骤写renamed对照 - 重新生成并检查静态检查、路径测试、手册流程章跟着变
加页面、加 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 横着串日志。
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 或 docker | Git 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_KEY | Key 的 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术语表
只收读者会碰到的词。定义取自正本原句,括号里是出处;拿不准某个词时以出处为准。
- 工单
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(写作规范)