把专业判断嵌进研发流水线:我的四个 Skill 如何与 Compound Engineering 协作
把专业判断嵌进研发流水线:我的四个 Skill 如何与 Compound Engineering 协作
安装 Compound Engineering 后,我没有把自己沉淀的 Skill 全部删除,而是留下了四个:
discover-domaindesign-systemwrite-unit-testswrite-integration-tests
Compound Engineering 负责把一轮研发工作从需求推进到交付;这四个 Skill 则补充领域假设验证、架构决策和测试层级选择。两者不是两套流程竞争,而是主流程与专业能力协作。
Compound Engineering 提供研发主循环
Compound Engineering 把研发活动组织成一条可以重复运行的链路:
flowchart LR
A["ce-brainstorm — 明确要做什么"] --> B["ce-plan — 形成实施计划"]
B --> C["ce-work — 执行计划"]
C --> D["ce-simplify-code — 简化实现"]
D --> E["ce-code-review — 审查结果"]
E --> F["ce-compound — 沉淀经验"]
F -. "为下一轮提供上下文" .-> A
这条主循环避免模糊需求直接进入编码,也让计划、代码、验收和经验沉淀形成闭环。但“流程覆盖了某个阶段”不等于“这个阶段里的专业问题已经解决”。
例如,面对陌生的清结算系统,需要先验证领域模型;设计跨模块能力时,需要决定数据所有权和一致性策略;测试阶段还要判断一个行为究竟应该由单元测试还是集成测试证明。
四个 Skill 就插在这些决策点上:
flowchart TB
D["discover-domain<br/>建立可验证的领域认知"] --> B["ce-brainstorm<br/>形成 Product Contract"]
B --> S["design-system<br/>形成架构决策包"]
S --> P["ce-plan<br/>生成实施计划"]
P --> W["ce-work<br/>实现功能"]
W --> U["write-unit-tests<br/>验证纯逻辑"]
W --> I["write-integration-tests<br/>验证真实组件链路"]
U --> R["ce-code-review<br/>综合审查"]
I --> R
R --> C["ce-compound<br/>沉淀解决方案"]
R -. "发现测试缺口" .-> U
R -. "发现链路缺口" .-> I
一、discover-domain:先验证领域假设
discover-domain 用来接手陌生业务领域、技术方向或既有子系统。它不定义功能,也不拆实施任务,而是建立可以被代码、数据和一手资料验证的认知模型。
它重点回答四个问题:
- 这个领域解决什么问题?
- 典型参与者、正常路径和失败场景是什么?
- 核心概念、组件和依赖如何关联?
- 常见的数据流、控制流和技术形态是什么?
更重要的是,它会把信息分成三类:
- 已被代码、数据或资料证实的事实。
- 根据证据作出的推断。
- 可能改变后续决策的待验证假设。
例子:接手清结算子系统
假设只知道系统里存在账户、账单、应收、实收、退款、对账和结算批次。直接规划,很容易把这些名称误认为已经明确的模块边界。
discover-domain 会先追踪一条真实资金链路:
1 | 订单业务事实 |
然后验证:
- 应收和实收的关系基数是什么?
- 账单是展示快照,还是结算依据?
- 退款发生在结算前后时分别怎样记账?
- 重放事件会不会造成重复记账或结算?
它最终交付事实、假设、认知缺口、风险和来源。下一步如果需要定义功能,进入 ce-brainstorm;如果需要判断是否采用某个外部方案,进入 ce-pov;需求已经明确时,再把证据交给 ce-plan。
它的价值不是“多做一次调研”,而是不让后续计划建立在未经验证的领域想象上。
二、design-system:把架构决策交给计划
ce-brainstorm 负责明确“做什么”,ce-plan 负责形成实现就绪的计划。design-system 位于两者之间,负责那些不应由产品讨论决定、也不应留到文件级任务拆解时临时决定的问题:
- 系统与模块边界。
- 数据所有权和依赖方向。
- API、事件、状态机和数据模型。
- 事务、幂等与并发更新。
- 外部调用的超时、重试和降级。
- 部署形态、扩展触发条件与观测点。
- 安全、性能、一致性和迁移风险。
Compound 的 Product Contract 会使用稳定标识:
| 标识 | 含义 |
|---|---|
R-* |
Requirement,需求 |
A-* |
Actor,参与者 |
F-* |
Flow,关键流程 |
AE-* |
Acceptance Example,验收示例 |
design-system 会保留这些标识,不在架构阶段重新解释已经确认的产品行为。它回答的是:为了可靠实现这些需求,架构必须满足哪些约束?
例子:通知暂停功能
假设 ce-brainstorm 已形成以下契约:
R-01:用户可以暂停某类通知。F-01:用户选择通知类型并设置恢复时间。AE-01:恢复时间到达后,通知自动恢复。- 范围外:不做日历联动。
design-system 会继续明确:
- 使用
(tenant_id, user_id, notification_type)唯一约束。 paused_until按 UTC 存储。- 有效暂停由
status == ACTIVE && paused_until > now判断。 - 定时任务只负责状态收敛,不能成为正确性的唯一保障。
- 用户延长暂停与后台恢复并发时使用条件更新。
- 状态修改和恢复事件通过 Transactional Outbox 原子提交。
最终交给 ce-plan 的不是另一份文件级计划,而是一份架构决策包:关联的 R/F/AE、实现护栏、ADR、迁移顺序、测试义务和仍需确认的决策。
这样,ce-plan 仍然拥有任务拆解权,但不需要在规划阶段猜测核心架构。
三、write-unit-tests:先判断该不该单测
许多 AI 生成的单元测试只是在验证 Mock 配置,或者用测试代码重新实现生产算法。write-unit-tests 的第一步不是写测试,而是判断测试层级:
- 行为是否包含数据库、HTTP、Redis、文件、消息或框架生命周期?
- 去掉外部依赖后,是否仍有值得保护的分支、计算或状态转换?
- 该行为是否容易变化,或者出错后影响很大?
只有隔离、确定性的业务行为才进入单元测试。SQL 排序、ORM 映射、事务提交和 HTTP 序列化,不会被强行 Mock 成“单测已覆盖”。
例子:优惠不能把应付金额减成负数
Compound 计划中存在:
R-07:折扣不得使应付金额低于 0。AE-09:100 元订单应用 120 元优惠,应付金额为 0。
对于纯函数 calculatePayable(total, discount),P0 场景很明确:
1 | 正常扣减:100 - 30 = 70 |
这些测试不需要 Mock,并且能直接关联回 R-07 与 AE-09。如果负数输入、货币精度或舍入方式没有产品约定,Skill 会把它们作为缺口返回,而不是自行创造规则。
它可以承接 ce-work 实现后的逻辑验证,也可以把 ce-code-review 发现的测试缺口变成最小回归测试。输出包括关联标识、场景、运行命令、实际结果和仍需交给集成测试验证的行为。
四、write-integration-tests:真实验证系统拥有的组件
write-integration-tests 负责 API 到数据库、事务、SQL、缓存、事件、流式响应和跨模块状态变化。它遵循一条边界原则:
真实运行系统自己拥有的组件,只替换不可控的外部系统。
| 依赖 | 默认策略 |
|---|---|
| 数据库、Schema、ORM、事务 | 真实运行 |
| 模块内 Service | 真实运行 |
| 第三方 HTTP、支付或 LLM | 协议级 Mock 或测试 Adapter |
| 外部消息系统 | 优先容器,成本过高时使用边界替身 |
| 时钟和随机源 | 可控注入 |
例子:退款与 Outbox 必须原子写入
假设 F-12 定义了这样的流程:
1 | 退款 API |
Service Mock 无法证明事务真的生效。集成测试需要使用真实应用装配和生产同类数据库验证:
- 成功请求只产生一条退款记录和一条 Outbox 记录。
- Outbox 写入失败时,退款记录一起回滚。
- 相同幂等键顺序请求两次,只产生一次业务结果。
- 相同幂等键并发请求,只允许一个事务创建记录。
- 重复投递事件时,下游消费者不重复产生副作用。
第三方退款渠道可以使用协议级 Mock Server,但退款 Service、Repository、事务管理和数据库唯一约束必须真实运行。
最终输出会带回 F-12、真实与替身边界、测试数据隔离方式、运行证据和剩余风险,供 ce-work 或 ce-code-review 继续处理。
一条完整链路可以压缩成八次交接
仍以通知暂停为例,完整协作不需要重复解释每个阶段:
| 阶段 | Skill | 主要输入 | 交付物 |
|---|---|---|---|
| 领域认知 | discover-domain |
现有通知模块 | 事实、假设、缺口和来源 |
| 产品定义 | ce-brainstorm |
认知交接块 | Product Contract 与 R/A/F/AE |
| 架构设计 | design-system |
Product Contract | 架构护栏、ADR 和测试义务 |
| 实施计划 | ce-plan |
统一计划与架构决策 | Implementation-ready 计划 |
| 功能实现 | ce-work |
实施计划 | 代码和基础验证 |
| 分层测试 | 两个测试 Skill | 需求标识与实现 | 逻辑及真实组件证据 |
| 综合审查 | ce-code-review |
计划、代码和测试结果 | Review 发现与回流 |
| 经验沉淀 | ce-compound |
已解决问题 | 可复用项目知识 |
Review 如果发现纯逻辑缺口,回到 write-unit-tests;发现数据库、事务或事件缺口,回到 write-integration-tests。涉及浏览器页面时,再使用 ce-test-browser 或自动浏览器 QA Skill ce-dogfood。
选择入口,而不是执行仪式
四个 Skill 融入 Compound,不意味着任何任务都必须经过全部节点。
| 当前任务 | 推荐入口 |
|---|---|
| 接手陌生领域或旧模块 | discover-domain |
| 需求模糊,不确定做什么 | ce-brainstorm |
| 需要独立系统架构方案 | design-system |
| 需求明确,需要实施计划 | ce-plan |
| 根据计划实现功能 | ce-work |
| 纯逻辑、状态转换或计算回归 | write-unit-tests |
| 数据库、事务、事件或跨模块回归 | write-integration-tests |
| 浏览器页面回归 | ce-test-browser 或 ce-dogfood |
| 已知 Bug 需要定位和修复 | ce-debug |
| 合并前综合审查 | ce-code-review |
一个纯函数边界 Bug 可以直接进入 write-unit-tests;数据库死锁应从 ce-debug 开始,再用 write-integration-tests 构造可重复竞争;页面样式回归没有必要经过 design-system。
这套组合遵循三条原则:
- 一个决策应有一个最终责任方。 其他 Skill 可以提供事实、约束和反馈,但不能静默改写已经确认的决定。
- 交接的是结构化证据。 事实、R/A/F/AE、ADR、测试结果和剩余风险比一句“完成了”更有价值。
- 流程根据风险扩展。 通用主循环提供广度,专业 Skill 只在需要领域验证、架构约束或更高测试层级时介入。
我保留这四个 Skill,不是为了在 Compound Engineering 之外维护另一套研发流程,而是为主流程增加四个专业接口:
1 | discover-domain → 认知接口 |
Compound Engineering 让研发工作完整地向前推进;四个专业 Skill 则确保领域假设、系统边界、一致性策略和测试层级不会因为“流程已经覆盖”而被跳过。