diff --git a/README.md b/README.md index 3c1a444..075745e 100644 --- a/README.md +++ b/README.md @@ -91,6 +91,11 @@ SkillSpace/ ├── versions/ ├── publish/ └── docs/ + +archives/ # 外部技能归档(从其他地方开发的技能压缩包基础版) +├── / # 解压后的技能目录 +├── .skill # 原始压缩包(.skill / .zip / .tar.gz) +└── README.md # 归档说明和导入流程 ``` --- diff --git a/archives/README.md b/archives/README.md new file mode 100644 index 0000000..cc73c2f --- /dev/null +++ b/archives/README.md @@ -0,0 +1,54 @@ +# SkillSpace Archives — 外部技能归档 + +本目录用于存放从其他地方开发的技能压缩包基础版,作为参考和导入来源。 + +## 目录结构 + +``` +archives/ +├── README.md # 本说明文档 +├── / # 解压后的技能目录(便于查看和引用) +│ ├── SKILL.md +│ ├── references/ +│ └── ... +├── .skill # 原始压缩包(.skill / .zip / .tar.gz) +└── ... +``` + +## 命名规范 + +- 解压目录与压缩包使用相同的 `` 前缀 +- 如有多个版本,追加版本号:`-v1.0.0.skill` + +## 不可变规则(强制) + +> **`archives/` 是最原始的数据来源,技能后续的版本迭代和优化严禁修改此目录下的任何技能文件。** + +| 允许修改 | 禁止修改 | +|---------|---------| +| `/README.md`(归档说明日志) | `SKILL.md`、`prompt.md`、`_meta.json` 等技能核心文件 | +| `/CHANGELOG.md`(归档日志) | `references/`、`scripts/`、`templates/` 等所有子目录和文件 | +| 本文件 `archives/README.md` | 原始压缩包(`.skill`、`.zip`、`.tar.gz`) | +| | `skill.json`、`tools/`、`tests/` 等所有文件 | + +**原因**:archives/ 是技能的**原始快照**,用于: +- 与迭代后的版本进行 diff 对比 +- 在导入版本出问题时回溯到原始状态 +- 作为不可变的审计基线 + +如需修改技能内容,必须在对应框架目录(`/skills//`)中操作,而非 archives/。 + +--- + +## 用途 + +- **参考学习**:查看其他团队或社区的优秀技能实现 +- **导入复用**:将外部技能适配后纳入 SkillSpace 生命周期管理 +- **基础版本归档**:保留技能的初始版本快照,便于对比迭代 + +## 导入到 SkillSpace 流程 + +1. 从 `archives/` 中选取技能 +2. 复制到对应框架目录:`/skills//` +3. 按需适配格式(参考 `skill-publisher` 的格式适配规则) +4. 进入生命周期管理(测试 → 审计 → 发布) diff --git a/archives/dev-pipeline-universal-v1.0.0.tar.gz b/archives/dev-pipeline-universal-v1.0.0.tar.gz new file mode 100644 index 0000000..fbf65ae Binary files /dev/null and b/archives/dev-pipeline-universal-v1.0.0.tar.gz differ diff --git a/archives/dev-pipeline-universal/README.md b/archives/dev-pipeline-universal/README.md new file mode 100644 index 0000000..bbef7b6 --- /dev/null +++ b/archives/dev-pipeline-universal/README.md @@ -0,0 +1,60 @@ +# 🔧 通用研发流水线技能包 + +> 版本: v1.0.0 | 适用: Hermes Agent / OpenClaw / AgentSkills 兼容平台 + +## 简介 + +一套完整的研发流水线技能包,覆盖从需求分析到功能上线的全流程。包含: + +- **7 个阶段**:需求分析 → 技术方案 → UI设计(可选) → 编码实现(结对) → 代码审查 → 测试验证 → 部署上线 +- **4 道质量门禁**:确保每个阶段产出质量 +- **7 个角色**:总管、架构师、设计师、主程序员、结对程序员、审查员、测试员 +- **测试分层策略**:单元测试 + 集成测试 + 冒烟测试 +- **实战陷阱文档**:FastAPI、前端构建、Excel导入等 + +## 安装 + +### OpenClaw + +```bash +# 复制到 OpenClaw 技能目录 +cp -r dev-pipeline-universal ~/.openclaw/skills/dev-pipeline + +# 或复制到工作区技能目录(更高优先级) +cp -r dev-pipeline-universal /skills/dev-pipeline +``` + +### Hermes Agent + +```bash +# 复制到 Hermes 技能目录 +cp -r dev-pipeline-universal ~/.hermes/skills/software-development/dev-pipeline +``` + +## 使用前配置 + +1. 复制 `references/roles.example.yaml` 为 `references/roles.yaml` +2. 修改模型名称为您实际可用的模型 +3. 根据您的技术栈调整测试框架配置 + +## 目录结构 + +``` +dev-pipeline-universal/ +├── SKILL.md # 主技能文档 +├── templates/ +│ └── stage-artifacts.md # 7阶段产物YAML模板 +├── references/ +│ ├── roles.example.yaml # 角色模型配置示例 +│ ├── quality-gates.md # 质量门禁详情 +│ ├── testing-strategy.md # 测试分层策略 +│ ├── fastapi-pitfalls.md # FastAPI 实战陷阱 +│ ├── frontend-build-optimization.md # 前端构建优化 +│ ├── operation-log-pattern.md # 操作日志系统模板 +│ ├── framework-comparison.md # AI框架调研对比 +│ ├── excel-data-import.md # Excel批量导入 +│ ├── revenue-allocation-pattern.md # 收益归属矩阵 +│ └── doc-sync-pattern.md # 文档同步模板 +└── scripts/ + └── show_roles.py # 角色对照表生成脚本 +``` diff --git a/archives/dev-pipeline-universal/SKILL.md b/archives/dev-pipeline-universal/SKILL.md new file mode 100644 index 0000000..807a33f --- /dev/null +++ b/archives/dev-pipeline-universal/SKILL.md @@ -0,0 +1,378 @@ +--- +name: dev-pipeline +description: 通用研发流水线 — 从需求分析到功能上线的全流程 Agent 协作方案。定义角色、阶段、质量门禁、测试分层和流转规则。 +version: 1.0.0 +date: 2026-06-30 +author: 马总管 🐎 +metadata: + openclaw: + emoji: "🔧" + tags: [研发流程, subagent, 多模型协作, 流水线, devops, 质量门禁, 测试分层] + requires: + bins: [] + hermes: + tags: [研发流程, subagent, 多模型协作, 流水线, devops, 质量门禁, 测试分层] +--- + +# 通用研发流水线(Dev Pipeline) + +> **版本**: v1.0.0(通用版) +> **创建日期**: 2026-06-30 +> **维护者**: 马总管 🐎 +> **适用平台**: Hermes Agent / OpenClaw / 其他 AgentSkills 兼容平台 + +## 一、概述 + +组建一个完整的研发小单元,覆盖从需求分析到功能上线的全流程。由总管负责调度,通过 delegate_task / subagent 机制将各阶段任务分派给不同角色的子 Agent,每个角色使用最适合的模型。 + +### 流程总览 + +``` +用户(提需求) + │ + ▼ +┌──────────────────────────────────────────────┐ +│ ① 需求分析 — 总管 │ +│ 理解业务意图,输出结构化需求文档,跟用户确认 │ +└──────────┬───────────────────────────────────┘ + ▼ [QG1: 需求门禁] +┌──────────────────────────────────────────────┐ +│ ② 技术方案 — 架构师 │ +│ 读代码库 + 需求文档,输出设计方案 │ +│ 总管 review 方案,必要时跟用户确认 │ +└──────────┬───────────────────────────────────┘ + ▼ [QG2: 设计门禁] +┌──────────────────────────────────────────────┐ +│ ③ UI设计 — 设计师 (可选) │ +│ 输出设计规范(配色/字体/间距/组件样式代码) │ +│ 仅面向用户的项目需要,纯后端/API可跳过 │ +└──────────┬───────────────────────────────────┘ + ▼ +┌──────────────────────────────────────────────┐ +│ ④ 编码实现(结对编程模式,可选) │ +│ ④a 主程序员写代码 │ +│ ④b 结对程序员 review+改进 │ +│ 大型/中型启用结对,小型/热修复单程序员 │ +└──────────┬───────────────────────────────────┘ + ▼ [QG3: 编码门禁] +┌──────────────────────────────────────────────┐ +│ ⑤ 代码审查 — 审查员 │ +│ Review 代码变更,输出结构化审查报告 │ +│ ├─ REQUEST_CHANGES → 回到④让程序员修改 │ +│ └─ APPROVED → 进入下一阶段 │ +└──────────┬───────────────────────────────────┘ + ▼ +┌──────────────────────────────────────────────┐ +│ ⑥ 测试验证 — 测试员 │ +│ 分层编写测试(单元+集成+冒烟)并执行 │ +│ ├─ PARTIAL_FAIL → 回到④让程序员修复 │ +│ └─ ALL_PASS → 进入下一阶段 │ +└──────────┬───────────────────────────────────┘ + ▼ [QG4: 测试门禁] +┌──────────────────────────────────────────────┐ +│ ⑦ 部署上线 — 总管 │ +│ 构建、部署、验证,汇报结果给用户 │ +└──────────────────────────────────────────────┘ +``` + +### 角色定义 + +| 角色 | 代号 | 流程阶段 | 推荐模型类型 | +|------|------|---------|-------------| +| 🧑‍💼 总管 | PM | ①需求分析 ⑦部署上线 | 快速响应模型(日常对话) | +| 🏗️ 架构师 | ARCH | ②技术方案 | 强推理模型(复杂推理) | +| 🎨 设计师 | UI | ③UI设计 | 编码版模型(设计+编码) | +| 💻 主程序员 | DEV | ④编码实现 | 深度推理编码模型 | +| 👥 结对程序员 | DEV2 | ④编码实现(review) | 与主程序员不同家族模型 | +| 🔍 审查员 | REVIEW | ⑤代码审查 | 深度推理模型 | +| 🧪 测试员 | QA | ⑥测试验证 | Agent/Tool 能力强的模型 | + +**模型选择原则**: +- 编码/审查/测试使用**不同模型家族**,消除单模型偏见 +- 主程序员和结对程序员用不同厂商模型,交叉审视 +- 测试员与编码员信息隔离(测试员不看实现思路) + +### 流程裁剪规则 + +并非所有需求都必须走完全部阶段。由总管根据需求规模判断裁剪: + +| 需求规模 | 定义 | 走哪些阶段 | 结对编程 | 示例 | +|---------|------|-----------|---------|------| +| 🔴 大型 | 新功能/新模块/架构变更 | ①②③④⑤⑥⑦ 全流程 | ✅ 启用 | 新增模块、系统重构 | +| 🟡 中型 | 现有功能扩展/较复杂 Bug | ①④⑤⑥ 跳过②③设计 | ✅ 启用 | 加导出功能、修复复杂 Bug | +| 🟡 中型(含UI) | 现有功能扩展+UI改版 | ①③④⑤⑥ 跳过②方案设计 | ✅ 启用 | 界面改版、新增交互页面 | +| 🟢 小型 | 简单修改/配置变更 | ①④⑥ 最小流程 | ❌ 单程序员 | 改字段校验、加配置项 | +| ⚪ 微型 | 一行代码/纯配置 | 总管直接做,不 delegate | — | 改文案、调参数 | +| 🔥 热修复 | 线上紧急 Bug | ④⑥⑦ 跳过需求和审查 | ❌ 单程序员 | 线上崩溃、数据错误 | + +**裁剪原则**: +- ①需求分析(总管)永远不跳过——再小的需求也要先确认理解对了(热修复除外) +- ⑤代码审查在中型以上需求中必须执行 +- ⑥测试验证在有代码变更时必须执行(至少验证不破坏现有功能) +- 总管负责判断需求规模,有争议时向用户确认 + +### 项目目录规范(建议) + +- 所有研发项目统一放在 `~/projects-dev/` 下(可自定义) +- 每个项目一个子目录,git 初始化管理 +- 便于代码审查阶段做 diff 和回滚 + +## 二、质量门禁 + +> 详细规范见 `references/quality-gates.md` + +### 门禁总览 + +| 门禁 | 位置 | 关键检查 | 通过条件 | +|------|------|---------|---------| +| QG1 | 需求→设计 | 产物完整性、验收标准可测试、用户确认 | 全部通过 | +| QG2 | 设计→编码 | 文件变更清单、API与需求对齐 | 无阻断问题 | +| QG3 | 编码→审查 | 编译通过、lint通过、变更与设计一致 | 自检全通过 | +| QG4 | 测试→部署 | 测试全通过、覆盖率达标、无回归、用户确认 | 全部通过 | + +### 重试与超时机制 + +**重试策略:** +``` +第1次失败 → 同模型重试,附带失败原因 +第2次失败 → 换备用模型重试 +第3次失败 → 上报用户,进入人工介入 +``` + +**超时保护:** + +| 阶段 | 超时时间 | 超时处理 | +|------|---------|---------| +| ②设计 | 30分钟 | 终止,记录已有产出,人工介入 | +| ③编码 | 50分钟 | 终止,保留已写代码,人工介入 | +| ④审查 | 25分钟 | 终止,标记"审查超时",直接进测试 | +| ⑤测试 | 40分钟 | 终止,保留已有测试结果,人工介入 | + +## 三、阶段产物规范 + +> 完整模板见 `templates/stage-artifacts.md` + +每个阶段的子 Agent **必须**输出结构化 YAML 产物。总管负责校验产物格式。 + +### 产物设计原则 + +1. **结构化优先**:用 YAML Schema 约束,减少解析歧义 +2. **摘要辅助**:每个产物附带自然语言摘要,帮助 LLM 快速定位 +3. **决策可追溯**:记录关键决策的理由和替代方案 +4. **问题前传**:显式列出 open_issues,确保下游关注 +5. **信息隔离**:审查员不看编码 prompt,测试员不看实现思路 + +### 产物传递规则 + +``` +① 需求产物 ──→ ②架构师(完整) + ④程序员(验收标准) +② 设计产物 ──→ ③设计师(页面/组件清单) + ④程序员(完整)+ ⑤审查员(摘要+文件清单) +③ UI设计产物 ──→ ④程序员(完整设计规范+组件样式) +④ 编码产物 ──→ ⑤审查员(git diff + 产物) + ⑥测试员(签名+验收标准) +⑤ 审查产物 ──→ ④程序员(如需修改:issues列表) +⑥ 测试产物 ──→ ④程序员(如有失败:failed_tests)/ ⑦总管(如全通过) +``` + +**关键**:测试员只接收接口签名和验收标准,不接收编码思路和实现 prompt。 + +## 四、测试分层策略 + +> 详细规范见 `references/testing-strategy.md` + +### 测试金字塔 + +``` + ╱╲ + ╱ 冒烟 ╲ ← 5-10% + ╱────────╲ + ╱ 集成测试 ╲ ← 20-30% + ╱──────────────╲ + ╱ 单元测试 ╲ ← 60-70% + ╱──────────────────╲ +``` + +### 覆盖率阈值 + +| 项目规模 | 行覆盖 | 分支覆盖 | 函数覆盖 | +|---------|--------|---------|---------| +| 大型(新项目) | ≥ 70% | ≥ 60% | ≥ 80% | +| 中型(新功能) | ≥ 60% | ≥ 50% | ≥ 75% | +| 小型(bug修复) | 修改行100% | — | — | + +## 五、各阶段执行规范 + +### ① 需求分析(总管直接执行) + +**输入**: 用户的口头/文字需求 +**输出**: 结构化需求产物(见 `templates/stage-artifacts.md` ①) + +**规则**: 必须跟用户确认需求文档后才进入下一阶段。 + +### ② 技术方案(delegate → 架构师) + +**输入**: 需求产物(完整) + 现有代码库上下文 +**输出**: 结构化设计产物(见 `templates/stage-artifacts.md` ②) + +**规则**: 总管 review 方案,重大决策需跟用户确认。 + +### ③ UI设计(delegate → 设计师)— 可选 + +**适用条件**: 面向用户的项目(H5、小程序、Web应用)。纯后端/API/CLI项目跳过此阶段。 + +**输入**: 需求产物 + 技术方案中的页面/组件清单 + 用户指定的风格偏好 +**输出**: 结构化UI设计产物(见 `templates/stage-artifacts.md` ③) + +**设计产物包含**: +1. 设计规范(Design Token):配色、字体、间距、圆角、阴影 +2. 组件样式清单:每个组件的具体 CSS/Tailwind 类名 +3. 页面布局描述:各页面的结构和组件组合方式 +4. 交互说明:关键交互的状态变化 + +**规则**: +- 设计师不需要画图,输出可直接使用的代码级设计规范 +- 风格偏好由用户指定(如微信风格、Material Design 等) +- 设计规范以 Tailwind CSS 类名为主要表达方式 + +### ④ 编码实现(结对编程模式,可选) + +**模式**: 主程序员写代码 → 结对程序员 review+改进 → 产出最终代码 + +**④a 主程序员(delegate)** + +**输入**: 技术方案产物(完整) + UI设计产物(如有) + 需求产物中的验收标准 +**输出**: 实现代码 + 结构化编码产物(见 `templates/stage-artifacts.md` ④) + +**④b 结对程序员(delegate)— 大型/中型项目启用** + +**输入**: 主程序员产出的代码(git diff) + 技术方案摘要 + 验收标准 +**输出**: review 意见 + 改进后的代码 + +**结对编程规则**: +- 大型/中型项目:必须启用结对,主程序员写完 → 结对程序员 review+改进 +- 小型/热修复:单主程序员即可,跳过④b +- 结对程序员的改动也会进入⑤代码审查,形成三道审视(结对→审查→测试) +- 结对程序员不重写代码,只做 review 和针对性改进 + +**规则**: +- 一次只实现一个功能点,避免大规模变更 +- 单次 delegate 涉及文件 ≤ 10 个,超过则拆分 +- 严禁在前台运行常驻进程(如 `npm run dev`),必须后台运行 +- 完成后必须运行 `git add -A && git commit` + +### ⑤ 代码审查(delegate → 审查员) + +**输入**: 代码变更(git diff) + 需求摘要 + 技术方案摘要(**不含编码 prompt**) +**输出**: 结构化审查产物(见 `templates/stage-artifacts.md` ⑤) + +**审查维度(七维度)**: + +| 维度 | 严重级别 | 检查重点 | +|------|---------|---------| +| 安全性 | 🔴 阻断 | SQL注入、XSS、硬编码密钥、路径遍历 | +| 正确性 | 🔴 阻断 | 逻辑错误、边界条件、空值处理、资源泄露 | +| 数据契约 | 🔴 阻断 | 前端 TS 接口与 API 实际返回字段一致性 | +| 性能 | 🟡 警告 | 算法复杂度、N+1查询、内存泄漏 | +| 可维护性 | 🟡 警告 | 函数长度、命名规范、DRY原则 | +| 规范 | 🟢 建议 | 代码风格、项目约定 | +| 测试 | 🟡 警告 | 测试覆盖、Mock合理性 | + +**规则**: 审查不通过 → 问题反馈给程序员修改 → 修改后重新审查。最多 3 轮。 + +### ⑥ 测试验证(delegate → 测试员) + +**输入**: 接口签名 + 验收标准(**不含实现思路和编码 prompt**) +**输出**: 测试代码 + 结构化测试产物(见 `templates/stage-artifacts.md` ⑥) + +**规则**: 测试不通过 → 失败信息反馈给程序员修复 → 修复后重新测试。最多 3 轮。 + +### ⑦ 部署上线(总管直接执行) + +**输入**: 通过审查和测试的代码 +**输出**: 结构化部署产物(见 `templates/stage-artifacts.md` ⑦) + +**规则**: 部署前跟用户确认。部署后验证核心功能。 + +## 六、设计理念与参考文献 + +### 核心设计理念 + +| 理念 | 来源 | 落地方式 | +|------|------|---------| +| SOP驱动+结构化输出 | MetaGPT (arXiv:2308.00352) | 7阶段YAML产物模板 | +| 测试与编码分离 | AgentCoder (arXiv:2312.13010) | 不同模型+信息隔离 | +| 多模型交叉审查 | 业界最佳实践 | 编码/审查/测试各用不同模型家族 | +| Task级重试 | CrewAI | 每阶段 max 3 次+备用模型降级 | +| 事件流快照 | OpenHands | git checkpoint 用于崩溃恢复 | +| ACI精简工具 | SWE-agent | 子 agent 按需分配最小工具集 | + +### 参考文献 + +1. MetaGPT — SOP驱动多角色协作,结构化中间产物减少30%信息损失 +2. AgentCoder — 独立测试Agent比自测通过率高12-18% +3. ChatDev — 角色扮演对话提升20%完成率 +4. SWE-bench — 60%修复失败源于定位错误,强调代码搜索能力 +5. Agentless — 简单流水线有时比复杂Agent更有效 + +> 完整框架对比调研见 `references/framework-comparison.md` + +## 七、实战陷阱与最佳实践 + +### 子 Agent 超时恢复模式 + +子 Agent 可能在执行过程中超时,但代码文件可能已经写入。超时后总管应执行以下恢复步骤: + +1. **检查文件系统** — 查看已生成的文件 +2. **检查 git 状态** — 确认子 Agent 是否已自动 commit +3. **验证后端** — 启动服务并测试 API 端点 +4. **验证前端** — 确认构建通过 +5. **修复关键问题** — 子 Agent 超时前可能来不及处理边界情况 +6. **提交修复** — 完成收尾 + +超时不代表失败——子 Agent 可能完成了 80% 的工作,总管收尾比重新 delegate 更高效。 + +### 前后端数据契约不一致(高频致命问题) + +程序员 Agent 同时写 API 和前端时,TypeScript 接口定义经常与 API 实际返回字段对不上,导致客户端 JS 崩溃。 + +**防范措施**: +1. 编码完成后,总管用 curl API 抓取实际响应 +2. 对比前端 TypeScript 接口定义与 API 实际字段 +3. 重点检查:字段名差异、字段是否存在、类型是否匹配 +4. 对可能为 undefined 的字段,检查是否有安全访问(`?.`、`|| 默认值`) + +### 常驻进程防护规则 + +子 Agent 禁止前台运行 `npm run dev` / `next start` / `python -m http.server` 等常驻命令,必须后台运行或设超时。违反此规则会导致整个 delegation 链路卡死。 + +### 代码修改必须提交后再通知构建 + +修改代码后,必须先 `git status` 确认已 staging、`git log --oneline -1` 确认已提交,再通知用户触发 CI/CD。本地工作区的修改不会自动进入远程仓库。 + +## 八、附带参考文档 + +本技能包附带以下参考文档,按通用性分类: + +### 通用技术参考(适用于任何项目) + +| 文档 | 内容 | +|------|------| +| `references/fastapi-pitfalls.md` | FastAPI 实战陷阱(路由顺序、N+1、NULL处理等) | +| `references/frontend-build-optimization.md` | Vite 代码分割 + 路由懒加载优化 | +| `references/operation-log-pattern.md` | 操作日志系统四层架构模板 | +| `references/testing-strategy.md` | 测试分层策略详情 | +| `references/quality-gates.md` | 质量门禁详情 | +| `references/framework-comparison.md` | AI 编码框架调研对比 | + +### 业务模式参考(按需选用) + +| 文档 | 适用场景 | +|------|---------| +| `references/excel-data-import.md` | 从 Excel 批量导入业务数据 | +| `references/revenue-allocation-pattern.md` | 人×项目收益归属矩阵 | +| `references/doc-sync-pattern.md` | 里程碑文档同步到仓库 | + +## Changelog + +| 版本 | 日期 | 变更内容 | +|------|------|---------| +| v1.0.0 | 2026-06-30 | 通用版首发。剥离环境特定信息(API key、服务器IP、具体项目名),保留通用流水线逻辑。适配 OpenClaw/Hermes 等多平台。 | diff --git a/archives/dev-pipeline-universal/references/doc-sync-pattern.md b/archives/dev-pipeline-universal/references/doc-sync-pattern.md new file mode 100644 index 0000000..cf53f4b --- /dev/null +++ b/archives/dev-pipeline-universal/references/doc-sync-pattern.md @@ -0,0 +1,59 @@ +# 里程碑文档同步模式(通用模板) + +**创建日期**: 2026-06-30 +**适用场景**: MVP/里程碑完成后,需要同步代码和文档到远程仓库 + +--- + +## 触发条件 + +- 重大功能完成(如 MVP v1.0) +- 里程碑文档创建完成 +- 需要备份/共享项目文档 + +## 同步流程 + +### 步骤 1: 代码和里程碑文档 → 远程仓库 + +```bash +# 进入项目目录 +cd <项目目录> + +# 查看未跟踪文件 +git status + +# 添加里程碑文档和关键代码 +git add milestone/ <其他关键文件> + +# 提交 +git commit -m "feat: <版本> <功能描述> + +- <成果1> +- <成果2>" + +# 推送到远程仓库 +git push origin <分支> +``` + +### 步骤 2: 核心文档 → 文档库(可选) + +如有独立的文档仓库,同步核心 .md 文档: + +```bash +# 进入文档库 +cd <文档库目录> + +# 复制核心文档 +cp -r <项目目录>/milestone/ <文档库目录>/<项目名>/ + +# 提交 +git add <项目名>/ +git commit -m "feat: 添加 <项目名> <版本> 里程碑文档" +git push origin main +``` + +## 注意事项 + +1. **先主仓库后文档库** — 确保代码和文档先在版本控制中 +2. **选择性同步** — 文档库只同步核心 .md 文档,不同步二进制/大文件 +3. **milestone 命名** — 格式 `YYYY-MM-DD-v<版本>-<标签>` diff --git a/archives/dev-pipeline-universal/references/excel-data-import.md b/archives/dev-pipeline-universal/references/excel-data-import.md new file mode 100644 index 0000000..f3e3720 --- /dev/null +++ b/archives/dev-pipeline-universal/references/excel-data-import.md @@ -0,0 +1,177 @@ +# Excel 数据导入实战参考 + +> **适用场景**: MVP/里程碑完成后,从业务 Excel 报表批量导入测试数据做效果验证 +> **创建日期**: 2026-06-24 +> **更新日期**: 2026-06-30 + +--- + +## 两种导入方式 + +### 方式一:CLI 脚本(适合首次全量导入) + +`scripts/import_excel_data.py` — 从文件系统读取 Excel,一次性导入全部数据。 + +**优点**: 无网络开销,可调试,适合大数据量 +**缺点**: 需要服务器文件系统访问权限 + +### 方式二:Web API(适合日常增量导入) + +`POST /api/import/excel` — 前端上传 Excel 文件,后端解析导入。 + +**优点**: 浏览器操作,无需服务器登录,有导入结果统计 +**缺点**: 文件大小受 HTTP 限制,大文件上传慢 + +**前端页面**: `/import` 路径,拖拽上传 + 导入结果展示 + +**API 端点**: +```python +@router.post("/api/import/excel") +async def import_excel(file: UploadFile = File(...), db: Session = Depends(get_db)): + # 保存临时文件 → openpyxl 解析 → 导入各表 → 删除临时文件 +``` + +--- + +## 核心挑战 + +业务 Excel 通常有 15-20 个 sheet,列布局因项目而异,且存在公式、合并单元格、同名项目等陷阱。一次性全量导入比逐条录入高效百倍,但需要处理以下问题。 + +--- + +## 实战陷阱与对策 + +### 1. 列布局因 sheet 而异 + +每个项目明细 sheet 的列数不同: + +| Sheet | 列布局 | 人日列 | 描述列 | +|-------|--------|:------:|:------:| +| 标准 | 序号\|模块\|功能项\|人日\|负责人\|占比\|... | col 3 | — | +| 工健健康小屋 | 序号\|模块\|功能项\|说明1\|详细说明\|人日\|负责人\|... | col 5 | col 4 | +| 基层社区AI医助 | 序号\|模块\|功能项\|描述\|人日\|负责人\|... | col 4 | col 3 | +| 汤原县AI医助 | 序号\|功能项\|描述\|人日\|负责人\|... | col 3 | col 2(无模块列) | + +**对策**: 为每个 sheet 定义独立的列映射配置,而非通用解析逻辑。 + +```python +sheet_configs = [ + ("项目-百度-珠江医院", "2026-BD-1", 1, 2, 3, 4, None, [...]), + ("项目-工健健康小屋", "2026-YZ-1", 1, 2, 5, 6, 4, [...]), + ("项目-汤原县AI医助", "2026-AI-2", None, 1, 3, 4, 2, [...]), +] +``` + +### 2. 同名项目(不同项目编号) + +Excel 中可能有多个同名项目(如"南方医科大学珠江医院"有 `20260205-A` 和 `2026-BD-1` 两个编号)。用 `project_name` 做 dict key 会覆盖。 + +**对策**: 始终用 `project_code` 做映射,不要用 `project_name`。 + +```python +projects_by_code = {p.project_code: {"name": p.project_name, "id": p.id} for p in db.query(Project).all()} +``` + +### 3. 人员不在人员概况 sheet 中 + +新 Excel 可能新增了人员(如"陈天然"),但只出现在收益分析 sheet 中,不在人员概况 sheet 里。 + +**对策**: 扫描所有 sheet 发现新人员,手动补加到人员表。 + +### 4. 公式字段 openpyxl 读不到 + +Excel 中的 `=SUM(...)`、`=C2/D2` 等公式,openpyxl 读取时返回公式字符串而非计算结果。 + +**对策**: +- 预期收益从收益分析 sheet 的"总计"行读取(那里是数值) +- 投产比等计算字段在数据库端用 ROI 计算器重新计算 + +### 5. 自由文本 → 结构化关联 + +"人员项目负荷情况" sheet 的工作描述是自由文本(如"1、百度医院智能体-南方医科大学珠江医院-近一个月工作占比50%"),需要从中提取项目关联和分配比例。 + +**对策**: 两阶段匹配: +1. 精确匹配:项目全名在文本中 +2. 关键词回退:`"健康小屋" → "工会健康小屋"`, `"AI医助" → "佳木斯中医院AI医助"` + +分配比例从文本中 `占比(\d+)%` 正则提取,无比例时按项目关联人数均分。 + +### 6. 增量更新 vs 全量重来 + +**原则**: 首次导入用全量清空重来;后续更新用增量 upsert(按 project_code/personnel_id 匹配)。 + +**增量 upsert 模式**: +```python +existing = db.query(Model).filter(Model.code == code).first() +if existing: + for key, val in new_data.items(): + setattr(existing, key, val) +else: + db.add(Model(**new_data)) +``` + +--- + +### 7. openpyxl 样式解析 bug(TypeError: expected Fill) + +openpyxl 3.1.5 在解析某些 Excel 文件的 `styles.xml` 时,遇到不兼容的 Fill 样式对象会抛出 `TypeError: expected `。 + +**无效尝试**: +- `data_only=True` — 只影响公式计算,不跳过样式解析 +- `read_only=True` — 同样需要解析样式表 +- 升级 openpyxl — 3.1.5 是当前最新版,bug 尚未修复 + +**根治方案**:改用 **python-calamine**(Rust 实现的 Excel 解析器),它完全不解析样式,只读数据。 + +```python +from python_calamine import CalamineWorkbook + +wb = CalamineWorkbook.from_path(path) +sheets = wb.sheet_names +ws = wb.get_sheet_by_name("Sheet1") +rows = list(ws.to_python()) # 返回 list[list],每个 cell 是 Python 原生类型 +``` + +**注意事项**: +- `python-calamine` 返回的单元格值是 Python 原生类型(float/int/str/None),无需额外转换 +- 不解析公式,返回的是缓存的计算结果(与 `data_only=True` 类似) +- 不支持写 Excel,只用于读取 +- 安装:`pip install python-calamine` 或加到 requirements.txt + +**⚠️ employee_id 空值陷阱**: +`python-calamine` 返回的空单元格是 `None`,但 Excel 中写了空字符串的单元格也会被 `str(val).strip()` 转为空字符串。用 `clean()` 函数处理时,空字符串会变成 `None`,导致 NOT NULL 约束失败。 + +```python +# ❌ 错误:clean(row[2]) 对空单元格返回 None +emp_id = clean(row[2]) if len(row) > 2 else f"EMP{name}" + +# ✅ 正确:显式检查 clean() 结果是否为空 +emp_id = clean(row[2]) if len(row) > 2 and clean(row[2]) else f"EMP{name}" +``` + +**规律**:任何 `clean()` 的返回值都可能为 `None`,不能因为列存在就假定值非空。在 NOT NULL 字段上使用 `clean()` 时,必须加 `and clean(val)` 二次检查。 + +**Web API 中的完整模式**: +```python +tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".xlsx") +try: + content = await file.read() + tmp.write(content) + tmp.close() + wb = CalamineWorkbook.from_path(tmp.name) + # ... 解析各 sheet ... +finally: + os.unlink(tmp.name) +``` + +--- + +## 导入后验证清单 + +- [ ] 项目数是否匹配 Excel 项目概况行数 +- [ ] 人员数是否覆盖所有出现的人名 +- [ ] 预期收益是否与 Excel 收益分析 sheet 的"总计"行一致 +- [ ] WBS 任务数是否合理(每个项目应有 >0 条) +- [ ] 人员-项目关联数是否覆盖主要参与关系 +- [ ] 收益矩阵 API 返回的数据与 Excel 收益分析 sheet 交叉验证 +- [ ] 仪表盘 OKR 完成率是否与 Excel 部门概况一致 diff --git a/archives/dev-pipeline-universal/references/fastapi-pitfalls.md b/archives/dev-pipeline-universal/references/fastapi-pitfalls.md new file mode 100644 index 0000000..4f82b06 --- /dev/null +++ b/archives/dev-pipeline-universal/references/fastapi-pitfalls.md @@ -0,0 +1,315 @@ +# FastAPI 实战陷阱与最佳实践 + +> **适用于 dev-pipeline ④编码实现阶段。程序员(主程序员/结对程序员)在编写 FastAPI 代码时必须注意以下陷阱。 + +--- + +## 1. 路由注册顺序 + +### 问题 +FastAPI 按注册顺序匹配路由。**具体路由必须在参数化路由之前注册**,否则会被错误匹配。 + +```python +# ❌ 错误:/{personnel_id} 先注册,/workload 被匹配为 personnel_id="workload" +@router.get("/{personnel_id}") # 第63行 +def get_personnel(...) + +@router.get("/{personnel_id}/workload") # 第151行 → 永远匹配不到 +def get_personnel_workload(...) + +# ✅ 正确:具体路由先注册 +@router.get("/{personnel_id}/workload") # 先注册 +def get_personnel_workload(...) + +@router.get("/{personnel_id}") # 后注册 +def get_personnel(...) +``` + +### 排查方法 +当某个路由返回 404 但确信路径正确时: +1. 检查路由注册顺序(`grep -n "@router\." file.py`) +2. 确认具体路由(含固定路径段)在参数化路由之前 + +### 同类陷阱 +- `/milestones/all` 必须在 `/{project_id}/milestones` 之前 +- `/tasks/all` 必须在 `/{project_id}/tasks` 之前 +- `/export/projects` 必须在 `/{project_id}` 之前 + +--- + +## 2. Excel 导出中文文件名编码 + +### 问题 +`Content-Disposition: attachment; filename=中文.xlsx` 中的中文字符在 Starlette TestClient 中触发 `UnicodeEncodeError`,某些浏览器也无法正确解析。 + +### 修复 +使用 RFC 5987 编码: + +```python +from urllib.parse import quote + +def _excel_response(wb, filename): + output = io.BytesIO() + wb.save(output) + output.seek(0) + encoded_filename = quote(filename) + return StreamingResponse( + output, + media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + headers={"Content-Disposition": f"attachment; filename*=UTF-8''{encoded_filename}"}, + ) +``` + +### 测试注意事项 +- Starlette TestClient 的 `UnicodeEncodeError` 是已知问题,测试中需 try/except 捕获 +- 验证 Excel 内容时检查 `content[:2] == b"PK"`(ZIP 签名)即可 +- 用 `openpyxl.load_workbook(io.BytesIO(resp.content))` 验证内容正确性 + +--- + +## 3. 依赖声明 + +### 问题 +新增 Python 依赖(如 `openpyxl`)后忘记更新 `requirements.txt`,导致部署时崩溃。 + +### 规则 +每次④编码实现阶段新增依赖后,必须: +1. 确认依赖已安装(`pip list | grep `) +2. 更新 `requirements.txt`(`pip freeze | grep >> requirements.txt` 或手动添加) +3. 结对程序员 review 时检查 requirements.txt 变更 + +--- + +## 4. SQLAlchemy N+1 查询 + +### 问题 +遍历 ORM 对象时访问关联属性会触发额外 SQL 查询。 + +```python +# ❌ N+1:对每个任务查一次 project +for task in tasks: + project_name = task.project.project_name # 触发额外 SQL + +# ✅ 修复:使用 joinedload 批量加载 +from sqlalchemy.orm import joinedload +tasks = db.query(ProjectTask).options(joinedload(ProjectTask.project)).all() +``` + +### 批量查询替代方案 +当无法使用 joinedload 时,用 `IN` 查询替代循环查询: + +```python +# ❌ N+1 +for task in tasks: + progress = db.query(TaskMonthlyProgress).filter( + TaskMonthlyProgress.task_id == task.id + ).first() + +# ✅ 批量 +all_progress = db.query(TaskMonthlyProgress).filter( + TaskMonthlyProgress.task_id.in_(task_ids) +).all() +task_latest = {p.task_id: p for p in all_progress} +``` + +--- + +## 5. SQLAlchemy NULL 处理 + +### 问题 +SQLAlchemy 中 `column < 100` 遇到 NULL 时返回 UNKNOWN(不匹配),导致 NULL 值被遗漏。 + +```python +# ❌ 遗漏 overall_progress IS NULL 的任务 +tasks = db.query(ProjectTask).filter(ProjectTask.overall_progress < 100).all() + +# ✅ 正确:显式处理 NULL +from sqlalchemy import or_ +tasks = db.query(ProjectTask).filter( + or_(ProjectTask.overall_progress < 100, ProjectTask.overall_progress.is_(None)) +).all() +# 或使用 | 运算符(注意括号) +tasks = db.query(ProjectTask).filter( + (ProjectTask.overall_progress < 100) | (ProjectTask.overall_progress.is_(None)) +).all() +``` + +--- + +## 6. 前端导出绕过认证 + +### 问题 +用 `` 标签直接访问 API 路径会跳过 axios 的 `Authorization: Bearer` 拦截器,导致 401。 + +```javascript +// ❌ 错误:绕过认证 +const link = document.createElement('a') +link.href = '/api/reports/export/projects' +link.click() + +// ✅ 正确:通过 axios 获取 blob 后下载 +api.get('/reports/export/projects', { responseType: 'blob' }).then(res => { + const url = URL.createObjectURL(new Blob([res.data])) + const link = document.createElement('a') + link.href = url + link.download = 'filename.xlsx' + link.click() + URL.revokeObjectURL(url) +}) +``` + +### DRY 原则 +多个导出函数应提取为通用函数: + +```javascript +function downloadExcel(url, filename) { + exporting.value = true + api.get(url, { responseType: 'blob' }).then(res => { + const blobUrl = URL.createObjectURL(new Blob([res.data])) + const link = document.createElement('a') + link.href = blobUrl + link.download = filename + link.click() + URL.revokeObjectURL(blobUrl) + }).finally(() => { exporting.value = false }) +} +``` + +--- + +## 7. ECharts 生命周期管理 + +### 问题 +Vue 组件销毁时未释放 ECharts 实例导致内存泄漏;路由参数变化(如 `/personnel/1` → `/personnel/2`)时图表不刷新。 + +### 修复 +```javascript +import { onBeforeUnmount, onBeforeRouteUpdate } from 'vue-router' + +// 销毁时释放 +onBeforeUnmount(() => { + chart?.dispose() +}) + +// 路由参数变化时重新加载 +onBeforeRouteUpdate(() => { + chart?.dispose() + loadData() +}) +``` + +--- + +## 8. 浮点精度 + +### 问题 +Python 浮点累加可能产生尾数误差(如 `49.9999999` 而非 `50.0`)。 + +### 修复 +```python +# 在最终输出时统一 round +total = round(sum(values), 2) +``` + +--- + +## 10. Pydantic Schema 字段同步 + +### 问题 +后端 API 返回字典中新增了字段,但 Pydantic `response_model` schema 中没有声明,导致字段被静默丢弃。前端收到 `undefined`,页面渲染异常。 + +```python +# ❌ 后端返回了 project_count,但 PersonnelOut schema 没有这个字段 +class PersonnelOut(BaseModel): + id: int + name: str + # ... 没有 project_count → 被 Pydantic 过滤掉 + +# ✅ 必须在 schema 中声明 +class PersonnelOut(BaseModel): + id: int + name: str + project_count: Optional[int] = 0 + total_allocation: Optional[float] = 0.0 +``` + +### 排查方法 +当前端收到 `undefined` 但确信后端有返回时: +1. 去掉 `response_model` 参数,看原始返回是否包含该字段 +2. 检查 schema 定义是否包含新字段 +3. 注意 `from_attributes = True` 只影响 ORM→Pydantic 转换,不影响 dict→Pydantic 过滤 + +### 关联陷阱 +- 修改 `_build_personnel_dict` 等 helper 函数后,必须同步更新对应的 schema +- 结对程序员 review 时重点检查:helper 返回字段 ↔ schema 字段 的一致性 + +--- + +## 11. 部署验证脚本模式 + +### 问题 +部署验证时使用 shell 管道(`curl | python3 -c`)容易触发安全防护(命令超时/阻断),尤其是涉及变量引用和 URL 编码时。 + +### 推荐方案 +用 Python 脚本替代 shell 管道,一个文件完成全部验证: + +```python +#!/usr/bin/env python3 +import urllib.request, json + +BASE = "http://127.0.0.1:8001" + +def api(method, path, data=None, token=None): + url = BASE + path + headers = {"Content-Type": "application/json"} + if token: + headers["Authorization"] = f"Bearer {token}" + body = json.dumps(data).encode() if data else None + req = urllib.request.Request(url, data=body, headers=headers, method=method) + resp = urllib.request.urlopen(req, timeout=10) + return resp.status, resp.read() + +# 1. 登录 +status, data = api("POST", "/api/auth/login", {"username": "admin", "password": "admin123"}) +token = json.loads(data)["access_token"] + +# 2. 验证端点 +status, data = api("GET", "/api/projects?project_type=创新项目", token=token) +projects = json.loads(data) +print(f"类型筛选: {len(projects)}个") + +# 3. 验证 Excel 导出 +status, data = api("GET", "/api/reports/export/projects", token=token) +assert data[:2] == b"PK" # ZIP 签名 +import openpyxl, io +wb = openpyxl.load_workbook(io.BytesIO(data)) +print(f"导出: {wb.active.title}, {wb.active.max_row-1}行") +``` + +### 优势 +- 避免 shell 变量注入和管道超时 +- 可在虚拟环境中直接运行 +- 断言清晰,失败时立即知道哪个端点出问题 +- 可复用(保存为 `scripts/verify_deploy.py`) + +--- + +## 9. 时区一致性 + +### 问题 +项目中混用 timezone-naive 和 timezone-aware 的 datetime 导致比较偏差。 + +### 规范 +```python +from datetime import datetime, timezone + +# 统一使用 UTC aware datetime +now = datetime.now(timezone.utc) + +# 解析字符串时也设为 aware +from calendar import monthrange +parts = month_str.split("-") +y, m = int(parts[0]), int(parts[1]) +last_day = monthrange(y, m)[1] +progress_date = datetime(y, m, last_day, tzinfo=timezone.utc) +``` diff --git a/archives/dev-pipeline-universal/references/framework-comparison.md b/archives/dev-pipeline-universal/references/framework-comparison.md new file mode 100644 index 0000000..70c63a3 --- /dev/null +++ b/archives/dev-pipeline-universal/references/framework-comparison.md @@ -0,0 +1,44 @@ +# AI 编码框架多代理协作调研(2026-04-19) + +> 本文档记录了 v2.0 设计决策的调研依据。用于未来架构演进参考。 + +## 三种多Agent协作范式 + +| 范式 | 代表框架 | 特点 | 我们的借鉴 | +|------|---------|------|-----------| +| **SOP驱动** | MetaGPT | 模拟软件公司,角色固定,结构化输出 | → 6阶段YAML产物模板 | +| **任务编排** | CrewAI | Agent/Task/Crew抽象,sequential/hierarchical | → delegate_task per-task模型路由 | +| **群聊协商** | AutoGen | GroupChat多Agent讨论,Manager分配 | 未采用(开销大) | + +## 框架与Hermes集成潜力排序 + +| 优先级 | 框架 | 集成方式 | 适合场景 | +|--------|------|---------|---------| +| 🥇 | **Aider** | 作为编码执行引擎 | git深度集成、repo map、双模型模式 | +| 🥈 | **CrewAI** | 借鉴编排模式 | Agent/Task/Crew抽象 | +| 🥉 | **MetaGPT** | 借鉴SOP+角色设计 | 结构化产物、发布订阅通信 | +| 4 | **OpenHands** | 借鉴事件流+浏览器能力 | 全栈开发(前端+后端) | +| 5 | **Claude Code** | 借鉴subagent+worktree并行 | 大任务并行编码 | + +## 关键学术发现(影响v2.0设计) + +| 论文 | 发现 | 落地到v2.0 | +|------|------|-----------| +| MetaGPT (2308.00352) | 结构化输出减少30%信息损失 | templates/stage-artifacts.md | +| AgentCoder (2312.13010) | 独立测试Agent比自测通过率高12-18% | 测试员信息隔离原则 | +| ChatDev (2307.07924) | 角色对话提升20%完成率,需设轮次上限 | 每阶段max 3轮重试 | +| SWE-bench | 60%失败源于定位错误 | 强调代码搜索能力(未来P2) | +| Agentless | 简单流水线有时比复杂Agent更好 | 小型需求总管直接做,不过度编排 | + +## 我们选择"不换框架"的理由 + +1. Hermes 的 `delegate_task` + custom_providers 已是成熟的多Agent编排 +2. 已有5角色6阶段,与MetaGPT的SOP模式架构等价 +3. 完全开源、模型灵活(火山方舟9个模型可切换)、可控性最高 +4. 不引入额外框架依赖,降低维护成本 + +## 未来演进方向(P2+) + +- **短期**: 集成 Aider 的 repo map(tree-sitter AST索引)提升代码定位能力 +- **中期**: 借鉴 Claude Code worktree 并行模式,大任务拆分后多分支并行编码 +- **长期**: 代码库向量索引(RAG),经验池积累成功案例 diff --git a/archives/dev-pipeline-universal/references/frontend-build-optimization.md b/archives/dev-pipeline-universal/references/frontend-build-optimization.md new file mode 100644 index 0000000..5fc248c --- /dev/null +++ b/archives/dev-pipeline-universal/references/frontend-build-optimization.md @@ -0,0 +1,94 @@ +# 前端构建优化(Vite 代码分割 + 路由懒加载) + +> 适用于 Vue 3 + Vite 项目,Element Plus + ECharts 技术栈 + +## 问题 + +Vue 3 + Element Plus + ECharts 项目构建后,默认所有代码打包成一个 JS 文件(通常 2~3MB),首屏加载全量代码,严重影响首次加载速度。 + +## 优化方案 + +### 1. Vite `manualChunks` 拆包 + +在 `vite.config.js` 中配置 `build.rollupOptions.output.manualChunks`,将大体积第三方库拆为独立 chunk: + +```js +// vite.config.js +export default defineConfig({ + plugins: [vue()], + build: { + rollupOptions: { + output: { + manualChunks(id) { + // echarts 单独拆包(~1MB,仅访问图表页面时加载) + if (id.includes('node_modules/echarts')) { + return 'echarts' + } + // element-plus 单独拆包(~1MB,浏览器缓存) + if (id.includes('node_modules/element-plus')) { + return 'element-plus' + } + // vue 核心库单独拆包(~120KB) + if (id.includes('node_modules/vue') || id.includes('node_modules/@vue')) { + return 'vue-core' + } + }, + }, + }, + chunkSizeWarningLimit: 500, // 提高告警阈值,避免拆包后仍有大 chunk 告警 + }, +}) +``` + +**效果**: +| Chunk | 大小 | 加载时机 | +|:------|:----:|:--------| +| `vue-core` | ~120KB | 首屏 | +| `element-plus` | ~1MB | 首屏(浏览器缓存后不重复下载) | +| `echarts` | ~1MB | 仅访问图表页面时按需加载 | +| 各页面组件 | 2~15KB | 按需加载 | + +### 2. 路由懒加载(动态 import) + +将 `router/index.js` 中的静态 import 改为动态 `() => import(...)`: + +```js +// ❌ 静态 import(全量加载) +import Dashboard from '../views/dashboard/Index.vue' + +// ✅ 动态 import(按需加载) +const routes = [ + { + path: '/dashboard', + component: () => import('../views/dashboard/Index.vue'), + }, +] +``` + +Vite 会自动为每个动态 import 生成独立 chunk,文件名基于组件名(如 `Index-abc123.js`)。 + +### 3. 验证优化效果 + +```bash +# 构建前 +ls -lh dist/assets/ +# 输出:index-DoEo0YCm.js 2.3M ← 单文件 + +# 配置后构建 +npm run build +ls -lh dist/assets/ +# 输出: +# vue-core-BuIKajZo.js 119KB +# element-plus-C03w9GoR.js 1.0MB +# echarts-Bb6yjXMn.js 1.0MB +# Index-xxx.js 2~15KB(每个页面) +# ... +``` + +## 注意事项 + +1. **manualChunks 函数**接收的是模块 ID(绝对路径),用 `id.includes()` 匹配 `node_modules` 中的包名 +2. **路由懒加载**只在用户访问对应路由时才加载 chunk,首次访问某页面会有短暂加载延迟(通常 < 200ms) +3. **echarts 拆包后**,只有访问包含 ECharts 图表的页面(仪表盘、经营数据等)才会加载 echarts chunk +4. **chunkSizeWarningLimit** 建议设为 500KB,避免拆包后 element-plus/echarts 仍触发告警(它们确实很大) +5. **浏览器缓存**:element-plus 和 vue-core 拆为独立 chunk 后,只要版本不变,浏览器会缓存,后续页面访问不再下载 diff --git a/archives/dev-pipeline-universal/references/operation-log-pattern.md b/archives/dev-pipeline-universal/references/operation-log-pattern.md new file mode 100644 index 0000000..e9901ad --- /dev/null +++ b/archives/dev-pipeline-universal/references/operation-log-pattern.md @@ -0,0 +1,212 @@ +# 操作日志系统(审计追踪模式) + +> **适用场景**: 任何需要审计追踪的 CRUD 管理系统 +> **创建日期**: 2026-06-29 + +--- + +## 四层架构 + +| 层次 | 文件 | 职责 | +|:----|:-----|:-----| +| 模型 | `models/operation_log.py` | 定义数据库表结构 | +| 服务 | `services/operation_log.py` | 工具函数 `log_operation()` | +| API | `routers/logs.py` | `GET /api/logs` 查询接口 | +| 埋点 | 各 CRUD 路由中 | 在 create/update/delete 后调用 | + +--- + +## 模型定义 + +```python +from sqlalchemy import Column, Integer, String, DateTime, Text +from sqlalchemy.sql import func +from app.database import Base + + +class OperationLog(Base): + __tablename__ = "operation_logs" + + id = Column(Integer, primary_key=True, index=True) + user = Column(String(64), default="admin", comment="操作人") + action = Column(String(32), nullable=False, comment="操作类型: create/update/delete") + entity_type = Column(String(32), nullable=False, comment="实体类型") + entity_id = Column(Integer, nullable=True, comment="实体ID") + entity_name = Column(String(128), nullable=True, comment="实体名称(冗余,方便展示)") + detail = Column(Text, nullable=True, comment="操作详情") + created_at = Column(DateTime(timezone=True), server_default=func.now(), comment="操作时间") +``` + +## 服务层 + +```python +from sqlalchemy.orm import Session +from app.models.operation_log import OperationLog + + +def log_operation( + db: Session, + action: str, + entity_type: str, + entity_id: int = None, + entity_name: str = None, + detail: str = None, + user: str = "admin", +): + log = OperationLog( + user=user, + action=action, + entity_type=entity_type, + entity_id=entity_id, + entity_name=entity_name, + detail=detail, + ) + db.add(log) + db.commit() +``` + +## API 路由 + +```python +from fastapi import APIRouter, Depends, Query +from sqlalchemy.orm import Session +from app.database import get_db +from app.models.operation_log import OperationLog +from typing import Optional + +router = APIRouter(prefix="/api/logs", tags=["操作日志"]) + + +@router.get("") +def list_logs( + entity_type: Optional[str] = Query(None), + action: Optional[str] = Query(None), + limit: int = Query(100, ge=1, le=500), + offset: int = Query(0, ge=0), + db: Session = Depends(get_db), +): + q = db.query(OperationLog).order_by(OperationLog.created_at.desc()) + if entity_type: + q = q.filter(OperationLog.entity_type == entity_type) + if action: + q = q.filter(OperationLog.action == action) + + total = q.count() + logs = q.offset(offset).limit(limit).all() + + return { + "total": total, + "logs": [ + { + "id": log.id, + "user": log.user, + "action": log.action, + "entity_type": log.entity_type, + "entity_id": log.entity_id, + "entity_name": log.entity_name, + "detail": log.detail, + "created_at": log.created_at.isoformat() if log.created_at else None, + } + for log in logs + ], + } +``` + +## 埋点注入模式 + +### 创建后 + +```python +log_operation(db, "create", "project", p.id, p.project_name, f"创建项目: {p.project_code}") +``` + +### 更新后 + +```python +log_operation(db, "update", "project", p.id, p.project_name, f"更新项目: {p.project_code}") +``` + +### 删除前(需要 entity_name 做记录) + +```python +log_operation(db, "delete", "project", project_id, p.project_name if p else None, f"删除项目: ID={project_id}") +``` + +### 批量导入 + +```python +log_operation(db, "create", "import", None, filename, f"Excel导入: {stats}") +``` + +## 注册路由 + +在 `main.py` 中: + +```python +from app.routers import auth, groups, personnel, projects, settings, dashboard, reports, search, finance, logs + +# 受保护路由 +app.include_router(logs.router, dependencies=[Depends(verify_token)]) +``` + +## 前端页面 + +```vue + +``` + +## 路由注册 + 侧边栏 + +```javascript +// router/index.js +{ + path: 'logs', + name: 'Logs', + component: () => import('../views/logs/Index.vue'), +} + +// Layout.vue 侧边栏 + + + 操作日志 + +``` + +## 适用实体类型 + +| entity_type | 含义 | 埋点位置 | +|:------------|:-----|:---------| +| project | 项目 | projects.py CRUD | +| task | WBS 任务 | projects.py task CRUD | +| milestone | 里程碑 | projects.py milestone CRUD | +| income | 月度收益 | projects.py income CRUD | +| personnel | 人员 | personnel.py CRUD | +| group | 组别 | groups.py CRUD | +| setting | 系统设置 | settings.py CRUD | +| import | 数据导入 | import_data.py | + +## 注意事项 + +1. **删除操作需在 delete 前记录**:`db.delete()` 后对象属性仍可访问,但 `db.commit()` 后不可用 +2. **SQLAlchemy Column 类型警告**:Pyright 会报 `Column[int]` 不能赋值给 `int` 的参数类型错误,这是已知假阳性,不影响运行 +3. **不要过度埋点**:GET 查询操作不需要记录,只记录 create/update/delete +4. **entity_name 冗余存储**:即使关联实体被删除,日志中仍保留名称用于展示 diff --git a/archives/dev-pipeline-universal/references/quality-gates.md b/archives/dev-pipeline-universal/references/quality-gates.md new file mode 100644 index 0000000..e82f55c --- /dev/null +++ b/archives/dev-pipeline-universal/references/quality-gates.md @@ -0,0 +1,109 @@ +# 研发流水线 — 质量门禁规范 +# 每个阶段完成后,由马总管自动执行质量门禁检查 + +--- + +## 质量门禁总览 + +``` +需求 ──→ [QG1] ──→ 设计 ──→ [QG2] ──→ 编码 ──→ [QG3] ──→ 测试 ──→ [QG4] ──→ 部署 +``` + +--- + +## QG1: 需求分析门禁 + +**执行时机:** ①需求分析完成后,进入②设计之前 + +| 检查项 | 通过标准 | 执行方式 | +|--------|---------|---------| +| 产物格式完整 | YAML所有必填字段非空 | 自动 | +| 验收标准可测试 | 每条AC标记testable=true | 自动 | +| 范围边界清晰 | in_scope和out_of_scope均非空 | 自动 | +| 用户确认 | 乔确认需求理解正确 | 人工 | + +**不通过处理:** 补充缺失信息,重新跟乔确认 + +--- + +## QG2: 技术方案门禁 + +**执行时机:** ②设计完成后,进入③编码之前 + +| 检查项 | 通过标准 | 执行方式 | +|--------|---------|---------| +| 产物格式完整 | YAML所有必填字段非空 | 自动 | +| 文件变更清单 | file_changes列表非空 | 自动 | +| API设计与需求对齐 | 每个AC至少对应一个API或功能点 | AI审查 | +| 无遗留阻断问题 | open_issues中无阻断级问题 | 自动 | +| 重大决策确认 | 涉及架构变更时需乔确认 | 条件人工 | + +**不通过处理:** 反馈问题给架构师Agent重新设计(最多2轮) + +--- + +## QG3: 编码实现门禁 + +**执行时机:** ③编码完成后,进入④审查之前 + +| 检查项 | 通过标准 | 执行方式 | +|--------|---------|---------| +| 产物格式完整 | YAML所有必填字段非空 | 自动 | +| 代码可编译/无语法错误 | self_check.compiles=true | 自动 | +| lint通过 | self_check.lint_passes=true | 自动 | +| 文件变更与设计一致 | 实际变更文件 ⊆ 设计中的file_changes | AI审查 | +| 无常驻进程残留 | 无未关闭的后台服务 | 自动 | + +**不通过处理:** 反馈给程序员Agent修复(最多3轮) + +--- + +## QG4: 测试验证门禁 + +**执行时机:** ⑤测试完成后,进入⑥部署之前 + +| 检查项 | 通过标准 | 执行方式 | +|--------|---------|---------| +| 所有测试通过 | verdict=ALL_PASS | 自动 | +| 覆盖率达标 | line_percent >= 阈值(见测试规范) | 自动 | +| 无回归 | existing_tests_still_pass=true | 自动 | +| 冒烟测试通过 | smoke.failed=0 | 自动 | +| 部署确认 | 乔确认可以部署 | 人工 | + +**不通过处理:** 失败信息反馈给程序员Agent修复 → 重新测试(最多3轮) + +--- + +## 门禁执行规则 + +### 重试策略 +``` +第1次失败 → 同模型重试,附带失败原因 +第2次失败 → 换备用模型重试 +第3次失败 → 上报乔,进入人工介入 +``` + +### 备用模型降级链(示例 — 根据实际可用模型替换) + +降级原则:主模型失败时,按以下优先级替换: +1. 同平台其他模型(相同 API 端点) +2. 不同平台同等级模型 +3. 快速响应模型兜底 + +| 角色 | 降级策略 | +|------|---------| +| 架构师 | 强推理模型 → 同平台次强模型 → 通用模型 | +| 设计师 | 编码版模型 → 通用强模型 → 快速模型 | +| 主程序员 | 深度编码模型 → 其他编码模型 → 快速模型 | +| 结对程序员 | 与主程序员不同家族模型 → 主程序员模型 | +| 审查员 | 深度推理模型 → 架构师模型 | +| 测试员 | Agent能力强的模型 → 编码模型 | + +### 超时保护 +| 阶段 | 超时时间 | 超时处理 | +|------|---------|---------| +| ②设计 | 30分钟 | 终止,记录已有产出,人工介入 | +| ③UI设计 | 10分钟 | 换模型重试,精简prompt | +| ④编码 | 50分钟 | 终止,保留已写代码,人工介入 | +| ⑤审查 | 25分钟 | 终止,标记"审查超时",进入测试 | +| ⑥测试 | 40分钟 | 终止,保留已有测试结果,人工介入 | diff --git a/archives/dev-pipeline-universal/references/revenue-allocation-pattern.md b/archives/dev-pipeline-universal/references/revenue-allocation-pattern.md new file mode 100644 index 0000000..9045eca --- /dev/null +++ b/archives/dev-pipeline-universal/references/revenue-allocation-pattern.md @@ -0,0 +1,113 @@ +# 收益归属矩阵(业务报表模式) + +> **适用场景**: 需要按人×项目维度展示收益归属矩阵 +> **创建日期**: 2026-06-24 + +--- + +## 业务含义 + +行 = 人员,列 = 项目,交叉单元格 = 该人在该项目的收益贡献。类似 Excel 透视表。 + +``` + 项目A 项目B 项目C 小计 +郑明义 ¥14,983 ¥4,142 ¥1,839 ¥20,964 +薛文 ¥11,600 ¥884 ¥3,678 ¥16,162 +总计 ¥82,031 ¥7,070 ¥9,196 ¥98,297 +``` + +--- + +## 计算逻辑 + +### 数据源 + +- `project_monthly_income` — 项目月度总收益(按项目×月份) +- `personnel_projects` — 人员-项目关联(含 `allocation_ratio` 分配比例) + +### 核心公式 + +``` +个人在项目的收益 = 项目总收益 × (该人的分配比例 / 100) +``` + +### 特殊情况 + +| 情况 | 处理方式 | +|------|---------| +| 人员有关联比例 | 按比例分摊项目总收益 | +| 人员无关联比例 | 收益为 0(不显示在矩阵中) | +| 项目无收益记录 | 收益为 0(不显示在矩阵中) | +| 月份筛选 | 只计算该月的收益记录 | + +### API 设计 + +``` +GET /api/reports/income-matrix?month=2026-06 + +Response: +{ + "rows": [ + { + "name": "郑明义", + "group_name": "四组", + "projects": {"南方医科大学珠江医院": 9666.67, "苏州市立医院": 1325.58}, + "subtotal": 12831.38 + } + ], + "project_totals": {"南方医科大学珠江医院": 82031.34, ...}, + "grand_total": 442598.68, + "month": null +} +``` + +--- + +## 前端实现要点 + +### 动态列 + +项目列是动态的(随数据变化),需要用 `v-for` 在 `` 上渲染: + +```vue + + + +``` + +### 总计行 + +用 `` 展示项目总计,放在表格下方: + +```vue + + + ¥{{ grandTotal.toLocaleString() }} + + + ¥{{ val.toLocaleString() }} + + +``` + +### 月份筛选 + +提供月份下拉框,不传参时汇总所有月份。筛选在 API 层完成,前端只传参数。 + +--- + +## 常见问题 + +### Q: 为什么矩阵中的项目总收益不等于项目列表中的预期收益? + +A: 矩阵中的收益来自 `project_monthly_income`(实际实现的月度收益),不等于项目的预期收益(合同金额)。两者是不同概念。 + +### Q: 为什么某些人没有出现在矩阵中? + +A: 只有 `subtotal > 0` 的行才会显示。如果人员有关联项目但项目没有收益记录,该人员不会出现。 + +### Q: 分配比例从哪里来? + +A: 从 `personnel_projects.allocation_ratio` 字段读取。初始导入时从 Excel 工作描述中的"占比 N%"正则提取,无比例时按项目关联人数均分。 diff --git a/archives/dev-pipeline-universal/references/roles.example.yaml b/archives/dev-pipeline-universal/references/roles.example.yaml new file mode 100644 index 0000000..c796b11 --- /dev/null +++ b/archives/dev-pipeline-universal/references/roles.example.yaml @@ -0,0 +1,41 @@ +# 研发流水线 — 角色模型配置示例 +# +# 使用前请复制为 roles.yaml,修改模型名称为您实际可用的模型。 +# 每个角色使用不同模型家族可获得更好的交叉审视效果。 + +roles: + - name: "架构师" + code: "ARCH" + emoji: "🏗️" + stages: ["②技术方案"] + model: "<强推理模型,如 glm-5.2 / claude-sonnet-4 / deepseek-v4-pro>" + + - name: "设计师" + code: "UI" + emoji: "🎨" + stages: ["③UI设计"] + model: "<编码版模型,如 kimi-k2.7-code / claude-sonnet-4>" + + - name: "主程序员" + code: "DEV" + emoji: "💻" + stages: ["④编码实现"] + model: "<深度编码模型,如 deepseek-v4-pro / claude-sonnet-4>" + + - name: "结对程序员" + code: "DEV2" + emoji: "👥" + stages: ["④编码实现(review)"] + model: "<与主程序员不同家族,如 kimi-k2.7-code / gpt-4o>" + + - name: "审查员" + code: "REVIEW" + emoji: "🔍" + stages: ["⑤代码审查"] + model: "<深度推理模型,如 deepseek-v4-pro / claude-sonnet-4>" + + - name: "测试员" + code: "QA" + emoji: "🧪" + stages: ["⑥测试验证"] + model: "" diff --git a/archives/dev-pipeline-universal/references/testing-strategy.md b/archives/dev-pipeline-universal/references/testing-strategy.md new file mode 100644 index 0000000..ae2f322 --- /dev/null +++ b/archives/dev-pipeline-universal/references/testing-strategy.md @@ -0,0 +1,125 @@ +# 研发流水线 — 测试分层策略 + +--- + +## 测试金字塔 + +``` + ╱╲ + ╱ 冒烟 ╲ ← 5-10% (部署后关键路径验证) + ╱────────╲ + ╱ 集成测试 ╲ ← 20-30% (API/服务间交互) + ╱──────────────╲ + ╱ 单元测试 ╲ ← 60-70% (函数/类级别) + ╱──────────────────╲ +``` + +--- + +## 各层测试规范 + +### 单元测试 + +**目标:** 验证单个函数/类的行为正确性 +**覆盖率要求:** 行覆盖 ≥ 70%,函数覆盖 ≥ 80% + +**测试Agent生成规则:** +1. 只看接口签名+文档+验收标准,不看实现细节(黑盒测试优先) +2. 必须覆盖:正常路径、边界值(空/null/最大/最小)、异常路径 +3. 每个测试函数只验证一个行为点 +4. 测试命名格式:`test_<功能>_<场景>_<预期结果>` + +### 集成测试 + +**目标:** 验证模块间/服务间交互正确性 +**覆盖率要求:** 所有API接口100%覆盖 + +**测试Agent生成规则:** +1. 每个API端点至少:1个成功用例 + 1个参数校验失败 + 1个权限失败 +2. 测试数据库/外部服务交互的完整流程 +3. 使用真实的数据库(SQLite内存模式)或合理的Mock + +### 冒烟测试 + +**目标:** 部署后快速验证核心功能可用 +**覆盖率要求:** 覆盖所有核心用户路径 + +**测试Agent生成规则:** +1. 从验收标准(AC)中提取关键路径 +2. 只验证"能不能用",不验证边界条件 +3. 执行时间 < 30秒 +4. 对于前端项目:启动服务 → 访问关键页面 → 验证无崩溃 + +--- + +## 测试质量保障 + +### 独立性原则(参考AgentCoder论文 arXiv:2312.13010) +- 测试Agent(minimax-m3)与编码Agent(deepseek-v4-pro)使用不同模型 +- 测试Agent的prompt中**不包含**编码Agent的prompt和实现思路 +- 测试Agent只接收:接口文档 + 验收标准 + 代码文件(只看签名,不解释逻辑) + +### 测试Agent的Context模板 +``` +你是一个QA测试工程师。根据以下信息编写测试: + +## 需求验收标准 +{acceptance_criteria} + +## 接口/函数签名 +{api_signatures} + +## 项目测试约定 +- 框架: {test_framework} +- 运行命令: {test_command} +- 测试目录: {test_directory} + +## 规则 +1. 优先编写能发现bug的测试(边界值、异常路径) +2. 不要写"同义反复"测试(只是重复实现逻辑) +3. 每个测试必须有明确的断言 +4. 测试之间相互独立,无执行顺序依赖 +5. 编写完成后运行全部测试并输出结果 +``` + +--- + +## 覆盖率阈值 + +| 项目规模 | 行覆盖 | 分支覆盖 | 函数覆盖 | +|---------|--------|---------|---------| +| 大型(新项目) | ≥ 70% | ≥ 60% | ≥ 80% | +| 中型(新功能) | ≥ 60% | ≥ 50% | ≥ 75% | +| 小型(bug修复) | 修改行100%覆盖 | — | — | + +--- + +## 前端项目特殊规则 + +前端项目(React/Vue/Next.js等)的测试策略有所不同: + +| 层级 | 内容 | 工具建议 | +|------|------|---------| +| 单元 | 组件渲染测试、工具函数测试 | Jest + Testing Library | +| 集成 | 页面级交互测试 | Playwright / Cypress | +| 冒烟 | 构建+启动+关键页面可达+无JS错误 | curl + Playwright | + +**前端冒烟测试最低要求:** +1. `npm run build` 成功(无编译错误) +2. 构建产物包含所有预期路由(检查 `.next/routes-manifest.json`) +3. 关键页面路由可访问(无404) +4. 浏览器控制台无未捕获错误 + +**⚠️ 陷阱:不要在vitest中spawn服务器** +在测试中用 `spawn('npm', ['run', 'start'])` 启动Next.js再fetch会超时(Next.js启动慢)且进程清理不干净。替代方案:解析build产物中的 `routes-manifest.json`,验证静态路由和动态路由是否完整。示例: +```typescript +it('should have all expected routes after build', () => { + const routesManifest = JSON.parse( + fs.readFileSync('.next/routes-manifest.json', 'utf-8') + ) + const dynamicRoutes = routesManifest.dynamicRoutes?.map(r => r.page) || [] + const staticRoutes = routesManifest.staticRoutes?.map(r => r.page) || [] + expect(staticRoutes).toContain('/') + expect(dynamicRoutes).toContain('/departments/[id]') +}) +``` diff --git a/archives/dev-pipeline-universal/scripts/show_roles.py b/archives/dev-pipeline-universal/scripts/show_roles.py new file mode 100644 index 0000000..a4d8328 --- /dev/null +++ b/archives/dev-pipeline-universal/scripts/show_roles.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +"""研发流水线 — 角色模型对照表生成脚本(通用模板) + +读取自定义的 roles.yaml 配置文件,输出角色模型对照表。 +用户需根据实际环境修改 references/roles.yaml 中的模型配置。 + +用法: python scripts/show_roles.py +""" + +import yaml +import os +import sys +from pathlib import Path + + +def load_roles(): + """加载 roles.yaml""" + script_dir = Path(__file__).parent.parent / "references" + roles_path = script_dir / "roles.yaml" + if not roles_path.exists(): + print(f"❌ 未找到 roles.yaml: {roles_path}") + print("请复制 references/roles.example.yaml 为 references/roles.yaml 并修改配置") + sys.exit(1) + with open(roles_path) as f: + return yaml.safe_load(f) + + +def main(): + roles_config = load_roles() + roles = roles_config.get("roles", []) + + print("=" * 80) + print("研发流水线 — 角色模型对照表") + print("=" * 80) + + print("\n## 当前角色分配\n") + print(f"{'角色':<12} {'代号':<8} {'阶段':<20} {'模型':<25}") + print("-" * 70) + for role in roles: + stages = ", ".join(role.get("stages", [])) + print(f"{role.get('emoji', '')} {role['name']:<10} {role['code']:<8} {stages:<20} {role['model']:<25}") + + # 一致性检查 + print(f"\n## 一致性检查\n") + print("✅ 请手动检查 roles.yaml 中的模型配置是否与您的 API 平台一致。") + + +if __name__ == "__main__": + main() diff --git a/archives/dev-pipeline-universal/templates/stage-artifacts.md b/archives/dev-pipeline-universal/templates/stage-artifacts.md new file mode 100644 index 0000000..07730d1 --- /dev/null +++ b/archives/dev-pipeline-universal/templates/stage-artifacts.md @@ -0,0 +1,334 @@ +# 研发流水线 — 阶段产物模板 +# 每个阶段的子Agent必须按此格式输出产物 +# 总管(小研)负责校验产物格式完整性 + +--- + +## ① 需求分析产物 + +```yaml +stage: requirements +version: "1.0" +timestamp: "{{ISO_TIMESTAMP}}" + +# 核心产物 +artifacts: + goal: "一句话描述功能目标" + user_stories: + - as: "角色" + want: "功能" + so_that: "价值" + acceptance_criteria: + - id: AC-1 + description: "验收条件描述" + testable: true + constraints: + technical: ["技术约束"] + timeline: "时间要求" + resources: "资源限制" + scope: + in_scope: ["包含的功能点"] + out_of_scope: ["明确排除的功能点"] + +# 元数据 +metadata: + complexity: "large|medium|small|micro" + estimated_stages: ["①", "②", "③", "④", "⑤", "⑥"] + risk_level: "high|medium|low" + +# 遗留问题 +open_issues: [] +``` + +--- + +## ② 技术方案产物 + +```yaml +stage: design +version: "1.0" +timestamp: "{{ISO_TIMESTAMP}}" + +artifacts: + architecture: + pattern: "架构模式(如 monolith/microservice/modular)" + modules: + - name: "模块名" + responsibility: "职责" + dependencies: ["依赖的其他模块"] + data_flow: "数据流描述" + + tech_stack: + language: "编程语言" + framework: "框架" + database: "数据库" + other: ["其他技术选型"] + reasons: "选型理由" + + data_models: + - name: "模型名" + fields: + - {name: "字段名", type: "类型", required: true, description: "说明"} + relations: ["与其他模型的关系"] + + api_design: + - method: "HTTP方法" + path: "/路径" + description: "接口说明" + request_schema: "请求体结构" + response_schema: "响应体结构" + + file_changes: + new_files: ["需要新建的文件路径"] + modified_files: ["需要修改的文件路径"] + deleted_files: ["需要删除的文件路径"] + + impact_analysis: + affected_modules: ["受影响的模块"] + breaking_changes: ["破坏性变更"] + migration_needed: false + +# 关键决策 +decisions: + - decision: "决策内容" + reason: "理由" + alternatives: ["考虑过的替代方案"] + +# 风险点 +risks: + - description: "风险描述" + probability: "high|medium|low" + mitigation: "缓解措施" + +open_issues: [] +``` + +--- + +## ③ UI设计产物(v2.1新增) + +```yaml +stage: ui_design +version: "1.0" +timestamp: "{{ISO_TIMESTAMP}}" + +artifacts: + style_reference: "设计风格参考(如 微信原生风格/Material Design/Ant Design)" + + design_tokens: + colors: + primary: "主色 (如 #07C160)" + primary_light: "主色浅 (如 #E8F8EE)" + secondary: "辅助色" + background: "背景色" + surface: "卡片/面板背景色" + text_primary: "主文字色" + text_secondary: "次要文字色" + text_hint: "提示文字色" + border: "边框色" + error: "错误色" + success: "成功色" + warning: "警告色" + typography: + font_family: "字体" + heading_1: "标题1样式" + heading_2: "标题2样式" + body: "正文样式" + caption: "说明文字样式" + spacing: + page_padding: "页面内边距" + card_padding: "卡片内边距" + section_gap: "区块间距" + item_gap: "列表项间距" + border_radius: + card: "卡片圆角" + button: "按钮圆角" + input: "输入框圆角" + avatar: "头像圆角" + shadows: + card: "卡片阴影" + elevated: "浮起阴影" + + component_styles: + - name: "组件名(如 DoctorCard)" + description: "组件用途" + tailwind_classes: "具体的Tailwind类名组合" + states: + default: "默认状态样式" + hover: "悬停状态样式(如有)" + active: "按下状态样式(如有)" + disabled: "禁用状态样式(如有)" + + page_layouts: + - page: "页面路径(如 /departments/[id])" + structure: "页面结构描述" + key_elements: ["页面包含的关键UI元素"] + + interaction_notes: + - element: "交互元素" + behavior: "交互行为描述" + +# 自然语言摘要 +summary: "设计方案一句话总结" + +open_issues: [] +``` + +--- + +## ④ 编码实现产物 + +```yaml +stage: implementation +version: "1.0" +timestamp: "{{ISO_TIMESTAMP}}" + +artifacts: + files_changed: + - path: "文件路径" + action: "created|modified|deleted" + description: "变更说明" + + implementation_notes: + approach: "实现思路简述" + key_decisions: ["实现中的关键决策"] + deviations_from_design: ["与设计方案的偏差及原因"] + + dependencies_added: + - name: "依赖名" + version: "版本" + reason: "添加原因" + + commands_to_run: + build: "构建命令" + start: "启动命令(如有)" + +# 自检结果 +self_check: + compiles: true + lint_passes: true + basic_smoke_test: "描述基本冒烟验证结果" + +open_issues: [] +``` + +--- + +## ⑤ 代码审查产物 + +```yaml +stage: code_review +version: "1.0" +timestamp: "{{ISO_TIMESTAMP}}" + +artifacts: + verdict: "APPROVED|REQUEST_CHANGES" + + issues: + - id: "CR-1" + severity: "CRITICAL|IMPORTANT|MINOR" + category: "security|correctness|performance|maintainability|convention|testing" + file: "文件路径" + line: 42 + description: "问题描述" + suggestion: "修改建议" + confidence: 0.9 + + dimensions_checked: + security: {score: "PASS|WARN|FAIL", notes: ""} + correctness: {score: "PASS|WARN|FAIL", notes: ""} + performance: {score: "PASS|WARN|FAIL", notes: ""} + maintainability: {score: "PASS|WARN|FAIL", notes: ""} + convention: {score: "PASS|WARN|FAIL", notes: ""} + test_coverage: {score: "PASS|WARN|FAIL", notes: ""} + + # 信息隔离声明 + review_context: + saw_implementation_prompt: false # 审查者不应看到编码prompt + saw_only: ["代码变更(git diff)", "需求文档", "技术方案"] + +open_issues: [] +``` + +--- + +## ⑥ 测试验证产物 + +```yaml +stage: testing +version: "1.0" +timestamp: "{{ISO_TIMESTAMP}}" + +artifacts: + verdict: "ALL_PASS|PARTIAL_FAIL|ALL_FAIL" + + test_layers: + unit: + total: 0 + passed: 0 + failed: 0 + skipped: 0 + coverage_percent: 0 + test_files: ["测试文件路径"] + integration: + total: 0 + passed: 0 + failed: 0 + skipped: 0 + test_files: [] + smoke: + total: 0 + passed: 0 + failed: 0 + description: "冒烟测试说明" + + failed_tests: + - test_name: "失败的测试名" + layer: "unit|integration|smoke" + error_message: "错误信息" + root_cause: "初步分析" + suggested_fix: "建议修复方式" + + coverage: + line_percent: 0 + branch_percent: 0 + function_percent: 0 + meets_threshold: true + + regression_check: + existing_tests_still_pass: true + broken_tests: [] + +open_issues: [] +``` + +--- + +## ⑦ 部署上线产物 + +```yaml +stage: deployment +version: "1.0" +timestamp: "{{ISO_TIMESTAMP}}" + +artifacts: + deployment_method: "描述部署方式" + environment: "production|staging|development" + + steps_executed: + - step: "步骤描述" + status: "success|failed" + output: "关键输出" + + verification: + service_running: true + health_check_passed: true + smoke_test_passed: true + key_features_verified: ["已验证的核心功能"] + + rollback_plan: + method: "回滚方式" + command: "回滚命令" + +open_issues: [] +``` diff --git a/hermes-agent/publish/registry.json b/hermes-agent/publish/registry.json index 11e7e24..70cc2d9 100644 --- a/hermes-agent/publish/registry.json +++ b/hermes-agent/publish/registry.json @@ -1,5 +1,16 @@ { "framework": "hermes-agent", - "skills": [], - "lastUpdated": "2026-07-01" + "skills": [ + { + "name": "dev-pipeline-universal", + "version": "1.0.0", + "description": "通用研发流水线 — 从需求分析到功能上线的全流程 Agent 协作方案", + "author": "马总管", + "source": "archives/dev-pipeline-universal-v1.0.0.tar.gz", + "importedAt": "2026-07-02", + "platform": "local", + "note": "SkillHub 暂不支持 Hermes Agent,仅本地管理" + } + ], + "lastUpdated": "2026-07-02" } diff --git a/hermes-agent/skills/dev-pipeline-universal/CHANGELOG.md b/hermes-agent/skills/dev-pipeline-universal/CHANGELOG.md new file mode 100644 index 0000000..7a22f9e --- /dev/null +++ b/hermes-agent/skills/dev-pipeline-universal/CHANGELOG.md @@ -0,0 +1,8 @@ +# Changelog + +## 1.0.0 - 2026-06-30 + +- 初始版本(由外部导入) +- 来源:archives/dev-pipeline-universal-v1.0.0.tar.gz +- 作者:马总管 +- 通用研发流水线:从需求分析到功能上线的全流程 Agent 协作方案 diff --git a/hermes-agent/skills/dev-pipeline-universal/README.md b/hermes-agent/skills/dev-pipeline-universal/README.md new file mode 100644 index 0000000..bbef7b6 --- /dev/null +++ b/hermes-agent/skills/dev-pipeline-universal/README.md @@ -0,0 +1,60 @@ +# 🔧 通用研发流水线技能包 + +> 版本: v1.0.0 | 适用: Hermes Agent / OpenClaw / AgentSkills 兼容平台 + +## 简介 + +一套完整的研发流水线技能包,覆盖从需求分析到功能上线的全流程。包含: + +- **7 个阶段**:需求分析 → 技术方案 → UI设计(可选) → 编码实现(结对) → 代码审查 → 测试验证 → 部署上线 +- **4 道质量门禁**:确保每个阶段产出质量 +- **7 个角色**:总管、架构师、设计师、主程序员、结对程序员、审查员、测试员 +- **测试分层策略**:单元测试 + 集成测试 + 冒烟测试 +- **实战陷阱文档**:FastAPI、前端构建、Excel导入等 + +## 安装 + +### OpenClaw + +```bash +# 复制到 OpenClaw 技能目录 +cp -r dev-pipeline-universal ~/.openclaw/skills/dev-pipeline + +# 或复制到工作区技能目录(更高优先级) +cp -r dev-pipeline-universal /skills/dev-pipeline +``` + +### Hermes Agent + +```bash +# 复制到 Hermes 技能目录 +cp -r dev-pipeline-universal ~/.hermes/skills/software-development/dev-pipeline +``` + +## 使用前配置 + +1. 复制 `references/roles.example.yaml` 为 `references/roles.yaml` +2. 修改模型名称为您实际可用的模型 +3. 根据您的技术栈调整测试框架配置 + +## 目录结构 + +``` +dev-pipeline-universal/ +├── SKILL.md # 主技能文档 +├── templates/ +│ └── stage-artifacts.md # 7阶段产物YAML模板 +├── references/ +│ ├── roles.example.yaml # 角色模型配置示例 +│ ├── quality-gates.md # 质量门禁详情 +│ ├── testing-strategy.md # 测试分层策略 +│ ├── fastapi-pitfalls.md # FastAPI 实战陷阱 +│ ├── frontend-build-optimization.md # 前端构建优化 +│ ├── operation-log-pattern.md # 操作日志系统模板 +│ ├── framework-comparison.md # AI框架调研对比 +│ ├── excel-data-import.md # Excel批量导入 +│ ├── revenue-allocation-pattern.md # 收益归属矩阵 +│ └── doc-sync-pattern.md # 文档同步模板 +└── scripts/ + └── show_roles.py # 角色对照表生成脚本 +``` diff --git a/hermes-agent/skills/dev-pipeline-universal/SKILL.md b/hermes-agent/skills/dev-pipeline-universal/SKILL.md new file mode 100644 index 0000000..807a33f --- /dev/null +++ b/hermes-agent/skills/dev-pipeline-universal/SKILL.md @@ -0,0 +1,378 @@ +--- +name: dev-pipeline +description: 通用研发流水线 — 从需求分析到功能上线的全流程 Agent 协作方案。定义角色、阶段、质量门禁、测试分层和流转规则。 +version: 1.0.0 +date: 2026-06-30 +author: 马总管 🐎 +metadata: + openclaw: + emoji: "🔧" + tags: [研发流程, subagent, 多模型协作, 流水线, devops, 质量门禁, 测试分层] + requires: + bins: [] + hermes: + tags: [研发流程, subagent, 多模型协作, 流水线, devops, 质量门禁, 测试分层] +--- + +# 通用研发流水线(Dev Pipeline) + +> **版本**: v1.0.0(通用版) +> **创建日期**: 2026-06-30 +> **维护者**: 马总管 🐎 +> **适用平台**: Hermes Agent / OpenClaw / 其他 AgentSkills 兼容平台 + +## 一、概述 + +组建一个完整的研发小单元,覆盖从需求分析到功能上线的全流程。由总管负责调度,通过 delegate_task / subagent 机制将各阶段任务分派给不同角色的子 Agent,每个角色使用最适合的模型。 + +### 流程总览 + +``` +用户(提需求) + │ + ▼ +┌──────────────────────────────────────────────┐ +│ ① 需求分析 — 总管 │ +│ 理解业务意图,输出结构化需求文档,跟用户确认 │ +└──────────┬───────────────────────────────────┘ + ▼ [QG1: 需求门禁] +┌──────────────────────────────────────────────┐ +│ ② 技术方案 — 架构师 │ +│ 读代码库 + 需求文档,输出设计方案 │ +│ 总管 review 方案,必要时跟用户确认 │ +└──────────┬───────────────────────────────────┘ + ▼ [QG2: 设计门禁] +┌──────────────────────────────────────────────┐ +│ ③ UI设计 — 设计师 (可选) │ +│ 输出设计规范(配色/字体/间距/组件样式代码) │ +│ 仅面向用户的项目需要,纯后端/API可跳过 │ +└──────────┬───────────────────────────────────┘ + ▼ +┌──────────────────────────────────────────────┐ +│ ④ 编码实现(结对编程模式,可选) │ +│ ④a 主程序员写代码 │ +│ ④b 结对程序员 review+改进 │ +│ 大型/中型启用结对,小型/热修复单程序员 │ +└──────────┬───────────────────────────────────┘ + ▼ [QG3: 编码门禁] +┌──────────────────────────────────────────────┐ +│ ⑤ 代码审查 — 审查员 │ +│ Review 代码变更,输出结构化审查报告 │ +│ ├─ REQUEST_CHANGES → 回到④让程序员修改 │ +│ └─ APPROVED → 进入下一阶段 │ +└──────────┬───────────────────────────────────┘ + ▼ +┌──────────────────────────────────────────────┐ +│ ⑥ 测试验证 — 测试员 │ +│ 分层编写测试(单元+集成+冒烟)并执行 │ +│ ├─ PARTIAL_FAIL → 回到④让程序员修复 │ +│ └─ ALL_PASS → 进入下一阶段 │ +└──────────┬───────────────────────────────────┘ + ▼ [QG4: 测试门禁] +┌──────────────────────────────────────────────┐ +│ ⑦ 部署上线 — 总管 │ +│ 构建、部署、验证,汇报结果给用户 │ +└──────────────────────────────────────────────┘ +``` + +### 角色定义 + +| 角色 | 代号 | 流程阶段 | 推荐模型类型 | +|------|------|---------|-------------| +| 🧑‍💼 总管 | PM | ①需求分析 ⑦部署上线 | 快速响应模型(日常对话) | +| 🏗️ 架构师 | ARCH | ②技术方案 | 强推理模型(复杂推理) | +| 🎨 设计师 | UI | ③UI设计 | 编码版模型(设计+编码) | +| 💻 主程序员 | DEV | ④编码实现 | 深度推理编码模型 | +| 👥 结对程序员 | DEV2 | ④编码实现(review) | 与主程序员不同家族模型 | +| 🔍 审查员 | REVIEW | ⑤代码审查 | 深度推理模型 | +| 🧪 测试员 | QA | ⑥测试验证 | Agent/Tool 能力强的模型 | + +**模型选择原则**: +- 编码/审查/测试使用**不同模型家族**,消除单模型偏见 +- 主程序员和结对程序员用不同厂商模型,交叉审视 +- 测试员与编码员信息隔离(测试员不看实现思路) + +### 流程裁剪规则 + +并非所有需求都必须走完全部阶段。由总管根据需求规模判断裁剪: + +| 需求规模 | 定义 | 走哪些阶段 | 结对编程 | 示例 | +|---------|------|-----------|---------|------| +| 🔴 大型 | 新功能/新模块/架构变更 | ①②③④⑤⑥⑦ 全流程 | ✅ 启用 | 新增模块、系统重构 | +| 🟡 中型 | 现有功能扩展/较复杂 Bug | ①④⑤⑥ 跳过②③设计 | ✅ 启用 | 加导出功能、修复复杂 Bug | +| 🟡 中型(含UI) | 现有功能扩展+UI改版 | ①③④⑤⑥ 跳过②方案设计 | ✅ 启用 | 界面改版、新增交互页面 | +| 🟢 小型 | 简单修改/配置变更 | ①④⑥ 最小流程 | ❌ 单程序员 | 改字段校验、加配置项 | +| ⚪ 微型 | 一行代码/纯配置 | 总管直接做,不 delegate | — | 改文案、调参数 | +| 🔥 热修复 | 线上紧急 Bug | ④⑥⑦ 跳过需求和审查 | ❌ 单程序员 | 线上崩溃、数据错误 | + +**裁剪原则**: +- ①需求分析(总管)永远不跳过——再小的需求也要先确认理解对了(热修复除外) +- ⑤代码审查在中型以上需求中必须执行 +- ⑥测试验证在有代码变更时必须执行(至少验证不破坏现有功能) +- 总管负责判断需求规模,有争议时向用户确认 + +### 项目目录规范(建议) + +- 所有研发项目统一放在 `~/projects-dev/` 下(可自定义) +- 每个项目一个子目录,git 初始化管理 +- 便于代码审查阶段做 diff 和回滚 + +## 二、质量门禁 + +> 详细规范见 `references/quality-gates.md` + +### 门禁总览 + +| 门禁 | 位置 | 关键检查 | 通过条件 | +|------|------|---------|---------| +| QG1 | 需求→设计 | 产物完整性、验收标准可测试、用户确认 | 全部通过 | +| QG2 | 设计→编码 | 文件变更清单、API与需求对齐 | 无阻断问题 | +| QG3 | 编码→审查 | 编译通过、lint通过、变更与设计一致 | 自检全通过 | +| QG4 | 测试→部署 | 测试全通过、覆盖率达标、无回归、用户确认 | 全部通过 | + +### 重试与超时机制 + +**重试策略:** +``` +第1次失败 → 同模型重试,附带失败原因 +第2次失败 → 换备用模型重试 +第3次失败 → 上报用户,进入人工介入 +``` + +**超时保护:** + +| 阶段 | 超时时间 | 超时处理 | +|------|---------|---------| +| ②设计 | 30分钟 | 终止,记录已有产出,人工介入 | +| ③编码 | 50分钟 | 终止,保留已写代码,人工介入 | +| ④审查 | 25分钟 | 终止,标记"审查超时",直接进测试 | +| ⑤测试 | 40分钟 | 终止,保留已有测试结果,人工介入 | + +## 三、阶段产物规范 + +> 完整模板见 `templates/stage-artifacts.md` + +每个阶段的子 Agent **必须**输出结构化 YAML 产物。总管负责校验产物格式。 + +### 产物设计原则 + +1. **结构化优先**:用 YAML Schema 约束,减少解析歧义 +2. **摘要辅助**:每个产物附带自然语言摘要,帮助 LLM 快速定位 +3. **决策可追溯**:记录关键决策的理由和替代方案 +4. **问题前传**:显式列出 open_issues,确保下游关注 +5. **信息隔离**:审查员不看编码 prompt,测试员不看实现思路 + +### 产物传递规则 + +``` +① 需求产物 ──→ ②架构师(完整) + ④程序员(验收标准) +② 设计产物 ──→ ③设计师(页面/组件清单) + ④程序员(完整)+ ⑤审查员(摘要+文件清单) +③ UI设计产物 ──→ ④程序员(完整设计规范+组件样式) +④ 编码产物 ──→ ⑤审查员(git diff + 产物) + ⑥测试员(签名+验收标准) +⑤ 审查产物 ──→ ④程序员(如需修改:issues列表) +⑥ 测试产物 ──→ ④程序员(如有失败:failed_tests)/ ⑦总管(如全通过) +``` + +**关键**:测试员只接收接口签名和验收标准,不接收编码思路和实现 prompt。 + +## 四、测试分层策略 + +> 详细规范见 `references/testing-strategy.md` + +### 测试金字塔 + +``` + ╱╲ + ╱ 冒烟 ╲ ← 5-10% + ╱────────╲ + ╱ 集成测试 ╲ ← 20-30% + ╱──────────────╲ + ╱ 单元测试 ╲ ← 60-70% + ╱──────────────────╲ +``` + +### 覆盖率阈值 + +| 项目规模 | 行覆盖 | 分支覆盖 | 函数覆盖 | +|---------|--------|---------|---------| +| 大型(新项目) | ≥ 70% | ≥ 60% | ≥ 80% | +| 中型(新功能) | ≥ 60% | ≥ 50% | ≥ 75% | +| 小型(bug修复) | 修改行100% | — | — | + +## 五、各阶段执行规范 + +### ① 需求分析(总管直接执行) + +**输入**: 用户的口头/文字需求 +**输出**: 结构化需求产物(见 `templates/stage-artifacts.md` ①) + +**规则**: 必须跟用户确认需求文档后才进入下一阶段。 + +### ② 技术方案(delegate → 架构师) + +**输入**: 需求产物(完整) + 现有代码库上下文 +**输出**: 结构化设计产物(见 `templates/stage-artifacts.md` ②) + +**规则**: 总管 review 方案,重大决策需跟用户确认。 + +### ③ UI设计(delegate → 设计师)— 可选 + +**适用条件**: 面向用户的项目(H5、小程序、Web应用)。纯后端/API/CLI项目跳过此阶段。 + +**输入**: 需求产物 + 技术方案中的页面/组件清单 + 用户指定的风格偏好 +**输出**: 结构化UI设计产物(见 `templates/stage-artifacts.md` ③) + +**设计产物包含**: +1. 设计规范(Design Token):配色、字体、间距、圆角、阴影 +2. 组件样式清单:每个组件的具体 CSS/Tailwind 类名 +3. 页面布局描述:各页面的结构和组件组合方式 +4. 交互说明:关键交互的状态变化 + +**规则**: +- 设计师不需要画图,输出可直接使用的代码级设计规范 +- 风格偏好由用户指定(如微信风格、Material Design 等) +- 设计规范以 Tailwind CSS 类名为主要表达方式 + +### ④ 编码实现(结对编程模式,可选) + +**模式**: 主程序员写代码 → 结对程序员 review+改进 → 产出最终代码 + +**④a 主程序员(delegate)** + +**输入**: 技术方案产物(完整) + UI设计产物(如有) + 需求产物中的验收标准 +**输出**: 实现代码 + 结构化编码产物(见 `templates/stage-artifacts.md` ④) + +**④b 结对程序员(delegate)— 大型/中型项目启用** + +**输入**: 主程序员产出的代码(git diff) + 技术方案摘要 + 验收标准 +**输出**: review 意见 + 改进后的代码 + +**结对编程规则**: +- 大型/中型项目:必须启用结对,主程序员写完 → 结对程序员 review+改进 +- 小型/热修复:单主程序员即可,跳过④b +- 结对程序员的改动也会进入⑤代码审查,形成三道审视(结对→审查→测试) +- 结对程序员不重写代码,只做 review 和针对性改进 + +**规则**: +- 一次只实现一个功能点,避免大规模变更 +- 单次 delegate 涉及文件 ≤ 10 个,超过则拆分 +- 严禁在前台运行常驻进程(如 `npm run dev`),必须后台运行 +- 完成后必须运行 `git add -A && git commit` + +### ⑤ 代码审查(delegate → 审查员) + +**输入**: 代码变更(git diff) + 需求摘要 + 技术方案摘要(**不含编码 prompt**) +**输出**: 结构化审查产物(见 `templates/stage-artifacts.md` ⑤) + +**审查维度(七维度)**: + +| 维度 | 严重级别 | 检查重点 | +|------|---------|---------| +| 安全性 | 🔴 阻断 | SQL注入、XSS、硬编码密钥、路径遍历 | +| 正确性 | 🔴 阻断 | 逻辑错误、边界条件、空值处理、资源泄露 | +| 数据契约 | 🔴 阻断 | 前端 TS 接口与 API 实际返回字段一致性 | +| 性能 | 🟡 警告 | 算法复杂度、N+1查询、内存泄漏 | +| 可维护性 | 🟡 警告 | 函数长度、命名规范、DRY原则 | +| 规范 | 🟢 建议 | 代码风格、项目约定 | +| 测试 | 🟡 警告 | 测试覆盖、Mock合理性 | + +**规则**: 审查不通过 → 问题反馈给程序员修改 → 修改后重新审查。最多 3 轮。 + +### ⑥ 测试验证(delegate → 测试员) + +**输入**: 接口签名 + 验收标准(**不含实现思路和编码 prompt**) +**输出**: 测试代码 + 结构化测试产物(见 `templates/stage-artifacts.md` ⑥) + +**规则**: 测试不通过 → 失败信息反馈给程序员修复 → 修复后重新测试。最多 3 轮。 + +### ⑦ 部署上线(总管直接执行) + +**输入**: 通过审查和测试的代码 +**输出**: 结构化部署产物(见 `templates/stage-artifacts.md` ⑦) + +**规则**: 部署前跟用户确认。部署后验证核心功能。 + +## 六、设计理念与参考文献 + +### 核心设计理念 + +| 理念 | 来源 | 落地方式 | +|------|------|---------| +| SOP驱动+结构化输出 | MetaGPT (arXiv:2308.00352) | 7阶段YAML产物模板 | +| 测试与编码分离 | AgentCoder (arXiv:2312.13010) | 不同模型+信息隔离 | +| 多模型交叉审查 | 业界最佳实践 | 编码/审查/测试各用不同模型家族 | +| Task级重试 | CrewAI | 每阶段 max 3 次+备用模型降级 | +| 事件流快照 | OpenHands | git checkpoint 用于崩溃恢复 | +| ACI精简工具 | SWE-agent | 子 agent 按需分配最小工具集 | + +### 参考文献 + +1. MetaGPT — SOP驱动多角色协作,结构化中间产物减少30%信息损失 +2. AgentCoder — 独立测试Agent比自测通过率高12-18% +3. ChatDev — 角色扮演对话提升20%完成率 +4. SWE-bench — 60%修复失败源于定位错误,强调代码搜索能力 +5. Agentless — 简单流水线有时比复杂Agent更有效 + +> 完整框架对比调研见 `references/framework-comparison.md` + +## 七、实战陷阱与最佳实践 + +### 子 Agent 超时恢复模式 + +子 Agent 可能在执行过程中超时,但代码文件可能已经写入。超时后总管应执行以下恢复步骤: + +1. **检查文件系统** — 查看已生成的文件 +2. **检查 git 状态** — 确认子 Agent 是否已自动 commit +3. **验证后端** — 启动服务并测试 API 端点 +4. **验证前端** — 确认构建通过 +5. **修复关键问题** — 子 Agent 超时前可能来不及处理边界情况 +6. **提交修复** — 完成收尾 + +超时不代表失败——子 Agent 可能完成了 80% 的工作,总管收尾比重新 delegate 更高效。 + +### 前后端数据契约不一致(高频致命问题) + +程序员 Agent 同时写 API 和前端时,TypeScript 接口定义经常与 API 实际返回字段对不上,导致客户端 JS 崩溃。 + +**防范措施**: +1. 编码完成后,总管用 curl API 抓取实际响应 +2. 对比前端 TypeScript 接口定义与 API 实际字段 +3. 重点检查:字段名差异、字段是否存在、类型是否匹配 +4. 对可能为 undefined 的字段,检查是否有安全访问(`?.`、`|| 默认值`) + +### 常驻进程防护规则 + +子 Agent 禁止前台运行 `npm run dev` / `next start` / `python -m http.server` 等常驻命令,必须后台运行或设超时。违反此规则会导致整个 delegation 链路卡死。 + +### 代码修改必须提交后再通知构建 + +修改代码后,必须先 `git status` 确认已 staging、`git log --oneline -1` 确认已提交,再通知用户触发 CI/CD。本地工作区的修改不会自动进入远程仓库。 + +## 八、附带参考文档 + +本技能包附带以下参考文档,按通用性分类: + +### 通用技术参考(适用于任何项目) + +| 文档 | 内容 | +|------|------| +| `references/fastapi-pitfalls.md` | FastAPI 实战陷阱(路由顺序、N+1、NULL处理等) | +| `references/frontend-build-optimization.md` | Vite 代码分割 + 路由懒加载优化 | +| `references/operation-log-pattern.md` | 操作日志系统四层架构模板 | +| `references/testing-strategy.md` | 测试分层策略详情 | +| `references/quality-gates.md` | 质量门禁详情 | +| `references/framework-comparison.md` | AI 编码框架调研对比 | + +### 业务模式参考(按需选用) + +| 文档 | 适用场景 | +|------|---------| +| `references/excel-data-import.md` | 从 Excel 批量导入业务数据 | +| `references/revenue-allocation-pattern.md` | 人×项目收益归属矩阵 | +| `references/doc-sync-pattern.md` | 里程碑文档同步到仓库 | + +## Changelog + +| 版本 | 日期 | 变更内容 | +|------|------|---------| +| v1.0.0 | 2026-06-30 | 通用版首发。剥离环境特定信息(API key、服务器IP、具体项目名),保留通用流水线逻辑。适配 OpenClaw/Hermes 等多平台。 | diff --git a/hermes-agent/skills/dev-pipeline-universal/references/doc-sync-pattern.md b/hermes-agent/skills/dev-pipeline-universal/references/doc-sync-pattern.md new file mode 100644 index 0000000..cf53f4b --- /dev/null +++ b/hermes-agent/skills/dev-pipeline-universal/references/doc-sync-pattern.md @@ -0,0 +1,59 @@ +# 里程碑文档同步模式(通用模板) + +**创建日期**: 2026-06-30 +**适用场景**: MVP/里程碑完成后,需要同步代码和文档到远程仓库 + +--- + +## 触发条件 + +- 重大功能完成(如 MVP v1.0) +- 里程碑文档创建完成 +- 需要备份/共享项目文档 + +## 同步流程 + +### 步骤 1: 代码和里程碑文档 → 远程仓库 + +```bash +# 进入项目目录 +cd <项目目录> + +# 查看未跟踪文件 +git status + +# 添加里程碑文档和关键代码 +git add milestone/ <其他关键文件> + +# 提交 +git commit -m "feat: <版本> <功能描述> + +- <成果1> +- <成果2>" + +# 推送到远程仓库 +git push origin <分支> +``` + +### 步骤 2: 核心文档 → 文档库(可选) + +如有独立的文档仓库,同步核心 .md 文档: + +```bash +# 进入文档库 +cd <文档库目录> + +# 复制核心文档 +cp -r <项目目录>/milestone/ <文档库目录>/<项目名>/ + +# 提交 +git add <项目名>/ +git commit -m "feat: 添加 <项目名> <版本> 里程碑文档" +git push origin main +``` + +## 注意事项 + +1. **先主仓库后文档库** — 确保代码和文档先在版本控制中 +2. **选择性同步** — 文档库只同步核心 .md 文档,不同步二进制/大文件 +3. **milestone 命名** — 格式 `YYYY-MM-DD-v<版本>-<标签>` diff --git a/hermes-agent/skills/dev-pipeline-universal/references/excel-data-import.md b/hermes-agent/skills/dev-pipeline-universal/references/excel-data-import.md new file mode 100644 index 0000000..f3e3720 --- /dev/null +++ b/hermes-agent/skills/dev-pipeline-universal/references/excel-data-import.md @@ -0,0 +1,177 @@ +# Excel 数据导入实战参考 + +> **适用场景**: MVP/里程碑完成后,从业务 Excel 报表批量导入测试数据做效果验证 +> **创建日期**: 2026-06-24 +> **更新日期**: 2026-06-30 + +--- + +## 两种导入方式 + +### 方式一:CLI 脚本(适合首次全量导入) + +`scripts/import_excel_data.py` — 从文件系统读取 Excel,一次性导入全部数据。 + +**优点**: 无网络开销,可调试,适合大数据量 +**缺点**: 需要服务器文件系统访问权限 + +### 方式二:Web API(适合日常增量导入) + +`POST /api/import/excel` — 前端上传 Excel 文件,后端解析导入。 + +**优点**: 浏览器操作,无需服务器登录,有导入结果统计 +**缺点**: 文件大小受 HTTP 限制,大文件上传慢 + +**前端页面**: `/import` 路径,拖拽上传 + 导入结果展示 + +**API 端点**: +```python +@router.post("/api/import/excel") +async def import_excel(file: UploadFile = File(...), db: Session = Depends(get_db)): + # 保存临时文件 → openpyxl 解析 → 导入各表 → 删除临时文件 +``` + +--- + +## 核心挑战 + +业务 Excel 通常有 15-20 个 sheet,列布局因项目而异,且存在公式、合并单元格、同名项目等陷阱。一次性全量导入比逐条录入高效百倍,但需要处理以下问题。 + +--- + +## 实战陷阱与对策 + +### 1. 列布局因 sheet 而异 + +每个项目明细 sheet 的列数不同: + +| Sheet | 列布局 | 人日列 | 描述列 | +|-------|--------|:------:|:------:| +| 标准 | 序号\|模块\|功能项\|人日\|负责人\|占比\|... | col 3 | — | +| 工健健康小屋 | 序号\|模块\|功能项\|说明1\|详细说明\|人日\|负责人\|... | col 5 | col 4 | +| 基层社区AI医助 | 序号\|模块\|功能项\|描述\|人日\|负责人\|... | col 4 | col 3 | +| 汤原县AI医助 | 序号\|功能项\|描述\|人日\|负责人\|... | col 3 | col 2(无模块列) | + +**对策**: 为每个 sheet 定义独立的列映射配置,而非通用解析逻辑。 + +```python +sheet_configs = [ + ("项目-百度-珠江医院", "2026-BD-1", 1, 2, 3, 4, None, [...]), + ("项目-工健健康小屋", "2026-YZ-1", 1, 2, 5, 6, 4, [...]), + ("项目-汤原县AI医助", "2026-AI-2", None, 1, 3, 4, 2, [...]), +] +``` + +### 2. 同名项目(不同项目编号) + +Excel 中可能有多个同名项目(如"南方医科大学珠江医院"有 `20260205-A` 和 `2026-BD-1` 两个编号)。用 `project_name` 做 dict key 会覆盖。 + +**对策**: 始终用 `project_code` 做映射,不要用 `project_name`。 + +```python +projects_by_code = {p.project_code: {"name": p.project_name, "id": p.id} for p in db.query(Project).all()} +``` + +### 3. 人员不在人员概况 sheet 中 + +新 Excel 可能新增了人员(如"陈天然"),但只出现在收益分析 sheet 中,不在人员概况 sheet 里。 + +**对策**: 扫描所有 sheet 发现新人员,手动补加到人员表。 + +### 4. 公式字段 openpyxl 读不到 + +Excel 中的 `=SUM(...)`、`=C2/D2` 等公式,openpyxl 读取时返回公式字符串而非计算结果。 + +**对策**: +- 预期收益从收益分析 sheet 的"总计"行读取(那里是数值) +- 投产比等计算字段在数据库端用 ROI 计算器重新计算 + +### 5. 自由文本 → 结构化关联 + +"人员项目负荷情况" sheet 的工作描述是自由文本(如"1、百度医院智能体-南方医科大学珠江医院-近一个月工作占比50%"),需要从中提取项目关联和分配比例。 + +**对策**: 两阶段匹配: +1. 精确匹配:项目全名在文本中 +2. 关键词回退:`"健康小屋" → "工会健康小屋"`, `"AI医助" → "佳木斯中医院AI医助"` + +分配比例从文本中 `占比(\d+)%` 正则提取,无比例时按项目关联人数均分。 + +### 6. 增量更新 vs 全量重来 + +**原则**: 首次导入用全量清空重来;后续更新用增量 upsert(按 project_code/personnel_id 匹配)。 + +**增量 upsert 模式**: +```python +existing = db.query(Model).filter(Model.code == code).first() +if existing: + for key, val in new_data.items(): + setattr(existing, key, val) +else: + db.add(Model(**new_data)) +``` + +--- + +### 7. openpyxl 样式解析 bug(TypeError: expected Fill) + +openpyxl 3.1.5 在解析某些 Excel 文件的 `styles.xml` 时,遇到不兼容的 Fill 样式对象会抛出 `TypeError: expected `。 + +**无效尝试**: +- `data_only=True` — 只影响公式计算,不跳过样式解析 +- `read_only=True` — 同样需要解析样式表 +- 升级 openpyxl — 3.1.5 是当前最新版,bug 尚未修复 + +**根治方案**:改用 **python-calamine**(Rust 实现的 Excel 解析器),它完全不解析样式,只读数据。 + +```python +from python_calamine import CalamineWorkbook + +wb = CalamineWorkbook.from_path(path) +sheets = wb.sheet_names +ws = wb.get_sheet_by_name("Sheet1") +rows = list(ws.to_python()) # 返回 list[list],每个 cell 是 Python 原生类型 +``` + +**注意事项**: +- `python-calamine` 返回的单元格值是 Python 原生类型(float/int/str/None),无需额外转换 +- 不解析公式,返回的是缓存的计算结果(与 `data_only=True` 类似) +- 不支持写 Excel,只用于读取 +- 安装:`pip install python-calamine` 或加到 requirements.txt + +**⚠️ employee_id 空值陷阱**: +`python-calamine` 返回的空单元格是 `None`,但 Excel 中写了空字符串的单元格也会被 `str(val).strip()` 转为空字符串。用 `clean()` 函数处理时,空字符串会变成 `None`,导致 NOT NULL 约束失败。 + +```python +# ❌ 错误:clean(row[2]) 对空单元格返回 None +emp_id = clean(row[2]) if len(row) > 2 else f"EMP{name}" + +# ✅ 正确:显式检查 clean() 结果是否为空 +emp_id = clean(row[2]) if len(row) > 2 and clean(row[2]) else f"EMP{name}" +``` + +**规律**:任何 `clean()` 的返回值都可能为 `None`,不能因为列存在就假定值非空。在 NOT NULL 字段上使用 `clean()` 时,必须加 `and clean(val)` 二次检查。 + +**Web API 中的完整模式**: +```python +tmp = tempfile.NamedTemporaryFile(delete=False, suffix=".xlsx") +try: + content = await file.read() + tmp.write(content) + tmp.close() + wb = CalamineWorkbook.from_path(tmp.name) + # ... 解析各 sheet ... +finally: + os.unlink(tmp.name) +``` + +--- + +## 导入后验证清单 + +- [ ] 项目数是否匹配 Excel 项目概况行数 +- [ ] 人员数是否覆盖所有出现的人名 +- [ ] 预期收益是否与 Excel 收益分析 sheet 的"总计"行一致 +- [ ] WBS 任务数是否合理(每个项目应有 >0 条) +- [ ] 人员-项目关联数是否覆盖主要参与关系 +- [ ] 收益矩阵 API 返回的数据与 Excel 收益分析 sheet 交叉验证 +- [ ] 仪表盘 OKR 完成率是否与 Excel 部门概况一致 diff --git a/hermes-agent/skills/dev-pipeline-universal/references/fastapi-pitfalls.md b/hermes-agent/skills/dev-pipeline-universal/references/fastapi-pitfalls.md new file mode 100644 index 0000000..4f82b06 --- /dev/null +++ b/hermes-agent/skills/dev-pipeline-universal/references/fastapi-pitfalls.md @@ -0,0 +1,315 @@ +# FastAPI 实战陷阱与最佳实践 + +> **适用于 dev-pipeline ④编码实现阶段。程序员(主程序员/结对程序员)在编写 FastAPI 代码时必须注意以下陷阱。 + +--- + +## 1. 路由注册顺序 + +### 问题 +FastAPI 按注册顺序匹配路由。**具体路由必须在参数化路由之前注册**,否则会被错误匹配。 + +```python +# ❌ 错误:/{personnel_id} 先注册,/workload 被匹配为 personnel_id="workload" +@router.get("/{personnel_id}") # 第63行 +def get_personnel(...) + +@router.get("/{personnel_id}/workload") # 第151行 → 永远匹配不到 +def get_personnel_workload(...) + +# ✅ 正确:具体路由先注册 +@router.get("/{personnel_id}/workload") # 先注册 +def get_personnel_workload(...) + +@router.get("/{personnel_id}") # 后注册 +def get_personnel(...) +``` + +### 排查方法 +当某个路由返回 404 但确信路径正确时: +1. 检查路由注册顺序(`grep -n "@router\." file.py`) +2. 确认具体路由(含固定路径段)在参数化路由之前 + +### 同类陷阱 +- `/milestones/all` 必须在 `/{project_id}/milestones` 之前 +- `/tasks/all` 必须在 `/{project_id}/tasks` 之前 +- `/export/projects` 必须在 `/{project_id}` 之前 + +--- + +## 2. Excel 导出中文文件名编码 + +### 问题 +`Content-Disposition: attachment; filename=中文.xlsx` 中的中文字符在 Starlette TestClient 中触发 `UnicodeEncodeError`,某些浏览器也无法正确解析。 + +### 修复 +使用 RFC 5987 编码: + +```python +from urllib.parse import quote + +def _excel_response(wb, filename): + output = io.BytesIO() + wb.save(output) + output.seek(0) + encoded_filename = quote(filename) + return StreamingResponse( + output, + media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", + headers={"Content-Disposition": f"attachment; filename*=UTF-8''{encoded_filename}"}, + ) +``` + +### 测试注意事项 +- Starlette TestClient 的 `UnicodeEncodeError` 是已知问题,测试中需 try/except 捕获 +- 验证 Excel 内容时检查 `content[:2] == b"PK"`(ZIP 签名)即可 +- 用 `openpyxl.load_workbook(io.BytesIO(resp.content))` 验证内容正确性 + +--- + +## 3. 依赖声明 + +### 问题 +新增 Python 依赖(如 `openpyxl`)后忘记更新 `requirements.txt`,导致部署时崩溃。 + +### 规则 +每次④编码实现阶段新增依赖后,必须: +1. 确认依赖已安装(`pip list | grep `) +2. 更新 `requirements.txt`(`pip freeze | grep >> requirements.txt` 或手动添加) +3. 结对程序员 review 时检查 requirements.txt 变更 + +--- + +## 4. SQLAlchemy N+1 查询 + +### 问题 +遍历 ORM 对象时访问关联属性会触发额外 SQL 查询。 + +```python +# ❌ N+1:对每个任务查一次 project +for task in tasks: + project_name = task.project.project_name # 触发额外 SQL + +# ✅ 修复:使用 joinedload 批量加载 +from sqlalchemy.orm import joinedload +tasks = db.query(ProjectTask).options(joinedload(ProjectTask.project)).all() +``` + +### 批量查询替代方案 +当无法使用 joinedload 时,用 `IN` 查询替代循环查询: + +```python +# ❌ N+1 +for task in tasks: + progress = db.query(TaskMonthlyProgress).filter( + TaskMonthlyProgress.task_id == task.id + ).first() + +# ✅ 批量 +all_progress = db.query(TaskMonthlyProgress).filter( + TaskMonthlyProgress.task_id.in_(task_ids) +).all() +task_latest = {p.task_id: p for p in all_progress} +``` + +--- + +## 5. SQLAlchemy NULL 处理 + +### 问题 +SQLAlchemy 中 `column < 100` 遇到 NULL 时返回 UNKNOWN(不匹配),导致 NULL 值被遗漏。 + +```python +# ❌ 遗漏 overall_progress IS NULL 的任务 +tasks = db.query(ProjectTask).filter(ProjectTask.overall_progress < 100).all() + +# ✅ 正确:显式处理 NULL +from sqlalchemy import or_ +tasks = db.query(ProjectTask).filter( + or_(ProjectTask.overall_progress < 100, ProjectTask.overall_progress.is_(None)) +).all() +# 或使用 | 运算符(注意括号) +tasks = db.query(ProjectTask).filter( + (ProjectTask.overall_progress < 100) | (ProjectTask.overall_progress.is_(None)) +).all() +``` + +--- + +## 6. 前端导出绕过认证 + +### 问题 +用 `` 标签直接访问 API 路径会跳过 axios 的 `Authorization: Bearer` 拦截器,导致 401。 + +```javascript +// ❌ 错误:绕过认证 +const link = document.createElement('a') +link.href = '/api/reports/export/projects' +link.click() + +// ✅ 正确:通过 axios 获取 blob 后下载 +api.get('/reports/export/projects', { responseType: 'blob' }).then(res => { + const url = URL.createObjectURL(new Blob([res.data])) + const link = document.createElement('a') + link.href = url + link.download = 'filename.xlsx' + link.click() + URL.revokeObjectURL(url) +}) +``` + +### DRY 原则 +多个导出函数应提取为通用函数: + +```javascript +function downloadExcel(url, filename) { + exporting.value = true + api.get(url, { responseType: 'blob' }).then(res => { + const blobUrl = URL.createObjectURL(new Blob([res.data])) + const link = document.createElement('a') + link.href = blobUrl + link.download = filename + link.click() + URL.revokeObjectURL(blobUrl) + }).finally(() => { exporting.value = false }) +} +``` + +--- + +## 7. ECharts 生命周期管理 + +### 问题 +Vue 组件销毁时未释放 ECharts 实例导致内存泄漏;路由参数变化(如 `/personnel/1` → `/personnel/2`)时图表不刷新。 + +### 修复 +```javascript +import { onBeforeUnmount, onBeforeRouteUpdate } from 'vue-router' + +// 销毁时释放 +onBeforeUnmount(() => { + chart?.dispose() +}) + +// 路由参数变化时重新加载 +onBeforeRouteUpdate(() => { + chart?.dispose() + loadData() +}) +``` + +--- + +## 8. 浮点精度 + +### 问题 +Python 浮点累加可能产生尾数误差(如 `49.9999999` 而非 `50.0`)。 + +### 修复 +```python +# 在最终输出时统一 round +total = round(sum(values), 2) +``` + +--- + +## 10. Pydantic Schema 字段同步 + +### 问题 +后端 API 返回字典中新增了字段,但 Pydantic `response_model` schema 中没有声明,导致字段被静默丢弃。前端收到 `undefined`,页面渲染异常。 + +```python +# ❌ 后端返回了 project_count,但 PersonnelOut schema 没有这个字段 +class PersonnelOut(BaseModel): + id: int + name: str + # ... 没有 project_count → 被 Pydantic 过滤掉 + +# ✅ 必须在 schema 中声明 +class PersonnelOut(BaseModel): + id: int + name: str + project_count: Optional[int] = 0 + total_allocation: Optional[float] = 0.0 +``` + +### 排查方法 +当前端收到 `undefined` 但确信后端有返回时: +1. 去掉 `response_model` 参数,看原始返回是否包含该字段 +2. 检查 schema 定义是否包含新字段 +3. 注意 `from_attributes = True` 只影响 ORM→Pydantic 转换,不影响 dict→Pydantic 过滤 + +### 关联陷阱 +- 修改 `_build_personnel_dict` 等 helper 函数后,必须同步更新对应的 schema +- 结对程序员 review 时重点检查:helper 返回字段 ↔ schema 字段 的一致性 + +--- + +## 11. 部署验证脚本模式 + +### 问题 +部署验证时使用 shell 管道(`curl | python3 -c`)容易触发安全防护(命令超时/阻断),尤其是涉及变量引用和 URL 编码时。 + +### 推荐方案 +用 Python 脚本替代 shell 管道,一个文件完成全部验证: + +```python +#!/usr/bin/env python3 +import urllib.request, json + +BASE = "http://127.0.0.1:8001" + +def api(method, path, data=None, token=None): + url = BASE + path + headers = {"Content-Type": "application/json"} + if token: + headers["Authorization"] = f"Bearer {token}" + body = json.dumps(data).encode() if data else None + req = urllib.request.Request(url, data=body, headers=headers, method=method) + resp = urllib.request.urlopen(req, timeout=10) + return resp.status, resp.read() + +# 1. 登录 +status, data = api("POST", "/api/auth/login", {"username": "admin", "password": "admin123"}) +token = json.loads(data)["access_token"] + +# 2. 验证端点 +status, data = api("GET", "/api/projects?project_type=创新项目", token=token) +projects = json.loads(data) +print(f"类型筛选: {len(projects)}个") + +# 3. 验证 Excel 导出 +status, data = api("GET", "/api/reports/export/projects", token=token) +assert data[:2] == b"PK" # ZIP 签名 +import openpyxl, io +wb = openpyxl.load_workbook(io.BytesIO(data)) +print(f"导出: {wb.active.title}, {wb.active.max_row-1}行") +``` + +### 优势 +- 避免 shell 变量注入和管道超时 +- 可在虚拟环境中直接运行 +- 断言清晰,失败时立即知道哪个端点出问题 +- 可复用(保存为 `scripts/verify_deploy.py`) + +--- + +## 9. 时区一致性 + +### 问题 +项目中混用 timezone-naive 和 timezone-aware 的 datetime 导致比较偏差。 + +### 规范 +```python +from datetime import datetime, timezone + +# 统一使用 UTC aware datetime +now = datetime.now(timezone.utc) + +# 解析字符串时也设为 aware +from calendar import monthrange +parts = month_str.split("-") +y, m = int(parts[0]), int(parts[1]) +last_day = monthrange(y, m)[1] +progress_date = datetime(y, m, last_day, tzinfo=timezone.utc) +``` diff --git a/hermes-agent/skills/dev-pipeline-universal/references/framework-comparison.md b/hermes-agent/skills/dev-pipeline-universal/references/framework-comparison.md new file mode 100644 index 0000000..70c63a3 --- /dev/null +++ b/hermes-agent/skills/dev-pipeline-universal/references/framework-comparison.md @@ -0,0 +1,44 @@ +# AI 编码框架多代理协作调研(2026-04-19) + +> 本文档记录了 v2.0 设计决策的调研依据。用于未来架构演进参考。 + +## 三种多Agent协作范式 + +| 范式 | 代表框架 | 特点 | 我们的借鉴 | +|------|---------|------|-----------| +| **SOP驱动** | MetaGPT | 模拟软件公司,角色固定,结构化输出 | → 6阶段YAML产物模板 | +| **任务编排** | CrewAI | Agent/Task/Crew抽象,sequential/hierarchical | → delegate_task per-task模型路由 | +| **群聊协商** | AutoGen | GroupChat多Agent讨论,Manager分配 | 未采用(开销大) | + +## 框架与Hermes集成潜力排序 + +| 优先级 | 框架 | 集成方式 | 适合场景 | +|--------|------|---------|---------| +| 🥇 | **Aider** | 作为编码执行引擎 | git深度集成、repo map、双模型模式 | +| 🥈 | **CrewAI** | 借鉴编排模式 | Agent/Task/Crew抽象 | +| 🥉 | **MetaGPT** | 借鉴SOP+角色设计 | 结构化产物、发布订阅通信 | +| 4 | **OpenHands** | 借鉴事件流+浏览器能力 | 全栈开发(前端+后端) | +| 5 | **Claude Code** | 借鉴subagent+worktree并行 | 大任务并行编码 | + +## 关键学术发现(影响v2.0设计) + +| 论文 | 发现 | 落地到v2.0 | +|------|------|-----------| +| MetaGPT (2308.00352) | 结构化输出减少30%信息损失 | templates/stage-artifacts.md | +| AgentCoder (2312.13010) | 独立测试Agent比自测通过率高12-18% | 测试员信息隔离原则 | +| ChatDev (2307.07924) | 角色对话提升20%完成率,需设轮次上限 | 每阶段max 3轮重试 | +| SWE-bench | 60%失败源于定位错误 | 强调代码搜索能力(未来P2) | +| Agentless | 简单流水线有时比复杂Agent更好 | 小型需求总管直接做,不过度编排 | + +## 我们选择"不换框架"的理由 + +1. Hermes 的 `delegate_task` + custom_providers 已是成熟的多Agent编排 +2. 已有5角色6阶段,与MetaGPT的SOP模式架构等价 +3. 完全开源、模型灵活(火山方舟9个模型可切换)、可控性最高 +4. 不引入额外框架依赖,降低维护成本 + +## 未来演进方向(P2+) + +- **短期**: 集成 Aider 的 repo map(tree-sitter AST索引)提升代码定位能力 +- **中期**: 借鉴 Claude Code worktree 并行模式,大任务拆分后多分支并行编码 +- **长期**: 代码库向量索引(RAG),经验池积累成功案例 diff --git a/hermes-agent/skills/dev-pipeline-universal/references/frontend-build-optimization.md b/hermes-agent/skills/dev-pipeline-universal/references/frontend-build-optimization.md new file mode 100644 index 0000000..5fc248c --- /dev/null +++ b/hermes-agent/skills/dev-pipeline-universal/references/frontend-build-optimization.md @@ -0,0 +1,94 @@ +# 前端构建优化(Vite 代码分割 + 路由懒加载) + +> 适用于 Vue 3 + Vite 项目,Element Plus + ECharts 技术栈 + +## 问题 + +Vue 3 + Element Plus + ECharts 项目构建后,默认所有代码打包成一个 JS 文件(通常 2~3MB),首屏加载全量代码,严重影响首次加载速度。 + +## 优化方案 + +### 1. Vite `manualChunks` 拆包 + +在 `vite.config.js` 中配置 `build.rollupOptions.output.manualChunks`,将大体积第三方库拆为独立 chunk: + +```js +// vite.config.js +export default defineConfig({ + plugins: [vue()], + build: { + rollupOptions: { + output: { + manualChunks(id) { + // echarts 单独拆包(~1MB,仅访问图表页面时加载) + if (id.includes('node_modules/echarts')) { + return 'echarts' + } + // element-plus 单独拆包(~1MB,浏览器缓存) + if (id.includes('node_modules/element-plus')) { + return 'element-plus' + } + // vue 核心库单独拆包(~120KB) + if (id.includes('node_modules/vue') || id.includes('node_modules/@vue')) { + return 'vue-core' + } + }, + }, + }, + chunkSizeWarningLimit: 500, // 提高告警阈值,避免拆包后仍有大 chunk 告警 + }, +}) +``` + +**效果**: +| Chunk | 大小 | 加载时机 | +|:------|:----:|:--------| +| `vue-core` | ~120KB | 首屏 | +| `element-plus` | ~1MB | 首屏(浏览器缓存后不重复下载) | +| `echarts` | ~1MB | 仅访问图表页面时按需加载 | +| 各页面组件 | 2~15KB | 按需加载 | + +### 2. 路由懒加载(动态 import) + +将 `router/index.js` 中的静态 import 改为动态 `() => import(...)`: + +```js +// ❌ 静态 import(全量加载) +import Dashboard from '../views/dashboard/Index.vue' + +// ✅ 动态 import(按需加载) +const routes = [ + { + path: '/dashboard', + component: () => import('../views/dashboard/Index.vue'), + }, +] +``` + +Vite 会自动为每个动态 import 生成独立 chunk,文件名基于组件名(如 `Index-abc123.js`)。 + +### 3. 验证优化效果 + +```bash +# 构建前 +ls -lh dist/assets/ +# 输出:index-DoEo0YCm.js 2.3M ← 单文件 + +# 配置后构建 +npm run build +ls -lh dist/assets/ +# 输出: +# vue-core-BuIKajZo.js 119KB +# element-plus-C03w9GoR.js 1.0MB +# echarts-Bb6yjXMn.js 1.0MB +# Index-xxx.js 2~15KB(每个页面) +# ... +``` + +## 注意事项 + +1. **manualChunks 函数**接收的是模块 ID(绝对路径),用 `id.includes()` 匹配 `node_modules` 中的包名 +2. **路由懒加载**只在用户访问对应路由时才加载 chunk,首次访问某页面会有短暂加载延迟(通常 < 200ms) +3. **echarts 拆包后**,只有访问包含 ECharts 图表的页面(仪表盘、经营数据等)才会加载 echarts chunk +4. **chunkSizeWarningLimit** 建议设为 500KB,避免拆包后 element-plus/echarts 仍触发告警(它们确实很大) +5. **浏览器缓存**:element-plus 和 vue-core 拆为独立 chunk 后,只要版本不变,浏览器会缓存,后续页面访问不再下载 diff --git a/hermes-agent/skills/dev-pipeline-universal/references/operation-log-pattern.md b/hermes-agent/skills/dev-pipeline-universal/references/operation-log-pattern.md new file mode 100644 index 0000000..e9901ad --- /dev/null +++ b/hermes-agent/skills/dev-pipeline-universal/references/operation-log-pattern.md @@ -0,0 +1,212 @@ +# 操作日志系统(审计追踪模式) + +> **适用场景**: 任何需要审计追踪的 CRUD 管理系统 +> **创建日期**: 2026-06-29 + +--- + +## 四层架构 + +| 层次 | 文件 | 职责 | +|:----|:-----|:-----| +| 模型 | `models/operation_log.py` | 定义数据库表结构 | +| 服务 | `services/operation_log.py` | 工具函数 `log_operation()` | +| API | `routers/logs.py` | `GET /api/logs` 查询接口 | +| 埋点 | 各 CRUD 路由中 | 在 create/update/delete 后调用 | + +--- + +## 模型定义 + +```python +from sqlalchemy import Column, Integer, String, DateTime, Text +from sqlalchemy.sql import func +from app.database import Base + + +class OperationLog(Base): + __tablename__ = "operation_logs" + + id = Column(Integer, primary_key=True, index=True) + user = Column(String(64), default="admin", comment="操作人") + action = Column(String(32), nullable=False, comment="操作类型: create/update/delete") + entity_type = Column(String(32), nullable=False, comment="实体类型") + entity_id = Column(Integer, nullable=True, comment="实体ID") + entity_name = Column(String(128), nullable=True, comment="实体名称(冗余,方便展示)") + detail = Column(Text, nullable=True, comment="操作详情") + created_at = Column(DateTime(timezone=True), server_default=func.now(), comment="操作时间") +``` + +## 服务层 + +```python +from sqlalchemy.orm import Session +from app.models.operation_log import OperationLog + + +def log_operation( + db: Session, + action: str, + entity_type: str, + entity_id: int = None, + entity_name: str = None, + detail: str = None, + user: str = "admin", +): + log = OperationLog( + user=user, + action=action, + entity_type=entity_type, + entity_id=entity_id, + entity_name=entity_name, + detail=detail, + ) + db.add(log) + db.commit() +``` + +## API 路由 + +```python +from fastapi import APIRouter, Depends, Query +from sqlalchemy.orm import Session +from app.database import get_db +from app.models.operation_log import OperationLog +from typing import Optional + +router = APIRouter(prefix="/api/logs", tags=["操作日志"]) + + +@router.get("") +def list_logs( + entity_type: Optional[str] = Query(None), + action: Optional[str] = Query(None), + limit: int = Query(100, ge=1, le=500), + offset: int = Query(0, ge=0), + db: Session = Depends(get_db), +): + q = db.query(OperationLog).order_by(OperationLog.created_at.desc()) + if entity_type: + q = q.filter(OperationLog.entity_type == entity_type) + if action: + q = q.filter(OperationLog.action == action) + + total = q.count() + logs = q.offset(offset).limit(limit).all() + + return { + "total": total, + "logs": [ + { + "id": log.id, + "user": log.user, + "action": log.action, + "entity_type": log.entity_type, + "entity_id": log.entity_id, + "entity_name": log.entity_name, + "detail": log.detail, + "created_at": log.created_at.isoformat() if log.created_at else None, + } + for log in logs + ], + } +``` + +## 埋点注入模式 + +### 创建后 + +```python +log_operation(db, "create", "project", p.id, p.project_name, f"创建项目: {p.project_code}") +``` + +### 更新后 + +```python +log_operation(db, "update", "project", p.id, p.project_name, f"更新项目: {p.project_code}") +``` + +### 删除前(需要 entity_name 做记录) + +```python +log_operation(db, "delete", "project", project_id, p.project_name if p else None, f"删除项目: ID={project_id}") +``` + +### 批量导入 + +```python +log_operation(db, "create", "import", None, filename, f"Excel导入: {stats}") +``` + +## 注册路由 + +在 `main.py` 中: + +```python +from app.routers import auth, groups, personnel, projects, settings, dashboard, reports, search, finance, logs + +# 受保护路由 +app.include_router(logs.router, dependencies=[Depends(verify_token)]) +``` + +## 前端页面 + +```vue + +``` + +## 路由注册 + 侧边栏 + +```javascript +// router/index.js +{ + path: 'logs', + name: 'Logs', + component: () => import('../views/logs/Index.vue'), +} + +// Layout.vue 侧边栏 + + + 操作日志 + +``` + +## 适用实体类型 + +| entity_type | 含义 | 埋点位置 | +|:------------|:-----|:---------| +| project | 项目 | projects.py CRUD | +| task | WBS 任务 | projects.py task CRUD | +| milestone | 里程碑 | projects.py milestone CRUD | +| income | 月度收益 | projects.py income CRUD | +| personnel | 人员 | personnel.py CRUD | +| group | 组别 | groups.py CRUD | +| setting | 系统设置 | settings.py CRUD | +| import | 数据导入 | import_data.py | + +## 注意事项 + +1. **删除操作需在 delete 前记录**:`db.delete()` 后对象属性仍可访问,但 `db.commit()` 后不可用 +2. **SQLAlchemy Column 类型警告**:Pyright 会报 `Column[int]` 不能赋值给 `int` 的参数类型错误,这是已知假阳性,不影响运行 +3. **不要过度埋点**:GET 查询操作不需要记录,只记录 create/update/delete +4. **entity_name 冗余存储**:即使关联实体被删除,日志中仍保留名称用于展示 diff --git a/hermes-agent/skills/dev-pipeline-universal/references/quality-gates.md b/hermes-agent/skills/dev-pipeline-universal/references/quality-gates.md new file mode 100644 index 0000000..e82f55c --- /dev/null +++ b/hermes-agent/skills/dev-pipeline-universal/references/quality-gates.md @@ -0,0 +1,109 @@ +# 研发流水线 — 质量门禁规范 +# 每个阶段完成后,由马总管自动执行质量门禁检查 + +--- + +## 质量门禁总览 + +``` +需求 ──→ [QG1] ──→ 设计 ──→ [QG2] ──→ 编码 ──→ [QG3] ──→ 测试 ──→ [QG4] ──→ 部署 +``` + +--- + +## QG1: 需求分析门禁 + +**执行时机:** ①需求分析完成后,进入②设计之前 + +| 检查项 | 通过标准 | 执行方式 | +|--------|---------|---------| +| 产物格式完整 | YAML所有必填字段非空 | 自动 | +| 验收标准可测试 | 每条AC标记testable=true | 自动 | +| 范围边界清晰 | in_scope和out_of_scope均非空 | 自动 | +| 用户确认 | 乔确认需求理解正确 | 人工 | + +**不通过处理:** 补充缺失信息,重新跟乔确认 + +--- + +## QG2: 技术方案门禁 + +**执行时机:** ②设计完成后,进入③编码之前 + +| 检查项 | 通过标准 | 执行方式 | +|--------|---------|---------| +| 产物格式完整 | YAML所有必填字段非空 | 自动 | +| 文件变更清单 | file_changes列表非空 | 自动 | +| API设计与需求对齐 | 每个AC至少对应一个API或功能点 | AI审查 | +| 无遗留阻断问题 | open_issues中无阻断级问题 | 自动 | +| 重大决策确认 | 涉及架构变更时需乔确认 | 条件人工 | + +**不通过处理:** 反馈问题给架构师Agent重新设计(最多2轮) + +--- + +## QG3: 编码实现门禁 + +**执行时机:** ③编码完成后,进入④审查之前 + +| 检查项 | 通过标准 | 执行方式 | +|--------|---------|---------| +| 产物格式完整 | YAML所有必填字段非空 | 自动 | +| 代码可编译/无语法错误 | self_check.compiles=true | 自动 | +| lint通过 | self_check.lint_passes=true | 自动 | +| 文件变更与设计一致 | 实际变更文件 ⊆ 设计中的file_changes | AI审查 | +| 无常驻进程残留 | 无未关闭的后台服务 | 自动 | + +**不通过处理:** 反馈给程序员Agent修复(最多3轮) + +--- + +## QG4: 测试验证门禁 + +**执行时机:** ⑤测试完成后,进入⑥部署之前 + +| 检查项 | 通过标准 | 执行方式 | +|--------|---------|---------| +| 所有测试通过 | verdict=ALL_PASS | 自动 | +| 覆盖率达标 | line_percent >= 阈值(见测试规范) | 自动 | +| 无回归 | existing_tests_still_pass=true | 自动 | +| 冒烟测试通过 | smoke.failed=0 | 自动 | +| 部署确认 | 乔确认可以部署 | 人工 | + +**不通过处理:** 失败信息反馈给程序员Agent修复 → 重新测试(最多3轮) + +--- + +## 门禁执行规则 + +### 重试策略 +``` +第1次失败 → 同模型重试,附带失败原因 +第2次失败 → 换备用模型重试 +第3次失败 → 上报乔,进入人工介入 +``` + +### 备用模型降级链(示例 — 根据实际可用模型替换) + +降级原则:主模型失败时,按以下优先级替换: +1. 同平台其他模型(相同 API 端点) +2. 不同平台同等级模型 +3. 快速响应模型兜底 + +| 角色 | 降级策略 | +|------|---------| +| 架构师 | 强推理模型 → 同平台次强模型 → 通用模型 | +| 设计师 | 编码版模型 → 通用强模型 → 快速模型 | +| 主程序员 | 深度编码模型 → 其他编码模型 → 快速模型 | +| 结对程序员 | 与主程序员不同家族模型 → 主程序员模型 | +| 审查员 | 深度推理模型 → 架构师模型 | +| 测试员 | Agent能力强的模型 → 编码模型 | + +### 超时保护 +| 阶段 | 超时时间 | 超时处理 | +|------|---------|---------| +| ②设计 | 30分钟 | 终止,记录已有产出,人工介入 | +| ③UI设计 | 10分钟 | 换模型重试,精简prompt | +| ④编码 | 50分钟 | 终止,保留已写代码,人工介入 | +| ⑤审查 | 25分钟 | 终止,标记"审查超时",进入测试 | +| ⑥测试 | 40分钟 | 终止,保留已有测试结果,人工介入 | diff --git a/hermes-agent/skills/dev-pipeline-universal/references/revenue-allocation-pattern.md b/hermes-agent/skills/dev-pipeline-universal/references/revenue-allocation-pattern.md new file mode 100644 index 0000000..9045eca --- /dev/null +++ b/hermes-agent/skills/dev-pipeline-universal/references/revenue-allocation-pattern.md @@ -0,0 +1,113 @@ +# 收益归属矩阵(业务报表模式) + +> **适用场景**: 需要按人×项目维度展示收益归属矩阵 +> **创建日期**: 2026-06-24 + +--- + +## 业务含义 + +行 = 人员,列 = 项目,交叉单元格 = 该人在该项目的收益贡献。类似 Excel 透视表。 + +``` + 项目A 项目B 项目C 小计 +郑明义 ¥14,983 ¥4,142 ¥1,839 ¥20,964 +薛文 ¥11,600 ¥884 ¥3,678 ¥16,162 +总计 ¥82,031 ¥7,070 ¥9,196 ¥98,297 +``` + +--- + +## 计算逻辑 + +### 数据源 + +- `project_monthly_income` — 项目月度总收益(按项目×月份) +- `personnel_projects` — 人员-项目关联(含 `allocation_ratio` 分配比例) + +### 核心公式 + +``` +个人在项目的收益 = 项目总收益 × (该人的分配比例 / 100) +``` + +### 特殊情况 + +| 情况 | 处理方式 | +|------|---------| +| 人员有关联比例 | 按比例分摊项目总收益 | +| 人员无关联比例 | 收益为 0(不显示在矩阵中) | +| 项目无收益记录 | 收益为 0(不显示在矩阵中) | +| 月份筛选 | 只计算该月的收益记录 | + +### API 设计 + +``` +GET /api/reports/income-matrix?month=2026-06 + +Response: +{ + "rows": [ + { + "name": "郑明义", + "group_name": "四组", + "projects": {"南方医科大学珠江医院": 9666.67, "苏州市立医院": 1325.58}, + "subtotal": 12831.38 + } + ], + "project_totals": {"南方医科大学珠江医院": 82031.34, ...}, + "grand_total": 442598.68, + "month": null +} +``` + +--- + +## 前端实现要点 + +### 动态列 + +项目列是动态的(随数据变化),需要用 `v-for` 在 `` 上渲染: + +```vue + + + +``` + +### 总计行 + +用 `` 展示项目总计,放在表格下方: + +```vue + + + ¥{{ grandTotal.toLocaleString() }} + + + ¥{{ val.toLocaleString() }} + + +``` + +### 月份筛选 + +提供月份下拉框,不传参时汇总所有月份。筛选在 API 层完成,前端只传参数。 + +--- + +## 常见问题 + +### Q: 为什么矩阵中的项目总收益不等于项目列表中的预期收益? + +A: 矩阵中的收益来自 `project_monthly_income`(实际实现的月度收益),不等于项目的预期收益(合同金额)。两者是不同概念。 + +### Q: 为什么某些人没有出现在矩阵中? + +A: 只有 `subtotal > 0` 的行才会显示。如果人员有关联项目但项目没有收益记录,该人员不会出现。 + +### Q: 分配比例从哪里来? + +A: 从 `personnel_projects.allocation_ratio` 字段读取。初始导入时从 Excel 工作描述中的"占比 N%"正则提取,无比例时按项目关联人数均分。 diff --git a/hermes-agent/skills/dev-pipeline-universal/references/roles.example.yaml b/hermes-agent/skills/dev-pipeline-universal/references/roles.example.yaml new file mode 100644 index 0000000..c796b11 --- /dev/null +++ b/hermes-agent/skills/dev-pipeline-universal/references/roles.example.yaml @@ -0,0 +1,41 @@ +# 研发流水线 — 角色模型配置示例 +# +# 使用前请复制为 roles.yaml,修改模型名称为您实际可用的模型。 +# 每个角色使用不同模型家族可获得更好的交叉审视效果。 + +roles: + - name: "架构师" + code: "ARCH" + emoji: "🏗️" + stages: ["②技术方案"] + model: "<强推理模型,如 glm-5.2 / claude-sonnet-4 / deepseek-v4-pro>" + + - name: "设计师" + code: "UI" + emoji: "🎨" + stages: ["③UI设计"] + model: "<编码版模型,如 kimi-k2.7-code / claude-sonnet-4>" + + - name: "主程序员" + code: "DEV" + emoji: "💻" + stages: ["④编码实现"] + model: "<深度编码模型,如 deepseek-v4-pro / claude-sonnet-4>" + + - name: "结对程序员" + code: "DEV2" + emoji: "👥" + stages: ["④编码实现(review)"] + model: "<与主程序员不同家族,如 kimi-k2.7-code / gpt-4o>" + + - name: "审查员" + code: "REVIEW" + emoji: "🔍" + stages: ["⑤代码审查"] + model: "<深度推理模型,如 deepseek-v4-pro / claude-sonnet-4>" + + - name: "测试员" + code: "QA" + emoji: "🧪" + stages: ["⑥测试验证"] + model: "" diff --git a/hermes-agent/skills/dev-pipeline-universal/references/testing-strategy.md b/hermes-agent/skills/dev-pipeline-universal/references/testing-strategy.md new file mode 100644 index 0000000..ae2f322 --- /dev/null +++ b/hermes-agent/skills/dev-pipeline-universal/references/testing-strategy.md @@ -0,0 +1,125 @@ +# 研发流水线 — 测试分层策略 + +--- + +## 测试金字塔 + +``` + ╱╲ + ╱ 冒烟 ╲ ← 5-10% (部署后关键路径验证) + ╱────────╲ + ╱ 集成测试 ╲ ← 20-30% (API/服务间交互) + ╱──────────────╲ + ╱ 单元测试 ╲ ← 60-70% (函数/类级别) + ╱──────────────────╲ +``` + +--- + +## 各层测试规范 + +### 单元测试 + +**目标:** 验证单个函数/类的行为正确性 +**覆盖率要求:** 行覆盖 ≥ 70%,函数覆盖 ≥ 80% + +**测试Agent生成规则:** +1. 只看接口签名+文档+验收标准,不看实现细节(黑盒测试优先) +2. 必须覆盖:正常路径、边界值(空/null/最大/最小)、异常路径 +3. 每个测试函数只验证一个行为点 +4. 测试命名格式:`test_<功能>_<场景>_<预期结果>` + +### 集成测试 + +**目标:** 验证模块间/服务间交互正确性 +**覆盖率要求:** 所有API接口100%覆盖 + +**测试Agent生成规则:** +1. 每个API端点至少:1个成功用例 + 1个参数校验失败 + 1个权限失败 +2. 测试数据库/外部服务交互的完整流程 +3. 使用真实的数据库(SQLite内存模式)或合理的Mock + +### 冒烟测试 + +**目标:** 部署后快速验证核心功能可用 +**覆盖率要求:** 覆盖所有核心用户路径 + +**测试Agent生成规则:** +1. 从验收标准(AC)中提取关键路径 +2. 只验证"能不能用",不验证边界条件 +3. 执行时间 < 30秒 +4. 对于前端项目:启动服务 → 访问关键页面 → 验证无崩溃 + +--- + +## 测试质量保障 + +### 独立性原则(参考AgentCoder论文 arXiv:2312.13010) +- 测试Agent(minimax-m3)与编码Agent(deepseek-v4-pro)使用不同模型 +- 测试Agent的prompt中**不包含**编码Agent的prompt和实现思路 +- 测试Agent只接收:接口文档 + 验收标准 + 代码文件(只看签名,不解释逻辑) + +### 测试Agent的Context模板 +``` +你是一个QA测试工程师。根据以下信息编写测试: + +## 需求验收标准 +{acceptance_criteria} + +## 接口/函数签名 +{api_signatures} + +## 项目测试约定 +- 框架: {test_framework} +- 运行命令: {test_command} +- 测试目录: {test_directory} + +## 规则 +1. 优先编写能发现bug的测试(边界值、异常路径) +2. 不要写"同义反复"测试(只是重复实现逻辑) +3. 每个测试必须有明确的断言 +4. 测试之间相互独立,无执行顺序依赖 +5. 编写完成后运行全部测试并输出结果 +``` + +--- + +## 覆盖率阈值 + +| 项目规模 | 行覆盖 | 分支覆盖 | 函数覆盖 | +|---------|--------|---------|---------| +| 大型(新项目) | ≥ 70% | ≥ 60% | ≥ 80% | +| 中型(新功能) | ≥ 60% | ≥ 50% | ≥ 75% | +| 小型(bug修复) | 修改行100%覆盖 | — | — | + +--- + +## 前端项目特殊规则 + +前端项目(React/Vue/Next.js等)的测试策略有所不同: + +| 层级 | 内容 | 工具建议 | +|------|------|---------| +| 单元 | 组件渲染测试、工具函数测试 | Jest + Testing Library | +| 集成 | 页面级交互测试 | Playwright / Cypress | +| 冒烟 | 构建+启动+关键页面可达+无JS错误 | curl + Playwright | + +**前端冒烟测试最低要求:** +1. `npm run build` 成功(无编译错误) +2. 构建产物包含所有预期路由(检查 `.next/routes-manifest.json`) +3. 关键页面路由可访问(无404) +4. 浏览器控制台无未捕获错误 + +**⚠️ 陷阱:不要在vitest中spawn服务器** +在测试中用 `spawn('npm', ['run', 'start'])` 启动Next.js再fetch会超时(Next.js启动慢)且进程清理不干净。替代方案:解析build产物中的 `routes-manifest.json`,验证静态路由和动态路由是否完整。示例: +```typescript +it('should have all expected routes after build', () => { + const routesManifest = JSON.parse( + fs.readFileSync('.next/routes-manifest.json', 'utf-8') + ) + const dynamicRoutes = routesManifest.dynamicRoutes?.map(r => r.page) || [] + const staticRoutes = routesManifest.staticRoutes?.map(r => r.page) || [] + expect(staticRoutes).toContain('/') + expect(dynamicRoutes).toContain('/departments/[id]') +}) +``` diff --git a/hermes-agent/skills/dev-pipeline-universal/scripts/show_roles.py b/hermes-agent/skills/dev-pipeline-universal/scripts/show_roles.py new file mode 100644 index 0000000..a4d8328 --- /dev/null +++ b/hermes-agent/skills/dev-pipeline-universal/scripts/show_roles.py @@ -0,0 +1,49 @@ +#!/usr/bin/env python3 +"""研发流水线 — 角色模型对照表生成脚本(通用模板) + +读取自定义的 roles.yaml 配置文件,输出角色模型对照表。 +用户需根据实际环境修改 references/roles.yaml 中的模型配置。 + +用法: python scripts/show_roles.py +""" + +import yaml +import os +import sys +from pathlib import Path + + +def load_roles(): + """加载 roles.yaml""" + script_dir = Path(__file__).parent.parent / "references" + roles_path = script_dir / "roles.yaml" + if not roles_path.exists(): + print(f"❌ 未找到 roles.yaml: {roles_path}") + print("请复制 references/roles.example.yaml 为 references/roles.yaml 并修改配置") + sys.exit(1) + with open(roles_path) as f: + return yaml.safe_load(f) + + +def main(): + roles_config = load_roles() + roles = roles_config.get("roles", []) + + print("=" * 80) + print("研发流水线 — 角色模型对照表") + print("=" * 80) + + print("\n## 当前角色分配\n") + print(f"{'角色':<12} {'代号':<8} {'阶段':<20} {'模型':<25}") + print("-" * 70) + for role in roles: + stages = ", ".join(role.get("stages", [])) + print(f"{role.get('emoji', '')} {role['name']:<10} {role['code']:<8} {stages:<20} {role['model']:<25}") + + # 一致性检查 + print(f"\n## 一致性检查\n") + print("✅ 请手动检查 roles.yaml 中的模型配置是否与您的 API 平台一致。") + + +if __name__ == "__main__": + main() diff --git a/hermes-agent/skills/dev-pipeline-universal/templates/stage-artifacts.md b/hermes-agent/skills/dev-pipeline-universal/templates/stage-artifacts.md new file mode 100644 index 0000000..07730d1 --- /dev/null +++ b/hermes-agent/skills/dev-pipeline-universal/templates/stage-artifacts.md @@ -0,0 +1,334 @@ +# 研发流水线 — 阶段产物模板 +# 每个阶段的子Agent必须按此格式输出产物 +# 总管(小研)负责校验产物格式完整性 + +--- + +## ① 需求分析产物 + +```yaml +stage: requirements +version: "1.0" +timestamp: "{{ISO_TIMESTAMP}}" + +# 核心产物 +artifacts: + goal: "一句话描述功能目标" + user_stories: + - as: "角色" + want: "功能" + so_that: "价值" + acceptance_criteria: + - id: AC-1 + description: "验收条件描述" + testable: true + constraints: + technical: ["技术约束"] + timeline: "时间要求" + resources: "资源限制" + scope: + in_scope: ["包含的功能点"] + out_of_scope: ["明确排除的功能点"] + +# 元数据 +metadata: + complexity: "large|medium|small|micro" + estimated_stages: ["①", "②", "③", "④", "⑤", "⑥"] + risk_level: "high|medium|low" + +# 遗留问题 +open_issues: [] +``` + +--- + +## ② 技术方案产物 + +```yaml +stage: design +version: "1.0" +timestamp: "{{ISO_TIMESTAMP}}" + +artifacts: + architecture: + pattern: "架构模式(如 monolith/microservice/modular)" + modules: + - name: "模块名" + responsibility: "职责" + dependencies: ["依赖的其他模块"] + data_flow: "数据流描述" + + tech_stack: + language: "编程语言" + framework: "框架" + database: "数据库" + other: ["其他技术选型"] + reasons: "选型理由" + + data_models: + - name: "模型名" + fields: + - {name: "字段名", type: "类型", required: true, description: "说明"} + relations: ["与其他模型的关系"] + + api_design: + - method: "HTTP方法" + path: "/路径" + description: "接口说明" + request_schema: "请求体结构" + response_schema: "响应体结构" + + file_changes: + new_files: ["需要新建的文件路径"] + modified_files: ["需要修改的文件路径"] + deleted_files: ["需要删除的文件路径"] + + impact_analysis: + affected_modules: ["受影响的模块"] + breaking_changes: ["破坏性变更"] + migration_needed: false + +# 关键决策 +decisions: + - decision: "决策内容" + reason: "理由" + alternatives: ["考虑过的替代方案"] + +# 风险点 +risks: + - description: "风险描述" + probability: "high|medium|low" + mitigation: "缓解措施" + +open_issues: [] +``` + +--- + +## ③ UI设计产物(v2.1新增) + +```yaml +stage: ui_design +version: "1.0" +timestamp: "{{ISO_TIMESTAMP}}" + +artifacts: + style_reference: "设计风格参考(如 微信原生风格/Material Design/Ant Design)" + + design_tokens: + colors: + primary: "主色 (如 #07C160)" + primary_light: "主色浅 (如 #E8F8EE)" + secondary: "辅助色" + background: "背景色" + surface: "卡片/面板背景色" + text_primary: "主文字色" + text_secondary: "次要文字色" + text_hint: "提示文字色" + border: "边框色" + error: "错误色" + success: "成功色" + warning: "警告色" + typography: + font_family: "字体" + heading_1: "标题1样式" + heading_2: "标题2样式" + body: "正文样式" + caption: "说明文字样式" + spacing: + page_padding: "页面内边距" + card_padding: "卡片内边距" + section_gap: "区块间距" + item_gap: "列表项间距" + border_radius: + card: "卡片圆角" + button: "按钮圆角" + input: "输入框圆角" + avatar: "头像圆角" + shadows: + card: "卡片阴影" + elevated: "浮起阴影" + + component_styles: + - name: "组件名(如 DoctorCard)" + description: "组件用途" + tailwind_classes: "具体的Tailwind类名组合" + states: + default: "默认状态样式" + hover: "悬停状态样式(如有)" + active: "按下状态样式(如有)" + disabled: "禁用状态样式(如有)" + + page_layouts: + - page: "页面路径(如 /departments/[id])" + structure: "页面结构描述" + key_elements: ["页面包含的关键UI元素"] + + interaction_notes: + - element: "交互元素" + behavior: "交互行为描述" + +# 自然语言摘要 +summary: "设计方案一句话总结" + +open_issues: [] +``` + +--- + +## ④ 编码实现产物 + +```yaml +stage: implementation +version: "1.0" +timestamp: "{{ISO_TIMESTAMP}}" + +artifacts: + files_changed: + - path: "文件路径" + action: "created|modified|deleted" + description: "变更说明" + + implementation_notes: + approach: "实现思路简述" + key_decisions: ["实现中的关键决策"] + deviations_from_design: ["与设计方案的偏差及原因"] + + dependencies_added: + - name: "依赖名" + version: "版本" + reason: "添加原因" + + commands_to_run: + build: "构建命令" + start: "启动命令(如有)" + +# 自检结果 +self_check: + compiles: true + lint_passes: true + basic_smoke_test: "描述基本冒烟验证结果" + +open_issues: [] +``` + +--- + +## ⑤ 代码审查产物 + +```yaml +stage: code_review +version: "1.0" +timestamp: "{{ISO_TIMESTAMP}}" + +artifacts: + verdict: "APPROVED|REQUEST_CHANGES" + + issues: + - id: "CR-1" + severity: "CRITICAL|IMPORTANT|MINOR" + category: "security|correctness|performance|maintainability|convention|testing" + file: "文件路径" + line: 42 + description: "问题描述" + suggestion: "修改建议" + confidence: 0.9 + + dimensions_checked: + security: {score: "PASS|WARN|FAIL", notes: ""} + correctness: {score: "PASS|WARN|FAIL", notes: ""} + performance: {score: "PASS|WARN|FAIL", notes: ""} + maintainability: {score: "PASS|WARN|FAIL", notes: ""} + convention: {score: "PASS|WARN|FAIL", notes: ""} + test_coverage: {score: "PASS|WARN|FAIL", notes: ""} + + # 信息隔离声明 + review_context: + saw_implementation_prompt: false # 审查者不应看到编码prompt + saw_only: ["代码变更(git diff)", "需求文档", "技术方案"] + +open_issues: [] +``` + +--- + +## ⑥ 测试验证产物 + +```yaml +stage: testing +version: "1.0" +timestamp: "{{ISO_TIMESTAMP}}" + +artifacts: + verdict: "ALL_PASS|PARTIAL_FAIL|ALL_FAIL" + + test_layers: + unit: + total: 0 + passed: 0 + failed: 0 + skipped: 0 + coverage_percent: 0 + test_files: ["测试文件路径"] + integration: + total: 0 + passed: 0 + failed: 0 + skipped: 0 + test_files: [] + smoke: + total: 0 + passed: 0 + failed: 0 + description: "冒烟测试说明" + + failed_tests: + - test_name: "失败的测试名" + layer: "unit|integration|smoke" + error_message: "错误信息" + root_cause: "初步分析" + suggested_fix: "建议修复方式" + + coverage: + line_percent: 0 + branch_percent: 0 + function_percent: 0 + meets_threshold: true + + regression_check: + existing_tests_still_pass: true + broken_tests: [] + +open_issues: [] +``` + +--- + +## ⑦ 部署上线产物 + +```yaml +stage: deployment +version: "1.0" +timestamp: "{{ISO_TIMESTAMP}}" + +artifacts: + deployment_method: "描述部署方式" + environment: "production|staging|development" + + steps_executed: + - step: "步骤描述" + status: "success|failed" + output: "关键输出" + + verification: + service_running: true + health_check_passed: true + smoke_test_passed: true + key_features_verified: ["已验证的核心功能"] + + rollback_plan: + method: "回滚方式" + command: "回滚命令" + +open_issues: [] +``` diff --git a/meta-skills/create-hermes-agent-skill/CHANGELOG.md b/meta-skills/create-hermes-agent-skill/CHANGELOG.md index 88bd599..fbcb92f 100644 --- a/meta-skills/create-hermes-agent-skill/CHANGELOG.md +++ b/meta-skills/create-hermes-agent-skill/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +## 0.2.0 - 2026-07-02 + +- 基于官方文档和 GitHub 仓库完整重构规范 +- 新增完整的 SKILL.md frontmatter 字段定义和验证器约束 +- 新增推荐正文结构(Overview → When to Use → Pitfalls → Verification) +- 新增渐进式披露三层加载机制 +- 新增写作质量 8 项原则 +- 新增官方参考技能列表和 GitHub 链接 +- 新增工具链说明(skill_manage、/learn、skill_view) +- 新增 Skill Bundles 和 Skills Hub 说明 +- 新增常见陷阱(9 项) + ## 0.1.0 - 2026-07-01 - 初始版本 diff --git a/meta-skills/create-hermes-agent-skill/prompt.md b/meta-skills/create-hermes-agent-skill/prompt.md index 3775e51..01398ef 100644 --- a/meta-skills/create-hermes-agent-skill/prompt.md +++ b/meta-skills/create-hermes-agent-skill/prompt.md @@ -1,21 +1,192 @@ # 如何创建 Hermes Agent 技能 -本技能指导你为 Hermes Agent 框架创建符合规范的技能,特别是结构化输出和工具调用协议。 +本技能指导你为 Hermes Agent 框架创建符合规范的技能,基于官方文档和 GitHub 仓库中的最佳实践。 + +## 核心概念 + +Hermes Agent 技能(Skill)是代理的**程序化记忆**(Procedural Memory),代理在运行时创建和复用。技能遵循 [agentskills.io](https://agentskills.io) 开放标准,可跨平台共享。 + +## 技能存放位置 + +| 位置 | 路径 | 用途 | +|------|------|------| +| **用户本地** | `~/.hermes/skills//SKILL.md` | 个人技能,不共享,通过 `skill_manage(action='create')` 创建 | +| **项目仓库内** | `skills///SKILL.md` | 随项目提交,团队共享 | ## 创建流程 -1. **了解 Hermes Agent 规范**:阅读 `spec.md`,了解结构化输出和工具调用协议 -2. **参考官方示例**:查看 `examples/` 目录中的参考实现 -3. **创建技能目录**:在 `hermes-agent/skills//` 下新建目录 -4. **编写技能文件**: - - `skill.json`:技能元信息 - - `prompt.md`:技能指令和输出格式定义 - - 按需添加工具定义和测试用例 -5. **验证技能**:在 Hermes Agent 环境中加载并测试 -6. **发布技能**:更新版本号,归档到 `versions/` +### 1. 调研已有技能 -## 注意事项 +```bash +# 查看目标分类下已有的技能 +ls skills// +``` -- Hermes Agent 强调结构化输出,技能需定义输出 Schema -- 工具调用协议有特定格式要求 -- 建议参考 `examples/` 中的示例了解输出格式 +阅读 2-3 个同类技能的 SKILL.md,匹配风格和结构。避免创建重复技能。 + +### 2. 创建 SKILL.md + +文件必须: +- 以 `---` 开头(不能有空行或 BOM) +- YAML frontmatter 以 `\n---\n` 闭合 +- frontmatter 后紧跟 Markdown 正文 + +### 3. 编写 Frontmatter + +```yaml +--- +name: my-skill-name # 小写+连字符,≤64 字符 +description: "Use when <触发条件>. <一句话行为描述>." # ≤1024 字符 +version: 1.0.0 +author: <作者名> +license: MIT +platforms: [linux, macos, windows] +metadata: + hermes: + tags: [短, 描述性, 标签] + related_skills: [other-skill, another-skill] +--- +``` + +**必填字段**(验证器强制): +- `name`:≤64 字符,正则 `^[a-z][a-z0-9_-]*$` +- `description`:≤1024 字符,以 "Use when ..." 开头 + +**推荐字段**(所有官方技能都包含): +- `version`、`author`、`license`、`platforms` +- `metadata.hermes.tags`、`metadata.hermes.related_skills` + +### 4. 编写正文结构 + +```markdown +# <技能标题> + +## Overview +一到两段:做什么,为什么需要。 + +## When to Use +- 触发条件(bullet 列表) +- "Don't use for:" 反触发条件 + +## <技能特定章节> +- 快速参考表 +- 精确命令的代码块 +- Hermes 特有的 recipes + +## Common Pitfalls +编号列表:常见错误和修复方法。 + +## Verification Checklist +- [ ] 操作后验证的 checkbox 列表 + +## One-Shot Recipes(可选) +命名场景 → 具体命令序列。 +``` + +### 5. 添加辅助文件 + +- `references/` — 按需加载的参考文档 +- `templates/` — 模板文件 +- `scripts/` — 辅助脚本 +- `assets/` — 静态资源 + +### 6. 本地验证 + +```python +import yaml, re, pathlib +content = pathlib.Path("skills///SKILL.md").read_text() +assert content.startswith("---") +m = re.search(r'\n---\s*\n', content[3:]) +fm = yaml.safe_load(content[3:m.start()+3]) +assert "name" in fm and "description" in fm +assert len(fm["description"]) <= 1024 +assert len(content) <= 100_000 +``` + +### 7. 提交 + +```bash +git add skills/// +git commit -m "Add skill: " +``` + +> 注意:当前会话的技能加载器在会话开始时缓存,新技能需要在新会话中才能被 `skill_view` / `skills_list` 看到。 + +## 关键规范 + +### Description 编写规范 + +- ≤ 1024 字符 +- 以 "Use when ..." 开头,描述**触发类别**而非单一任务 +- 示例: + - ✅ "Use when debugging test failures. Enforce RED-GREEN-REFACTOR cycle." + - ❌ "Debug tests" + - ❌ "Be thorough when testing" + +### 文件大小限制 + +| 限制项 | 值 | 说明 | +|--------|---|------| +| Description | ≤ 1024 字符 | 验证器强制 | +| 完整 SKILL.md | ≤ 100,000 字符 | 约 36k tokens | +| 推荐范围 | 8-14k 字符 | 官方技能平均水平 | +| 超过 20k | 拆分到 `references/*.md` | 渐进式披露 | + +### 渐进式披露(三层加载) + +| 层级 | 调用方式 | 内容 | +|------|---------|------| +| L0 | `skills_list()` | 仅加载基础元数据 | +| L1 | `skill_view(name)` | 加载完整 SKILL.md | +| L2 | `skill_view(name, path)` | 加载特定参考文件 | + +### 触发机制 + +- 斜杠命令:`/` +- 自然语言对话 +- `fallback_for_toolsets`:仅在特定高级工具缺失时显示 +- `platforms`:自动隐藏不兼容操作系统的技能 + +### 写作质量原则 + +1. **优化过程可预测性** — 每一行都应改变代理行为,否则删除 +2. **正确的上下文负载** — description 每次都会被加载,保持精炼 +3. **信息层级** — 常用步骤放 SKILL.md,详细内容放 references/ +4. **完成标准** — 每个步骤都要有可检查的完成条件 +5. **规则与概念共存** — 定义、警告、示例、验证放在一起 +6. **使用强引导词** — "tight loop"、"root cause"、"regression test" 比长解释更省 token +7. **消除重复和无效内容** — "Be careful"、"use best practices" 不改变行为,删除 +8. **防止过早完成** — 如果代理倾向于跳过某步骤,先锐化该步骤的完成标准 + +## 官方参考技能 + +| 技能 | 路径 | 说明 | +|------|------|------| +| [Skill Authoring](https://github.com/nousresearch/hermes-agent/blob/main/skills/software-development/hermes-agent-skill-authoring/SKILL.md) | `skills/software-development/hermes-agent-skill-authoring/` | 官方技能编写指南 | +| [Test-Driven Development](https://github.com/nousresearch/hermes-agent/blob/main/skills/software-development/test-driven-development/SKILL.md) | `skills/software-development/test-driven-development/` | TDD 工作流 | +| [Systematic Debugging](https://github.com/nousresearch/hermes-agent/blob/main/skills/software-development/systematic-debugging/SKILL.md) | `skills/software-development/systematic-debugging/` | 系统化调试 | +| [Plan](https://github.com/nousresearch/hermes-agent/blob/main/skills/software-development/plan/SKILL.md) | `skills/software-development/plan/` | 任务规划 | + +## 工具链 + +| 工具 | 用途 | +|------|------| +| `skill_manage(action='create')` | 创建用户本地技能(`~/.hermes/skills/`) | +| `skill_manage(action='patch')` | 补丁更新(支持 in-repo 和本地) | +| `skill_manage(action='write_file')` | 写入辅助文件(references/templates/scripts/assets) | +| `/learn` 命令 | 从 URL 或本地上下文自动生成技能 | +| `skill_view(name)` | 查看技能完整内容 | +| `skills_list()` | 列出所有可用技能 | + +## 常见陷阱 + +| 陷阱 | 说明 | +|------|------| +| 用 `skill_manage(create)` 创建 in-repo 技能 | 会写到 `~/.hermes/skills/`,应用 `write_file` | +| `---` 前有空行 | 验证器检查 `startswith("---")`,会失败 | +| Description 太通用 | 应以 "Use when ..." 开头描述触发类别 | +| 缺少 author/license/metadata | 验证器不强制,但所有官方技能都有 | +| 创建重复技能 | 先 `ls skills//` 检查 | +| 期望当前会话看到新技能 | 技能加载器在会话开始时缓存 | +| 积累沉淀内容 | 技能应越来越精炼,添加新规则时删除旧措辞 | +| 无效内容 | "Be careful" 不改变行为,用可检查的完成标准替代 | diff --git a/meta-skills/create-hermes-agent-skill/skill.json b/meta-skills/create-hermes-agent-skill/skill.json index 4156441..d1584b6 100644 --- a/meta-skills/create-hermes-agent-skill/skill.json +++ b/meta-skills/create-hermes-agent-skill/skill.json @@ -1,8 +1,13 @@ { "name": "create-hermes-agent-skill", - "version": "0.1.0", - "description": "指导如何为 Hermes Agent 创建技能(Skill)", + "version": "0.2.0", + "description": "指导如何为 Hermes Agent 创建技能(Skill),包含完整规范、官方参考和最佳实践", "targetFramework": "hermes-agent", "type": "meta-skill", - "tags": ["hermes-agent", "skill-creation", "guide"] + "tags": ["hermes-agent", "skill-creation", "guide"], + "sources": [ + "https://hermes-agent.nousresearch.com/docs/user-guide/features/skills", + "https://github.com/nousresearch/hermes-agent/blob/main/skills/software-development/hermes-agent-skill-authoring/SKILL.md", + "https://github.com/nousresearch/hermes-agent/blob/main/skills/software-development/test-driven-development/SKILL.md" + ] } diff --git a/meta-skills/create-hermes-agent-skill/spec.md b/meta-skills/create-hermes-agent-skill/spec.md index 3b47218..58a11e7 100644 --- a/meta-skills/create-hermes-agent-skill/spec.md +++ b/meta-skills/create-hermes-agent-skill/spec.md @@ -1,56 +1,124 @@ # Hermes Agent 技能规范摘要 -> 本文件摘要整理 Hermes Agent 技能的核心规范,供快速参考。完整规范请参阅 Hermes Agent 官方文档。 +> 基于 Hermes Agent 官方文档和 GitHub 仓库(`nousresearch/hermes-agent`)整理。 -## 技能目录结构 +## 文件结构 ``` / -├── skill.json # 技能元信息(必填) -├── prompt.md # 技能指令和输出定义(必填) -├── tools/ # 工具定义(可选) -├── tests/ # 验证用例(可选) -└── CHANGELOG.md # 版本变更记录(推荐) +├── SKILL.md # 核心指令文件(必填) +├── references/ # 按需加载的参考文档(可选) +├── templates/ # 模板文件(可选) +├── scripts/ # 辅助脚本(可选) +├── assets/ # 静态资源(可选) +└── CHANGELOG.md # 版本变更记录(推荐) ``` -## skill.json 字段 +## SKILL.md 规范 -| 字段 | 类型 | 必填 | 说明 | -|------|------|------|------| -| `name` | string | 是 | 技能名称 | -| `version` | string | 是 | 语义化版本号 | -| `description` | string | 是 | 技能功能描述 | -| `outputSchema` | object | 否 | 结构化输出的 JSON Schema | -| `tools` | array | 否 | 依赖的工具列表 | -| `tags` | array | 否 | 标签 | +### YAML Frontmatter -## prompt.md 格式 +文件必须以 `---` 开头(第一个字节),无空行或 BOM: -Hermes Agent 的技能指令定义: +```yaml +--- +name: my-skill-name # 必填,≤64 字符,^[a-z][a-z0-9_-]*$ +description: "Use when ..." # 必填,≤1024 字符 +version: 1.0.0 # 推荐 +author: <作者> # 推荐 +license: MIT # 推荐 +platforms: [linux, macos, windows] # 推荐,不兼容平台自动隐藏 +metadata: + hermes: + tags: [tag1, tag2] # 推荐,搜索标签 + category: software-development # 可选 + related_skills: [other-skill] # 推荐,跨技能引用 + fallback_for_toolsets: [] # 可选,仅在特定工具缺失时显示 + requires_toolsets: [] # 可选,依赖的工具集 + config: [] # 可选,配置项 +--- +``` -- 使用 Markdown 格式编写 -- **必须明确定义输出格式**(JSON Schema 或示例) -- 描述技能的执行规则和约束 -- 指定工具调用的条件和参数 -- 建议包含输入输出示例 +### 验证器硬约束 -## 结构化输出 +| 约束 | 值 | 来源 | +|------|---|------| +| `name` 必填 | — | `skill_manager_tool.py::_validate_frontmatter` | +| `name` 最大长度 | 64 字符 | `MAX_NAME_LENGTH` | +| `description` 必填 | — | 同上 | +| `description` 最大长度 | 1024 字符 | `MAX_DESCRIPTION_LENGTH` | +| SKILL.md 最大长度 | 100,000 字符 | `MAX_SKILL_CONTENT_CHARS` | +| Frontmatter 开头 | `---`(第 0 字节) | 同上 | +| Frontmatter 闭合 | `\n---\n` | 同上 | +| Frontmatter 后正文 | 非空 | 同上 | -Hermes Agent 的核心特性: +### 推荐正文结构 -- 技能输出必须符合预定义的 JSON Schema -- 在 `skill.json` 的 `outputSchema` 字段定义 -- 或在 `prompt.md` 中明确描述输出格式 -- 支持嵌套对象和数组类型 +```markdown +# <标题> -## 工具调用协议 +## Overview +做什么,为什么。 -- 工具以标准化接口定义 -- 支持同步和异步调用 -- 工具定义可放在 `tools/` 目录 -- 需声明工具参数的 JSON Schema +## When to Use +- 触发条件 +- "Don't use for:" 反触发 -## 参考链接 +## <特定章节> +命令、表格、recipes... -- [Hermes Agent 官方文档](https://docs.hermes-agent.dev)(待确认) -- `examples/` 目录中的参考实现 +## Common Pitfalls +编号列表。 + +## Verification Checklist +- [ ] 验证项 +``` + +## 存放位置 + +| 类型 | 路径 | 创建方式 | +|------|------|---------| +| 用户本地 | `~/.hermes/skills//` | `skill_manage(action='create')` | +| 项目仓库 | `skills///` | `write_file` + `git add` | +| 外部导入 | `~/.hermes/skills/openclaw-imports/` | 从 OpenClaw 迁移 | + +## 分类目录(官方) + +``` +autonomous-ai-agents creative data-science devops dogfood +email gaming github leisure mcp media mlops +note-taking productivity red-teaming research +smart-home social-media software-development +``` + +选择最接近的已有分类,不要随意创建新分类。 + +## 渐进式披露 + +| 层级 | API | 内容 | +|------|-----|------| +| L0 | `skills_list()` | 基础元数据(name + description) | +| L1 | `skill_view(name)` | 完整 SKILL.md | +| L2 | `skill_view(name, path)` | 特定 references/ 文件 | + +## Skill Bundles + +多个技能可打包为一个 Bundle: + +- 存放路径:`~/.hermes/skill-bundles/` +- 格式:YAML 文件 +- 通过单个斜杠命令调用一组技能 + +## Skills Hub + +- 官方 Hub:[agentskills.io](https://agentskills.io) +- 支持来源:`official`、`skills-sh`、`well-known`、`github` +- 所有第三方安装会经过安全扫描 + +## 编辑已有技能 + +| 操作 | 方法 | +|------|------| +| 小修复 | `skill_manage(action='patch', name=..., old_string=..., new_string=...)` | +| 大重写 | `write_file` 整个 SKILL.md | +| 添加辅助文件 | `write_file` 到 references/templates/scripts/assets |