add-coder 0.1.0
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 +50 -0
- package/bin/add-coder.js +2 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +576 -0
- package/package.json +64 -0
- package/templates/adapters/claude/hooks/doc-format-guard.sh +17 -0
- package/templates/adapters/claude/hooks/notification.sh +9 -0
- package/templates/adapters/claude/hooks/permission-gate.sh +18 -0
- package/templates/adapters/claude/hooks/post-tool-failure.sh +10 -0
- package/templates/adapters/claude/hooks/post-tool-use.sh +18 -0
- package/templates/adapters/claude/hooks/pre-compact.sh +14 -0
- package/templates/adapters/claude/hooks/pre-tool-use.sh +28 -0
- package/templates/adapters/claude/hooks/prompt-submit.sh +16 -0
- package/templates/adapters/claude/hooks/review-checklist.sh +10 -0
- package/templates/adapters/claude/hooks/session-start.sh +23 -0
- package/templates/adapters/claude/hooks/stop-check.sh +10 -0
- package/templates/adapters/claude/hooks/subagent-guard.sh +15 -0
- package/templates/adapters/claude/mcp.json +13 -0
- package/templates/adapters/claude/settings.json +125 -0
- package/templates/adapters/qoder/hooks/doc-format-guard.sh +164 -0
- package/templates/adapters/qoder/hooks/lib/context-inject.sh +96 -0
- package/templates/adapters/qoder/hooks/lib/state-detect.sh +104 -0
- package/templates/adapters/qoder/hooks/lib/vocabulary.sh +49 -0
- package/templates/adapters/qoder/hooks/notification.sh +22 -0
- package/templates/adapters/qoder/hooks/permission-gate.sh +8 -0
- package/templates/adapters/qoder/hooks/post-tool-failure.sh +8 -0
- package/templates/adapters/qoder/hooks/post-tool-use.sh +20 -0
- package/templates/adapters/qoder/hooks/pre-compact.sh +12 -0
- package/templates/adapters/qoder/hooks/pre-tool-use.sh +77 -0
- package/templates/adapters/qoder/hooks/prompt-submit.sh +72 -0
- package/templates/adapters/qoder/hooks/review-checklist.sh +157 -0
- package/templates/adapters/qoder/hooks/session-start.sh +16 -0
- package/templates/adapters/qoder/hooks/stop-check.sh +71 -0
- package/templates/adapters/qoder/hooks/subagent-guard.sh +11 -0
- package/templates/adapters/qoder/mcp.json +13 -0
- package/templates/adapters/qoder/settings.json +125 -0
- package/templates/adapters/qoder/sync-policy.json +18 -0
- package/templates/adapters/vscode/extensions.json +5 -0
- package/templates/adapters/vscode/launch.json +16 -0
- package/templates/adapters/vscode/settings.json +16 -0
- package/templates/adapters/vscode/tasks.json +38 -0
- package/templates/core/agents/add-flow-guardian.md +276 -0
- package/templates/core/agents/add-orchestrator.md +217 -0
- package/templates/core/plans/2026-07/08/farm-agent-add-coder-npm-package-add-route-v1.md +323 -0
- package/templates/core/plans/2026-07/08/farm-agent-add-coder-npm-package-handoff-v1.md +678 -0
- package/templates/core/plans/2026-07/08/farm-agent-add-coder-npm-package-plan-v1.md +785 -0
- package/templates/core/prisma/add.prisma +34 -0
- package/templates/core/reports/REPORT-WORKFLOW.md +250 -0
- package/templates/core/reports/boundary-runtime-report.md +134 -0
- package/templates/core/reports/code-review-combined-report.md +227 -0
- package/templates/core/reports/code-review-fix-verification-report.md +505 -0
- package/templates/core/reports/code-review-suggestions.md +66 -0
- package/templates/core/reports/index.md +57 -0
- package/templates/core/reports/runtime-report/gateway.md +741 -0
- package/templates/core/rules/project_rules.md +905 -0
- package/templates/core/rules/theory-practice-map.toml +105 -0
- package/templates/core/scripts/mcp-server.ts +3492 -0
- package/templates/core/skills/add-paradigm/SKILL.md +1086 -0
- package/templates/core/skills/session-init/SKILL.md +215 -0
- package/templates/core/specs/farm-agent-add-coder-npm-package/checklist.md +125 -0
- package/templates/core/specs/farm-agent-add-coder-npm-package/spec.md +343 -0
- package/templates/core/specs/farm-agent-add-coder-npm-package/tasks.md +203 -0
- package/templates/core/templates/01-/346/236/266/346/236/204//343/200/212ADD/345/274/200/345/217/221/345/267/245/344/275/234/350/267/257/345/276/204/344/270/216/346/226/207/346/241/243/345/215/217/345/220/214/350/247/204/350/214/203/343/200/213.md +386 -0
- package/templates/core/templates/TERMINOLOGY.md +81 -0
- package/templates/core/templates/add-route-template-heavyweight.md +288 -0
- package/templates/core/templates/add-route-template.md +242 -0
- package/templates/core/templates/add-route-template.schema.json +35 -0
- package/templates/core/templates/checklist-template.md +72 -0
- package/templates/core/templates/checklist-template.schema.json +20 -0
- package/templates/core/templates/fix-verification-template.md +132 -0
- package/templates/core/templates/fix-verification-template.schema.json +54 -0
- package/templates/core/templates/handoff-multi-round-template.md +295 -0
- package/templates/core/templates/handoff-multi-round.schema.json +48 -0
- package/templates/core/templates/handoff-single-round-template.md +145 -0
- package/templates/core/templates/handoff-single-round.schema.json +92 -0
- package/templates/core/templates/index.md +60 -0
- package/templates/core/templates/report-template.md +126 -0
- package/templates/core/templates/report-template.schema.json +69 -0
- package/templates/core/templates/review-implementation-template.md +66 -0
- package/templates/core/templates/review-implementation-template.schema.json +58 -0
- package/templates/core/templates/review-runtime-template.md +73 -0
- package/templates/core/templates/review-runtime-template.schema.json +47 -0
- package/templates/core/templates/review-template.md +37 -0
- package/templates/core/templates/review-template.schema.json +42 -0
- package/templates/core/templates/runtime-report-template.md +73 -0
- package/templates/core/templates/runtime-report-template.schema.json +48 -0
- package/templates/core/templates/simple-plan-template.md +166 -0
- package/templates/core/templates/simple-plan-template.schema.json +109 -0
- package/templates/core/templates/spec-template.md +22 -0
- package/templates/core/templates/spec-template.schema.json +41 -0
- package/templates/core/templates/standard-plan-template.md +96 -0
- package/templates/core/templates/standard-plan-template.schema.json +73 -0
- package/templates/core/templates/tasks-template.md +54 -0
- package/templates/core/templates/tasks-template.schema.json +43 -0
- package/templates/core/tools/README.md +361 -0
- package/templates/core/vocabulary/add-governance-vocabulary.md +370 -0
- package/templates/shared/hooks-lib/common.sh +22 -0
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# state-detect.sh — ADD 活跃流程检测 + dev action 追踪
|
|
3
|
+
# 共享库
|
|
4
|
+
|
|
5
|
+
PROJECT_DIR="${QODER_PROJECT_DIR:-${QODERCN_PROJECT_DIR:-$PWD}}"
|
|
6
|
+
QODER_DIR="$PROJECT_DIR/.qoder"
|
|
7
|
+
PLANS_DIR="$QODER_DIR/plans"
|
|
8
|
+
|
|
9
|
+
# dev action 标记文件(项目级,PreToolUse 写入,Stop 读取)
|
|
10
|
+
DEV_FLAG="/tmp/qoder_dev_$(echo "$PROJECT_DIR" | md5sum 2>/dev/null | cut -c1-8 || echo "default")"
|
|
11
|
+
|
|
12
|
+
# 检测活跃 ADD 流程
|
|
13
|
+
# 返回: "plan_keyword::step_x/total::round_n/total_r::handoff_path::add_route_path" 或 ""
|
|
14
|
+
detect_active_add() {
|
|
15
|
+
local handoff=""
|
|
16
|
+
local today_dir="$PLANS_DIR/$(date +%Y-%m)"
|
|
17
|
+
[ -d "$today_dir" ] && handoff=$(find "$today_dir" -name "*handoff*.md" -mtime -7 -type f 2>/dev/null | head -1)
|
|
18
|
+
[ -z "$handoff" ] && handoff=$(find "$PLANS_DIR" -name "*handoff*.md" -mtime -7 -type f 2>/dev/null | head -1)
|
|
19
|
+
[ -z "$handoff" ] && return 1
|
|
20
|
+
|
|
21
|
+
local plan_kw=$(basename "$handoff" | sed 's/-handoff.*//')
|
|
22
|
+
|
|
23
|
+
# add-route
|
|
24
|
+
local add_route=$(find "$PLANS_DIR" -name "*add-route*.md" -type f 2>/dev/null | head -1)
|
|
25
|
+
|
|
26
|
+
# Step 统计(从 add-route)
|
|
27
|
+
local step_info="?"
|
|
28
|
+
if [ -f "$add_route" ]; then
|
|
29
|
+
local ck=$(grep -c '\[x\]' "$add_route" 2>/dev/null || true)
|
|
30
|
+
local uc=$(grep -c '\[ \]' "$add_route" 2>/dev/null || true)
|
|
31
|
+
ck=${ck:-0}; uc=${uc:-0}
|
|
32
|
+
local total=$((ck + uc))
|
|
33
|
+
[ "$total" -gt 0 ] && step_info="${ck}/${total}"
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
# 轮次统计(从 handoff)
|
|
37
|
+
local round_info="?"
|
|
38
|
+
if grep -q '<第[0-9]轮>' "$handoff" 2>/dev/null; then
|
|
39
|
+
local ck=$(grep -c '\[x\]' "$handoff" 2>/dev/null || true); ck=${ck:-0}
|
|
40
|
+
local total=$(grep -c '<第[0-9]轮>' "$handoff" 2>/dev/null || true); total=${total:-0}
|
|
41
|
+
[ "$total" -gt 0 ] && round_info="${ck}/${total}"
|
|
42
|
+
else
|
|
43
|
+
round_info="1/1"
|
|
44
|
+
fi
|
|
45
|
+
|
|
46
|
+
echo "${plan_kw}::${step_info}::${round_info}::${handoff}::${add_route:-none}"
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
# 标记 dev action
|
|
50
|
+
mark_dev_action() {
|
|
51
|
+
touch "$DEV_FLAG" 2>/dev/null || true
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
# 检测 dev action
|
|
55
|
+
has_dev_action() {
|
|
56
|
+
[ -f "$DEV_FLAG" ]
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
# 清理 dev action 标记(验收闭环后调用)
|
|
60
|
+
clear_dev_action() {
|
|
61
|
+
rm -f "$DEV_FLAG" 2>/dev/null || true
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
# 检查验收完整度,返回 issues 文本
|
|
65
|
+
check_add_completeness() {
|
|
66
|
+
local handoff="$1" add_route="$2"
|
|
67
|
+
local issues=""
|
|
68
|
+
|
|
69
|
+
# devlog(内容已回流至 handoff,检查 handoff 是否含验收结果)
|
|
70
|
+
if [ -f "$handoff" ] && ! grep -qE '验收|收敛|闭环|本轮改了什么|devlog' "$handoff" 2>/dev/null; then
|
|
71
|
+
issues="${issues} [ ] devlog 缺失(handoff 无验收记录)\n"
|
|
72
|
+
fi
|
|
73
|
+
|
|
74
|
+
# handoff 验证标准
|
|
75
|
+
if [ -f "$handoff" ]; then
|
|
76
|
+
local uc=$(grep -c '\[ \]' "$handoff" 2>/dev/null || echo "0")
|
|
77
|
+
[ "$uc" -gt 0 ] && issues="${issues} [ ] handoff ${uc} 项未勾选\n"
|
|
78
|
+
fi
|
|
79
|
+
|
|
80
|
+
# add-route Step
|
|
81
|
+
if [ -f "$add_route" ]; then
|
|
82
|
+
local uc=$(grep -c '\[ \]' "$add_route" 2>/dev/null || echo "0")
|
|
83
|
+
[ "$uc" -gt 0 ] && issues="${issues} [ ] add-route ${uc} Step 未闭环\n"
|
|
84
|
+
fi
|
|
85
|
+
|
|
86
|
+
echo -e "$issues"
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
# 检查是否已验收(幂等保护)
|
|
90
|
+
# 返回 0 = 未验收,1 = 已验收
|
|
91
|
+
is_already_accepted() {
|
|
92
|
+
local add_route="$1" handoff="$2"
|
|
93
|
+
# add-route Step 8 是否已 [x]
|
|
94
|
+
if [ -f "$add_route" ]; then
|
|
95
|
+
# 检查 Step 8 产出项是否勾选
|
|
96
|
+
if grep -A 10 'Step 8' "$add_route" 2>/dev/null | grep -q '\[x\].*验证并更新项目状态'; then
|
|
97
|
+
# handoff 是否有验收记录
|
|
98
|
+
if [ -f "$handoff" ] && grep -qE '✅.*验收|收敛|全部闭环|全部.*完成' "$handoff" 2>/dev/null; then
|
|
99
|
+
return 0
|
|
100
|
+
fi
|
|
101
|
+
fi
|
|
102
|
+
fi
|
|
103
|
+
return 1
|
|
104
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# vocabulary.sh — 从 vocabulary markdown 表格加载触发词
|
|
3
|
+
# 单一数据源: .qoder/vocabulary/add-governance-vocabulary.md §类别 A-F 表格
|
|
4
|
+
|
|
5
|
+
VOCABULARY_FILE="$PWD/.qoder/vocabulary/add-governance-vocabulary.md"
|
|
6
|
+
|
|
7
|
+
# 输出格式: 优先级::触发词正则::响应文本(:: 避免与触发词内的 | 冲突)
|
|
8
|
+
load_triggers() {
|
|
9
|
+
[ ! -f "$VOCABULARY_FILE" ] && return 1
|
|
10
|
+
sed -n '/^## 类别 A: 文档类型/,/^## 类别 [G-Z]/p' "$VOCABULARY_FILE" \
|
|
11
|
+
| grep -E '^\| (P0|P1|P2) ' \
|
|
12
|
+
| while IFS='|' read -r _ prio raw_trigger action; do
|
|
13
|
+
prio=$(echo "$prio" | xargs)
|
|
14
|
+
trigger=$(echo "$raw_trigger" | sed 's/`//g;s/ *\/ */|/g;s/^ *//;s/ *$//')
|
|
15
|
+
action=$(echo "$action" | xargs)
|
|
16
|
+
[ -z "$trigger" ] && continue
|
|
17
|
+
echo "${prio}::${trigger}::${action}"
|
|
18
|
+
done || true
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
match_trigger() {
|
|
22
|
+
local prompt="$1"
|
|
23
|
+
while IFS= read -r line; do
|
|
24
|
+
[ -z "$line" ] && continue
|
|
25
|
+
local prio="${line%%::*}"
|
|
26
|
+
local rest="${line#*::}"
|
|
27
|
+
local regex="${rest%%::*}"
|
|
28
|
+
local action="${rest#*::}"
|
|
29
|
+
# 跳过开发关键词检测行(由 Layer 2/3 分流处理,特征:超长regex含"修bug")
|
|
30
|
+
if echo "$regex" | grep -qE '修\.\?bug|fix\.\?bug' 2>/dev/null; then
|
|
31
|
+
continue
|
|
32
|
+
fi
|
|
33
|
+
if echo "$prompt" | grep -qiE "$regex" 2>/dev/null; then
|
|
34
|
+
echo "[ADD 触发] ${regex} → ${action}"
|
|
35
|
+
fi
|
|
36
|
+
done < <(load_triggers 2>/dev/null)
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
load_dev_keywords() {
|
|
40
|
+
load_triggers 2>/dev/null | while IFS= read -r line; do
|
|
41
|
+
[ -z "$line" ] && continue
|
|
42
|
+
# 只取包含"开发|改功能"的开发关键词检测行
|
|
43
|
+
if echo "$line" | grep -q '开发|改功能' 2>/dev/null; then
|
|
44
|
+
local rest="${line#*::}"
|
|
45
|
+
local regex="${rest%%::*}"
|
|
46
|
+
echo "$regex"
|
|
47
|
+
fi
|
|
48
|
+
done || true
|
|
49
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# notification.sh — Notification Review 提醒
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
input=$(cat)
|
|
5
|
+
ntype=$(echo "$input" | jq -r '.notification_type // ""')
|
|
6
|
+
|
|
7
|
+
if [ "$ntype" != "result" ]; then
|
|
8
|
+
exit 0
|
|
9
|
+
fi
|
|
10
|
+
|
|
11
|
+
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
12
|
+
source "$HOOK_DIR/lib/state-detect.sh"
|
|
13
|
+
|
|
14
|
+
state=$(detect_active_add 2>/dev/null || true)
|
|
15
|
+
[ -z "$state" ] && exit 0
|
|
16
|
+
|
|
17
|
+
# 检查是否有未读 Review
|
|
18
|
+
reviews_dir="${QODER_DIR:-.qoder}/reviews"
|
|
19
|
+
if ls "$reviews_dir"/*.md >/dev/null 2>&1; then
|
|
20
|
+
echo "[ADD Notification] 请检查 Review 文档: ${reviews_dir}"
|
|
21
|
+
fi
|
|
22
|
+
exit 0
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# permission-gate.sh — PermissionRequest 人工卡位(不干预)
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
# ADD Review 卡位由 Qoder 本身的权限弹窗处理,此 hook 仅做日志
|
|
5
|
+
input=$(cat)
|
|
6
|
+
tool_name=$(echo "$input" | jq -r '.tool_name // "unknown"')
|
|
7
|
+
echo "[ADD PermissionRequest] 工具 ${tool_name} 请求权限。如有 Review 文档待确认,请先检查。" >&2
|
|
8
|
+
exit 0
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# post-tool-failure.sh — PostToolUseFailure 错误定位
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
input=$(cat)
|
|
5
|
+
tool_name=$(echo "$input" | jq -r '.tool_name // "unknown"')
|
|
6
|
+
error=$(echo "$input" | jq -r '.error // "unknown"')
|
|
7
|
+
echo "[ADD PostToolUseFailure] 工具 ${tool_name} 失败: ${error}。检查是否需要回退到上一 ADD Step 重新执行。" >&2
|
|
8
|
+
exit 0
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# post-tool-use.sh — PostToolUse 审计提醒
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
input=$(cat)
|
|
5
|
+
file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty')
|
|
6
|
+
[ -z "$file_path" ] && exit 0
|
|
7
|
+
|
|
8
|
+
# 只在写入核心文件时提醒
|
|
9
|
+
if ! echo "$file_path" | grep -qE 'src/agents/|src/lib/agent-audit-logger\.ts|src/types/|prisma/schema\.prisma'; then
|
|
10
|
+
exit 0
|
|
11
|
+
fi
|
|
12
|
+
|
|
13
|
+
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
14
|
+
source "$HOOK_DIR/lib/state-detect.sh"
|
|
15
|
+
|
|
16
|
+
state=$(detect_active_add 2>/dev/null || true)
|
|
17
|
+
[ -z "$state" ] && exit 0
|
|
18
|
+
|
|
19
|
+
echo "[ADD PostToolUse] 文件已写入: ${file_path}。如果尚未记录,请执行 record_dev_operation({ targetId: '${file_path}' }) 落库审计。"
|
|
20
|
+
exit 0
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# pre-compact.sh — PreCompact ADD 状态快照
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
5
|
+
source "$HOOK_DIR/lib/state-detect.sh"
|
|
6
|
+
|
|
7
|
+
state=$(detect_active_add 2>/dev/null || true)
|
|
8
|
+
[ -z "$state" ] && exit 0
|
|
9
|
+
|
|
10
|
+
IFS='::' read -r plan step rounds handoff add_route <<< "$state"
|
|
11
|
+
echo "[ADD PreCompact] 压缩前状态: Plan=${plan}, 轮次=${rounds}, Step=${step}"
|
|
12
|
+
exit 0
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# pre-tool-use.sh — PreToolUse §B:源码 Plan 关联检查(阻断模式 v3)
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
input=$(cat)
|
|
6
|
+
file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty')
|
|
7
|
+
[ -z "$file_path" ] && exit 0
|
|
8
|
+
|
|
9
|
+
if ! echo "$file_path" | grep -qE '(src/|/src/).*\.(ts|tsx)$'; then
|
|
10
|
+
exit 0
|
|
11
|
+
fi
|
|
12
|
+
|
|
13
|
+
PROJECT_DIR="${QODER_PROJECT_DIR:-${QODERCN_PROJECT_DIR:-$PWD}}"
|
|
14
|
+
MOD=$(basename "$file_path" | sed 's/\.[jt]sx\?$//')
|
|
15
|
+
|
|
16
|
+
MATCHES=$(grep -rl "$MOD" "$PROJECT_DIR/.qoder/plans" "$PROJECT_DIR/.qoder/specs" "$PROJECT_DIR/.qoder/reports" 2>/dev/null | wc -l)
|
|
17
|
+
|
|
18
|
+
if [ "$MATCHES" -gt 0 ]; then
|
|
19
|
+
echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"allow","permissionDecisionReason":"相关 ADD Plan 已存在"}}'
|
|
20
|
+
exit 0
|
|
21
|
+
fi
|
|
22
|
+
|
|
23
|
+
echo "⛔ 阻断: ${file_path} 无相关 ADD Plan。请先创建 Plan(plan-template / simple-plan-template)。" >&2
|
|
24
|
+
echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"无相关 ADD Plan。请用 AskUserQuestion 询问用户选择 plan-template 或 simple-plan-template 创建 Plan。"}}'
|
|
25
|
+
exit 2
|
|
26
|
+
#!/bin/bash
|
|
27
|
+
# pre-tool-use.sh — PreToolUse §B:源码 Plan 关联检查(阻断模式)
|
|
28
|
+
set -euo pipefail
|
|
29
|
+
|
|
30
|
+
input=$(cat)
|
|
31
|
+
file_path=$(echo "$input" | jq -r '.tool_input.file_path // empty')
|
|
32
|
+
[ -z "$file_path" ] && exit 0
|
|
33
|
+
|
|
34
|
+
# 只处理 src/**/*.ts / src/**/*.tsx
|
|
35
|
+
if ! echo "$file_path" | grep -qE '^src/.*\.(ts|tsx)$' && ! echo "$file_path" | grep -qE '^/home/.*/src/.*\.(ts|tsx)$'; then
|
|
36
|
+
exit 0
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
PROJECT_DIR="${QODER_PROJECT_DIR:-${QODERCN_PROJECT_DIR:-$PWD}}"
|
|
40
|
+
PLANS_DIR="$PROJECT_DIR/.qoder/plans"
|
|
41
|
+
SPECS_DIR="$PROJECT_DIR/.qoder/specs"
|
|
42
|
+
REPORTS_DIR="$PROJECT_DIR/.qoder/reports"
|
|
43
|
+
|
|
44
|
+
MOD=$(basename "$file_path" | sed 's/\.[jt]sx\?$//')
|
|
45
|
+
|
|
46
|
+
MATCHES=$(grep -rl "$MOD" "$PLANS_DIR" "$SPECS_DIR" "$REPORTS_DIR" 2>/dev/null \
|
|
47
|
+
| sed "s|$PROJECT_DIR/||" \
|
|
48
|
+
| grep -oE '[^/]*-(plan|handoff|review|report)-v[0-9]+' \
|
|
49
|
+
| sed 's/\(plan\|handoff\|review\|report\)-v[0-9]\+\.md//' \
|
|
50
|
+
| sort -u | head -10 2>/dev/null || true)
|
|
51
|
+
|
|
52
|
+
if [ -n "$MATCHES" ]; then
|
|
53
|
+
cat >&2 <<EOF
|
|
54
|
+
[ADD PreToolUse] 📋 相关文档:
|
|
55
|
+
$(echo "$MATCHES" | sed 's/^/ - /')
|
|
56
|
+
允许编辑 $file_path。
|
|
57
|
+
EOF
|
|
58
|
+
exit 0
|
|
59
|
+
fi
|
|
60
|
+
|
|
61
|
+
cat >&2 <<EOF
|
|
62
|
+
[ADD PreToolUse] ⛔ 阻断:${file_path} 无相关 ADD 文档。
|
|
63
|
+
|
|
64
|
+
必须先生成 Plan 后才能修改源码。请执行:
|
|
65
|
+
① 用 AskUserQuestion 询问用户:要创建 Plan 吗?
|
|
66
|
+
A) plan-template — 复杂改动,含架构设计 + 独立 Spec
|
|
67
|
+
B) simple-plan-template — 单一修复,Tasks 内联于 Plan 体
|
|
68
|
+
② 按模板创建 Plan → Plan 中引用此文件路径
|
|
69
|
+
③ 重新执行修改操作
|
|
70
|
+
|
|
71
|
+
JSON 输出格式(阻断时必须):
|
|
72
|
+
{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"无相关 ADD Plan,请先生成 Plan 文档"}}
|
|
73
|
+
EOF
|
|
74
|
+
|
|
75
|
+
# 输出阻断 JSON 到 stdout,Qoder 会读它来展示阻断原因
|
|
76
|
+
echo '{"hookSpecificOutput":{"hookEventName":"PreToolUse","permissionDecision":"deny","permissionDecisionReason":"无相关 ADD Plan,请先生成 Plan 文档"}}'
|
|
77
|
+
exit 2
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# prompt-submit.sh — UserPromptSubmit 触发词智能路由(★入口)
|
|
3
|
+
input=$(cat)
|
|
4
|
+
prompt=$(echo "$input" | jq -r '.prompt // empty')
|
|
5
|
+
[ -z "$prompt" ] && exit 0
|
|
6
|
+
|
|
7
|
+
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
8
|
+
source "$HOOK_DIR/lib/vocabulary.sh"
|
|
9
|
+
source "$HOOK_DIR/lib/state-detect.sh"
|
|
10
|
+
|
|
11
|
+
# ─── Layer 1: 精准 P0 触发词 ───
|
|
12
|
+
matched=$(match_trigger "$prompt")
|
|
13
|
+
if [ -n "$matched" ]; then
|
|
14
|
+
# 验收幂等保护: 如果已验收,提示不重复
|
|
15
|
+
if echo "$prompt" | grep -qiE '验收|收敛' 2>/dev/null; then
|
|
16
|
+
add_state=$(detect_active_add 2>/dev/null || true)
|
|
17
|
+
if [ -n "$add_state" ]; then
|
|
18
|
+
_handoff=$(echo "$add_state" | awk -F'::' '{print $4}')
|
|
19
|
+
_add_route=$(echo "$add_state" | awk -F'::' '{print $5}')
|
|
20
|
+
if is_already_accepted "$_add_route" "$_handoff" 2>/dev/null; then
|
|
21
|
+
printf '%s\n' \
|
|
22
|
+
"[ADD 验收] ⚠️ 已验收。进入 Review 模式:" \
|
|
23
|
+
" ① 重新检查 checklist [T]/[R] 项" \
|
|
24
|
+
" ② 审查 audit 记录完整性" \
|
|
25
|
+
" ③ 如有差异 → Review 回流至 handoff(增量更新,不覆盖已有结论)" \
|
|
26
|
+
" ④ 无差异 → 记录 'Review 已确认,无新发现'" \
|
|
27
|
+
" ★ 同步检查: 如 checklist 有新 cuid 但 handoff 审计表缺失 → 更新 handoff ADD-7 表 + query_audit_logs 命令"
|
|
28
|
+
# 执行 checklist 质量检查
|
|
29
|
+
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
30
|
+
"$HOOK_DIR/review-checklist.sh" "$_handoff" "$_add_route" 2>/dev/null
|
|
31
|
+
exit 0
|
|
32
|
+
fi
|
|
33
|
+
fi
|
|
34
|
+
fi
|
|
35
|
+
echo "$matched"
|
|
36
|
+
exit 0
|
|
37
|
+
fi
|
|
38
|
+
|
|
39
|
+
# ─── 开发关键词检测 ───
|
|
40
|
+
dev_kw=$(load_dev_keywords 2>/dev/null || true)
|
|
41
|
+
if [ -z "$dev_kw" ]; then
|
|
42
|
+
exit 0
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
if ! echo "$prompt" | grep -qiE "$dev_kw"; then
|
|
46
|
+
exit 0
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# ─── Layer 2/3: 按活跃 ADD 分流 ───
|
|
50
|
+
state=$(detect_active_add 2>/dev/null || true)
|
|
51
|
+
if [ -z "$state" ]; then
|
|
52
|
+
# Layer 2: 无活跃 ADD → 强制启动
|
|
53
|
+
cat >&2 <<'EOF'
|
|
54
|
+
[ADD 强制规则] 检测到开发任务。你必须先执行 add-paradigm SKILL 完成 ADD 工作流:
|
|
55
|
+
Step 0: 文档先行 (Plan → Review → Specs)
|
|
56
|
+
Step 1: 扩展 AgentAuditPhase
|
|
57
|
+
Step 2: 确认 agentAudit() 通道
|
|
58
|
+
Step 3: 代码实现 + 审计植入
|
|
59
|
+
...
|
|
60
|
+
Step 8: 收敛判断
|
|
61
|
+
如果 add-paradigm SKILL 尚未激活,请先调用它。
|
|
62
|
+
EOF
|
|
63
|
+
exit 2
|
|
64
|
+
fi
|
|
65
|
+
|
|
66
|
+
# Layer 3: 有活跃 ADD → 注入状态
|
|
67
|
+
plan=$(echo "$state" | awk -F'::' '{print $1}')
|
|
68
|
+
step=$(echo "$state" | awk -F'::' '{print $2}')
|
|
69
|
+
rounds=$(echo "$state" | awk -F'::' '{print $3}')
|
|
70
|
+
handoff=$(echo "$state" | awk -F'::' '{print $4}')
|
|
71
|
+
echo "[ADD 状态] Plan: ${plan}, 轮次: ${rounds}, Step: ${step}, handoff: ${handoff}"
|
|
72
|
+
exit 0
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# review-checklist.sh — 验收 Review 模式:检查 checklist 质量
|
|
3
|
+
# 被 prompt-submit.sh 的"验收"幂等检查后调用
|
|
4
|
+
#
|
|
5
|
+
# 输入: handoff_path add_route_path
|
|
6
|
+
# 输出: checklist 质量问题清单
|
|
7
|
+
|
|
8
|
+
handoff="$1"
|
|
9
|
+
add_route="$2"
|
|
10
|
+
[ -z "$handoff" ] && exit 0
|
|
11
|
+
|
|
12
|
+
# 从 handoff 关联找到 spec 目录
|
|
13
|
+
plan_dir=$(dirname "$handoff")
|
|
14
|
+
plan_kw=$(basename "$handoff" | sed 's/-handoff.*//')
|
|
15
|
+
|
|
16
|
+
# 找 checklist
|
|
17
|
+
spec_dir=".qoder/specs/${plan_kw}"
|
|
18
|
+
checklist=""
|
|
19
|
+
[ -d "$spec_dir" ] && checklist="$spec_dir/checklist.md"
|
|
20
|
+
# fallback: 搜索
|
|
21
|
+
[ ! -f "$checklist" ] && checklist=$(find .qoder/specs -name "checklist.md" -path "*${plan_kw}*" 2>/dev/null | head -1)
|
|
22
|
+
|
|
23
|
+
tasks_file=""
|
|
24
|
+
[ -d "$spec_dir" ] && tasks_file="$spec_dir/tasks.md"
|
|
25
|
+
[ ! -f "$tasks_file" ] && tasks_file=$(find .qoder/specs -name "tasks.md" -path "*${plan_kw}*" 2>/dev/null | head -1)
|
|
26
|
+
|
|
27
|
+
issues=""
|
|
28
|
+
|
|
29
|
+
# ══════════════════════════════════════════════════════════════════════
|
|
30
|
+
# 0. Step 0 准入: ADD 核心文档存在性(BLOCKING)
|
|
31
|
+
# ══════════════════════════════════════════════════════════════════════
|
|
32
|
+
_missing_docs=""
|
|
33
|
+
if [ ! -f "$handoff" ]; then
|
|
34
|
+
_missing_docs="${_missing_docs} Handoff"
|
|
35
|
+
else
|
|
36
|
+
# 章节完整性: 至少要有 spec 文件/你要改的文件/验证标准/完成后记录 四个关键小节
|
|
37
|
+
_h_sections=0
|
|
38
|
+
grep -q "spec 文件" "$handoff" 2>/dev/null && _h_sections=$((_h_sections + 1))
|
|
39
|
+
grep -q "你要改的文件" "$handoff" 2>/dev/null && _h_sections=$((_h_sections + 1))
|
|
40
|
+
grep -q "验证标准" "$handoff" 2>/dev/null && _h_sections=$((_h_sections + 1))
|
|
41
|
+
grep -q "完成后记录 ADD-7 审计" "$handoff" 2>/dev/null && _h_sections=$((_h_sections + 1))
|
|
42
|
+
if [ "$_h_sections" -lt 4 ]; then
|
|
43
|
+
_missing_docs="${_missing_docs} Handoff(缺章节:${_h_sections}/4)"
|
|
44
|
+
fi
|
|
45
|
+
fi
|
|
46
|
+
if [ ! -f "$add_route" ]; then
|
|
47
|
+
_missing_docs="${_missing_docs} add-route"
|
|
48
|
+
else
|
|
49
|
+
# add-route 至少要有 Task 映射表 + 文件清单
|
|
50
|
+
if ! grep -q "Task 映射表" "$add_route" 2>/dev/null && ! grep -q "文件清单" "$add_route" 2>/dev/null; then
|
|
51
|
+
_missing_docs="${_missing_docs} add-route(缺Task映射/文件清单)"
|
|
52
|
+
fi
|
|
53
|
+
fi
|
|
54
|
+
if [ ! -f "$checklist" ]; then
|
|
55
|
+
_missing_docs="${_missing_docs} checklist"
|
|
56
|
+
else
|
|
57
|
+
# checklist 至少要有 [T] 项
|
|
58
|
+
if ! grep -q '\[T\]' "$checklist" 2>/dev/null; then
|
|
59
|
+
_missing_docs="${_missing_docs} checklist(无[T]项)"
|
|
60
|
+
fi
|
|
61
|
+
fi
|
|
62
|
+
if [ ! -f "$tasks_file" ]; then
|
|
63
|
+
_missing_docs="${_missing_docs} tasks"
|
|
64
|
+
else
|
|
65
|
+
# tasks 至少要有 Task 列表 + 验证
|
|
66
|
+
if ! grep -q 'Task\|\- \[ \]' "$tasks_file" 2>/dev/null; then
|
|
67
|
+
_missing_docs="${_missing_docs} tasks(无Task项)"
|
|
68
|
+
fi
|
|
69
|
+
fi
|
|
70
|
+
if [ -n "$_missing_docs" ]; then
|
|
71
|
+
echo " ❌ Step 0 未完成:$(echo $_missing_docs | sed 's/ /, /g') 文件缺失。回退 Step 0.5/Step 1 补建后再进入代码实现。"
|
|
72
|
+
exit 1
|
|
73
|
+
fi
|
|
74
|
+
|
|
75
|
+
# 1. checklist [x] 数 vs tasks.md [x] 数 是否一致
|
|
76
|
+
if [ -f "$checklist" ] && [ -f "$tasks_file" ]; then
|
|
77
|
+
cl_ck=$(grep -c '\[x\]' "$checklist" 2>/dev/null || true); cl_ck=${cl_ck:-0}
|
|
78
|
+
cl_open=$(grep -c '\[ \]' "$checklist" 2>/dev/null || true); cl_open=${cl_open:-0}
|
|
79
|
+
tk_ck=$(grep -c '\[x\]' "$tasks_file" 2>/dev/null || echo "0")
|
|
80
|
+
|
|
81
|
+
if [ "$cl_open" -gt 0 ]; then
|
|
82
|
+
issues="${issues} ⚠️ checklist 有 ${cl_open} 项未勾选\n"
|
|
83
|
+
fi
|
|
84
|
+
|
|
85
|
+
# 2. [T] 项是否都有 [x](编译期验证项)
|
|
86
|
+
t_items=$(grep -c '\[T\]' "$checklist" 2>/dev/null || true); t_items=${t_items:-0}
|
|
87
|
+
t_checked=$(grep '\[T\]' "$checklist" 2>/dev/null | grep -c '\[x\]' || true); t_checked=${t_checked:-0}
|
|
88
|
+
if [ "$t_items" -gt "$t_checked" ]; then
|
|
89
|
+
issues="${issues} ⚠️ [T] 编译期验证: ${t_checked}/${t_items} 通过\n"
|
|
90
|
+
fi
|
|
91
|
+
|
|
92
|
+
# 3. 证据缺失检测:[x] 但缺 — 证据: 标记
|
|
93
|
+
_no_evidence=0
|
|
94
|
+
while IFS= read -r line; do
|
|
95
|
+
[ -z "$line" ] && continue
|
|
96
|
+
# 有证据: — 证据: 字段 + 具体内容(tsc/vitest/grep/审计ID 等)
|
|
97
|
+
if echo "$line" | grep -qE '—\s*证据:\s*\S' 2>/dev/null; then
|
|
98
|
+
continue
|
|
99
|
+
fi
|
|
100
|
+
# 有验证结果描述也行
|
|
101
|
+
if echo "$line" | grep -qE 'npx|tsc|vitest|grep|✅|cmq[0-9a-z]{10}|18/18|exit.*0' 2>/dev/null; then
|
|
102
|
+
continue
|
|
103
|
+
fi
|
|
104
|
+
_no_evidence=$((_no_evidence + 1))
|
|
105
|
+
done < <(grep '\[x\]' "$checklist" 2>/dev/null)
|
|
106
|
+
|
|
107
|
+
if [ "$_no_evidence" -gt 0 ]; then
|
|
108
|
+
issues="${issues} ❌ ${_no_evidence} 项 [x] 缺少验收证据(需附 — 证据: tsc/vitest/grep/审计ID 等)\n"
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
# 4. 审计链:[x] 项引用 audit ID 的比例
|
|
112
|
+
# 初验: 有证据即可,审计ID是证据产出物
|
|
113
|
+
# 复验: 有审计ID + 证据仍有效 → 不重复落库;证据失效 → 追写新审计
|
|
114
|
+
_with_audit=$(grep '\[x\]' "$checklist" 2>/dev/null | grep -cE 'cmq[a-z0-9]{10,}' || true); _with_audit=${_with_audit:-0}
|
|
115
|
+
_fake_audit=$(grep '\[x\]' "$checklist" 2>/dev/null | grep -cE 'cmq\.\.\.|cmqxxx|审计.*cmq\.\.' || true); _fake_audit=${_fake_audit:-0}
|
|
116
|
+
if [ "$_fake_audit" -gt 0 ]; then
|
|
117
|
+
issues="${issues} ❌ ${_fake_audit} 项 [x] 使用了占位符审计ID(cmq.../cmqxxx),必须调 record_dev_operation 获取真实 cuid 后替换\n"
|
|
118
|
+
fi
|
|
119
|
+
_with_evidence=$(grep '\[x\]' "$checklist" 2>/dev/null | grep -cE 'tsc|vitest|npx|grep|✅|验证|确认|compgen|审计.*cmq[a-z0-9]{10}' || true); _with_evidence=${_with_evidence:-0}
|
|
120
|
+
if [ "$_with_evidence" -gt 0 ] && [ "$_with_audit" -eq 0 ]; then
|
|
121
|
+
issues="${issues} 📎 初验: ${_with_evidence}/${cl_ck} 项有证据但未写审计 ID(需调 record_dev_operation 落库)\n"
|
|
122
|
+
elif [ "$_with_audit" -gt 0 ] && [ "$_with_audit" -lt "$cl_ck" ]; then
|
|
123
|
+
issues="${issues} 📎 复验: ${_with_audit}/${cl_ck} 项引用审计 ID。${_with_evidence}/${cl_ck} 项有证据。证据一致则不需追写 devlog日志(走mcp)\n"
|
|
124
|
+
fi
|
|
125
|
+
fi
|
|
126
|
+
|
|
127
|
+
# 5. add-route Step 闭环
|
|
128
|
+
if [ -f "$add_route" ]; then
|
|
129
|
+
ar_ck=$(grep -c '\[x\]' "$add_route" 2>/dev/null || true); ar_ck=${ar_ck:-0}
|
|
130
|
+
ar_open=$(grep -c '\[ \]' "$add_route" 2>/dev/null || true); ar_open=${ar_open:-0}
|
|
131
|
+
if [ "$ar_open" -gt 0 ]; then
|
|
132
|
+
issues="${issues} ⚠️ add-route ${ar_open} Step 未闭环\n"
|
|
133
|
+
fi
|
|
134
|
+
fi
|
|
135
|
+
|
|
136
|
+
# 6. handoff 审计表同步:checklist 中的 cuid 是否在 handoff 中有记录
|
|
137
|
+
if [ -f "$handoff" ] && [ -f "$checklist" ]; then
|
|
138
|
+
_new_cuids=""
|
|
139
|
+
while IFS= read -r cuid; do
|
|
140
|
+
[ -z "$cuid" ] && continue
|
|
141
|
+
if ! grep -q "$cuid" "$handoff" 2>/dev/null; then
|
|
142
|
+
[ -n "$_new_cuids" ] && _new_cuids="${_new_cuids}, "
|
|
143
|
+
_new_cuids="${_new_cuids}${cuid}"
|
|
144
|
+
fi
|
|
145
|
+
done < <(grep -oE 'cmq[a-z0-9]{10,}' "$checklist" 2>/dev/null | sort -u)
|
|
146
|
+
if [ -n "$_new_cuids" ]; then
|
|
147
|
+
_new_count=$(echo "$_new_cuids" | tr ',' '\n' | wc -l)
|
|
148
|
+
issues="${issues} ❌ handoff 审计表未同步: ${_new_count} 个 cuid 在 checklist 中存在但 handoff 中缺失(需更新 handoff ADD-7 表 + query_audit_logs 命令)\n"
|
|
149
|
+
fi
|
|
150
|
+
fi
|
|
151
|
+
|
|
152
|
+
if [ -z "$issues" ]; then
|
|
153
|
+
echo " ✅ Review: checklist 质量检查通过"
|
|
154
|
+
else
|
|
155
|
+
echo " 📋 Review 发现问题:"
|
|
156
|
+
echo -e "$issues"
|
|
157
|
+
fi
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# SessionStart — ADD 上下文恢复
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
|
|
5
|
+
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
6
|
+
source "$HOOK_DIR/lib/state-detect.sh"
|
|
7
|
+
source "$HOOK_DIR/lib/context-inject.sh"
|
|
8
|
+
|
|
9
|
+
state=$(detect_active_add 2>/dev/null || true)
|
|
10
|
+
if [ -z "$state" ]; then
|
|
11
|
+
exit 0
|
|
12
|
+
fi
|
|
13
|
+
|
|
14
|
+
IFS='::' read -r plan step rounds handoff <<< "$state"
|
|
15
|
+
build_session_start_json "$plan" "$step" "$rounds" "$handoff"
|
|
16
|
+
exit 0
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# stop-check.sh — Stop 验收闭环检查(四象限 + few-shot)
|
|
3
|
+
input=$(cat)
|
|
4
|
+
stop_active=$(echo "$input" | jq -r '.stop_hook_active // false')
|
|
5
|
+
[ "$stop_active" = "true" ] && exit 0
|
|
6
|
+
|
|
7
|
+
HOOK_DIR="$(cd "$(dirname "$0")" && pwd)"
|
|
8
|
+
source "$HOOK_DIR/lib/state-detect.sh"
|
|
9
|
+
source "$HOOK_DIR/lib/context-inject.sh"
|
|
10
|
+
|
|
11
|
+
state=$(detect_active_add 2>/dev/null || true)
|
|
12
|
+
has_dev=$(has_dev_action 2>/dev/null && echo "true" || echo "false")
|
|
13
|
+
|
|
14
|
+
# ═══════════════ 四象限分流 ═══════════════
|
|
15
|
+
|
|
16
|
+
# Q1: 无 ADD + 无 dev → 正常停
|
|
17
|
+
if [ -z "$state" ] && [ "$has_dev" != "true" ]; then
|
|
18
|
+
exit 0
|
|
19
|
+
fi
|
|
20
|
+
|
|
21
|
+
# Q2: 无 ADD + 有 dev → 严重违规,强制阻止
|
|
22
|
+
if [ -z "$state" ] && [ "$has_dev" = "true" ]; then
|
|
23
|
+
build_stop_context "no_add_has_dev" >&2
|
|
24
|
+
exit 2
|
|
25
|
+
fi
|
|
26
|
+
|
|
27
|
+
# 解析 state
|
|
28
|
+
plan=$(echo "$state" | cut -d':' -f1 | sed 's/^:://')
|
|
29
|
+
step_info=$(echo "$state" | awk -F'::' '{print $2}')
|
|
30
|
+
round_info=$(echo "$state" | awk -F'::' '{print $3}')
|
|
31
|
+
handoff=$(echo "$state" | awk -F'::' '{print $4}')
|
|
32
|
+
add_route=$(echo "$state" | awk -F'::' '{print $5}')
|
|
33
|
+
|
|
34
|
+
# Q3: 有 ADD + 无 dev → 注入状态
|
|
35
|
+
if [ "$has_dev" != "true" ]; then
|
|
36
|
+
echo "[ADD Stop] Plan: ${plan}, 轮次: ${round_info}, Step: ${step_info}"
|
|
37
|
+
echo "本次无代码改动。下次继续时执行 session-init 恢复上下文。"
|
|
38
|
+
exit 0
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
# Q4: 有 ADD + 有 dev → Step 定位分流
|
|
42
|
+
issues=$(check_add_completeness "$handoff" "$add_route" 2>/dev/null || true)
|
|
43
|
+
|
|
44
|
+
# 提取 Step 勾选数
|
|
45
|
+
ck=$(grep -c '\[x\]' "$add_route" 2>/dev/null || true); ck=${ck:-0}
|
|
46
|
+
uc=$(grep -c '\[ \]' "$add_route" 2>/dev/null || true); uc=${uc:-0}
|
|
47
|
+
|
|
48
|
+
# Step 0-2: 文档/审计阶段(勾选数 < 3 或 Step 0/1/2 任一项 [ ])
|
|
49
|
+
if [ "$ck" -lt 3 ] 2>/dev/null; then
|
|
50
|
+
echo "[ADD Stop] ADD 阶段: 文档先行/审计准备 (add-route ${ck}/${total})."
|
|
51
|
+
echo "无需验收闭环。下一步: 进入 Step 3 代码实现。"
|
|
52
|
+
exit 0
|
|
53
|
+
fi
|
|
54
|
+
|
|
55
|
+
# Step 3 进行中: 有 [ ] Step 但非全部完成
|
|
56
|
+
if [ "$uc" -gt 0 ] 2>/dev/null && [ -n "$issues" ]; then
|
|
57
|
+
echo "[ADD Stop] ADD Step 3: 代码实现进行中 (add-route ${ck}/${total})."
|
|
58
|
+
echo "tasks.md 还有 ${uc} 项待完成。"
|
|
59
|
+
exit 0
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# Step 3+ 完成 + 未闭环
|
|
63
|
+
if [ -n "$issues" ]; then
|
|
64
|
+
build_stop_context "has_add_dev_unclosed" "$issues" >&2
|
|
65
|
+
exit 2
|
|
66
|
+
fi
|
|
67
|
+
|
|
68
|
+
# 全部闭环
|
|
69
|
+
clear_dev_action 2>/dev/null || true
|
|
70
|
+
echo "[ADD Stop] ✅ 验收闭环: add-route 全部 [x], devlog 已写, handoff 已更新。"
|
|
71
|
+
exit 0
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# subagent-guard.sh — SubagentStart/Stop 门禁日志
|
|
3
|
+
set -euo pipefail
|
|
4
|
+
input=$(cat)
|
|
5
|
+
agent_type=$(echo "$input" | jq -r '.agent_type // ""')
|
|
6
|
+
hook_event=$(echo "$input" | jq -r '.hook_event_name // ""')
|
|
7
|
+
|
|
8
|
+
if echo "$agent_type" | grep -qiE 'guardian|orchestrator'; then
|
|
9
|
+
echo "[ADD Subagent] ${hook_event}: ${agent_type}"
|
|
10
|
+
fi
|
|
11
|
+
exit 0
|