skill-gate / gate (pull_request) Waiting to run
- scan-skill.sh: loopback 不算风险、命中走允许清单 - 11 个文件的 /Users/<机器名> 绝对路径去环境化(脚本 $HOME、文档 ~) - 允许清单登记运维环境地址与示例占位符(非凭据),附理由 - scan: 57 warns -> 0 warns / 0 high - 新增 .gitea/workflows/skill-gate.yml(validate --strict + scan + catalog --check + 测试)
131 lines
4.0 KiB
Bash
Executable File
131 lines
4.0 KiB
Bash
Executable File
#!/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\` 智能提交"
|