AGENTS.md@packages/coding-agent · git:20260815.3a6942a · 2026-08-15 · sha256 e217b13c8be31080
AGENTS.md@packages/coding-agent git:20260815.3a6942aA
Immutable. This exact content never changes and is served at /api/v1/blob/e217b13c8be31080.
# Team: Coding Agent > 本包是 Coding Agent 的产品组合层。所有修改必须同时服从仓库根 `AGENTS.md`;本文件只补充本包的架构与长期演进约束。 ## 架构定位 `@vetta/coding-agent` 定义 Coding Agent 产品:它下接 AI、Agent Core 与各 Runtime 能力域,向平台 Runtime 和应用提供产品 Feature、策略、默认配置和稳定产品 API 映射。它不是通用 Runtime Host,也 不是最终平台 Composition Root。 本包拥有: - 默认 Profile、Prompt、Mode 与产品 Feature 集合。 - Todo、Memory、Knowledge、Skill、Plugin、IM、Compaction 和上下文的产品规则与策略。 - 产品 Feature 与 Session Extension 定义,以及产品事件和稳定产品 API 的语义映射。 - Coding Agent 历史数据格式的显式读取与迁移边界。 本包不拥有: - 模型 Provider 协议与流式实现,属于 `@vetta/ai`。 - Agent Kernel、Turn Pipeline 和通用 Port,属于 `@vetta/runtime-core` / `@vetta/agent-core`。 - Session 创建、恢复、切换、Queue、Snapshot、生命周期事务和通用事件路由,属于 `@vetta/runtime-core`。 - Coding Tool 协议与纯逻辑属于 `@vetta/runtime-tools`;Node Tool 实现属于 `@vetta/runtime-node`。 - Conversation Repository 端口属于 `@vetta/runtime-storage`;Node 文件/内存实现属于 `@vetta/runtime-node`。 - MCP 协议与通用生命周期属于 `@vetta/runtime-mcp`;Node transport、文件和 OAuth 实现属于 `@vetta/runtime-node`。 - 通用知识库、Subagent 和观测实现,属于对应 `@vetta/runtime-*` 包。 - CLI、Desktop 或 IM 自身的进程入口、UI 和传输协议。 - Node/Desktop 环境实现和最终平台 Composition Root,属于现有平台 Runtime 或应用宿主。 ## 依赖方向 - Apps 只能依赖本包在 `package.json#exports` 中声明的公开入口,不得深度导入 `src/`。 - 本包可以依赖 `@vetta/runtime-*`、`@vetta/ai` 和 `@vetta/agent-core`;Kernel、协议包和 `runtime-node` 不得反向依赖本包,平台 Composition Root(例如 `runtime-desktop`)可以组合本包。 - 产品 Feature 不得选择 `@vetta/runtime-node` 默认实现;具体实现只允许在现有平台 Composition Root 中选择。迁移期间保留的 Node 接线必须登记并按纵向切片移除。 - `runtime-contracts/`、`composition/contracts/` 和其他合同文件不得依赖 Composition、Host、Adapter 或 Public API 实现。 - 产品能力域不得依赖 `composition/` 实现、`adapters/` 或 Public API facade。 - Adapter 可以依赖稳定合同,但不得反向控制 Composition,也不得复制 Runtime 域实现。 - `src/core/`、`src/compat/` 和旧执行入口属于退役架构,不得恢复。 - 历史格式兼容只能位于 `sessions/legacy/` 等明确的数据边界,不得成为活动 Agent 执行路径。 ## 关键目录 - `src/composition/`:产品定义和默认 Feature/策略集合;通用 Session 装配与生命周期应迁入 Runtime。 - `src/composition/contracts/`、`src/runtime-contracts/`:稳定产品合同与依赖倒置边界。 - `src/sessions/`:会话产品语义、投影、迁移和历史格式隔离。 - `src/features/`:Todo 等完整产品能力,按领域共同放置状态、Tool、Extension 和产品策略。 - `src/extensions/`、`src/plugins/`、`src/resources/`:扩展、Plugin、Skill 和 Prompt 的产品域。 - `src/model-context/`、`src/compaction/`、`src/memory/`:待按产品能力或策略继续收敛的现有领域。 - `src/mcp/`:Coding Agent 的 MCP 路径、OAuth 和宿主组合;通用 MCP 实现仍属于 `runtime-mcp`。 - `src/adapters/`、`src/host/`:迁移中的混合区域;只允许保留产品语义映射,通用机制和环境实现应迁出。 - `src/public-api/`:稳定公开入口;入口文件只导出,不承载业务实现。 ## 编码前必须分析 非平凡修改不得直接开始写实现。先完成以下分析,并在工作计划或实施说明中给出结论: 1. **目标与不变量**:明确要改变的行为、必须保持的旧功能、错误/取消/并发/释放语义,以及可验证的完成标准。 2. **职责所有者**:确认代码应属于 Coding Agent 产品策略、Runtime 通用能力、Host Adapter 还是具体 App;位置不对时先调整设计,不在错误层级补丁式实现。 3. **变化点**:识别真正可能变化的维度,例如 Provider、存储、策略算法、宿主环境或动态能力,而不是假设所有代码未来都会替换。 4. **候选方案**:至少比较当前直接方案与一个合理替代方案,说明依赖方向、复杂度、兼容风险和测试成本;优先选择能满足当前需求的最简单方案。 5. **抽象与模式**:说明是否需要设计模式。使用时写清它解决的变化点;不使用时保持直接、局部和可读的实现。 6. **验证策略**:在编码前确定单元、合同、差分或宿主测试分别验证什么,行为修改必须先有可运行的失败场景或明确基线。 若需求存在多个会显著改变合同或用户行为的解释,应先向用户说明,不得静默选择。若只是局部、无分支、无外部边界的简单修改,可以简化上述记录,但仍须确认职责位置和验证方式。 ## 设计原则 ### 面向长期迭代 - 围绕稳定职责组织模块,不围绕一次需求、页面或临时调用者组织代码。 - 稳定合同与易变实现分离;业务语义通过领域类型表达,不使用通用 `Record`、字符串约定或共享 metadata 隐藏依赖。 - 组合优于继承。具体实现只在 Composition Root 选择,领域代码依赖窄 Port。 - 动态 Tool、MCP、Skill、Plugin、Prompt 与模型策略在 Turn admission 绑定同一个不可变 generation;普通外部更新只对后续 Turn 可见,不得在同一 Turn 的模型调用、工具执行或 Hook dispatch 中读取新的 current revision。 - Model Call 仍可观察本 Turn 自己产生的消息、工具结果、Todo、usage 与 deferred activation;不要把该 Turn-local state 误当成外部 generation,也不要把 snapshot 固定到整个 Session。 - ConversationDocument 和持久化事件是 canonical 事实;上下文裁剪、图片预算和 microcompact 应优先实现为模型调用视图的纯投影。 - 公共合同按兼容方式演进;需要破坏性变化时,使用显式版本和迁移器,不以双执行路径或永久 Adapter 掩盖迁移。 - 一次架构修改只解决一个清晰问题。不要顺带重写无关模块或改变用户可观察功能。 ### 可维护性与易读性 - 一个文件只承担一个可描述的职责;入口文件保持薄,只做注册、导出和装配。 - 当文件要求读者同时理解多个独立状态、协议或副作用时,按职责拆分,而不是仅按代码行数机械拆分。 - 使用能表达领域含义的文件和类型名称,避免新的 `Manager`、`Service`、`Helper`、`Utils` 或 `Common` 大杂烩。 - 控制函数和构造参数规模。配置项属于哪个对象就由哪个对象拥有,不把所有依赖汇总成不断增长的 Options 对象。 - 副作用集中在 Adapter/Host 边界;选择、校验、状态转换和投影逻辑尽量保持纯函数并独立测试。 - 错误使用稳定类型或判别联合表达;不要依赖解析自然语言错误文本决定控制流。 - 不通过注释解释混乱结构。先改善命名、职责和控制流,只为非显然约束保留简短注释。 ## 设计模式使用准则 设计模式是解决已识别结构问题的工具,不是代码质量指标。只有当模式能减少耦合、明确所有权或稳定真实变化点时才使用。 适合本架构的常见模式: - **Strategy**:Compaction、上下文裁剪、重试、Tool Result 投影等存在可替换产品策略时使用。 - **Ports and Adapters / Adapter**:隔离文件系统、进程、网络、模型、存储、MCP SDK、Legacy 格式和宿主 API。 - **Composition Root / Factory**:集中选择具体实现、组装依赖和定义资源所有权;Factory 不得隐藏全局状态。 - **State Machine**:Session、Turn、取消、切换、关闭和资源生命周期存在合法状态迁移时使用。 - **Typed Pipeline**:固定的 Turn 阶段需要有序编排时使用;不要开放可任意修改共享上下文的万能 Middleware。 - **Repository**:会话持久化需要原子追加、版本、分支和恢复等领域语义时使用,不退化为通用键值存储。 - **Registry/Catalog**:动态能力需要注册、撤销、revision 和在途执行仲裁时使用;读取面与修改面应分离。 - **Decorator**:在不改变 Tool/Port 核心实现的前提下增加 Hook、观测、权限或结果策略时使用。 - **Observer**:观察已发生事件且失败不得影响主流程时使用;Observer 不得修改 Turn 结果。 - **Anti-Corruption Layer**:适配旧格式或第三方协议时使用,转换结果必须进入当前稳定领域合同。 以下情况通常不要引入模式或接口: - 只有一个实现、没有外部边界且测试不需要替换的局部逻辑。 - 简单计算、规范化、排序或状态转换可以由命名清晰的纯函数完成。 - 只是为了减少几行重复,或为了“以后可能需要”而增加 Factory、Builder、事件总线或插件系统。 - 用抽象隐藏尚未理解的业务差异,或让调用者依赖大量可选参数和运行时约定。 新增抽象后必须能够回答:它稳定了哪个合同、隔离了哪个变化点、删除它会造成什么真实耦合。无法回答时,使用更直接的实现。 ## 执行与动态能力约束 - Turn 使用固定阶段的 Typed Pipeline;Tool Loop 是 Execution 阶段内的循环,不得伪装成一次性线性 Stage。 - 不引入公开的 `next()` Middleware 让任意 Feature 修改 messages、tools、instructions 或终止结果。 - 新上下文来源使用 Context Provider;模型调用级动态能力使用 Contribution Provider;上下文预算使用 Context Strategy;权限使用 Tool Policy;非关键后处理使用 Observer。 - Feature 不得持有可变 Session 内部对象,不得通过共享对象互相通信,不得静默覆盖同名 Tool 或资源。 - 注册、移除或替换动态能力默认从下一 Turn 可见;普通 retirement 允许持有旧 generation lease 的在途调用完成,只有携带 reason 与审计信息的 hard revoke 可以在安全检查点立即拒绝或取消。 - 失败、取消和关闭必须沿 `AbortSignal` 与生命周期合同传播;资源创建与释放必须成对并可在部分初始化失败时回滚。 ## 功能兼容与数据边界 - 当前工作是架构演进,不是功能重写。Tool Schema、描述、结果、错误、副作用、路径语义和事件顺序必须保持,除非用户明确批准行为变化。 - 不得通过删除功能、降低校验、吞掉错误或回退旧执行路径修复架构问题。 - 旧实现只能作为行为 Oracle 或显式数据迁移输入,不能被新生产代码调用。 - 来自模型、磁盘、网络、MCP、Plugin、Extension 或 RPC 的数据必须在首次进入领域边界时运行时校验。 - Tool 参数和需要发送给 Provider 的 JSON Schema 使用 TypeBox;复杂外部配置在确有 preprocess/transform 需求或既有约定时使用 Zod;已经校验的内部对象只使用 TypeScript 合同,不重复维护两套 Schema。 - Schema 只验证结构,Session 身份、事件顺序、版本和权限等领域不变量由明确代码验证。 ## 测试要求 - 行为修改必须随代码提供测试;架构重构必须通过现有行为测试或差分测试证明功能未变。 - 纯策略、选择、校验和状态转换优先使用表驱动单元测试。 - Port、协议、Schema、公开 API、持久化事件和 Tool 输入输出使用合同测试。 - Session、Composition 和生命周期修改至少覆盖成功、失败、中止、部分初始化回滚和最终释放。 - 动态能力修改至少覆盖新增、删除、替换、未变化、在途执行和下一模型调用可见性。 - 跨 CLI、Desktop、IM 的真实环境行为使用现有 Agent Host 验证入口,不新增临时执行路径或硬编码超时绕过问题。 - 测试断言可观察合同,不锁定私有类、文件布局、偶然调用顺序或实现细节。 从仓库根目录执行: ```bash bun run check:quick bun scripts/quality/run-vitest.mjs --run <相关测试文件> bun run check ``` `bun run check` 不运行测试;定向测试和完整质量门禁都必须单独执行。文档或注释修改无需为了形式新增测试,但必须运行适当的格式和链接检查。 ## 完成前审查 提交结果前逐项确认: - 代码是否位于正确所有者,依赖方向是否单向。 - 是否存在更简单且同样满足需求的实现。 - 使用的抽象或设计模式是否对应真实变化点,而非形式化包装。 - 是否引入重复事实源、隐藏全局状态、万能 Options 或新的大文件职责混合。 - 是否保持原有功能、动态能力语义和数据兼容性。 - 测试是否覆盖本次决策和失败路径,而不只是覆盖代码行。 - `bun run check:quick`、相关测试和代码变更后的 `bun run check` 是否全部通过。 固定重写目标见 [`REWRITE-CHARTER.md`](../../docs/agent/coding-agent/05-greenfield-rewrite/08-implementation-log/REWRITE-CHARTER.md),三层所有权以 ADR-0077 为准。架构守卫以 `scripts/quality/check-coding-agent-architecture.mjs` 和包边界守卫为准。