add-coder 0.3.27 → 0.3.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +246 -145
- package/package.json +2 -1
- package/templates/.add-coder-src-hash.json +126 -148
- package/templates/adapters/claude/hooks/doc-format-guard.ts +32 -0
- package/templates/adapters/claude/hooks/lib/claude-env.ts +7 -0
- package/templates/adapters/claude/hooks/notification.ts +24 -0
- package/templates/adapters/claude/hooks/permission-denied.ts +33 -0
- package/templates/adapters/claude/hooks/permission-gate.ts +12 -0
- package/templates/adapters/claude/hooks/post-tool-failure.ts +4 -0
- package/templates/adapters/claude/hooks/post-tool-use.ts +17 -0
- package/templates/adapters/claude/hooks/pre-compact.ts +10 -0
- package/templates/adapters/claude/hooks/pre-tool-use.ts +81 -0
- package/templates/adapters/claude/hooks/prompt-submit.ts +82 -0
- package/templates/adapters/claude/hooks/review-checklist.ts +4 -0
- package/templates/adapters/claude/hooks/session-end.ts +10 -0
- package/templates/adapters/claude/hooks/session-start.ts +24 -0
- package/templates/adapters/claude/hooks/stop-check.ts +15 -0
- package/templates/adapters/claude/hooks/stop-failure.ts +34 -0
- package/templates/adapters/claude/hooks/subagent-guard.ts +25 -0
- package/templates/adapters/claude/hooks/subagent-stop.ts +12 -0
- package/templates/adapters/claude/settings.json +13 -13
- package/templates/adapters/codex/hooks/doc-format-guard.ts +30 -0
- package/templates/adapters/codex/hooks/notification.ts +26 -0
- package/templates/adapters/codex/hooks/permission-gate.ts +15 -0
- package/templates/adapters/codex/hooks/post-tool-failure.ts +14 -0
- package/templates/adapters/codex/hooks/post-tool-use.ts +85 -0
- package/templates/adapters/codex/hooks/pre-compact.ts +20 -0
- package/templates/adapters/codex/hooks/pre-tool-use.ts +141 -0
- package/templates/adapters/codex/hooks/prompt-submit.ts +38 -0
- package/templates/adapters/codex/hooks/review-checklist.ts +5 -0
- package/templates/adapters/codex/hooks/session-end.ts +19 -0
- package/templates/adapters/codex/hooks/session-start.ts +45 -0
- package/templates/adapters/codex/hooks/stop-check.ts +59 -0
- package/templates/adapters/codex/hooks/subagent-guard.ts +22 -0
- package/templates/adapters/codex/hooks/subagent-stop.ts +20 -0
- package/templates/adapters/codex/hooks.json +5 -5
- package/templates/adapters/qoder/hooks/doc-format-guard.ts +34 -0
- package/templates/adapters/qoder/hooks/lib/context-inject.ts +61 -0
- package/templates/adapters/qoder/hooks/lib/qoder-env.ts +23 -0
- package/templates/adapters/qoder/hooks/lib/review-checklist.ts +5 -0
- package/templates/adapters/qoder/hooks/notification.ts +34 -0
- package/templates/adapters/qoder/hooks/permission-gate.ts +26 -0
- package/templates/adapters/qoder/hooks/post-tool-failure.ts +30 -0
- package/templates/adapters/qoder/hooks/post-tool-use.ts +32 -0
- package/templates/adapters/qoder/hooks/pre-compact.ts +16 -0
- package/templates/adapters/qoder/hooks/pre-tool-use.ts +112 -0
- package/templates/adapters/qoder/hooks/prompt-submit.ts +66 -0
- package/templates/adapters/qoder/hooks/review-checklist.ts +24 -0
- package/templates/adapters/qoder/hooks/session-end.ts +27 -0
- package/templates/adapters/qoder/hooks/session-start.ts +83 -0
- package/templates/adapters/qoder/hooks/stop-check.ts +69 -0
- package/templates/adapters/qoder/hooks/subagent-guard.ts +16 -0
- package/templates/adapters/qoder/hooks/subagent-stop.ts +33 -0
- package/templates/adapters/qoder/settings.json +13 -13
- package/templates/adapters/trae/hooks/doc-format-guard.ts +30 -0
- package/templates/adapters/trae/hooks/notification.ts +22 -0
- package/templates/adapters/trae/hooks/permission-gate.ts +15 -0
- package/templates/adapters/trae/hooks/post-tool-failure.ts +14 -0
- package/templates/adapters/trae/hooks/post-tool-use.ts +24 -0
- package/templates/adapters/trae/hooks/pre-compact.ts +15 -0
- package/templates/adapters/trae/hooks/pre-tool-use.ts +40 -0
- package/templates/adapters/trae/hooks/prompt-submit.ts +29 -0
- package/templates/adapters/trae/hooks/review-checklist.ts +5 -0
- package/templates/adapters/trae/hooks/session-end.ts +16 -0
- package/templates/adapters/trae/hooks/session-start.ts +15 -0
- package/templates/adapters/trae/hooks/stop-check.ts +20 -0
- package/templates/adapters/trae/hooks/subagent-guard.ts +22 -0
- package/templates/adapters/trae/hooks/subagent-stop.ts +15 -0
- package/templates/adapters/trae/hooks.json +1 -1
- package/templates/adapters/vscode/hooks/doc-format-guard.ts +27 -0
- package/templates/adapters/vscode/hooks/notification.ts +22 -0
- package/templates/adapters/vscode/hooks/permission-gate.ts +15 -0
- package/templates/adapters/vscode/hooks/post-tool-failure.ts +32 -0
- package/templates/adapters/vscode/hooks/post-tool-use.ts +25 -0
- package/templates/adapters/vscode/hooks/pre-compact.ts +15 -0
- package/templates/adapters/vscode/hooks/pre-tool-use.ts +78 -0
- package/templates/adapters/vscode/hooks/prompt-submit.ts +74 -0
- package/templates/adapters/vscode/hooks/review-checklist.ts +5 -0
- package/templates/adapters/vscode/hooks/session-end.ts +16 -0
- package/templates/adapters/vscode/hooks/session-start.ts +24 -0
- package/templates/adapters/vscode/hooks/stop-check.ts +21 -0
- package/templates/adapters/vscode/hooks/subagent-guard.ts +21 -0
- package/templates/adapters/vscode/hooks/subagent-stop.ts +15 -0
- package/templates/core/docs/ADD-governance-claude-code.md +3 -3
- package/templates/core/docs/ADD-governance-codex.md +5 -5
- package/templates/core/docs/ADD-governance-qoder-cn.md +4 -4
- package/templates/core/docs/ADD-governance-trae.md +2 -2
- package/templates/core/docs/ADD-governance-vscode-copilot.md +21 -22
- package/templates/core/governance/audit-bridge.ts +47 -0
- package/templates/core/governance/common.ts +299 -0
- package/templates/core/governance/context-inject.ts +53 -0
- package/templates/core/governance/doc-format-guard.ts +440 -0
- package/templates/core/governance/notification-router.ts +62 -0
- package/templates/core/governance/notify.ts +66 -0
- package/templates/core/governance/permission-gate-router.ts +42 -0
- package/templates/core/governance/post-tool-failure-router.ts +56 -0
- package/templates/core/governance/post-tool-router.ts +212 -0
- package/templates/core/governance/pre-compact-guard.ts +41 -0
- package/templates/core/governance/pre-tool-guard.ts +309 -0
- package/templates/core/governance/preload-templates.ts +241 -0
- package/templates/core/governance/prompt-router.ts +222 -0
- package/templates/core/governance/review-checklist-guard.ts +186 -0
- package/templates/core/governance/rules.ts +720 -0
- package/templates/core/governance/session-end.ts +88 -0
- package/templates/core/governance/session-start-guard.ts +99 -0
- package/templates/core/governance/state-detect.ts +6 -0
- package/templates/core/governance/stop-router.ts +140 -0
- package/templates/core/governance/subagent-guard-router.ts +35 -0
- package/templates/core/governance/subagent-stop-router.ts +93 -0
- package/templates/core/governance/subagent-stop.ts +75 -0
- package/templates/core/governance/vocabulary.ts +109 -0
- package/templates/core/hooks/doc-format-guard.ts +21 -0
- package/templates/core/hooks/notification.ts +11 -0
- package/templates/core/hooks/permission-gate.ts +7 -0
- package/templates/core/hooks/post-tool-failure.ts +7 -0
- package/templates/core/hooks/post-tool-use.ts +23 -0
- package/templates/core/hooks/pre-compact.ts +9 -0
- package/templates/core/hooks/pre-tool-use.ts +30 -0
- package/templates/core/hooks/prompt-submit.ts +11 -0
- package/templates/core/hooks/review-checklist.ts +4 -0
- package/templates/core/hooks/session-end.ts +10 -0
- package/templates/core/hooks/session-start.ts +9 -0
- package/templates/core/hooks/stop-check.ts +14 -0
- package/templates/core/hooks/subagent-guard.ts +8 -0
- package/templates/core/hooks/subagent-stop.ts +9 -0
- package/templates/core/scripts/mcp-server/tools/gateway/check_rahs.ts +12 -1
- package/templates/core/scripts/mcp-server/tools/plan.ts +12 -2
- package/templates/adapters/claude/hooks/doc-format-guard.sh +0 -283
- package/templates/adapters/claude/hooks/lib/common.sh +0 -220
- package/templates/adapters/claude/hooks/lib/context-inject.sh +0 -96
- package/templates/adapters/claude/hooks/lib/notify.sh +0 -36
- package/templates/adapters/claude/hooks/lib/preload-templates.sh +0 -212
- package/templates/adapters/claude/hooks/lib/session-end.sh +0 -76
- package/templates/adapters/claude/hooks/lib/state-detect.sh +0 -13
- package/templates/adapters/claude/hooks/lib/subagent-stop.sh +0 -90
- package/templates/adapters/claude/hooks/lib/vocabulary.sh +0 -62
- package/templates/adapters/claude/hooks/notification.sh +0 -45
- package/templates/adapters/claude/hooks/permission-denied.sh +0 -42
- package/templates/adapters/claude/hooks/permission-gate.sh +0 -18
- package/templates/adapters/claude/hooks/post-tool-failure.sh +0 -10
- package/templates/adapters/claude/hooks/post-tool-use.sh +0 -35
- package/templates/adapters/claude/hooks/pre-compact.sh +0 -37
- package/templates/adapters/claude/hooks/pre-tool-use.sh +0 -153
- package/templates/adapters/claude/hooks/prompt-submit.sh +0 -99
- package/templates/adapters/claude/hooks/review-checklist.sh +0 -10
- package/templates/adapters/claude/hooks/session-end.sh +0 -21
- package/templates/adapters/claude/hooks/session-start.sh +0 -36
- package/templates/adapters/claude/hooks/stop-check.sh +0 -54
- package/templates/adapters/claude/hooks/stop-failure.sh +0 -44
- package/templates/adapters/claude/hooks/subagent-guard.sh +0 -36
- package/templates/adapters/claude/hooks/subagent-stop.sh +0 -20
- package/templates/adapters/codex/hooks/doc-format-guard.sh +0 -343
- package/templates/adapters/codex/hooks/lib/common.sh +0 -209
- package/templates/adapters/codex/hooks/lib/context-inject.sh +0 -96
- package/templates/adapters/codex/hooks/lib/notify.sh +0 -36
- package/templates/adapters/codex/hooks/lib/preload-templates.sh +0 -208
- package/templates/adapters/codex/hooks/lib/session-end.sh +0 -76
- package/templates/adapters/codex/hooks/lib/state-detect.sh +0 -8
- package/templates/adapters/codex/hooks/lib/subagent-stop.sh +0 -90
- package/templates/adapters/codex/hooks/lib/vocabulary.sh +0 -51
- package/templates/adapters/codex/hooks/notification.sh +0 -30
- package/templates/adapters/codex/hooks/permission-gate.sh +0 -18
- package/templates/adapters/codex/hooks/post-tool-failure.sh +0 -10
- package/templates/adapters/codex/hooks/post-tool-use.sh +0 -43
- package/templates/adapters/codex/hooks/pre-compact.sh +0 -37
- package/templates/adapters/codex/hooks/pre-tool-use.sh +0 -130
- package/templates/adapters/codex/hooks/prompt-submit.sh +0 -92
- package/templates/adapters/codex/hooks/review-checklist.sh +0 -10
- package/templates/adapters/codex/hooks/session-end.sh +0 -38
- package/templates/adapters/codex/hooks/session-start.sh +0 -63
- package/templates/adapters/codex/hooks/stop-check.sh +0 -71
- package/templates/adapters/codex/hooks/subagent-guard.sh +0 -15
- package/templates/adapters/codex/hooks/subagent-stop.sh +0 -47
- package/templates/adapters/qoder/hooks/doc-format-guard.sh +0 -341
- package/templates/adapters/qoder/hooks/lib/common.sh +0 -223
- package/templates/adapters/qoder/hooks/lib/context-inject.sh +0 -96
- package/templates/adapters/qoder/hooks/lib/notify.sh +0 -36
- package/templates/adapters/qoder/hooks/lib/preload-templates.sh +0 -212
- package/templates/adapters/qoder/hooks/lib/session-end.sh +0 -76
- package/templates/adapters/qoder/hooks/lib/state-detect.sh +0 -13
- package/templates/adapters/qoder/hooks/lib/subagent-stop.sh +0 -90
- package/templates/adapters/qoder/hooks/lib/vocabulary.sh +0 -62
- package/templates/adapters/qoder/hooks/notification.sh +0 -25
- package/templates/adapters/qoder/hooks/permission-gate.sh +0 -8
- package/templates/adapters/qoder/hooks/post-tool-failure.sh +0 -8
- package/templates/adapters/qoder/hooks/post-tool-use.sh +0 -121
- package/templates/adapters/qoder/hooks/pre-compact.sh +0 -37
- package/templates/adapters/qoder/hooks/pre-tool-use.sh +0 -154
- package/templates/adapters/qoder/hooks/prompt-submit.sh +0 -96
- package/templates/adapters/qoder/hooks/review-checklist.sh +0 -157
- package/templates/adapters/qoder/hooks/session-end.sh +0 -24
- package/templates/adapters/qoder/hooks/session-start.sh +0 -45
- package/templates/adapters/qoder/hooks/stop-check.sh +0 -59
- package/templates/adapters/qoder/hooks/subagent-guard.sh +0 -27
- package/templates/adapters/qoder/hooks/subagent-stop.sh +0 -26
- package/templates/adapters/trae/hooks/doc-format-guard.sh +0 -343
- package/templates/adapters/trae/hooks/lib/common.sh +0 -220
- package/templates/adapters/trae/hooks/lib/context-inject.sh +0 -96
- package/templates/adapters/trae/hooks/lib/notify.sh +0 -36
- package/templates/adapters/trae/hooks/lib/preload-templates.sh +0 -212
- package/templates/adapters/trae/hooks/lib/session-end.sh +0 -76
- package/templates/adapters/trae/hooks/lib/state-detect.sh +0 -10
- package/templates/adapters/trae/hooks/lib/subagent-stop.sh +0 -90
- package/templates/adapters/trae/hooks/lib/vocabulary.sh +0 -62
- package/templates/adapters/trae/hooks/notification.sh +0 -45
- package/templates/adapters/trae/hooks/permission-gate.sh +0 -18
- package/templates/adapters/trae/hooks/post-tool-failure.sh +0 -10
- package/templates/adapters/trae/hooks/post-tool-use.sh +0 -138
- package/templates/adapters/trae/hooks/pre-compact.sh +0 -37
- package/templates/adapters/trae/hooks/pre-tool-use.sh +0 -223
- package/templates/adapters/trae/hooks/prompt-submit.sh +0 -87
- package/templates/adapters/trae/hooks/review-checklist.sh +0 -10
- package/templates/adapters/trae/hooks/session-end.sh +0 -38
- package/templates/adapters/trae/hooks/session-start.sh +0 -53
- package/templates/adapters/trae/hooks/stop-check.sh +0 -54
- package/templates/adapters/trae/hooks/subagent-guard.sh +0 -15
- package/templates/adapters/trae/hooks/subagent-stop.sh +0 -47
- package/templates/adapters/vscode/hooks/doc-format-guard.sh +0 -282
- package/templates/adapters/vscode/hooks/lib/common.sh +0 -220
- package/templates/adapters/vscode/hooks/lib/context-inject.sh +0 -96
- package/templates/adapters/vscode/hooks/lib/notify.sh +0 -36
- package/templates/adapters/vscode/hooks/lib/preload-templates.sh +0 -212
- package/templates/adapters/vscode/hooks/lib/session-end.sh +0 -76
- package/templates/adapters/vscode/hooks/lib/state-detect.sh +0 -13
- package/templates/adapters/vscode/hooks/lib/subagent-stop.sh +0 -90
- package/templates/adapters/vscode/hooks/lib/vocabulary.sh +0 -62
- package/templates/adapters/vscode/hooks/notification.sh +0 -43
- package/templates/adapters/vscode/hooks/permission-gate.sh +0 -18
- package/templates/adapters/vscode/hooks/post-tool-failure.sh +0 -28
- package/templates/adapters/vscode/hooks/post-tool-use.sh +0 -35
- package/templates/adapters/vscode/hooks/pre-compact.sh +0 -37
- package/templates/adapters/vscode/hooks/pre-tool-use.sh +0 -153
- package/templates/adapters/vscode/hooks/prompt-submit.sh +0 -99
- package/templates/adapters/vscode/hooks/review-checklist.sh +0 -10
- package/templates/adapters/vscode/hooks/session-end.sh +0 -13
- package/templates/adapters/vscode/hooks/session-start.sh +0 -35
- package/templates/adapters/vscode/hooks/stop-check.sh +0 -62
- package/templates/adapters/vscode/hooks/subagent-guard.sh +0 -37
- package/templates/adapters/vscode/hooks/subagent-stop.sh +0 -12
- package/templates/core/hooks/doc-format-guard.sh +0 -343
- package/templates/core/hooks/lib/common.sh +0 -220
- package/templates/core/hooks/lib/context-inject.sh +0 -96
- package/templates/core/hooks/lib/notify.sh +0 -36
- package/templates/core/hooks/lib/preload-templates.sh +0 -212
- package/templates/core/hooks/lib/session-end.sh +0 -76
- package/templates/core/hooks/lib/state-detect.sh +0 -10
- package/templates/core/hooks/lib/subagent-stop.sh +0 -90
- package/templates/core/hooks/lib/vocabulary.sh +0 -62
- package/templates/core/hooks/notification.sh +0 -45
- package/templates/core/hooks/permission-gate.sh +0 -18
- package/templates/core/hooks/post-tool-failure.sh +0 -10
- package/templates/core/hooks/post-tool-use.sh +0 -138
- package/templates/core/hooks/pre-compact.sh +0 -37
- package/templates/core/hooks/pre-tool-use.sh +0 -223
- package/templates/core/hooks/prompt-submit.sh +0 -87
- package/templates/core/hooks/review-checklist.sh +0 -10
- package/templates/core/hooks/session-end.sh +0 -38
- package/templates/core/hooks/session-start.sh +0 -53
- package/templates/core/hooks/stop-check.sh +0 -54
- package/templates/core/hooks/subagent-guard.sh +0 -15
- package/templates/core/hooks/subagent-stop.sh +0 -47
- package/templates/shared/hooks-lib/common.sh +0 -22
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# post-tool-use.sh — PostToolUse:格式化 + 文档守卫 + 审计提醒 + DPS 自动化
|
|
3
|
-
# 治理卡位 #5: 格式化 + ADD文档守卫 + 审计落库 + 结果增强 + 哨兵自动化
|
|
4
|
-
set -euo pipefail
|
|
5
|
-
|
|
6
|
-
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
7
|
-
COMMON_LIB="$HOOK_DIR/lib/common.sh"
|
|
8
|
-
[ -f "$COMMON_LIB" ] && source "$COMMON_LIB"
|
|
9
|
-
|
|
10
|
-
input=$(parse_input)
|
|
11
|
-
tool_name=$(json_get "$input" "tool_name")
|
|
12
|
-
[ -z "$tool_name" ] && tool_name=$(echo "$input" | grep -o '"tool_name"[[:space:]]*:[[:space:]]*"[^"]*"' 2>/dev/null | sed 's/.*: *"\([^"]*\)".*/\1/' || echo "")
|
|
13
|
-
|
|
14
|
-
# ═══════════════ §1: HITL DPS 自动化 — check_dps ≥ 80 → 自动建哨兵 ═══════════════
|
|
15
|
-
# 检测 MCP check_dps 调用结果,DPS ≥ 80 自动 touch .tongyi-{plan} 哨兵
|
|
16
|
-
if echo "$input" | grep -q '"check_dps"'; then
|
|
17
|
-
tool_output=$(echo "$input" | grep -o '"output"[[:space:]]*:[[:space:]]*"[^"]*"\|"content"[[:space:]]*:[[:space:]]*"[^"]*"' 2>/dev/null || echo "")
|
|
18
|
-
dps_score=$(echo "$tool_output" | grep -oP 'DPS\s*=\s*\K\d+' 2>/dev/null || echo "")
|
|
19
|
-
plan_keyword=$(echo "$input" | grep -oP '"planKeyword"\s*:\s*"\K[^"]+' 2>/dev/null || echo "")
|
|
20
|
-
|
|
21
|
-
if [ -n "$dps_score" ] && [ -n "$plan_keyword" ]; then
|
|
22
|
-
if [ "$dps_score" -ge 80 ] 2>/dev/null; then
|
|
23
|
-
sentinel="${PROJECT_DIR:-$PWD}/${MAGIC_DIR:-.qoder}/hitl/.tongyi-${plan_keyword}"
|
|
24
|
-
if [ ! -f "$sentinel" ]; then
|
|
25
|
-
touch "$sentinel" 2>/dev/null && echo "[ADD PostToolUse] ✅ DPS=${dps_score} ≥80, HITL 自动通过 → ${sentinel}" >&2 || true
|
|
26
|
-
echo "[ADD PostToolUse] DPS=${dps_score} ≥80, 已自动建哨兵 ${sentinel}" >&2
|
|
27
|
-
else
|
|
28
|
-
echo "[ADD PostToolUse] DPS=${dps_score} ≥80, 哨兵已存在 → ${sentinel}" >&2
|
|
29
|
-
fi
|
|
30
|
-
else
|
|
31
|
-
echo "[ADD PostToolUse] ⚠️ DPS=${dps_score} <80, 需 Review 后手动建哨兵 .tongyi-${plan_keyword}" >&2
|
|
32
|
-
echo "[ADD PostToolUse] 修复文档后重新 check_dps,通过即自动放行。" >&2
|
|
33
|
-
fi
|
|
34
|
-
fi
|
|
35
|
-
fi
|
|
36
|
-
|
|
37
|
-
# ═══════════════ §2: Edit/Write matcher: 格式化 + 文档守卫 + 自动 plan_track ═══════════════
|
|
38
|
-
if [ "$tool_name" = "Edit" ] || [ "$tool_name" = "Write" ]; then
|
|
39
|
-
file_path=$(echo "$input" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' 2>/dev/null | sed 's/.*: *"\([^"]*\)".*/\1/' || echo "")
|
|
40
|
-
[ -z "$file_path" ] && exit 0
|
|
41
|
-
|
|
42
|
-
# §2a: ADD 文档结构守卫
|
|
43
|
-
if echo "$file_path" | grep -qE '\.(qoder|claude|add)/(plans|specs|reviews)/'; then
|
|
44
|
-
echo "[ADD PostToolUse] ADD 文档已写入: ${file_path}。请确保章节完整、双向链接齐全。" >&2
|
|
45
|
-
fi
|
|
46
|
-
|
|
47
|
-
# §2b: plan_track 自动触发 — specs/ 或 add-route 写入后自动落库
|
|
48
|
-
if echo "$file_path" | grep -qE '/(specs|plans)/.*add-route'; then
|
|
49
|
-
plan_name=$(basename "$file_path" | sed 's/-add-route.*//' | sed 's/-plan-v[0-9]*$//')
|
|
50
|
-
# 从路径提取完整 planName(含 -plan-vN 后缀)
|
|
51
|
-
if echo "$file_path" | grep -qE 'add-route'; then
|
|
52
|
-
# add-route 写入:从文件名反推 planName
|
|
53
|
-
plan_prefix=$(basename "$file_path" | sed 's/-add-route-v[0-9]*\.md$//')
|
|
54
|
-
plan_dir=$(dirname "$file_path")
|
|
55
|
-
if [ -d "$plan_dir" ]; then
|
|
56
|
-
plan_file=$(ls "$plan_dir"/*-plan-v*.md 2>/dev/null | head -1 || echo "")
|
|
57
|
-
if [ -n "$plan_file" ]; then
|
|
58
|
-
plan_name=$(basename "$plan_file" .md)
|
|
59
|
-
fi
|
|
60
|
-
fi
|
|
61
|
-
fi
|
|
62
|
-
if [ -n "$plan_name" ]; then
|
|
63
|
-
echo "[ADD PostToolUse] 📊 自动同步 PlanRecord: plan_track({ planName: \"${plan_name}\" }) — 请执行" >&2
|
|
64
|
-
fi
|
|
65
|
-
fi
|
|
66
|
-
|
|
67
|
-
# §2c: devlog 自动提醒 — add-route Step 8 全 [x] 时提醒
|
|
68
|
-
if echo "$file_path" | grep -qE 'add-route.*\.md$'; then
|
|
69
|
-
if [ -f "$file_path" ]; then
|
|
70
|
-
step8_content=$(sed -n '/## Step 8/,/^## /p' "$file_path" 2>/dev/null || echo "")
|
|
71
|
-
unchecked=$(echo "$step8_content" | grep -c '^\- \[ \]' 2>/dev/null || echo "0")
|
|
72
|
-
checked=$(echo "$step8_content" | grep -c '^\- \[x\]' 2>/dev/null || echo "0")
|
|
73
|
-
if [ "$unchecked" = "0" ] && [ "$checked" -gt 0 ]; then
|
|
74
|
-
echo "[ADD PostToolUse] ⚠️ Step 8 全部收敛完成!请写 devlog日志(走mcp) → 更新 handoff" >&2
|
|
75
|
-
fi
|
|
76
|
-
fi
|
|
77
|
-
fi
|
|
78
|
-
|
|
79
|
-
# §2d: schema.json 自动 regen — 模板 .md 修改后更新对应 schema
|
|
80
|
-
if echo "$file_path" | grep -qE 'templates/.*\.md$'; then
|
|
81
|
-
schema_file="${file_path%.md}.schema.json"
|
|
82
|
-
if [ -f "$schema_file" ]; then
|
|
83
|
-
# 扫描模板实际 ## 标题,更新 schema sections
|
|
84
|
-
headings=$(grep -oP '^## \K.+' "$file_path" 2>/dev/null | head -20 || echo "")
|
|
85
|
-
if [ -n "$headings" ]; then
|
|
86
|
-
echo "[ADD PostToolUse] 🔄 模板已修改,请检查 ${schema_file} 是否需更新(§ sections)" >&2
|
|
87
|
-
echo "[ADD PostToolUse] 模板标题: $(echo "$headings" | tr '\n' ' ')" >&2
|
|
88
|
-
fi
|
|
89
|
-
fi
|
|
90
|
-
fi
|
|
91
|
-
|
|
92
|
-
# §2e: 审计提醒
|
|
93
|
-
echo "[ADD PostToolUse] 文件已写入: ${file_path}。请执行 record_dev_operation 落库审计(ADD-7)。" >&2
|
|
94
|
-
exit 0
|
|
95
|
-
fi
|
|
96
|
-
|
|
97
|
-
# ═══════════════ §3: Bash matcher: 结果增强 ═══════════════
|
|
98
|
-
if [ "$tool_name" = "Bash" ]; then
|
|
99
|
-
echo "[ADD PostToolUse] 命令执行完成。如有 lint/tsc 错误请修复。" >&2
|
|
100
|
-
exit 0
|
|
101
|
-
fi
|
|
102
|
-
|
|
103
|
-
exit 0
|
|
104
|
-
#!/bin/bash
|
|
105
|
-
# post-tool-use.sh — Claude Code PostToolUse:格式化 + 文档守卫 + 审计提醒
|
|
106
|
-
# 治理卡位 #5: 格式化 + ADD文档守卫 + 审计落库 + 结果增强
|
|
107
|
-
set -euo pipefail
|
|
108
|
-
|
|
109
|
-
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
110
|
-
COMMON_LIB="$HOOK_DIR/lib/common.sh"
|
|
111
|
-
[ -f "$COMMON_LIB" ] && source "$COMMON_LIB"
|
|
112
|
-
|
|
113
|
-
input=$(parse_input)
|
|
114
|
-
tool_name=$(json_get "$input" "tool_name")
|
|
115
|
-
[ -z "$tool_name" ] && tool_name=$(echo "$input" | grep -o '"tool_name"[[:space:]]*:[[:space:]]*"[^"]*"' 2>/dev/null | sed 's/.*: *"\([^"]*\)".*/\1/' || echo "")
|
|
116
|
-
|
|
117
|
-
# ── Edit/Write matcher: 格式化 + ADD文档守卫 ──
|
|
118
|
-
if [ "$tool_name" = "Edit" ] || [ "$tool_name" = "Write" ]; then
|
|
119
|
-
file_path=$(echo "$input" | grep -o '"file_path"[[:space:]]*:[[:space:]]*"[^"]*"' 2>/dev/null | sed 's/.*: *"\([^"]*\)".*/\1/' || echo "")
|
|
120
|
-
[ -z "$file_path" ] && exit 0
|
|
121
|
-
|
|
122
|
-
# ADD 文档结构守卫:写入 plans/specs/reviews 后提示
|
|
123
|
-
if echo "$file_path" | grep -qE '\.(qoder|claude|add)/(plans|specs|reviews)/'; then
|
|
124
|
-
echo "[ADD PostToolUse] ADD 文档已写入: ${file_path}。请确保章节完整、双向链接齐全、增量修订格式正确。" >&2
|
|
125
|
-
fi
|
|
126
|
-
|
|
127
|
-
# 审计提醒(所有文件写入)
|
|
128
|
-
echo "[ADD PostToolUse] 文件已写入: ${file_path}。请执行 record_dev_operation 落库审计(ADD-7)。" >&2
|
|
129
|
-
exit 0
|
|
130
|
-
fi
|
|
131
|
-
|
|
132
|
-
# ── Bash matcher: 结果增强 ──
|
|
133
|
-
if [ "$tool_name" = "Bash" ]; then
|
|
134
|
-
echo "[ADD PostToolUse] 命令执行完成。如有 lint/tsc 错误请修复。" >&2
|
|
135
|
-
exit 0
|
|
136
|
-
fi
|
|
137
|
-
|
|
138
|
-
exit 0
|
|
@@ -1,37 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# pre-compact.sh — 上下文压缩前 ADD 状态保存(Claude Code 适配)
|
|
3
|
-
# 治理卡位 #9: ADD状态保存 + 恢复清单导出 + tpl标记清理
|
|
4
|
-
set -euo pipefail
|
|
5
|
-
|
|
6
|
-
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
7
|
-
export CURRENT_MAGIC=$(basename "$(dirname "$HOOK_DIR")")
|
|
8
|
-
COMMON_LIB="$HOOK_DIR/lib/common.sh"
|
|
9
|
-
[ -f "$COMMON_LIB" ] && source "$COMMON_LIB"
|
|
10
|
-
|
|
11
|
-
export PROJECT_DIR="$PWD"
|
|
12
|
-
|
|
13
|
-
# ── ① 获取 ADD 状态并保存到标记文件 ──
|
|
14
|
-
if type detect_active_add >/dev/null 2>&1; then
|
|
15
|
-
state=$(detect_active_add 2>/dev/null || true)
|
|
16
|
-
if [ -n "$state" ]; then
|
|
17
|
-
IFS='::' read -r plan step rounds handoff add_route <<< "$state"
|
|
18
|
-
|
|
19
|
-
# 写入恢复标记文件(SessionStart 恢复时读取)
|
|
20
|
-
RECOVERY_FILE="/tmp/add_recovery_$(echo "${PROJECT_DIR}" | md5sum 2>/dev/null | cut -c1-8 || echo "default")"
|
|
21
|
-
cat > "$RECOVERY_FILE" <<EOF
|
|
22
|
-
plan=${plan}
|
|
23
|
-
step=${step}
|
|
24
|
-
rounds=${rounds}
|
|
25
|
-
handoff=${handoff}
|
|
26
|
-
add_route=${add_route}
|
|
27
|
-
EOF
|
|
28
|
-
|
|
29
|
-
echo "[ADD PreCompact] ADD 状态已保存: Plan=${plan}, Step=${step}" >&2
|
|
30
|
-
fi
|
|
31
|
-
fi
|
|
32
|
-
|
|
33
|
-
# ── ② 清理 tpl-injected 标记(compact 后上下文丢失,下次需重注) ──
|
|
34
|
-
TPL_FLAG="/tmp/add_tpl_$(echo "${PROJECT_DIR}" | md5sum 2>/dev/null | cut -c1-8 || echo "default")"
|
|
35
|
-
rm -f "$TPL_FLAG" 2>/dev/null || true
|
|
36
|
-
|
|
37
|
-
exit 0
|
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# pre-tool-use.sh — PreToolUse §A§B(阻断模式,通用适配版)
|
|
3
|
-
# §A: Bash 裸写保护 — 拦截所有绕过 IDE 追踪的文件写操作
|
|
4
|
-
# §B: Write/Edit 写入前置守卫 — Plan/Spec/Review 需要活跃 ADD Plan + 敏感文件保护
|
|
5
|
-
# 治理卡位 #4: 危险命令拦截 / 模板路径兜底 / 写入前置守卫 / 敏感文件保护
|
|
6
|
-
set -euo pipefail
|
|
7
|
-
|
|
8
|
-
input=$(cat)
|
|
9
|
-
|
|
10
|
-
# 探测 MAGIC_DIR 和 PROJECT_DIR(兼容多种 adapter)
|
|
11
|
-
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
12
|
-
PARENT="$(dirname "$HOOK_DIR")"
|
|
13
|
-
MAGIC_DIR="$(basename "$PARENT")"
|
|
14
|
-
PROJECT_DIR="$PWD"
|
|
15
|
-
|
|
16
|
-
# ── Hook 通知: 拦截事件写入 jsonl(旁路,失败不阻断 exit 2)──
|
|
17
|
-
source "${HOOK_DIR}/lib/notify.sh" 2>/dev/null || true
|
|
18
|
-
ACTIVE_PLAN=$(detect_active_add 2>/dev/null || true)
|
|
19
|
-
if [ -n "$ACTIVE_PLAN" ]; then
|
|
20
|
-
PLAN_KEYWORD="${ACTIVE_PLAN%%::*}"
|
|
21
|
-
PLAN_STATUS="active"
|
|
22
|
-
else
|
|
23
|
-
PLAN_KEYWORD="no-active-plan"
|
|
24
|
-
PLAN_STATUS="none"
|
|
25
|
-
fi
|
|
26
|
-
|
|
27
|
-
# ── §A 辅助函数: 阻断日志 ──
|
|
28
|
-
_log_block() {
|
|
29
|
-
local rule="$1" cmd="$2"
|
|
30
|
-
mkdir -p "$PROJECT_DIR/$MAGIC_DIR/debug-dump"
|
|
31
|
-
cat >> "$PROJECT_DIR/$MAGIC_DIR/debug-dump/stdin.log" <<BLOCKLOG
|
|
32
|
-
=== $(date) [BLOCKED by §A: ${rule}] ===
|
|
33
|
-
command: ${cmd:0:300}
|
|
34
|
-
=== DONE ===
|
|
35
|
-
BLOCKLOG
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
# ═══════════════ §A: Bash 工具写入保护 ═══════════════
|
|
39
|
-
# 任何通过 Bash 修改文件内容的操作都会绕过 IDE 工具层(Write/SearchReplace),
|
|
40
|
-
# 导致 Plan 关联检查、doc-format-guard、审计追踪全部失效。
|
|
41
|
-
# 因此全局阻断所有可写文件的 Bash 命令,强制走 IDE 工具通道。
|
|
42
|
-
command=$(echo "$input" | jq -r '.tool_input.command // empty')
|
|
43
|
-
if [ -n "$command" ]; then
|
|
44
|
-
|
|
45
|
-
# 检测 1: 脚本解释器 — 可写任意文件,无法解析脚本内容做细粒度拦截
|
|
46
|
-
if echo "$command" | grep -qE '(^|;|\|\||&&|\|)\s*(python3?|node|ruby|perl|php)(\s|$)'; then
|
|
47
|
-
_reason="禁止通过脚本解释器直接修改文件。请使用 Write 或 SearchReplace 工具操作文件。"
|
|
48
|
-
cat >&2 <<'EOF'
|
|
49
|
-
⛔ [ADD PreToolUse §A] 阻断: 禁止通过脚本解释器直接修改文件。
|
|
50
|
-
|
|
51
|
-
python/node/ruby/perl/php 可在脚本中写入任意文件,绕过:
|
|
52
|
-
· Plan 关联检查(哪个文件属于哪个 ADD Plan?)
|
|
53
|
-
· doc-format-guard(章节/占位符/禁止词校验)
|
|
54
|
-
· 审计追踪(agentAudit 无法感知 Bash 内部的文件变更)
|
|
55
|
-
|
|
56
|
-
→ 请改用 Write 或 SearchReplace 工具操作文件。
|
|
57
|
-
→ 如需运行构建/测试脚本,使用 npx/pnpm/npm 命令。
|
|
58
|
-
EOF
|
|
59
|
-
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"ask\",\"permissionDecisionReason\":\"${_reason}\"}}"
|
|
60
|
-
_log_block "脚本解释器" "$command"
|
|
61
|
-
write_hook_event "pre-tool-use" "deny" "$command" "禁止通过脚本解释器直接修改文件" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
62
|
-
exit 2
|
|
63
|
-
fi
|
|
64
|
-
|
|
65
|
-
# 检测 2: sed -i 原地编辑(精确判定:`-i` 必须是 sed 独立 option;不把路径子串如 session-init 误判)
|
|
66
|
-
# 协议层契约(Review P0 #3/命令分类): 与 codex 已实现版本同契约语义
|
|
67
|
-
if echo "$command" | grep -qE '(^|[;&|][[:space:]]*)sed[[:space:]]+([^;&|]*[[:space:]])?(-[[:alpha:]]*i[^[:space:];&|]*|--in-place(=[^[:space:];&|]*)?)([[:space:];&|]|$)'; then
|
|
68
|
-
_reason="禁止通过 sed -i 直接编辑文件。请使用 SearchReplace 工具。"
|
|
69
|
-
cat >&2 <<'EOF'
|
|
70
|
-
⛔ [ADD PreToolUse §A] 阻断: 禁止通过 sed -i 原地编辑文件。
|
|
71
|
-
|
|
72
|
-
sed -i 直接写入文件,绕过 IDE 工具层的所有校验。
|
|
73
|
-
→ 请改用 SearchReplace 工具。
|
|
74
|
-
EOF
|
|
75
|
-
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"ask\",\"permissionDecisionReason\":\"${_reason}\"}}"
|
|
76
|
-
_log_block "sed -i" "$command"
|
|
77
|
-
write_hook_event "pre-tool-use" "deny" "$command" "禁止通过 sed -i 原地编辑" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
78
|
-
exit 2
|
|
79
|
-
fi
|
|
80
|
-
|
|
81
|
-
# 检测 3: 输出重定向 (>/>>) 写入文件
|
|
82
|
-
if echo "$command" | grep -qE '[>]{1,2}\s+\S'; then
|
|
83
|
-
_reason="禁止通过重定向写入文件。请使用 Write 工具。"
|
|
84
|
-
cat >&2 <<'EOF'
|
|
85
|
-
⛔ [ADD PreToolUse §A] 阻断: 禁止通过重定向(>/>>)写入文件。
|
|
86
|
-
|
|
87
|
-
重定向写入绕过 IDE 工具层,变更无法追踪。
|
|
88
|
-
→ 请改用 Write 工具。
|
|
89
|
-
EOF
|
|
90
|
-
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"ask\",\"permissionDecisionReason\":\"${_reason}\"}}"
|
|
91
|
-
_log_block "重定向" "$command"
|
|
92
|
-
write_hook_event "pre-tool-use" "deny" "$command" "禁止通过重定向写入文件" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
93
|
-
exit 2
|
|
94
|
-
fi
|
|
95
|
-
|
|
96
|
-
# 检测 4: tee / dd 写入
|
|
97
|
-
if echo "$command" | grep -qE '\btee\b|\bdd\b.*of='; then
|
|
98
|
-
_reason="禁止通过 tee/dd 写入文件。请使用 Write 或 SearchReplace 工具。"
|
|
99
|
-
cat >&2 <<'EOF'
|
|
100
|
-
⛔ [ADD PreToolUse §A] 阻断: 禁止通过 tee/dd 写入文件。
|
|
101
|
-
|
|
102
|
-
→ 请改用 Write 或 SearchReplace 工具。
|
|
103
|
-
EOF
|
|
104
|
-
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"ask\",\"permissionDecisionReason\":\"${_reason}\"}}"
|
|
105
|
-
_log_block "tee/dd" "$command"
|
|
106
|
-
write_hook_event "pre-tool-use" "deny" "$command" "禁止通过 tee/dd 写入文件" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
107
|
-
exit 2
|
|
108
|
-
fi
|
|
109
|
-
|
|
110
|
-
# 检测 5: cp / mv / touch — 可创建或覆盖文件
|
|
111
|
-
if echo "$command" | grep -qE '(^|;|\|\||&&|\|)\s*(cp|mv|touch)\b'; then
|
|
112
|
-
_reason="禁止通过 cp/mv/touch 操作文件。请使用 Write 或 SearchReplace 工具。"
|
|
113
|
-
cat >&2 <<'EOF'
|
|
114
|
-
⛔ [ADD PreToolUse §A] 阻断: 禁止通过 cp/mv/touch 操作文件。
|
|
115
|
-
|
|
116
|
-
→ 请改用 Write 或 SearchReplace 工具。
|
|
117
|
-
EOF
|
|
118
|
-
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"ask\",\"permissionDecisionReason\":\"${_reason}\"}}"
|
|
119
|
-
_log_block "cp/mv/touch" "$command"
|
|
120
|
-
write_hook_event "pre-tool-use" "deny" "$command" "禁止通过 cp/mv/touch 操作文件" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
121
|
-
exit 2
|
|
122
|
-
fi
|
|
123
|
-
|
|
124
|
-
# 放行: 构建工具(npx/pnpm/npm/yarn)、版本控制(git)、
|
|
125
|
-
# 只读操作(ls/cat/grep/find/head/tail/wc)、目录操作(mkdir/rmdir) 等
|
|
126
|
-
exit 0
|
|
127
|
-
fi
|
|
128
|
-
|
|
129
|
-
# ═══════════════ §B: Write/Edit 文件写入前置守卫 ═══════════════
|
|
130
|
-
# 非 Bash 工具(Write/Edit)的文件写入需要经过:
|
|
131
|
-
# 1. Plan/Spec/Review 文档写入 → 需要活跃 ADD Plan
|
|
132
|
-
# 2. 敏感文件保护 → 阻断写入
|
|
133
|
-
# 3. Dev Action 标记 → 用于 Stop 检查
|
|
134
|
-
# 注意: 不再对 src/**/*.ts 做 Plan 白名单放行,避免绕过 skill/rules 规定的 HITL。
|
|
135
|
-
tool_name=$(echo "$input" | jq -r '.tool_name // empty')
|
|
136
|
-
if [ "$tool_name" = "Write" ] || [ "$tool_name" = "Edit" ] || [ "$tool_name" = "SearchReplace" ]; then
|
|
137
|
-
file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty')
|
|
138
|
-
[ -z "$file_path" ] && exit 0
|
|
139
|
-
|
|
140
|
-
# §B: 写入守卫按当前 magicDir 限域(Review P1 #5: 禁止多端路径正则)
|
|
141
|
-
if echo "$file_path" | grep -qE "${MAGIC_DIR}/(plans|specs|reviews)/"; then
|
|
142
|
-
if type detect_active_add >/dev/null 2>&1; then
|
|
143
|
-
state=$(detect_active_add 2>/dev/null || true)
|
|
144
|
-
if [ -z "$state" ]; then
|
|
145
|
-
echo "[ADD 提示] 正在写入 Plan/Spec/Review 文档但无活跃 ADD Plan——首次创建场景放行,建议先执行 add-paradigm 生成 Plan+add-route" >&2
|
|
146
|
-
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"allow\",\"permissionDecisionReason\":\"无活跃 ADD Plan 但为 Plan/Spec/Review 写入(首次创建场景),提示而非拦截\"}}"
|
|
147
|
-
write_hook_event "pre-tool-use" "info" "$tool_name $file_path" "无活跃 ADD Plan 下写入 Plan/Spec/Review(首次创建放行)" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
148
|
-
exit 0
|
|
149
|
-
fi
|
|
150
|
-
fi
|
|
151
|
-
fi
|
|
152
|
-
|
|
153
|
-
if echo "$file_path" | grep -qE '\.env$|\.env\.production$|\.env\.local$|credentials|secrets'; then
|
|
154
|
-
echo "⛔ 敏感文件受保护,禁止写入: $file_path" >&2
|
|
155
|
-
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"敏感文件受保护\"}}"
|
|
156
|
-
exit 2
|
|
157
|
-
fi
|
|
158
|
-
|
|
159
|
-
# §C: 模板类型前置注入 — 仅当前 magicDir plans/ 写入前提示应选模板
|
|
160
|
-
if echo "$file_path" | grep -qE "${MAGIC_DIR}/(plans)/"; then
|
|
161
|
-
fname=$(basename "$file_path")
|
|
162
|
-
if echo "$fname" | grep -qE 'plan-v[0-9]'; then
|
|
163
|
-
echo "💡 [ADD PreToolUse] 写入 Plan → 模板: standard-plan-template.md(标准)或 simple-plan-template.md(≤3文件)" >&2
|
|
164
|
-
elif echo "$fname" | grep -qE 'add-route'; then
|
|
165
|
-
echo "💡 [ADD PreToolUse] 写入 ADD Route → 模板: add-route-template.md" >&2
|
|
166
|
-
elif echo "$fname" | grep -qE 'handoff'; then
|
|
167
|
-
echo "💡 [ADD PreToolUse] 写入 Handoff → 模板: handoff-single-round-template.md(单轮)或 handoff-multi-round-template.md(多轮)" >&2
|
|
168
|
-
fi
|
|
169
|
-
# Write 大文件适配 — 已存在大文件建议用 SearchReplace 分块
|
|
170
|
-
if echo "$tool_name" | grep -qE 'Write' && [ -f "$file_path" ]; then
|
|
171
|
-
fsize=$(wc -c < "$file_path" 2>/dev/null || echo "0")
|
|
172
|
-
if [ "$fsize" -gt 2000 ] 2>/dev/null; then
|
|
173
|
-
echo "⚠️ [ADD PreToolUse] 文件已有 ${fsize} 字节,Write 全量覆盖可能触发工具 payload 限制。建议用 SearchReplace 分块追加。" >&2
|
|
174
|
-
fi
|
|
175
|
-
fi
|
|
176
|
-
fi
|
|
177
|
-
|
|
178
|
-
# §C: HITL tongyi 检查 — plans/ + PLAN_REVIEW reviews/ 写入前必须有 .hitl-tongyi-{planName} 哨兵
|
|
179
|
-
# implementation/runtime review 不需要 HITL,走 §B 活跃 Plan 检查
|
|
180
|
-
# handoff 是 Step 8 收敛产物(多轮交接手册),不经 HITL 审批,同样豁免
|
|
181
|
-
# TODO 应该caijuehub管理
|
|
182
|
-
if echo "$file_path" | grep -qE "${MAGIC_DIR}/(plans)/"; then
|
|
183
|
-
if echo "$file_path" | grep -qE '\-handoff'; then
|
|
184
|
-
_do_hitl=false # handoff 不被 HITL 拦截(Step 8 产物,无独立审批)
|
|
185
|
-
else
|
|
186
|
-
_do_hitl=true
|
|
187
|
-
fi
|
|
188
|
-
elif echo "$file_path" | grep -qE "${MAGIC_DIR}/(reviews)/"; then
|
|
189
|
-
if echo "$file_path" | grep -qE '-(implementation|runtime)'; then
|
|
190
|
-
_do_hitl=false # implementation/runtime review 不被 HITL 拦截
|
|
191
|
-
else
|
|
192
|
-
_do_hitl=true # PLAN_REVIEW 需要 HITL
|
|
193
|
-
fi
|
|
194
|
-
else
|
|
195
|
-
_do_hitl=false
|
|
196
|
-
fi
|
|
197
|
-
|
|
198
|
-
if [ "$_do_hitl" = true ]; then
|
|
199
|
-
_relative=$(echo "$file_path" | sed "s|.*/\.\(qoder\|claude\|add\|vscode\|trae\)/\(plans\|reviews\)/||")
|
|
200
|
-
# 限域: 仅当前 magicDir 下的 plans/reviews 触发 HITL 门禁
|
|
201
|
-
if ! echo "$file_path" | grep -qE "${MAGIC_DIR}/(plans|reviews)/"; then
|
|
202
|
-
_do_hitl=false
|
|
203
|
-
fi
|
|
204
|
-
_planName=$(basename "$_relative" .md | sed 's/\.hitl$//;s/-plan-v[0-9]*$//;s/-add-route-v[0-9]*$//;s/-review-v[0-9]*$//;s/-review-implementation$//;s/-review-runtime$//')
|
|
205
|
-
if [ -n "$_planName" ]; then
|
|
206
|
-
_tongyi_marker="${PROJECT_DIR}/${MAGIC_DIR}/hitl/.tongyi-${_planName}"
|
|
207
|
-
if [ ! -f "$_tongyi_marker" ]; then
|
|
208
|
-
echo "⛔ [ADD PreToolUse §C] HITL 未 tongyi: $file_path" >&2
|
|
209
|
-
echo " 原因: 哨兵文件 $_tongyi_marker 不存在" >&2
|
|
210
|
-
echo " 操作: 请先调用 create_hitl 创建审批,再 update_hitl({ status: \"TONGYI\" })" >&2
|
|
211
|
-
_reason="HITL 未 tongyi: 哨兵 ${_tongyi_marker} 不存在。请先 create_hitl → 人工 tongyi → update_hitl 后再写入"
|
|
212
|
-
echo "{\"hookSpecificOutput\":{\"hookEventName\":\"PreToolUse\",\"permissionDecision\":\"deny\",\"permissionDecisionReason\":\"${_reason}\",\"additionalContext\":\"${_reason}\"}}"
|
|
213
|
-
write_hook_event "pre-tool-use" "deny" "$tool_name $file_path" "HITL 未 tongyi: $_tongyi_marker" "$PLAN_KEYWORD" "$PLAN_STATUS" 2>/dev/null || true
|
|
214
|
-
exit 0
|
|
215
|
-
fi
|
|
216
|
-
fi
|
|
217
|
-
fi
|
|
218
|
-
|
|
219
|
-
mark_dev_action 2>/dev/null || true
|
|
220
|
-
exit 0
|
|
221
|
-
fi
|
|
222
|
-
|
|
223
|
-
exit 0
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# prompt-submit.sh — UserPromptSubmit 触发词智能路由(通用适配版)
|
|
3
|
-
# 治理卡位 #3: Layer 1 精准触发 → Layer 2 阻断 → Layer 3 状态注入
|
|
4
|
-
set -euo pipefail
|
|
5
|
-
|
|
6
|
-
input=$(cat)
|
|
7
|
-
prompt=$(echo "$input" | jq -r '.prompt // empty')
|
|
8
|
-
[ -z "$prompt" ] && exit 0
|
|
9
|
-
|
|
10
|
-
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
11
|
-
source "$HOOK_DIR/lib/vocabulary.sh" 2>/dev/null || true
|
|
12
|
-
source "$HOOK_DIR/lib/state-detect.sh" 2>/dev/null || true
|
|
13
|
-
source "$HOOK_DIR/lib/notify.sh" 2>/dev/null || true
|
|
14
|
-
|
|
15
|
-
# ─── Layer 1: 精准 P0 触发词 ───
|
|
16
|
-
matched=$(match_trigger "$prompt" 2>/dev/null || true)
|
|
17
|
-
if [ -n "$matched" ]; then
|
|
18
|
-
# 验收幂等保护: 如果已验收,提示不重复
|
|
19
|
-
if echo "$prompt" | grep -qiE '验收|收敛' 2>/dev/null; then
|
|
20
|
-
add_state=$(detect_active_add 2>/dev/null || true)
|
|
21
|
-
if [ -n "$add_state" ]; then
|
|
22
|
-
_handoff=$(echo "$add_state" | awk -F'::' '{print $4}')
|
|
23
|
-
_add_route=$(echo "$add_state" | awk -F'::' '{print $5}')
|
|
24
|
-
if is_already_accepted "$_add_route" "$_handoff" 2>/dev/null; then
|
|
25
|
-
cat <<EOF
|
|
26
|
-
[ADD 验收] ⚠️ 已验收。进入 Review 模式:
|
|
27
|
-
① 重新检查 checklist [T]/[R] 项
|
|
28
|
-
② 审查 audit 记录完整性
|
|
29
|
-
③ 如有差异 → Review 回流至 handoff(增量更新,不覆盖已有结论)
|
|
30
|
-
④ 无差异 → 记录 'Review 已确认,无新发现'
|
|
31
|
-
★ 同步检查: 如 checklist 有新 cuid 但 handoff 审计表缺失 → 更新 handoff ADD-7 表 + query_audit_logs 命令
|
|
32
|
-
EOF
|
|
33
|
-
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
34
|
-
"$HOOK_DIR/review-checklist.sh" "$_handoff" "$_add_route" 2>/dev/null || true
|
|
35
|
-
exit 0
|
|
36
|
-
fi
|
|
37
|
-
fi
|
|
38
|
-
fi
|
|
39
|
-
echo "$matched"
|
|
40
|
-
exit 0
|
|
41
|
-
fi
|
|
42
|
-
|
|
43
|
-
# ─── 开发关键词检测(动态加载) ───
|
|
44
|
-
dev_kw=$(load_dev_keywords 2>/dev/null || true)
|
|
45
|
-
if [ -z "$dev_kw" ]; then
|
|
46
|
-
exit 0
|
|
47
|
-
fi
|
|
48
|
-
|
|
49
|
-
if ! echo "$prompt" | grep -qiE "$dev_kw"; then
|
|
50
|
-
exit 0
|
|
51
|
-
fi
|
|
52
|
-
|
|
53
|
-
# ─── Layer 2/3: 按活跃 ADD 分流 ───
|
|
54
|
-
state=$(detect_active_add 2>/dev/null || true)
|
|
55
|
-
if [ -z "$state" ]; then
|
|
56
|
-
# Layer 2: 无活跃 ADD → 提示启动(不阻断)
|
|
57
|
-
cat >&2 <<'EOF'
|
|
58
|
-
[ADD 提示] 检测到开发任务,但无活跃 ADD Plan。建议先执行 add-paradigm SKILL:
|
|
59
|
-
Step 0: 文档先行 (Plan → Review → Specs)
|
|
60
|
-
Step 3: 代码实现 + 审计植入
|
|
61
|
-
Step 8: 收敛判断
|
|
62
|
-
EOF
|
|
63
|
-
write_hook_event "prompt-submit" "info" "$prompt" "无活跃 ADD Plan 下检测到开发任务" "no-active-plan" "none" 2>/dev/null || true
|
|
64
|
-
exit 0
|
|
65
|
-
fi
|
|
66
|
-
|
|
67
|
-
# Layer 3: 有活跃 ADD → 注入状态
|
|
68
|
-
plan=$(echo "$state" | awk -F'::' '{print $1}')
|
|
69
|
-
step=$(echo "$state" | awk -F'::' '{print $2}')
|
|
70
|
-
rounds=$(echo "$state" | awk -F'::' '{print $3}')
|
|
71
|
-
handoff=$(echo "$state" | awk -F'::' '{print $4}')
|
|
72
|
-
echo "[ADD 状态] Plan: ${plan}, 轮次: ${rounds}, Step: ${step}, handoff: ${handoff}"
|
|
73
|
-
|
|
74
|
-
# ─── Hook 治理日报(注入 AI 上下文)───
|
|
75
|
-
HOOK_JSONL="${MAGIC_DIR:-.qoder}/reports/hook-events.jsonl"
|
|
76
|
-
if [ -f "$HOOK_JSONL" ]; then
|
|
77
|
-
TODAY="$(date +%Y-%m-%d)"
|
|
78
|
-
TOTAL=$(grep -c "\"ts\":\"${TODAY}" "$HOOK_JSONL" 2>/dev/null || echo 0)
|
|
79
|
-
NO_PLAN=$(grep "\"ts\":\"${TODAY}" "$HOOK_JSONL" 2>/dev/null | grep -c '"planKeyword":"no-active-plan"' || echo 0)
|
|
80
|
-
if [ "$TOTAL" -gt 0 ] 2>/dev/null; then
|
|
81
|
-
echo "[Hook 治理] 今日提示: ${TOTAL} 次 | 无 Plan 提示: ${NO_PLAN} 次"
|
|
82
|
-
if [ "$NO_PLAN" -ge 10 ] 2>/dev/null; then
|
|
83
|
-
echo "[Hook ⚠️] 无 Plan 提示已达 ${NO_PLAN} 次(≥10),建议创建 Plan 或检查 hooks 误报"
|
|
84
|
-
fi
|
|
85
|
-
fi
|
|
86
|
-
fi
|
|
87
|
-
exit 0
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# review-checklist.sh — Review 检查清单校验(Claude Code 适配)
|
|
3
|
-
set -euo pipefail
|
|
4
|
-
|
|
5
|
-
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
6
|
-
SHARED_LIB="$HOOK_DIR/../../shared/hooks-lib/common.sh"
|
|
7
|
-
[ -f "$SHARED_LIB" ] && source "$SHARED_LIB"
|
|
8
|
-
|
|
9
|
-
echo "[ADD ReviewChecklist] 请在提交前确认 checklist.md 全部项已勾选。"
|
|
10
|
-
exit 0
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# SessionEnd — 通用版(核心模板,Trae 等适配器继承)
|
|
3
|
-
# 治理卡位 #2: 标记清理 + 会话审计结算 + Stop未触发兜底
|
|
4
|
-
set -euo pipefail
|
|
5
|
-
|
|
6
|
-
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
7
|
-
COMMON_LIB="$HOOK_DIR/lib/common.sh"
|
|
8
|
-
[ -f "$COMMON_LIB" ] && source "$COMMON_LIB"
|
|
9
|
-
|
|
10
|
-
export PROJECT_DIR="$PWD"
|
|
11
|
-
|
|
12
|
-
# ── ① 清理 tpl-injected 标记 ──
|
|
13
|
-
project_hash=$(echo "${PROJECT_DIR:-$PWD}" | md5sum 2>/dev/null | cut -c1-8 || echo "default")
|
|
14
|
-
rm -f "/tmp/add_tpl_${project_hash}" 2>/dev/null || true
|
|
15
|
-
|
|
16
|
-
# ── ② 清理 dev action 标记 ──
|
|
17
|
-
rm -f "/tmp/add_dev_${project_hash}" 2>/dev/null || true
|
|
18
|
-
|
|
19
|
-
# ── ③ Stop 未触发兜底: 如果 dev action 标记还在,补执行 checklist 快照 ──
|
|
20
|
-
if has_dev_action 2>/dev/null; then
|
|
21
|
-
echo "[ADD SessionEnd] ⚠️ 检测到 dev action 标记未清除——Stop 可能未触发验收检查" >&2
|
|
22
|
-
|
|
23
|
-
state=$(detect_active_add 2>/dev/null || true)
|
|
24
|
-
if [ -n "$state" ]; then
|
|
25
|
-
handoff=$(echo "$state" | awk -F'::' '{print $4}')
|
|
26
|
-
add_route=$(echo "$state" | awk -F'::' '{print $5}')
|
|
27
|
-
if [ -f "$handoff" ]; then
|
|
28
|
-
echo "[ADD SessionEnd] 补执行 checklist 快照(best-effort,不阻断)" >&2
|
|
29
|
-
if type check_add_completeness >/dev/null 2>&1; then
|
|
30
|
-
check_add_completeness "$handoff" "$add_route" >&2 2>/dev/null || true
|
|
31
|
-
fi
|
|
32
|
-
fi
|
|
33
|
-
fi
|
|
34
|
-
fi
|
|
35
|
-
|
|
36
|
-
# ── ④ 审计结算 ──
|
|
37
|
-
echo "[ADD SessionEnd] 会话结束 — $(date -Iseconds)" >&2
|
|
38
|
-
exit 0
|
|
@@ -1,53 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# SessionStart — ADD 上下文恢复 + 模板索引注入(Claude Code 适配)
|
|
3
|
-
# 治理卡位 #1: ADD状态恢复 + 模板索引注入
|
|
4
|
-
set -euo pipefail
|
|
5
|
-
|
|
6
|
-
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
7
|
-
export CURRENT_MAGIC=$(basename "$(dirname "$HOOK_DIR")")
|
|
8
|
-
|
|
9
|
-
# 加载四端通用函数(路径统一后: .claude/hooks/lib/common.sh)
|
|
10
|
-
COMMON_LIB="$HOOK_DIR/lib/common.sh"
|
|
11
|
-
[ -f "$COMMON_LIB" ] && source "$COMMON_LIB"
|
|
12
|
-
|
|
13
|
-
# 设置项目目录
|
|
14
|
-
export PROJECT_DIR="$PWD"
|
|
15
|
-
|
|
16
|
-
# ── ① ADD 状态恢复 ──
|
|
17
|
-
state=$(detect_active_add 2>/dev/null || true)
|
|
18
|
-
if [ -n "$state" ]; then
|
|
19
|
-
IFS='::' read -r plan step rounds handoff add_route <<< "$state"
|
|
20
|
-
cat <<EOF
|
|
21
|
-
[ADD SessionStart] 检测到活跃 ADD Plan:
|
|
22
|
-
Plan: ${plan}
|
|
23
|
-
轮次: ${rounds}
|
|
24
|
-
当前 Step: ${step}
|
|
25
|
-
handoff: ${handoff}
|
|
26
|
-
恢复命令: query_audit_logs({ planKeyword: '${plan}' })
|
|
27
|
-
EOF
|
|
28
|
-
fi
|
|
29
|
-
|
|
30
|
-
# ── ② 模板索引注入 ──
|
|
31
|
-
TPL_SCRIPT="$HOOK_DIR/lib/preload-templates.sh"
|
|
32
|
-
if [ -f "$TPL_SCRIPT" ]; then
|
|
33
|
-
bash "$TPL_SCRIPT" --index
|
|
34
|
-
fi
|
|
35
|
-
|
|
36
|
-
# ── ③ §代办刷新:活跃 Plan 时提醒加载 IDE 代办 ──
|
|
37
|
-
# session-init Step 2.6 依赖 IDE resume invoke SKILL,本段作为兜底
|
|
38
|
-
if [ -n "$state" ]; then
|
|
39
|
-
IFS='::' read -r plan step rounds handoff add_route <<< "$state"
|
|
40
|
-
cat <<EOF
|
|
41
|
-
[代办] 检测到活跃 Plan: ${plan}。如有未加载的 IDE 代办清单,请从 tasks.md §IDE JSON 刷新 TodoWrite。
|
|
42
|
-
EOF
|
|
43
|
-
fi
|
|
44
|
-
|
|
45
|
-
# ── ④ §HITL 待审批检测 ──
|
|
46
|
-
if [ -d "$PLANS_DIR" ]; then
|
|
47
|
-
hitl_count=$(find "$PLANS_DIR" -name "*.hitl.md" -mtime -7 -type f 2>/dev/null | wc -l)
|
|
48
|
-
if [ "$hitl_count" -gt 0 ] 2>/dev/null; then
|
|
49
|
-
echo "[HITL 待审批] 检测到 ${hitl_count} 个待审批 HITL 提案,请检查并处理"
|
|
50
|
-
fi
|
|
51
|
-
fi
|
|
52
|
-
|
|
53
|
-
exit 0
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
# stop-check.sh — Claude Code Stop:四象限分流 + 验收检查(few-shot 上下文注入)
|
|
3
|
-
# 治理卡位 #7: 验收检查 + devlog + 阻断
|
|
4
|
-
# DB lifecycle 真相源(协议层):DB 不可用时 fail-closed,禁止回退 Handoff/add-route 猜测
|
|
5
|
-
set -euo pipefail
|
|
6
|
-
|
|
7
|
-
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
8
|
-
export CURRENT_MAGIC=$(basename "$(dirname "$HOOK_DIR")")
|
|
9
|
-
export MAGIC_DIR=$(basename "$(dirname "$HOOK_DIR")")
|
|
10
|
-
COMMON_LIB="$HOOK_DIR/lib/common.sh"
|
|
11
|
-
[ -f "$COMMON_LIB" ] && source "$COMMON_LIB"
|
|
12
|
-
|
|
13
|
-
export PROJECT_DIR="$PWD"
|
|
14
|
-
|
|
15
|
-
state=$(detect_active_add 2>/dev/null || true)
|
|
16
|
-
has_dev=$(has_dev_action 2>/dev/null && echo "true" || echo "false")
|
|
17
|
-
|
|
18
|
-
# ═══════ Q0: DB 不可用 → fail closed(禁止当“无 Plan”) ═══════
|
|
19
|
-
if [ "${state%%::*}" = "__STATUS_UNAVAILABLE__" ]; then
|
|
20
|
-
reason=$(echo "$state" | awk -F'::' '{print $2}')
|
|
21
|
-
echo "[ADD Stop] ⛔ Plan status 暂不可用(${reason})。未回退 Handoff/add-route 猜测,请恢复数据库或 MCP resolver 后重试。" >&2
|
|
22
|
-
exit "${EXIT_BLOCK:-2}"
|
|
23
|
-
fi
|
|
24
|
-
|
|
25
|
-
# ═══════ Q1: 无 ADD + 无 dev → 正常停 ═══════
|
|
26
|
-
if [ -z "$state" ] && [ "$has_dev" != "true" ]; then
|
|
27
|
-
exit 0
|
|
28
|
-
fi
|
|
29
|
-
|
|
30
|
-
# ═══════ Q2: 无 ADD + 有 dev → 严重违规,few-shot 注入 ═══════
|
|
31
|
-
if [ -z "$state" ] && [ "$has_dev" = "true" ]; then
|
|
32
|
-
build_stop_context "no_add_has_dev" >&2
|
|
33
|
-
exit $EXIT_BLOCK
|
|
34
|
-
fi
|
|
35
|
-
|
|
36
|
-
IFS='::' read -r plan step rounds handoff add_route <<< "$state"
|
|
37
|
-
|
|
38
|
-
# ═══════ Q3: 有 ADD + 无 dev → 注入状态 ═══════
|
|
39
|
-
if [ "$has_dev" != "true" ]; then
|
|
40
|
-
echo "[ADD Stop] Plan: ${plan}, 轮次: ${rounds}, Step: ${step}"
|
|
41
|
-
echo "本次无代码改动。下次继续时执行 session-init 恢复上下文。"
|
|
42
|
-
exit 0
|
|
43
|
-
fi
|
|
44
|
-
|
|
45
|
-
# ═══════ Q4: 有 ADD + 有 dev → 验收检查 ═══════
|
|
46
|
-
issues=$(check_add_completeness "$handoff" "$add_route" 2>/dev/null || true)
|
|
47
|
-
if [ -n "$issues" ]; then
|
|
48
|
-
build_stop_context "has_add_dev_unclosed" "$issues" >&2
|
|
49
|
-
exit $EXIT_BLOCK
|
|
50
|
-
fi
|
|
51
|
-
|
|
52
|
-
clear_dev_action 2>/dev/null || true
|
|
53
|
-
echo "[ADD Stop] ✅ 验收通过——checklist 全部勾选,devlog 已记录。"
|
|
54
|
-
exit 0
|