c5afa4b31e
- 替换方案规范为 design/pdd/ + design/prd/ 编号体系 - 移除 docs/roadmap.md 进度同步规则(全局未要求) - 新增 design/ 子目录职责、读写权限与兜底规则
284 lines
11 KiB
Markdown
284 lines
11 KiB
Markdown
# AGENTS.md
|
||
|
||
---
|
||
|
||
## 交互要求
|
||
|
||
- 思考过程全程必须使用中文,包括需求分析、逻辑拆解、方案选择等所有推理环节
|
||
- 最终输出内容必须全部使用中文,除代码语法本身和英文关键词以外
|
||
|
||
---
|
||
|
||
## 核心原则 (Karpathy)
|
||
|
||
### 1. 先思考再编码 (Think Before Coding)
|
||
**不要预设。不要隐藏困惑。呈现权衡。**
|
||
|
||
- 明确陈述你的假设。如果不确定,就问。
|
||
- 如果存在多种解释,全部列出——不要默默选择其一。
|
||
- 如果有更简单的方法,就说出来。在必要时提出反对。
|
||
- 如果某件事不清楚,停下来。说出困惑所在。然后提问。
|
||
|
||
### 2. 简洁优先 (Simplicity First)
|
||
**解决问题的最小代码量。不写任何推测性代码。**
|
||
|
||
- 不实现超出需求的特性。
|
||
- 不为只用一次的代码创建抽象。
|
||
- 不添加未经要求的"灵活性"或"可配置性"。
|
||
- 不为不可能发生的场景做错误处理。
|
||
- 如果你写了 200 行而它本可以用 50 行完成,重写它。
|
||
|
||
### 3. 精准变更 (Surgical Changes)
|
||
**只改动必须改的。只清理你自己造成的混乱。**
|
||
|
||
- 未明确要求时不修改已有文件
|
||
- 先确认意图再动手
|
||
- 不要"优化"相邻的代码、注释或格式。
|
||
- 不要重构没有问题的代码。
|
||
- 遵循已有风格,即使你自己的写法不同。
|
||
- 如果你注意到不相关的死代码,提出来——但不要删除它。
|
||
- 删除你的改动导致的未使用的导入/变量/函数。
|
||
|
||
### 4. 目标驱动执行 (Goal-Driven Execution)
|
||
**定义成功标准。迭代直至验证通过。**
|
||
|
||
- "添加验证" → "通过测试验证已有实现的正确性"
|
||
- "修复缺陷" → "编写测试复现问题,验证修复"
|
||
- "重构 X" → "确保重构后测试仍然通过"
|
||
|
||
对于多步骤任务,简要列出计划:
|
||
```
|
||
1. [步骤] → 验证:[检查项]
|
||
2. [步骤] → 验证:[检查项]
|
||
```
|
||
|
||
---
|
||
|
||
## 技术栈规范
|
||
|
||
### 通用规范
|
||
|
||
**包管理器**: `cargo`
|
||
|
||
**代码风格**
|
||
- 文件/文件夹命名:`kebab-case`
|
||
- 类/组件命名:`PascalCase`
|
||
- 变量/函数命名:`snake_case`
|
||
|
||
**测试要求**
|
||
- 核心业务逻辑需测试(关键算法、边界条件、错误处理)
|
||
- 简单逻辑不需要测试(枚举字面值、Getter、无分支的简单转换)
|
||
- 不主动补测试(除非用户明确要求)
|
||
|
||
**错误处理**
|
||
- 优先使用 `Result` 处理错误,避免 `unwrap()`
|
||
- 异步 API 使用 `?` 传播错误,不在 `catch` 中静默吞掉错误
|
||
- 错误按层级组织:公开 API 用全局 Error,内部实现可定义细粒度子错误
|
||
|
||
**安全规范**
|
||
- 不硬编码密钥,使用环境变量
|
||
- 用户输入必须验证
|
||
- 依赖升级策略:
|
||
- **安全补丁**:立即升级(修复已知漏洞)
|
||
- **次要版本**:评估后升级(新功能、向后兼容)
|
||
- **主要版本**:谨慎升级(可能破坏兼容性,需全面测试)
|
||
- **验证**:升级后运行完整测试套件确保无回归
|
||
|
||
**Git Commit 规范**
|
||
- 使用 Conventional Commits 格式:`<type>(<scope>): <description>`
|
||
- **描述使用中文**
|
||
- 类型:
|
||
- `feat` - 新功能
|
||
- `fix` - Bug 修复
|
||
- `enhance` - 增强现有功能(非新功能)
|
||
- `docs` - 文档更新
|
||
- `style` - 代码格式(不影响功能)
|
||
- `refactor` - 重构
|
||
- `test` - 测试相关
|
||
- `chore` - 构建/工具/配置
|
||
- 描述使用祈使句、现在时态、句尾无句号
|
||
- **Body 规则**:不列举 commit 中每一个文件的变更,body 只列出变更概要列表即可
|
||
- **Scope 推导规则**:
|
||
- 从被提交的文件路径中推导出一个最相关的 scope
|
||
- 一个 commit 只写一个主要 scope,不要罗列多个
|
||
- 如果改动涉及多个模块,选择影响范围最大的那个或使用更上层抽象名称
|
||
- 如果改动是全局的,可以省略 scope 或使用 `core`/`global`
|
||
- **示例**:
|
||
- `feat(llm): 添加流式响应支持`(修改 `src/llm/stream.rs`)
|
||
- `fix(memory): 修复向量检索边界条件`(修改 `src/memory/vector_store.rs`)
|
||
- `refactor(core): 统一错误类型定义`(修改多个模块的错误处理)
|
||
- `docs: 更新 API 文档`(全局文档更新)
|
||
- `chore(deps): 升级 tokio 到 1.40`(依赖更新)
|
||
|
||
### Commit 提交流程
|
||
|
||
在生成 commit message 后,**必须先展示给用户确认**,不可直接执行 `git commit`。
|
||
|
||
流程:
|
||
1. Agent 根据 diff 生成符合规范的 commit message
|
||
2. 展示生成的 message,等待用户明确回应
|
||
3. 用户有三种选择:
|
||
- **确认** → 执行 `git commit`
|
||
- **重新生成** → 根据用户反馈修改 message 后重新展示
|
||
- **取消** → 放弃本次 commit 操作
|
||
|
||
---
|
||
|
||
### Rust
|
||
|
||
**包管理器**: `cargo`
|
||
|
||
**代码风格**
|
||
- `cargo fmt` 格式化,`cargo clippy` 检查
|
||
- 变量/函数命名:`snake_case`
|
||
- 优先使用 `Result` 处理错误,避免 `unwrap()`
|
||
- 所有权规则:不使用 `&mut` 时不用,引用必须合法
|
||
|
||
**模块组织**
|
||
- 按功能领域组织模块(一个模块一个职责)
|
||
- **2018+ 版风格**:使用 `foo.rs` 作为模块根,子模块放在 `foo/` 目录下
|
||
- **扁平优先**:如果模块没有子模块,直接用单个 `foo.rs` 文件
|
||
- **需要子模块时才用目录**:只有当模块需要组织多个子模块时才创建 `foo/` 目录
|
||
- **避免 `mod.rs`**:不使用 `foo/mod.rs` 风格,统一使用 `foo.rs` 作为模块根
|
||
- **公共 API 重导出**:在模块根中使用 `pub use` 重新导出子模块的公共类型,提供清晰的 API 边界
|
||
|
||
**示例结构图**:
|
||
```
|
||
src/
|
||
├── lib.rs # crate 根,声明顶层模块
|
||
├── llm.rs # LLM 模块(无子模块,扁平文件)
|
||
├── memory.rs # 记忆模块根(有子模块)
|
||
├── memory/
|
||
│ ├── conversation.rs # ✓ 子模块
|
||
│ └── vector_store.rs # ✓ 子模块
|
||
├── prompt.rs # 提示词模块根(有子模块)
|
||
├── prompt/
|
||
│ ├── template.rs # ✓ 子模块
|
||
│ └── optimizer.rs # ✓ 子模块
|
||
├── tool.rs # 工具模块根(有子模块)
|
||
├── tool/
|
||
│ ├── mcp.rs # ✓ 子模块
|
||
│ └── registry.rs # ✓ 子模块
|
||
└── agent.rs # Agent 模块根(有子模块)
|
||
└── agent/
|
||
├── runtime.rs # ✓ 子模块
|
||
└── planner.rs # ✓ 子模块
|
||
|
||
# ❌ 避免的风格
|
||
src/
|
||
└── memory/
|
||
└── mod.rs # ❌ 不使用 mod.rs 风格
|
||
|
||
# ✅ memory.rs 示例:声明子模块并重导出公共 API
|
||
pub mod conversation;
|
||
pub mod vector_store;
|
||
|
||
// 重导出常用类型,提供简洁的公共 API
|
||
pub use conversation::ConversationMemory;
|
||
pub use vector_store::VectorStore;
|
||
```
|
||
|
||
**测试文件**: 内联测试(`#[cfg(test)] mod tests {}`)或 `tests/` 目录
|
||
|
||
**依赖管理**: `Cargo.toml`,语义化版本
|
||
|
||
---
|
||
|
||
## 文档规范
|
||
|
||
### 文档编号规范(design/pdd/ + design/prd/)
|
||
|
||
`design/pdd/`(方案文档)和 `design/prd/`(需求文档)使用相同的命名格式,但**各自独立编号**:
|
||
|
||
```
|
||
<序号>-<简短描述>.md
|
||
```
|
||
|
||
规则:
|
||
- 序号使用数字,从 1 开始递增。**创建前必须通过 shell 命令确认目标目录当前实际最大编号再加 1:**
|
||
```bash
|
||
# 查 design/pdd/ 的最大编号
|
||
ls design/pdd/ 2>/dev/null | grep -E '^\d+-' | sort -t- -k1 -n | tail -1 | cut -d- -f1
|
||
# 查 design/prd/ 的最大编号
|
||
ls design/prd/ 2>/dev/null | grep -E '^\d+-' | sort -t- -k1 -n | tail -1 | cut -d- -f1
|
||
# 无输出则从 1 开始
|
||
```
|
||
禁止使用上下文中缓存的编号。
|
||
- 描述:中文,简短概括主题
|
||
- 两个目录各自独立编号——`design/pdd/` 已有 `3-` 时,`design/prd/` 的新文件仍从当前最大号 +1 开始,互不影响
|
||
|
||
方案文档(`design/pdd/`)应包含:
|
||
- 背景与目标
|
||
- 需求推演概要(需求拆解、边界识别、关键假设的简要推演)
|
||
- 当前问题分析
|
||
- 架构决策记录(重大技术选型、架构变更的决策过程与理由)
|
||
- 设计方案(含架构图/流程图)
|
||
- 实施步骤
|
||
- 验证标准
|
||
- 回滚方案(如适用)
|
||
|
||
示例:
|
||
- `design/pdd/1-ui-components重构方案.md`
|
||
- `design/prd/1-用户认证需求.md`
|
||
- `design/pdd/2-数据库迁移方案.md`
|
||
|
||
---
|
||
|
||
### 设计目录(design/)
|
||
|
||
项目根下的 `design/` 目录集中管理所有设计相关的文件,供人类和 agent 共同读写。
|
||
|
||
| 子目录 | 内容 | 谁写 | 谁读 |
|
||
|--------|------|------|------|
|
||
| `design/pdd/` | 方案设计文档(PDD)→ 架构方案、设计决策、转换方案 | proposal→writer pipeline | Think 参考、Build 实现、Vet 审查 |
|
||
| `design/prd/` | 需求文档(PRD)→ 功能需求、用户故事、验收标准 | 人写 | Think 分析、Proposal 写方案时参考 |
|
||
| `design/prototype/` | **OD 导出的原型 HTML** → 视觉稿、交互原型、页面 layout | OD 桌面版导出 | Think 分析结构、Build 对照实现 |
|
||
| `design/notes/` | 笔记记录 → 零散想法、会议纪要、调研速记 | 人写 | 各 agent 参考 |
|
||
| `design/roadmap/` | 路线图 → 里程碑规划、版本计划、优先级列表 | 人写 | Proposal 排期参考 |
|
||
| `design/DESIGN.md` | 设计系统(品牌规范)→ 色板、字体、间距、语气 | OD 导出 / 人维护 | Think 提取 token、Build 同步到 `src/` |
|
||
| `design/tokens.css` | 设计 Token CSS → 从 DESIGN.md 提取的 CSS 变量 | 人同步 / agent 同步 | 所有 Svelte 组件引用 |
|
||
|
||
**访问规则:**
|
||
- 读:所有 agent 默认可读(`read_file` 不需要额外权限)
|
||
- 写:writer agent 可通过 `"design/**": allow` 写入 `design/` 下任意子目录
|
||
- 注意:`prototype/` 由 OD 桌面版导出,agent 只读不写;`DESIGN.md` 和 `tokens.css` 建议手动维护或 agent 写入时确认后再改
|
||
|
||
**兜底规则:** 文档类型不在上表时(如教程、接口文档、临时记录),或目标目录不存在时 → **向用户提问确认路径**。不允许自行推断存放位置。
|
||
|
||
---
|
||
|
||
## 项目特定规则
|
||
|
||
### 项目结构
|
||
- 源代码:`src/`(lib crate)
|
||
- 测试:内联 `#[cfg(test)] mod tests {}`
|
||
|
||
### 项目目标
|
||
agcore 是一个智能体(Agent)核心工具箱,提供:
|
||
- **LLM 调用**:完整的请求/响应周期管理
|
||
- **提示词工程**:组合、模板化、优化
|
||
- **记忆系统**:存储、检索、管理对话/向量记忆
|
||
- **工具调用**:MCP 协议集成与自定义工具注册
|
||
- **Agent 运行时**:多轮对话、任务编排
|
||
|
||
### 设计原则
|
||
- **模块化**:每个功能领域独立 module,通过 trait 定义接口
|
||
- **可插拔**:LLM 后端、记忆存储、工具注册均通过 trait 抽象
|
||
- **无运行时依赖**:core 层尽量少依赖,具体实现在 separate crates
|
||
- **异步优先**:涉及 IO 的 API 均使用 `async`
|
||
|
||
### 特殊约定
|
||
- 所有公开 API 必须有文档注释(`///`)
|
||
- 使用 `thiserror` 或 `derive_more` 定义错误类型
|
||
- 错误按层级组织:公开 API 用全局 Error,内部实现可定义细粒度子错误
|
||
- 跨 module 依赖通过 trait 而非具体类型
|
||
- 配置优先从环境变量读取,支持 builder 模式注入
|
||
|
||
---
|
||
|
||
**这些指南生效的标志:**
|
||
- diff 中不必要的改动更少
|
||
- 因过度复杂而导致的重写更少
|
||
- 澄清问题在实现之前提出
|
||
- 干净、精简的 PR
|