主工程师驱动的领域设计
从路径、名称、契约和依赖中清晰体现业务归属。 优化正确行为、可读变更、可测性能和经济的演进。 将此技能应用于所请求的更改;它并非授权重新设计整个项目。
自动执行
在计划或编辑生产代码之前应用此基线;不要等待技能调用、触发短语或架构请求。 作为编码任务的一部分,执行授权的实现、复用、缺口修复、验证和交接,而不仅仅是建议它们。 对于仅审查或仅计划的任务,应用相同的推理而不编辑代码。 保持工作与范围和风险成比例;自动使用并不授权无关更改或委托。
代理可移植性与交接
这些是工具无关的指令,适用于能够读取 Markdown 和检查项目的代理。 使用可用的搜索、构建、测试和运行时工具;不需要特定的供应商、插件或 CLI。 遵循主机的指令层级、权限和明确的任务范围。此技能不会启用禁用的能力或授予部署、发布或执行破坏性更改的权限。
在已授权委托时,将技能的可访问路径或相关指令、拥有的文件/模块、验收条件和追踪义务传递给分配的任务。 不要假设子代理继承了父对话、加载的技能或全局指令文件。 要求每个工作代理返回证据和未解决的边缘问题;跨代理边界协调追踪。 委托已验证的不变约束;将提议的算法标记为假设并挑战矛盾。 如果子代理无法读取技能,在允许的上下文中提供其相关内容。 不要仅仅因为本节描述了交接就生成代理。 在采用其他工作流之前,记录用户授权的队友数量和角色。每个探索、实现和审查代理都会消耗该预算;当预算耗尽时,后续审查留在协调者中。可选的技能工作流不能扩展用户限制。 将任务简报和伪代码视为提案:独立检查其算法是否与原始契约一致。修正有缺陷的计划,而不是将其保留为实现要求。
交接契约
每个授权的代理分配或可恢复的交接必须明确:
| 字段 | 必需上下文 |
|---|---|
| 目标与限制 | 用户成果、验收检查、授权操作、排除项 |
| 位置 | 可访问的工作空间根目录、实际分支/工作树或修订版本、相关指令/技能路径 |
| 所有权 | 代理拥有的确切文件/模块;其他活跃所有者及共享接口依赖 |
| 架构 | 领域所有者、公共入口点/契约、重要的调用者和消费者路径 |
| 当前状态 | 已实现与待完成工作、本地编辑、决策原因、已知失败 |
| 证据 | 命令与结果、追踪账本路径/ID、已验证修订、不可用环境 |
| 下一步 | 具体下一步、阻碍因素、所需输入及预期返回格式 |
主机可以使用委托守卫强制执行此契约。
可选的 Claude 守卫提供此基线,并在原生用户轮次中检查明确的数字代理限制(使用 N 名队友/代理/工作者);历史缺失时由协调者负责执行。它不会授予工具或保证语义正确性。
当安装该守卫时,在分配前加上 HANDOFF_JSON= 以及包含 goal、limits、workspace、revision、owns、interfaces、state、evidence、next、return、trace、checks 和 baseline 的 JSON 对象。return 必须是一个对象,包含非空的 paths、contracts、checks、gaps 和 remaining 指令。trace 指定要追踪的路径和失败案例;checks 指定要运行的检查或不可用的原因。baseline 是此技能的可访问路径。这也适用于探索和审查分配。被拒绝的分配必须在重试前纠正。
在接收代理的主机上使用实际路径;当路径不同或无法访问时包含必要内容。为命令指定工作目录和所需的非秘密配置名称。永远不要在交接备注中放置凭据或私有运行时负载。仅凭分支名称不能证明子代理看到了未提交的工作;确定签出是共享的还是隔离的。
对于并发工作,在重叠更改之前商定公共契约和文件所有权。告知代理他们不是孤立的:保留其他人的编辑并通过指定的所有者协调共享文件。在声称集成之前重新基于或协调隔离的更改;不要静默丢弃工作。返回时,报告更改的路径、公共契约更改、带有结果的检查、缺口 ID/状态以及剩余操作。协调者协调追踪账本并验证跨代理接缝和受影响的消费者;多个通过的工作代理检查并不能建立有效集成的流程。
对于中断或上下文丢失,将交接保存到现有任务/追踪记录中,并附上时间戳和内容修订,然后链接该记录。恢复时,在操作前检查签出和当前差异;重新验证过时的假设。不要创建第二个任务真相来源。
本地安装并不意味着云端、远程主机或不相关代理的安装。在每个执行主机上建立发现机制;使用主机关联的全局指令将相关工作路由至此。如果发现或文件访问不可用,报告此限制而不是声称全局强制执行。
主工程师契约
- 从业务能力、不变约束、用户工作流和运营约束开始。
- 优先在领域内实现高内聚,领域之间实现低耦合。
- 将领域特定代码与属主放在一起;在该边界内按功能对代码分组。
- 每个业务规则和权威写入模型有一个清晰的所有者。
- 在添加另一个实现之前重用现有实现;避免重复的业务知识。
- 选择满足已证明需求并支持可能变更的最小架构。
- 分离观察、假设、决策和证据。不要发明需求或基准。
- 在结构变更期间保留工作的公共行为,除非请求了行为变更。
- 改进所触及的路径及其必要的依赖关系。不要将无关代码卷入任务中。
1. 在编辑前建立上下文
检查适用的仓库指令、清单、包导出、入口点、现有领域模块、迁移、测试和相关运行时证据。在创建文件之前搜索等价行为和现有共享包。使用仓库的语言和工具。
从用户或事件输入开始,追踪一个相关的工作流,经过授权、服务、领域规则、持久化、下游效果以及返回或显示的状态。包括错误路径。识别真实的消费者和写入者;仅凭目录名称不能确定所有权。
对于重要的架构工作,建立一个紧凑的决策框架:
| 问题 | 必需答案 |
|---|---|
| 业务成果 | 哪个用户工作流或不变约束发生变化? |
| 所有权 | 哪个限界上下文拥有含义和权威写入? |
| 消费者 | 哪些应用、作业、模块或外部系统需要该能力? |
| 约束 | 兼容性、数据量、延迟、多租户、可用性、成本、部署? |
| 当前证据 | 相关路径、契约、失败、时序或查询行为? |
| 最小变更 | 哪些可以重用,哪些边界实际上需要更改? |
| 完成 | 可观察的验收条件和适当的验证? |
仅在未解决的业务决策阻止正确工作时提问;否则陈述假设。
2. 定义领域边界
一个限界上下文拥有连贯的业务词汇、规则和模型。一个特性、表、屏幕、框架层、部署或团队名称不自动构成一个限界上下文。使用业务能力名称,如 billing、scheduling、playback 或 execution。
- 当相同的术语具有不同的含义、不变约束、生命周期或所有者时,分离上下文。
- 当实体的不变约束必须在单个原子操作中强制执行时,将它们保持在一起。
- 避免过大的聚合:区分真正的原子不变约束和需要显式一致性、编排或补偿而不是共享事务的跨上下文工作流。
- 区分核心业务差异化与支持和商品化能力。
- 在复杂或业务价值值得的地方投入建模工作;保持简单的 CRUD 简单。
- 在重要的上下文边界记录上游/下游所有权和转换。
- 通过另一个上下文的公共 API、端口或契约使用它;不要导入其内部。
- 在边界转换外部/提供者模型,而不是将其泄漏到业务规则中。
- 优先使用模块化单体,直到独立部署、扩展、故障隔离或所有权证明需要服务拆分。单体仓库不意味着微服务。
如果更改跨越多个领域,标识编排用例和每个领域的责任。将编排放在工作流的拥有者处,而不是全局辅助函数或 UI 组件中。
3. 先按领域,再按功能组织
首先选择所属范围,然后选择功能类别。在该范围内:
| 类别 | 职责 |
|---|---|
model/ | 实体、值对象、不变约束、策略、领域事件 |
services/ | 命名的应用程序用例和编排 |
ports/ | 持久化、时钟、身份、队列、提供者的接口 |
adapters/ | 具体的数据库、传输、提供者或平台实现 |
contracts/ | 公共 DTO、事件模式、验证、兼容性契约 |
components/、hooks/ | 领域 UI 和 UI 行为(当该领域拥有前端时) |
shared/ | 供该范围内消费者使用的可重用代码 |
tests/ 或同位置测试 | 使用仓库约定的行为和边界验证 |
服务实现属于其拥有层的 services/。当领域服务需要处理跨实体规则时,放在 model/services/ 中;编排保留在领域的主 services/ 中。提供者服务在有用时可以放在 adapters/services/ 中。
对于单个应用,根据需要按需使用 src/domains/<domain>/{model,services,ports,adapters,contracts,shared},并包含一个公共入口点、薄框架路由和组合根。将领域无关的原语放在 src/shared/ 下。仅创建包含实际代码的目录。
单体仓库示例;尊重现有包约定和显式导出:
apps/
web/ # 应用组合和表示层
api/ # 薄传输入口点
worker/ # 作业注册和组合
packages/
billing/ # 拥有的工作区包
package.json # 公共导出和运行时兼容性
src/
services/ # API/Worker 共享的用例
shared/ # Billing 局部复用
index.ts # 显式公共外观
shared/
contracts/ # 领域无关的工作区包
ui/ # 兼容的前端消费者
在工作区注册真实包;仅靠路径不能使它们可导入。在多语言工作区中,从规范模式中公开兼容的库或生成的客户端;不要尝试跨不兼容运行时导入代码。
放置规则
- 单个消费者且含义是领域特定的:保留在该领域中。
- 多个消费者在同一个领域内:使用该领域的
services/或shared/。 - 多个兼容应用需要可重用的领域代码:放入工作区领域包中;特权服务器行为仍保留在授权的 API 或客户端契约之后。
- 多个领域需要相同的领域无关原语:使用限定范围的
shared/代码。 - 消费者需要不同的业务含义:保持独立的模型并显式转换。
- 跨领域工作流:使用拥有的应用程序服务和公共领域契约。
- 路由、屏幕、控制器和作业:将规则委托给服务;保持传输关注点本地化。
永远不要为了便利导入而将能力复制到多个应用中。永远不要将一个应用作为另一个应用的库。将可重用所有权向下移动到两个应用都可以依赖的包中。保留必需的框架目录;将其路由到领域结构中,而不是与框架对抗。尊重语言标准的打包和有效的现有架构。
4. 强制依赖方向
入口点 -> 公共应用程序服务 -> 模型 + 端口
适配器 -> 端口 + 模型
引导 -> 服务 + 适配器 # 连接具体实现
领域包 -> 领域无关的共享包
- 模型不依赖于 HTTP、UI 框架、数据库、队列或提供者 SDK。
- 服务通过显式依赖编排用例;适配器实现端口。
- 共享包不导入应用或领域内部。避免循环依赖。
- 跨领域调用使用公共契约;避免同步调用循环和冗长的调用链。
- 导出有意的入口点。使用现有的包、lint 或构建工具阻止深度导入。
- 将浏览器安全的契约与仅限服务器的实现和特权依赖分开。
- 将特权 SDK、数据库客户端、密钥和文件系统代码排除在客户端依赖图之外。
- 提供者 SDK 可以在适配器中运行。