Files
ai-proj-helper/hooks/session-context.sh
johnQ b390c29af3
skill-gate / gate (pull_request) Waiting to run
chore(skill): 安全扫描警告清零 + 加入 skill-gate CI
- scan-skill.sh: loopback 不算风险、命中走允许清单
- 11 个文件的 /Users/<机器名> 绝对路径去环境化(脚本 $HOME、文档 ~)
- 允许清单登记运维环境地址与示例占位符(非凭据),附理由
- scan: 57 warns -> 0 warns / 0 high
- 新增 .gitea/workflows/skill-gate.yml(validate --strict + scan + catalog --check + 测试)
2026-10-31 22:24:05 +08:00

131 lines
4.0 KiB
Bash
Executable File
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/bin/bash
# session-context.sh
# SessionStart Hook: 会话启动时自动注入需求上下文
#
# 从当前 Git 分支名解析 REQ-ID,调用 ai-proj MCP API 查询需求详情,
# 把标题 / 状态 / delivery_stage / reviewer / 进行中需求数注入 system-reminder。
#
# 安装方式:
# 在 ~/.claude/settings.json 的 hooks.SessionStart 配置:
# {
# "command": "$HOME/coding/qiudl/ai-proj-helper/hooks/session-context.sh",
# "timeout": 10
# }
#
# 参考:devflow-claude 同名脚本 + ai-proj MCP 适配
# REQ-20260416-0017 P0-1
set -e
# 仅在 git 仓库内执行
if ! git rev-parse --git-dir >/dev/null 2>&1; then
exit 0
fi
REPO_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
if [ -z "$REPO_ROOT" ]; then
exit 0
fi
cd "$REPO_ROOT"
# ============ 1. 当前分支 → REQ ID ============
BRANCH=$(git symbolic-ref --short HEAD 2>/dev/null || echo "")
REQ_ID=""
if [ -n "$BRANCH" ]; then
# 匹配 feat/REQ-20260416-0017-xxx / fix/REQ-20260416-0017 / feature/req-20260416-0017
REQ_ID=$(echo "$BRANCH" | grep -oiE 'REQ-[0-9]{8}-[0-9]{4}' | head -1 | tr '[:lower:]' '[:upper:]')
fi
# ============ 2. 无 REQ 时仅输出分支信息(静默退出条件) ============
if [ -z "$REQ_ID" ]; then
# 只要不在 main/develop 上就提示一下
case "$BRANCH" in
main|master|develop|"") exit 0 ;;
esac
echo "# 会话上下文"
echo ""
echo "- 当前分支: \`${BRANCH}\`(未检测到 REQ ID)"
exit 0
fi
# ============ 3. 查询 MCP API ============
# MCP API 通过 localhost:8080 直连(ai-proj 本地后端)或 ai-proj-prod
# 这里优先读项目根的 .ai-proj-env 决定环境
API_BASE="${AI_PROJ_API_BASE:-}"
API_TOKEN="${AI_PROJ_MCP_KEY:-}"
if [ -f "$REPO_ROOT/.ai-proj-env" ]; then
# shellcheck disable=SC1091
source "$REPO_ROOT/.ai-proj-env"
fi
if [ -z "$API_BASE" ]; then
# 默认走本地 dev
API_BASE="http://localhost:8080"
fi
# 查询需求
RESP=""
if command -v curl >/dev/null 2>&1; then
if [ -n "$API_TOKEN" ]; then
RESP=$(curl -s --max-time 3 -H "X-MCP-API-Key: $API_TOKEN" \
"${API_BASE}/api/v1/mcp/requirements/by-display-id/${REQ_ID}" 2>/dev/null || echo "")
else
RESP=$(curl -s --max-time 3 \
"${API_BASE}/api/v1/mcp/requirements/by-display-id/${REQ_ID}" 2>/dev/null || echo "")
fi
fi
# ============ 4. 解析并输出 ============
echo "# 需求上下文(SessionStart Hook)"
echo ""
echo "- 分支: \`${BRANCH}\`"
echo "- 需求: **${REQ_ID}**"
if [ -n "$RESP" ] && command -v python3 >/dev/null 2>&1; then
# 尝试用 python 解析
PARSED=$(python3 -c "
import sys, json
try:
d = json.loads('''$RESP''')
data = d.get('data', {})
if not data:
sys.exit(0)
title = data.get('title', '?')
status = data.get('status', '?')
stage = data.get('delivery_stage', '?')
priority = data.get('priority', '?')
project = data.get('project_name', '?')
print(f'title={title}')
print(f'status={status}')
print(f'stage={stage}')
print(f'priority={priority}')
print(f'project={project}')
except Exception:
pass
" 2>/dev/null)
if [ -n "$PARSED" ]; then
TITLE=$(echo "$PARSED" | grep '^title=' | sed 's/^title=//')
STATUS=$(echo "$PARSED" | grep '^status=' | sed 's/^status=//')
STAGE=$(echo "$PARSED" | grep '^stage=' | sed 's/^stage=//')
PRIORITY=$(echo "$PARSED" | grep '^priority=' | sed 's/^priority=//')
PROJECT=$(echo "$PARSED" | grep '^project=' | sed 's/^project=//')
[ -n "$TITLE" ] && echo "- 标题: ${TITLE}"
[ -n "$PROJECT" ] && echo "- 项目: ${PROJECT}"
[ -n "$STATUS" ] && echo "- 状态: ${STATUS}"
[ -n "$STAGE" ] && echo "- 交付阶段: ${STAGE}"
[ -n "$PRIORITY" ] && echo "- 优先级: ${PRIORITY}"
else
echo "- 📡 MCP API 响应为空或未授权(API_BASE=${API_BASE})"
fi
else
echo "- ⚠️ 无法连接 MCP API(${API_BASE}),仅显示分支信息"
fi
echo ""
echo "💡 相关命令:\`/req get ${REQ_ID}\` 查看详情 · \`/commit\` 智能提交"