feat: P1-10/12/13/14 风险扫描 + 粒度判断 + Issue 集成 + PRD 校验 (REQ-20260416-0017)

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)
This commit is contained in:
2026-04-19 13:33:26 +09:30
parent 79c4e55719
commit e5805cbb51
6 changed files with 389 additions and 0 deletions

View File

@@ -35,6 +35,18 @@
], ],
"strict": false "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", "name": "publish-plugin",
"source": "./skills-core/publish-plugin", "source": "./skills-core/publish-plugin",

98
hooks/validate-prd.sh Executable file
View File

@@ -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: "<path>/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

View File

@@ -0,0 +1,8 @@
{
"name": "pm-risk-plugin",
"description": "三维度项目风险扫描:需求层/代码层/流程层。当用户说'/risk'、'风险扫描'、'有什么风险'时自动激活",
"version": "1.0.0",
"author": {
"name": "qiudl"
}
}

View File

@@ -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

View File

@@ -114,6 +114,48 @@ feat/REQ-xxx-i42 + commit → commit message 自动加 "closes #42"
确认提交?(y/n) 确认提交?(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 集成 ## 与 ai-proj 集成
- **查询当前需求**:通过 MCP `mcp__ai-proj__find_requirement``list_requirements` 找 user 进行中的 - **查询当前需求**:通过 MCP `mcp__ai-proj__find_requirement``list_requirements` 找 user 进行中的

View File

@@ -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 用户积分规则-修改接口
```
---
## 用户故事编写 ## 用户故事编写
### 标准格式 ### 标准格式