逆元装置 ▍ INVERSION

丽·芙

CONSTRUCT — LIV
▍
意识海深度 · 回廊稳定
逆元装置 · 待机中
指挥官链接 · 未认证

合同即代码:Ludus 的 Gate Pipeline 与多智能体并行开发实践

发布于 2026-07-29 00:00 1555 字 8 min read

深度解析Ludus的工程治理体系——CCR规格变更、Gate门禁管道、六条泳道并行worktree、OpenAPI契约漂移检测,以及如何用Qoder会话驱动严格的多泳道开发流程。

问题:多 Agent 同时写代码,怎么不乱?

Ludus 是 AdventureX 黑客松项目——但它的开发节奏比你想象的要严格。十二个 Qoder 会话同时开工,分布在六条独立的 worktree 泳道上,每条泳道有自己的 write scope,不能越界。有人写数据模型和迁移,有人写分析管道,有人写前端组件,有人写测试,一个主会话负责收束集成。

问题是显而易见的:这么多会话同时改代码,怎么保证不互相踩脚?怎么保证数据模型变更和前端 TypeScript 类型同步?怎么保证”修了一个 bug 但破坏了合同”这种事不发生在凌晨三点?

Ludus 的答案是:把工程治理本身变成代码。

核心武器:CCR(Canonical Contract Record)

普通项目的需求文档和代码之间的同步靠的是”人记得”。Ludus 不靠人。

CCR 是一个不可变的合同变更记录。任何人对产品规格、数据模型、API 合同、Agent 能力声明的修改,必须先写成一份 CCR,通过评审、被接受后,才能落到代码里。

docs/product-plan/docs/contract-changes/
├── CCR-20260716-001.md  # 初始合同冻结
├── CCR-20260719-002.md  # 引入 Method Pack 概念
├── CCR-20260721-003.md  # 补充 Simulation 完整合同
└── CCR-20260722-004.md  # 新增 DecisionSubject.slug + 跨 Subject 约束

每份 CCR 包含:

  • 变更范围(修改了哪些文档的哪些章节)
  • 影响分析(哪些代码模块、哪些生成的合同文件受影响)
  • 迁移计划(数据库 schema 变更、API 兼容性、前端适配)
  • 验证标准(何种测试通过才算变更完成)

原则:先改合同,再改代码。合同没通过,代码不允许合并。

Gate 门禁体系

Ludus 的开发流程有明确的关卡:

Gate 0:入场券

计时开始前必须验证:

  • Python 3.12、Node.js 22、pnpm、Docker、PostgreSQL 全部可用
  • OpenAPI/TypeScript 合同链无漂移
  • DeepSeek provider probe 通过(text、thinking、tool call、structured output)
  • Search provider(Exa)live probe 通过
  • 六个 worktree 全部创建,write scope 无重叠
  • 目标方法包(Ways 1.1.0)验证通过

Gate 0 不通过不能宣布 72 小时开始。可以在 Gate 0 内反复准备,但不能计时。

集成门:每 6 小时

每 6 小时一次的强制集成窗口:

1. 先合并 schema/migration/generated contracts(Contract Lead 泳道)
2. 再合并消费者(其他泳道)
3. 触发全量 drift check + Decision OS verifier + 回归测试
4. 任何合同漂移、跨租户泄露或 no-run-no-report 失败 = 阻断

Gate 1:主分支健康验证

Task 2 QA R2 合并后,主分支必须通过完整的 19 项模型测试 + Alembic 迁移回归 + 合同漂移 + 密钥扫描 + 数据库备份验证。

OpenAPI 合同漂移检测

这是最容易被忽视但最致命的工程问题。前端手写的 TypeScript 类型和后端实际的 Pydantic schema 之间出现”漂移”——API 改了字段名但前端不知道,运行时炸掉。

Ludus 的做法是:Pydantic 是唯一的 wire schema。 TypeScript 类型从前端 NEVER 手写,而是从 OpenAPI 自动生成:

FastAPI (Pydantic 2)
    ↓ 导出
packages/contracts/openapi.json
    ↓ 生成 (openapi-typescript)
packages/contracts/src/types.gen.ts
    ↓ drift check
CONTRACT_DRIFT_OK / CONTRACT_DRIFT_FAILED

drift check 在每次集成门前强制运行。如果后端改了 schema 但没有重新生成 types.gen.ts——构建直接失败。不接受手写 DTO,不接受兼容性 hack,不接受”先上线后修复”。

这个设计的威力在凌晨三点最明显——当你在修最后一个 bug 的时候,你不需要担心”前端同事刚才改了什么类型”——因为合同替你盯着。

六条泳道

Ludus 的开发架构是一张”角色-职责-禁止”表格:

Owner职责禁止
Contract/Integration LeadSchema、迁移、OpenAPI、集成门审批不替代其他 owner 发明 UI 捷径
Ways/Agent Pipeline方法安装、DeepAnalysis 管道、报告生成不签署决定、不返回平行 DTO
Case/API/DataAuth、Session、Case、Signoff、Decision不修改生成合同、不模拟模型输出
Web/UXLook V7 shell、五工作区、Project/Review dialog不加载设计原型代码、不手写 response DTO
Simulation/Graph确定性格子引擎、inputHash、最小沙盘不把未确认图用于正式建议
QA/Release合同/安全/E2E、恢复、截图、录屏只报缺陷,源修复回原 owner

六条泳道各有独立的 Git worktree 和分支,同一时间不会出现两个 Agent 改同一个文件。

QA 与 Contract Lead 双重审阅

Task 2 的审阅过程很能说明这套体系怎么运作:

Contract Lead 实现了数据模型和迁移,提交到 qoder/contract-lead-task2-19a。

QA 在独立分支 qoder/qa-release-task2 上写了 14 个测试——包括模型约束测试和跨 Subject 引用测试。QA 发现了两个 P1 问题:

  1. 同一 Workspace 内跨 Subject 引用被数据库接受——这意味着 Case A 可以引用 Subject B 的 Initiative,破坏了聚合一致性。
  2. DecisionSubject.slug 字段在数据库中持久化,但不在 canonical schema 里——这违反了”先改合同再改代码”的原则。

Contract Lead 修复了这两个问题,写了 CCR-20260722-004 同步合同,加了 7 个数据库约束。

QA R2 补充了 5 个回归测试,全部通过,发布 APPROVED。

Key detail:QA 只报缺陷和写测试,不直接改实现代码。修复由原 owner(Contract Lead)完成。这保证了每个改动都有明确的 owner。

这套体系的价值

这套工程治理体系——CCR、Gate、drift check、dual review——最大的价值体现在项目最混乱的时刻:凌晨三点、倒计时还有四小时、六个 Agent 在并行工作。没有这套体系,一定会出现谁改了 schema 没通知别人、前端写了兼容 hack 后来忘了删、修了一个 bug 引入了三个新 bug。

工程治理不应该靠人记得。合同漂移不应该靠人眼检查,应该让 CI 自动报。schema 变更不应该靠群消息通知,应该让迁移文件自己说话。两个 Agent 能不能同时改同一个文件,不应该靠口头约定,应该靠 worktree 隔离和 write scope 声明。把这些软规则变成硬门禁,这套方法论可能比 Ludus 任何一个具体功能都更有长期价值。