feat: P1-8 客户场景章节 + P1-9 pm-ask skill (REQ-20260416-0017) #2
@@ -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
98
hooks/validate-prd.sh
Executable 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
|
||||||
8
skills-core/pm-risk-plugin/.claude-plugin/plugin.json
Normal file
8
skills-core/pm-risk-plugin/.claude-plugin/plugin.json
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
{
|
||||||
|
"name": "pm-risk-plugin",
|
||||||
|
"description": "三维度项目风险扫描:需求层/代码层/流程层。当用户说'/risk'、'风险扫描'、'有什么风险'时自动激活",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"author": {
|
||||||
|
"name": "qiudl"
|
||||||
|
}
|
||||||
|
}
|
||||||
154
skills-core/pm-risk-plugin/skills/SKILL.md
Normal file
154
skills-core/pm-risk-plugin/skills/SKILL.md
Normal 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
|
||||||
@@ -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 进行中的
|
||||||
|
|||||||
@@ -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 用户积分规则-修改接口
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
## 用户故事编写
|
## 用户故事编写
|
||||||
|
|
||||||
### 标准格式
|
### 标准格式
|
||||||
|
|||||||
Reference in New Issue
Block a user