From e5805cbb51bac502b9143f226a9ca85176c8161f Mon Sep 17 00:00:00 2001 From: John Qiu Date: Sun, 19 Apr 2026 13:33:26 +0930 Subject: [PATCH] =?UTF-8?q?feat:=20P1-10/12/13/14=20=E9=A3=8E=E9=99=A9?= =?UTF-8?q?=E6=89=AB=E6=8F=8F=20+=20=E7=B2=92=E5=BA=A6=E5=88=A4=E6=96=AD?= =?UTF-8?q?=20+=20Issue=20=E9=9B=86=E6=88=90=20+=20PRD=20=E6=A0=A1?= =?UTF-8?q?=E9=AA=8C=20(REQ-20260416-0017)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit P1-10: pm-risk skill — 三维度风险扫描 需求层: 停滞/草稿滞留/开发无提交/测试超期/批准未开发 代码层: 未合并分支/频繁修复文件/提交频率下降 流程层: 跳过评审/PR 无 review/测试门禁跳过/直接推 main 三级风险: 🔴 严重 / 🟡 警告 / 🔵 提示 P1-12: req-prd 需求粒度 AI 判断 创建前启发式检查:标题过宽建议拆分、过窄建议合并或改 task 粒度参考表 + 已有需求扩展决策表 + 前后端拆分规则 P1-13: dev-commit issue 集成规范 分支名 -iN 后缀传递 issue 编号 commit message 自动追加 closes #N P1-14: hooks/validate-prd.sh — PRD 章节校验 PostToolUse hook 自动检查 10 个必需章节 缺失时给出明确提示 marketplace: 48 → 49 plugins (新增 pm-risk-plugin) --- .claude-plugin/marketplace.json | 12 ++ hooks/validate-prd.sh | 98 +++++++++++ .../pm-risk-plugin/.claude-plugin/plugin.json | 8 + skills-core/pm-risk-plugin/skills/SKILL.md | 154 ++++++++++++++++++ skills-dev/dev-commit-plugin/skills/SKILL.md | 42 +++++ skills-req/req-prd-plugin/skills/SKILL.md | 75 +++++++++ 6 files changed, 389 insertions(+) create mode 100755 hooks/validate-prd.sh create mode 100644 skills-core/pm-risk-plugin/.claude-plugin/plugin.json create mode 100644 skills-core/pm-risk-plugin/skills/SKILL.md diff --git a/.claude-plugin/marketplace.json b/.claude-plugin/marketplace.json index c8b26ac..456a72a 100644 --- a/.claude-plugin/marketplace.json +++ b/.claude-plugin/marketplace.json @@ -35,6 +35,18 @@ ], "strict": false }, + { + "name": "pm-risk-plugin", + "source": "./skills-core/pm-risk-plugin", + "description": "三维度项目风险扫描:需求层/代码层/流程层。当用户说'/risk'、'风险扫描'、'有什么风险'时自动激活", + "version": "1.0.0", + "category": "utility", + "keywords": [ + "utility", + "tools" + ], + "strict": false + }, { "name": "publish-plugin", "source": "./skills-core/publish-plugin", diff --git a/hooks/validate-prd.sh b/hooks/validate-prd.sh new file mode 100755 index 0000000..6b37e44 --- /dev/null +++ b/hooks/validate-prd.sh @@ -0,0 +1,98 @@ +#!/bin/bash +# validate-prd.sh +# PostToolUse Hook: PRD 文档写入/编辑后自动校验章节完整性 +# +# 检查标准 PRD 模板的必需章节是否存在。 +# 借鉴 devflow-claude validate-requirement.sh。 +# REQ-20260416-0017 P1-14 +# +# 安装方式(可选,加到 ~/.claude/settings.json): +# hooks.PostToolUse: +# - matcher: "Write|Edit" +# hooks: +# - type: command +# command: "/hooks/validate-prd.sh" +# timeout: 5 +# +# 也可由 skill 脚本在 PRD 写完后手动调用: +# bash validate-prd.sh /path/to/PRD.md + +set -e + +# ============ 1. 获取文件路径 ============ +FILE_PATH="$1" + +# 如果没有参数,从 stdin JSON 提取(PostToolUse hook 模式) +if [ -z "$FILE_PATH" ] && command -v jq >/dev/null 2>&1; then + INPUT=$(cat 2>/dev/null || echo "") + if [ -n "$INPUT" ]; then + FILE_PATH=$(echo "$INPUT" | jq -r '.tool_input.file_path // .tool_input.content // empty' 2>/dev/null) + fi +fi + +# 没有文件路径,静默退出 +if [ -z "$FILE_PATH" ]; then + exit 0 +fi + +# 不是 .md 文件,跳过 +case "$FILE_PATH" in + *.md) ;; + *) exit 0 ;; +esac + +# 文件不存在,跳过 +if [ ! -f "$FILE_PATH" ]; then + exit 0 +fi + +# 不含 PRD / 需求 关键词的文件名,跳过 +BASENAME=$(basename "$FILE_PATH") +case "$BASENAME" in + *PRD*|*prd*|*需求*|*requirement*|*REQ*) ;; + *) exit 0 ;; +esac + +# ============ 2. 检查章节 ============ + +# 标准 PRD 必需章节(来自 req-prd SKILL.md 的模板) +REQUIRED_SECTIONS=( + "## 1. 概述" + "### 1.1 背景" + "### 1.2 目标" + "### 1.4 客户原始诉求" + "## 2. 用户分析" + "## 3. 功能需求" + "## 4. 交互设计" + "## 5. 技术要求" + "## 6. 上线计划" + "## 7. 风险评估" +) + +MISSING=() +CONTENT=$(cat "$FILE_PATH") + +for section in "${REQUIRED_SECTIONS[@]}"; do + # 模糊匹配:忽略空格差异和标点 + PATTERN=$(echo "$section" | sed 's/[[:space:]]*//g') + CONTENT_CLEAN=$(echo "$CONTENT" | sed 's/[[:space:]]*//g') + if ! echo "$CONTENT_CLEAN" | grep -qi "$(echo "$PATTERN" | sed 's/#//g')"; then + MISSING+=("$section") + fi +done + +# ============ 3. 输出 ============ +if [ ${#MISSING[@]} -gt 0 ]; then + echo "" + echo "⚠️ PRD 章节检查:${BASENAME}" + echo "" + echo "缺少 ${#MISSING[@]} 个必需章节:" + for m in "${MISSING[@]}"; do + echo " ❌ $m" + done + echo "" + echo "💡 请参考 req-prd skill 的 PRD 模板补充缺失章节。" + echo " 章节结构不可变:不得新增、删除、合并或重命名模板中的章节。" +fi + +exit 0 diff --git a/skills-core/pm-risk-plugin/.claude-plugin/plugin.json b/skills-core/pm-risk-plugin/.claude-plugin/plugin.json new file mode 100644 index 0000000..03cadb3 --- /dev/null +++ b/skills-core/pm-risk-plugin/.claude-plugin/plugin.json @@ -0,0 +1,8 @@ +{ + "name": "pm-risk-plugin", + "description": "三维度项目风险扫描:需求层/代码层/流程层。当用户说'/risk'、'风险扫描'、'有什么风险'时自动激活", + "version": "1.0.0", + "author": { + "name": "qiudl" + } +} diff --git a/skills-core/pm-risk-plugin/skills/SKILL.md b/skills-core/pm-risk-plugin/skills/SKILL.md new file mode 100644 index 0000000..6b3b08c --- /dev/null +++ b/skills-core/pm-risk-plugin/skills/SKILL.md @@ -0,0 +1,154 @@ +--- +name: pm-risk +description: 三维度项目风险扫描(需求层/代码层/流程层)。当用户说"/risk"、"风险扫描"、"有什么风险"、"哪些需求停滞了"、"分支健康"时自动激活。 +--- + +# pm-risk Skill — 三维度风险扫描 + +借鉴自 devflow-claude `/pm:risk`。源自 REQ-20260416-0017 P1-10。 + +## 命令 + +``` +/risk [--save] +``` + +- 不加参数:扫描并展示报告 +- `--save`:保存到思源笔记 + +## 扫描维度 + +### 维度 1: 需求层 + +通过 ai-proj MCP 查询需求状态: + +| 检测项 | 数据源 | 严重 | 警告 | 提示 | +|--------|--------|------|------|------| +| 需求停滞 | `list_requirements` + `updated_at` | >14 天无更新 | >7 天无更新 | >3 天无更新 | +| 草稿滞留 | `list_requirements --status=draft` | >30 天 | >14 天 | >7 天 | +| 开发中无提交 | 需求关联分支 + `git log` | >7 天无 commit | >3 天 | - | +| 测试中超期 | `list_requirements --delivery_stage=testing` | >14 天 | >7 天 | - | +| 已批准未开发 | `list_requirements --status=approved` | >30 天 | >14 天 | - | + +**查询方式**: +``` +mcp__ai-proj__list_requirements(status=in_progress) +→ 遍历每个需求的 updated_at,计算距今天数 +``` + +### 维度 2: 代码层 + +通过 git 命令分析: + +| 检测项 | 命令 | 严重 | 警告 | +|--------|------|------|------| +| 未合并分支过久 | `git branch -r --no-merged origin/develop` + `git log -1` | >14 天无 commit | >7 天 | +| 频繁修复文件 | `git log --diff-filter=M --name-only` 近 30 天 | 同文件 >5 次 fix commit | >3 次 | +| 提交频率下降 | 本周 vs 上周 commit 数 | 下降 >70% | 下降 >50% | +| 大文件提交 | `git log --diff-filter=A --name-only` | >10MB 文件 | >5MB | + +**查询方式**: +```bash +# 未合并分支 +git for-each-ref --sort=-committerdate --format='%(refname:short) %(committerdate:short)' refs/remotes/origin/ | grep -v 'main\|develop\|HEAD' + +# 频繁修复 +git log --since='30 days ago' --grep='fix' --diff-filter=M --name-only --pretty=format:'' | sort | uniq -c | sort -rn | head -10 + +# 提交频率 +THIS_WEEK=$(git log --since='7 days ago' --oneline | wc -l) +LAST_WEEK=$(git log --since='14 days ago' --until='7 days ago' --oneline | wc -l) +``` + +### 维度 3: 流程层 + +通过 MCP + git 交叉分析: + +| 检测项 | 检测方法 | 级别 | +|--------|---------|------| +| 跳过评审直接开发 | 需求 status 从 draft 直接跳到 in_progress(没有 approved 记录) | 警告 | +| PR 无评审直接合并 | Gitea API 查 PR 无 review approve 就 merge | 警告 | +| 测试门禁跳过 | delivery_stage 从 dev 跳到 released(没有 testing) | 严重 | +| 直接推 main | `git log --first-parent origin/main` 非 merge commit | 严重 | + +## 风险级别定义 + +| 级别 | 图标 | 含义 | 响应 | +|------|------|------|------| +| 严重 | 🔴 | 立即关注 | 当天处理 | +| 警告 | 🟡 | 近期需处理 | 3 天内处理 | +| 提示 | 🔵 | 值得留意 | 下次迭代关注 | + +## 输出模板 + +```markdown +# 🔍 风险扫描报告 + +**扫描时间**: YYYY-MM-DD HH:MM CST +**扫描范围**: 项目 ai-proj + +## 概览 + +| 维度 | 🔴 严重 | 🟡 警告 | 🔵 提示 | +|------|---------|---------|---------| +| 需求层 | X | X | X | +| 代码层 | X | X | X | +| 流程层 | X | X | X | + +## 🔴 严重风险 + +### [S1] REQ-20260410-0001 停滞 18 天 +- **需求**: REQ-20260410-0001 用户积分管理 +- **状态**: in_progress +- **最后更新**: 2026-04-01 +- **建议**: 联系负责人确认是否阻塞,必要时降级或暂停 + +### [S2] ... + +## 🟡 警告 + +### [W1] 分支 feat/xxx 14 天未合并 +- **分支**: feat/old-feature +- **最后 commit**: 2026-04-05 +- **建议**: 确认是否放弃,清理或合并 + +## 🔵 提示 + +... + +## ✅ 一切正常的维度 + +- (无严重/警告时显示此段) + +--- + +**下次扫描建议**: 每周一早会前执行 `/risk` +``` + +## 无风险时的输出 + +``` +✅ 风险扫描完成 — 一切正常 + +扫描了 X 个需求、Y 个分支、Z 条提交,未发现风险项。 + +下次扫描建议:下周一 +``` + +## 定期执行建议 + +- **手动**:每周一早会前 `/risk` +- **自动**:可配合 `/loop 7d /risk --save` 定期扫描并保存到思源笔记 + +## 与其他 skill 的关系 + +| skill | 协作 | +|-------|------| +| `pm-ask` | risk 发现问题后,用 `/ask` 深入分析 | +| `req-workflow` | risk 发现流程违规后,用 `/req` 修正 | +| `ai-proj` | 底层 MCP 数据查询 | + +## 参考 + +- devflow-claude: `plugins/pm/commands/risk.md` +- REQ-20260416-0017 P1-10 diff --git a/skills-dev/dev-commit-plugin/skills/SKILL.md b/skills-dev/dev-commit-plugin/skills/SKILL.md index 858393f..053e5ba 100644 --- a/skills-dev/dev-commit-plugin/skills/SKILL.md +++ b/skills-dev/dev-commit-plugin/skills/SKILL.md @@ -114,6 +114,48 @@ feat/REQ-xxx-i42 + commit → commit message 自动加 "closes #42" 确认提交?(y/n) ``` +## Issue 集成规范(REQ-20260416-0017 P1-13) + +借鉴 devflow-claude 的 issue 关联机制。 + +### 分支名 `-iN` 后缀 + +当任务/需求来自 Gitea/GitHub issue 时,分支名末尾追加 `-iN`: + +``` +feat/REQ-20260416-0017-user-points-i12 ← issue #12 +fix/login-token-expired-i5 ← issue #5 +``` + +**规则**: +- `-iN` 仅当 issue 关联存在时追加 +- `N` 为纯数字(不带 `#`) +- 位于分支名最末尾 + +### commit message 自动追加 `closes #N` + +当分支名含 `-iN` 后缀时,commit message 末尾自动追加 `closes #N`: + +``` +feat(user): 实现积分规则管理 (REQ-20260416-0017) closes #12 +fix(auth): 修复 token 过期未刷新 closes #5 +``` + +**效果**:PR 合并后 Gitea/GitHub 自动关闭关联 issue。 + +### Issue 编号读取优先级 + +| 优先级 | 来源 | 说明 | +|-------|------|------| +| 1 | `--from-issue=#N` 参数 | 用户显式指定 | +| 2 | 分支名 `-iN` 后缀 | 自动解析 `(-i(\d+))$` | +| 3 | MCP 需求文档关联的 issue | (预留) | + +### 不触发的情况 + +- 分支名不含 `-iN` → 不追加 `closes` +- 用户显式说"不关联 issue" → 跳过 + ## 与 ai-proj 集成 - **查询当前需求**:通过 MCP `mcp__ai-proj__find_requirement` 或 `list_requirements` 找 user 进行中的 diff --git a/skills-req/req-prd-plugin/skills/SKILL.md b/skills-req/req-prd-plugin/skills/SKILL.md index 07f49e6..8e9dc56 100644 --- a/skills-req/req-prd-plugin/skills/SKILL.md +++ b/skills-req/req-prd-plugin/skills/SKILL.md @@ -172,6 +172,81 @@ description: 产品设计与需求管理。用于 PRD 文档编写、需求分 --- +## 需求粒度判断(REQ-20260416-0017 P1-12) + +**创建需求前,AI 必须先对标题做粒度预判。** 借鉴 devflow-claude `/req:split`。 + +### 核心问题 + +> **"这个需求完成后,用户能感知到一个完整的功能变化吗?"** +> - 能 → 粒度合适 +> - 不能(太大或太小)→ 需调整 + +### 粒度参考表 + +| 标题示例 | 粒度 | 建议 | +|---------|------|------| +| "用户积分系统"(含规则+查询+兑换+排行) | 太大 | 拆为 4 个需求 | +| "用户积分-积分规则管理"(含 CRUD+校验) | 合适 | 直接创建 | +| "用户积分-新增积分接口"(仅一个 API) | 太小 | 合并到功能级需求,或用任务(task) | +| "用户积分-新增 model 层"(按技术层拆) | 错误 | 按功能拆,不按技术层拆 | + +### AI 自动检测规则 + +**标题过宽信号**(建议拆分): +- 含"系统"/"模块"/"平台"/"管理"等宏观词 +- 描述中功能点 > 5 个 +- 预估涉及文件 > 15 个 + +**标题过窄信号**(建议合并或改 task): +- 含"新增XX接口"/"修改XX字段"/"加一个按钮" +- 单个 CRUD 操作 +- 预估涉及文件 ≤ 2 个 + +**错误拆分信号**(按技术层拆了): +- 标题含"model 层"/"service 层"/"handler 层"/"前端样式" +- 同一业务被拆为"后端接口"和"前端页面"两个独立需求 + +### 执行时机 + +1. **创建需求时**(`/req new` 或 `create_requirement`):检查标题,给出建议 +2. **编辑需求时**:功能清单超 8 项时提醒"是否应拆分" +3. **独立评估**:用 `/req split <标题>` 预判粒度 + +### 三种输出 + +1. **粒度合适** → 正常创建 +2. **建议拆分** → 列出子功能建议,用户确认后批量创建 +3. **建议改 task/QUICK** → 提示"这个用任务更合适" + +### 已有需求扩展功能的决策 + +> **"去掉这个新功能点,原需求还能独立交付吗?"** +> - 能 → 新建需求 +> - 不能 → 修改原需求(`/req edit`) + +| 场景 | 建议 | +|------|------| +| 新功能是原需求的自然延伸 | 修改原需求 | +| 新功能可独立上线 | 新建需求 | +| 原需求已完成/归档 | 必须新建 | +| 原需求开发中,新增会影响已有代码 | 新建(防范围蔓延) | + +### 前后端拆分规则 + +``` +✅ 正确: + REQ-001 用户积分规则管理-后端(含 CRUD 全部接口) + REQ-002 用户积分规则管理-前端(含 CRUD 全部页面) + +❌ 错误: + REQ-001 用户积分规则-新增接口 + REQ-002 用户积分规则-查询接口 + REQ-003 用户积分规则-修改接口 +``` + +--- + ## 用户故事编写 ### 标准格式